##// END OF EJS Templates
update change RM
avaldez -
r1384:2acdbd5998b4
parent child
Show More
This diff has been collapsed as it changes many lines, (628 lines changed) Show them Hide them
@@ -0,0 +1,628
1 import os
2 import datetime
3 import numpy
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 from schainpy.utils import log
8 # libreria wradlib
9 import wradlib as wrl
10
11 EARTH_RADIUS = 6.3710e3
12
13
14 def ll2xy(lat1, lon1, lat2, lon2):
15
16 p = 0.017453292519943295
17 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
18 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
19 r = 12742 * numpy.arcsin(numpy.sqrt(a))
20 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
21 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
22 theta = -theta + numpy.pi/2
23 return r*numpy.cos(theta), r*numpy.sin(theta)
24
25
26 def km2deg(km):
27 '''
28 Convert distance in km to degrees
29 '''
30
31 return numpy.rad2deg(km/EARTH_RADIUS)
32
33
34
35 class SpectralMomentsPlot(SpectraPlot):
36 '''
37 Plot for Spectral Moments
38 '''
39 CODE = 'spc_moments'
40 # colormap = 'jet'
41 # plot_type = 'pcolor'
42
43 class DobleGaussianPlot(SpectraPlot):
44 '''
45 Plot for Double Gaussian Plot
46 '''
47 CODE = 'gaussian_fit'
48 # colormap = 'jet'
49 # plot_type = 'pcolor'
50
51 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
52 '''
53 Plot SpectraCut with Double Gaussian Fit
54 '''
55 CODE = 'cut_gaussian_fit'
56
57 class SnrPlot(RTIPlot):
58 '''
59 Plot for SNR Data
60 '''
61
62 CODE = 'snr'
63 colormap = 'jet'
64
65 def update(self, dataOut):
66
67 data = {
68 'snr': 10*numpy.log10(dataOut.data_snr)
69 }
70
71 return data, {}
72
73 class DopplerPlot(RTIPlot):
74 '''
75 Plot for DOPPLER Data (1st moment)
76 '''
77
78 CODE = 'dop'
79 colormap = 'jet'
80
81 def update(self, dataOut):
82
83 data = {
84 'dop': 10*numpy.log10(dataOut.data_dop)
85 }
86
87 return data, {}
88
89 class PowerPlot(RTIPlot):
90 '''
91 Plot for Power Data (0 moment)
92 '''
93
94 CODE = 'pow'
95 colormap = 'jet'
96
97 def update(self, dataOut):
98
99 data = {
100 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
101 }
102
103 return data, {}
104
105 class SpectralWidthPlot(RTIPlot):
106 '''
107 Plot for Spectral Width Data (2nd moment)
108 '''
109
110 CODE = 'width'
111 colormap = 'jet'
112
113 def update(self, dataOut):
114
115 data = {
116 'width': dataOut.data_width
117 }
118
119 return data, {}
120
121 class SkyMapPlot(Plot):
122 '''
123 Plot for meteors detection data
124 '''
125
126 CODE = 'param'
127
128 def setup(self):
129
130 self.ncols = 1
131 self.nrows = 1
132 self.width = 7.2
133 self.height = 7.2
134 self.nplots = 1
135 self.xlabel = 'Zonal Zenith Angle (deg)'
136 self.ylabel = 'Meridional Zenith Angle (deg)'
137 self.polar = True
138 self.ymin = -180
139 self.ymax = 180
140 self.colorbar = False
141
142 def plot(self):
143
144 arrayParameters = numpy.concatenate(self.data['param'])
145 error = arrayParameters[:, -1]
146 indValid = numpy.where(error == 0)[0]
147 finalMeteor = arrayParameters[indValid, :]
148 finalAzimuth = finalMeteor[:, 3]
149 finalZenith = finalMeteor[:, 4]
150
151 x = finalAzimuth * numpy.pi / 180
152 y = finalZenith
153
154 ax = self.axes[0]
155
156 if ax.firsttime:
157 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
158 else:
159 ax.plot.set_data(x, y)
160
161 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
162 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
163 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
164 dt2,
165 len(x))
166 self.titles[0] = title
167
168
169 class GenericRTIPlot(Plot):
170 '''
171 Plot for data_xxxx object
172 '''
173
174 CODE = 'param'
175 colormap = 'viridis'
176 plot_type = 'pcolorbuffer'
177
178 def setup(self):
179 self.xaxis = 'time'
180 self.ncols = 1
181 self.nrows = self.data.shape('param')[0]
182 self.nplots = self.nrows
183 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
184
185 if not self.xlabel:
186 self.xlabel = 'Time'
187
188 self.ylabel = 'Range [km]'
189 if not self.titles:
190 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
191
192 def update(self, dataOut):
193
194 data = {
195 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
196 }
197
198 meta = {}
199
200 return data, meta
201
202 def plot(self):
203 # self.data.normalize_heights()
204 self.x = self.data.times
205 self.y = self.data.yrange
206 self.z = self.data['param']
207
208 self.z = 10*numpy.log10(self.z)
209
210 self.z = numpy.ma.masked_invalid(self.z)
211
212 if self.decimation is None:
213 x, y, z = self.fill_gaps(self.x, self.y, self.z)
214 else:
215 x, y, z = self.fill_gaps(*self.decimate())
216
217 for n, ax in enumerate(self.axes):
218
219 self.zmax = self.zmax if self.zmax is not None else numpy.max(
220 self.z[n])
221 self.zmin = self.zmin if self.zmin is not None else numpy.min(
222 self.z[n])
223
224 if ax.firsttime:
225 if self.zlimits is not None:
226 self.zmin, self.zmax = self.zlimits[n]
227
228 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
229 vmin=self.zmin,
230 vmax=self.zmax,
231 cmap=self.cmaps[n]
232 )
233 else:
234 if self.zlimits is not None:
235 self.zmin, self.zmax = self.zlimits[n]
236 ax.collections.remove(ax.collections[0])
237 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
238 vmin=self.zmin,
239 vmax=self.zmax,
240 cmap=self.cmaps[n]
241 )
242
243
244 class PolarMapPlot(Plot):
245 '''
246 Plot for weather radar
247 '''
248
249 CODE = 'param'
250 colormap = 'seismic'
251
252 def setup(self):
253 self.ncols = 1
254 self.nrows = 1
255 self.width = 9
256 self.height = 8
257 self.mode = self.data.meta['mode']
258 if self.channels is not None:
259 self.nplots = len(self.channels)
260 self.nrows = len(self.channels)
261 else:
262 self.nplots = self.data.shape(self.CODE)[0]
263 self.nrows = self.nplots
264 self.channels = list(range(self.nplots))
265 if self.mode == 'E':
266 self.xlabel = 'Longitude'
267 self.ylabel = 'Latitude'
268 else:
269 self.xlabel = 'Range (km)'
270 self.ylabel = 'Height (km)'
271 self.bgcolor = 'white'
272 self.cb_labels = self.data.meta['units']
273 self.lat = self.data.meta['latitude']
274 self.lon = self.data.meta['longitude']
275 self.xmin, self.xmax = float(
276 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
277 self.ymin, self.ymax = float(
278 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
279 # self.polar = True
280
281 def plot(self):
282
283 for n, ax in enumerate(self.axes):
284 data = self.data['param'][self.channels[n]]
285
286 zeniths = numpy.linspace(
287 0, self.data.meta['max_range'], data.shape[1])
288 if self.mode == 'E':
289 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
290 r, theta = numpy.meshgrid(zeniths, azimuths)
291 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
292 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
293 x = km2deg(x) + self.lon
294 y = km2deg(y) + self.lat
295 else:
296 azimuths = numpy.radians(self.data.yrange)
297 r, theta = numpy.meshgrid(zeniths, azimuths)
298 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
299 self.y = zeniths
300
301 if ax.firsttime:
302 if self.zlimits is not None:
303 self.zmin, self.zmax = self.zlimits[n]
304 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
305 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
306 vmin=self.zmin,
307 vmax=self.zmax,
308 cmap=self.cmaps[n])
309 else:
310 if self.zlimits is not None:
311 self.zmin, self.zmax = self.zlimits[n]
312 ax.collections.remove(ax.collections[0])
313 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
314 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
315 vmin=self.zmin,
316 vmax=self.zmax,
317 cmap=self.cmaps[n])
318
319 if self.mode == 'A':
320 continue
321
322 # plot district names
323 f = open('/data/workspace/schain_scripts/distrito.csv')
324 for line in f:
325 label, lon, lat = [s.strip() for s in line.split(',') if s]
326 lat = float(lat)
327 lon = float(lon)
328 # ax.plot(lon, lat, '.b', ms=2)
329 ax.text(lon, lat, label.decode('utf8'), ha='center',
330 va='bottom', size='8', color='black')
331
332 # plot limites
333 limites = []
334 tmp = []
335 for line in open('/data/workspace/schain_scripts/lima.csv'):
336 if '#' in line:
337 if tmp:
338 limites.append(tmp)
339 tmp = []
340 continue
341 values = line.strip().split(',')
342 tmp.append((float(values[0]), float(values[1])))
343 for points in limites:
344 ax.add_patch(
345 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
346
347 # plot Cuencas
348 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
349 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
350 values = [line.strip().split(',') for line in f]
351 points = [(float(s[0]), float(s[1])) for s in values]
352 ax.add_patch(Polygon(points, ec='b', fc='none'))
353
354 # plot grid
355 for r in (15, 30, 45, 60):
356 ax.add_artist(plt.Circle((self.lon, self.lat),
357 km2deg(r), color='0.6', fill=False, lw=0.2))
358 ax.text(
359 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
360 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
361 '{}km'.format(r),
362 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
363
364 if self.mode == 'E':
365 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
366 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
367 else:
368 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
369 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
370
371 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
372 self.titles = ['{} {}'.format(
373 self.data.parameters[x], title) for x in self.channels]
374
375 class WeatherPlot(Plot):
376 CODE = 'weather'
377 plot_name = 'weather'
378 plot_type = 'ppistyle'
379 buffering = False
380
381 def setup(self):
382 self.ncols = 1
383 self.nrows = 1
384 self.nplots= 1
385 self.ylabel= 'Range [Km]'
386 self.titles= ['Weather']
387 self.colorbar=False
388 self.width =8
389 self.height =8
390 self.ini =0
391 self.len_azi =0
392 self.buffer_ini = None
393 self.buffer_azi = None
394 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
395 self.flag =0
396 self.indicador= 0
397
398 def update(self, dataOut):
399
400 data = {}
401 meta = {}
402 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(250**2))
403 data['azi'] = dataOut.data_azi
404
405 return data, meta
406
407 def plot(self):
408 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
409 print("--------------------------------------",self.ini,"-----------------------------------")
410 print("time",self.data.times[-1])
411 data = self.data[-1]
412 #print("debug_0", data)
413 tmp_h = (data['weather'].shape[1])/10.0
414 #print("debug_1",tmp_h)
415 stoprange = float(tmp_h*1.5)#stoprange = float(33*1.5) por ahora 400
416 rangestep = float(0.15)
417 r = numpy.arange(0, stoprange, rangestep)
418 self.y = 2*r
419 print("---------------")
420 tmp_v = data['weather']
421 #print("tmp_v",tmp_v.shape)
422 tmp_z = data['azi']
423 print("tmp_z-------------->",tmp_z)
424 ##if self.ini==0:
425 ## tmp_z= [0,1,2,3,4,5,6,7,8,9]
426
427 #print("tmp_z",tmp_z.shape)
428 res = 1
429 step = (360/(res*tmp_v.shape[0]))
430 #print("step",step)
431 mode = 1
432 if mode==0:
433 #print("self.ini",self.ini)
434 val = numpy.mean(tmp_v[:,0])
435 self.len_azi = len(tmp_z)
436 ones = numpy.ones([(360-tmp_v.shape[0]),tmp_v.shape[1]])*val
437 self.buffer_ini = numpy.vstack((tmp_v,ones))
438
439 n = ((360/res)-len(tmp_z))
440 start = tmp_z[-1]+res
441 end = tmp_z[0]-res
442 if start>end:
443 end = end+360
444 azi_zeros = numpy.linspace(start,end,int(n))
445 azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
446 self.buffer_ini_azi = numpy.hstack((tmp_z,azi_zeros))
447 self.ini = self.ini+1
448
449 if mode==1:
450 #print("################")
451 #print("################")
452 #print("mode",self.ini)
453 #print("self.ini",self.ini)
454 if self.ini==0:
455 res = 1
456 step = (360/(res*tmp_v.shape[0]))
457 val = numpy.mean(tmp_v[:,0])
458 self.len_azi = len(tmp_z)
459 self.buf_tmp = tmp_v
460 ones = numpy.ones([(360-tmp_v.shape[0]),tmp_v.shape[1]])*val
461 self.buffer_ini = numpy.vstack((tmp_v,ones))
462
463 n = ((360/res)-len(tmp_z))
464 start = tmp_z[-1]+res
465 end = tmp_z[0]-res
466 if start>end:
467 end =end+360
468 azi_zeros = numpy.linspace(start,end,int(n))
469 azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
470 self.buf_azi = tmp_z
471 self.buffer_ini_azi = numpy.hstack((tmp_z,azi_zeros))
472 self.ini = self.ini+1
473 elif 0<self.ini<step:
474 '''
475 if self.ini>31:
476 start= tmp_z[0]
477 end =tmp_z[-1]
478 print("start","end",start,end)
479 if self.ini==32:
480 tmp_v=tmp_v+20
481 if self.ini==33:
482 tmp_v=tmp_v+10
483 if self.ini==34:
484 tmp_v=tmp_v+20
485 if self.ini==35:
486 tmp_v=tmp_v+20
487 '''
488 self.buf_tmp= numpy.vstack((self.buf_tmp,tmp_v))
489 print("ERROR_INMINENTE",self.buf_tmp.shape)
490 if self.buf_tmp.shape[0]==360:
491 print("entre aqui en 360 grados")
492 self.buffer_ini=self.buf_tmp
493 else:
494 # nuevo#########
495 self.buffer_ini[0:self.buf_tmp.shape[0],:]=self.buf_tmp
496 ################
497 #val=30.0
498 #ones = numpy.ones([(360-self.buf_tmp.shape[0]),self.buf_tmp.shape[1]])*val
499 #self.buffer_ini = numpy.vstack((self.buf_tmp,ones))
500
501 self.buf_azi = numpy.hstack((self.buf_azi,tmp_z))
502 n = ((360/res)-len(self.buf_azi))
503 print("n----->",n)
504 if n==0:
505 self.buffer_ini_azi = self.buf_azi
506 else:
507 start = self.buf_azi[-1]+res
508 end = self.buf_azi[0]-res
509 print("start",start)
510 print("end",end)
511 if start>end:
512 end =end+360
513 azi_zeros = numpy.linspace(start,end,int(n))
514 azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
515 print("self.buf_azi",self.buf_azi[0])
516 print("tmp_Z 0 ",tmp_z[0])
517 print("tmp_Z -1",tmp_z[-1])
518 if tmp_z[0]<self.buf_azi[0] <tmp_z[-1]:
519 print("activando indicador")
520 self.indicador=1
521 if self.indicador==1:
522 azi_zeros = numpy.ones(360-len(self.buf_azi))*(tmp_z[-1]+res)
523 ###start = tmp_z[-1]+res
524 ###end = tmp_z[0]-res
525 ###if start>end:
526 ### end =end+360
527 ###azi_zeros = numpy.linspace(start,end,int(n))
528 ###azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
529 #print("azi_zeros",azi_zeros)
530
531 ######self.buffer_ini_azi = numpy.hstack((self.buf_azi,azi_zeros))
532 #self.buffer_ini[0:tmv.shape[0],:]=tmp_v
533 ##self.indicador=0
534
535 # self.indicador = True
536 #if self.indicador==True:
537 # azi_zeros = numpy.ones(360-len(self.buf_azi))*(tmp_z[-1]+res)
538
539 #self.buf_azi = tmp_z
540 self.buffer_ini_azi = numpy.hstack((self.buf_azi,azi_zeros))
541
542 if self.ini==step-1:
543 start= tmp_z[0]
544 end = tmp_z[-1]
545 #print("start","end",start,end)
546 ###print(self.buffer_ini_azi[:80])
547 self.ini = self.ini+1
548
549 else:
550 step = (360/(res*tmp_v.shape[0]))
551 # aqui estaba realizando el debug de simulacion
552 # tmp_v=tmp_v +5 en cada step sumaba 5
553 # y el mismo valor despues de la primera vuelta
554 #tmp_v=tmp_v+5+(self.ini-step)*1### aqui yo habia sumado 5 por las puras
555
556 start= tmp_z[0]
557 end = tmp_z[-1]
558 #print("start","end",start,end)
559 ###print(self.buffer_ini_azi[:120])
560
561 if step>=2:
562 if self.flag<step-1:
563 limit_i=self.buf_azi[len(tmp_z)*(self.flag+1)]
564 limit_s=self.buf_azi[len(tmp_z)*(self.flag+2)-1]
565 print("flag",self.flag,limit_i,limit_s)
566 if limit_i< tmp_z[-1]< limit_s:
567 index_i=int(numpy.where(tmp_z<=self.buf_azi[len(tmp_z)*(self.flag+1)])[0][-1])
568 tmp_r =int(numpy.where(self.buf_azi[(self.flag+1)*len(tmp_z):(self.flag+2)*len(tmp_z)]>=tmp_z[-1])[0][0])
569 print("tmp_r",tmp_r)
570 index_f=(self.flag+1)*len(tmp_z)+tmp_r
571
572 if len(tmp_z[index_i:])>len(self.buf_azi[len(tmp_z)*(self.flag+1):index_f]):
573 final = len(self.buf_azi[len(tmp_z)*(self.flag+1):index_f])
574 else:
575 final= len(tmp_z[index_i:])
576 self.buf_azi[len(tmp_z)*(self.flag+1):index_f]=tmp_z[index_i:index_i+final]
577 self.buf_tmp[len(tmp_z)*(self.flag+1):index_f,:]=tmp_v[index_i:index_i+final,:]
578 if limit_i<tmp_z[0]<limit_s:
579 index_f =int(numpy.where(self.buf_azi>=tmp_z[-1])[0][0])
580 n_p =index_f-len(tmp_z)*(self.flag+1)
581 if n_p>0:
582 self.buf_azi[len(tmp_z)*(self.flag+1):index_f]=tmp_z[-1]*numpy.ones(n_p)
583 self.buf_tmp[len(tmp_z)*(self.flag+1):index_f,:]=tmp_v[-1,:]*numpy.ones([n_p,tmp_v.shape[1]])
584
585 '''
586 if self.buf_azi[len(tmp_z)]<tmp_z[-1]<self.buf_azi[2*len(tmp_z)-1]:
587 index_i= int(numpy.where(tmp_z <= self.buf_azi[len(tmp_z)])[0][-1])
588 index_f= int(numpy.where(self.buf_azi>=tmp_z[-1])[0][0])
589 #print("index",index_i,index_f)
590 if len(tmp_z[index_i:])>len(self.buf_azi[len(tmp_z):index_f]):
591 final = len(self.buf_azi[len(tmp_z):index_f])
592 else:
593 final = len(tmp_z[index_i:])
594 self.buf_azi[len(tmp_z):index_f]=tmp_z[index_i:index_i+final]
595 self.buf_tmp[len(tmp_z):index_f,:]=tmp_v[index_i:index_i+final,:]
596 '''
597 self.buf_tmp[len(tmp_z)*(self.flag):len(tmp_z)*(self.flag+1),:]=tmp_v
598 self.buf_azi[len(tmp_z)*(self.flag):len(tmp_z)*(self.flag+1)] = tmp_z
599 self.buffer_ini=self.buf_tmp
600 self.buffer_ini_azi = self.buf_azi
601 ##print("--------salida------------")
602 start= tmp_z[0]
603 end = tmp_z[-1]
604 ##print("start","end",start,end)
605 ##print(self.buffer_ini_azi[:120])
606 self.ini= self.ini+1
607 self.flag = self.flag +1
608 if self.flag==step:
609 self.flag=0
610 numpy.set_printoptions(suppress=True)
611 print("buffer_ini_azi")
612 print(self.buffer_ini_azi[:20])
613 print(self.buffer_ini_azi[-40:])
614 for i,ax in enumerate(self.axes):
615 if ax.firsttime:
616 plt.clf()
617 cgax, pm = wrl.vis.plot_ppi(self.buffer_ini,r=r,az=self.buffer_ini_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
618 else:
619 plt.clf()
620 cgax, pm = wrl.vis.plot_ppi(self.buffer_ini,r=r,az=self.buffer_ini_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
621 caax = cgax.parasites[0]
622 paax = cgax.parasites[1]
623 cbar = plt.gcf().colorbar(pm, pad=0.075)
624 caax.set_xlabel('x_range [km]')
625 caax.set_ylabel('y_range [km]')
626 plt.text(1.0, 1.05, 'azimuth '+str(thisDatetime)+"step"+str(self.ini), transform=caax.transAxes, va='bottom',ha='right')
627 #import time
628 #time.sleep(0.5)
@@ -1,627 +1,518
1 import os
1 import os
2 import datetime
2 import datetime
3 import numpy
3 import numpy
4
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 from schainpy.utils import log
7 from schainpy.utils import log
8 # libreria wradlib
8 # libreria wradlib
9 import wradlib as wrl
9 import wradlib as wrl
10
10
11 EARTH_RADIUS = 6.3710e3
11 EARTH_RADIUS = 6.3710e3
12
12
13
13
14 def ll2xy(lat1, lon1, lat2, lon2):
14 def ll2xy(lat1, lon1, lat2, lon2):
15
15
16 p = 0.017453292519943295
16 p = 0.017453292519943295
17 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
17 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
18 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
18 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
19 r = 12742 * numpy.arcsin(numpy.sqrt(a))
19 r = 12742 * numpy.arcsin(numpy.sqrt(a))
20 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
20 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
21 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
21 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
22 theta = -theta + numpy.pi/2
22 theta = -theta + numpy.pi/2
23 return r*numpy.cos(theta), r*numpy.sin(theta)
23 return r*numpy.cos(theta), r*numpy.sin(theta)
24
24
25
25
26 def km2deg(km):
26 def km2deg(km):
27 '''
27 '''
28 Convert distance in km to degrees
28 Convert distance in km to degrees
29 '''
29 '''
30
30
31 return numpy.rad2deg(km/EARTH_RADIUS)
31 return numpy.rad2deg(km/EARTH_RADIUS)
32
32
33
33
34
34
35 class SpectralMomentsPlot(SpectraPlot):
35 class SpectralMomentsPlot(SpectraPlot):
36 '''
36 '''
37 Plot for Spectral Moments
37 Plot for Spectral Moments
38 '''
38 '''
39 CODE = 'spc_moments'
39 CODE = 'spc_moments'
40 # colormap = 'jet'
40 # colormap = 'jet'
41 # plot_type = 'pcolor'
41 # plot_type = 'pcolor'
42
42
43 class DobleGaussianPlot(SpectraPlot):
43 class DobleGaussianPlot(SpectraPlot):
44 '''
44 '''
45 Plot for Double Gaussian Plot
45 Plot for Double Gaussian Plot
46 '''
46 '''
47 CODE = 'gaussian_fit'
47 CODE = 'gaussian_fit'
48 # colormap = 'jet'
48 # colormap = 'jet'
49 # plot_type = 'pcolor'
49 # plot_type = 'pcolor'
50
50
51 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
51 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
52 '''
52 '''
53 Plot SpectraCut with Double Gaussian Fit
53 Plot SpectraCut with Double Gaussian Fit
54 '''
54 '''
55 CODE = 'cut_gaussian_fit'
55 CODE = 'cut_gaussian_fit'
56
56
57 class SnrPlot(RTIPlot):
57 class SnrPlot(RTIPlot):
58 '''
58 '''
59 Plot for SNR Data
59 Plot for SNR Data
60 '''
60 '''
61
61
62 CODE = 'snr'
62 CODE = 'snr'
63 colormap = 'jet'
63 colormap = 'jet'
64
64
65 def update(self, dataOut):
65 def update(self, dataOut):
66
66
67 data = {
67 data = {
68 'snr': 10*numpy.log10(dataOut.data_snr)
68 'snr': 10*numpy.log10(dataOut.data_snr)
69 }
69 }
70
70
71 return data, {}
71 return data, {}
72
72
73 class DopplerPlot(RTIPlot):
73 class DopplerPlot(RTIPlot):
74 '''
74 '''
75 Plot for DOPPLER Data (1st moment)
75 Plot for DOPPLER Data (1st moment)
76 '''
76 '''
77
77
78 CODE = 'dop'
78 CODE = 'dop'
79 colormap = 'jet'
79 colormap = 'jet'
80
80
81 def update(self, dataOut):
81 def update(self, dataOut):
82
82
83 data = {
83 data = {
84 'dop': 10*numpy.log10(dataOut.data_dop)
84 'dop': 10*numpy.log10(dataOut.data_dop)
85 }
85 }
86
86
87 return data, {}
87 return data, {}
88
88
89 class PowerPlot(RTIPlot):
89 class PowerPlot(RTIPlot):
90 '''
90 '''
91 Plot for Power Data (0 moment)
91 Plot for Power Data (0 moment)
92 '''
92 '''
93
93
94 CODE = 'pow'
94 CODE = 'pow'
95 colormap = 'jet'
95 colormap = 'jet'
96
96
97 def update(self, dataOut):
97 def update(self, dataOut):
98
98
99 data = {
99 data = {
100 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
100 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
101 }
101 }
102
102
103 return data, {}
103 return data, {}
104
104
105 class SpectralWidthPlot(RTIPlot):
105 class SpectralWidthPlot(RTIPlot):
106 '''
106 '''
107 Plot for Spectral Width Data (2nd moment)
107 Plot for Spectral Width Data (2nd moment)
108 '''
108 '''
109
109
110 CODE = 'width'
110 CODE = 'width'
111 colormap = 'jet'
111 colormap = 'jet'
112
112
113 def update(self, dataOut):
113 def update(self, dataOut):
114
114
115 data = {
115 data = {
116 'width': dataOut.data_width
116 'width': dataOut.data_width
117 }
117 }
118
118
119 return data, {}
119 return data, {}
120
120
121 class SkyMapPlot(Plot):
121 class SkyMapPlot(Plot):
122 '''
122 '''
123 Plot for meteors detection data
123 Plot for meteors detection data
124 '''
124 '''
125
125
126 CODE = 'param'
126 CODE = 'param'
127
127
128 def setup(self):
128 def setup(self):
129
129
130 self.ncols = 1
130 self.ncols = 1
131 self.nrows = 1
131 self.nrows = 1
132 self.width = 7.2
132 self.width = 7.2
133 self.height = 7.2
133 self.height = 7.2
134 self.nplots = 1
134 self.nplots = 1
135 self.xlabel = 'Zonal Zenith Angle (deg)'
135 self.xlabel = 'Zonal Zenith Angle (deg)'
136 self.ylabel = 'Meridional Zenith Angle (deg)'
136 self.ylabel = 'Meridional Zenith Angle (deg)'
137 self.polar = True
137 self.polar = True
138 self.ymin = -180
138 self.ymin = -180
139 self.ymax = 180
139 self.ymax = 180
140 self.colorbar = False
140 self.colorbar = False
141
141
142 def plot(self):
142 def plot(self):
143
143
144 arrayParameters = numpy.concatenate(self.data['param'])
144 arrayParameters = numpy.concatenate(self.data['param'])
145 error = arrayParameters[:, -1]
145 error = arrayParameters[:, -1]
146 indValid = numpy.where(error == 0)[0]
146 indValid = numpy.where(error == 0)[0]
147 finalMeteor = arrayParameters[indValid, :]
147 finalMeteor = arrayParameters[indValid, :]
148 finalAzimuth = finalMeteor[:, 3]
148 finalAzimuth = finalMeteor[:, 3]
149 finalZenith = finalMeteor[:, 4]
149 finalZenith = finalMeteor[:, 4]
150
150
151 x = finalAzimuth * numpy.pi / 180
151 x = finalAzimuth * numpy.pi / 180
152 y = finalZenith
152 y = finalZenith
153
153
154 ax = self.axes[0]
154 ax = self.axes[0]
155
155
156 if ax.firsttime:
156 if ax.firsttime:
157 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
157 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
158 else:
158 else:
159 ax.plot.set_data(x, y)
159 ax.plot.set_data(x, y)
160
160
161 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
161 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
162 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
162 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
163 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
163 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
164 dt2,
164 dt2,
165 len(x))
165 len(x))
166 self.titles[0] = title
166 self.titles[0] = title
167
167
168
168
169 class GenericRTIPlot(Plot):
169 class GenericRTIPlot(Plot):
170 '''
170 '''
171 Plot for data_xxxx object
171 Plot for data_xxxx object
172 '''
172 '''
173
173
174 CODE = 'param'
174 CODE = 'param'
175 colormap = 'viridis'
175 colormap = 'viridis'
176 plot_type = 'pcolorbuffer'
176 plot_type = 'pcolorbuffer'
177
177
178 def setup(self):
178 def setup(self):
179 self.xaxis = 'time'
179 self.xaxis = 'time'
180 self.ncols = 1
180 self.ncols = 1
181 self.nrows = self.data.shape('param')[0]
181 self.nrows = self.data.shape('param')[0]
182 self.nplots = self.nrows
182 self.nplots = self.nrows
183 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
183 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
184
184
185 if not self.xlabel:
185 if not self.xlabel:
186 self.xlabel = 'Time'
186 self.xlabel = 'Time'
187
187
188 self.ylabel = 'Range [km]'
188 self.ylabel = 'Range [km]'
189 if not self.titles:
189 if not self.titles:
190 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
190 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
191
191
192 def update(self, dataOut):
192 def update(self, dataOut):
193
193
194 data = {
194 data = {
195 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
195 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
196 }
196 }
197
197
198 meta = {}
198 meta = {}
199
199
200 return data, meta
200 return data, meta
201
201
202 def plot(self):
202 def plot(self):
203 # self.data.normalize_heights()
203 # self.data.normalize_heights()
204 self.x = self.data.times
204 self.x = self.data.times
205 self.y = self.data.yrange
205 self.y = self.data.yrange
206 self.z = self.data['param']
206 self.z = self.data['param']
207
207
208 self.z = 10*numpy.log10(self.z)
208 self.z = 10*numpy.log10(self.z)
209
209
210 self.z = numpy.ma.masked_invalid(self.z)
210 self.z = numpy.ma.masked_invalid(self.z)
211
211
212 if self.decimation is None:
212 if self.decimation is None:
213 x, y, z = self.fill_gaps(self.x, self.y, self.z)
213 x, y, z = self.fill_gaps(self.x, self.y, self.z)
214 else:
214 else:
215 x, y, z = self.fill_gaps(*self.decimate())
215 x, y, z = self.fill_gaps(*self.decimate())
216
216
217 for n, ax in enumerate(self.axes):
217 for n, ax in enumerate(self.axes):
218
218
219 self.zmax = self.zmax if self.zmax is not None else numpy.max(
219 self.zmax = self.zmax if self.zmax is not None else numpy.max(
220 self.z[n])
220 self.z[n])
221 self.zmin = self.zmin if self.zmin is not None else numpy.min(
221 self.zmin = self.zmin if self.zmin is not None else numpy.min(
222 self.z[n])
222 self.z[n])
223
223
224 if ax.firsttime:
224 if ax.firsttime:
225 if self.zlimits is not None:
225 if self.zlimits is not None:
226 self.zmin, self.zmax = self.zlimits[n]
226 self.zmin, self.zmax = self.zlimits[n]
227
227
228 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
228 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
229 vmin=self.zmin,
229 vmin=self.zmin,
230 vmax=self.zmax,
230 vmax=self.zmax,
231 cmap=self.cmaps[n]
231 cmap=self.cmaps[n]
232 )
232 )
233 else:
233 else:
234 if self.zlimits is not None:
234 if self.zlimits is not None:
235 self.zmin, self.zmax = self.zlimits[n]
235 self.zmin, self.zmax = self.zlimits[n]
236 ax.collections.remove(ax.collections[0])
236 ax.collections.remove(ax.collections[0])
237 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
237 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
238 vmin=self.zmin,
238 vmin=self.zmin,
239 vmax=self.zmax,
239 vmax=self.zmax,
240 cmap=self.cmaps[n]
240 cmap=self.cmaps[n]
241 )
241 )
242
242
243
243
244 class PolarMapPlot(Plot):
244 class PolarMapPlot(Plot):
245 '''
245 '''
246 Plot for weather radar
246 Plot for weather radar
247 '''
247 '''
248
248
249 CODE = 'param'
249 CODE = 'param'
250 colormap = 'seismic'
250 colormap = 'seismic'
251
251
252 def setup(self):
252 def setup(self):
253 self.ncols = 1
253 self.ncols = 1
254 self.nrows = 1
254 self.nrows = 1
255 self.width = 9
255 self.width = 9
256 self.height = 8
256 self.height = 8
257 self.mode = self.data.meta['mode']
257 self.mode = self.data.meta['mode']
258 if self.channels is not None:
258 if self.channels is not None:
259 self.nplots = len(self.channels)
259 self.nplots = len(self.channels)
260 self.nrows = len(self.channels)
260 self.nrows = len(self.channels)
261 else:
261 else:
262 self.nplots = self.data.shape(self.CODE)[0]
262 self.nplots = self.data.shape(self.CODE)[0]
263 self.nrows = self.nplots
263 self.nrows = self.nplots
264 self.channels = list(range(self.nplots))
264 self.channels = list(range(self.nplots))
265 if self.mode == 'E':
265 if self.mode == 'E':
266 self.xlabel = 'Longitude'
266 self.xlabel = 'Longitude'
267 self.ylabel = 'Latitude'
267 self.ylabel = 'Latitude'
268 else:
268 else:
269 self.xlabel = 'Range (km)'
269 self.xlabel = 'Range (km)'
270 self.ylabel = 'Height (km)'
270 self.ylabel = 'Height (km)'
271 self.bgcolor = 'white'
271 self.bgcolor = 'white'
272 self.cb_labels = self.data.meta['units']
272 self.cb_labels = self.data.meta['units']
273 self.lat = self.data.meta['latitude']
273 self.lat = self.data.meta['latitude']
274 self.lon = self.data.meta['longitude']
274 self.lon = self.data.meta['longitude']
275 self.xmin, self.xmax = float(
275 self.xmin, self.xmax = float(
276 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
276 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
277 self.ymin, self.ymax = float(
277 self.ymin, self.ymax = float(
278 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
278 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
279 # self.polar = True
279 # self.polar = True
280
280
281 def plot(self):
281 def plot(self):
282
282
283 for n, ax in enumerate(self.axes):
283 for n, ax in enumerate(self.axes):
284 data = self.data['param'][self.channels[n]]
284 data = self.data['param'][self.channels[n]]
285
285
286 zeniths = numpy.linspace(
286 zeniths = numpy.linspace(
287 0, self.data.meta['max_range'], data.shape[1])
287 0, self.data.meta['max_range'], data.shape[1])
288 if self.mode == 'E':
288 if self.mode == 'E':
289 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
289 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
290 r, theta = numpy.meshgrid(zeniths, azimuths)
290 r, theta = numpy.meshgrid(zeniths, azimuths)
291 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
291 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
292 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
292 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
293 x = km2deg(x) + self.lon
293 x = km2deg(x) + self.lon
294 y = km2deg(y) + self.lat
294 y = km2deg(y) + self.lat
295 else:
295 else:
296 azimuths = numpy.radians(self.data.yrange)
296 azimuths = numpy.radians(self.data.yrange)
297 r, theta = numpy.meshgrid(zeniths, azimuths)
297 r, theta = numpy.meshgrid(zeniths, azimuths)
298 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
298 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
299 self.y = zeniths
299 self.y = zeniths
300
300
301 if ax.firsttime:
301 if ax.firsttime:
302 if self.zlimits is not None:
302 if self.zlimits is not None:
303 self.zmin, self.zmax = self.zlimits[n]
303 self.zmin, self.zmax = self.zlimits[n]
304 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
304 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
305 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
305 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
306 vmin=self.zmin,
306 vmin=self.zmin,
307 vmax=self.zmax,
307 vmax=self.zmax,
308 cmap=self.cmaps[n])
308 cmap=self.cmaps[n])
309 else:
309 else:
310 if self.zlimits is not None:
310 if self.zlimits is not None:
311 self.zmin, self.zmax = self.zlimits[n]
311 self.zmin, self.zmax = self.zlimits[n]
312 ax.collections.remove(ax.collections[0])
312 ax.collections.remove(ax.collections[0])
313 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
313 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
314 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
314 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
315 vmin=self.zmin,
315 vmin=self.zmin,
316 vmax=self.zmax,
316 vmax=self.zmax,
317 cmap=self.cmaps[n])
317 cmap=self.cmaps[n])
318
318
319 if self.mode == 'A':
319 if self.mode == 'A':
320 continue
320 continue
321
321
322 # plot district names
322 # plot district names
323 f = open('/data/workspace/schain_scripts/distrito.csv')
323 f = open('/data/workspace/schain_scripts/distrito.csv')
324 for line in f:
324 for line in f:
325 label, lon, lat = [s.strip() for s in line.split(',') if s]
325 label, lon, lat = [s.strip() for s in line.split(',') if s]
326 lat = float(lat)
326 lat = float(lat)
327 lon = float(lon)
327 lon = float(lon)
328 # ax.plot(lon, lat, '.b', ms=2)
328 # ax.plot(lon, lat, '.b', ms=2)
329 ax.text(lon, lat, label.decode('utf8'), ha='center',
329 ax.text(lon, lat, label.decode('utf8'), ha='center',
330 va='bottom', size='8', color='black')
330 va='bottom', size='8', color='black')
331
331
332 # plot limites
332 # plot limites
333 limites = []
333 limites = []
334 tmp = []
334 tmp = []
335 for line in open('/data/workspace/schain_scripts/lima.csv'):
335 for line in open('/data/workspace/schain_scripts/lima.csv'):
336 if '#' in line:
336 if '#' in line:
337 if tmp:
337 if tmp:
338 limites.append(tmp)
338 limites.append(tmp)
339 tmp = []
339 tmp = []
340 continue
340 continue
341 values = line.strip().split(',')
341 values = line.strip().split(',')
342 tmp.append((float(values[0]), float(values[1])))
342 tmp.append((float(values[0]), float(values[1])))
343 for points in limites:
343 for points in limites:
344 ax.add_patch(
344 ax.add_patch(
345 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
345 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
346
346
347 # plot Cuencas
347 # plot Cuencas
348 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
348 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
349 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
349 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
350 values = [line.strip().split(',') for line in f]
350 values = [line.strip().split(',') for line in f]
351 points = [(float(s[0]), float(s[1])) for s in values]
351 points = [(float(s[0]), float(s[1])) for s in values]
352 ax.add_patch(Polygon(points, ec='b', fc='none'))
352 ax.add_patch(Polygon(points, ec='b', fc='none'))
353
353
354 # plot grid
354 # plot grid
355 for r in (15, 30, 45, 60):
355 for r in (15, 30, 45, 60):
356 ax.add_artist(plt.Circle((self.lon, self.lat),
356 ax.add_artist(plt.Circle((self.lon, self.lat),
357 km2deg(r), color='0.6', fill=False, lw=0.2))
357 km2deg(r), color='0.6', fill=False, lw=0.2))
358 ax.text(
358 ax.text(
359 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
359 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
360 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
360 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
361 '{}km'.format(r),
361 '{}km'.format(r),
362 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
362 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
363
363
364 if self.mode == 'E':
364 if self.mode == 'E':
365 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
365 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
366 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
366 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
367 else:
367 else:
368 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
368 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
369 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
369 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
370
370
371 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
371 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
372 self.titles = ['{} {}'.format(
372 self.titles = ['{} {}'.format(
373 self.data.parameters[x], title) for x in self.channels]
373 self.data.parameters[x], title) for x in self.channels]
374
374
375 class WeatherPlot(Plot):
375 class WeatherPlot(Plot):
376 CODE = 'weather'
376 CODE = 'weather'
377 plot_name = 'weather'
377 plot_name = 'weather'
378 plot_type = 'ppistyle'
378 plot_type = 'ppistyle'
379 buffering = False
379 buffering = False
380
380
381 def setup(self):
381 def setup(self):
382 self.ncols = 1
382 self.ncols = 1
383 self.nrows = 1
383 self.nrows = 1
384 self.nplots= 1
384 self.nplots= 1
385 self.ylabel= 'Range [Km]'
385 self.ylabel= 'Range [Km]'
386 self.titles= ['Weather']
386 self.titles= ['Weather']
387 self.colorbar=False
387 self.colorbar=False
388 self.width =8
388 self.width =8
389 self.height =8
389 self.height =8
390 self.ini =0
390 self.ini =0
391 self.len_azi =0
391 self.len_azi =0
392 self.buffer_ini = None
392 self.buffer_ini = None
393 self.buffer_azi = None
393 self.buffer_azi = None
394 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
394 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
395 self.flag =0
395 self.flag =0
396 self.indicador= 0
396 self.indicador= 0
397
397
398 def update(self, dataOut):
398 def update(self, dataOut):
399
399
400 data = {}
400 data = {}
401 meta = {}
401 meta = {}
402 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(250**2))
402 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(250**2))
403 print(data['weather'])
403 data['azi'] = dataOut.data_azi
404 data['azi'] = dataOut.data_azi
404
405 print("UPDATE",data['azi'])
405 return data, meta
406 return data, meta
406
407
408 def const_ploteo(self,data_weather,data_azi,step,res):
409 #print("data_weather",data_weather)
410 print("data_azi",data_azi)
411 print("step",step)
412 if self.ini==0:
413 #------- AZIMUTH
414 n = (360/res)-len(data_azi)
415 start = data_azi[-1] + res
416 end = data_azi[0] - res
417 if start>end:
418 end = end + 360
419 azi_vacia = numpy.linspace(start,end,int(n))
420 azi_vacia = numpy.where(azi_vacia>360,azi_vacia-360,azi_vacia)
421 data_azi = numpy.hstack((data_azi,azi_vacia))
422 # RADAR
423 val_mean = numpy.mean(data_weather[:,0])
424 data_weather_cmp = numpy.ones([(360-data_weather.shape[0]),data_weather.shape[1]])*val_mean
425 data_weather = numpy.vstack((data_weather,data_weather_cmp))
426 else:
427 # azimuth
428 flag=0
429 start_azi = self.res_azi[0]
430 start = data_azi[0]
431 end = data_azi[-1]
432 print("start",start)
433 print("end",end)
434 if start< start_azi:
435 start = start +360
436 if end <start_azi:
437 end = end +360
438
439 print("start",start)
440 print("end",end)
441 #### AQUI SERA LA MAGIA
442 pos_ini = int((start-start_azi)/res)
443 len_azi = len(data_azi)
444 if (360-pos_ini)<len_azi:
445 if pos_ini+1==360:
446 pos_ini=0
447 else:
448 flag=1
449 dif= 360-pos_ini
450 comp= len_azi-dif
451
452 print(pos_ini)
453 print(len_azi)
454 print("shape",self.res_azi.shape)
455 if flag==0:
456 # AZIMUTH
457 self.res_azi[pos_ini:pos_ini+len_azi] = data_azi
458 # RADAR
459 self.res_weather[pos_ini:pos_ini+len_azi,:] = data_weather
460 else:
461 # AZIMUTH
462 self.res_azi[pos_ini:pos_ini+dif] = data_azi[0:dif]
463 self.res_azi[0:comp] = data_azi[dif:]
464 # RADAR
465 self.res_weather[pos_ini:pos_ini+dif,:] = data_weather[0:dif,:]
466 self.res_weather[0:comp,:] = data_weather[dif:,:]
467 flag=0
468 data_azi = self.res_azi
469 data_weather = self.res_weather
470
471 return data_weather,data_azi
472
407 def plot(self):
473 def plot(self):
408 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
409 print("--------------------------------------",self.ini,"-----------------------------------")
474 print("--------------------------------------",self.ini,"-----------------------------------")
410 print("time",self.data.times[-1])
475 #numpy.set_printoptions(suppress=True)
411 data = self.data[-1]
476 #print(self.data.times)
412 #print("debug_0", data)
477 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
413 tmp_h = (data['weather'].shape[1])/10.0
478 data = self.data[-1]
414 #print("debug_1",tmp_h)
479 # ALTURA altura_tmp_h
415 stoprange = float(tmp_h*1.5)#stoprange = float(33*1.5) por ahora 400
480 altura_h = (data['weather'].shape[1])/10.0
481 stoprange = float(altura_h*1.5)#stoprange = float(33*1.5) por ahora 400
416 rangestep = float(0.15)
482 rangestep = float(0.15)
417 r = numpy.arange(0, stoprange, rangestep)
483 r = numpy.arange(0, stoprange, rangestep)
418 self.y = 2*r
484 self.y = 2*r
419 print("---------------")
485 # RADAR
420 tmp_v = data['weather']
486 #data_weather = data['weather']
421 #print("tmp_v",tmp_v.shape)
487 # PEDESTAL
422 tmp_z = data['azi']
488 #data_azi = data['azi']
423 print("tmp_z-------------->",tmp_z)
489 res = 1
424 ##if self.ini==0:
490 # STEP
425 ## tmp_z= [0,1,2,3,4,5,6,7,8,9]
491 step = (360/(res*data['weather'].shape[0]))
426
492 #print("shape wr_data", wr_data.shape)
427 #print("tmp_z",tmp_z.shape)
493 #print("shape wr_azi",wr_azi.shape)
428 res = 1
429 step = (360/(res*tmp_v.shape[0]))
430 #print("step",step)
494 #print("step",step)
431 mode = 1
495 print("Time---->",self.data.times[-1],thisDatetime)
432 if mode==0:
496 #print("alturas", len(self.y))
433 #print("self.ini",self.ini)
497 self.res_weather, self.res_azi = self.const_ploteo(data_weather=data['weather'],data_azi=data['azi'],step=step,res=res)
434 val = numpy.mean(tmp_v[:,0])
498 #numpy.set_printoptions(suppress=True)
435 self.len_azi = len(tmp_z)
499 #print("resultado",self.res_azi)
436 ones = numpy.ones([(360-tmp_v.shape[0]),tmp_v.shape[1]])*val
500 ##########################################################
437 self.buffer_ini = numpy.vstack((tmp_v,ones))
501 ################# PLOTEO ###################
438
502 ##########################################################
439 n = ((360/res)-len(tmp_z))
440 start = tmp_z[-1]+res
441 end = tmp_z[0]-res
442 if start>end:
443 end = end+360
444 azi_zeros = numpy.linspace(start,end,int(n))
445 azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
446 self.buffer_ini_azi = numpy.hstack((tmp_z,azi_zeros))
447 self.ini = self.ini+1
448
449 if mode==1:
450 #print("################")
451 #print("################")
452 #print("mode",self.ini)
453 #print("self.ini",self.ini)
454 if self.ini==0:
455 res = 1
456 step = (360/(res*tmp_v.shape[0]))
457 val = numpy.mean(tmp_v[:,0])
458 self.len_azi = len(tmp_z)
459 self.buf_tmp = tmp_v
460 ones = numpy.ones([(360-tmp_v.shape[0]),tmp_v.shape[1]])*val
461 self.buffer_ini = numpy.vstack((tmp_v,ones))
462
463 n = ((360/res)-len(tmp_z))
464 start = tmp_z[-1]+res
465 end = tmp_z[0]-res
466 if start>end:
467 end =end+360
468 azi_zeros = numpy.linspace(start,end,int(n))
469 azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
470 self.buf_azi = tmp_z
471 self.buffer_ini_azi = numpy.hstack((tmp_z,azi_zeros))
472 self.ini = self.ini+1
473 elif 0<self.ini<step:
474 '''
475 if self.ini>31:
476 start= tmp_z[0]
477 end =tmp_z[-1]
478 print("start","end",start,end)
479 if self.ini==32:
480 tmp_v=tmp_v+20
481 if self.ini==33:
482 tmp_v=tmp_v+10
483 if self.ini==34:
484 tmp_v=tmp_v+20
485 if self.ini==35:
486 tmp_v=tmp_v+20
487 '''
488 self.buf_tmp= numpy.vstack((self.buf_tmp,tmp_v))
489 print("ERROR_INMINENTE",self.buf_tmp.shape)
490 if self.buf_tmp.shape[0]==360:
491 print("entre aqui en 360 grados")
492 self.buffer_ini=self.buf_tmp
493 else:
494 # nuevo#########
495 self.buffer_ini[0:self.buf_tmp.shape[0],:]=self.buf_tmp
496 ################
497 #val=30.0
498 #ones = numpy.ones([(360-self.buf_tmp.shape[0]),self.buf_tmp.shape[1]])*val
499 #self.buffer_ini = numpy.vstack((self.buf_tmp,ones))
500
501 self.buf_azi = numpy.hstack((self.buf_azi,tmp_z))
502 n = ((360/res)-len(self.buf_azi))
503 print("n----->",n)
504 if n==0:
505 self.buffer_ini_azi = self.buf_azi
506 else:
507 start = self.buf_azi[-1]+res
508 end = self.buf_azi[0]-res
509 print("start",start)
510 print("end",end)
511 if start>end:
512 end =end+360
513 azi_zeros = numpy.linspace(start,end,int(n))
514 azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
515 print("self.buf_azi",self.buf_azi[0])
516 print("tmp_Z 0 ",tmp_z[0])
517 print("tmp_Z -1",tmp_z[-1])
518 if tmp_z[0]<self.buf_azi[0] <tmp_z[-1]:
519 print("activando indicador")
520 self.indicador=1
521 if self.indicador==1:
522 azi_zeros = numpy.ones(360-len(self.buf_azi))*(tmp_z[-1]+res)
523 ###start = tmp_z[-1]+res
524 ###end = tmp_z[0]-res
525 ###if start>end:
526 ### end =end+360
527 ###azi_zeros = numpy.linspace(start,end,int(n))
528 ###azi_zeros = numpy.where(azi_zeros>360,azi_zeros-360,azi_zeros)
529 print("azi_zeros",azi_zeros)
530
531 ######self.buffer_ini_azi = numpy.hstack((self.buf_azi,azi_zeros))
532 #self.buffer_ini[0:tmv.shape[0],:]=tmp_v
533 ##self.indicador=0
534
535 # self.indicador = True
536 #if self.indicador==True:
537 # azi_zeros = numpy.ones(360-len(self.buf_azi))*(tmp_z[-1]+res)
538
539 #self.buf_azi = tmp_z
540 self.buffer_ini_azi = numpy.hstack((self.buf_azi,azi_zeros))
541
542 if self.ini==step-1:
543 start= tmp_z[0]
544 end = tmp_z[-1]
545 #print("start","end",start,end)
546 ###print(self.buffer_ini_azi[:80])
547 self.ini = self.ini+1
548
503
549 else:
550 step = (360/(res*tmp_v.shape[0]))
551 # aqui estaba realizando el debug de simulacion
552 # tmp_v=tmp_v +5 en cada step sumaba 5
553 # y el mismo valor despues de la primera vuelta
554 #tmp_v=tmp_v+5+(self.ini-step)*1### aqui yo habia sumado 5 por las puras
555
556 start= tmp_z[0]
557 end = tmp_z[-1]
558 #print("start","end",start,end)
559 ###print(self.buffer_ini_azi[:120])
560
561 if step>=2:
562 if self.flag<step-1:
563 limit_i=self.buf_azi[len(tmp_z)*(self.flag+1)]
564 limit_s=self.buf_azi[len(tmp_z)*(self.flag+2)-1]
565 print("flag",self.flag,limit_i,limit_s)
566 if limit_i< tmp_z[-1]< limit_s:
567 index_i=int(numpy.where(tmp_z<=self.buf_azi[len(tmp_z)*(self.flag+1)])[0][-1])
568 tmp_r =int(numpy.where(self.buf_azi[(self.flag+1)*len(tmp_z):(self.flag+2)*len(tmp_z)]>=tmp_z[-1])[0][0])
569 print("tmp_r",tmp_r)
570 index_f=(self.flag+1)*len(tmp_z)+tmp_r
571
572 if len(tmp_z[index_i:])>len(self.buf_azi[len(tmp_z)*(self.flag+1):index_f]):
573 final = len(self.buf_azi[len(tmp_z)*(self.flag+1):index_f])
574 else:
575 final= len(tmp_z[index_i:])
576 self.buf_azi[len(tmp_z)*(self.flag+1):index_f]=tmp_z[index_i:index_i+final]
577 self.buf_tmp[len(tmp_z)*(self.flag+1):index_f,:]=tmp_v[index_i:index_i+final,:]
578 if limit_i<tmp_z[0]<limit_s:
579 index_f =int(numpy.where(self.buf_azi>=tmp_z[-1])[0][0])
580 n_p =index_f-len(tmp_z)*(self.flag+1)
581 if n_p>0:
582 self.buf_azi[len(tmp_z)*(self.flag+1):index_f]=tmp_z[-1]*numpy.ones(n_p)
583 self.buf_tmp[len(tmp_z)*(self.flag+1):index_f,:]=tmp_v[-1,:]*numpy.ones([n_p,tmp_v.shape[1]])
584
585 '''
586 if self.buf_azi[len(tmp_z)]<tmp_z[-1]<self.buf_azi[2*len(tmp_z)-1]:
587 index_i= int(numpy.where(tmp_z <= self.buf_azi[len(tmp_z)])[0][-1])
588 index_f= int(numpy.where(self.buf_azi>=tmp_z[-1])[0][0])
589 #print("index",index_i,index_f)
590 if len(tmp_z[index_i:])>len(self.buf_azi[len(tmp_z):index_f]):
591 final = len(self.buf_azi[len(tmp_z):index_f])
592 else:
593 final = len(tmp_z[index_i:])
594 self.buf_azi[len(tmp_z):index_f]=tmp_z[index_i:index_i+final]
595 self.buf_tmp[len(tmp_z):index_f,:]=tmp_v[index_i:index_i+final,:]
596 '''
597 self.buf_tmp[len(tmp_z)*(self.flag):len(tmp_z)*(self.flag+1),:]=tmp_v
598 self.buf_azi[len(tmp_z)*(self.flag):len(tmp_z)*(self.flag+1)] = tmp_z
599 self.buffer_ini=self.buf_tmp
600 self.buffer_ini_azi = self.buf_azi
601 ##print("--------salida------------")
602 start= tmp_z[0]
603 end = tmp_z[-1]
604 ##print("start","end",start,end)
605 ##print(self.buffer_ini_azi[:120])
606 self.ini= self.ini+1
607 self.flag = self.flag +1
608 if self.flag==step:
609 self.flag=0
610 numpy.set_printoptions(suppress=True)
611 print("buffer_ini_azi")
612 print(self.buffer_ini_azi)
613 for i,ax in enumerate(self.axes):
504 for i,ax in enumerate(self.axes):
614 if ax.firsttime:
505 if ax.firsttime:
615 plt.clf()
506 plt.clf()
616 cgax, pm = wrl.vis.plot_ppi(self.buffer_ini,r=r,az=self.buffer_ini_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
507 cgax, pm = wrl.vis.plot_ppi(self.res_weather,r=r,az=self.res_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
617 else:
508 else:
618 plt.clf()
509 plt.clf()
619 cgax, pm = wrl.vis.plot_ppi(self.buffer_ini,r=r,az=self.buffer_ini_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
510 cgax, pm = wrl.vis.plot_ppi(self.res_weather,r=r,az=self.res_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
620 caax = cgax.parasites[0]
511 caax = cgax.parasites[0]
621 paax = cgax.parasites[1]
512 paax = cgax.parasites[1]
622 cbar = plt.gcf().colorbar(pm, pad=0.075)
513 cbar = plt.gcf().colorbar(pm, pad=0.075)
623 caax.set_xlabel('x_range [km]')
514 caax.set_xlabel('x_range [km]')
624 caax.set_ylabel('y_range [km]')
515 caax.set_ylabel('y_range [km]')
625 plt.text(1.0, 1.05, 'azimuth '+str(thisDatetime)+"step"+str(self.ini), transform=caax.transAxes, va='bottom',ha='right')
516 plt.text(1.0, 1.05, 'azimuth '+str(thisDatetime)+"step"+str(self.ini), transform=caax.transAxes, va='bottom',ha='right')
626 #import time
517
627 #time.sleep(0.5)
518 self.ini= self.ini+1
@@ -1,203 +1,206
1 '''
1 '''
2 Base clases to create Processing units and operations, the MPDecorator
2 Base clases to create Processing units and operations, the MPDecorator
3 must be used in plotting and writing operations to allow to run as an
3 must be used in plotting and writing operations to allow to run as an
4 external process.
4 external process.
5 '''
5 '''
6
6
7 import inspect
7 import inspect
8 import zmq
8 import zmq
9 import time
9 import time
10 import pickle
10 import pickle
11 import traceback
11 import traceback
12 from threading import Thread
12 from threading import Thread
13 from multiprocessing import Process, Queue
13 from multiprocessing import Process, Queue
14 from schainpy.utils import log
14 from schainpy.utils import log
15
15
16
16
17 class ProcessingUnit(object):
17 class ProcessingUnit(object):
18 '''
18 '''
19 Base class to create Signal Chain Units
19 Base class to create Signal Chain Units
20 '''
20 '''
21
21
22 proc_type = 'processing'
22 proc_type = 'processing'
23
23
24 def __init__(self):
24 def __init__(self):
25
25
26 self.dataIn = None
26 self.dataIn = None
27 self.dataOut = None
27 self.dataOut = None
28 self.isConfig = False
28 self.isConfig = False
29 self.operations = []
29 self.operations = []
30
30
31 def setInput(self, unit):
31 def setInput(self, unit):
32
32
33 self.dataIn = unit.dataOut
33 self.dataIn = unit.dataOut
34
34
35 def getAllowedArgs(self):
35 def getAllowedArgs(self):
36 if hasattr(self, '__attrs__'):
36 if hasattr(self, '__attrs__'):
37 return self.__attrs__
37 return self.__attrs__
38 else:
38 else:
39 return inspect.getargspec(self.run).args
39 return inspect.getargspec(self.run).args
40
40
41 def addOperation(self, conf, operation):
41 def addOperation(self, conf, operation):
42 '''
42 '''
43 '''
43 '''
44
44
45 self.operations.append((operation, conf.type, conf.getKwargs()))
45 self.operations.append((operation, conf.type, conf.getKwargs()))
46
46
47 def getOperationObj(self, objId):
47 def getOperationObj(self, objId):
48
48
49 if objId not in list(self.operations.keys()):
49 if objId not in list(self.operations.keys()):
50 return None
50 return None
51
51
52 return self.operations[objId]
52 return self.operations[objId]
53
53
54 def call(self, **kwargs):
54 def call(self, **kwargs):
55 '''
55 '''
56 '''
56 '''
57
57
58 try:
58 try:
59 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
59 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
60 return self.dataIn.isReady()
60 return self.dataIn.isReady()
61 elif self.dataIn is None or not self.dataIn.error:
61 elif self.dataIn is None or not self.dataIn.error:
62 self.run(**kwargs)
62 self.run(**kwargs)
63 elif self.dataIn.error:
63 elif self.dataIn.error:
64 self.dataOut.error = self.dataIn.error
64 self.dataOut.error = self.dataIn.error
65 self.dataOut.flagNoData = True
65 self.dataOut.flagNoData = True
66 except:
66 except:
67 err = traceback.format_exc()
67 err = traceback.format_exc()
68 if 'SchainWarning' in err:
68 if 'SchainWarning' in err:
69 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
69 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
70 elif 'SchainError' in err:
70 elif 'SchainError' in err:
71 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
71 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
72 else:
72 else:
73 log.error(err, self.name)
73 log.error(err, self.name)
74 self.dataOut.error = True
74 self.dataOut.error = True
75
75 ##### correcion de la declaracion Out
76 for op, optype, opkwargs in self.operations:
76 for op, optype, opkwargs in self.operations:
77 aux = self.dataOut.copy()
77 if optype == 'other' and not self.dataOut.flagNoData:
78 if optype == 'other' and not self.dataOut.flagNoData:
78 self.dataOut = op.run(self.dataOut, **opkwargs)
79 self.dataOut = op.run(self.dataOut, **opkwargs)
79 elif optype == 'external' and not self.dataOut.flagNoData:
80 elif optype == 'external' and not self.dataOut.flagNoData:
80 op.queue.put(self.dataOut)
81 #op.queue.put(self.dataOut)
81 elif optype == 'external' and self.dataOut.error:
82 op.queue.put(aux)
82 op.queue.put(self.dataOut)
83 elif optype == 'external' and self.dataOut.error:
84 #op.queue.put(self.dataOut)
85 op.queue.put(aux)
83
86
84 return 'Error' if self.dataOut.error else self.dataOut.isReady()
87 return 'Error' if self.dataOut.error else self.dataOut.isReady()
85
88
86 def setup(self):
89 def setup(self):
87
90
88 raise NotImplementedError
91 raise NotImplementedError
89
92
90 def run(self):
93 def run(self):
91
94
92 raise NotImplementedError
95 raise NotImplementedError
93
96
94 def close(self):
97 def close(self):
95
98
96 return
99 return
97
100
98
101
99 class Operation(object):
102 class Operation(object):
100
103
101 '''
104 '''
102 '''
105 '''
103
106
104 proc_type = 'operation'
107 proc_type = 'operation'
105
108
106 def __init__(self):
109 def __init__(self):
107
110
108 self.id = None
111 self.id = None
109 self.isConfig = False
112 self.isConfig = False
110
113
111 if not hasattr(self, 'name'):
114 if not hasattr(self, 'name'):
112 self.name = self.__class__.__name__
115 self.name = self.__class__.__name__
113
116
114 def getAllowedArgs(self):
117 def getAllowedArgs(self):
115 if hasattr(self, '__attrs__'):
118 if hasattr(self, '__attrs__'):
116 return self.__attrs__
119 return self.__attrs__
117 else:
120 else:
118 return inspect.getargspec(self.run).args
121 return inspect.getargspec(self.run).args
119
122
120 def setup(self):
123 def setup(self):
121
124
122 self.isConfig = True
125 self.isConfig = True
123
126
124 raise NotImplementedError
127 raise NotImplementedError
125
128
126 def run(self, dataIn, **kwargs):
129 def run(self, dataIn, **kwargs):
127 """
130 """
128 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
131 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
129 atributos del objeto dataIn.
132 atributos del objeto dataIn.
130
133
131 Input:
134 Input:
132
135
133 dataIn : objeto del tipo JROData
136 dataIn : objeto del tipo JROData
134
137
135 Return:
138 Return:
136
139
137 None
140 None
138
141
139 Affected:
142 Affected:
140 __buffer : buffer de recepcion de datos.
143 __buffer : buffer de recepcion de datos.
141
144
142 """
145 """
143 if not self.isConfig:
146 if not self.isConfig:
144 self.setup(**kwargs)
147 self.setup(**kwargs)
145
148
146 raise NotImplementedError
149 raise NotImplementedError
147
150
148 def close(self):
151 def close(self):
149
152
150 return
153 return
151
154
152
155
153 def MPDecorator(BaseClass):
156 def MPDecorator(BaseClass):
154 """
157 """
155 Multiprocessing class decorator
158 Multiprocessing class decorator
156
159
157 This function add multiprocessing features to a BaseClass.
160 This function add multiprocessing features to a BaseClass.
158 """
161 """
159
162
160 class MPClass(BaseClass, Process):
163 class MPClass(BaseClass, Process):
161
164
162 def __init__(self, *args, **kwargs):
165 def __init__(self, *args, **kwargs):
163 super(MPClass, self).__init__()
166 super(MPClass, self).__init__()
164 Process.__init__(self)
167 Process.__init__(self)
165
168
166 self.args = args
169 self.args = args
167 self.kwargs = kwargs
170 self.kwargs = kwargs
168 self.t = time.time()
171 self.t = time.time()
169 self.op_type = 'external'
172 self.op_type = 'external'
170 self.name = BaseClass.__name__
173 self.name = BaseClass.__name__
171 self.__doc__ = BaseClass.__doc__
174 self.__doc__ = BaseClass.__doc__
172
175
173 if 'plot' in self.name.lower() and not self.name.endswith('_'):
176 if 'plot' in self.name.lower() and not self.name.endswith('_'):
174 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
177 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
175
178
176 self.start_time = time.time()
179 self.start_time = time.time()
177 self.err_queue = args[3]
180 self.err_queue = args[3]
178 self.queue = Queue(maxsize=1)
181 self.queue = Queue(maxsize=1)
179 self.myrun = BaseClass.run
182 self.myrun = BaseClass.run
180
183
181 def run(self):
184 def run(self):
182
185
183 while True:
186 while True:
184
187
185 dataOut = self.queue.get()
188 dataOut = self.queue.get()
186
189
187 if not dataOut.error:
190 if not dataOut.error:
188 try:
191 try:
189 BaseClass.run(self, dataOut, **self.kwargs)
192 BaseClass.run(self, dataOut, **self.kwargs)
190 except:
193 except:
191 err = traceback.format_exc()
194 err = traceback.format_exc()
192 log.error(err, self.name)
195 log.error(err, self.name)
193 else:
196 else:
194 break
197 break
195
198
196 self.close()
199 self.close()
197
200
198 def close(self):
201 def close(self):
199
202
200 BaseClass.close(self)
203 BaseClass.close(self)
201 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
204 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
202
205
203 return MPClass
206 return MPClass
@@ -1,4502 +1,4450
1 import numpy,os,h5py
1 import numpy,os,h5py
2 import math
2 import math
3 from scipy import optimize, interpolate, signal, stats, ndimage
3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 import scipy
5 import re
5 import re
6 import datetime
6 import datetime
7 import copy
7 import copy
8 import sys
8 import sys
9 import importlib
9 import importlib
10 import itertools
10 import itertools
11 from multiprocessing import Pool, TimeoutError
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
12 from multiprocessing.pool import ThreadPool
13 import time
13 import time
14
14
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 from scipy import asarray as ar,exp
18 from scipy import asarray as ar,exp
19 from scipy.optimize import curve_fit
19 from scipy.optimize import curve_fit
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import warnings
21 import warnings
22 from numpy import NaN
22 from numpy import NaN
23 from scipy.optimize.optimize import OptimizeWarning
23 from scipy.optimize.optimize import OptimizeWarning
24 warnings.filterwarnings('ignore')
24 warnings.filterwarnings('ignore')
25
25
26 import matplotlib.pyplot as plt
26 import matplotlib.pyplot as plt
27
27
28 SPEED_OF_LIGHT = 299792458
28 SPEED_OF_LIGHT = 299792458
29
29
30 '''solving pickling issue'''
30 '''solving pickling issue'''
31
31
32 def _pickle_method(method):
32 def _pickle_method(method):
33 func_name = method.__func__.__name__
33 func_name = method.__func__.__name__
34 obj = method.__self__
34 obj = method.__self__
35 cls = method.__self__.__class__
35 cls = method.__self__.__class__
36 return _unpickle_method, (func_name, obj, cls)
36 return _unpickle_method, (func_name, obj, cls)
37
37
38 def _unpickle_method(func_name, obj, cls):
38 def _unpickle_method(func_name, obj, cls):
39 for cls in cls.mro():
39 for cls in cls.mro():
40 try:
40 try:
41 func = cls.__dict__[func_name]
41 func = cls.__dict__[func_name]
42 except KeyError:
42 except KeyError:
43 pass
43 pass
44 else:
44 else:
45 break
45 break
46 return func.__get__(obj, cls)
46 return func.__get__(obj, cls)
47
47
48 def isNumber(str):
48 def isNumber(str):
49 try:
49 try:
50 float(str)
50 float(str)
51 return True
51 return True
52 except:
52 except:
53 return False
53 return False
54
54
55 class ParametersProc(ProcessingUnit):
55 class ParametersProc(ProcessingUnit):
56
56
57 METHODS = {}
57 METHODS = {}
58 nSeconds = None
58 nSeconds = None
59
59
60 def __init__(self):
60 def __init__(self):
61 ProcessingUnit.__init__(self)
61 ProcessingUnit.__init__(self)
62
62
63 # self.objectDict = {}
63 # self.objectDict = {}
64 self.buffer = None
64 self.buffer = None
65 self.firstdatatime = None
65 self.firstdatatime = None
66 self.profIndex = 0
66 self.profIndex = 0
67 self.dataOut = Parameters()
67 self.dataOut = Parameters()
68 self.setupReq = False #Agregar a todas las unidades de proc
68 self.setupReq = False #Agregar a todas las unidades de proc
69
69
70 def __updateObjFromInput(self):
70 def __updateObjFromInput(self):
71
71
72 self.dataOut.inputUnit = self.dataIn.type
72 self.dataOut.inputUnit = self.dataIn.type
73
73
74 self.dataOut.timeZone = self.dataIn.timeZone
74 self.dataOut.timeZone = self.dataIn.timeZone
75 self.dataOut.dstFlag = self.dataIn.dstFlag
75 self.dataOut.dstFlag = self.dataIn.dstFlag
76 self.dataOut.errorCount = self.dataIn.errorCount
76 self.dataOut.errorCount = self.dataIn.errorCount
77 self.dataOut.useLocalTime = self.dataIn.useLocalTime
77 self.dataOut.useLocalTime = self.dataIn.useLocalTime
78
78
79 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
79 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
80 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
80 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
81 self.dataOut.channelList = self.dataIn.channelList
81 self.dataOut.channelList = self.dataIn.channelList
82 self.dataOut.heightList = self.dataIn.heightList
82 self.dataOut.heightList = self.dataIn.heightList
83 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
83 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
84 # self.dataOut.nHeights = self.dataIn.nHeights
84 # self.dataOut.nHeights = self.dataIn.nHeights
85 # self.dataOut.nChannels = self.dataIn.nChannels
85 # self.dataOut.nChannels = self.dataIn.nChannels
86 # self.dataOut.nBaud = self.dataIn.nBaud
86 # self.dataOut.nBaud = self.dataIn.nBaud
87 # self.dataOut.nCode = self.dataIn.nCode
87 # self.dataOut.nCode = self.dataIn.nCode
88 # self.dataOut.code = self.dataIn.code
88 # self.dataOut.code = self.dataIn.code
89 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
89 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
90 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
90 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
91 # self.dataOut.utctime = self.firstdatatime
91 # self.dataOut.utctime = self.firstdatatime
92 self.dataOut.utctime = self.dataIn.utctime
92 self.dataOut.utctime = self.dataIn.utctime
93 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
93 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
94 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
94 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
95 self.dataOut.nCohInt = self.dataIn.nCohInt
95 self.dataOut.nCohInt = self.dataIn.nCohInt
96 # self.dataOut.nIncohInt = 1
96 # self.dataOut.nIncohInt = 1
97 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
97 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
98 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
98 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
99 self.dataOut.timeInterval1 = self.dataIn.timeInterval
99 self.dataOut.timeInterval1 = self.dataIn.timeInterval
100 self.dataOut.heightList = self.dataIn.heightList
100 self.dataOut.heightList = self.dataIn.heightList
101 self.dataOut.frequency = self.dataIn.frequency
101 self.dataOut.frequency = self.dataIn.frequency
102 # self.dataOut.noise = self.dataIn.noise
102 # self.dataOut.noise = self.dataIn.noise
103
103
104 def run(self):
104 def run(self):
105
105
106
106
107 #print("HOLA MUNDO SOY YO")
107 #print("HOLA MUNDO SOY YO")
108 #---------------------- Voltage Data ---------------------------
108 #---------------------- Voltage Data ---------------------------
109
109
110 if self.dataIn.type == "Voltage":
110 if self.dataIn.type == "Voltage":
111
111
112 self.__updateObjFromInput()
112 self.__updateObjFromInput()
113 self.dataOut.data_pre = self.dataIn.data.copy()
113 self.dataOut.data_pre = self.dataIn.data.copy()
114 self.dataOut.flagNoData = False
114 self.dataOut.flagNoData = False
115 self.dataOut.utctimeInit = self.dataIn.utctime
115 self.dataOut.utctimeInit = self.dataIn.utctime
116 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
116 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
117
117
118 if hasattr(self.dataIn, 'flagDataAsBlock'):
118 if hasattr(self.dataIn, 'flagDataAsBlock'):
119 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
119 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
120
120
121 if hasattr(self.dataIn, 'profileIndex'):
121 if hasattr(self.dataIn, 'profileIndex'):
122 self.dataOut.profileIndex = self.dataIn.profileIndex
122 self.dataOut.profileIndex = self.dataIn.profileIndex
123
123
124 if hasattr(self.dataIn, 'dataPP_POW'):
124 if hasattr(self.dataIn, 'dataPP_POW'):
125 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
125 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
126
126
127 if hasattr(self.dataIn, 'dataPP_POWER'):
127 if hasattr(self.dataIn, 'dataPP_POWER'):
128 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
128 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
129
129
130 if hasattr(self.dataIn, 'dataPP_DOP'):
130 if hasattr(self.dataIn, 'dataPP_DOP'):
131 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
131 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
132
132
133 if hasattr(self.dataIn, 'dataPP_SNR'):
133 if hasattr(self.dataIn, 'dataPP_SNR'):
134 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
134 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
135
135
136 if hasattr(self.dataIn, 'dataPP_WIDTH'):
136 if hasattr(self.dataIn, 'dataPP_WIDTH'):
137 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
137 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
138 return
138 return
139
139
140 #---------------------- Spectra Data ---------------------------
140 #---------------------- Spectra Data ---------------------------
141
141
142 if self.dataIn.type == "Spectra":
142 if self.dataIn.type == "Spectra":
143 #print("que paso en spectra")
143 #print("que paso en spectra")
144 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
144 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
145 self.dataOut.data_spc = self.dataIn.data_spc
145 self.dataOut.data_spc = self.dataIn.data_spc
146 self.dataOut.data_cspc = self.dataIn.data_cspc
146 self.dataOut.data_cspc = self.dataIn.data_cspc
147 self.dataOut.nProfiles = self.dataIn.nProfiles
147 self.dataOut.nProfiles = self.dataIn.nProfiles
148 self.dataOut.nIncohInt = self.dataIn.nIncohInt
148 self.dataOut.nIncohInt = self.dataIn.nIncohInt
149 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
149 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
150 self.dataOut.ippFactor = self.dataIn.ippFactor
150 self.dataOut.ippFactor = self.dataIn.ippFactor
151 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
151 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
152 self.dataOut.spc_noise = self.dataIn.getNoise()
152 self.dataOut.spc_noise = self.dataIn.getNoise()
153 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
153 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
154 # self.dataOut.normFactor = self.dataIn.normFactor
154 # self.dataOut.normFactor = self.dataIn.normFactor
155 self.dataOut.pairsList = self.dataIn.pairsList
155 self.dataOut.pairsList = self.dataIn.pairsList
156 self.dataOut.groupList = self.dataIn.pairsList
156 self.dataOut.groupList = self.dataIn.pairsList
157 self.dataOut.flagNoData = False
157 self.dataOut.flagNoData = False
158
158
159 if hasattr(self.dataIn, 'flagDataAsBlock'):
159 if hasattr(self.dataIn, 'flagDataAsBlock'):
160 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
160 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
161
161
162 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
162 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
163 self.dataOut.ChanDist = self.dataIn.ChanDist
163 self.dataOut.ChanDist = self.dataIn.ChanDist
164 else: self.dataOut.ChanDist = None
164 else: self.dataOut.ChanDist = None
165
165
166 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
166 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
167 # self.dataOut.VelRange = self.dataIn.VelRange
167 # self.dataOut.VelRange = self.dataIn.VelRange
168 #else: self.dataOut.VelRange = None
168 #else: self.dataOut.VelRange = None
169
169
170 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
170 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
171 self.dataOut.RadarConst = self.dataIn.RadarConst
171 self.dataOut.RadarConst = self.dataIn.RadarConst
172
172
173 if hasattr(self.dataIn, 'NPW'): #NPW
173 if hasattr(self.dataIn, 'NPW'): #NPW
174 self.dataOut.NPW = self.dataIn.NPW
174 self.dataOut.NPW = self.dataIn.NPW
175
175
176 if hasattr(self.dataIn, 'COFA'): #COFA
176 if hasattr(self.dataIn, 'COFA'): #COFA
177 self.dataOut.COFA = self.dataIn.COFA
177 self.dataOut.COFA = self.dataIn.COFA
178
178
179
179
180
180
181 #---------------------- Correlation Data ---------------------------
181 #---------------------- Correlation Data ---------------------------
182
182
183 if self.dataIn.type == "Correlation":
183 if self.dataIn.type == "Correlation":
184 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
184 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
185
185
186 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
186 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
187 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
187 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
188 self.dataOut.groupList = (acf_pairs, ccf_pairs)
188 self.dataOut.groupList = (acf_pairs, ccf_pairs)
189
189
190 self.dataOut.abscissaList = self.dataIn.lagRange
190 self.dataOut.abscissaList = self.dataIn.lagRange
191 self.dataOut.noise = self.dataIn.noise
191 self.dataOut.noise = self.dataIn.noise
192 self.dataOut.data_snr = self.dataIn.SNR
192 self.dataOut.data_snr = self.dataIn.SNR
193 self.dataOut.flagNoData = False
193 self.dataOut.flagNoData = False
194 self.dataOut.nAvg = self.dataIn.nAvg
194 self.dataOut.nAvg = self.dataIn.nAvg
195
195
196 #---------------------- Parameters Data ---------------------------
196 #---------------------- Parameters Data ---------------------------
197
197
198 if self.dataIn.type == "Parameters":
198 if self.dataIn.type == "Parameters":
199 self.dataOut.copy(self.dataIn)
199 self.dataOut.copy(self.dataIn)
200 self.dataOut.flagNoData = False
200 self.dataOut.flagNoData = False
201
201
202 return True
202 return True
203
203
204 self.__updateObjFromInput()
204 self.__updateObjFromInput()
205
205
206 self.dataOut.utctimeInit = self.dataIn.utctime
206 self.dataOut.utctimeInit = self.dataIn.utctime
207 self.dataOut.paramInterval = self.dataIn.timeInterval
207 self.dataOut.paramInterval = self.dataIn.timeInterval
208 #print("soy spectra ",self.dataOut.utctimeInit)
208 #print("soy spectra ",self.dataOut.utctimeInit)
209 return
209 return
210
210
211
211
212 def target(tups):
212 def target(tups):
213
213
214 obj, args = tups
214 obj, args = tups
215
215
216 return obj.FitGau(args)
216 return obj.FitGau(args)
217
217
218 class RemoveWideGC(Operation):
218 class RemoveWideGC(Operation):
219 ''' This class remove the wide clutter and replace it with a simple interpolation points
219 ''' This class remove the wide clutter and replace it with a simple interpolation points
220 This mainly applies to CLAIRE radar
220 This mainly applies to CLAIRE radar
221
221
222 ClutterWidth : Width to look for the clutter peak
222 ClutterWidth : Width to look for the clutter peak
223
223
224 Input:
224 Input:
225
225
226 self.dataOut.data_pre : SPC and CSPC
226 self.dataOut.data_pre : SPC and CSPC
227 self.dataOut.spc_range : To select wind and rainfall velocities
227 self.dataOut.spc_range : To select wind and rainfall velocities
228
228
229 Affected:
229 Affected:
230
230
231 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
231 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
232
232
233 Written by D. ScipiΓ³n 25.02.2021
233 Written by D. ScipiΓ³n 25.02.2021
234 '''
234 '''
235 def __init__(self):
235 def __init__(self):
236 Operation.__init__(self)
236 Operation.__init__(self)
237 self.i = 0
237 self.i = 0
238 self.ich = 0
238 self.ich = 0
239 self.ir = 0
239 self.ir = 0
240
240
241 def run(self, dataOut, ClutterWidth=2.5):
241 def run(self, dataOut, ClutterWidth=2.5):
242 # print ('Entering RemoveWideGC ... ')
242 # print ('Entering RemoveWideGC ... ')
243
243
244 self.spc = dataOut.data_pre[0].copy()
244 self.spc = dataOut.data_pre[0].copy()
245 self.spc_out = dataOut.data_pre[0].copy()
245 self.spc_out = dataOut.data_pre[0].copy()
246 self.Num_Chn = self.spc.shape[0]
246 self.Num_Chn = self.spc.shape[0]
247 self.Num_Hei = self.spc.shape[2]
247 self.Num_Hei = self.spc.shape[2]
248 VelRange = dataOut.spc_range[2][:-1]
248 VelRange = dataOut.spc_range[2][:-1]
249 dv = VelRange[1]-VelRange[0]
249 dv = VelRange[1]-VelRange[0]
250
250
251 # Find the velocities that corresponds to zero
251 # Find the velocities that corresponds to zero
252 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
252 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
253
253
254 # Removing novalid data from the spectra
254 # Removing novalid data from the spectra
255 for ich in range(self.Num_Chn) :
255 for ich in range(self.Num_Chn) :
256 for ir in range(self.Num_Hei) :
256 for ir in range(self.Num_Hei) :
257 # Estimate the noise at each range
257 # Estimate the noise at each range
258 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
258 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
259
259
260 # Removing the noise floor at each range
260 # Removing the noise floor at each range
261 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
261 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
262 self.spc[ich,novalid,ir] = HSn
262 self.spc[ich,novalid,ir] = HSn
263
263
264 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
264 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
265 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
265 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
266 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
266 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
267 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
267 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
268 continue
268 continue
269 junk3 = numpy.squeeze(numpy.diff(j1index))
269 junk3 = numpy.squeeze(numpy.diff(j1index))
270 junk4 = numpy.squeeze(numpy.diff(j2index))
270 junk4 = numpy.squeeze(numpy.diff(j2index))
271
271
272 valleyindex = j2index[numpy.where(junk4>1)]
272 valleyindex = j2index[numpy.where(junk4>1)]
273 peakindex = j1index[numpy.where(junk3>1)]
273 peakindex = j1index[numpy.where(junk3>1)]
274
274
275 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
275 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
276 if numpy.size(isvalid) == 0 :
276 if numpy.size(isvalid) == 0 :
277 continue
277 continue
278 if numpy.size(isvalid) >1 :
278 if numpy.size(isvalid) >1 :
279 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
279 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
280 isvalid = isvalid[vindex]
280 isvalid = isvalid[vindex]
281
281
282 # clutter peak
282 # clutter peak
283 gcpeak = peakindex[isvalid]
283 gcpeak = peakindex[isvalid]
284 vl = numpy.where(valleyindex < gcpeak)
284 vl = numpy.where(valleyindex < gcpeak)
285 if numpy.size(vl) == 0:
285 if numpy.size(vl) == 0:
286 continue
286 continue
287 gcvl = valleyindex[vl[0][-1]]
287 gcvl = valleyindex[vl[0][-1]]
288 vr = numpy.where(valleyindex > gcpeak)
288 vr = numpy.where(valleyindex > gcpeak)
289 if numpy.size(vr) == 0:
289 if numpy.size(vr) == 0:
290 continue
290 continue
291 gcvr = valleyindex[vr[0][0]]
291 gcvr = valleyindex[vr[0][0]]
292
292
293 # Removing the clutter
293 # Removing the clutter
294 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
294 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
295 gcindex = gc_values[gcvl+1:gcvr-1]
295 gcindex = gc_values[gcvl+1:gcvr-1]
296 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
296 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
297
297
298 dataOut.data_pre[0] = self.spc_out
298 dataOut.data_pre[0] = self.spc_out
299 #print ('Leaving RemoveWideGC ... ')
299 #print ('Leaving RemoveWideGC ... ')
300 return dataOut
300 return dataOut
301
301
302 class SpectralFilters(Operation):
302 class SpectralFilters(Operation):
303 ''' This class allows to replace the novalid values with noise for each channel
303 ''' This class allows to replace the novalid values with noise for each channel
304 This applies to CLAIRE RADAR
304 This applies to CLAIRE RADAR
305
305
306 PositiveLimit : RightLimit of novalid data
306 PositiveLimit : RightLimit of novalid data
307 NegativeLimit : LeftLimit of novalid data
307 NegativeLimit : LeftLimit of novalid data
308
308
309 Input:
309 Input:
310
310
311 self.dataOut.data_pre : SPC and CSPC
311 self.dataOut.data_pre : SPC and CSPC
312 self.dataOut.spc_range : To select wind and rainfall velocities
312 self.dataOut.spc_range : To select wind and rainfall velocities
313
313
314 Affected:
314 Affected:
315
315
316 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
316 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
317
317
318 Written by D. ScipiΓ³n 29.01.2021
318 Written by D. ScipiΓ³n 29.01.2021
319 '''
319 '''
320 def __init__(self):
320 def __init__(self):
321 Operation.__init__(self)
321 Operation.__init__(self)
322 self.i = 0
322 self.i = 0
323
323
324 def run(self, dataOut, ):
324 def run(self, dataOut, ):
325
325
326 self.spc = dataOut.data_pre[0].copy()
326 self.spc = dataOut.data_pre[0].copy()
327 self.Num_Chn = self.spc.shape[0]
327 self.Num_Chn = self.spc.shape[0]
328 VelRange = dataOut.spc_range[2]
328 VelRange = dataOut.spc_range[2]
329
329
330 # novalid corresponds to data within the Negative and PositiveLimit
330 # novalid corresponds to data within the Negative and PositiveLimit
331
331
332
332
333 # Removing novalid data from the spectra
333 # Removing novalid data from the spectra
334 for i in range(self.Num_Chn):
334 for i in range(self.Num_Chn):
335 self.spc[i,novalid,:] = dataOut.noise[i]
335 self.spc[i,novalid,:] = dataOut.noise[i]
336 dataOut.data_pre[0] = self.spc
336 dataOut.data_pre[0] = self.spc
337 return dataOut
337 return dataOut
338
338
339 class GaussianFit(Operation):
339 class GaussianFit(Operation):
340
340
341 '''
341 '''
342 Function that fit of one and two generalized gaussians (gg) based
342 Function that fit of one and two generalized gaussians (gg) based
343 on the PSD shape across an "power band" identified from a cumsum of
343 on the PSD shape across an "power band" identified from a cumsum of
344 the measured spectrum - noise.
344 the measured spectrum - noise.
345
345
346 Input:
346 Input:
347 self.dataOut.data_pre : SelfSpectra
347 self.dataOut.data_pre : SelfSpectra
348
348
349 Output:
349 Output:
350 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
350 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
351
351
352 '''
352 '''
353 def __init__(self):
353 def __init__(self):
354 Operation.__init__(self)
354 Operation.__init__(self)
355 self.i=0
355 self.i=0
356
356
357
357
358 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
358 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
359 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
359 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
360 """This routine will find a couple of generalized Gaussians to a power spectrum
360 """This routine will find a couple of generalized Gaussians to a power spectrum
361 methods: generalized, squared
361 methods: generalized, squared
362 input: spc
362 input: spc
363 output:
363 output:
364 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
364 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
365 """
365 """
366 print ('Entering ',method,' double Gaussian fit')
366 print ('Entering ',method,' double Gaussian fit')
367 self.spc = dataOut.data_pre[0].copy()
367 self.spc = dataOut.data_pre[0].copy()
368 self.Num_Hei = self.spc.shape[2]
368 self.Num_Hei = self.spc.shape[2]
369 self.Num_Bin = self.spc.shape[1]
369 self.Num_Bin = self.spc.shape[1]
370 self.Num_Chn = self.spc.shape[0]
370 self.Num_Chn = self.spc.shape[0]
371
371
372 start_time = time.time()
372 start_time = time.time()
373
373
374 pool = Pool(processes=self.Num_Chn)
374 pool = Pool(processes=self.Num_Chn)
375 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
375 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
376 objs = [self for __ in range(self.Num_Chn)]
376 objs = [self for __ in range(self.Num_Chn)]
377 attrs = list(zip(objs, args))
377 attrs = list(zip(objs, args))
378 DGauFitParam = pool.map(target, attrs)
378 DGauFitParam = pool.map(target, attrs)
379 # Parameters:
379 # Parameters:
380 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
380 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
381 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
381 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
382
382
383 # Double Gaussian Curves
383 # Double Gaussian Curves
384 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
384 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
385 gau0[:] = numpy.NaN
385 gau0[:] = numpy.NaN
386 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
386 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
387 gau1[:] = numpy.NaN
387 gau1[:] = numpy.NaN
388 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
388 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
389 for iCh in range(self.Num_Chn):
389 for iCh in range(self.Num_Chn):
390 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
390 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
391 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
391 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
392 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
392 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
393 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
393 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
394 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
394 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
395 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
395 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
396 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
396 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
397 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
397 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
398 if method == 'genealized':
398 if method == 'genealized':
399 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
399 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
400 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
400 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
401 elif method == 'squared':
401 elif method == 'squared':
402 p0 = 2.
402 p0 = 2.
403 p1 = 2.
403 p1 = 2.
404 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
404 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
405 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
405 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
406 dataOut.GaussFit0 = gau0
406 dataOut.GaussFit0 = gau0
407 dataOut.GaussFit1 = gau1
407 dataOut.GaussFit1 = gau1
408
408
409 print('Leaving ',method ,' double Gaussian fit')
409 print('Leaving ',method ,' double Gaussian fit')
410 return dataOut
410 return dataOut
411
411
412 def FitGau(self, X):
412 def FitGau(self, X):
413 # print('Entering FitGau')
413 # print('Entering FitGau')
414 # Assigning the variables
414 # Assigning the variables
415 Vrange, ch, wnoise, num_intg, SNRlimit = X
415 Vrange, ch, wnoise, num_intg, SNRlimit = X
416 # Noise Limits
416 # Noise Limits
417 noisebl = wnoise * 0.9
417 noisebl = wnoise * 0.9
418 noisebh = wnoise * 1.1
418 noisebh = wnoise * 1.1
419 # Radar Velocity
419 # Radar Velocity
420 Va = max(Vrange)
420 Va = max(Vrange)
421 deltav = Vrange[1] - Vrange[0]
421 deltav = Vrange[1] - Vrange[0]
422 x = numpy.arange(self.Num_Bin)
422 x = numpy.arange(self.Num_Bin)
423
423
424 # print ('stop 0')
424 # print ('stop 0')
425
425
426 # 5 parameters, 2 Gaussians
426 # 5 parameters, 2 Gaussians
427 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
427 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
428 DGauFitParam[:] = numpy.NaN
428 DGauFitParam[:] = numpy.NaN
429
429
430 # SPCparam = []
430 # SPCparam = []
431 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
431 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
432 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
432 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
433 # SPC_ch1[:] = 0 #numpy.NaN
433 # SPC_ch1[:] = 0 #numpy.NaN
434 # SPC_ch2[:] = 0 #numpy.NaN
434 # SPC_ch2[:] = 0 #numpy.NaN
435 # print ('stop 1')
435 # print ('stop 1')
436 for ht in range(self.Num_Hei):
436 for ht in range(self.Num_Hei):
437 # print (ht)
437 # print (ht)
438 # print ('stop 2')
438 # print ('stop 2')
439 # Spectra at each range
439 # Spectra at each range
440 spc = numpy.asarray(self.spc)[ch,:,ht]
440 spc = numpy.asarray(self.spc)[ch,:,ht]
441 snr = ( spc.mean() - wnoise ) / wnoise
441 snr = ( spc.mean() - wnoise ) / wnoise
442 snrdB = 10.*numpy.log10(snr)
442 snrdB = 10.*numpy.log10(snr)
443
443
444 #print ('stop 3')
444 #print ('stop 3')
445 if snrdB < SNRlimit :
445 if snrdB < SNRlimit :
446 # snr = numpy.NaN
446 # snr = numpy.NaN
447 # SPC_ch1[:,ht] = 0#numpy.NaN
447 # SPC_ch1[:,ht] = 0#numpy.NaN
448 # SPC_ch1[:,ht] = 0#numpy.NaN
448 # SPC_ch1[:,ht] = 0#numpy.NaN
449 # SPCparam = (SPC_ch1,SPC_ch2)
449 # SPCparam = (SPC_ch1,SPC_ch2)
450 # print ('SNR less than SNRth')
450 # print ('SNR less than SNRth')
451 continue
451 continue
452 # wnoise = hildebrand_sekhon(spc,num_intg)
452 # wnoise = hildebrand_sekhon(spc,num_intg)
453 # print ('stop 2.01')
453 # print ('stop 2.01')
454 #############################################
454 #############################################
455 # normalizing spc and noise
455 # normalizing spc and noise
456 # This part differs from gg1
456 # This part differs from gg1
457 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
457 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
458 #spc = spc / spc_norm_max
458 #spc = spc / spc_norm_max
459 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
459 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
460 #############################################
460 #############################################
461
461
462 # print ('stop 2.1')
462 # print ('stop 2.1')
463 fatspectra=1.0
463 fatspectra=1.0
464 # noise per channel.... we might want to use the noise at each range
464 # noise per channel.... we might want to use the noise at each range
465
465
466 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
466 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
467 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
467 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
468 #if wnoise>1.1*pnoise: # to be tested later
468 #if wnoise>1.1*pnoise: # to be tested later
469 # wnoise=pnoise
469 # wnoise=pnoise
470 # noisebl = wnoise*0.9
470 # noisebl = wnoise*0.9
471 # noisebh = wnoise*1.1
471 # noisebh = wnoise*1.1
472 spc = spc - wnoise # signal
472 spc = spc - wnoise # signal
473
473
474 # print ('stop 2.2')
474 # print ('stop 2.2')
475 minx = numpy.argmin(spc)
475 minx = numpy.argmin(spc)
476 #spcs=spc.copy()
476 #spcs=spc.copy()
477 spcs = numpy.roll(spc,-minx)
477 spcs = numpy.roll(spc,-minx)
478 cum = numpy.cumsum(spcs)
478 cum = numpy.cumsum(spcs)
479 # tot_noise = wnoise * self.Num_Bin #64;
479 # tot_noise = wnoise * self.Num_Bin #64;
480
480
481 # print ('stop 2.3')
481 # print ('stop 2.3')
482 # snr = sum(spcs) / tot_noise
482 # snr = sum(spcs) / tot_noise
483 # snrdB = 10.*numpy.log10(snr)
483 # snrdB = 10.*numpy.log10(snr)
484 #print ('stop 3')
484 #print ('stop 3')
485 # if snrdB < SNRlimit :
485 # if snrdB < SNRlimit :
486 # snr = numpy.NaN
486 # snr = numpy.NaN
487 # SPC_ch1[:,ht] = 0#numpy.NaN
487 # SPC_ch1[:,ht] = 0#numpy.NaN
488 # SPC_ch1[:,ht] = 0#numpy.NaN
488 # SPC_ch1[:,ht] = 0#numpy.NaN
489 # SPCparam = (SPC_ch1,SPC_ch2)
489 # SPCparam = (SPC_ch1,SPC_ch2)
490 # print ('SNR less than SNRth')
490 # print ('SNR less than SNRth')
491 # continue
491 # continue
492
492
493
493
494 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
494 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
495 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
495 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
496 # print ('stop 4')
496 # print ('stop 4')
497 cummax = max(cum)
497 cummax = max(cum)
498 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
498 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
499 cumlo = cummax * epsi
499 cumlo = cummax * epsi
500 cumhi = cummax * (1-epsi)
500 cumhi = cummax * (1-epsi)
501 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
501 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
502
502
503 # print ('stop 5')
503 # print ('stop 5')
504 if len(powerindex) < 1:# case for powerindex 0
504 if len(powerindex) < 1:# case for powerindex 0
505 # print ('powerindex < 1')
505 # print ('powerindex < 1')
506 continue
506 continue
507 powerlo = powerindex[0]
507 powerlo = powerindex[0]
508 powerhi = powerindex[-1]
508 powerhi = powerindex[-1]
509 powerwidth = powerhi-powerlo
509 powerwidth = powerhi-powerlo
510 if powerwidth <= 1:
510 if powerwidth <= 1:
511 # print('powerwidth <= 1')
511 # print('powerwidth <= 1')
512 continue
512 continue
513
513
514 # print ('stop 6')
514 # print ('stop 6')
515 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
515 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
516 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
516 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
517 midpeak = (firstpeak + secondpeak)/2.
517 midpeak = (firstpeak + secondpeak)/2.
518 firstamp = spcs[int(firstpeak)]
518 firstamp = spcs[int(firstpeak)]
519 secondamp = spcs[int(secondpeak)]
519 secondamp = spcs[int(secondpeak)]
520 midamp = spcs[int(midpeak)]
520 midamp = spcs[int(midpeak)]
521
521
522 y_data = spc + wnoise
522 y_data = spc + wnoise
523
523
524 ''' single Gaussian '''
524 ''' single Gaussian '''
525 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
525 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
526 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
526 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
527 power0 = 2.
527 power0 = 2.
528 amplitude0 = midamp
528 amplitude0 = midamp
529 state0 = [shift0,width0,amplitude0,power0,wnoise]
529 state0 = [shift0,width0,amplitude0,power0,wnoise]
530 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
530 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
531 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
531 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
532 # print ('stop 7.1')
532 # print ('stop 7.1')
533 # print (bnds)
533 # print (bnds)
534
534
535 chiSq1=lsq1[1]
535 chiSq1=lsq1[1]
536
536
537 # print ('stop 8')
537 # print ('stop 8')
538 if fatspectra<1.0 and powerwidth<4:
538 if fatspectra<1.0 and powerwidth<4:
539 choice=0
539 choice=0
540 Amplitude0=lsq1[0][2]
540 Amplitude0=lsq1[0][2]
541 shift0=lsq1[0][0]
541 shift0=lsq1[0][0]
542 width0=lsq1[0][1]
542 width0=lsq1[0][1]
543 p0=lsq1[0][3]
543 p0=lsq1[0][3]
544 Amplitude1=0.
544 Amplitude1=0.
545 shift1=0.
545 shift1=0.
546 width1=0.
546 width1=0.
547 p1=0.
547 p1=0.
548 noise=lsq1[0][4]
548 noise=lsq1[0][4]
549 #return (numpy.array([shift0,width0,Amplitude0,p0]),
549 #return (numpy.array([shift0,width0,Amplitude0,p0]),
550 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
550 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
551
551
552 # print ('stop 9')
552 # print ('stop 9')
553 ''' two Gaussians '''
553 ''' two Gaussians '''
554 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
554 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
555 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
555 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
556 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
556 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
557 width0 = powerwidth/6.
557 width0 = powerwidth/6.
558 width1 = width0
558 width1 = width0
559 power0 = 2.
559 power0 = 2.
560 power1 = power0
560 power1 = power0
561 amplitude0 = firstamp
561 amplitude0 = firstamp
562 amplitude1 = secondamp
562 amplitude1 = secondamp
563 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
563 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
564 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
564 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
565 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))
565 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))
566 #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))
566 #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))
567
567
568 # print ('stop 10')
568 # print ('stop 10')
569 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
569 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
570
570
571 # print ('stop 11')
571 # print ('stop 11')
572 chiSq2 = lsq2[1]
572 chiSq2 = lsq2[1]
573
573
574 # print ('stop 12')
574 # print ('stop 12')
575
575
576 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)
576 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)
577
577
578 # print ('stop 13')
578 # print ('stop 13')
579 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
579 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
580 if oneG:
580 if oneG:
581 choice = 0
581 choice = 0
582 else:
582 else:
583 w1 = lsq2[0][1]; w2 = lsq2[0][5]
583 w1 = lsq2[0][1]; w2 = lsq2[0][5]
584 a1 = lsq2[0][2]; a2 = lsq2[0][6]
584 a1 = lsq2[0][2]; a2 = lsq2[0][6]
585 p1 = lsq2[0][3]; p2 = lsq2[0][7]
585 p1 = lsq2[0][3]; p2 = lsq2[0][7]
586 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
586 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
587 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
587 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
588 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
588 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
589
589
590 if gp1>gp2:
590 if gp1>gp2:
591 if a1>0.7*a2:
591 if a1>0.7*a2:
592 choice = 1
592 choice = 1
593 else:
593 else:
594 choice = 2
594 choice = 2
595 elif gp2>gp1:
595 elif gp2>gp1:
596 if a2>0.7*a1:
596 if a2>0.7*a1:
597 choice = 2
597 choice = 2
598 else:
598 else:
599 choice = 1
599 choice = 1
600 else:
600 else:
601 choice = numpy.argmax([a1,a2])+1
601 choice = numpy.argmax([a1,a2])+1
602 #else:
602 #else:
603 #choice=argmin([std2a,std2b])+1
603 #choice=argmin([std2a,std2b])+1
604
604
605 else: # with low SNR go to the most energetic peak
605 else: # with low SNR go to the most energetic peak
606 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
606 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
607
607
608 # print ('stop 14')
608 # print ('stop 14')
609 shift0 = lsq2[0][0]
609 shift0 = lsq2[0][0]
610 vel0 = Vrange[0] + shift0 * deltav
610 vel0 = Vrange[0] + shift0 * deltav
611 shift1 = lsq2[0][4]
611 shift1 = lsq2[0][4]
612 # vel1=Vrange[0] + shift1 * deltav
612 # vel1=Vrange[0] + shift1 * deltav
613
613
614 # max_vel = 1.0
614 # max_vel = 1.0
615 # Va = max(Vrange)
615 # Va = max(Vrange)
616 # deltav = Vrange[1]-Vrange[0]
616 # deltav = Vrange[1]-Vrange[0]
617 # print ('stop 15')
617 # print ('stop 15')
618 #first peak will be 0, second peak will be 1
618 #first peak will be 0, second peak will be 1
619 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
619 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
620 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
620 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
621 shift0 = lsq2[0][0]
621 shift0 = lsq2[0][0]
622 width0 = lsq2[0][1]
622 width0 = lsq2[0][1]
623 Amplitude0 = lsq2[0][2]
623 Amplitude0 = lsq2[0][2]
624 p0 = lsq2[0][3]
624 p0 = lsq2[0][3]
625
625
626 shift1 = lsq2[0][4]
626 shift1 = lsq2[0][4]
627 width1 = lsq2[0][5]
627 width1 = lsq2[0][5]
628 Amplitude1 = lsq2[0][6]
628 Amplitude1 = lsq2[0][6]
629 p1 = lsq2[0][7]
629 p1 = lsq2[0][7]
630 noise = lsq2[0][8]
630 noise = lsq2[0][8]
631 else:
631 else:
632 shift1 = lsq2[0][0]
632 shift1 = lsq2[0][0]
633 width1 = lsq2[0][1]
633 width1 = lsq2[0][1]
634 Amplitude1 = lsq2[0][2]
634 Amplitude1 = lsq2[0][2]
635 p1 = lsq2[0][3]
635 p1 = lsq2[0][3]
636
636
637 shift0 = lsq2[0][4]
637 shift0 = lsq2[0][4]
638 width0 = lsq2[0][5]
638 width0 = lsq2[0][5]
639 Amplitude0 = lsq2[0][6]
639 Amplitude0 = lsq2[0][6]
640 p0 = lsq2[0][7]
640 p0 = lsq2[0][7]
641 noise = lsq2[0][8]
641 noise = lsq2[0][8]
642
642
643 if Amplitude0<0.05: # in case the peak is noise
643 if Amplitude0<0.05: # in case the peak is noise
644 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
644 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
645 if Amplitude1<0.05:
645 if Amplitude1<0.05:
646 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
646 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
647
647
648 # print ('stop 16 ')
648 # print ('stop 16 ')
649 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
649 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
650 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
650 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
651 # SPCparam = (SPC_ch1,SPC_ch2)
651 # SPCparam = (SPC_ch1,SPC_ch2)
652
652
653 DGauFitParam[0,ht,0] = noise
653 DGauFitParam[0,ht,0] = noise
654 DGauFitParam[0,ht,1] = noise
654 DGauFitParam[0,ht,1] = noise
655 DGauFitParam[1,ht,0] = Amplitude0
655 DGauFitParam[1,ht,0] = Amplitude0
656 DGauFitParam[1,ht,1] = Amplitude1
656 DGauFitParam[1,ht,1] = Amplitude1
657 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
657 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
658 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
658 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
659 DGauFitParam[3,ht,0] = width0 * deltav
659 DGauFitParam[3,ht,0] = width0 * deltav
660 DGauFitParam[3,ht,1] = width1 * deltav
660 DGauFitParam[3,ht,1] = width1 * deltav
661 DGauFitParam[4,ht,0] = p0
661 DGauFitParam[4,ht,0] = p0
662 DGauFitParam[4,ht,1] = p1
662 DGauFitParam[4,ht,1] = p1
663
663
664 # print (DGauFitParam.shape)
664 # print (DGauFitParam.shape)
665 # print ('Leaving FitGau')
665 # print ('Leaving FitGau')
666 return DGauFitParam
666 return DGauFitParam
667 # return SPCparam
667 # return SPCparam
668 # return GauSPC
668 # return GauSPC
669
669
670 def y_model1(self,x,state):
670 def y_model1(self,x,state):
671 shift0, width0, amplitude0, power0, noise = state
671 shift0, width0, amplitude0, power0, noise = state
672 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
672 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
673 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
673 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
674 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
674 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
675 return model0 + model0u + model0d + noise
675 return model0 + model0u + model0d + noise
676
676
677 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
677 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
678 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
678 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
679 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
679 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
680 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
680 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
681 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
681 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
682
682
683 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
683 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
684 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
684 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
685 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
685 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
686 return model0 + model0u + model0d + model1 + model1u + model1d + noise
686 return model0 + model0u + model0d + model1 + model1u + model1d + noise
687
687
688 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.
688 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.
689
689
690 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
690 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
691
691
692 def misfit2(self,state,y_data,x,num_intg):
692 def misfit2(self,state,y_data,x,num_intg):
693 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
693 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
694
694
695
695
696
696
697 class PrecipitationProc(Operation):
697 class PrecipitationProc(Operation):
698
698
699 '''
699 '''
700 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
700 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
701
701
702 Input:
702 Input:
703 self.dataOut.data_pre : SelfSpectra
703 self.dataOut.data_pre : SelfSpectra
704
704
705 Output:
705 Output:
706
706
707 self.dataOut.data_output : Reflectivity factor, rainfall Rate
707 self.dataOut.data_output : Reflectivity factor, rainfall Rate
708
708
709
709
710 Parameters affected:
710 Parameters affected:
711 '''
711 '''
712
712
713 def __init__(self):
713 def __init__(self):
714 Operation.__init__(self)
714 Operation.__init__(self)
715 self.i=0
715 self.i=0
716
716
717 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
717 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
718 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
718 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
719
719
720 # print ('Entering PrecepitationProc ... ')
720 # print ('Entering PrecepitationProc ... ')
721
721
722 if radar == "MIRA35C" :
722 if radar == "MIRA35C" :
723
723
724 self.spc = dataOut.data_pre[0].copy()
724 self.spc = dataOut.data_pre[0].copy()
725 self.Num_Hei = self.spc.shape[2]
725 self.Num_Hei = self.spc.shape[2]
726 self.Num_Bin = self.spc.shape[1]
726 self.Num_Bin = self.spc.shape[1]
727 self.Num_Chn = self.spc.shape[0]
727 self.Num_Chn = self.spc.shape[0]
728 Ze = self.dBZeMODE2(dataOut)
728 Ze = self.dBZeMODE2(dataOut)
729
729
730 else:
730 else:
731
731
732 self.spc = dataOut.data_pre[0].copy()
732 self.spc = dataOut.data_pre[0].copy()
733
733
734 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
734 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
735 self.spc[:,:,0:7]= numpy.NaN
735 self.spc[:,:,0:7]= numpy.NaN
736
736
737 self.Num_Hei = self.spc.shape[2]
737 self.Num_Hei = self.spc.shape[2]
738 self.Num_Bin = self.spc.shape[1]
738 self.Num_Bin = self.spc.shape[1]
739 self.Num_Chn = self.spc.shape[0]
739 self.Num_Chn = self.spc.shape[0]
740
740
741 VelRange = dataOut.spc_range[2]
741 VelRange = dataOut.spc_range[2]
742
742
743 ''' Se obtiene la constante del RADAR '''
743 ''' Se obtiene la constante del RADAR '''
744
744
745 self.Pt = Pt
745 self.Pt = Pt
746 self.Gt = Gt
746 self.Gt = Gt
747 self.Gr = Gr
747 self.Gr = Gr
748 self.Lambda = Lambda
748 self.Lambda = Lambda
749 self.aL = aL
749 self.aL = aL
750 self.tauW = tauW
750 self.tauW = tauW
751 self.ThetaT = ThetaT
751 self.ThetaT = ThetaT
752 self.ThetaR = ThetaR
752 self.ThetaR = ThetaR
753 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
753 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
754 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
754 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
755 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
755 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
756
756
757 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
757 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
758 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
758 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
759 RadarConstant = 10e-26 * Numerator / Denominator #
759 RadarConstant = 10e-26 * Numerator / Denominator #
760 ExpConstant = 10**(40/10) #Constante Experimental
760 ExpConstant = 10**(40/10) #Constante Experimental
761
761
762 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
762 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
763 for i in range(self.Num_Chn):
763 for i in range(self.Num_Chn):
764 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
764 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
765 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
765 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
766
766
767 SPCmean = numpy.mean(SignalPower, 0)
767 SPCmean = numpy.mean(SignalPower, 0)
768 Pr = SPCmean[:,:]/dataOut.normFactor
768 Pr = SPCmean[:,:]/dataOut.normFactor
769
769
770 # Declaring auxiliary variables
770 # Declaring auxiliary variables
771 Range = dataOut.heightList*1000. #Range in m
771 Range = dataOut.heightList*1000. #Range in m
772 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
772 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
773 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
773 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
774 zMtrx = rMtrx+Altitude
774 zMtrx = rMtrx+Altitude
775 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
775 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
776 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
776 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
777
777
778 # height dependence to air density Foote and Du Toit (1969)
778 # height dependence to air density Foote and Du Toit (1969)
779 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
779 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
780 VMtrx = VelMtrx / delv_z #Normalized velocity
780 VMtrx = VelMtrx / delv_z #Normalized velocity
781 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
781 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
782 # Diameter is related to the fall speed of falling drops
782 # Diameter is related to the fall speed of falling drops
783 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
783 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
784 # Only valid for D>= 0.16 mm
784 # Only valid for D>= 0.16 mm
785 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
785 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
786
786
787 #Calculate Radar Reflectivity ETAn
787 #Calculate Radar Reflectivity ETAn
788 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
788 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
789 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
789 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
790 # Radar Cross Section
790 # Radar Cross Section
791 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
791 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
792 # Drop Size Distribution
792 # Drop Size Distribution
793 DSD = ETAn / sigmaD
793 DSD = ETAn / sigmaD
794 # Equivalente Reflectivy
794 # Equivalente Reflectivy
795 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
795 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
796 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
796 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
797 # RainFall Rate
797 # RainFall Rate
798 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
798 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
799
799
800 # Censoring the data
800 # Censoring the data
801 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
801 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
802 SNRth = 10**(SNRdBlimit/10) #-30dB
802 SNRth = 10**(SNRdBlimit/10) #-30dB
803 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
803 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
804 W = numpy.nanmean(dataOut.data_dop,0)
804 W = numpy.nanmean(dataOut.data_dop,0)
805 W[novalid] = numpy.NaN
805 W[novalid] = numpy.NaN
806 Ze_org[novalid] = numpy.NaN
806 Ze_org[novalid] = numpy.NaN
807 RR[novalid] = numpy.NaN
807 RR[novalid] = numpy.NaN
808
808
809 dataOut.data_output = RR[8]
809 dataOut.data_output = RR[8]
810 dataOut.data_param = numpy.ones([3,self.Num_Hei])
810 dataOut.data_param = numpy.ones([3,self.Num_Hei])
811 dataOut.channelList = [0,1,2]
811 dataOut.channelList = [0,1,2]
812
812
813 dataOut.data_param[0]=10*numpy.log10(Ze_org)
813 dataOut.data_param[0]=10*numpy.log10(Ze_org)
814 dataOut.data_param[1]=-W
814 dataOut.data_param[1]=-W
815 dataOut.data_param[2]=RR
815 dataOut.data_param[2]=RR
816
816
817 # print ('Leaving PrecepitationProc ... ')
817 # print ('Leaving PrecepitationProc ... ')
818 return dataOut
818 return dataOut
819
819
820 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
820 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
821
821
822 NPW = dataOut.NPW
822 NPW = dataOut.NPW
823 COFA = dataOut.COFA
823 COFA = dataOut.COFA
824
824
825 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
825 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
826 RadarConst = dataOut.RadarConst
826 RadarConst = dataOut.RadarConst
827 #frequency = 34.85*10**9
827 #frequency = 34.85*10**9
828
828
829 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
829 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
830 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
830 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
831
831
832 ETA = numpy.sum(SNR,1)
832 ETA = numpy.sum(SNR,1)
833
833
834 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
834 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
835
835
836 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
836 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
837
837
838 for r in range(self.Num_Hei):
838 for r in range(self.Num_Hei):
839
839
840 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
840 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
841 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
841 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
842
842
843 return Ze
843 return Ze
844
844
845 # def GetRadarConstant(self):
845 # def GetRadarConstant(self):
846 #
846 #
847 # """
847 # """
848 # Constants:
848 # Constants:
849 #
849 #
850 # Pt: Transmission Power dB 5kW 5000
850 # Pt: Transmission Power dB 5kW 5000
851 # Gt: Transmission Gain dB 24.7 dB 295.1209
851 # Gt: Transmission Gain dB 24.7 dB 295.1209
852 # Gr: Reception Gain dB 18.5 dB 70.7945
852 # Gr: Reception Gain dB 18.5 dB 70.7945
853 # Lambda: Wavelenght m 0.6741 m 0.6741
853 # Lambda: Wavelenght m 0.6741 m 0.6741
854 # aL: Attenuation loses dB 4dB 2.5118
854 # aL: Attenuation loses dB 4dB 2.5118
855 # tauW: Width of transmission pulse s 4us 4e-6
855 # tauW: Width of transmission pulse s 4us 4e-6
856 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
856 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
857 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
857 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
858 #
858 #
859 # """
859 # """
860 #
860 #
861 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
861 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
862 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
862 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
863 # RadarConstant = Numerator / Denominator
863 # RadarConstant = Numerator / Denominator
864 #
864 #
865 # return RadarConstant
865 # return RadarConstant
866
866
867
867
868
868
869 class FullSpectralAnalysis(Operation):
869 class FullSpectralAnalysis(Operation):
870
870
871 """
871 """
872 Function that implements Full Spectral Analysis technique.
872 Function that implements Full Spectral Analysis technique.
873
873
874 Input:
874 Input:
875 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
875 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
876 self.dataOut.groupList : Pairlist of channels
876 self.dataOut.groupList : Pairlist of channels
877 self.dataOut.ChanDist : Physical distance between receivers
877 self.dataOut.ChanDist : Physical distance between receivers
878
878
879
879
880 Output:
880 Output:
881
881
882 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
882 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
883
883
884
884
885 Parameters affected: Winds, height range, SNR
885 Parameters affected: Winds, height range, SNR
886
886
887 """
887 """
888 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
888 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
889 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
889 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
890
890
891 spc = dataOut.data_pre[0].copy()
891 spc = dataOut.data_pre[0].copy()
892 cspc = dataOut.data_pre[1]
892 cspc = dataOut.data_pre[1]
893 nHeights = spc.shape[2]
893 nHeights = spc.shape[2]
894
894
895 # first_height = 0.75 #km (ref: data header 20170822)
895 # first_height = 0.75 #km (ref: data header 20170822)
896 # resolution_height = 0.075 #km
896 # resolution_height = 0.075 #km
897 '''
897 '''
898 finding height range. check this when radar parameters are changed!
898 finding height range. check this when radar parameters are changed!
899 '''
899 '''
900 if maxheight is not None:
900 if maxheight is not None:
901 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
901 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
902 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
902 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
903 else:
903 else:
904 range_max = nHeights
904 range_max = nHeights
905 if minheight is not None:
905 if minheight is not None:
906 # range_min = int((minheight - first_height) / resolution_height) # theoretical
906 # range_min = int((minheight - first_height) / resolution_height) # theoretical
907 range_min = int(13.26 * minheight - 5) # empirical, works better
907 range_min = int(13.26 * minheight - 5) # empirical, works better
908 if range_min < 0:
908 if range_min < 0:
909 range_min = 0
909 range_min = 0
910 else:
910 else:
911 range_min = 0
911 range_min = 0
912
912
913 pairsList = dataOut.groupList
913 pairsList = dataOut.groupList
914 if dataOut.ChanDist is not None :
914 if dataOut.ChanDist is not None :
915 ChanDist = dataOut.ChanDist
915 ChanDist = dataOut.ChanDist
916 else:
916 else:
917 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
917 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
918
918
919 # 4 variables: zonal, meridional, vertical, and average SNR
919 # 4 variables: zonal, meridional, vertical, and average SNR
920 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
920 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
921 velocityX = numpy.zeros([nHeights]) * numpy.NaN
921 velocityX = numpy.zeros([nHeights]) * numpy.NaN
922 velocityY = numpy.zeros([nHeights]) * numpy.NaN
922 velocityY = numpy.zeros([nHeights]) * numpy.NaN
923 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
923 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
924
924
925 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
925 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
926
926
927 '''***********************************************WIND ESTIMATION**************************************'''
927 '''***********************************************WIND ESTIMATION**************************************'''
928 for Height in range(nHeights):
928 for Height in range(nHeights):
929
929
930 if Height >= range_min and Height < range_max:
930 if Height >= range_min and Height < range_max:
931 # error_code will be useful in future analysis
931 # error_code will be useful in future analysis
932 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
932 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
933 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
933 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
934
934
935 if abs(Vzon) < 100. and abs(Vmer) < 100.:
935 if abs(Vzon) < 100. and abs(Vmer) < 100.:
936 velocityX[Height] = Vzon
936 velocityX[Height] = Vzon
937 velocityY[Height] = -Vmer
937 velocityY[Height] = -Vmer
938 velocityZ[Height] = Vver
938 velocityZ[Height] = Vver
939
939
940 # Censoring data with SNR threshold
940 # Censoring data with SNR threshold
941 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
941 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
942
942
943 data_param[0] = velocityX
943 data_param[0] = velocityX
944 data_param[1] = velocityY
944 data_param[1] = velocityY
945 data_param[2] = velocityZ
945 data_param[2] = velocityZ
946 data_param[3] = dbSNR
946 data_param[3] = dbSNR
947 dataOut.data_param = data_param
947 dataOut.data_param = data_param
948 return dataOut
948 return dataOut
949
949
950 def moving_average(self,x, N=2):
950 def moving_average(self,x, N=2):
951 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
951 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
952 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
952 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
953
953
954 def gaus(self,xSamples,Amp,Mu,Sigma):
954 def gaus(self,xSamples,Amp,Mu,Sigma):
955 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
955 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
956
956
957 def Moments(self, ySamples, xSamples):
957 def Moments(self, ySamples, xSamples):
958 Power = numpy.nanmean(ySamples) # Power, 0th Moment
958 Power = numpy.nanmean(ySamples) # Power, 0th Moment
959 yNorm = ySamples / numpy.nansum(ySamples)
959 yNorm = ySamples / numpy.nansum(ySamples)
960 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
960 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
961 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
961 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
962 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
962 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
963 return numpy.array([Power,RadVel,StdDev])
963 return numpy.array([Power,RadVel,StdDev])
964
964
965 def StopWindEstimation(self, error_code):
965 def StopWindEstimation(self, error_code):
966 Vzon = numpy.NaN
966 Vzon = numpy.NaN
967 Vmer = numpy.NaN
967 Vmer = numpy.NaN
968 Vver = numpy.NaN
968 Vver = numpy.NaN
969 return Vzon, Vmer, Vver, error_code
969 return Vzon, Vmer, Vver, error_code
970
970
971 def AntiAliasing(self, interval, maxstep):
971 def AntiAliasing(self, interval, maxstep):
972 """
972 """
973 function to prevent errors from aliased values when computing phaseslope
973 function to prevent errors from aliased values when computing phaseslope
974 """
974 """
975 antialiased = numpy.zeros(len(interval))
975 antialiased = numpy.zeros(len(interval))
976 copyinterval = interval.copy()
976 copyinterval = interval.copy()
977
977
978 antialiased[0] = copyinterval[0]
978 antialiased[0] = copyinterval[0]
979
979
980 for i in range(1,len(antialiased)):
980 for i in range(1,len(antialiased)):
981 step = interval[i] - interval[i-1]
981 step = interval[i] - interval[i-1]
982 if step > maxstep:
982 if step > maxstep:
983 copyinterval -= 2*numpy.pi
983 copyinterval -= 2*numpy.pi
984 antialiased[i] = copyinterval[i]
984 antialiased[i] = copyinterval[i]
985 elif step < maxstep*(-1):
985 elif step < maxstep*(-1):
986 copyinterval += 2*numpy.pi
986 copyinterval += 2*numpy.pi
987 antialiased[i] = copyinterval[i]
987 antialiased[i] = copyinterval[i]
988 else:
988 else:
989 antialiased[i] = copyinterval[i].copy()
989 antialiased[i] = copyinterval[i].copy()
990
990
991 return antialiased
991 return antialiased
992
992
993 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
993 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
994 """
994 """
995 Function that Calculates Zonal, Meridional and Vertical wind velocities.
995 Function that Calculates Zonal, Meridional and Vertical wind velocities.
996 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
996 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
997
997
998 Input:
998 Input:
999 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
999 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1000 pairsList : Pairlist of channels
1000 pairsList : Pairlist of channels
1001 ChanDist : array of xi_ij and eta_ij
1001 ChanDist : array of xi_ij and eta_ij
1002 Height : height at which data is processed
1002 Height : height at which data is processed
1003 noise : noise in [channels] format for specific height
1003 noise : noise in [channels] format for specific height
1004 Abbsisarange : range of the frequencies or velocities
1004 Abbsisarange : range of the frequencies or velocities
1005 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1005 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1006
1006
1007 Output:
1007 Output:
1008 Vzon, Vmer, Vver : wind velocities
1008 Vzon, Vmer, Vver : wind velocities
1009 error_code : int that states where code is terminated
1009 error_code : int that states where code is terminated
1010
1010
1011 0 : no error detected
1011 0 : no error detected
1012 1 : Gaussian of mean spc exceeds widthlimit
1012 1 : Gaussian of mean spc exceeds widthlimit
1013 2 : no Gaussian of mean spc found
1013 2 : no Gaussian of mean spc found
1014 3 : SNR to low or velocity to high -> prec. e.g.
1014 3 : SNR to low or velocity to high -> prec. e.g.
1015 4 : at least one Gaussian of cspc exceeds widthlimit
1015 4 : at least one Gaussian of cspc exceeds widthlimit
1016 5 : zero out of three cspc Gaussian fits converged
1016 5 : zero out of three cspc Gaussian fits converged
1017 6 : phase slope fit could not be found
1017 6 : phase slope fit could not be found
1018 7 : arrays used to fit phase have different length
1018 7 : arrays used to fit phase have different length
1019 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1019 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1020
1020
1021 """
1021 """
1022
1022
1023 error_code = 0
1023 error_code = 0
1024
1024
1025 nChan = spc.shape[0]
1025 nChan = spc.shape[0]
1026 nProf = spc.shape[1]
1026 nProf = spc.shape[1]
1027 nPair = cspc.shape[0]
1027 nPair = cspc.shape[0]
1028
1028
1029 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1029 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1030 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1030 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1031 phase = numpy.zeros([nPair, nProf]) # phase between channels
1031 phase = numpy.zeros([nPair, nProf]) # phase between channels
1032 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1032 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1033 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1033 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1034 xFrec = AbbsisaRange[0][:-1] # frequency range
1034 xFrec = AbbsisaRange[0][:-1] # frequency range
1035 xVel = AbbsisaRange[2][:-1] # velocity range
1035 xVel = AbbsisaRange[2][:-1] # velocity range
1036 xSamples = xFrec # the frequency range is taken
1036 xSamples = xFrec # the frequency range is taken
1037 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1037 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1038
1038
1039 # only consider velocities with in NegativeLimit and PositiveLimit
1039 # only consider velocities with in NegativeLimit and PositiveLimit
1040 if (NegativeLimit is None):
1040 if (NegativeLimit is None):
1041 NegativeLimit = numpy.min(xVel)
1041 NegativeLimit = numpy.min(xVel)
1042 if (PositiveLimit is None):
1042 if (PositiveLimit is None):
1043 PositiveLimit = numpy.max(xVel)
1043 PositiveLimit = numpy.max(xVel)
1044 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1044 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1045 xSamples_zoom = xSamples[xvalid]
1045 xSamples_zoom = xSamples[xvalid]
1046
1046
1047 '''Getting Eij and Nij'''
1047 '''Getting Eij and Nij'''
1048 Xi01, Xi02, Xi12 = ChanDist[:,0]
1048 Xi01, Xi02, Xi12 = ChanDist[:,0]
1049 Eta01, Eta02, Eta12 = ChanDist[:,1]
1049 Eta01, Eta02, Eta12 = ChanDist[:,1]
1050
1050
1051 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1051 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1052 widthlimit = 10
1052 widthlimit = 10
1053 '''************************* SPC is normalized ********************************'''
1053 '''************************* SPC is normalized ********************************'''
1054 spc_norm = spc.copy()
1054 spc_norm = spc.copy()
1055 # For each channel
1055 # For each channel
1056 for i in range(nChan):
1056 for i in range(nChan):
1057 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1057 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1058 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1058 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1059
1059
1060 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1060 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1061
1061
1062 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1062 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1063 you only fit the curve and don't need the absolute value of height for calculation,
1063 you only fit the curve and don't need the absolute value of height for calculation,
1064 only for estimation of width. for normalization of cross spectra, you need initial,
1064 only for estimation of width. for normalization of cross spectra, you need initial,
1065 unnormalized self-spectra With noise.
1065 unnormalized self-spectra With noise.
1066
1066
1067 Technically, you don't even need to normalize the self-spectra, as you only need the
1067 Technically, you don't even need to normalize the self-spectra, as you only need the
1068 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1068 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1069 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1069 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1070 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1070 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1071 """
1071 """
1072 # initial conditions
1072 # initial conditions
1073 popt = [1e-10,0,1e-10]
1073 popt = [1e-10,0,1e-10]
1074 # Spectra average
1074 # Spectra average
1075 SPCMean = numpy.average(SPC_Samples,0)
1075 SPCMean = numpy.average(SPC_Samples,0)
1076 # Moments in frequency
1076 # Moments in frequency
1077 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1077 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1078
1078
1079 # Gauss Fit SPC in frequency domain
1079 # Gauss Fit SPC in frequency domain
1080 if dbSNR > SNRlimit: # only if SNR > SNRth
1080 if dbSNR > SNRlimit: # only if SNR > SNRth
1081 try:
1081 try:
1082 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1082 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1083 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1083 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1084 return self.StopWindEstimation(error_code = 1)
1084 return self.StopWindEstimation(error_code = 1)
1085 FitGauss = self.gaus(xSamples_zoom,*popt)
1085 FitGauss = self.gaus(xSamples_zoom,*popt)
1086 except :#RuntimeError:
1086 except :#RuntimeError:
1087 return self.StopWindEstimation(error_code = 2)
1087 return self.StopWindEstimation(error_code = 2)
1088 else:
1088 else:
1089 return self.StopWindEstimation(error_code = 3)
1089 return self.StopWindEstimation(error_code = 3)
1090
1090
1091 '''***************************** CSPC Normalization *************************
1091 '''***************************** CSPC Normalization *************************
1092 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1092 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1093 influence the norm which is not desired. First, a range is identified where the
1093 influence the norm which is not desired. First, a range is identified where the
1094 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1094 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1095 around it gets cut off and values replaced by mean determined by the boundary
1095 around it gets cut off and values replaced by mean determined by the boundary
1096 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1096 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1097
1097
1098 The sums are then added and multiplied by range/datapoints, because you need
1098 The sums are then added and multiplied by range/datapoints, because you need
1099 an integral and not a sum for normalization.
1099 an integral and not a sum for normalization.
1100
1100
1101 A norm is found according to Briggs 92.
1101 A norm is found according to Briggs 92.
1102 '''
1102 '''
1103 # for each pair
1103 # for each pair
1104 for i in range(nPair):
1104 for i in range(nPair):
1105 cspc_norm = cspc[i,:].copy()
1105 cspc_norm = cspc[i,:].copy()
1106 chan_index0 = pairsList[i][0]
1106 chan_index0 = pairsList[i][0]
1107 chan_index1 = pairsList[i][1]
1107 chan_index1 = pairsList[i][1]
1108 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1108 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1109 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1109 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1110
1110
1111 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1111 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1112 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1112 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1113 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1113 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1114
1114
1115 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1115 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1116 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1116 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1117
1117
1118 '''*******************************FIT GAUSS CSPC************************************'''
1118 '''*******************************FIT GAUSS CSPC************************************'''
1119 try:
1119 try:
1120 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1120 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1121 if popt01[2] > widthlimit: # CONDITION
1121 if popt01[2] > widthlimit: # CONDITION
1122 return self.StopWindEstimation(error_code = 4)
1122 return self.StopWindEstimation(error_code = 4)
1123 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1123 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1124 if popt02[2] > widthlimit: # CONDITION
1124 if popt02[2] > widthlimit: # CONDITION
1125 return self.StopWindEstimation(error_code = 4)
1125 return self.StopWindEstimation(error_code = 4)
1126 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1126 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1127 if popt12[2] > widthlimit: # CONDITION
1127 if popt12[2] > widthlimit: # CONDITION
1128 return self.StopWindEstimation(error_code = 4)
1128 return self.StopWindEstimation(error_code = 4)
1129
1129
1130 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1130 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1131 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1131 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1132 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1132 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1133 except:
1133 except:
1134 return self.StopWindEstimation(error_code = 5)
1134 return self.StopWindEstimation(error_code = 5)
1135
1135
1136
1136
1137 '''************* Getting Fij ***************'''
1137 '''************* Getting Fij ***************'''
1138 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1138 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1139 GaussCenter = popt[1]
1139 GaussCenter = popt[1]
1140 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1140 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1141 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1141 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1142
1142
1143 # Point where e^-1 is located in the gaussian
1143 # Point where e^-1 is located in the gaussian
1144 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1144 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1145 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1145 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1146 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1146 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1147 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1147 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1148
1148
1149 '''********** Taking frequency ranges from mean SPCs **********'''
1149 '''********** Taking frequency ranges from mean SPCs **********'''
1150 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1150 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1151 Range = numpy.empty(2)
1151 Range = numpy.empty(2)
1152 Range[0] = GaussCenter - GauWidth
1152 Range[0] = GaussCenter - GauWidth
1153 Range[1] = GaussCenter + GauWidth
1153 Range[1] = GaussCenter + GauWidth
1154 # Point in x-axis where the bandwidth is located (min:max)
1154 # Point in x-axis where the bandwidth is located (min:max)
1155 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1155 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1156 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1156 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1157 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1157 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1158 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1158 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1159 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1159 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1160 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1160 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1161
1161
1162 '''************************** Getting Phase Slope ***************************'''
1162 '''************************** Getting Phase Slope ***************************'''
1163 for i in range(nPair):
1163 for i in range(nPair):
1164 if len(FrecRange) > 5:
1164 if len(FrecRange) > 5:
1165 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1165 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1166 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1166 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1167 if len(FrecRange) == len(PhaseRange):
1167 if len(FrecRange) == len(PhaseRange):
1168 try:
1168 try:
1169 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1169 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1170 PhaseSlope[i] = slope
1170 PhaseSlope[i] = slope
1171 PhaseInter[i] = intercept
1171 PhaseInter[i] = intercept
1172 except:
1172 except:
1173 return self.StopWindEstimation(error_code = 6)
1173 return self.StopWindEstimation(error_code = 6)
1174 else:
1174 else:
1175 return self.StopWindEstimation(error_code = 7)
1175 return self.StopWindEstimation(error_code = 7)
1176 else:
1176 else:
1177 return self.StopWindEstimation(error_code = 8)
1177 return self.StopWindEstimation(error_code = 8)
1178
1178
1179 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1179 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1180
1180
1181 '''Getting constant C'''
1181 '''Getting constant C'''
1182 cC=(Fij*numpy.pi)**2
1182 cC=(Fij*numpy.pi)**2
1183
1183
1184 '''****** Getting constants F and G ******'''
1184 '''****** Getting constants F and G ******'''
1185 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1185 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1186 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1186 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1187 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1187 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1188 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1188 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1189 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1189 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1190 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1190 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1191 MijResults = numpy.array([MijResult1, MijResult2])
1191 MijResults = numpy.array([MijResult1, MijResult2])
1192 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1192 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1193
1193
1194 '''****** Getting constants A, B and H ******'''
1194 '''****** Getting constants A, B and H ******'''
1195 W01 = numpy.nanmax( FitGauss01 )
1195 W01 = numpy.nanmax( FitGauss01 )
1196 W02 = numpy.nanmax( FitGauss02 )
1196 W02 = numpy.nanmax( FitGauss02 )
1197 W12 = numpy.nanmax( FitGauss12 )
1197 W12 = numpy.nanmax( FitGauss12 )
1198
1198
1199 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1199 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1200 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1200 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1201 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1201 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1202 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1202 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1203
1203
1204 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1204 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1205 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1205 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1206
1206
1207 VxVy = numpy.array([[cA,cH],[cH,cB]])
1207 VxVy = numpy.array([[cA,cH],[cH,cB]])
1208 VxVyResults = numpy.array([-cF,-cG])
1208 VxVyResults = numpy.array([-cF,-cG])
1209 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1209 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1210 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1210 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1211 error_code = 0
1211 error_code = 0
1212
1212
1213 return Vzon, Vmer, Vver, error_code
1213 return Vzon, Vmer, Vver, error_code
1214
1214
1215 class SpectralMoments(Operation):
1215 class SpectralMoments(Operation):
1216
1216
1217 '''
1217 '''
1218 Function SpectralMoments()
1218 Function SpectralMoments()
1219
1219
1220 Calculates moments (power, mean, standard deviation) and SNR of the signal
1220 Calculates moments (power, mean, standard deviation) and SNR of the signal
1221
1221
1222 Type of dataIn: Spectra
1222 Type of dataIn: Spectra
1223
1223
1224 Configuration Parameters:
1224 Configuration Parameters:
1225
1225
1226 dirCosx : Cosine director in X axis
1226 dirCosx : Cosine director in X axis
1227 dirCosy : Cosine director in Y axis
1227 dirCosy : Cosine director in Y axis
1228
1228
1229 elevation :
1229 elevation :
1230 azimuth :
1230 azimuth :
1231
1231
1232 Input:
1232 Input:
1233 channelList : simple channel list to select e.g. [2,3,7]
1233 channelList : simple channel list to select e.g. [2,3,7]
1234 self.dataOut.data_pre : Spectral data
1234 self.dataOut.data_pre : Spectral data
1235 self.dataOut.abscissaList : List of frequencies
1235 self.dataOut.abscissaList : List of frequencies
1236 self.dataOut.noise : Noise level per channel
1236 self.dataOut.noise : Noise level per channel
1237
1237
1238 Affected:
1238 Affected:
1239 self.dataOut.moments : Parameters per channel
1239 self.dataOut.moments : Parameters per channel
1240 self.dataOut.data_snr : SNR per channel
1240 self.dataOut.data_snr : SNR per channel
1241
1241
1242 '''
1242 '''
1243
1243
1244 def run(self, dataOut):
1244 def run(self, dataOut):
1245
1245
1246 data = dataOut.data_pre[0]
1246 data = dataOut.data_pre[0]
1247 absc = dataOut.abscissaList[:-1]
1247 absc = dataOut.abscissaList[:-1]
1248 noise = dataOut.noise
1248 noise = dataOut.noise
1249 nChannel = data.shape[0]
1249 nChannel = data.shape[0]
1250 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1250 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1251
1251
1252 for ind in range(nChannel):
1252 for ind in range(nChannel):
1253 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1253 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1254
1254
1255 dataOut.moments = data_param[:,1:,:]
1255 dataOut.moments = data_param[:,1:,:]
1256 dataOut.data_snr = data_param[:,0]
1256 dataOut.data_snr = data_param[:,0]
1257 dataOut.data_pow = data_param[:,1]
1257 dataOut.data_pow = data_param[:,1]
1258 dataOut.data_dop = data_param[:,2]
1258 dataOut.data_dop = data_param[:,2]
1259 dataOut.data_width = data_param[:,3]
1259 dataOut.data_width = data_param[:,3]
1260
1260
1261 return dataOut
1261 return dataOut
1262
1262
1263 def __calculateMoments(self, oldspec, oldfreq, n0,
1263 def __calculateMoments(self, oldspec, oldfreq, n0,
1264 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1264 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1265
1265
1266 if (nicoh is None): nicoh = 1
1266 if (nicoh is None): nicoh = 1
1267 if (graph is None): graph = 0
1267 if (graph is None): graph = 0
1268 if (smooth is None): smooth = 0
1268 if (smooth is None): smooth = 0
1269 elif (self.smooth < 3): smooth = 0
1269 elif (self.smooth < 3): smooth = 0
1270
1270
1271 if (type1 is None): type1 = 0
1271 if (type1 is None): type1 = 0
1272 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1272 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1273 if (snrth is None): snrth = -3
1273 if (snrth is None): snrth = -3
1274 if (dc is None): dc = 0
1274 if (dc is None): dc = 0
1275 if (aliasing is None): aliasing = 0
1275 if (aliasing is None): aliasing = 0
1276 if (oldfd is None): oldfd = 0
1276 if (oldfd is None): oldfd = 0
1277 if (wwauto is None): wwauto = 0
1277 if (wwauto is None): wwauto = 0
1278
1278
1279 if (n0 < 1.e-20): n0 = 1.e-20
1279 if (n0 < 1.e-20): n0 = 1.e-20
1280
1280
1281 freq = oldfreq
1281 freq = oldfreq
1282 vec_power = numpy.zeros(oldspec.shape[1])
1282 vec_power = numpy.zeros(oldspec.shape[1])
1283 vec_fd = numpy.zeros(oldspec.shape[1])
1283 vec_fd = numpy.zeros(oldspec.shape[1])
1284 vec_w = numpy.zeros(oldspec.shape[1])
1284 vec_w = numpy.zeros(oldspec.shape[1])
1285 vec_snr = numpy.zeros(oldspec.shape[1])
1285 vec_snr = numpy.zeros(oldspec.shape[1])
1286
1286
1287 # oldspec = numpy.ma.masked_invalid(oldspec)
1287 # oldspec = numpy.ma.masked_invalid(oldspec)
1288
1288
1289 for ind in range(oldspec.shape[1]):
1289 for ind in range(oldspec.shape[1]):
1290
1290
1291 spec = oldspec[:,ind]
1291 spec = oldspec[:,ind]
1292 aux = spec*fwindow
1292 aux = spec*fwindow
1293 max_spec = aux.max()
1293 max_spec = aux.max()
1294 m = aux.tolist().index(max_spec)
1294 m = aux.tolist().index(max_spec)
1295
1295
1296 # Smooth
1296 # Smooth
1297 if (smooth == 0):
1297 if (smooth == 0):
1298 spec2 = spec
1298 spec2 = spec
1299 else:
1299 else:
1300 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1300 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1301
1301
1302 # Moments Estimation
1302 # Moments Estimation
1303 bb = spec2[numpy.arange(m,spec2.size)]
1303 bb = spec2[numpy.arange(m,spec2.size)]
1304 bb = (bb<n0).nonzero()
1304 bb = (bb<n0).nonzero()
1305 bb = bb[0]
1305 bb = bb[0]
1306
1306
1307 ss = spec2[numpy.arange(0,m + 1)]
1307 ss = spec2[numpy.arange(0,m + 1)]
1308 ss = (ss<n0).nonzero()
1308 ss = (ss<n0).nonzero()
1309 ss = ss[0]
1309 ss = ss[0]
1310
1310
1311 if (bb.size == 0):
1311 if (bb.size == 0):
1312 bb0 = spec.size - 1 - m
1312 bb0 = spec.size - 1 - m
1313 else:
1313 else:
1314 bb0 = bb[0] - 1
1314 bb0 = bb[0] - 1
1315 if (bb0 < 0):
1315 if (bb0 < 0):
1316 bb0 = 0
1316 bb0 = 0
1317
1317
1318 if (ss.size == 0):
1318 if (ss.size == 0):
1319 ss1 = 1
1319 ss1 = 1
1320 else:
1320 else:
1321 ss1 = max(ss) + 1
1321 ss1 = max(ss) + 1
1322
1322
1323 if (ss1 > m):
1323 if (ss1 > m):
1324 ss1 = m
1324 ss1 = m
1325
1325
1326 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1326 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1327
1327
1328 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1328 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1329 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1329 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1330 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1330 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1331 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1331 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1332 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1332 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1333 snr = (spec2.mean()-n0)/n0
1333 snr = (spec2.mean()-n0)/n0
1334 if (snr < 1.e-20) :
1334 if (snr < 1.e-20) :
1335 snr = 1.e-20
1335 snr = 1.e-20
1336
1336
1337 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1337 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1338 vec_power[ind] = total_power
1338 vec_power[ind] = total_power
1339 vec_fd[ind] = fd
1339 vec_fd[ind] = fd
1340 vec_w[ind] = w
1340 vec_w[ind] = w
1341 vec_snr[ind] = snr
1341 vec_snr[ind] = snr
1342
1342
1343 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1343 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1344
1344
1345 #------------------ Get SA Parameters --------------------------
1345 #------------------ Get SA Parameters --------------------------
1346
1346
1347 def GetSAParameters(self):
1347 def GetSAParameters(self):
1348 #SA en frecuencia
1348 #SA en frecuencia
1349 pairslist = self.dataOut.groupList
1349 pairslist = self.dataOut.groupList
1350 num_pairs = len(pairslist)
1350 num_pairs = len(pairslist)
1351
1351
1352 vel = self.dataOut.abscissaList
1352 vel = self.dataOut.abscissaList
1353 spectra = self.dataOut.data_pre
1353 spectra = self.dataOut.data_pre
1354 cspectra = self.dataIn.data_cspc
1354 cspectra = self.dataIn.data_cspc
1355 delta_v = vel[1] - vel[0]
1355 delta_v = vel[1] - vel[0]
1356
1356
1357 #Calculating the power spectrum
1357 #Calculating the power spectrum
1358 spc_pow = numpy.sum(spectra, 3)*delta_v
1358 spc_pow = numpy.sum(spectra, 3)*delta_v
1359 #Normalizing Spectra
1359 #Normalizing Spectra
1360 norm_spectra = spectra/spc_pow
1360 norm_spectra = spectra/spc_pow
1361 #Calculating the norm_spectra at peak
1361 #Calculating the norm_spectra at peak
1362 max_spectra = numpy.max(norm_spectra, 3)
1362 max_spectra = numpy.max(norm_spectra, 3)
1363
1363
1364 #Normalizing Cross Spectra
1364 #Normalizing Cross Spectra
1365 norm_cspectra = numpy.zeros(cspectra.shape)
1365 norm_cspectra = numpy.zeros(cspectra.shape)
1366
1366
1367 for i in range(num_chan):
1367 for i in range(num_chan):
1368 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1368 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1369
1369
1370 max_cspectra = numpy.max(norm_cspectra,2)
1370 max_cspectra = numpy.max(norm_cspectra,2)
1371 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1371 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1372
1372
1373 for i in range(num_pairs):
1373 for i in range(num_pairs):
1374 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1374 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1375 #------------------- Get Lags ----------------------------------
1375 #------------------- Get Lags ----------------------------------
1376
1376
1377 class SALags(Operation):
1377 class SALags(Operation):
1378 '''
1378 '''
1379 Function GetMoments()
1379 Function GetMoments()
1380
1380
1381 Input:
1381 Input:
1382 self.dataOut.data_pre
1382 self.dataOut.data_pre
1383 self.dataOut.abscissaList
1383 self.dataOut.abscissaList
1384 self.dataOut.noise
1384 self.dataOut.noise
1385 self.dataOut.normFactor
1385 self.dataOut.normFactor
1386 self.dataOut.data_snr
1386 self.dataOut.data_snr
1387 self.dataOut.groupList
1387 self.dataOut.groupList
1388 self.dataOut.nChannels
1388 self.dataOut.nChannels
1389
1389
1390 Affected:
1390 Affected:
1391 self.dataOut.data_param
1391 self.dataOut.data_param
1392
1392
1393 '''
1393 '''
1394 def run(self, dataOut):
1394 def run(self, dataOut):
1395 data_acf = dataOut.data_pre[0]
1395 data_acf = dataOut.data_pre[0]
1396 data_ccf = dataOut.data_pre[1]
1396 data_ccf = dataOut.data_pre[1]
1397 normFactor_acf = dataOut.normFactor[0]
1397 normFactor_acf = dataOut.normFactor[0]
1398 normFactor_ccf = dataOut.normFactor[1]
1398 normFactor_ccf = dataOut.normFactor[1]
1399 pairs_acf = dataOut.groupList[0]
1399 pairs_acf = dataOut.groupList[0]
1400 pairs_ccf = dataOut.groupList[1]
1400 pairs_ccf = dataOut.groupList[1]
1401
1401
1402 nHeights = dataOut.nHeights
1402 nHeights = dataOut.nHeights
1403 absc = dataOut.abscissaList
1403 absc = dataOut.abscissaList
1404 noise = dataOut.noise
1404 noise = dataOut.noise
1405 SNR = dataOut.data_snr
1405 SNR = dataOut.data_snr
1406 nChannels = dataOut.nChannels
1406 nChannels = dataOut.nChannels
1407 # pairsList = dataOut.groupList
1407 # pairsList = dataOut.groupList
1408 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1408 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1409
1409
1410 for l in range(len(pairs_acf)):
1410 for l in range(len(pairs_acf)):
1411 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1411 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1412
1412
1413 for l in range(len(pairs_ccf)):
1413 for l in range(len(pairs_ccf)):
1414 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1414 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1415
1415
1416 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1416 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1417 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1417 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1418 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1418 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1419 return
1419 return
1420
1420
1421 # def __getPairsAutoCorr(self, pairsList, nChannels):
1421 # def __getPairsAutoCorr(self, pairsList, nChannels):
1422 #
1422 #
1423 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1423 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1424 #
1424 #
1425 # for l in range(len(pairsList)):
1425 # for l in range(len(pairsList)):
1426 # firstChannel = pairsList[l][0]
1426 # firstChannel = pairsList[l][0]
1427 # secondChannel = pairsList[l][1]
1427 # secondChannel = pairsList[l][1]
1428 #
1428 #
1429 # #Obteniendo pares de Autocorrelacion
1429 # #Obteniendo pares de Autocorrelacion
1430 # if firstChannel == secondChannel:
1430 # if firstChannel == secondChannel:
1431 # pairsAutoCorr[firstChannel] = int(l)
1431 # pairsAutoCorr[firstChannel] = int(l)
1432 #
1432 #
1433 # pairsAutoCorr = pairsAutoCorr.astype(int)
1433 # pairsAutoCorr = pairsAutoCorr.astype(int)
1434 #
1434 #
1435 # pairsCrossCorr = range(len(pairsList))
1435 # pairsCrossCorr = range(len(pairsList))
1436 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1436 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1437 #
1437 #
1438 # return pairsAutoCorr, pairsCrossCorr
1438 # return pairsAutoCorr, pairsCrossCorr
1439
1439
1440 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1440 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1441
1441
1442 lag0 = data_acf.shape[1]/2
1442 lag0 = data_acf.shape[1]/2
1443 #Funcion de Autocorrelacion
1443 #Funcion de Autocorrelacion
1444 mean_acf = stats.nanmean(data_acf, axis = 0)
1444 mean_acf = stats.nanmean(data_acf, axis = 0)
1445
1445
1446 #Obtencion Indice de TauCross
1446 #Obtencion Indice de TauCross
1447 ind_ccf = data_ccf.argmax(axis = 1)
1447 ind_ccf = data_ccf.argmax(axis = 1)
1448 #Obtencion Indice de TauAuto
1448 #Obtencion Indice de TauAuto
1449 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1449 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1450 ccf_lag0 = data_ccf[:,lag0,:]
1450 ccf_lag0 = data_ccf[:,lag0,:]
1451
1451
1452 for i in range(ccf_lag0.shape[0]):
1452 for i in range(ccf_lag0.shape[0]):
1453 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1453 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1454
1454
1455 #Obtencion de TauCross y TauAuto
1455 #Obtencion de TauCross y TauAuto
1456 tau_ccf = lagRange[ind_ccf]
1456 tau_ccf = lagRange[ind_ccf]
1457 tau_acf = lagRange[ind_acf]
1457 tau_acf = lagRange[ind_acf]
1458
1458
1459 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1459 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1460
1460
1461 tau_ccf[Nan1,Nan2] = numpy.nan
1461 tau_ccf[Nan1,Nan2] = numpy.nan
1462 tau_acf[Nan1,Nan2] = numpy.nan
1462 tau_acf[Nan1,Nan2] = numpy.nan
1463 tau = numpy.vstack((tau_ccf,tau_acf))
1463 tau = numpy.vstack((tau_ccf,tau_acf))
1464
1464
1465 return tau
1465 return tau
1466
1466
1467 def __calculateLag1Phase(self, data, lagTRange):
1467 def __calculateLag1Phase(self, data, lagTRange):
1468 data1 = stats.nanmean(data, axis = 0)
1468 data1 = stats.nanmean(data, axis = 0)
1469 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1469 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1470
1470
1471 phase = numpy.angle(data1[lag1,:])
1471 phase = numpy.angle(data1[lag1,:])
1472
1472
1473 return phase
1473 return phase
1474
1474
1475 class SpectralFitting(Operation):
1475 class SpectralFitting(Operation):
1476 '''
1476 '''
1477 Function GetMoments()
1477 Function GetMoments()
1478
1478
1479 Input:
1479 Input:
1480 Output:
1480 Output:
1481 Variables modified:
1481 Variables modified:
1482 '''
1482 '''
1483
1483
1484 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1484 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1485
1485
1486
1486
1487 if path != None:
1487 if path != None:
1488 sys.path.append(path)
1488 sys.path.append(path)
1489 self.dataOut.library = importlib.import_module(file)
1489 self.dataOut.library = importlib.import_module(file)
1490
1490
1491 #To be inserted as a parameter
1491 #To be inserted as a parameter
1492 groupArray = numpy.array(groupList)
1492 groupArray = numpy.array(groupList)
1493 # groupArray = numpy.array([[0,1],[2,3]])
1493 # groupArray = numpy.array([[0,1],[2,3]])
1494 self.dataOut.groupList = groupArray
1494 self.dataOut.groupList = groupArray
1495
1495
1496 nGroups = groupArray.shape[0]
1496 nGroups = groupArray.shape[0]
1497 nChannels = self.dataIn.nChannels
1497 nChannels = self.dataIn.nChannels
1498 nHeights=self.dataIn.heightList.size
1498 nHeights=self.dataIn.heightList.size
1499
1499
1500 #Parameters Array
1500 #Parameters Array
1501 self.dataOut.data_param = None
1501 self.dataOut.data_param = None
1502
1502
1503 #Set constants
1503 #Set constants
1504 constants = self.dataOut.library.setConstants(self.dataIn)
1504 constants = self.dataOut.library.setConstants(self.dataIn)
1505 self.dataOut.constants = constants
1505 self.dataOut.constants = constants
1506 M = self.dataIn.normFactor
1506 M = self.dataIn.normFactor
1507 N = self.dataIn.nFFTPoints
1507 N = self.dataIn.nFFTPoints
1508 ippSeconds = self.dataIn.ippSeconds
1508 ippSeconds = self.dataIn.ippSeconds
1509 K = self.dataIn.nIncohInt
1509 K = self.dataIn.nIncohInt
1510 pairsArray = numpy.array(self.dataIn.pairsList)
1510 pairsArray = numpy.array(self.dataIn.pairsList)
1511
1511
1512 #List of possible combinations
1512 #List of possible combinations
1513 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1513 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1514 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1514 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1515
1515
1516 if getSNR:
1516 if getSNR:
1517 listChannels = groupArray.reshape((groupArray.size))
1517 listChannels = groupArray.reshape((groupArray.size))
1518 listChannels.sort()
1518 listChannels.sort()
1519 noise = self.dataIn.getNoise()
1519 noise = self.dataIn.getNoise()
1520 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1520 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1521
1521
1522 for i in range(nGroups):
1522 for i in range(nGroups):
1523 coord = groupArray[i,:]
1523 coord = groupArray[i,:]
1524
1524
1525 #Input data array
1525 #Input data array
1526 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1526 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1527 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1527 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1528
1528
1529 #Cross Spectra data array for Covariance Matrixes
1529 #Cross Spectra data array for Covariance Matrixes
1530 ind = 0
1530 ind = 0
1531 for pairs in listComb:
1531 for pairs in listComb:
1532 pairsSel = numpy.array([coord[x],coord[y]])
1532 pairsSel = numpy.array([coord[x],coord[y]])
1533 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1533 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1534 ind += 1
1534 ind += 1
1535 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1535 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1536 dataCross = dataCross**2/K
1536 dataCross = dataCross**2/K
1537
1537
1538 for h in range(nHeights):
1538 for h in range(nHeights):
1539
1539
1540 #Input
1540 #Input
1541 d = data[:,h]
1541 d = data[:,h]
1542
1542
1543 #Covariance Matrix
1543 #Covariance Matrix
1544 D = numpy.diag(d**2/K)
1544 D = numpy.diag(d**2/K)
1545 ind = 0
1545 ind = 0
1546 for pairs in listComb:
1546 for pairs in listComb:
1547 #Coordinates in Covariance Matrix
1547 #Coordinates in Covariance Matrix
1548 x = pairs[0]
1548 x = pairs[0]
1549 y = pairs[1]
1549 y = pairs[1]
1550 #Channel Index
1550 #Channel Index
1551 S12 = dataCross[ind,:,h]
1551 S12 = dataCross[ind,:,h]
1552 D12 = numpy.diag(S12)
1552 D12 = numpy.diag(S12)
1553 #Completing Covariance Matrix with Cross Spectras
1553 #Completing Covariance Matrix with Cross Spectras
1554 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1554 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1555 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1555 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1556 ind += 1
1556 ind += 1
1557 Dinv=numpy.linalg.inv(D)
1557 Dinv=numpy.linalg.inv(D)
1558 L=numpy.linalg.cholesky(Dinv)
1558 L=numpy.linalg.cholesky(Dinv)
1559 LT=L.T
1559 LT=L.T
1560
1560
1561 dp = numpy.dot(LT,d)
1561 dp = numpy.dot(LT,d)
1562
1562
1563 #Initial values
1563 #Initial values
1564 data_spc = self.dataIn.data_spc[coord,:,h]
1564 data_spc = self.dataIn.data_spc[coord,:,h]
1565
1565
1566 if (h>0)and(error1[3]<5):
1566 if (h>0)and(error1[3]<5):
1567 p0 = self.dataOut.data_param[i,:,h-1]
1567 p0 = self.dataOut.data_param[i,:,h-1]
1568 else:
1568 else:
1569 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1569 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1570
1570
1571 try:
1571 try:
1572 #Least Squares
1572 #Least Squares
1573 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1573 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1574 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1574 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1575 #Chi square error
1575 #Chi square error
1576 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1576 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1577 #Error with Jacobian
1577 #Error with Jacobian
1578 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1578 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1579 except:
1579 except:
1580 minp = p0*numpy.nan
1580 minp = p0*numpy.nan
1581 error0 = numpy.nan
1581 error0 = numpy.nan
1582 error1 = p0*numpy.nan
1582 error1 = p0*numpy.nan
1583
1583
1584 #Save
1584 #Save
1585 if self.dataOut.data_param is None:
1585 if self.dataOut.data_param is None:
1586 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1586 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1587 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1587 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1588
1588
1589 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1589 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1590 self.dataOut.data_param[i,:,h] = minp
1590 self.dataOut.data_param[i,:,h] = minp
1591 return
1591 return
1592
1592
1593 def __residFunction(self, p, dp, LT, constants):
1593 def __residFunction(self, p, dp, LT, constants):
1594
1594
1595 fm = self.dataOut.library.modelFunction(p, constants)
1595 fm = self.dataOut.library.modelFunction(p, constants)
1596 fmp=numpy.dot(LT,fm)
1596 fmp=numpy.dot(LT,fm)
1597
1597
1598 return dp-fmp
1598 return dp-fmp
1599
1599
1600 def __getSNR(self, z, noise):
1600 def __getSNR(self, z, noise):
1601
1601
1602 avg = numpy.average(z, axis=1)
1602 avg = numpy.average(z, axis=1)
1603 SNR = (avg.T-noise)/noise
1603 SNR = (avg.T-noise)/noise
1604 SNR = SNR.T
1604 SNR = SNR.T
1605 return SNR
1605 return SNR
1606
1606
1607 def __chisq(p,chindex,hindex):
1607 def __chisq(p,chindex,hindex):
1608 #similar to Resid but calculates CHI**2
1608 #similar to Resid but calculates CHI**2
1609 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1609 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1610 dp=numpy.dot(LT,d)
1610 dp=numpy.dot(LT,d)
1611 fmp=numpy.dot(LT,fm)
1611 fmp=numpy.dot(LT,fm)
1612 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1612 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1613 return chisq
1613 return chisq
1614
1614
1615 class WindProfiler(Operation):
1615 class WindProfiler(Operation):
1616
1616
1617 __isConfig = False
1617 __isConfig = False
1618
1618
1619 __initime = None
1619 __initime = None
1620 __lastdatatime = None
1620 __lastdatatime = None
1621 __integrationtime = None
1621 __integrationtime = None
1622
1622
1623 __buffer = None
1623 __buffer = None
1624
1624
1625 __dataReady = False
1625 __dataReady = False
1626
1626
1627 __firstdata = None
1627 __firstdata = None
1628
1628
1629 n = None
1629 n = None
1630
1630
1631 def __init__(self):
1631 def __init__(self):
1632 Operation.__init__(self)
1632 Operation.__init__(self)
1633
1633
1634 def __calculateCosDir(self, elev, azim):
1634 def __calculateCosDir(self, elev, azim):
1635 zen = (90 - elev)*numpy.pi/180
1635 zen = (90 - elev)*numpy.pi/180
1636 azim = azim*numpy.pi/180
1636 azim = azim*numpy.pi/180
1637 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1637 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1638 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1638 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1639
1639
1640 signX = numpy.sign(numpy.cos(azim))
1640 signX = numpy.sign(numpy.cos(azim))
1641 signY = numpy.sign(numpy.sin(azim))
1641 signY = numpy.sign(numpy.sin(azim))
1642
1642
1643 cosDirX = numpy.copysign(cosDirX, signX)
1643 cosDirX = numpy.copysign(cosDirX, signX)
1644 cosDirY = numpy.copysign(cosDirY, signY)
1644 cosDirY = numpy.copysign(cosDirY, signY)
1645 return cosDirX, cosDirY
1645 return cosDirX, cosDirY
1646
1646
1647 def __calculateAngles(self, theta_x, theta_y, azimuth):
1647 def __calculateAngles(self, theta_x, theta_y, azimuth):
1648
1648
1649 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1649 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1650 zenith_arr = numpy.arccos(dir_cosw)
1650 zenith_arr = numpy.arccos(dir_cosw)
1651 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1651 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1652
1652
1653 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1653 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1654 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1654 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1655
1655
1656 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1656 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1657
1657
1658 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1658 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1659
1659
1660 #
1660 #
1661 if horOnly:
1661 if horOnly:
1662 A = numpy.c_[dir_cosu,dir_cosv]
1662 A = numpy.c_[dir_cosu,dir_cosv]
1663 else:
1663 else:
1664 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1664 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1665 A = numpy.asmatrix(A)
1665 A = numpy.asmatrix(A)
1666 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1666 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1667
1667
1668 return A1
1668 return A1
1669
1669
1670 def __correctValues(self, heiRang, phi, velRadial, SNR):
1670 def __correctValues(self, heiRang, phi, velRadial, SNR):
1671 listPhi = phi.tolist()
1671 listPhi = phi.tolist()
1672 maxid = listPhi.index(max(listPhi))
1672 maxid = listPhi.index(max(listPhi))
1673 minid = listPhi.index(min(listPhi))
1673 minid = listPhi.index(min(listPhi))
1674
1674
1675 rango = list(range(len(phi)))
1675 rango = list(range(len(phi)))
1676 # rango = numpy.delete(rango,maxid)
1676 # rango = numpy.delete(rango,maxid)
1677
1677
1678 heiRang1 = heiRang*math.cos(phi[maxid])
1678 heiRang1 = heiRang*math.cos(phi[maxid])
1679 heiRangAux = heiRang*math.cos(phi[minid])
1679 heiRangAux = heiRang*math.cos(phi[minid])
1680 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1680 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1681 heiRang1 = numpy.delete(heiRang1,indOut)
1681 heiRang1 = numpy.delete(heiRang1,indOut)
1682
1682
1683 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1683 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1684 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1684 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1685
1685
1686 for i in rango:
1686 for i in rango:
1687 x = heiRang*math.cos(phi[i])
1687 x = heiRang*math.cos(phi[i])
1688 y1 = velRadial[i,:]
1688 y1 = velRadial[i,:]
1689 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1689 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1690
1690
1691 x1 = heiRang1
1691 x1 = heiRang1
1692 y11 = f1(x1)
1692 y11 = f1(x1)
1693
1693
1694 y2 = SNR[i,:]
1694 y2 = SNR[i,:]
1695 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1695 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1696 y21 = f2(x1)
1696 y21 = f2(x1)
1697
1697
1698 velRadial1[i,:] = y11
1698 velRadial1[i,:] = y11
1699 SNR1[i,:] = y21
1699 SNR1[i,:] = y21
1700
1700
1701 return heiRang1, velRadial1, SNR1
1701 return heiRang1, velRadial1, SNR1
1702
1702
1703 def __calculateVelUVW(self, A, velRadial):
1703 def __calculateVelUVW(self, A, velRadial):
1704
1704
1705 #Operacion Matricial
1705 #Operacion Matricial
1706 # velUVW = numpy.zeros((velRadial.shape[1],3))
1706 # velUVW = numpy.zeros((velRadial.shape[1],3))
1707 # for ind in range(velRadial.shape[1]):
1707 # for ind in range(velRadial.shape[1]):
1708 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1708 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1709 # velUVW = velUVW.transpose()
1709 # velUVW = velUVW.transpose()
1710 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1710 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1711 velUVW[:,:] = numpy.dot(A,velRadial)
1711 velUVW[:,:] = numpy.dot(A,velRadial)
1712
1712
1713
1713
1714 return velUVW
1714 return velUVW
1715
1715
1716 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1716 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1717
1717
1718 def techniqueDBS(self, kwargs):
1718 def techniqueDBS(self, kwargs):
1719 """
1719 """
1720 Function that implements Doppler Beam Swinging (DBS) technique.
1720 Function that implements Doppler Beam Swinging (DBS) technique.
1721
1721
1722 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1722 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1723 Direction correction (if necessary), Ranges and SNR
1723 Direction correction (if necessary), Ranges and SNR
1724
1724
1725 Output: Winds estimation (Zonal, Meridional and Vertical)
1725 Output: Winds estimation (Zonal, Meridional and Vertical)
1726
1726
1727 Parameters affected: Winds, height range, SNR
1727 Parameters affected: Winds, height range, SNR
1728 """
1728 """
1729 velRadial0 = kwargs['velRadial']
1729 velRadial0 = kwargs['velRadial']
1730 heiRang = kwargs['heightList']
1730 heiRang = kwargs['heightList']
1731 SNR0 = kwargs['SNR']
1731 SNR0 = kwargs['SNR']
1732
1732
1733 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1733 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1734 theta_x = numpy.array(kwargs['dirCosx'])
1734 theta_x = numpy.array(kwargs['dirCosx'])
1735 theta_y = numpy.array(kwargs['dirCosy'])
1735 theta_y = numpy.array(kwargs['dirCosy'])
1736 else:
1736 else:
1737 elev = numpy.array(kwargs['elevation'])
1737 elev = numpy.array(kwargs['elevation'])
1738 azim = numpy.array(kwargs['azimuth'])
1738 azim = numpy.array(kwargs['azimuth'])
1739 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1739 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1740 azimuth = kwargs['correctAzimuth']
1740 azimuth = kwargs['correctAzimuth']
1741 if 'horizontalOnly' in kwargs:
1741 if 'horizontalOnly' in kwargs:
1742 horizontalOnly = kwargs['horizontalOnly']
1742 horizontalOnly = kwargs['horizontalOnly']
1743 else: horizontalOnly = False
1743 else: horizontalOnly = False
1744 if 'correctFactor' in kwargs:
1744 if 'correctFactor' in kwargs:
1745 correctFactor = kwargs['correctFactor']
1745 correctFactor = kwargs['correctFactor']
1746 else: correctFactor = 1
1746 else: correctFactor = 1
1747 if 'channelList' in kwargs:
1747 if 'channelList' in kwargs:
1748 channelList = kwargs['channelList']
1748 channelList = kwargs['channelList']
1749 if len(channelList) == 2:
1749 if len(channelList) == 2:
1750 horizontalOnly = True
1750 horizontalOnly = True
1751 arrayChannel = numpy.array(channelList)
1751 arrayChannel = numpy.array(channelList)
1752 param = param[arrayChannel,:,:]
1752 param = param[arrayChannel,:,:]
1753 theta_x = theta_x[arrayChannel]
1753 theta_x = theta_x[arrayChannel]
1754 theta_y = theta_y[arrayChannel]
1754 theta_y = theta_y[arrayChannel]
1755
1755
1756 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1756 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1757 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1757 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1758 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1758 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1759
1759
1760 #Calculo de Componentes de la velocidad con DBS
1760 #Calculo de Componentes de la velocidad con DBS
1761 winds = self.__calculateVelUVW(A,velRadial1)
1761 winds = self.__calculateVelUVW(A,velRadial1)
1762
1762
1763 return winds, heiRang1, SNR1
1763 return winds, heiRang1, SNR1
1764
1764
1765 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1765 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1766
1766
1767 nPairs = len(pairs_ccf)
1767 nPairs = len(pairs_ccf)
1768 posx = numpy.asarray(posx)
1768 posx = numpy.asarray(posx)
1769 posy = numpy.asarray(posy)
1769 posy = numpy.asarray(posy)
1770
1770
1771 #Rotacion Inversa para alinear con el azimuth
1771 #Rotacion Inversa para alinear con el azimuth
1772 if azimuth!= None:
1772 if azimuth!= None:
1773 azimuth = azimuth*math.pi/180
1773 azimuth = azimuth*math.pi/180
1774 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1774 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1775 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1775 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1776 else:
1776 else:
1777 posx1 = posx
1777 posx1 = posx
1778 posy1 = posy
1778 posy1 = posy
1779
1779
1780 #Calculo de Distancias
1780 #Calculo de Distancias
1781 distx = numpy.zeros(nPairs)
1781 distx = numpy.zeros(nPairs)
1782 disty = numpy.zeros(nPairs)
1782 disty = numpy.zeros(nPairs)
1783 dist = numpy.zeros(nPairs)
1783 dist = numpy.zeros(nPairs)
1784 ang = numpy.zeros(nPairs)
1784 ang = numpy.zeros(nPairs)
1785
1785
1786 for i in range(nPairs):
1786 for i in range(nPairs):
1787 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1787 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1788 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1788 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1789 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1789 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1790 ang[i] = numpy.arctan2(disty[i],distx[i])
1790 ang[i] = numpy.arctan2(disty[i],distx[i])
1791
1791
1792 return distx, disty, dist, ang
1792 return distx, disty, dist, ang
1793 #Calculo de Matrices
1793 #Calculo de Matrices
1794 # nPairs = len(pairs)
1794 # nPairs = len(pairs)
1795 # ang1 = numpy.zeros((nPairs, 2, 1))
1795 # ang1 = numpy.zeros((nPairs, 2, 1))
1796 # dist1 = numpy.zeros((nPairs, 2, 1))
1796 # dist1 = numpy.zeros((nPairs, 2, 1))
1797 #
1797 #
1798 # for j in range(nPairs):
1798 # for j in range(nPairs):
1799 # dist1[j,0,0] = dist[pairs[j][0]]
1799 # dist1[j,0,0] = dist[pairs[j][0]]
1800 # dist1[j,1,0] = dist[pairs[j][1]]
1800 # dist1[j,1,0] = dist[pairs[j][1]]
1801 # ang1[j,0,0] = ang[pairs[j][0]]
1801 # ang1[j,0,0] = ang[pairs[j][0]]
1802 # ang1[j,1,0] = ang[pairs[j][1]]
1802 # ang1[j,1,0] = ang[pairs[j][1]]
1803 #
1803 #
1804 # return distx,disty, dist1,ang1
1804 # return distx,disty, dist1,ang1
1805
1805
1806
1806
1807 def __calculateVelVer(self, phase, lagTRange, _lambda):
1807 def __calculateVelVer(self, phase, lagTRange, _lambda):
1808
1808
1809 Ts = lagTRange[1] - lagTRange[0]
1809 Ts = lagTRange[1] - lagTRange[0]
1810 velW = -_lambda*phase/(4*math.pi*Ts)
1810 velW = -_lambda*phase/(4*math.pi*Ts)
1811
1811
1812 return velW
1812 return velW
1813
1813
1814 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1814 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1815 nPairs = tau1.shape[0]
1815 nPairs = tau1.shape[0]
1816 nHeights = tau1.shape[1]
1816 nHeights = tau1.shape[1]
1817 vel = numpy.zeros((nPairs,3,nHeights))
1817 vel = numpy.zeros((nPairs,3,nHeights))
1818 dist1 = numpy.reshape(dist, (dist.size,1))
1818 dist1 = numpy.reshape(dist, (dist.size,1))
1819
1819
1820 angCos = numpy.cos(ang)
1820 angCos = numpy.cos(ang)
1821 angSin = numpy.sin(ang)
1821 angSin = numpy.sin(ang)
1822
1822
1823 vel0 = dist1*tau1/(2*tau2**2)
1823 vel0 = dist1*tau1/(2*tau2**2)
1824 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1824 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1825 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1825 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1826
1826
1827 ind = numpy.where(numpy.isinf(vel))
1827 ind = numpy.where(numpy.isinf(vel))
1828 vel[ind] = numpy.nan
1828 vel[ind] = numpy.nan
1829
1829
1830 return vel
1830 return vel
1831
1831
1832 # def __getPairsAutoCorr(self, pairsList, nChannels):
1832 # def __getPairsAutoCorr(self, pairsList, nChannels):
1833 #
1833 #
1834 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1834 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1835 #
1835 #
1836 # for l in range(len(pairsList)):
1836 # for l in range(len(pairsList)):
1837 # firstChannel = pairsList[l][0]
1837 # firstChannel = pairsList[l][0]
1838 # secondChannel = pairsList[l][1]
1838 # secondChannel = pairsList[l][1]
1839 #
1839 #
1840 # #Obteniendo pares de Autocorrelacion
1840 # #Obteniendo pares de Autocorrelacion
1841 # if firstChannel == secondChannel:
1841 # if firstChannel == secondChannel:
1842 # pairsAutoCorr[firstChannel] = int(l)
1842 # pairsAutoCorr[firstChannel] = int(l)
1843 #
1843 #
1844 # pairsAutoCorr = pairsAutoCorr.astype(int)
1844 # pairsAutoCorr = pairsAutoCorr.astype(int)
1845 #
1845 #
1846 # pairsCrossCorr = range(len(pairsList))
1846 # pairsCrossCorr = range(len(pairsList))
1847 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1847 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1848 #
1848 #
1849 # return pairsAutoCorr, pairsCrossCorr
1849 # return pairsAutoCorr, pairsCrossCorr
1850
1850
1851 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1851 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1852 def techniqueSA(self, kwargs):
1852 def techniqueSA(self, kwargs):
1853
1853
1854 """
1854 """
1855 Function that implements Spaced Antenna (SA) technique.
1855 Function that implements Spaced Antenna (SA) technique.
1856
1856
1857 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1857 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1858 Direction correction (if necessary), Ranges and SNR
1858 Direction correction (if necessary), Ranges and SNR
1859
1859
1860 Output: Winds estimation (Zonal, Meridional and Vertical)
1860 Output: Winds estimation (Zonal, Meridional and Vertical)
1861
1861
1862 Parameters affected: Winds
1862 Parameters affected: Winds
1863 """
1863 """
1864 position_x = kwargs['positionX']
1864 position_x = kwargs['positionX']
1865 position_y = kwargs['positionY']
1865 position_y = kwargs['positionY']
1866 azimuth = kwargs['azimuth']
1866 azimuth = kwargs['azimuth']
1867
1867
1868 if 'correctFactor' in kwargs:
1868 if 'correctFactor' in kwargs:
1869 correctFactor = kwargs['correctFactor']
1869 correctFactor = kwargs['correctFactor']
1870 else:
1870 else:
1871 correctFactor = 1
1871 correctFactor = 1
1872
1872
1873 groupList = kwargs['groupList']
1873 groupList = kwargs['groupList']
1874 pairs_ccf = groupList[1]
1874 pairs_ccf = groupList[1]
1875 tau = kwargs['tau']
1875 tau = kwargs['tau']
1876 _lambda = kwargs['_lambda']
1876 _lambda = kwargs['_lambda']
1877
1877
1878 #Cross Correlation pairs obtained
1878 #Cross Correlation pairs obtained
1879 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1879 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1880 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1880 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1881 # pairsSelArray = numpy.array(pairsSelected)
1881 # pairsSelArray = numpy.array(pairsSelected)
1882 # pairs = []
1882 # pairs = []
1883 #
1883 #
1884 # #Wind estimation pairs obtained
1884 # #Wind estimation pairs obtained
1885 # for i in range(pairsSelArray.shape[0]/2):
1885 # for i in range(pairsSelArray.shape[0]/2):
1886 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1886 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1887 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1887 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1888 # pairs.append((ind1,ind2))
1888 # pairs.append((ind1,ind2))
1889
1889
1890 indtau = tau.shape[0]/2
1890 indtau = tau.shape[0]/2
1891 tau1 = tau[:indtau,:]
1891 tau1 = tau[:indtau,:]
1892 tau2 = tau[indtau:-1,:]
1892 tau2 = tau[indtau:-1,:]
1893 # tau1 = tau1[pairs,:]
1893 # tau1 = tau1[pairs,:]
1894 # tau2 = tau2[pairs,:]
1894 # tau2 = tau2[pairs,:]
1895 phase1 = tau[-1,:]
1895 phase1 = tau[-1,:]
1896
1896
1897 #---------------------------------------------------------------------
1897 #---------------------------------------------------------------------
1898 #Metodo Directo
1898 #Metodo Directo
1899 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1899 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1900 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1900 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1901 winds = stats.nanmean(winds, axis=0)
1901 winds = stats.nanmean(winds, axis=0)
1902 #---------------------------------------------------------------------
1902 #---------------------------------------------------------------------
1903 #Metodo General
1903 #Metodo General
1904 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1904 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1905 # #Calculo Coeficientes de Funcion de Correlacion
1905 # #Calculo Coeficientes de Funcion de Correlacion
1906 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1906 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1907 # #Calculo de Velocidades
1907 # #Calculo de Velocidades
1908 # winds = self.calculateVelUV(F,G,A,B,H)
1908 # winds = self.calculateVelUV(F,G,A,B,H)
1909
1909
1910 #---------------------------------------------------------------------
1910 #---------------------------------------------------------------------
1911 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1911 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1912 winds = correctFactor*winds
1912 winds = correctFactor*winds
1913 return winds
1913 return winds
1914
1914
1915 def __checkTime(self, currentTime, paramInterval, outputInterval):
1915 def __checkTime(self, currentTime, paramInterval, outputInterval):
1916
1916
1917 dataTime = currentTime + paramInterval
1917 dataTime = currentTime + paramInterval
1918 deltaTime = dataTime - self.__initime
1918 deltaTime = dataTime - self.__initime
1919
1919
1920 if deltaTime >= outputInterval or deltaTime < 0:
1920 if deltaTime >= outputInterval or deltaTime < 0:
1921 self.__dataReady = True
1921 self.__dataReady = True
1922 return
1922 return
1923
1923
1924 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1924 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1925 '''
1925 '''
1926 Function that implements winds estimation technique with detected meteors.
1926 Function that implements winds estimation technique with detected meteors.
1927
1927
1928 Input: Detected meteors, Minimum meteor quantity to wind estimation
1928 Input: Detected meteors, Minimum meteor quantity to wind estimation
1929
1929
1930 Output: Winds estimation (Zonal and Meridional)
1930 Output: Winds estimation (Zonal and Meridional)
1931
1931
1932 Parameters affected: Winds
1932 Parameters affected: Winds
1933 '''
1933 '''
1934 #Settings
1934 #Settings
1935 nInt = (heightMax - heightMin)/2
1935 nInt = (heightMax - heightMin)/2
1936 nInt = int(nInt)
1936 nInt = int(nInt)
1937 winds = numpy.zeros((2,nInt))*numpy.nan
1937 winds = numpy.zeros((2,nInt))*numpy.nan
1938
1938
1939 #Filter errors
1939 #Filter errors
1940 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1940 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1941 finalMeteor = arrayMeteor[error,:]
1941 finalMeteor = arrayMeteor[error,:]
1942
1942
1943 #Meteor Histogram
1943 #Meteor Histogram
1944 finalHeights = finalMeteor[:,2]
1944 finalHeights = finalMeteor[:,2]
1945 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1945 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1946 nMeteorsPerI = hist[0]
1946 nMeteorsPerI = hist[0]
1947 heightPerI = hist[1]
1947 heightPerI = hist[1]
1948
1948
1949 #Sort of meteors
1949 #Sort of meteors
1950 indSort = finalHeights.argsort()
1950 indSort = finalHeights.argsort()
1951 finalMeteor2 = finalMeteor[indSort,:]
1951 finalMeteor2 = finalMeteor[indSort,:]
1952
1952
1953 # Calculating winds
1953 # Calculating winds
1954 ind1 = 0
1954 ind1 = 0
1955 ind2 = 0
1955 ind2 = 0
1956
1956
1957 for i in range(nInt):
1957 for i in range(nInt):
1958 nMet = nMeteorsPerI[i]
1958 nMet = nMeteorsPerI[i]
1959 ind1 = ind2
1959 ind1 = ind2
1960 ind2 = ind1 + nMet
1960 ind2 = ind1 + nMet
1961
1961
1962 meteorAux = finalMeteor2[ind1:ind2,:]
1962 meteorAux = finalMeteor2[ind1:ind2,:]
1963
1963
1964 if meteorAux.shape[0] >= meteorThresh:
1964 if meteorAux.shape[0] >= meteorThresh:
1965 vel = meteorAux[:, 6]
1965 vel = meteorAux[:, 6]
1966 zen = meteorAux[:, 4]*numpy.pi/180
1966 zen = meteorAux[:, 4]*numpy.pi/180
1967 azim = meteorAux[:, 3]*numpy.pi/180
1967 azim = meteorAux[:, 3]*numpy.pi/180
1968
1968
1969 n = numpy.cos(zen)
1969 n = numpy.cos(zen)
1970 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1970 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1971 # l = m*numpy.tan(azim)
1971 # l = m*numpy.tan(azim)
1972 l = numpy.sin(zen)*numpy.sin(azim)
1972 l = numpy.sin(zen)*numpy.sin(azim)
1973 m = numpy.sin(zen)*numpy.cos(azim)
1973 m = numpy.sin(zen)*numpy.cos(azim)
1974
1974
1975 A = numpy.vstack((l, m)).transpose()
1975 A = numpy.vstack((l, m)).transpose()
1976 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1976 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1977 windsAux = numpy.dot(A1, vel)
1977 windsAux = numpy.dot(A1, vel)
1978
1978
1979 winds[0,i] = windsAux[0]
1979 winds[0,i] = windsAux[0]
1980 winds[1,i] = windsAux[1]
1980 winds[1,i] = windsAux[1]
1981
1981
1982 return winds, heightPerI[:-1]
1982 return winds, heightPerI[:-1]
1983
1983
1984 def techniqueNSM_SA(self, **kwargs):
1984 def techniqueNSM_SA(self, **kwargs):
1985 metArray = kwargs['metArray']
1985 metArray = kwargs['metArray']
1986 heightList = kwargs['heightList']
1986 heightList = kwargs['heightList']
1987 timeList = kwargs['timeList']
1987 timeList = kwargs['timeList']
1988
1988
1989 rx_location = kwargs['rx_location']
1989 rx_location = kwargs['rx_location']
1990 groupList = kwargs['groupList']
1990 groupList = kwargs['groupList']
1991 azimuth = kwargs['azimuth']
1991 azimuth = kwargs['azimuth']
1992 dfactor = kwargs['dfactor']
1992 dfactor = kwargs['dfactor']
1993 k = kwargs['k']
1993 k = kwargs['k']
1994
1994
1995 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1995 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1996 d = dist*dfactor
1996 d = dist*dfactor
1997 #Phase calculation
1997 #Phase calculation
1998 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1998 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1999
1999
2000 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2000 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2001
2001
2002 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2002 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2003 azimuth1 = azimuth1*numpy.pi/180
2003 azimuth1 = azimuth1*numpy.pi/180
2004
2004
2005 for i in range(heightList.size):
2005 for i in range(heightList.size):
2006 h = heightList[i]
2006 h = heightList[i]
2007 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2007 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2008 metHeight = metArray1[indH,:]
2008 metHeight = metArray1[indH,:]
2009 if metHeight.shape[0] >= 2:
2009 if metHeight.shape[0] >= 2:
2010 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2010 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2011 iazim = metHeight[:,1].astype(int)
2011 iazim = metHeight[:,1].astype(int)
2012 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2012 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2013 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2013 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2014 A = numpy.asmatrix(A)
2014 A = numpy.asmatrix(A)
2015 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2015 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2016 velHor = numpy.dot(A1,velAux)
2016 velHor = numpy.dot(A1,velAux)
2017
2017
2018 velEst[i,:] = numpy.squeeze(velHor)
2018 velEst[i,:] = numpy.squeeze(velHor)
2019 return velEst
2019 return velEst
2020
2020
2021 def __getPhaseSlope(self, metArray, heightList, timeList):
2021 def __getPhaseSlope(self, metArray, heightList, timeList):
2022 meteorList = []
2022 meteorList = []
2023 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2023 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2024 #Putting back together the meteor matrix
2024 #Putting back together the meteor matrix
2025 utctime = metArray[:,0]
2025 utctime = metArray[:,0]
2026 uniqueTime = numpy.unique(utctime)
2026 uniqueTime = numpy.unique(utctime)
2027
2027
2028 phaseDerThresh = 0.5
2028 phaseDerThresh = 0.5
2029 ippSeconds = timeList[1] - timeList[0]
2029 ippSeconds = timeList[1] - timeList[0]
2030 sec = numpy.where(timeList>1)[0][0]
2030 sec = numpy.where(timeList>1)[0][0]
2031 nPairs = metArray.shape[1] - 6
2031 nPairs = metArray.shape[1] - 6
2032 nHeights = len(heightList)
2032 nHeights = len(heightList)
2033
2033
2034 for t in uniqueTime:
2034 for t in uniqueTime:
2035 metArray1 = metArray[utctime==t,:]
2035 metArray1 = metArray[utctime==t,:]
2036 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2036 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2037 tmet = metArray1[:,1].astype(int)
2037 tmet = metArray1[:,1].astype(int)
2038 hmet = metArray1[:,2].astype(int)
2038 hmet = metArray1[:,2].astype(int)
2039
2039
2040 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2040 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2041 metPhase[:,:] = numpy.nan
2041 metPhase[:,:] = numpy.nan
2042 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2042 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2043
2043
2044 #Delete short trails
2044 #Delete short trails
2045 metBool = ~numpy.isnan(metPhase[0,:,:])
2045 metBool = ~numpy.isnan(metPhase[0,:,:])
2046 heightVect = numpy.sum(metBool, axis = 1)
2046 heightVect = numpy.sum(metBool, axis = 1)
2047 metBool[heightVect<sec,:] = False
2047 metBool[heightVect<sec,:] = False
2048 metPhase[:,heightVect<sec,:] = numpy.nan
2048 metPhase[:,heightVect<sec,:] = numpy.nan
2049
2049
2050 #Derivative
2050 #Derivative
2051 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2051 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2052 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2052 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2053 metPhase[phDerAux] = numpy.nan
2053 metPhase[phDerAux] = numpy.nan
2054
2054
2055 #--------------------------METEOR DETECTION -----------------------------------------
2055 #--------------------------METEOR DETECTION -----------------------------------------
2056 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2056 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2057
2057
2058 for p in numpy.arange(nPairs):
2058 for p in numpy.arange(nPairs):
2059 phase = metPhase[p,:,:]
2059 phase = metPhase[p,:,:]
2060 phDer = metDer[p,:,:]
2060 phDer = metDer[p,:,:]
2061
2061
2062 for h in indMet:
2062 for h in indMet:
2063 height = heightList[h]
2063 height = heightList[h]
2064 phase1 = phase[h,:] #82
2064 phase1 = phase[h,:] #82
2065 phDer1 = phDer[h,:]
2065 phDer1 = phDer[h,:]
2066
2066
2067 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2067 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2068
2068
2069 indValid = numpy.where(~numpy.isnan(phase1))[0]
2069 indValid = numpy.where(~numpy.isnan(phase1))[0]
2070 initMet = indValid[0]
2070 initMet = indValid[0]
2071 endMet = 0
2071 endMet = 0
2072
2072
2073 for i in range(len(indValid)-1):
2073 for i in range(len(indValid)-1):
2074
2074
2075 #Time difference
2075 #Time difference
2076 inow = indValid[i]
2076 inow = indValid[i]
2077 inext = indValid[i+1]
2077 inext = indValid[i+1]
2078 idiff = inext - inow
2078 idiff = inext - inow
2079 #Phase difference
2079 #Phase difference
2080 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2080 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2081
2081
2082 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2082 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2083 sizeTrail = inow - initMet + 1
2083 sizeTrail = inow - initMet + 1
2084 if sizeTrail>3*sec: #Too short meteors
2084 if sizeTrail>3*sec: #Too short meteors
2085 x = numpy.arange(initMet,inow+1)*ippSeconds
2085 x = numpy.arange(initMet,inow+1)*ippSeconds
2086 y = phase1[initMet:inow+1]
2086 y = phase1[initMet:inow+1]
2087 ynnan = ~numpy.isnan(y)
2087 ynnan = ~numpy.isnan(y)
2088 x = x[ynnan]
2088 x = x[ynnan]
2089 y = y[ynnan]
2089 y = y[ynnan]
2090 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2090 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2091 ylin = x*slope + intercept
2091 ylin = x*slope + intercept
2092 rsq = r_value**2
2092 rsq = r_value**2
2093 if rsq > 0.5:
2093 if rsq > 0.5:
2094 vel = slope#*height*1000/(k*d)
2094 vel = slope#*height*1000/(k*d)
2095 estAux = numpy.array([utctime,p,height, vel, rsq])
2095 estAux = numpy.array([utctime,p,height, vel, rsq])
2096 meteorList.append(estAux)
2096 meteorList.append(estAux)
2097 initMet = inext
2097 initMet = inext
2098 metArray2 = numpy.array(meteorList)
2098 metArray2 = numpy.array(meteorList)
2099
2099
2100 return metArray2
2100 return metArray2
2101
2101
2102 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2102 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2103
2103
2104 azimuth1 = numpy.zeros(len(pairslist))
2104 azimuth1 = numpy.zeros(len(pairslist))
2105 dist = numpy.zeros(len(pairslist))
2105 dist = numpy.zeros(len(pairslist))
2106
2106
2107 for i in range(len(rx_location)):
2107 for i in range(len(rx_location)):
2108 ch0 = pairslist[i][0]
2108 ch0 = pairslist[i][0]
2109 ch1 = pairslist[i][1]
2109 ch1 = pairslist[i][1]
2110
2110
2111 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2111 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2112 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2112 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2113 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2113 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2114 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2114 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2115
2115
2116 azimuth1 -= azimuth0
2116 azimuth1 -= azimuth0
2117 return azimuth1, dist
2117 return azimuth1, dist
2118
2118
2119 def techniqueNSM_DBS(self, **kwargs):
2119 def techniqueNSM_DBS(self, **kwargs):
2120 metArray = kwargs['metArray']
2120 metArray = kwargs['metArray']
2121 heightList = kwargs['heightList']
2121 heightList = kwargs['heightList']
2122 timeList = kwargs['timeList']
2122 timeList = kwargs['timeList']
2123 azimuth = kwargs['azimuth']
2123 azimuth = kwargs['azimuth']
2124 theta_x = numpy.array(kwargs['theta_x'])
2124 theta_x = numpy.array(kwargs['theta_x'])
2125 theta_y = numpy.array(kwargs['theta_y'])
2125 theta_y = numpy.array(kwargs['theta_y'])
2126
2126
2127 utctime = metArray[:,0]
2127 utctime = metArray[:,0]
2128 cmet = metArray[:,1].astype(int)
2128 cmet = metArray[:,1].astype(int)
2129 hmet = metArray[:,3].astype(int)
2129 hmet = metArray[:,3].astype(int)
2130 SNRmet = metArray[:,4]
2130 SNRmet = metArray[:,4]
2131 vmet = metArray[:,5]
2131 vmet = metArray[:,5]
2132 spcmet = metArray[:,6]
2132 spcmet = metArray[:,6]
2133
2133
2134 nChan = numpy.max(cmet) + 1
2134 nChan = numpy.max(cmet) + 1
2135 nHeights = len(heightList)
2135 nHeights = len(heightList)
2136
2136
2137 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2137 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2138 hmet = heightList[hmet]
2138 hmet = heightList[hmet]
2139 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2139 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2140
2140
2141 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2141 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2142
2142
2143 for i in range(nHeights - 1):
2143 for i in range(nHeights - 1):
2144 hmin = heightList[i]
2144 hmin = heightList[i]
2145 hmax = heightList[i + 1]
2145 hmax = heightList[i + 1]
2146
2146
2147 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2147 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2148 indthisH = numpy.where(thisH)
2148 indthisH = numpy.where(thisH)
2149
2149
2150 if numpy.size(indthisH) > 3:
2150 if numpy.size(indthisH) > 3:
2151
2151
2152 vel_aux = vmet[thisH]
2152 vel_aux = vmet[thisH]
2153 chan_aux = cmet[thisH]
2153 chan_aux = cmet[thisH]
2154 cosu_aux = dir_cosu[chan_aux]
2154 cosu_aux = dir_cosu[chan_aux]
2155 cosv_aux = dir_cosv[chan_aux]
2155 cosv_aux = dir_cosv[chan_aux]
2156 cosw_aux = dir_cosw[chan_aux]
2156 cosw_aux = dir_cosw[chan_aux]
2157
2157
2158 nch = numpy.size(numpy.unique(chan_aux))
2158 nch = numpy.size(numpy.unique(chan_aux))
2159 if nch > 1:
2159 if nch > 1:
2160 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2160 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2161 velEst[i,:] = numpy.dot(A,vel_aux)
2161 velEst[i,:] = numpy.dot(A,vel_aux)
2162
2162
2163 return velEst
2163 return velEst
2164
2164
2165 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2165 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2166
2166
2167 param = dataOut.data_param
2167 param = dataOut.data_param
2168 if dataOut.abscissaList != None:
2168 if dataOut.abscissaList != None:
2169 absc = dataOut.abscissaList[:-1]
2169 absc = dataOut.abscissaList[:-1]
2170 # noise = dataOut.noise
2170 # noise = dataOut.noise
2171 heightList = dataOut.heightList
2171 heightList = dataOut.heightList
2172 SNR = dataOut.data_snr
2172 SNR = dataOut.data_snr
2173
2173
2174 if technique == 'DBS':
2174 if technique == 'DBS':
2175
2175
2176 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2176 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2177 kwargs['heightList'] = heightList
2177 kwargs['heightList'] = heightList
2178 kwargs['SNR'] = SNR
2178 kwargs['SNR'] = SNR
2179
2179
2180 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2180 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2181 dataOut.utctimeInit = dataOut.utctime
2181 dataOut.utctimeInit = dataOut.utctime
2182 dataOut.outputInterval = dataOut.paramInterval
2182 dataOut.outputInterval = dataOut.paramInterval
2183
2183
2184 elif technique == 'SA':
2184 elif technique == 'SA':
2185
2185
2186 #Parameters
2186 #Parameters
2187 # position_x = kwargs['positionX']
2187 # position_x = kwargs['positionX']
2188 # position_y = kwargs['positionY']
2188 # position_y = kwargs['positionY']
2189 # azimuth = kwargs['azimuth']
2189 # azimuth = kwargs['azimuth']
2190 #
2190 #
2191 # if kwargs.has_key('crosspairsList'):
2191 # if kwargs.has_key('crosspairsList'):
2192 # pairs = kwargs['crosspairsList']
2192 # pairs = kwargs['crosspairsList']
2193 # else:
2193 # else:
2194 # pairs = None
2194 # pairs = None
2195 #
2195 #
2196 # if kwargs.has_key('correctFactor'):
2196 # if kwargs.has_key('correctFactor'):
2197 # correctFactor = kwargs['correctFactor']
2197 # correctFactor = kwargs['correctFactor']
2198 # else:
2198 # else:
2199 # correctFactor = 1
2199 # correctFactor = 1
2200
2200
2201 # tau = dataOut.data_param
2201 # tau = dataOut.data_param
2202 # _lambda = dataOut.C/dataOut.frequency
2202 # _lambda = dataOut.C/dataOut.frequency
2203 # pairsList = dataOut.groupList
2203 # pairsList = dataOut.groupList
2204 # nChannels = dataOut.nChannels
2204 # nChannels = dataOut.nChannels
2205
2205
2206 kwargs['groupList'] = dataOut.groupList
2206 kwargs['groupList'] = dataOut.groupList
2207 kwargs['tau'] = dataOut.data_param
2207 kwargs['tau'] = dataOut.data_param
2208 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2208 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2209 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2209 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2210 dataOut.data_output = self.techniqueSA(kwargs)
2210 dataOut.data_output = self.techniqueSA(kwargs)
2211 dataOut.utctimeInit = dataOut.utctime
2211 dataOut.utctimeInit = dataOut.utctime
2212 dataOut.outputInterval = dataOut.timeInterval
2212 dataOut.outputInterval = dataOut.timeInterval
2213
2213
2214 elif technique == 'Meteors':
2214 elif technique == 'Meteors':
2215 dataOut.flagNoData = True
2215 dataOut.flagNoData = True
2216 self.__dataReady = False
2216 self.__dataReady = False
2217
2217
2218 if 'nHours' in kwargs:
2218 if 'nHours' in kwargs:
2219 nHours = kwargs['nHours']
2219 nHours = kwargs['nHours']
2220 else:
2220 else:
2221 nHours = 1
2221 nHours = 1
2222
2222
2223 if 'meteorsPerBin' in kwargs:
2223 if 'meteorsPerBin' in kwargs:
2224 meteorThresh = kwargs['meteorsPerBin']
2224 meteorThresh = kwargs['meteorsPerBin']
2225 else:
2225 else:
2226 meteorThresh = 6
2226 meteorThresh = 6
2227
2227
2228 if 'hmin' in kwargs:
2228 if 'hmin' in kwargs:
2229 hmin = kwargs['hmin']
2229 hmin = kwargs['hmin']
2230 else: hmin = 70
2230 else: hmin = 70
2231 if 'hmax' in kwargs:
2231 if 'hmax' in kwargs:
2232 hmax = kwargs['hmax']
2232 hmax = kwargs['hmax']
2233 else: hmax = 110
2233 else: hmax = 110
2234
2234
2235 dataOut.outputInterval = nHours*3600
2235 dataOut.outputInterval = nHours*3600
2236
2236
2237 if self.__isConfig == False:
2237 if self.__isConfig == False:
2238 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2238 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2239 #Get Initial LTC time
2239 #Get Initial LTC time
2240 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2240 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2241 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2241 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2242
2242
2243 self.__isConfig = True
2243 self.__isConfig = True
2244
2244
2245 if self.__buffer is None:
2245 if self.__buffer is None:
2246 self.__buffer = dataOut.data_param
2246 self.__buffer = dataOut.data_param
2247 self.__firstdata = copy.copy(dataOut)
2247 self.__firstdata = copy.copy(dataOut)
2248
2248
2249 else:
2249 else:
2250 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2250 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2251
2251
2252 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2252 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2253
2253
2254 if self.__dataReady:
2254 if self.__dataReady:
2255 dataOut.utctimeInit = self.__initime
2255 dataOut.utctimeInit = self.__initime
2256
2256
2257 self.__initime += dataOut.outputInterval #to erase time offset
2257 self.__initime += dataOut.outputInterval #to erase time offset
2258
2258
2259 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2259 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2260 dataOut.flagNoData = False
2260 dataOut.flagNoData = False
2261 self.__buffer = None
2261 self.__buffer = None
2262
2262
2263 elif technique == 'Meteors1':
2263 elif technique == 'Meteors1':
2264 dataOut.flagNoData = True
2264 dataOut.flagNoData = True
2265 self.__dataReady = False
2265 self.__dataReady = False
2266
2266
2267 if 'nMins' in kwargs:
2267 if 'nMins' in kwargs:
2268 nMins = kwargs['nMins']
2268 nMins = kwargs['nMins']
2269 else: nMins = 20
2269 else: nMins = 20
2270 if 'rx_location' in kwargs:
2270 if 'rx_location' in kwargs:
2271 rx_location = kwargs['rx_location']
2271 rx_location = kwargs['rx_location']
2272 else: rx_location = [(0,1),(1,1),(1,0)]
2272 else: rx_location = [(0,1),(1,1),(1,0)]
2273 if 'azimuth' in kwargs:
2273 if 'azimuth' in kwargs:
2274 azimuth = kwargs['azimuth']
2274 azimuth = kwargs['azimuth']
2275 else: azimuth = 51.06
2275 else: azimuth = 51.06
2276 if 'dfactor' in kwargs:
2276 if 'dfactor' in kwargs:
2277 dfactor = kwargs['dfactor']
2277 dfactor = kwargs['dfactor']
2278 if 'mode' in kwargs:
2278 if 'mode' in kwargs:
2279 mode = kwargs['mode']
2279 mode = kwargs['mode']
2280 if 'theta_x' in kwargs:
2280 if 'theta_x' in kwargs:
2281 theta_x = kwargs['theta_x']
2281 theta_x = kwargs['theta_x']
2282 if 'theta_y' in kwargs:
2282 if 'theta_y' in kwargs:
2283 theta_y = kwargs['theta_y']
2283 theta_y = kwargs['theta_y']
2284 else: mode = 'SA'
2284 else: mode = 'SA'
2285
2285
2286 #Borrar luego esto
2286 #Borrar luego esto
2287 if dataOut.groupList is None:
2287 if dataOut.groupList is None:
2288 dataOut.groupList = [(0,1),(0,2),(1,2)]
2288 dataOut.groupList = [(0,1),(0,2),(1,2)]
2289 groupList = dataOut.groupList
2289 groupList = dataOut.groupList
2290 C = 3e8
2290 C = 3e8
2291 freq = 50e6
2291 freq = 50e6
2292 lamb = C/freq
2292 lamb = C/freq
2293 k = 2*numpy.pi/lamb
2293 k = 2*numpy.pi/lamb
2294
2294
2295 timeList = dataOut.abscissaList
2295 timeList = dataOut.abscissaList
2296 heightList = dataOut.heightList
2296 heightList = dataOut.heightList
2297
2297
2298 if self.__isConfig == False:
2298 if self.__isConfig == False:
2299 dataOut.outputInterval = nMins*60
2299 dataOut.outputInterval = nMins*60
2300 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2300 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2301 #Get Initial LTC time
2301 #Get Initial LTC time
2302 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2302 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2303 minuteAux = initime.minute
2303 minuteAux = initime.minute
2304 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2304 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2305 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2305 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2306
2306
2307 self.__isConfig = True
2307 self.__isConfig = True
2308
2308
2309 if self.__buffer is None:
2309 if self.__buffer is None:
2310 self.__buffer = dataOut.data_param
2310 self.__buffer = dataOut.data_param
2311 self.__firstdata = copy.copy(dataOut)
2311 self.__firstdata = copy.copy(dataOut)
2312
2312
2313 else:
2313 else:
2314 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2314 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2315
2315
2316 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2316 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2317
2317
2318 if self.__dataReady:
2318 if self.__dataReady:
2319 dataOut.utctimeInit = self.__initime
2319 dataOut.utctimeInit = self.__initime
2320 self.__initime += dataOut.outputInterval #to erase time offset
2320 self.__initime += dataOut.outputInterval #to erase time offset
2321
2321
2322 metArray = self.__buffer
2322 metArray = self.__buffer
2323 if mode == 'SA':
2323 if mode == 'SA':
2324 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2324 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2325 elif mode == 'DBS':
2325 elif mode == 'DBS':
2326 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2326 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2327 dataOut.data_output = dataOut.data_output.T
2327 dataOut.data_output = dataOut.data_output.T
2328 dataOut.flagNoData = False
2328 dataOut.flagNoData = False
2329 self.__buffer = None
2329 self.__buffer = None
2330
2330
2331 return
2331 return
2332
2332
2333 class EWDriftsEstimation(Operation):
2333 class EWDriftsEstimation(Operation):
2334
2334
2335 def __init__(self):
2335 def __init__(self):
2336 Operation.__init__(self)
2336 Operation.__init__(self)
2337
2337
2338 def __correctValues(self, heiRang, phi, velRadial, SNR):
2338 def __correctValues(self, heiRang, phi, velRadial, SNR):
2339 listPhi = phi.tolist()
2339 listPhi = phi.tolist()
2340 maxid = listPhi.index(max(listPhi))
2340 maxid = listPhi.index(max(listPhi))
2341 minid = listPhi.index(min(listPhi))
2341 minid = listPhi.index(min(listPhi))
2342
2342
2343 rango = list(range(len(phi)))
2343 rango = list(range(len(phi)))
2344 # rango = numpy.delete(rango,maxid)
2344 # rango = numpy.delete(rango,maxid)
2345
2345
2346 heiRang1 = heiRang*math.cos(phi[maxid])
2346 heiRang1 = heiRang*math.cos(phi[maxid])
2347 heiRangAux = heiRang*math.cos(phi[minid])
2347 heiRangAux = heiRang*math.cos(phi[minid])
2348 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2348 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2349 heiRang1 = numpy.delete(heiRang1,indOut)
2349 heiRang1 = numpy.delete(heiRang1,indOut)
2350
2350
2351 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2351 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2352 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2352 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2353
2353
2354 for i in rango:
2354 for i in rango:
2355 x = heiRang*math.cos(phi[i])
2355 x = heiRang*math.cos(phi[i])
2356 y1 = velRadial[i,:]
2356 y1 = velRadial[i,:]
2357 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2357 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2358
2358
2359 x1 = heiRang1
2359 x1 = heiRang1
2360 y11 = f1(x1)
2360 y11 = f1(x1)
2361
2361
2362 y2 = SNR[i,:]
2362 y2 = SNR[i,:]
2363 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2363 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2364 y21 = f2(x1)
2364 y21 = f2(x1)
2365
2365
2366 velRadial1[i,:] = y11
2366 velRadial1[i,:] = y11
2367 SNR1[i,:] = y21
2367 SNR1[i,:] = y21
2368
2368
2369 return heiRang1, velRadial1, SNR1
2369 return heiRang1, velRadial1, SNR1
2370
2370
2371 def run(self, dataOut, zenith, zenithCorrection):
2371 def run(self, dataOut, zenith, zenithCorrection):
2372 heiRang = dataOut.heightList
2372 heiRang = dataOut.heightList
2373 velRadial = dataOut.data_param[:,3,:]
2373 velRadial = dataOut.data_param[:,3,:]
2374 SNR = dataOut.data_snr
2374 SNR = dataOut.data_snr
2375
2375
2376 zenith = numpy.array(zenith)
2376 zenith = numpy.array(zenith)
2377 zenith -= zenithCorrection
2377 zenith -= zenithCorrection
2378 zenith *= numpy.pi/180
2378 zenith *= numpy.pi/180
2379
2379
2380 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2380 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2381
2381
2382 alp = zenith[0]
2382 alp = zenith[0]
2383 bet = zenith[1]
2383 bet = zenith[1]
2384
2384
2385 w_w = velRadial1[0,:]
2385 w_w = velRadial1[0,:]
2386 w_e = velRadial1[1,:]
2386 w_e = velRadial1[1,:]
2387
2387
2388 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2388 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2389 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2389 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2390
2390
2391 winds = numpy.vstack((u,w))
2391 winds = numpy.vstack((u,w))
2392
2392
2393 dataOut.heightList = heiRang1
2393 dataOut.heightList = heiRang1
2394 dataOut.data_output = winds
2394 dataOut.data_output = winds
2395 dataOut.data_snr = SNR1
2395 dataOut.data_snr = SNR1
2396
2396
2397 dataOut.utctimeInit = dataOut.utctime
2397 dataOut.utctimeInit = dataOut.utctime
2398 dataOut.outputInterval = dataOut.timeInterval
2398 dataOut.outputInterval = dataOut.timeInterval
2399 return
2399 return
2400
2400
2401 #--------------- Non Specular Meteor ----------------
2401 #--------------- Non Specular Meteor ----------------
2402
2402
2403 class NonSpecularMeteorDetection(Operation):
2403 class NonSpecularMeteorDetection(Operation):
2404
2404
2405 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2405 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2406 data_acf = dataOut.data_pre[0]
2406 data_acf = dataOut.data_pre[0]
2407 data_ccf = dataOut.data_pre[1]
2407 data_ccf = dataOut.data_pre[1]
2408 pairsList = dataOut.groupList[1]
2408 pairsList = dataOut.groupList[1]
2409
2409
2410 lamb = dataOut.C/dataOut.frequency
2410 lamb = dataOut.C/dataOut.frequency
2411 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2411 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2412 paramInterval = dataOut.paramInterval
2412 paramInterval = dataOut.paramInterval
2413
2413
2414 nChannels = data_acf.shape[0]
2414 nChannels = data_acf.shape[0]
2415 nLags = data_acf.shape[1]
2415 nLags = data_acf.shape[1]
2416 nProfiles = data_acf.shape[2]
2416 nProfiles = data_acf.shape[2]
2417 nHeights = dataOut.nHeights
2417 nHeights = dataOut.nHeights
2418 nCohInt = dataOut.nCohInt
2418 nCohInt = dataOut.nCohInt
2419 sec = numpy.round(nProfiles/dataOut.paramInterval)
2419 sec = numpy.round(nProfiles/dataOut.paramInterval)
2420 heightList = dataOut.heightList
2420 heightList = dataOut.heightList
2421 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2421 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2422 utctime = dataOut.utctime
2422 utctime = dataOut.utctime
2423
2423
2424 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2424 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2425
2425
2426 #------------------------ SNR --------------------------------------
2426 #------------------------ SNR --------------------------------------
2427 power = data_acf[:,0,:,:].real
2427 power = data_acf[:,0,:,:].real
2428 noise = numpy.zeros(nChannels)
2428 noise = numpy.zeros(nChannels)
2429 SNR = numpy.zeros(power.shape)
2429 SNR = numpy.zeros(power.shape)
2430 for i in range(nChannels):
2430 for i in range(nChannels):
2431 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2431 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2432 SNR[i] = (power[i]-noise[i])/noise[i]
2432 SNR[i] = (power[i]-noise[i])/noise[i]
2433 SNRm = numpy.nanmean(SNR, axis = 0)
2433 SNRm = numpy.nanmean(SNR, axis = 0)
2434 SNRdB = 10*numpy.log10(SNR)
2434 SNRdB = 10*numpy.log10(SNR)
2435
2435
2436 if mode == 'SA':
2436 if mode == 'SA':
2437 dataOut.groupList = dataOut.groupList[1]
2437 dataOut.groupList = dataOut.groupList[1]
2438 nPairs = data_ccf.shape[0]
2438 nPairs = data_ccf.shape[0]
2439 #---------------------- Coherence and Phase --------------------------
2439 #---------------------- Coherence and Phase --------------------------
2440 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2440 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2441 # phase1 = numpy.copy(phase)
2441 # phase1 = numpy.copy(phase)
2442 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2442 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2443
2443
2444 for p in range(nPairs):
2444 for p in range(nPairs):
2445 ch0 = pairsList[p][0]
2445 ch0 = pairsList[p][0]
2446 ch1 = pairsList[p][1]
2446 ch1 = pairsList[p][1]
2447 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2447 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2448 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2448 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2449 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2449 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2450 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2450 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2451 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2451 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2452 coh = numpy.nanmax(coh1, axis = 0)
2452 coh = numpy.nanmax(coh1, axis = 0)
2453 # struc = numpy.ones((5,1))
2453 # struc = numpy.ones((5,1))
2454 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2454 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2455 #---------------------- Radial Velocity ----------------------------
2455 #---------------------- Radial Velocity ----------------------------
2456 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2456 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2457 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2457 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2458
2458
2459 if allData:
2459 if allData:
2460 boolMetFin = ~numpy.isnan(SNRm)
2460 boolMetFin = ~numpy.isnan(SNRm)
2461 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2461 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2462 else:
2462 else:
2463 #------------------------ Meteor mask ---------------------------------
2463 #------------------------ Meteor mask ---------------------------------
2464 # #SNR mask
2464 # #SNR mask
2465 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2465 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2466 #
2466 #
2467 # #Erase small objects
2467 # #Erase small objects
2468 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2468 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2469 #
2469 #
2470 # auxEEJ = numpy.sum(boolMet1,axis=0)
2470 # auxEEJ = numpy.sum(boolMet1,axis=0)
2471 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2471 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2472 # indEEJ = numpy.where(indOver)[0]
2472 # indEEJ = numpy.where(indOver)[0]
2473 # indNEEJ = numpy.where(~indOver)[0]
2473 # indNEEJ = numpy.where(~indOver)[0]
2474 #
2474 #
2475 # boolMetFin = boolMet1
2475 # boolMetFin = boolMet1
2476 #
2476 #
2477 # if indEEJ.size > 0:
2477 # if indEEJ.size > 0:
2478 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2478 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2479 #
2479 #
2480 # boolMet2 = coh > cohThresh
2480 # boolMet2 = coh > cohThresh
2481 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2481 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2482 #
2482 #
2483 # #Final Meteor mask
2483 # #Final Meteor mask
2484 # boolMetFin = boolMet1|boolMet2
2484 # boolMetFin = boolMet1|boolMet2
2485
2485
2486 #Coherence mask
2486 #Coherence mask
2487 boolMet1 = coh > 0.75
2487 boolMet1 = coh > 0.75
2488 struc = numpy.ones((30,1))
2488 struc = numpy.ones((30,1))
2489 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2489 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2490
2490
2491 #Derivative mask
2491 #Derivative mask
2492 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2492 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2493 boolMet2 = derPhase < 0.2
2493 boolMet2 = derPhase < 0.2
2494 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2494 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2495 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2495 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2496 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2496 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2497 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2497 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2498 # #Final mask
2498 # #Final mask
2499 # boolMetFin = boolMet2
2499 # boolMetFin = boolMet2
2500 boolMetFin = boolMet1&boolMet2
2500 boolMetFin = boolMet1&boolMet2
2501 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2501 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2502 #Creating data_param
2502 #Creating data_param
2503 coordMet = numpy.where(boolMetFin)
2503 coordMet = numpy.where(boolMetFin)
2504
2504
2505 tmet = coordMet[0]
2505 tmet = coordMet[0]
2506 hmet = coordMet[1]
2506 hmet = coordMet[1]
2507
2507
2508 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2508 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2509 data_param[:,0] = utctime
2509 data_param[:,0] = utctime
2510 data_param[:,1] = tmet
2510 data_param[:,1] = tmet
2511 data_param[:,2] = hmet
2511 data_param[:,2] = hmet
2512 data_param[:,3] = SNRm[tmet,hmet]
2512 data_param[:,3] = SNRm[tmet,hmet]
2513 data_param[:,4] = velRad[tmet,hmet]
2513 data_param[:,4] = velRad[tmet,hmet]
2514 data_param[:,5] = coh[tmet,hmet]
2514 data_param[:,5] = coh[tmet,hmet]
2515 data_param[:,6:] = phase[:,tmet,hmet].T
2515 data_param[:,6:] = phase[:,tmet,hmet].T
2516
2516
2517 elif mode == 'DBS':
2517 elif mode == 'DBS':
2518 dataOut.groupList = numpy.arange(nChannels)
2518 dataOut.groupList = numpy.arange(nChannels)
2519
2519
2520 #Radial Velocities
2520 #Radial Velocities
2521 phase = numpy.angle(data_acf[:,1,:,:])
2521 phase = numpy.angle(data_acf[:,1,:,:])
2522 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2522 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2523 velRad = phase*lamb/(4*numpy.pi*tSamp)
2523 velRad = phase*lamb/(4*numpy.pi*tSamp)
2524
2524
2525 #Spectral width
2525 #Spectral width
2526 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2526 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2527 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2527 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2528 acf1 = data_acf[:,1,:,:]
2528 acf1 = data_acf[:,1,:,:]
2529 acf2 = data_acf[:,2,:,:]
2529 acf2 = data_acf[:,2,:,:]
2530
2530
2531 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2531 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2532 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2532 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2533 if allData:
2533 if allData:
2534 boolMetFin = ~numpy.isnan(SNRdB)
2534 boolMetFin = ~numpy.isnan(SNRdB)
2535 else:
2535 else:
2536 #SNR
2536 #SNR
2537 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2537 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2538 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2538 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2539
2539
2540 #Radial velocity
2540 #Radial velocity
2541 boolMet2 = numpy.abs(velRad) < 20
2541 boolMet2 = numpy.abs(velRad) < 20
2542 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2542 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2543
2543
2544 #Spectral Width
2544 #Spectral Width
2545 boolMet3 = spcWidth < 30
2545 boolMet3 = spcWidth < 30
2546 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2546 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2547 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2547 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2548 boolMetFin = boolMet1&boolMet2&boolMet3
2548 boolMetFin = boolMet1&boolMet2&boolMet3
2549
2549
2550 #Creating data_param
2550 #Creating data_param
2551 coordMet = numpy.where(boolMetFin)
2551 coordMet = numpy.where(boolMetFin)
2552
2552
2553 cmet = coordMet[0]
2553 cmet = coordMet[0]
2554 tmet = coordMet[1]
2554 tmet = coordMet[1]
2555 hmet = coordMet[2]
2555 hmet = coordMet[2]
2556
2556
2557 data_param = numpy.zeros((tmet.size, 7))
2557 data_param = numpy.zeros((tmet.size, 7))
2558 data_param[:,0] = utctime
2558 data_param[:,0] = utctime
2559 data_param[:,1] = cmet
2559 data_param[:,1] = cmet
2560 data_param[:,2] = tmet
2560 data_param[:,2] = tmet
2561 data_param[:,3] = hmet
2561 data_param[:,3] = hmet
2562 data_param[:,4] = SNR[cmet,tmet,hmet].T
2562 data_param[:,4] = SNR[cmet,tmet,hmet].T
2563 data_param[:,5] = velRad[cmet,tmet,hmet].T
2563 data_param[:,5] = velRad[cmet,tmet,hmet].T
2564 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2564 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2565
2565
2566 # self.dataOut.data_param = data_int
2566 # self.dataOut.data_param = data_int
2567 if len(data_param) == 0:
2567 if len(data_param) == 0:
2568 dataOut.flagNoData = True
2568 dataOut.flagNoData = True
2569 else:
2569 else:
2570 dataOut.data_param = data_param
2570 dataOut.data_param = data_param
2571
2571
2572 def __erase_small(self, binArray, threshX, threshY):
2572 def __erase_small(self, binArray, threshX, threshY):
2573 labarray, numfeat = ndimage.measurements.label(binArray)
2573 labarray, numfeat = ndimage.measurements.label(binArray)
2574 binArray1 = numpy.copy(binArray)
2574 binArray1 = numpy.copy(binArray)
2575
2575
2576 for i in range(1,numfeat + 1):
2576 for i in range(1,numfeat + 1):
2577 auxBin = (labarray==i)
2577 auxBin = (labarray==i)
2578 auxSize = auxBin.sum()
2578 auxSize = auxBin.sum()
2579
2579
2580 x,y = numpy.where(auxBin)
2580 x,y = numpy.where(auxBin)
2581 widthX = x.max() - x.min()
2581 widthX = x.max() - x.min()
2582 widthY = y.max() - y.min()
2582 widthY = y.max() - y.min()
2583
2583
2584 #width X: 3 seg -> 12.5*3
2584 #width X: 3 seg -> 12.5*3
2585 #width Y:
2585 #width Y:
2586
2586
2587 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2587 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2588 binArray1[auxBin] = False
2588 binArray1[auxBin] = False
2589
2589
2590 return binArray1
2590 return binArray1
2591
2591
2592 #--------------- Specular Meteor ----------------
2592 #--------------- Specular Meteor ----------------
2593
2593
2594 class SMDetection(Operation):
2594 class SMDetection(Operation):
2595 '''
2595 '''
2596 Function DetectMeteors()
2596 Function DetectMeteors()
2597 Project developed with paper:
2597 Project developed with paper:
2598 HOLDSWORTH ET AL. 2004
2598 HOLDSWORTH ET AL. 2004
2599
2599
2600 Input:
2600 Input:
2601 self.dataOut.data_pre
2601 self.dataOut.data_pre
2602
2602
2603 centerReceiverIndex: From the channels, which is the center receiver
2603 centerReceiverIndex: From the channels, which is the center receiver
2604
2604
2605 hei_ref: Height reference for the Beacon signal extraction
2605 hei_ref: Height reference for the Beacon signal extraction
2606 tauindex:
2606 tauindex:
2607 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2607 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2608
2608
2609 cohDetection: Whether to user Coherent detection or not
2609 cohDetection: Whether to user Coherent detection or not
2610 cohDet_timeStep: Coherent Detection calculation time step
2610 cohDet_timeStep: Coherent Detection calculation time step
2611 cohDet_thresh: Coherent Detection phase threshold to correct phases
2611 cohDet_thresh: Coherent Detection phase threshold to correct phases
2612
2612
2613 noise_timeStep: Noise calculation time step
2613 noise_timeStep: Noise calculation time step
2614 noise_multiple: Noise multiple to define signal threshold
2614 noise_multiple: Noise multiple to define signal threshold
2615
2615
2616 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2616 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2617 multDet_rangeLimit: Multiple Detection Removal range limit in km
2617 multDet_rangeLimit: Multiple Detection Removal range limit in km
2618
2618
2619 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2619 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2620 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2620 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2621
2621
2622 hmin: Minimum Height of the meteor to use it in the further wind estimations
2622 hmin: Minimum Height of the meteor to use it in the further wind estimations
2623 hmax: Maximum Height of the meteor to use it in the further wind estimations
2623 hmax: Maximum Height of the meteor to use it in the further wind estimations
2624 azimuth: Azimuth angle correction
2624 azimuth: Azimuth angle correction
2625
2625
2626 Affected:
2626 Affected:
2627 self.dataOut.data_param
2627 self.dataOut.data_param
2628
2628
2629 Rejection Criteria (Errors):
2629 Rejection Criteria (Errors):
2630 0: No error; analysis OK
2630 0: No error; analysis OK
2631 1: SNR < SNR threshold
2631 1: SNR < SNR threshold
2632 2: angle of arrival (AOA) ambiguously determined
2632 2: angle of arrival (AOA) ambiguously determined
2633 3: AOA estimate not feasible
2633 3: AOA estimate not feasible
2634 4: Large difference in AOAs obtained from different antenna baselines
2634 4: Large difference in AOAs obtained from different antenna baselines
2635 5: echo at start or end of time series
2635 5: echo at start or end of time series
2636 6: echo less than 5 examples long; too short for analysis
2636 6: echo less than 5 examples long; too short for analysis
2637 7: echo rise exceeds 0.3s
2637 7: echo rise exceeds 0.3s
2638 8: echo decay time less than twice rise time
2638 8: echo decay time less than twice rise time
2639 9: large power level before echo
2639 9: large power level before echo
2640 10: large power level after echo
2640 10: large power level after echo
2641 11: poor fit to amplitude for estimation of decay time
2641 11: poor fit to amplitude for estimation of decay time
2642 12: poor fit to CCF phase variation for estimation of radial drift velocity
2642 12: poor fit to CCF phase variation for estimation of radial drift velocity
2643 13: height unresolvable echo: not valid height within 70 to 110 km
2643 13: height unresolvable echo: not valid height within 70 to 110 km
2644 14: height ambiguous echo: more then one possible height within 70 to 110 km
2644 14: height ambiguous echo: more then one possible height within 70 to 110 km
2645 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2645 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2646 16: oscilatory echo, indicating event most likely not an underdense echo
2646 16: oscilatory echo, indicating event most likely not an underdense echo
2647
2647
2648 17: phase difference in meteor Reestimation
2648 17: phase difference in meteor Reestimation
2649
2649
2650 Data Storage:
2650 Data Storage:
2651 Meteors for Wind Estimation (8):
2651 Meteors for Wind Estimation (8):
2652 Utc Time | Range Height
2652 Utc Time | Range Height
2653 Azimuth Zenith errorCosDir
2653 Azimuth Zenith errorCosDir
2654 VelRad errorVelRad
2654 VelRad errorVelRad
2655 Phase0 Phase1 Phase2 Phase3
2655 Phase0 Phase1 Phase2 Phase3
2656 TypeError
2656 TypeError
2657
2657
2658 '''
2658 '''
2659
2659
2660 def run(self, dataOut, hei_ref = None, tauindex = 0,
2660 def run(self, dataOut, hei_ref = None, tauindex = 0,
2661 phaseOffsets = None,
2661 phaseOffsets = None,
2662 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2662 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2663 noise_timeStep = 4, noise_multiple = 4,
2663 noise_timeStep = 4, noise_multiple = 4,
2664 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2664 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2665 phaseThresh = 20, SNRThresh = 5,
2665 phaseThresh = 20, SNRThresh = 5,
2666 hmin = 50, hmax=150, azimuth = 0,
2666 hmin = 50, hmax=150, azimuth = 0,
2667 channelPositions = None) :
2667 channelPositions = None) :
2668
2668
2669
2669
2670 #Getting Pairslist
2670 #Getting Pairslist
2671 if channelPositions is None:
2671 if channelPositions is None:
2672 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2672 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2673 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2673 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2674 meteorOps = SMOperations()
2674 meteorOps = SMOperations()
2675 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2675 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2676 heiRang = dataOut.heightList
2676 heiRang = dataOut.heightList
2677 #Get Beacon signal - No Beacon signal anymore
2677 #Get Beacon signal - No Beacon signal anymore
2678 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2678 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2679 #
2679 #
2680 # if hei_ref != None:
2680 # if hei_ref != None:
2681 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2681 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2682 #
2682 #
2683
2683
2684
2684
2685 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2685 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2686 # see if the user put in pre defined phase shifts
2686 # see if the user put in pre defined phase shifts
2687 voltsPShift = dataOut.data_pre.copy()
2687 voltsPShift = dataOut.data_pre.copy()
2688
2688
2689 # if predefinedPhaseShifts != None:
2689 # if predefinedPhaseShifts != None:
2690 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2690 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2691 #
2691 #
2692 # # elif beaconPhaseShifts:
2692 # # elif beaconPhaseShifts:
2693 # # #get hardware phase shifts using beacon signal
2693 # # #get hardware phase shifts using beacon signal
2694 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2694 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2695 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2695 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2696 #
2696 #
2697 # else:
2697 # else:
2698 # hardwarePhaseShifts = numpy.zeros(5)
2698 # hardwarePhaseShifts = numpy.zeros(5)
2699 #
2699 #
2700 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2700 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2701 # for i in range(self.dataOut.data_pre.shape[0]):
2701 # for i in range(self.dataOut.data_pre.shape[0]):
2702 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2702 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2703
2703
2704 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2704 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2705
2705
2706 #Remove DC
2706 #Remove DC
2707 voltsDC = numpy.mean(voltsPShift,1)
2707 voltsDC = numpy.mean(voltsPShift,1)
2708 voltsDC = numpy.mean(voltsDC,1)
2708 voltsDC = numpy.mean(voltsDC,1)
2709 for i in range(voltsDC.shape[0]):
2709 for i in range(voltsDC.shape[0]):
2710 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2710 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2711
2711
2712 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2712 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2713 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2713 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2714
2714
2715 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2715 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2716 #Coherent Detection
2716 #Coherent Detection
2717 if cohDetection:
2717 if cohDetection:
2718 #use coherent detection to get the net power
2718 #use coherent detection to get the net power
2719 cohDet_thresh = cohDet_thresh*numpy.pi/180
2719 cohDet_thresh = cohDet_thresh*numpy.pi/180
2720 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2720 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2721
2721
2722 #Non-coherent detection!
2722 #Non-coherent detection!
2723 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2723 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2724 #********** END OF COH/NON-COH POWER CALCULATION**********************
2724 #********** END OF COH/NON-COH POWER CALCULATION**********************
2725
2725
2726 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2726 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2727 #Get noise
2727 #Get noise
2728 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2728 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2729 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2729 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2730 #Get signal threshold
2730 #Get signal threshold
2731 signalThresh = noise_multiple*noise
2731 signalThresh = noise_multiple*noise
2732 #Meteor echoes detection
2732 #Meteor echoes detection
2733 listMeteors = self.__findMeteors(powerNet, signalThresh)
2733 listMeteors = self.__findMeteors(powerNet, signalThresh)
2734 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2734 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2735
2735
2736 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2736 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2737 #Parameters
2737 #Parameters
2738 heiRange = dataOut.heightList
2738 heiRange = dataOut.heightList
2739 rangeInterval = heiRange[1] - heiRange[0]
2739 rangeInterval = heiRange[1] - heiRange[0]
2740 rangeLimit = multDet_rangeLimit/rangeInterval
2740 rangeLimit = multDet_rangeLimit/rangeInterval
2741 timeLimit = multDet_timeLimit/dataOut.timeInterval
2741 timeLimit = multDet_timeLimit/dataOut.timeInterval
2742 #Multiple detection removals
2742 #Multiple detection removals
2743 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2743 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2744 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2744 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2745
2745
2746 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2746 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2747 #Parameters
2747 #Parameters
2748 phaseThresh = phaseThresh*numpy.pi/180
2748 phaseThresh = phaseThresh*numpy.pi/180
2749 thresh = [phaseThresh, noise_multiple, SNRThresh]
2749 thresh = [phaseThresh, noise_multiple, SNRThresh]
2750 #Meteor reestimation (Errors N 1, 6, 12, 17)
2750 #Meteor reestimation (Errors N 1, 6, 12, 17)
2751 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2751 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2752 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2752 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2753 #Estimation of decay times (Errors N 7, 8, 11)
2753 #Estimation of decay times (Errors N 7, 8, 11)
2754 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2754 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2755 #******************* END OF METEOR REESTIMATION *******************
2755 #******************* END OF METEOR REESTIMATION *******************
2756
2756
2757 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2757 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2758 #Calculating Radial Velocity (Error N 15)
2758 #Calculating Radial Velocity (Error N 15)
2759 radialStdThresh = 10
2759 radialStdThresh = 10
2760 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2760 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2761
2761
2762 if len(listMeteors4) > 0:
2762 if len(listMeteors4) > 0:
2763 #Setting New Array
2763 #Setting New Array
2764 date = dataOut.utctime
2764 date = dataOut.utctime
2765 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2765 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2766
2766
2767 #Correcting phase offset
2767 #Correcting phase offset
2768 if phaseOffsets != None:
2768 if phaseOffsets != None:
2769 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2769 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2770 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2770 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2771
2771
2772 #Second Pairslist
2772 #Second Pairslist
2773 pairsList = []
2773 pairsList = []
2774 pairx = (0,1)
2774 pairx = (0,1)
2775 pairy = (2,3)
2775 pairy = (2,3)
2776 pairsList.append(pairx)
2776 pairsList.append(pairx)
2777 pairsList.append(pairy)
2777 pairsList.append(pairy)
2778
2778
2779 jph = numpy.array([0,0,0,0])
2779 jph = numpy.array([0,0,0,0])
2780 h = (hmin,hmax)
2780 h = (hmin,hmax)
2781 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2781 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2782
2782
2783 # #Calculate AOA (Error N 3, 4)
2783 # #Calculate AOA (Error N 3, 4)
2784 # #JONES ET AL. 1998
2784 # #JONES ET AL. 1998
2785 # error = arrayParameters[:,-1]
2785 # error = arrayParameters[:,-1]
2786 # AOAthresh = numpy.pi/8
2786 # AOAthresh = numpy.pi/8
2787 # phases = -arrayParameters[:,9:13]
2787 # phases = -arrayParameters[:,9:13]
2788 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2788 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2789 #
2789 #
2790 # #Calculate Heights (Error N 13 and 14)
2790 # #Calculate Heights (Error N 13 and 14)
2791 # error = arrayParameters[:,-1]
2791 # error = arrayParameters[:,-1]
2792 # Ranges = arrayParameters[:,2]
2792 # Ranges = arrayParameters[:,2]
2793 # zenith = arrayParameters[:,5]
2793 # zenith = arrayParameters[:,5]
2794 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2794 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2795 # error = arrayParameters[:,-1]
2795 # error = arrayParameters[:,-1]
2796 #********************* END OF PARAMETERS CALCULATION **************************
2796 #********************* END OF PARAMETERS CALCULATION **************************
2797
2797
2798 #***************************+ PASS DATA TO NEXT STEP **********************
2798 #***************************+ PASS DATA TO NEXT STEP **********************
2799 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2799 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2800 dataOut.data_param = arrayParameters
2800 dataOut.data_param = arrayParameters
2801
2801
2802 if arrayParameters is None:
2802 if arrayParameters is None:
2803 dataOut.flagNoData = True
2803 dataOut.flagNoData = True
2804 else:
2804 else:
2805 dataOut.flagNoData = True
2805 dataOut.flagNoData = True
2806
2806
2807 return
2807 return
2808
2808
2809 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2809 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2810
2810
2811 minIndex = min(newheis[0])
2811 minIndex = min(newheis[0])
2812 maxIndex = max(newheis[0])
2812 maxIndex = max(newheis[0])
2813
2813
2814 voltage = voltage0[:,:,minIndex:maxIndex+1]
2814 voltage = voltage0[:,:,minIndex:maxIndex+1]
2815 nLength = voltage.shape[1]/n
2815 nLength = voltage.shape[1]/n
2816 nMin = 0
2816 nMin = 0
2817 nMax = 0
2817 nMax = 0
2818 phaseOffset = numpy.zeros((len(pairslist),n))
2818 phaseOffset = numpy.zeros((len(pairslist),n))
2819
2819
2820 for i in range(n):
2820 for i in range(n):
2821 nMax += nLength
2821 nMax += nLength
2822 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2822 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2823 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2823 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2824 phaseOffset[:,i] = phaseCCF.transpose()
2824 phaseOffset[:,i] = phaseCCF.transpose()
2825 nMin = nMax
2825 nMin = nMax
2826 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2826 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2827
2827
2828 #Remove Outliers
2828 #Remove Outliers
2829 factor = 2
2829 factor = 2
2830 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2830 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2831 dw = numpy.std(wt,axis = 1)
2831 dw = numpy.std(wt,axis = 1)
2832 dw = dw.reshape((dw.size,1))
2832 dw = dw.reshape((dw.size,1))
2833 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2833 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2834 phaseOffset[ind] = numpy.nan
2834 phaseOffset[ind] = numpy.nan
2835 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2835 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2836
2836
2837 return phaseOffset
2837 return phaseOffset
2838
2838
2839 def __shiftPhase(self, data, phaseShift):
2839 def __shiftPhase(self, data, phaseShift):
2840 #this will shift the phase of a complex number
2840 #this will shift the phase of a complex number
2841 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2841 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2842 return dataShifted
2842 return dataShifted
2843
2843
2844 def __estimatePhaseDifference(self, array, pairslist):
2844 def __estimatePhaseDifference(self, array, pairslist):
2845 nChannel = array.shape[0]
2845 nChannel = array.shape[0]
2846 nHeights = array.shape[2]
2846 nHeights = array.shape[2]
2847 numPairs = len(pairslist)
2847 numPairs = len(pairslist)
2848 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2848 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2849 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2849 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2850
2850
2851 #Correct phases
2851 #Correct phases
2852 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2852 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2853 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2853 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2854
2854
2855 if indDer[0].shape[0] > 0:
2855 if indDer[0].shape[0] > 0:
2856 for i in range(indDer[0].shape[0]):
2856 for i in range(indDer[0].shape[0]):
2857 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2857 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2858 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2858 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2859
2859
2860 # for j in range(numSides):
2860 # for j in range(numSides):
2861 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2861 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2862 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2862 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2863 #
2863 #
2864 #Linear
2864 #Linear
2865 phaseInt = numpy.zeros((numPairs,1))
2865 phaseInt = numpy.zeros((numPairs,1))
2866 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2866 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2867 for j in range(numPairs):
2867 for j in range(numPairs):
2868 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2868 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2869 phaseInt[j] = fit[1]
2869 phaseInt[j] = fit[1]
2870 #Phase Differences
2870 #Phase Differences
2871 phaseDiff = phaseInt - phaseCCF[:,2,:]
2871 phaseDiff = phaseInt - phaseCCF[:,2,:]
2872 phaseArrival = phaseInt.reshape(phaseInt.size)
2872 phaseArrival = phaseInt.reshape(phaseInt.size)
2873
2873
2874 #Dealias
2874 #Dealias
2875 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2875 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2876 # indAlias = numpy.where(phaseArrival > numpy.pi)
2876 # indAlias = numpy.where(phaseArrival > numpy.pi)
2877 # phaseArrival[indAlias] -= 2*numpy.pi
2877 # phaseArrival[indAlias] -= 2*numpy.pi
2878 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2878 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2879 # phaseArrival[indAlias] += 2*numpy.pi
2879 # phaseArrival[indAlias] += 2*numpy.pi
2880
2880
2881 return phaseDiff, phaseArrival
2881 return phaseDiff, phaseArrival
2882
2882
2883 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2883 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2884 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2884 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2885 #find the phase shifts of each channel over 1 second intervals
2885 #find the phase shifts of each channel over 1 second intervals
2886 #only look at ranges below the beacon signal
2886 #only look at ranges below the beacon signal
2887 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2887 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2888 numBlocks = int(volts.shape[1]/numProfPerBlock)
2888 numBlocks = int(volts.shape[1]/numProfPerBlock)
2889 numHeights = volts.shape[2]
2889 numHeights = volts.shape[2]
2890 nChannel = volts.shape[0]
2890 nChannel = volts.shape[0]
2891 voltsCohDet = volts.copy()
2891 voltsCohDet = volts.copy()
2892
2892
2893 pairsarray = numpy.array(pairslist)
2893 pairsarray = numpy.array(pairslist)
2894 indSides = pairsarray[:,1]
2894 indSides = pairsarray[:,1]
2895 # indSides = numpy.array(range(nChannel))
2895 # indSides = numpy.array(range(nChannel))
2896 # indSides = numpy.delete(indSides, indCenter)
2896 # indSides = numpy.delete(indSides, indCenter)
2897 #
2897 #
2898 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2898 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2899 listBlocks = numpy.array_split(volts, numBlocks, 1)
2899 listBlocks = numpy.array_split(volts, numBlocks, 1)
2900
2900
2901 startInd = 0
2901 startInd = 0
2902 endInd = 0
2902 endInd = 0
2903
2903
2904 for i in range(numBlocks):
2904 for i in range(numBlocks):
2905 startInd = endInd
2905 startInd = endInd
2906 endInd = endInd + listBlocks[i].shape[1]
2906 endInd = endInd + listBlocks[i].shape[1]
2907
2907
2908 arrayBlock = listBlocks[i]
2908 arrayBlock = listBlocks[i]
2909 # arrayBlockCenter = listCenter[i]
2909 # arrayBlockCenter = listCenter[i]
2910
2910
2911 #Estimate the Phase Difference
2911 #Estimate the Phase Difference
2912 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2912 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2913 #Phase Difference RMS
2913 #Phase Difference RMS
2914 arrayPhaseRMS = numpy.abs(phaseDiff)
2914 arrayPhaseRMS = numpy.abs(phaseDiff)
2915 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2915 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2916 indPhase = numpy.where(phaseRMSaux==4)
2916 indPhase = numpy.where(phaseRMSaux==4)
2917 #Shifting
2917 #Shifting
2918 if indPhase[0].shape[0] > 0:
2918 if indPhase[0].shape[0] > 0:
2919 for j in range(indSides.size):
2919 for j in range(indSides.size):
2920 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2920 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2921 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2921 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2922
2922
2923 return voltsCohDet
2923 return voltsCohDet
2924
2924
2925 def __calculateCCF(self, volts, pairslist ,laglist):
2925 def __calculateCCF(self, volts, pairslist ,laglist):
2926
2926
2927 nHeights = volts.shape[2]
2927 nHeights = volts.shape[2]
2928 nPoints = volts.shape[1]
2928 nPoints = volts.shape[1]
2929 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2929 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2930
2930
2931 for i in range(len(pairslist)):
2931 for i in range(len(pairslist)):
2932 volts1 = volts[pairslist[i][0]]
2932 volts1 = volts[pairslist[i][0]]
2933 volts2 = volts[pairslist[i][1]]
2933 volts2 = volts[pairslist[i][1]]
2934
2934
2935 for t in range(len(laglist)):
2935 for t in range(len(laglist)):
2936 idxT = laglist[t]
2936 idxT = laglist[t]
2937 if idxT >= 0:
2937 if idxT >= 0:
2938 vStacked = numpy.vstack((volts2[idxT:,:],
2938 vStacked = numpy.vstack((volts2[idxT:,:],
2939 numpy.zeros((idxT, nHeights),dtype='complex')))
2939 numpy.zeros((idxT, nHeights),dtype='complex')))
2940 else:
2940 else:
2941 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2941 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2942 volts2[:(nPoints + idxT),:]))
2942 volts2[:(nPoints + idxT),:]))
2943 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2943 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2944
2944
2945 vStacked = None
2945 vStacked = None
2946 return voltsCCF
2946 return voltsCCF
2947
2947
2948 def __getNoise(self, power, timeSegment, timeInterval):
2948 def __getNoise(self, power, timeSegment, timeInterval):
2949 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2949 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2950 numBlocks = int(power.shape[0]/numProfPerBlock)
2950 numBlocks = int(power.shape[0]/numProfPerBlock)
2951 numHeights = power.shape[1]
2951 numHeights = power.shape[1]
2952
2952
2953 listPower = numpy.array_split(power, numBlocks, 0)
2953 listPower = numpy.array_split(power, numBlocks, 0)
2954 noise = numpy.zeros((power.shape[0], power.shape[1]))
2954 noise = numpy.zeros((power.shape[0], power.shape[1]))
2955 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2955 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2956
2956
2957 startInd = 0
2957 startInd = 0
2958 endInd = 0
2958 endInd = 0
2959
2959
2960 for i in range(numBlocks): #split por canal
2960 for i in range(numBlocks): #split por canal
2961 startInd = endInd
2961 startInd = endInd
2962 endInd = endInd + listPower[i].shape[0]
2962 endInd = endInd + listPower[i].shape[0]
2963
2963
2964 arrayBlock = listPower[i]
2964 arrayBlock = listPower[i]
2965 noiseAux = numpy.mean(arrayBlock, 0)
2965 noiseAux = numpy.mean(arrayBlock, 0)
2966 # noiseAux = numpy.median(noiseAux)
2966 # noiseAux = numpy.median(noiseAux)
2967 # noiseAux = numpy.mean(arrayBlock)
2967 # noiseAux = numpy.mean(arrayBlock)
2968 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2968 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2969
2969
2970 noiseAux1 = numpy.mean(arrayBlock)
2970 noiseAux1 = numpy.mean(arrayBlock)
2971 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2971 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2972
2972
2973 return noise, noise1
2973 return noise, noise1
2974
2974
2975 def __findMeteors(self, power, thresh):
2975 def __findMeteors(self, power, thresh):
2976 nProf = power.shape[0]
2976 nProf = power.shape[0]
2977 nHeights = power.shape[1]
2977 nHeights = power.shape[1]
2978 listMeteors = []
2978 listMeteors = []
2979
2979
2980 for i in range(nHeights):
2980 for i in range(nHeights):
2981 powerAux = power[:,i]
2981 powerAux = power[:,i]
2982 threshAux = thresh[:,i]
2982 threshAux = thresh[:,i]
2983
2983
2984 indUPthresh = numpy.where(powerAux > threshAux)[0]
2984 indUPthresh = numpy.where(powerAux > threshAux)[0]
2985 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2985 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2986
2986
2987 j = 0
2987 j = 0
2988
2988
2989 while (j < indUPthresh.size - 2):
2989 while (j < indUPthresh.size - 2):
2990 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2990 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2991 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2991 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2992 indDNthresh = indDNthresh[indDNAux]
2992 indDNthresh = indDNthresh[indDNAux]
2993
2993
2994 if (indDNthresh.size > 0):
2994 if (indDNthresh.size > 0):
2995 indEnd = indDNthresh[0] - 1
2995 indEnd = indDNthresh[0] - 1
2996 indInit = indUPthresh[j]
2996 indInit = indUPthresh[j]
2997
2997
2998 meteor = powerAux[indInit:indEnd + 1]
2998 meteor = powerAux[indInit:indEnd + 1]
2999 indPeak = meteor.argmax() + indInit
2999 indPeak = meteor.argmax() + indInit
3000 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3000 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3001
3001
3002 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3002 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3003 j = numpy.where(indUPthresh == indEnd)[0] + 1
3003 j = numpy.where(indUPthresh == indEnd)[0] + 1
3004 else: j+=1
3004 else: j+=1
3005 else: j+=1
3005 else: j+=1
3006
3006
3007 return listMeteors
3007 return listMeteors
3008
3008
3009 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3009 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3010
3010
3011 arrayMeteors = numpy.asarray(listMeteors)
3011 arrayMeteors = numpy.asarray(listMeteors)
3012 listMeteors1 = []
3012 listMeteors1 = []
3013
3013
3014 while arrayMeteors.shape[0] > 0:
3014 while arrayMeteors.shape[0] > 0:
3015 FLAs = arrayMeteors[:,4]
3015 FLAs = arrayMeteors[:,4]
3016 maxFLA = FLAs.argmax()
3016 maxFLA = FLAs.argmax()
3017 listMeteors1.append(arrayMeteors[maxFLA,:])
3017 listMeteors1.append(arrayMeteors[maxFLA,:])
3018
3018
3019 MeteorInitTime = arrayMeteors[maxFLA,1]
3019 MeteorInitTime = arrayMeteors[maxFLA,1]
3020 MeteorEndTime = arrayMeteors[maxFLA,3]
3020 MeteorEndTime = arrayMeteors[maxFLA,3]
3021 MeteorHeight = arrayMeteors[maxFLA,0]
3021 MeteorHeight = arrayMeteors[maxFLA,0]
3022
3022
3023 #Check neighborhood
3023 #Check neighborhood
3024 maxHeightIndex = MeteorHeight + rangeLimit
3024 maxHeightIndex = MeteorHeight + rangeLimit
3025 minHeightIndex = MeteorHeight - rangeLimit
3025 minHeightIndex = MeteorHeight - rangeLimit
3026 minTimeIndex = MeteorInitTime - timeLimit
3026 minTimeIndex = MeteorInitTime - timeLimit
3027 maxTimeIndex = MeteorEndTime + timeLimit
3027 maxTimeIndex = MeteorEndTime + timeLimit
3028
3028
3029 #Check Heights
3029 #Check Heights
3030 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3030 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3031 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3031 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3032 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3032 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3033
3033
3034 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3034 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3035
3035
3036 return listMeteors1
3036 return listMeteors1
3037
3037
3038 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3038 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3039 numHeights = volts.shape[2]
3039 numHeights = volts.shape[2]
3040 nChannel = volts.shape[0]
3040 nChannel = volts.shape[0]
3041
3041
3042 thresholdPhase = thresh[0]
3042 thresholdPhase = thresh[0]
3043 thresholdNoise = thresh[1]
3043 thresholdNoise = thresh[1]
3044 thresholdDB = float(thresh[2])
3044 thresholdDB = float(thresh[2])
3045
3045
3046 thresholdDB1 = 10**(thresholdDB/10)
3046 thresholdDB1 = 10**(thresholdDB/10)
3047 pairsarray = numpy.array(pairslist)
3047 pairsarray = numpy.array(pairslist)
3048 indSides = pairsarray[:,1]
3048 indSides = pairsarray[:,1]
3049
3049
3050 pairslist1 = list(pairslist)
3050 pairslist1 = list(pairslist)
3051 pairslist1.append((0,1))
3051 pairslist1.append((0,1))
3052 pairslist1.append((3,4))
3052 pairslist1.append((3,4))
3053
3053
3054 listMeteors1 = []
3054 listMeteors1 = []
3055 listPowerSeries = []
3055 listPowerSeries = []
3056 listVoltageSeries = []
3056 listVoltageSeries = []
3057 #volts has the war data
3057 #volts has the war data
3058
3058
3059 if frequency == 30e6:
3059 if frequency == 30e6:
3060 timeLag = 45*10**-3
3060 timeLag = 45*10**-3
3061 else:
3061 else:
3062 timeLag = 15*10**-3
3062 timeLag = 15*10**-3
3063 lag = numpy.ceil(timeLag/timeInterval)
3063 lag = numpy.ceil(timeLag/timeInterval)
3064
3064
3065 for i in range(len(listMeteors)):
3065 for i in range(len(listMeteors)):
3066
3066
3067 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3067 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3068 meteorAux = numpy.zeros(16)
3068 meteorAux = numpy.zeros(16)
3069
3069
3070 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3070 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3071 mHeight = listMeteors[i][0]
3071 mHeight = listMeteors[i][0]
3072 mStart = listMeteors[i][1]
3072 mStart = listMeteors[i][1]
3073 mPeak = listMeteors[i][2]
3073 mPeak = listMeteors[i][2]
3074 mEnd = listMeteors[i][3]
3074 mEnd = listMeteors[i][3]
3075
3075
3076 #get the volt data between the start and end times of the meteor
3076 #get the volt data between the start and end times of the meteor
3077 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3077 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3078 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3078 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3079
3079
3080 #3.6. Phase Difference estimation
3080 #3.6. Phase Difference estimation
3081 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3081 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3082
3082
3083 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3083 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3084 #meteorVolts0.- all Channels, all Profiles
3084 #meteorVolts0.- all Channels, all Profiles
3085 meteorVolts0 = volts[:,:,mHeight]
3085 meteorVolts0 = volts[:,:,mHeight]
3086 meteorThresh = noise[:,mHeight]*thresholdNoise
3086 meteorThresh = noise[:,mHeight]*thresholdNoise
3087 meteorNoise = noise[:,mHeight]
3087 meteorNoise = noise[:,mHeight]
3088 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3088 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3089 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3089 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3090
3090
3091 #Times reestimation
3091 #Times reestimation
3092 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3092 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3093 if mStart1.size > 0:
3093 if mStart1.size > 0:
3094 mStart1 = mStart1[-1] + 1
3094 mStart1 = mStart1[-1] + 1
3095
3095
3096 else:
3096 else:
3097 mStart1 = mPeak
3097 mStart1 = mPeak
3098
3098
3099 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3099 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3100 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3100 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3101 if mEndDecayTime1.size == 0:
3101 if mEndDecayTime1.size == 0:
3102 mEndDecayTime1 = powerNet0.size
3102 mEndDecayTime1 = powerNet0.size
3103 else:
3103 else:
3104 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3104 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3105 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3105 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3106
3106
3107 #meteorVolts1.- all Channels, from start to end
3107 #meteorVolts1.- all Channels, from start to end
3108 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3108 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3109 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3109 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3110 if meteorVolts2.shape[1] == 0:
3110 if meteorVolts2.shape[1] == 0:
3111 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3111 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3112 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3112 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3113 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3113 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3114 ##################### END PARAMETERS REESTIMATION #########################
3114 ##################### END PARAMETERS REESTIMATION #########################
3115
3115
3116 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3116 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3117 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3117 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3118 if meteorVolts2.shape[1] > 0:
3118 if meteorVolts2.shape[1] > 0:
3119 #Phase Difference re-estimation
3119 #Phase Difference re-estimation
3120 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3120 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3121 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3121 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3123 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3123 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3124 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3124 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3125
3125
3126 #Phase Difference RMS
3126 #Phase Difference RMS
3127 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3127 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3128 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3128 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3129 #Data from Meteor
3129 #Data from Meteor
3130 mPeak1 = powerNet1.argmax() + mStart1
3130 mPeak1 = powerNet1.argmax() + mStart1
3131 mPeakPower1 = powerNet1.max()
3131 mPeakPower1 = powerNet1.max()
3132 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3132 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3133 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3133 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3134 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3134 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3135 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3135 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3136 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3136 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3137 #Vectorize
3137 #Vectorize
3138 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3138 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3139 meteorAux[7:11] = phaseDiffint[0:4]
3139 meteorAux[7:11] = phaseDiffint[0:4]
3140
3140
3141 #Rejection Criterions
3141 #Rejection Criterions
3142 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3142 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3143 meteorAux[-1] = 17
3143 meteorAux[-1] = 17
3144 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3144 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3145 meteorAux[-1] = 1
3145 meteorAux[-1] = 1
3146
3146
3147
3147
3148 else:
3148 else:
3149 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3149 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3150 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3150 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3151 PowerSeries = 0
3151 PowerSeries = 0
3152
3152
3153 listMeteors1.append(meteorAux)
3153 listMeteors1.append(meteorAux)
3154 listPowerSeries.append(PowerSeries)
3154 listPowerSeries.append(PowerSeries)
3155 listVoltageSeries.append(meteorVolts1)
3155 listVoltageSeries.append(meteorVolts1)
3156
3156
3157 return listMeteors1, listPowerSeries, listVoltageSeries
3157 return listMeteors1, listPowerSeries, listVoltageSeries
3158
3158
3159 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3159 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3160
3160
3161 threshError = 10
3161 threshError = 10
3162 #Depending if it is 30 or 50 MHz
3162 #Depending if it is 30 or 50 MHz
3163 if frequency == 30e6:
3163 if frequency == 30e6:
3164 timeLag = 45*10**-3
3164 timeLag = 45*10**-3
3165 else:
3165 else:
3166 timeLag = 15*10**-3
3166 timeLag = 15*10**-3
3167 lag = numpy.ceil(timeLag/timeInterval)
3167 lag = numpy.ceil(timeLag/timeInterval)
3168
3168
3169 listMeteors1 = []
3169 listMeteors1 = []
3170
3170
3171 for i in range(len(listMeteors)):
3171 for i in range(len(listMeteors)):
3172 meteorPower = listPower[i]
3172 meteorPower = listPower[i]
3173 meteorAux = listMeteors[i]
3173 meteorAux = listMeteors[i]
3174
3174
3175 if meteorAux[-1] == 0:
3175 if meteorAux[-1] == 0:
3176
3176
3177 try:
3177 try:
3178 indmax = meteorPower.argmax()
3178 indmax = meteorPower.argmax()
3179 indlag = indmax + lag
3179 indlag = indmax + lag
3180
3180
3181 y = meteorPower[indlag:]
3181 y = meteorPower[indlag:]
3182 x = numpy.arange(0, y.size)*timeLag
3182 x = numpy.arange(0, y.size)*timeLag
3183
3183
3184 #first guess
3184 #first guess
3185 a = y[0]
3185 a = y[0]
3186 tau = timeLag
3186 tau = timeLag
3187 #exponential fit
3187 #exponential fit
3188 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3188 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3189 y1 = self.__exponential_function(x, *popt)
3189 y1 = self.__exponential_function(x, *popt)
3190 #error estimation
3190 #error estimation
3191 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3191 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3192
3192
3193 decayTime = popt[1]
3193 decayTime = popt[1]
3194 riseTime = indmax*timeInterval
3194 riseTime = indmax*timeInterval
3195 meteorAux[11:13] = [decayTime, error]
3195 meteorAux[11:13] = [decayTime, error]
3196
3196
3197 #Table items 7, 8 and 11
3197 #Table items 7, 8 and 11
3198 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3198 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3199 meteorAux[-1] = 7
3199 meteorAux[-1] = 7
3200 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3200 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3201 meteorAux[-1] = 8
3201 meteorAux[-1] = 8
3202 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3202 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3203 meteorAux[-1] = 11
3203 meteorAux[-1] = 11
3204
3204
3205
3205
3206 except:
3206 except:
3207 meteorAux[-1] = 11
3207 meteorAux[-1] = 11
3208
3208
3209
3209
3210 listMeteors1.append(meteorAux)
3210 listMeteors1.append(meteorAux)
3211
3211
3212 return listMeteors1
3212 return listMeteors1
3213
3213
3214 #Exponential Function
3214 #Exponential Function
3215
3215
3216 def __exponential_function(self, x, a, tau):
3216 def __exponential_function(self, x, a, tau):
3217 y = a*numpy.exp(-x/tau)
3217 y = a*numpy.exp(-x/tau)
3218 return y
3218 return y
3219
3219
3220 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3220 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3221
3221
3222 pairslist1 = list(pairslist)
3222 pairslist1 = list(pairslist)
3223 pairslist1.append((0,1))
3223 pairslist1.append((0,1))
3224 pairslist1.append((3,4))
3224 pairslist1.append((3,4))
3225 numPairs = len(pairslist1)
3225 numPairs = len(pairslist1)
3226 #Time Lag
3226 #Time Lag
3227 timeLag = 45*10**-3
3227 timeLag = 45*10**-3
3228 c = 3e8
3228 c = 3e8
3229 lag = numpy.ceil(timeLag/timeInterval)
3229 lag = numpy.ceil(timeLag/timeInterval)
3230 freq = 30e6
3230 freq = 30e6
3231
3231
3232 listMeteors1 = []
3232 listMeteors1 = []
3233
3233
3234 for i in range(len(listMeteors)):
3234 for i in range(len(listMeteors)):
3235 meteorAux = listMeteors[i]
3235 meteorAux = listMeteors[i]
3236 if meteorAux[-1] == 0:
3236 if meteorAux[-1] == 0:
3237 mStart = listMeteors[i][1]
3237 mStart = listMeteors[i][1]
3238 mPeak = listMeteors[i][2]
3238 mPeak = listMeteors[i][2]
3239 mLag = mPeak - mStart + lag
3239 mLag = mPeak - mStart + lag
3240
3240
3241 #get the volt data between the start and end times of the meteor
3241 #get the volt data between the start and end times of the meteor
3242 meteorVolts = listVolts[i]
3242 meteorVolts = listVolts[i]
3243 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3243 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3244
3244
3245 #Get CCF
3245 #Get CCF
3246 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3246 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3247
3247
3248 #Method 2
3248 #Method 2
3249 slopes = numpy.zeros(numPairs)
3249 slopes = numpy.zeros(numPairs)
3250 time = numpy.array([-2,-1,1,2])*timeInterval
3250 time = numpy.array([-2,-1,1,2])*timeInterval
3251 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3251 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3252
3252
3253 #Correct phases
3253 #Correct phases
3254 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3254 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3255 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3255 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3256
3256
3257 if indDer[0].shape[0] > 0:
3257 if indDer[0].shape[0] > 0:
3258 for i in range(indDer[0].shape[0]):
3258 for i in range(indDer[0].shape[0]):
3259 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3259 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3260 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3260 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3261
3261
3262 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3262 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3263 for j in range(numPairs):
3263 for j in range(numPairs):
3264 fit = stats.linregress(time, angAllCCF[j,:])
3264 fit = stats.linregress(time, angAllCCF[j,:])
3265 slopes[j] = fit[0]
3265 slopes[j] = fit[0]
3266
3266
3267 #Remove Outlier
3267 #Remove Outlier
3268 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3268 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3269 # slopes = numpy.delete(slopes,indOut)
3269 # slopes = numpy.delete(slopes,indOut)
3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3271 # slopes = numpy.delete(slopes,indOut)
3271 # slopes = numpy.delete(slopes,indOut)
3272
3272
3273 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3273 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3274 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3274 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3275 meteorAux[-2] = radialError
3275 meteorAux[-2] = radialError
3276 meteorAux[-3] = radialVelocity
3276 meteorAux[-3] = radialVelocity
3277
3277
3278 #Setting Error
3278 #Setting Error
3279 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3279 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3280 if numpy.abs(radialVelocity) > 200:
3280 if numpy.abs(radialVelocity) > 200:
3281 meteorAux[-1] = 15
3281 meteorAux[-1] = 15
3282 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3282 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3283 elif radialError > radialStdThresh:
3283 elif radialError > radialStdThresh:
3284 meteorAux[-1] = 12
3284 meteorAux[-1] = 12
3285
3285
3286 listMeteors1.append(meteorAux)
3286 listMeteors1.append(meteorAux)
3287 return listMeteors1
3287 return listMeteors1
3288
3288
3289 def __setNewArrays(self, listMeteors, date, heiRang):
3289 def __setNewArrays(self, listMeteors, date, heiRang):
3290
3290
3291 #New arrays
3291 #New arrays
3292 arrayMeteors = numpy.array(listMeteors)
3292 arrayMeteors = numpy.array(listMeteors)
3293 arrayParameters = numpy.zeros((len(listMeteors), 13))
3293 arrayParameters = numpy.zeros((len(listMeteors), 13))
3294
3294
3295 #Date inclusion
3295 #Date inclusion
3296 # date = re.findall(r'\((.*?)\)', date)
3296 # date = re.findall(r'\((.*?)\)', date)
3297 # date = date[0].split(',')
3297 # date = date[0].split(',')
3298 # date = map(int, date)
3298 # date = map(int, date)
3299 #
3299 #
3300 # if len(date)<6:
3300 # if len(date)<6:
3301 # date.append(0)
3301 # date.append(0)
3302 #
3302 #
3303 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3303 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3304 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3304 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3305 arrayDate = numpy.tile(date, (len(listMeteors)))
3305 arrayDate = numpy.tile(date, (len(listMeteors)))
3306
3306
3307 #Meteor array
3307 #Meteor array
3308 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3308 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3309 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3309 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3310
3310
3311 #Parameters Array
3311 #Parameters Array
3312 arrayParameters[:,0] = arrayDate #Date
3312 arrayParameters[:,0] = arrayDate #Date
3313 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3313 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3314 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3314 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3315 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3315 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3316 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3316 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3317
3317
3318
3318
3319 return arrayParameters
3319 return arrayParameters
3320
3320
3321 class CorrectSMPhases(Operation):
3321 class CorrectSMPhases(Operation):
3322
3322
3323 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3323 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3324
3324
3325 arrayParameters = dataOut.data_param
3325 arrayParameters = dataOut.data_param
3326 pairsList = []
3326 pairsList = []
3327 pairx = (0,1)
3327 pairx = (0,1)
3328 pairy = (2,3)
3328 pairy = (2,3)
3329 pairsList.append(pairx)
3329 pairsList.append(pairx)
3330 pairsList.append(pairy)
3330 pairsList.append(pairy)
3331 jph = numpy.zeros(4)
3331 jph = numpy.zeros(4)
3332
3332
3333 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3333 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3334 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3334 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3335 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3335 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3336
3336
3337 meteorOps = SMOperations()
3337 meteorOps = SMOperations()
3338 if channelPositions is None:
3338 if channelPositions is None:
3339 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3339 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3340 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3340 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3341
3341
3342 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3342 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3343 h = (hmin,hmax)
3343 h = (hmin,hmax)
3344
3344
3345 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3345 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3346
3346
3347 dataOut.data_param = arrayParameters
3347 dataOut.data_param = arrayParameters
3348 return
3348 return
3349
3349
3350 class SMPhaseCalibration(Operation):
3350 class SMPhaseCalibration(Operation):
3351
3351
3352 __buffer = None
3352 __buffer = None
3353
3353
3354 __initime = None
3354 __initime = None
3355
3355
3356 __dataReady = False
3356 __dataReady = False
3357
3357
3358 __isConfig = False
3358 __isConfig = False
3359
3359
3360 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3360 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3361
3361
3362 dataTime = currentTime + paramInterval
3362 dataTime = currentTime + paramInterval
3363 deltaTime = dataTime - initTime
3363 deltaTime = dataTime - initTime
3364
3364
3365 if deltaTime >= outputInterval or deltaTime < 0:
3365 if deltaTime >= outputInterval or deltaTime < 0:
3366 return True
3366 return True
3367
3367
3368 return False
3368 return False
3369
3369
3370 def __getGammas(self, pairs, d, phases):
3370 def __getGammas(self, pairs, d, phases):
3371 gammas = numpy.zeros(2)
3371 gammas = numpy.zeros(2)
3372
3372
3373 for i in range(len(pairs)):
3373 for i in range(len(pairs)):
3374
3374
3375 pairi = pairs[i]
3375 pairi = pairs[i]
3376
3376
3377 phip3 = phases[:,pairi[0]]
3377 phip3 = phases[:,pairi[0]]
3378 d3 = d[pairi[0]]
3378 d3 = d[pairi[0]]
3379 phip2 = phases[:,pairi[1]]
3379 phip2 = phases[:,pairi[1]]
3380 d2 = d[pairi[1]]
3380 d2 = d[pairi[1]]
3381 #Calculating gamma
3381 #Calculating gamma
3382 # jdcos = alp1/(k*d1)
3382 # jdcos = alp1/(k*d1)
3383 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3383 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3384 jgamma = -phip2*d3/d2 - phip3
3384 jgamma = -phip2*d3/d2 - phip3
3385 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3385 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3386 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3386 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3387 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3387 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3388
3388
3389 #Revised distribution
3389 #Revised distribution
3390 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3390 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3391
3391
3392 #Histogram
3392 #Histogram
3393 nBins = 64
3393 nBins = 64
3394 rmin = -0.5*numpy.pi
3394 rmin = -0.5*numpy.pi
3395 rmax = 0.5*numpy.pi
3395 rmax = 0.5*numpy.pi
3396 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3396 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3397
3397
3398 meteorsY = phaseHisto[0]
3398 meteorsY = phaseHisto[0]
3399 phasesX = phaseHisto[1][:-1]
3399 phasesX = phaseHisto[1][:-1]
3400 width = phasesX[1] - phasesX[0]
3400 width = phasesX[1] - phasesX[0]
3401 phasesX += width/2
3401 phasesX += width/2
3402
3402
3403 #Gaussian aproximation
3403 #Gaussian aproximation
3404 bpeak = meteorsY.argmax()
3404 bpeak = meteorsY.argmax()
3405 peak = meteorsY.max()
3405 peak = meteorsY.max()
3406 jmin = bpeak - 5
3406 jmin = bpeak - 5
3407 jmax = bpeak + 5 + 1
3407 jmax = bpeak + 5 + 1
3408
3408
3409 if jmin<0:
3409 if jmin<0:
3410 jmin = 0
3410 jmin = 0
3411 jmax = 6
3411 jmax = 6
3412 elif jmax > meteorsY.size:
3412 elif jmax > meteorsY.size:
3413 jmin = meteorsY.size - 6
3413 jmin = meteorsY.size - 6
3414 jmax = meteorsY.size
3414 jmax = meteorsY.size
3415
3415
3416 x0 = numpy.array([peak,bpeak,50])
3416 x0 = numpy.array([peak,bpeak,50])
3417 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3417 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3418
3418
3419 #Gammas
3419 #Gammas
3420 gammas[i] = coeff[0][1]
3420 gammas[i] = coeff[0][1]
3421
3421
3422 return gammas
3422 return gammas
3423
3423
3424 def __residualFunction(self, coeffs, y, t):
3424 def __residualFunction(self, coeffs, y, t):
3425
3425
3426 return y - self.__gauss_function(t, coeffs)
3426 return y - self.__gauss_function(t, coeffs)
3427
3427
3428 def __gauss_function(self, t, coeffs):
3428 def __gauss_function(self, t, coeffs):
3429
3429
3430 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3430 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3431
3431
3432 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3432 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3433 meteorOps = SMOperations()
3433 meteorOps = SMOperations()
3434 nchan = 4
3434 nchan = 4
3435 pairx = pairsList[0] #x es 0
3435 pairx = pairsList[0] #x es 0
3436 pairy = pairsList[1] #y es 1
3436 pairy = pairsList[1] #y es 1
3437 center_xangle = 0
3437 center_xangle = 0
3438 center_yangle = 0
3438 center_yangle = 0
3439 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3439 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3440 ntimes = len(range_angle)
3440 ntimes = len(range_angle)
3441
3441
3442 nstepsx = 20
3442 nstepsx = 20
3443 nstepsy = 20
3443 nstepsy = 20
3444
3444
3445 for iz in range(ntimes):
3445 for iz in range(ntimes):
3446 min_xangle = -range_angle[iz]/2 + center_xangle
3446 min_xangle = -range_angle[iz]/2 + center_xangle
3447 max_xangle = range_angle[iz]/2 + center_xangle
3447 max_xangle = range_angle[iz]/2 + center_xangle
3448 min_yangle = -range_angle[iz]/2 + center_yangle
3448 min_yangle = -range_angle[iz]/2 + center_yangle
3449 max_yangle = range_angle[iz]/2 + center_yangle
3449 max_yangle = range_angle[iz]/2 + center_yangle
3450
3450
3451 inc_x = (max_xangle-min_xangle)/nstepsx
3451 inc_x = (max_xangle-min_xangle)/nstepsx
3452 inc_y = (max_yangle-min_yangle)/nstepsy
3452 inc_y = (max_yangle-min_yangle)/nstepsy
3453
3453
3454 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3454 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3455 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3455 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3456 penalty = numpy.zeros((nstepsx,nstepsy))
3456 penalty = numpy.zeros((nstepsx,nstepsy))
3457 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3457 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3458 jph = numpy.zeros(nchan)
3458 jph = numpy.zeros(nchan)
3459
3459
3460 # Iterations looking for the offset
3460 # Iterations looking for the offset
3461 for iy in range(int(nstepsy)):
3461 for iy in range(int(nstepsy)):
3462 for ix in range(int(nstepsx)):
3462 for ix in range(int(nstepsx)):
3463 d3 = d[pairsList[1][0]]
3463 d3 = d[pairsList[1][0]]
3464 d2 = d[pairsList[1][1]]
3464 d2 = d[pairsList[1][1]]
3465 d5 = d[pairsList[0][0]]
3465 d5 = d[pairsList[0][0]]
3466 d4 = d[pairsList[0][1]]
3466 d4 = d[pairsList[0][1]]
3467
3467
3468 alp2 = alpha_y[iy] #gamma 1
3468 alp2 = alpha_y[iy] #gamma 1
3469 alp4 = alpha_x[ix] #gamma 0
3469 alp4 = alpha_x[ix] #gamma 0
3470
3470
3471 alp3 = -alp2*d3/d2 - gammas[1]
3471 alp3 = -alp2*d3/d2 - gammas[1]
3472 alp5 = -alp4*d5/d4 - gammas[0]
3472 alp5 = -alp4*d5/d4 - gammas[0]
3473 # jph[pairy[1]] = alpha_y[iy]
3473 # jph[pairy[1]] = alpha_y[iy]
3474 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3474 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3475
3475
3476 # jph[pairx[1]] = alpha_x[ix]
3476 # jph[pairx[1]] = alpha_x[ix]
3477 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3477 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3478 jph[pairsList[0][1]] = alp4
3478 jph[pairsList[0][1]] = alp4
3479 jph[pairsList[0][0]] = alp5
3479 jph[pairsList[0][0]] = alp5
3480 jph[pairsList[1][0]] = alp3
3480 jph[pairsList[1][0]] = alp3
3481 jph[pairsList[1][1]] = alp2
3481 jph[pairsList[1][1]] = alp2
3482 jph_array[:,ix,iy] = jph
3482 jph_array[:,ix,iy] = jph
3483 # d = [2.0,2.5,2.5,2.0]
3483 # d = [2.0,2.5,2.5,2.0]
3484 #falta chequear si va a leer bien los meteoros
3484 #falta chequear si va a leer bien los meteoros
3485 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3485 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3486 error = meteorsArray1[:,-1]
3486 error = meteorsArray1[:,-1]
3487 ind1 = numpy.where(error==0)[0]
3487 ind1 = numpy.where(error==0)[0]
3488 penalty[ix,iy] = ind1.size
3488 penalty[ix,iy] = ind1.size
3489
3489
3490 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3490 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3491 phOffset = jph_array[:,i,j]
3491 phOffset = jph_array[:,i,j]
3492
3492
3493 center_xangle = phOffset[pairx[1]]
3493 center_xangle = phOffset[pairx[1]]
3494 center_yangle = phOffset[pairy[1]]
3494 center_yangle = phOffset[pairy[1]]
3495
3495
3496 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3496 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3497 phOffset = phOffset*180/numpy.pi
3497 phOffset = phOffset*180/numpy.pi
3498 return phOffset
3498 return phOffset
3499
3499
3500
3500
3501 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3501 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3502
3502
3503 dataOut.flagNoData = True
3503 dataOut.flagNoData = True
3504 self.__dataReady = False
3504 self.__dataReady = False
3505 dataOut.outputInterval = nHours*3600
3505 dataOut.outputInterval = nHours*3600
3506
3506
3507 if self.__isConfig == False:
3507 if self.__isConfig == False:
3508 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3508 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3509 #Get Initial LTC time
3509 #Get Initial LTC time
3510 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3510 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3511 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3511 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3512
3512
3513 self.__isConfig = True
3513 self.__isConfig = True
3514
3514
3515 if self.__buffer is None:
3515 if self.__buffer is None:
3516 self.__buffer = dataOut.data_param.copy()
3516 self.__buffer = dataOut.data_param.copy()
3517
3517
3518 else:
3518 else:
3519 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3519 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3520
3520
3521 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3521 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3522
3522
3523 if self.__dataReady:
3523 if self.__dataReady:
3524 dataOut.utctimeInit = self.__initime
3524 dataOut.utctimeInit = self.__initime
3525 self.__initime += dataOut.outputInterval #to erase time offset
3525 self.__initime += dataOut.outputInterval #to erase time offset
3526
3526
3527 freq = dataOut.frequency
3527 freq = dataOut.frequency
3528 c = dataOut.C #m/s
3528 c = dataOut.C #m/s
3529 lamb = c/freq
3529 lamb = c/freq
3530 k = 2*numpy.pi/lamb
3530 k = 2*numpy.pi/lamb
3531 azimuth = 0
3531 azimuth = 0
3532 h = (hmin, hmax)
3532 h = (hmin, hmax)
3533 # pairs = ((0,1),(2,3)) #Estrella
3533 # pairs = ((0,1),(2,3)) #Estrella
3534 # pairs = ((1,0),(2,3)) #T
3534 # pairs = ((1,0),(2,3)) #T
3535
3535
3536 if channelPositions is None:
3536 if channelPositions is None:
3537 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3537 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3538 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3538 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3539 meteorOps = SMOperations()
3539 meteorOps = SMOperations()
3540 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3540 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3541
3541
3542 #Checking correct order of pairs
3542 #Checking correct order of pairs
3543 pairs = []
3543 pairs = []
3544 if distances[1] > distances[0]:
3544 if distances[1] > distances[0]:
3545 pairs.append((1,0))
3545 pairs.append((1,0))
3546 else:
3546 else:
3547 pairs.append((0,1))
3547 pairs.append((0,1))
3548
3548
3549 if distances[3] > distances[2]:
3549 if distances[3] > distances[2]:
3550 pairs.append((3,2))
3550 pairs.append((3,2))
3551 else:
3551 else:
3552 pairs.append((2,3))
3552 pairs.append((2,3))
3553 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3553 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3554
3554
3555 meteorsArray = self.__buffer
3555 meteorsArray = self.__buffer
3556 error = meteorsArray[:,-1]
3556 error = meteorsArray[:,-1]
3557 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3557 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3558 ind1 = numpy.where(boolError)[0]
3558 ind1 = numpy.where(boolError)[0]
3559 meteorsArray = meteorsArray[ind1,:]
3559 meteorsArray = meteorsArray[ind1,:]
3560 meteorsArray[:,-1] = 0
3560 meteorsArray[:,-1] = 0
3561 phases = meteorsArray[:,8:12]
3561 phases = meteorsArray[:,8:12]
3562
3562
3563 #Calculate Gammas
3563 #Calculate Gammas
3564 gammas = self.__getGammas(pairs, distances, phases)
3564 gammas = self.__getGammas(pairs, distances, phases)
3565 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3565 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3566 #Calculate Phases
3566 #Calculate Phases
3567 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3567 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3568 phasesOff = phasesOff.reshape((1,phasesOff.size))
3568 phasesOff = phasesOff.reshape((1,phasesOff.size))
3569 dataOut.data_output = -phasesOff
3569 dataOut.data_output = -phasesOff
3570 dataOut.flagNoData = False
3570 dataOut.flagNoData = False
3571 self.__buffer = None
3571 self.__buffer = None
3572
3572
3573
3573
3574 return
3574 return
3575
3575
3576 class SMOperations():
3576 class SMOperations():
3577
3577
3578 def __init__(self):
3578 def __init__(self):
3579
3579
3580 return
3580 return
3581
3581
3582 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3582 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3583
3583
3584 arrayParameters = arrayParameters0.copy()
3584 arrayParameters = arrayParameters0.copy()
3585 hmin = h[0]
3585 hmin = h[0]
3586 hmax = h[1]
3586 hmax = h[1]
3587
3587
3588 #Calculate AOA (Error N 3, 4)
3588 #Calculate AOA (Error N 3, 4)
3589 #JONES ET AL. 1998
3589 #JONES ET AL. 1998
3590 AOAthresh = numpy.pi/8
3590 AOAthresh = numpy.pi/8
3591 error = arrayParameters[:,-1]
3591 error = arrayParameters[:,-1]
3592 phases = -arrayParameters[:,8:12] + jph
3592 phases = -arrayParameters[:,8:12] + jph
3593 # phases = numpy.unwrap(phases)
3593 # phases = numpy.unwrap(phases)
3594 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3594 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3595
3595
3596 #Calculate Heights (Error N 13 and 14)
3596 #Calculate Heights (Error N 13 and 14)
3597 error = arrayParameters[:,-1]
3597 error = arrayParameters[:,-1]
3598 Ranges = arrayParameters[:,1]
3598 Ranges = arrayParameters[:,1]
3599 zenith = arrayParameters[:,4]
3599 zenith = arrayParameters[:,4]
3600 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3600 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3601
3601
3602 #----------------------- Get Final data ------------------------------------
3602 #----------------------- Get Final data ------------------------------------
3603 # error = arrayParameters[:,-1]
3603 # error = arrayParameters[:,-1]
3604 # ind1 = numpy.where(error==0)[0]
3604 # ind1 = numpy.where(error==0)[0]
3605 # arrayParameters = arrayParameters[ind1,:]
3605 # arrayParameters = arrayParameters[ind1,:]
3606
3606
3607 return arrayParameters
3607 return arrayParameters
3608
3608
3609 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3609 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3610
3610
3611 arrayAOA = numpy.zeros((phases.shape[0],3))
3611 arrayAOA = numpy.zeros((phases.shape[0],3))
3612 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3612 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3613
3613
3614 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3614 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3615 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3615 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3616 arrayAOA[:,2] = cosDirError
3616 arrayAOA[:,2] = cosDirError
3617
3617
3618 azimuthAngle = arrayAOA[:,0]
3618 azimuthAngle = arrayAOA[:,0]
3619 zenithAngle = arrayAOA[:,1]
3619 zenithAngle = arrayAOA[:,1]
3620
3620
3621 #Setting Error
3621 #Setting Error
3622 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3622 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3623 error[indError] = 0
3623 error[indError] = 0
3624 #Number 3: AOA not fesible
3624 #Number 3: AOA not fesible
3625 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3625 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3626 error[indInvalid] = 3
3626 error[indInvalid] = 3
3627 #Number 4: Large difference in AOAs obtained from different antenna baselines
3627 #Number 4: Large difference in AOAs obtained from different antenna baselines
3628 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3628 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3629 error[indInvalid] = 4
3629 error[indInvalid] = 4
3630 return arrayAOA, error
3630 return arrayAOA, error
3631
3631
3632 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3632 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3633
3633
3634 #Initializing some variables
3634 #Initializing some variables
3635 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3635 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3636 ang_aux = ang_aux.reshape(1,ang_aux.size)
3636 ang_aux = ang_aux.reshape(1,ang_aux.size)
3637
3637
3638 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3638 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3639 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3639 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3640
3640
3641
3641
3642 for i in range(2):
3642 for i in range(2):
3643 ph0 = arrayPhase[:,pairsList[i][0]]
3643 ph0 = arrayPhase[:,pairsList[i][0]]
3644 ph1 = arrayPhase[:,pairsList[i][1]]
3644 ph1 = arrayPhase[:,pairsList[i][1]]
3645 d0 = distances[pairsList[i][0]]
3645 d0 = distances[pairsList[i][0]]
3646 d1 = distances[pairsList[i][1]]
3646 d1 = distances[pairsList[i][1]]
3647
3647
3648 ph0_aux = ph0 + ph1
3648 ph0_aux = ph0 + ph1
3649 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3649 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3650 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3650 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3651 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3651 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3652 #First Estimation
3652 #First Estimation
3653 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3653 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3654
3654
3655 #Most-Accurate Second Estimation
3655 #Most-Accurate Second Estimation
3656 phi1_aux = ph0 - ph1
3656 phi1_aux = ph0 - ph1
3657 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3657 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3658 #Direction Cosine 1
3658 #Direction Cosine 1
3659 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3659 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3660
3660
3661 #Searching the correct Direction Cosine
3661 #Searching the correct Direction Cosine
3662 cosdir0_aux = cosdir0[:,i]
3662 cosdir0_aux = cosdir0[:,i]
3663 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3663 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3664 #Minimum Distance
3664 #Minimum Distance
3665 cosDiff = (cosdir1 - cosdir0_aux)**2
3665 cosDiff = (cosdir1 - cosdir0_aux)**2
3666 indcos = cosDiff.argmin(axis = 1)
3666 indcos = cosDiff.argmin(axis = 1)
3667 #Saving Value obtained
3667 #Saving Value obtained
3668 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3668 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3669
3669
3670 return cosdir0, cosdir
3670 return cosdir0, cosdir
3671
3671
3672 def __calculateAOA(self, cosdir, azimuth):
3672 def __calculateAOA(self, cosdir, azimuth):
3673 cosdirX = cosdir[:,0]
3673 cosdirX = cosdir[:,0]
3674 cosdirY = cosdir[:,1]
3674 cosdirY = cosdir[:,1]
3675
3675
3676 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3676 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3677 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3677 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3678 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3678 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3679
3679
3680 return angles
3680 return angles
3681
3681
3682 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3682 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3683
3683
3684 Ramb = 375 #Ramb = c/(2*PRF)
3684 Ramb = 375 #Ramb = c/(2*PRF)
3685 Re = 6371 #Earth Radius
3685 Re = 6371 #Earth Radius
3686 heights = numpy.zeros(Ranges.shape)
3686 heights = numpy.zeros(Ranges.shape)
3687
3687
3688 R_aux = numpy.array([0,1,2])*Ramb
3688 R_aux = numpy.array([0,1,2])*Ramb
3689 R_aux = R_aux.reshape(1,R_aux.size)
3689 R_aux = R_aux.reshape(1,R_aux.size)
3690
3690
3691 Ranges = Ranges.reshape(Ranges.size,1)
3691 Ranges = Ranges.reshape(Ranges.size,1)
3692
3692
3693 Ri = Ranges + R_aux
3693 Ri = Ranges + R_aux
3694 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3694 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3695
3695
3696 #Check if there is a height between 70 and 110 km
3696 #Check if there is a height between 70 and 110 km
3697 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3697 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3698 ind_h = numpy.where(h_bool == 1)[0]
3698 ind_h = numpy.where(h_bool == 1)[0]
3699
3699
3700 hCorr = hi[ind_h, :]
3700 hCorr = hi[ind_h, :]
3701 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3701 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3702
3702
3703 hCorr = hi[ind_hCorr][:len(ind_h)]
3703 hCorr = hi[ind_hCorr][:len(ind_h)]
3704 heights[ind_h] = hCorr
3704 heights[ind_h] = hCorr
3705
3705
3706 #Setting Error
3706 #Setting Error
3707 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3707 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3708 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3708 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3709 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3709 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3710 error[indError] = 0
3710 error[indError] = 0
3711 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3711 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3712 error[indInvalid2] = 14
3712 error[indInvalid2] = 14
3713 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3713 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3714 error[indInvalid1] = 13
3714 error[indInvalid1] = 13
3715
3715
3716 return heights, error
3716 return heights, error
3717
3717
3718 def getPhasePairs(self, channelPositions):
3718 def getPhasePairs(self, channelPositions):
3719 chanPos = numpy.array(channelPositions)
3719 chanPos = numpy.array(channelPositions)
3720 listOper = list(itertools.combinations(list(range(5)),2))
3720 listOper = list(itertools.combinations(list(range(5)),2))
3721
3721
3722 distances = numpy.zeros(4)
3722 distances = numpy.zeros(4)
3723 axisX = []
3723 axisX = []
3724 axisY = []
3724 axisY = []
3725 distX = numpy.zeros(3)
3725 distX = numpy.zeros(3)
3726 distY = numpy.zeros(3)
3726 distY = numpy.zeros(3)
3727 ix = 0
3727 ix = 0
3728 iy = 0
3728 iy = 0
3729
3729
3730 pairX = numpy.zeros((2,2))
3730 pairX = numpy.zeros((2,2))
3731 pairY = numpy.zeros((2,2))
3731 pairY = numpy.zeros((2,2))
3732
3732
3733 for i in range(len(listOper)):
3733 for i in range(len(listOper)):
3734 pairi = listOper[i]
3734 pairi = listOper[i]
3735
3735
3736 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3736 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3737
3737
3738 if posDif[0] == 0:
3738 if posDif[0] == 0:
3739 axisY.append(pairi)
3739 axisY.append(pairi)
3740 distY[iy] = posDif[1]
3740 distY[iy] = posDif[1]
3741 iy += 1
3741 iy += 1
3742 elif posDif[1] == 0:
3742 elif posDif[1] == 0:
3743 axisX.append(pairi)
3743 axisX.append(pairi)
3744 distX[ix] = posDif[0]
3744 distX[ix] = posDif[0]
3745 ix += 1
3745 ix += 1
3746
3746
3747 for i in range(2):
3747 for i in range(2):
3748 if i==0:
3748 if i==0:
3749 dist0 = distX
3749 dist0 = distX
3750 axis0 = axisX
3750 axis0 = axisX
3751 else:
3751 else:
3752 dist0 = distY
3752 dist0 = distY
3753 axis0 = axisY
3753 axis0 = axisY
3754
3754
3755 side = numpy.argsort(dist0)[:-1]
3755 side = numpy.argsort(dist0)[:-1]
3756 axis0 = numpy.array(axis0)[side,:]
3756 axis0 = numpy.array(axis0)[side,:]
3757 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3757 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3758 axis1 = numpy.unique(numpy.reshape(axis0,4))
3758 axis1 = numpy.unique(numpy.reshape(axis0,4))
3759 side = axis1[axis1 != chanC]
3759 side = axis1[axis1 != chanC]
3760 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3760 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3761 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3761 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3762 if diff1<0:
3762 if diff1<0:
3763 chan2 = side[0]
3763 chan2 = side[0]
3764 d2 = numpy.abs(diff1)
3764 d2 = numpy.abs(diff1)
3765 chan1 = side[1]
3765 chan1 = side[1]
3766 d1 = numpy.abs(diff2)
3766 d1 = numpy.abs(diff2)
3767 else:
3767 else:
3768 chan2 = side[1]
3768 chan2 = side[1]
3769 d2 = numpy.abs(diff2)
3769 d2 = numpy.abs(diff2)
3770 chan1 = side[0]
3770 chan1 = side[0]
3771 d1 = numpy.abs(diff1)
3771 d1 = numpy.abs(diff1)
3772
3772
3773 if i==0:
3773 if i==0:
3774 chanCX = chanC
3774 chanCX = chanC
3775 chan1X = chan1
3775 chan1X = chan1
3776 chan2X = chan2
3776 chan2X = chan2
3777 distances[0:2] = numpy.array([d1,d2])
3777 distances[0:2] = numpy.array([d1,d2])
3778 else:
3778 else:
3779 chanCY = chanC
3779 chanCY = chanC
3780 chan1Y = chan1
3780 chan1Y = chan1
3781 chan2Y = chan2
3781 chan2Y = chan2
3782 distances[2:4] = numpy.array([d1,d2])
3782 distances[2:4] = numpy.array([d1,d2])
3783 # axisXsides = numpy.reshape(axisX[ix,:],4)
3783 # axisXsides = numpy.reshape(axisX[ix,:],4)
3784 #
3784 #
3785 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3785 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3786 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3786 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3787 #
3787 #
3788 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3788 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3789 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3789 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3790 # channel25X = int(pairX[0,ind25X])
3790 # channel25X = int(pairX[0,ind25X])
3791 # channel20X = int(pairX[1,ind20X])
3791 # channel20X = int(pairX[1,ind20X])
3792 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3792 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3793 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3793 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3794 # channel25Y = int(pairY[0,ind25Y])
3794 # channel25Y = int(pairY[0,ind25Y])
3795 # channel20Y = int(pairY[1,ind20Y])
3795 # channel20Y = int(pairY[1,ind20Y])
3796
3796
3797 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3797 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3798 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3798 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3799
3799
3800 return pairslist, distances
3800 return pairslist, distances
3801 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3801 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3802 #
3802 #
3803 # arrayAOA = numpy.zeros((phases.shape[0],3))
3803 # arrayAOA = numpy.zeros((phases.shape[0],3))
3804 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3804 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3805 #
3805 #
3806 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3806 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3807 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3807 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3808 # arrayAOA[:,2] = cosDirError
3808 # arrayAOA[:,2] = cosDirError
3809 #
3809 #
3810 # azimuthAngle = arrayAOA[:,0]
3810 # azimuthAngle = arrayAOA[:,0]
3811 # zenithAngle = arrayAOA[:,1]
3811 # zenithAngle = arrayAOA[:,1]
3812 #
3812 #
3813 # #Setting Error
3813 # #Setting Error
3814 # #Number 3: AOA not fesible
3814 # #Number 3: AOA not fesible
3815 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3815 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3816 # error[indInvalid] = 3
3816 # error[indInvalid] = 3
3817 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3817 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3818 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3818 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3819 # error[indInvalid] = 4
3819 # error[indInvalid] = 4
3820 # return arrayAOA, error
3820 # return arrayAOA, error
3821 #
3821 #
3822 # def __getDirectionCosines(self, arrayPhase, pairsList):
3822 # def __getDirectionCosines(self, arrayPhase, pairsList):
3823 #
3823 #
3824 # #Initializing some variables
3824 # #Initializing some variables
3825 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3825 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3826 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3826 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3827 #
3827 #
3828 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3828 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3829 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3829 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3830 #
3830 #
3831 #
3831 #
3832 # for i in range(2):
3832 # for i in range(2):
3833 # #First Estimation
3833 # #First Estimation
3834 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3834 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3835 # #Dealias
3835 # #Dealias
3836 # indcsi = numpy.where(phi0_aux > numpy.pi)
3836 # indcsi = numpy.where(phi0_aux > numpy.pi)
3837 # phi0_aux[indcsi] -= 2*numpy.pi
3837 # phi0_aux[indcsi] -= 2*numpy.pi
3838 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3838 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3839 # phi0_aux[indcsi] += 2*numpy.pi
3839 # phi0_aux[indcsi] += 2*numpy.pi
3840 # #Direction Cosine 0
3840 # #Direction Cosine 0
3841 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3841 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3842 #
3842 #
3843 # #Most-Accurate Second Estimation
3843 # #Most-Accurate Second Estimation
3844 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3844 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3845 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3845 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3846 # #Direction Cosine 1
3846 # #Direction Cosine 1
3847 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3847 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3848 #
3848 #
3849 # #Searching the correct Direction Cosine
3849 # #Searching the correct Direction Cosine
3850 # cosdir0_aux = cosdir0[:,i]
3850 # cosdir0_aux = cosdir0[:,i]
3851 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3851 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3852 # #Minimum Distance
3852 # #Minimum Distance
3853 # cosDiff = (cosdir1 - cosdir0_aux)**2
3853 # cosDiff = (cosdir1 - cosdir0_aux)**2
3854 # indcos = cosDiff.argmin(axis = 1)
3854 # indcos = cosDiff.argmin(axis = 1)
3855 # #Saving Value obtained
3855 # #Saving Value obtained
3856 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3856 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3857 #
3857 #
3858 # return cosdir0, cosdir
3858 # return cosdir0, cosdir
3859 #
3859 #
3860 # def __calculateAOA(self, cosdir, azimuth):
3860 # def __calculateAOA(self, cosdir, azimuth):
3861 # cosdirX = cosdir[:,0]
3861 # cosdirX = cosdir[:,0]
3862 # cosdirY = cosdir[:,1]
3862 # cosdirY = cosdir[:,1]
3863 #
3863 #
3864 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3864 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3865 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3865 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3866 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3866 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3867 #
3867 #
3868 # return angles
3868 # return angles
3869 #
3869 #
3870 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3870 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3871 #
3871 #
3872 # Ramb = 375 #Ramb = c/(2*PRF)
3872 # Ramb = 375 #Ramb = c/(2*PRF)
3873 # Re = 6371 #Earth Radius
3873 # Re = 6371 #Earth Radius
3874 # heights = numpy.zeros(Ranges.shape)
3874 # heights = numpy.zeros(Ranges.shape)
3875 #
3875 #
3876 # R_aux = numpy.array([0,1,2])*Ramb
3876 # R_aux = numpy.array([0,1,2])*Ramb
3877 # R_aux = R_aux.reshape(1,R_aux.size)
3877 # R_aux = R_aux.reshape(1,R_aux.size)
3878 #
3878 #
3879 # Ranges = Ranges.reshape(Ranges.size,1)
3879 # Ranges = Ranges.reshape(Ranges.size,1)
3880 #
3880 #
3881 # Ri = Ranges + R_aux
3881 # Ri = Ranges + R_aux
3882 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3882 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3883 #
3883 #
3884 # #Check if there is a height between 70 and 110 km
3884 # #Check if there is a height between 70 and 110 km
3885 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3885 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3886 # ind_h = numpy.where(h_bool == 1)[0]
3886 # ind_h = numpy.where(h_bool == 1)[0]
3887 #
3887 #
3888 # hCorr = hi[ind_h, :]
3888 # hCorr = hi[ind_h, :]
3889 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3889 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3890 #
3890 #
3891 # hCorr = hi[ind_hCorr]
3891 # hCorr = hi[ind_hCorr]
3892 # heights[ind_h] = hCorr
3892 # heights[ind_h] = hCorr
3893 #
3893 #
3894 # #Setting Error
3894 # #Setting Error
3895 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3895 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3896 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3896 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3897 #
3897 #
3898 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3898 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3899 # error[indInvalid2] = 14
3899 # error[indInvalid2] = 14
3900 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3900 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3901 # error[indInvalid1] = 13
3901 # error[indInvalid1] = 13
3902 #
3902 #
3903 # return heights, error
3903 # return heights, error
3904
3904
3905
3905
3906 class WeatherRadar(Operation):
3906 class WeatherRadar(Operation):
3907 '''
3907 '''
3908 Function tat implements Weather Radar operations-
3908 Function tat implements Weather Radar operations-
3909 Input:
3909 Input:
3910 Output:
3910 Output:
3911 Parameters affected:
3911 Parameters affected:
3912 '''
3912 '''
3913 isConfig = False
3913 isConfig = False
3914
3914
3915 def __init__(self):
3915 def __init__(self):
3916 Operation.__init__(self)
3916 Operation.__init__(self)
3917
3917
3918 def setup(self,dataOut,Pt=0,Gt=0,Gr=0,lambda_=0, aL=0,
3918 def setup(self,dataOut,Pt=0,Gt=0,Gr=0,lambda_=0, aL=0,
3919 tauW= 0,thetaT=0,thetaR=0,Km =0):
3919 tauW= 0,thetaT=0,thetaR=0,Km =0):
3920 self.nCh = dataOut.nChannels
3920 self.nCh = dataOut.nChannels
3921 self.nHeis = dataOut.nHeights
3921 self.nHeis = dataOut.nHeights
3922 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3922 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3923 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3923 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3924 self.Range = self.Range.reshape(1,self.nHeis)
3924 self.Range = self.Range.reshape(1,self.nHeis)
3925 self.Range = numpy.tile(self.Range,[self.nCh,1])
3925 self.Range = numpy.tile(self.Range,[self.nCh,1])
3926 '''-----------1 Constante del Radar----------'''
3926 '''-----------1 Constante del Radar----------'''
3927 self.Pt = Pt
3927 self.Pt = Pt
3928 self.Gt = Gt
3928 self.Gt = Gt
3929 self.Gr = Gr
3929 self.Gr = Gr
3930 self.lambda_ = lambda_
3930 self.lambda_ = lambda_
3931 self.aL = aL
3931 self.aL = aL
3932 self.tauW = tauW
3932 self.tauW = tauW
3933 self.thetaT = thetaT
3933 self.thetaT = thetaT
3934 self.thetaR = thetaR
3934 self.thetaR = thetaR
3935 self.Km = Km
3935 self.Km = Km
3936 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3936 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3937 Denominator = (Pt * Gt * Gr * lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3937 Denominator = (Pt * Gt * Gr * lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3938 self.RadarConstant = Numerator/Denominator
3938 self.RadarConstant = Numerator/Denominator
3939 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3939 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3940 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3940 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3941 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3941 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3942
3942
3943 def setMoments(self,dataOut,i):
3943 def setMoments(self,dataOut,i):
3944
3944
3945 type = dataOut.inputUnit
3945 type = dataOut.inputUnit
3946 nCh = dataOut.nChannels
3946 nCh = dataOut.nChannels
3947 nHeis= dataOut.nHeights
3947 nHeis= dataOut.nHeights
3948 data_param = numpy.zeros((nCh,4,nHeis))
3948 data_param = numpy.zeros((nCh,4,nHeis))
3949 if type == "Voltage":
3949 if type == "Voltage":
3950 data_param[:,0,:] = dataOut.dataPP_POW/(dataOut.nCohInt**2)
3950 data_param[:,0,:] = dataOut.dataPP_POW/(dataOut.nCohInt**2)
3951 data_param[:,1,:] = dataOut.dataPP_DOP
3951 data_param[:,1,:] = dataOut.dataPP_DOP
3952 data_param[:,2,:] = dataOut.dataPP_WIDTH
3952 data_param[:,2,:] = dataOut.dataPP_WIDTH
3953 data_param[:,3,:] = dataOut.dataPP_SNR
3953 data_param[:,3,:] = dataOut.dataPP_SNR
3954 if type == "Spectra":
3954 if type == "Spectra":
3955 data_param[:,0,:] = dataOut.data_POW
3955 data_param[:,0,:] = dataOut.data_POW
3956 data_param[:,1,:] = dataOut.data_DOP
3956 data_param[:,1,:] = dataOut.data_DOP
3957 data_param[:,2,:] = dataOut.data_WIDTH
3957 data_param[:,2,:] = dataOut.data_WIDTH
3958 def setMoments(self,dataOut,i):
3958 def setMoments(self,dataOut,i):
3959 data_param[:,3,:] = dataOut.data_SNR
3959 data_param[:,3,:] = dataOut.data_SNR
3960
3960
3961 return data_param[:,i,:]
3961 return data_param[:,i,:]
3962
3962
3963
3963
3964 def run(self,dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3964 def run(self,dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3965 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93):
3965 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93):
3966
3966
3967 if not self.isConfig:
3967 if not self.isConfig:
3968 self.setup(dataOut= dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3968 self.setup(dataOut= dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3969 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93)
3969 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93)
3970 self.isConfig = True
3970 self.isConfig = True
3971 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3971 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3972 Pr = self.setMoments(dataOut,0)
3972 Pr = self.setMoments(dataOut,0)
3973
3973
3974 for R in range(self.nHeis):
3974 for R in range(self.nHeis):
3975 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
3975 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
3976
3976
3977 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
3977 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
3978
3978
3979 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3979 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3980 Zeh = self.Z_radar
3980 Zeh = self.Z_radar
3981 dBZeh = 10*numpy.log10(Zeh)
3981 dBZeh = 10*numpy.log10(Zeh)
3982 dataOut.factor_Zeh= dBZeh
3982 dataOut.factor_Zeh= dBZeh
3983 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3983 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3984 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3984 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3985
3985
3986 return dataOut
3986 return dataOut
3987
3987
3988 class PedestalInformation(Operation):
3988 class PedestalInformation(Operation):
3989 path_ped = None
3989 path_ped = None
3990 path_adq = None
3990 path_adq = None
3991 t_Interval_p = None
3991 t_Interval_p = None
3992 n_Muestras_p = None
3992 n_Muestras_p = None
3993 isConfig = False
3993 isConfig = False
3994 blocksPerfile= None
3994 blocksPerfile= None
3995 f_a_p = None
3995 f_a_p = None
3996 online = None
3996 online = None
3997 angulo_adq = None
3997 angulo_adq = None
3998 nro_file = None
3998 nro_file = None
3999 nro_key_p = None
3999 nro_key_p = None
4000 tmp = None
4000 tmp = None
4001
4001
4002
4002
4003 def __init__(self):
4003 def __init__(self):
4004 Operation.__init__(self)
4004 Operation.__init__(self)
4005
4005
4006 def getfirstFilefromPath(self,path,meta,ext):
4006 def getfirstFilefromPath(self,path,meta,ext):
4007 validFilelist = []
4007 validFilelist = []
4008 #print("SEARH",path)
4008 #print("SEARH",path)
4009 try:
4009 try:
4010 fileList = os.listdir(path)
4010 fileList = os.listdir(path)
4011 except:
4011 except:
4012 print("check path - fileList")
4012 print("check path - fileList")
4013 if len(fileList)<1:
4013 if len(fileList)<1:
4014 return None
4014 return None
4015 # meta 1234 567 8-18 BCDE
4015 # meta 1234 567 8-18 BCDE
4016 # H,D,PE YYYY DDD EPOC .ext
4016 # H,D,PE YYYY DDD EPOC .ext
4017
4017
4018 for thisFile in fileList:
4018 for thisFile in fileList:
4019 #print("HI",thisFile)
4019 #print("HI",thisFile)
4020 if meta =="PE":
4020 if meta =="PE":
4021 try:
4021 try:
4022 number= int(thisFile[len(meta)+7:len(meta)+17])
4022 number= int(thisFile[len(meta)+7:len(meta)+17])
4023 except:
4023 except:
4024 print("There is a file or folder with different format")
4024 print("There is a file or folder with different format")
4025 if meta == "D":
4025 if meta == "D":
4026 try:
4026 try:
4027 number= int(thisFile[8:11])
4027 number= int(thisFile[8:11])
4028 except:
4028 except:
4029 print("There is a file or folder with different format")
4029 print("There is a file or folder with different format")
4030
4030
4031 if not isNumber(str=number):
4031 if not isNumber(str=number):
4032 continue
4032 continue
4033 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4033 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4034 continue
4034 continue
4035 validFilelist.sort()
4035 validFilelist.sort()
4036 validFilelist.append(thisFile)
4036 validFilelist.append(thisFile)
4037 if len(validFilelist)>0:
4037 if len(validFilelist)>0:
4038 validFilelist = sorted(validFilelist,key=str.lower)
4038 validFilelist = sorted(validFilelist,key=str.lower)
4039 return validFilelist
4039 return validFilelist
4040 return None
4040 return None
4041
4041
4042 def gettimeutcfromDirFilename(self,path,file):
4042 def gettimeutcfromDirFilename(self,path,file):
4043 dir_file= path+"/"+file
4043 dir_file= path+"/"+file
4044 fp = h5py.File(dir_file,'r')
4044 fp = h5py.File(dir_file,'r')
4045 #epoc = fp['Metadata'].get('utctimeInit')[()]
4045 #epoc = fp['Metadata'].get('utctimeInit')[()]
4046 epoc = fp['Data'].get('utc')[()]
4046 epoc = fp['Data'].get('utc')[()]
4047 fp.close()
4047 fp.close()
4048 return epoc
4048 return epoc
4049
4049
4050 def gettimeutcadqfromDirFilename(self,path,file):
4050 def gettimeutcadqfromDirFilename(self,path,file):
4051 dir_file= path+"/"+file
4051 dir_file= path+"/"+file
4052 fp = h5py.File(dir_file,'r')
4052 fp = h5py.File(dir_file,'r')
4053 epoc = fp['Metadata'].get('utctimeInit')[()]
4053 epoc = fp['Metadata'].get('utctimeInit')[()]
4054 #epoc = fp['Data'].get('utc')[()]
4054 #epoc = fp['Data'].get('utc')[()]
4055 fp.close()
4055 fp.close()
4056 return epoc
4056 return epoc
4057
4057
4058 def getDatavaluefromDirFilename(self,path,file,value):
4058 def getDatavaluefromDirFilename(self,path,file,value):
4059 dir_file= path+"/"+file
4059 dir_file= path+"/"+file
4060 fp = h5py.File(dir_file,'r')
4060 fp = h5py.File(dir_file,'r')
4061 array = fp['Data'].get(value)[()]
4061 array = fp['Data'].get(value)[()]
4062 fp.close()
4062 fp.close()
4063 return array
4063 return array
4064
4064
4065 def getFile_KeyP(self,list_pedestal,list_adq):
4065 def getFile_KeyP(self,list_pedestal,list_adq):
4066 print(list_pedestal)
4066 print(list_pedestal)
4067 print(list_adq)
4067 print(list_adq)
4068
4068
4069 def getNROFile(self,utc_adq,utc_ped_list):
4069 def getNROFile(self,utc_adq,utc_ped_list):
4070 c=0
4070 c=0
4071 print("insidegetNROFile")
4071 print("insidegetNROFile")
4072 print(utc_adq)
4072 print(utc_adq)
4073 print(len(utc_ped_list))
4073 print(len(utc_ped_list))
4074 for i in range(len(utc_ped_list)):
4074 for i in range(len(utc_ped_list)):
4075 if utc_adq>utc_ped_list[i]:
4075 if utc_adq>utc_ped_list[i]:
4076 #print("mayor")
4076 #print("mayor")
4077 #print("utc_ped_list",utc_ped_list[i])
4077 #print("utc_ped_list",utc_ped_list[i])
4078 c +=1
4078 c +=1
4079
4079
4080 return c-1,utc_ped_list[c-1],utc_ped_list[c]
4080 return c-1,utc_ped_list[c-1],utc_ped_list[c]
4081
4081
4082
4082 def verificarNROFILE(self,dataOut,utc_ped,f_a_p,n_Muestras_p):
4083 def setup_offline(self,list_pedestal,list_adq):
4083 var =int(f_a_p/n_Muestras_p)
4084 flag=0
4085 for i in range(var):
4086 if dataOut.utctime+i==utc_ped:
4087 flag==1
4088 break
4089 return flag
4090
4091 def setup_offline(self,dataOut,list_pedestal,list_adq):
4084 print("SETUP OFFLINE")
4092 print("SETUP OFFLINE")
4085 print(self.path_ped)
4093 print(self.path_ped)
4086 print(self.path_adq)
4094 print(self.path_adq)
4087 print(len(self.list_pedestal))
4095 print(len(self.list_pedestal))
4088 print(len(self.list_adq))
4096 print(len(self.list_adq))
4089 utc_ped_list=[]
4097 utc_ped_list=[]
4090 for i in range(len(self.list_pedestal)):
4098 for i in range(len(self.list_pedestal)):
4091 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4099 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4092
4100
4093 #utc_ped_list= utc_ped_list
4101 #utc_ped_list= utc_ped_list
4094 utc_adq = self.gettimeutcadqfromDirFilename(path=self.path_adq,file=self.list_adq[0])
4102 utc_adq = self.gettimeutcadqfromDirFilename(path=self.path_adq,file=self.list_adq[0])
4095 print("dios existe donde esta")
4103 print("dios existe donde esta")
4096 #print("utc_ped_list",utc_ped_list)
4104 #print("utc_ped_list",utc_ped_list)
4097 print("utc_adq",utc_adq)
4105 print("utc_adq",utc_adq)
4098 nro_file,utc_ped,utc_ped_1ss = self.getNROFile(utc_adq=utc_adq, utc_ped_list= utc_ped_list)
4106 # utc_adq_dataOut
4107 utc_adq_dataOut =dataOut.utctime
4108 print("Offline-utc_adq_dataout",utc_adq_dataOut)
4109
4110 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq, utc_ped_list= utc_ped_list)
4099
4111
4100 print("nro_file",nro_file,"utc_ped",utc_ped)
4112 print("nro_file",nro_file,"utc_ped",utc_ped)
4101 print("nro_file",i)
4113 print("nro_file",i)
4102 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1 # ojito al -1 estimado alex
4114 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1 # ojito al -1 estimado alex
4103 print("nro_key_p",nro_key_p)
4115 print("nro_key_p",nro_key_p)
4104
4116
4105 ff_pedestal = self.list_pedestal[nro_file]
4117 ff_pedestal = self.list_pedestal[nro_file]
4106 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4118 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4107 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4119 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4108
4120
4109 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4121 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4110 print("angulo_array :",angulo[nro_key_p])
4122 print("angulo_array :",angulo[nro_key_p])
4111 self.nro_file = nro_file
4123 self.nro_file = nro_file
4112 self.nro_key_p = nro_key_p
4124 self.nro_key_p = nro_key_p
4113
4125
4114 def setup_online(self,dataOut):
4126 def setup_online(self,dataOut):
4115 utc_adq =dataOut.utctime
4127 utc_adq =dataOut.utctime
4116 print("Online-utc_adq",utc_adq)
4128 print("Online-utc_adq",utc_adq)
4117 print(len(self.list_pedestal))
4129 print(len(self.list_pedestal))
4118 utc_ped_list=[]
4130 utc_ped_list=[]
4119 for i in range(len(self.list_pedestal)):
4131 for i in range(len(self.list_pedestal)):
4120 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4132 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4121 print(utc_ped_list[:20])
4133 print(utc_ped_list[:20])
4122 #print(utc_ped_list[488:498])
4134 #print(utc_ped_list[488:498])
4123 print("ultimo UTC-PEDESTAL",utc_ped_list[-1])
4135 print("ultimo UTC-PEDESTAL",utc_ped_list[-1])
4124 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq, utc_ped_list= utc_ped_list)
4136 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq, utc_ped_list= utc_ped_list)
4125 print("nro_file",nro_file,"utc_ped",utc_ped,"utc_ped_1",utc_ped_1)
4137 print("nro_file",nro_file,"utc_ped",utc_ped,"utc_ped_1",utc_ped_1)
4126 print("name_PEDESTAL",self.list_pedestal[nro_file])
4138 print("name_PEDESTAL",self.list_pedestal[nro_file])
4127 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1
4139 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1
4128 print("nro_key_p",nro_key_p)
4140 print("nro_key_p",nro_key_p)
4129 ff_pedestal = self.list_pedestal[nro_file]
4141 ff_pedestal = self.list_pedestal[nro_file]
4130 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4142 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4131 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4143 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4132
4144
4133 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4145 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4134 print("angulo_array :",angulo[nro_key_p])
4146 print("angulo_array :",angulo[nro_key_p])
4135 self.nro_file = nro_file
4147 self.nro_file = nro_file
4136 self.nro_key_p = nro_key_p
4148 self.nro_key_p = nro_key_p
4137
4149
4138
4139 '''
4140 print("############################")
4141 utc_adq = dataOut.utctime
4142 print("ONLINE",dataOut.utctime)
4143 print("utc_adq" , utc_adq)
4144 utc_pedestal= self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[0])
4145 print("utc_pedestal", utc_pedestal)
4146 flag_i = 0
4147 flag = 0
4148 ready = 0
4149 if len(self.list_pedestal)!=0:
4150 enable_p=1
4151 if (enable_p!=0):
4152 while(flag_i==0):
4153 if utc_adq>utc_pedestal:
4154 nro_file = int((utc_adq - utc_pedestal)/(self.t_Interval_p*self.n_Muestras_p))
4155 print("nro_file--------------------",nro_file)
4156 print(len(self.list_pedestal))
4157 if nro_file> len(self.list_pedestal):
4158 nro_file = len(self.list_pedestal)-1
4159 ff_pedestal = self.list_pedestal[nro_file]
4160 print(ff_pedestal)
4161 utc_pedestal = self.gettimeutcfromDirFilename(path=self.path_ped,file=ff_pedestal)
4162 while(flag==0):
4163 print("adq",utc_adq)
4164 print("ped",utc_pedestal)
4165 print("nro_file",nro_file)
4166 if utc_adq >utc_pedestal:
4167 print("DENTRO DEL IF-SETUP")
4168 ff_pedestal = self.list_pedestal[nro_file]
4169 if 0<(utc_adq - utc_pedestal)<(self.t_Interval_p*self.n_Muestras_p):
4170 nro_file= nro_file
4171 ff_pedestal = self.list_pedestal[nro_file]
4172 ready = 1
4173 if (utc_adq-utc_pedestal)>(self.t_Interval_p*self.n_Muestras_p):
4174 nro_tmp= int((utc_adq-utc_pedestal)/(self.n_Muestras_p))
4175 nro_file= nro_file+1*nro_tmp#chsssssssssssssssssssasssddasdas/ equear esta condicion
4176 if nro_tmp==0:
4177 nro_file= nro_file +1
4178 ff_pedestal = self.list_pedestal[nro_file]
4179 print("",ff_pedestal)
4180 utc_pedestal = self.gettimeutcfromDirFilename(path=self.path_ped,file=ff_pedestal)
4181 else:
4182 print("DENTRO DEL ELSE-SETUP")
4183 nro_tmp= int((utc_pedestal-utc_adq)/(self.n_Muestras_p))
4184 if utc_pedestal>utc_adq and nro_tmp==0:
4185 nro_tmp= int((utc_pedestal-utc_adq))
4186 print("nro_tmp",nro_tmp)
4187 if nro_file>nro_tmp:
4188 nro_file = nro_file-1*nro_tmp
4189 else:
4190 nro_file =nro_file -1
4191
4192 ff_pedestal = self.list_pedestal[nro_file]
4193 utc_pedestal = self.gettimeutcfromDirFilename(path=self.path_ped,file=ff_pedestal)
4194
4195 if ready:
4196 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4197 nro_key_p = int((utc_adq-utc_pedestal)/self.t_Interval_p)
4198 print("nro_file :",nro_file)
4199 print("name_file :",ff_pedestal)
4200 print("utc_pedestal_file :",utc_pedestal)
4201 print("nro_key_p :",nro_key_p)
4202 print("utc_pedestal_init :",utc_pedestal+nro_key_p*self.t_Interval_p)
4203 print("angulo_array :",angulo[nro_key_p])
4204 flag=1
4205 flag_i=1
4206 else:
4207 print("La lista de archivos de pedestal o adq esta vacia")
4208 nro_file=None
4209 nro_key_p=None
4210 self.nro_file = nro_file
4211 self.nro_key_p = nro_key_p
4212 '''
4213
4214 def setup(self,dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4150 def setup(self,dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4215 self.__dataReady = False
4151 self.__dataReady = False
4216 self.path_ped = path_ped
4152 self.path_ped = path_ped
4217 self.path_adq = path_adq
4153 self.path_adq = path_adq
4218 self.t_Interval_p = t_Interval_p
4154 self.t_Interval_p = t_Interval_p
4219 self.n_Muestras_p = n_Muestras_p
4155 self.n_Muestras_p = n_Muestras_p
4220 self.blocksPerfile= blocksPerfile
4156 self.blocksPerfile= blocksPerfile
4221 self.f_a_p = f_a_p
4157 self.f_a_p = f_a_p
4222 self.online = online
4158 self.online = online
4223 self.angulo_adq = numpy.zeros(self.blocksPerfile)
4159 self.angulo_adq = numpy.zeros(self.blocksPerfile)
4224 self.__profIndex = 0
4160 self.__profIndex = 0
4225 self.tmp = 0
4161 self.tmp = 0
4226 self.c_ped = 0
4162 self.c_ped = 0
4227 print(self.path_ped)
4163 print(self.path_ped)
4228 print(self.path_adq)
4164 print(self.path_adq)
4229 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4165 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4230 print("LIST NEW", self.list_pedestal[:20])
4166 print("LIST NEW", self.list_pedestal[:20])
4231 self.list_adq = self.getfirstFilefromPath(path=self.path_adq,meta="D",ext=".hdf5")
4167 self.list_adq = self.getfirstFilefromPath(path=self.path_adq,meta="D",ext=".hdf5")
4232 print("*************Longitud list pedestal****************",len(self.list_pedestal))
4168 print("*************Longitud list pedestal****************",len(self.list_pedestal))
4233
4169
4234 if self.online:
4170 if self.online:
4235 print("Enable Online")
4171 print("Enable Online")
4236 self.setup_online(dataOut)
4172 self.setup_online(dataOut)
4237 else:
4173 else:
4238 self.setup_offline(list_pedestal=self.list_pedestal,list_adq=self.list_adq)
4174 self.setup_offline(dataOut,list_pedestal=self.list_pedestal,list_adq=self.list_adq)
4239
4175
4240 def setNextFileP(self,dataOut):
4176 def setNextFileP(self,dataOut):
4241 if self.online:
4177 if self.online:
4242 data_pedestal = self.setNextFileonline()
4178 data_pedestal = self.setNextFileonline()
4243 else:
4179 else:
4244 data_pedestal = self.setNextFileoffline()
4180 data_pedestal = self.setNextFileoffline(dataOut)
4245
4181
4246 return data_pedestal
4182 return data_pedestal
4247
4183
4248
4184
4249 def setNextFileoffline(self):
4185 def setNextFileoffline(self,dataOut):
4250 ##tmp=0
4186 ##tmp=0
4251 for j in range(self.blocksPerfile):
4187 for j in range(self.blocksPerfile):
4252 ###print("NUMERO DEL BLOQUE---->",j)
4188 ###print("NUMERO DEL BLOQUE---->",j)
4253 ###print("nro_key_p",self.nro_key_p)
4189 ###print("nro_key_p",self.nro_key_p)
4254
4190
4255 #iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4191 #iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4256 iterador = self.nro_key_p +self.f_a_p*self.c_ped
4192 iterador = self.nro_key_p +self.f_a_p*self.c_ped
4257 self.c_ped = self.c_ped +1
4193 self.c_ped = self.c_ped +1
4258
4194
4259 ###print("iterador------------->",iterador)
4195 ###print("iterador------------->",iterador)
4260 if iterador < self.n_Muestras_p:
4196 if iterador < self.n_Muestras_p:
4261 self.nro_file = self.nro_file
4197 self.nro_file = self.nro_file
4262 else:
4198 else:
4263 self.nro_file = self.nro_file+1
4199 self.nro_file = self.nro_file+1
4200 print("PRUEBA-------------")
4201 utc_ped_setnext=self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[self.nro_file])
4202 utc_adq_setnext=dataOut.utctime
4203 print("utc_pedestal",utc_ped_setnext)
4204 print("utc_adq",utc_adq_setnext)
4205
4206
4264 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(self.c_ped-2))
4207 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(self.c_ped-2))
4265 self.c_ped = 1
4208 self.c_ped = 1
4266 ##tmp = j
4209 ##tmp = j
4267 ##print("tmp else",tmp)
4210 ##print("tmp else",tmp)
4268 self.nro_key_p= self.f_a_p-dif
4211 self.nro_key_p= self.f_a_p-dif
4269 iterador = self.nro_key_p
4212 iterador = self.nro_key_p
4270 ###print("iterador else",iterador)
4213 ###print("iterador else",iterador)
4271 #self.c_ped = self.c_ped +1
4214 #self.c_ped = self.c_ped +1
4272
4215
4273 ###print("nro_file",self.nro_file)
4216 ###print("nro_file",self.nro_file)
4274 #print("tmp",tmp)
4217 #print("tmp",tmp)
4275 try:
4218 try:
4276 ff_pedestal = self.list_pedestal[self.nro_file]
4219 ff_pedestal = self.list_pedestal[self.nro_file]
4220 print("ff_pedestal",ff_pedestal)
4277 except:
4221 except:
4222 print("############# EXCEPCION ######################")
4278 return numpy.ones(self.blocksPerfile)*numpy.nan
4223 return numpy.ones(self.blocksPerfile)*numpy.nan
4279
4224
4280 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4225 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4281 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4226 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4282
4227
4283 self.angulo_adq[j]= angulo[iterador]
4228 self.angulo_adq[j]= angulo[iterador]
4284
4229
4285 return self.angulo_adq
4230 return self.angulo_adq
4286
4231
4287 def setNextFileonline(self):
4232 def setNextFileonline(self):
4288 tmp = 0
4233 tmp = 0
4289 self.nTries_p = 3
4234 self.nTries_p = 3
4290 self.delay = 3
4235 self.delay = 3
4291 ready = 1
4236 ready = 1
4292 for j in range(self.blocksPerfile):
4237 for j in range(self.blocksPerfile):
4293 iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4238 iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4294 if iterador < self.n_Muestras_p:
4239 if iterador < self.n_Muestras_p:
4295 self.nro_file = self.nro_file
4240 self.nro_file = self.nro_file
4296 else:
4241 else:
4297 self.nro_file = self.nro_file+1
4242 self.nro_file = self.nro_file+1
4298 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(j-tmp-1))
4243 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(j-tmp-1))
4299 tmp = j
4244 tmp = j
4300 self.nro_key_p= self.f_a_p-dif
4245 self.nro_key_p= self.f_a_p-dif
4301 iterador = self.nro_key_p
4246 iterador = self.nro_key_p
4302 #print("nro_file---------------- :",self.nro_file)
4247 #print("nro_file---------------- :",self.nro_file)
4303 try:
4248 try:
4304 # update list_pedestal
4249 # update list_pedestal
4305 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4250 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4306 ff_pedestal = self.list_pedestal[self.nro_file]
4251 ff_pedestal = self.list_pedestal[self.nro_file]
4307 except:
4252 except:
4308 ff_pedestal = None
4253 ff_pedestal = None
4309 ready = 0
4254 ready = 0
4310 for nTries_p in range(self.nTries_p):
4255 for nTries_p in range(self.nTries_p):
4311 try:
4256 try:
4312 # update list_pedestal
4257 # update list_pedestal
4313 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4258 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4314 ff_pedestal = self.list_pedestal[self.nro_file]
4259 ff_pedestal = self.list_pedestal[self.nro_file]
4315 except:
4260 except:
4316 ff_pedestal = None
4261 ff_pedestal = None
4317 if ff_pedestal is not None:
4262 if ff_pedestal is not None:
4318 ready=1
4263 ready=1
4319 break
4264 break
4320 log.warning("Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, self.nro_file, nTries_p + 1))
4265 log.warning("Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, self.nro_file, nTries_p + 1))
4321 time.sleep(self.delay)
4266 time.sleep(self.delay)
4322 continue
4267 continue
4323 #return numpy.ones(self.blocksPerfile)*numpy.nan
4268 #return numpy.ones(self.blocksPerfile)*numpy.nan
4324
4269
4325 if ready == 1:
4270 if ready == 1:
4326 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4271 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4327 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4272 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4328
4273
4329 else:
4274 else:
4330 print("there is no pedestal file")
4275 print("there is no pedestal file")
4331 angulo = numpy.ones(self.n_Muestras_p)*numpy.nan
4276 angulo = numpy.ones(self.n_Muestras_p)*numpy.nan
4332 self.angulo_adq[j]= angulo[iterador]
4277 self.angulo_adq[j]= angulo[iterador]
4333 ####print("Angulo",self.angulo_adq)
4278 ####print("Angulo",self.angulo_adq)
4334 ####print("Angulo",len(self.angulo_adq))
4279 ####print("Angulo",len(self.angulo_adq))
4335 #self.nro_key_p=iterador + self.f_a_p
4280 #self.nro_key_p=iterador + self.f_a_p
4336 #if self.nro_key_p< self.n_Muestras_p:
4281 #if self.nro_key_p< self.n_Muestras_p:
4337 # self.nro_file = self.nro_file
4282 # self.nro_file = self.nro_file
4338 #else:
4283 #else:
4339 # self.nro_file = self.nro_file+1
4284 # self.nro_file = self.nro_file+1
4340 # self.nro_key_p= self.nro_key_p
4285 # self.nro_key_p= self.nro_key_p
4341 return self.angulo_adq
4286 return self.angulo_adq
4342
4287
4343
4288
4344 def run(self, dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4289 def run(self, dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4345 if not self.isConfig:
4290 if not self.isConfig:
4291 print("######################SETUP#########################################")
4346 self.setup( dataOut, path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online)
4292 self.setup( dataOut, path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online)
4347 self.isConfig = True
4293 self.isConfig = True
4348
4294
4349 dataOut.flagNoData = True
4295 dataOut.flagNoData = True
4350 #print("profIndex",self.__profIndex)
4296 #print("profIndex",self.__profIndex)
4351
4297
4352 if self.__profIndex==0:
4298 if self.__profIndex==0:
4353 angulo_adq = self.setNextFileP(dataOut)
4299 angulo_adq = self.setNextFileP(dataOut)
4354 dataOut.azimuth = angulo_adq
4300 dataOut.azimuth = angulo_adq
4301 print("TIEMPO:",dataOut.utctime)
4355 ##print("####################################################################")
4302 ##print("####################################################################")
4356 ##print("angulos",dataOut.azimuth,len(dataOut.azimuth))
4303 ##print("angulos",dataOut.azimuth,len(dataOut.azimuth))
4357 self.__dataReady = True
4304 self.__dataReady = True
4358 self.__profIndex += 1
4305 self.__profIndex += 1
4306 print("TIEMPO_bucle:",dataOut.utctime)
4359 if self.__profIndex== blocksPerfile:
4307 if self.__profIndex== blocksPerfile:
4360 self.__profIndex = 0
4308 self.__profIndex = 0
4361 if self.__dataReady:
4309 if self.__dataReady:
4362 #print(self.__profIndex,dataOut.azimuth[:10])
4310 #print(self.__profIndex,dataOut.azimuth[:10])
4363 dataOut.flagNoData = False
4311 dataOut.flagNoData = False
4364 return dataOut
4312 return dataOut
4365
4313
4366
4314
4367 class Block360(Operation):
4315 class Block360(Operation):
4368 '''
4316 '''
4369 '''
4317 '''
4370 isConfig = False
4318 isConfig = False
4371 __profIndex = 0
4319 __profIndex = 0
4372 __initime = None
4320 __initime = None
4373 __lastdatatime = None
4321 __lastdatatime = None
4374 __buffer = None
4322 __buffer = None
4375 __dataReady = False
4323 __dataReady = False
4376 n = None
4324 n = None
4377 __nch = 0
4325 __nch = 0
4378 __nHeis = 0
4326 __nHeis = 0
4379 index = 0
4327 index = 0
4380
4328
4381 def __init__(self,**kwargs):
4329 def __init__(self,**kwargs):
4382 Operation.__init__(self,**kwargs)
4330 Operation.__init__(self,**kwargs)
4383
4331
4384 def setup(self, dataOut, n = None):
4332 def setup(self, dataOut, n = None):
4385 '''
4333 '''
4386 n= Numero de PRF's de entrada
4334 n= Numero de PRF's de entrada
4387 '''
4335 '''
4388 self.__initime = None
4336 self.__initime = None
4389 self.__lastdatatime = 0
4337 self.__lastdatatime = 0
4390 self.__dataReady = False
4338 self.__dataReady = False
4391 self.__buffer = 0
4339 self.__buffer = 0
4392 self.__buffer_1D = 0
4340 self.__buffer_1D = 0
4393 self.__profIndex = 0
4341 self.__profIndex = 0
4394 self.index = 0
4342 self.index = 0
4395 self.__nch = dataOut.nChannels
4343 self.__nch = dataOut.nChannels
4396 self.__nHeis = dataOut.nHeights
4344 self.__nHeis = dataOut.nHeights
4397 ##print("ELVALOR DE n es:", n)
4345 ##print("ELVALOR DE n es:", n)
4398 if n == None:
4346 if n == None:
4399 raise ValueError("n should be specified.")
4347 raise ValueError("n should be specified.")
4400
4348
4401 if n != None:
4349 if n != None:
4402 if n<1:
4350 if n<1:
4403 print("n should be greater than 2")
4351 print("n should be greater than 2")
4404 raise ValueError("n should be greater than 2")
4352 raise ValueError("n should be greater than 2")
4405
4353
4406 self.n = n
4354 self.n = n
4407 #print("nHeights")
4355 #print("nHeights")
4408 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4356 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4409 self.__buffer2= numpy.zeros(n)
4357 self.__buffer2= numpy.zeros(n)
4410
4358
4411 def putData(self,data):
4359 def putData(self,data):
4412 '''
4360 '''
4413 Add a profile to he __buffer and increase in one the __profiel Index
4361 Add a profile to he __buffer and increase in one the __profiel Index
4414 '''
4362 '''
4415 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4363 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4416 #print("line 4049",data.azimuth.shape,data.azimuth)
4364 #print("line 4049",data.azimuth.shape,data.azimuth)
4417 self.__buffer[:,self.__profIndex,:]= data.dataPP_POW
4365 self.__buffer[:,self.__profIndex,:]= data.dataPP_POW
4418 #print("me casi",self.index,data.azimuth[self.index])
4366 #print("me casi",self.index,data.azimuth[self.index])
4419 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4367 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4420 #print("magic",data.profileIndex)
4368 #print("magic",data.profileIndex)
4421 #print(data.azimuth[self.index])
4369 #print(data.azimuth[self.index])
4422 #print("index",self.index)
4370 #print("index",self.index)
4423
4371
4424 self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4372 self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4425 #print("q pasa")
4373 #print("q pasa")
4426 self.index+=1
4374 self.index+=1
4427 #print("index",self.index,data.azimuth[:10])
4375 #print("index",self.index,data.azimuth[:10])
4428 self.__profIndex += 1
4376 self.__profIndex += 1
4429 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4377 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4430
4378
4431 def pushData(self,data):
4379 def pushData(self,data):
4432 '''
4380 '''
4433 Return the PULSEPAIR and the profiles used in the operation
4381 Return the PULSEPAIR and the profiles used in the operation
4434 Affected : self.__profileIndex
4382 Affected : self.__profileIndex
4435 '''
4383 '''
4436 #print("pushData")
4384 #print("pushData")
4437
4385
4438 data_360 = self.__buffer
4386 data_360 = self.__buffer
4439 data_p = self.__buffer2
4387 data_p = self.__buffer2
4440 n = self.__profIndex
4388 n = self.__profIndex
4441
4389
4442 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4390 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4443 self.__buffer2 = numpy.zeros(self.n)
4391 self.__buffer2 = numpy.zeros(self.n)
4444 self.__profIndex = 0
4392 self.__profIndex = 0
4445 #print("pushData")
4393 #print("pushData")
4446 return data_360,n,data_p
4394 return data_360,n,data_p
4447
4395
4448
4396
4449 def byProfiles(self,dataOut):
4397 def byProfiles(self,dataOut):
4450
4398
4451 self.__dataReady = False
4399 self.__dataReady = False
4452 data_360 = None
4400 data_360 = None
4453 data_p = None
4401 data_p = None
4454 #print("dataOu",dataOut.dataPP_POW)
4402 #print("dataOu",dataOut.dataPP_POW)
4455 self.putData(data=dataOut)
4403 self.putData(data=dataOut)
4456 #print("profIndex",self.__profIndex)
4404 #print("profIndex",self.__profIndex)
4457 if self.__profIndex == self.n:
4405 if self.__profIndex == self.n:
4458 data_360,n,data_p = self.pushData(data=dataOut)
4406 data_360,n,data_p = self.pushData(data=dataOut)
4459 self.__dataReady = True
4407 self.__dataReady = True
4460
4408
4461 return data_360,data_p
4409 return data_360,data_p
4462
4410
4463
4411
4464 def blockOp(self, dataOut, datatime= None):
4412 def blockOp(self, dataOut, datatime= None):
4465 if self.__initime == None:
4413 if self.__initime == None:
4466 self.__initime = datatime
4414 self.__initime = datatime
4467 data_360,data_p = self.byProfiles(dataOut)
4415 data_360,data_p = self.byProfiles(dataOut)
4468 self.__lastdatatime = datatime
4416 self.__lastdatatime = datatime
4469
4417
4470 if data_360 is None:
4418 if data_360 is None:
4471 return None, None,None
4419 return None, None,None
4472
4420
4473 avgdatatime = self.__initime
4421 avgdatatime = self.__initime
4474 deltatime = datatime - self.__lastdatatime
4422 deltatime = datatime - self.__lastdatatime
4475 self.__initime = datatime
4423 self.__initime = datatime
4476 #print(data_360.shape,avgdatatime,data_p.shape)
4424 #print(data_360.shape,avgdatatime,data_p.shape)
4477 return data_360,avgdatatime,data_p
4425 return data_360,avgdatatime,data_p
4478
4426
4479 def run(self, dataOut,n = None,**kwargs):
4427 def run(self, dataOut,n = None,**kwargs):
4480
4428
4481 if not self.isConfig:
4429 if not self.isConfig:
4482 self.setup(dataOut = dataOut, n = n , **kwargs)
4430 self.setup(dataOut = dataOut, n = n , **kwargs)
4483 self.index = 0
4431 self.index = 0
4484 #print("comova",self.isConfig)
4432 #print("comova",self.isConfig)
4485 self.isConfig = True
4433 self.isConfig = True
4486 if self.index==dataOut.azimuth.shape[0]:
4434 if self.index==dataOut.azimuth.shape[0]:
4487 self.index=0
4435 self.index=0
4488 data_360, avgdatatime,data_p = self.blockOp(dataOut, dataOut.utctime)
4436 data_360, avgdatatime,data_p = self.blockOp(dataOut, dataOut.utctime)
4489 dataOut.flagNoData = True
4437 dataOut.flagNoData = True
4490
4438
4491 if self.__dataReady:
4439 if self.__dataReady:
4492 dataOut.data_360 = data_360 # S
4440 dataOut.data_360 = data_360 # S
4493 ##print("---------------------------------------------------------------------------------")
4441 ##print("---------------------------------------------------------------------------------")
4494 ##print("---------------------------DATAREADY---------------------------------------------")
4442 ##print("---------------------------DATAREADY---------------------------------------------")
4495 ##print("---------------------------------------------------------------------------------")
4443 ##print("---------------------------------------------------------------------------------")
4496 ##print("data_360",dataOut.data_360.shape)
4444 ##print("data_360",dataOut.data_360.shape)
4497 dataOut.data_azi = data_p
4445 dataOut.data_azi = data_p
4498 ##print("azi: ",dataOut.data_azi)
4446 ##print("azi: ",dataOut.data_azi)
4499 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4447 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4500 dataOut.utctime = avgdatatime
4448 dataOut.utctime = avgdatatime
4501 dataOut.flagNoData = False
4449 dataOut.flagNoData = False
4502 return dataOut
4450 return dataOut
@@ -1,127 +1,147
1 #!python
1 #!python
2 '''
2 '''
3 '''
3 '''
4
4
5 import os, sys
5 import os, sys
6 import datetime
6 import datetime
7 import time
7 import time
8
8
9 #path = os.path.dirname(os.getcwd())
9 #path = os.path.dirname(os.getcwd())
10 #path = os.path.dirname(path)
10 #path = os.path.dirname(path)
11 #sys.path.insert(0, path)
11 #sys.path.insert(0, path)
12
12
13 from schainpy.controller import Project
13 from schainpy.controller import Project
14
14
15 desc = "USRP_test"
15 desc = "USRP_test"
16 filename = "USRP_processing.xml"
16 filename = "USRP_processing.xml"
17 controllerObj = Project()
17 controllerObj = Project()
18 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
18 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
19
19
20 ############## USED TO PLOT IQ VOLTAGE, POWER AND SPECTRA #############
20 ############## USED TO PLOT IQ VOLTAGE, POWER AND SPECTRA #############
21
21
22 #######################################################################
22 #######################################################################
23 ######PATH DE LECTURA, ESCRITURA, GRAFICOS Y ENVIO WEB#################
23 ######PATH DE LECTURA, ESCRITURA, GRAFICOS Y ENVIO WEB#################
24 #######################################################################
24 #######################################################################
25 #path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman'
25 #path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman'
26 #path = '/DATA_RM/TEST_INTEGRACION'
26 #path = '/DATA_RM/TEST_INTEGRACION'
27 #path = '/DATA_RM/TEST_ONLINE'
27 #path = '/DATA_RM/TEST_ONLINE'
28 path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
28 #path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
29 path_pp = '/DATA_RM/TEST_HDF5'
29 # ULTIMO TEST 22 DE SEPTIEMBRE
30 path = '/DATA_RM/USRP_22'
31 #path_pp = '/DATA_RM/TEST_HDF5'
32 # UTIMO TEST 22 DE SEPTIEMBRE
33 path_pp = '/DATA_RM/TEST_HDF5_PP_22'
34 ######################################################
35 ##### OJO TENER EN CUENTA EL n= para el Pulse Pair ###
36 ######################################################
37 ######## BUSCAMOS EL numero de IPP equivalente 1Β°#####
38 ######## Sea V la velocidad del Pedestal en Β°/seg#####
39 ######## 1Β° sera Recorrido en un tiempo de 1/V ######
40 ######## IPP del Radar 400 useg --> 60 Km ############
41 ######## n = 1/(V*IPP) , NUMERO DE IPP #############
42 ######## n = 1/(V*IPP) #############################
43 V=2
44 IPP=400*1e-6
45 n= 1/(V*IPP)
46 print("n numero de Perfiles a procesar con Pulse Pair: ", n)
47
48
49
30
50
31 figpath = '/home/soporte/Pictures/TEST_INTEGRACION_IMG'
51 figpath = '/home/soporte/Pictures/TEST_INTEGRACION_IMG'
32 #remotefolder = "/home/wmaster/graficos"
52 #remotefolder = "/home/wmaster/graficos"
33 #######################################################################
53 #######################################################################
34 ################# RANGO DE PLOTEO######################################
54 ################# RANGO DE PLOTEO######################################
35 #######################################################################
55 #######################################################################
36 dBmin = '-5'
56 dBmin = '-5'
37 dBmax = '20'
57 dBmax = '20'
38 xmin = '0'
58 xmin = '0'
39 xmax ='24'
59 xmax ='24'
40 ymin = '0'
60 ymin = '0'
41 ymax = '600'
61 ymax = '600'
42 #######################################################################
62 #######################################################################
43 ########################FECHA##########################################
63 ########################FECHA##########################################
44 #######################################################################
64 #######################################################################
45 str = datetime.date.today()
65 str = datetime.date.today()
46 today = str.strftime("%Y/%m/%d")
66 today = str.strftime("%Y/%m/%d")
47 str2 = str - datetime.timedelta(days=1)
67 str2 = str - datetime.timedelta(days=1)
48 yesterday = str2.strftime("%Y/%m/%d")
68 yesterday = str2.strftime("%Y/%m/%d")
49 #######################################################################
69 #######################################################################
50 ######################## UNIDAD DE LECTURA#############################
70 ######################## UNIDAD DE LECTURA#############################
51 #######################################################################
71 #######################################################################
52 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
72 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
53 path=path,
73 path=path,
54 startDate="2021/01/01",#today,
74 startDate="2021/01/01",#today,
55 endDate="2021/12/30",#today,
75 endDate="2021/12/30",#today,
56 startTime='00:00:00',
76 startTime='00:00:00',
57 endTime='23:59:59',
77 endTime='23:59:59',
58 delay=0,
78 delay=0,
59 #set=0,
79 #set=0,
60 online=0,
80 online=0,
61 walk=1,
81 walk=1,
62 ippKm = 60)
82 ippKm = 60)
63
83
64 opObj11 = readUnitConfObj.addOperation(name='printInfo')
84 opObj11 = readUnitConfObj.addOperation(name='printInfo')
65 #opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
85 #opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
66 #######################################################################
86 #######################################################################
67 ################ OPERACIONES DOMINIO DEL TIEMPO########################
87 ################ OPERACIONES DOMINIO DEL TIEMPO########################
68 #######################################################################
88 #######################################################################
69
89
70 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
90 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
71
91
72 #
92 #
73 # codigo64='1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,1,0,1,1,1,0,0,0,1,0,'+\
93 # codigo64='1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,1,0,1,1,1,0,0,0,1,0,'+\
74 # '1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1'
94 # '1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1'
75
95
76 #opObj11 = procUnitConfObjA.addOperation(name='setRadarFrequency')
96 #opObj11 = procUnitConfObjA.addOperation(name='setRadarFrequency')
77 #opObj11.addParameter(name='frequency', value='70312500')
97 #opObj11.addParameter(name='frequency', value='70312500')
78 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
98 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
79 opObj11.addParameter(name='n', value='16', format='int')#10 VOY A USAR 250 DADO QUE LA VELOCIDAD ES 10 GRADOS
99 opObj11.addParameter(name='n', value=int(n), format='int')#10 VOY A USAR 250 DADO QUE LA VELOCIDAD ES 10 GRADOS
80 opObj11.addParameter(name='removeDC', value=1, format='int')
100 opObj11.addParameter(name='removeDC', value=1, format='int')
81 # Ploteo TEST
101 # Ploteo TEST
82 '''
102 '''
83 opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')
103 opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')
84 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
104 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
85 opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
105 opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
86 #opObj11.addParameter(name='xmax', value=8)
106 #opObj11.addParameter(name='xmax', value=8)
87 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSpecwidthPlot', optype='other')
107 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSpecwidthPlot', optype='other')
88 '''
108 '''
89 # OJO SCOPE
109 # OJO SCOPE
90 #opObj10 = procUnitConfObjA.addOperation(name='ScopePlot', optype='external')
110 #opObj10 = procUnitConfObjA.addOperation(name='ScopePlot', optype='external')
91 #opObj10.addParameter(name='id', value='10', format='int')
111 #opObj10.addParameter(name='id', value='10', format='int')
92 ##opObj10.addParameter(name='xmin', value='0', format='int')
112 ##opObj10.addParameter(name='xmin', value='0', format='int')
93 ##opObj10.addParameter(name='xmax', value='50', format='int')
113 ##opObj10.addParameter(name='xmax', value='50', format='int')
94 #opObj10.addParameter(name='type', value='iq')
114 #opObj10.addParameter(name='type', value='iq')
95 ##opObj10.addParameter(name='ymin', value='-5000', format='int')
115 ##opObj10.addParameter(name='ymin', value='-5000', format='int')
96 ##opObj10.addParameter(name='ymax', value='8500', format='int')
116 ##opObj10.addParameter(name='ymax', value='8500', format='int')
97 #opObj11.addParameter(name='save', value=figpath, format='str')
117 #opObj11.addParameter(name='save', value=figpath, format='str')
98 #opObj11.addParameter(name='save_period', value=10, format='int')
118 #opObj11.addParameter(name='save_period', value=10, format='int')
99
119
100 #opObj10 = procUnitConfObjA.addOperation(name='setH0')
120 #opObj10 = procUnitConfObjA.addOperation(name='setH0')
101 #opObj10.addParameter(name='h0', value='-5000', format='float')
121 #opObj10.addParameter(name='h0', value='-5000', format='float')
102
122
103 #opObj11 = procUnitConfObjA.addOperation(name='filterByHeights')
123 #opObj11 = procUnitConfObjA.addOperation(name='filterByHeights')
104 #opObj11.addParameter(name='window', value='1', format='int')
124 #opObj11.addParameter(name='window', value='1', format='int')
105
125
106 #codigo='1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,1,1,1,-1,-1,-1'
126 #codigo='1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,1,1,1,-1,-1,-1'
107 #opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other')
127 #opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other')
108 #opObj11.addParameter(name='code', value=codigo, formatyesterday='floatlist')
128 #opObj11.addParameter(name='code', value=codigo, formatyesterday='floatlist')
109 #opObj11.addParameter(name='nCode', value='1', format='int')
129 #opObj11.addParameter(name='nCode', value='1', format='int')
110 #opObj11.addParameter(name='nBaud', value='28', format='int')
130 #opObj11.addParameter(name='nBaud', value='28', format='int')
111
131
112 #opObj11 = procUnitConfObjA.addOperation(name='CohInt', optype='other')
132 #opObj11 = procUnitConfObjA.addOperation(name='CohInt', optype='other')
113 #opObj11.addParameter(name='n', value='100', format='int')
133 #opObj11.addParameter(name='n', value='100', format='int')
114
134
115 #######################################################################
135 #######################################################################
116 ########## OPERACIONES ParametersProc########################
136 ########## OPERACIONES ParametersProc########################
117 #######################################################################
137 #######################################################################
118
138
119 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
139 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
120 opObj10 = procUnitConfObjB.addOperation(name='HDFWriter')
140 opObj10 = procUnitConfObjB.addOperation(name='HDFWriter')
121 opObj10.addParameter(name='path',value=path_pp)
141 opObj10.addParameter(name='path',value=path_pp)
122 #opObj10.addParameter(name='mode',value=0)
142 #opObj10.addParameter(name='mode',value=0)
123 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
143 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
124 opObj10.addParameter(name='metadataList',value='utctimeInit,timeZone,paramInterval,profileIndex,channelList,heightList,flagDataAsBlock',format='list')
144 opObj10.addParameter(name='metadataList',value='utctimeInit,timeZone,paramInterval,profileIndex,channelList,heightList,flagDataAsBlock',format='list')
125 opObj10.addParameter(name='dataList',value='dataPP_POW,dataPP_DOP,utctime',format='list')#,format='list'
145 opObj10.addParameter(name='dataList',value='dataPP_POW,dataPP_DOP,utctime',format='list')#,format='list'
126
146
127 controllerObj.start()
147 controllerObj.start()
@@ -1,146 +1,157
1 #!python
1 #!python
2 '''
2 '''
3 '''
3 '''
4
4
5 import os, sys
5 import os, sys
6 import datetime
6 import datetime
7 import time
7 import time
8
8
9 #path = os.path.dirname(os.getcwd())
9 #path = os.path.dirname(os.getcwd())
10 #path = os.path.dirname(path)
10 #path = os.path.dirname(path)
11 #sys.path.insert(0, path)
11 #sys.path.insert(0, path)
12
12
13 from schainpy.controller import Project
13 from schainpy.controller import Project
14
14
15 desc = "USRP_test"
15 desc = "USRP_test"
16 filename = "USRP_processing.xml"
16 filename = "USRP_processing.xml"
17 controllerObj = Project()
17 controllerObj = Project()
18 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
18 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
19
19
20 ############## USED TO PLOT IQ VOLTAGE, POWER AND SPECTRA #############
20 ############## USED TO PLOT IQ VOLTAGE, POWER AND SPECTRA #############
21
21
22 #######################################################################
22 #######################################################################
23 ######PATH DE LECTURA, ESCRITURA, GRAFICOS Y ENVIO WEB#################
23 ######PATH DE LECTURA, ESCRITURA, GRAFICOS Y ENVIO WEB#################
24 #######################################################################
24 #######################################################################
25 #path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman'
25 #path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman'
26 #path = '/DATA_RM/TEST_INTEGRACION'
26 #path = '/DATA_RM/TEST_INTEGRACION'
27 #path = '/DATA_RM/TEST_ONLINE'
27 #path = '/DATA_RM/TEST_ONLINE'
28 #path_pp = '/DATA_RM/TEST_HDF5'
28 #path_pp = '/DATA_RM/TEST_HDF5'
29
29
30 #figpath = '/home/soporte/Pictures/TEST_INTEGRACION_IMG'
30 #figpath = '/home/soporte/Pictures/TEST_INTEGRACION_IMG'
31 path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
31 ###path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
32 path_pp = '/DATA_RM/TEST_HDF5_SPEC'
32 ###path_pp = '/DATA_RM/TEST_HDF5_SPEC'
33
34
35
33
34 #path = '/DATA_RM/USRP_22'
35 path = '/DATA_RM/23/6v'
36 #path_pp = '/DATA_RM/TEST_HDF5'
37 # UTIMO TEST 22 DE SEPTIEMBRE
38 #path_pp = '/DATA_RM/TEST_HDF5_SPEC_22'
39 #path_pp = '/DATA_RM/TEST_HDF5_SPEC_3v'
40 path_pp = '/DATA_RM/TEST_HDF5_SPEC_23/6v'
36
41
37
42
38 #remotefolder = "/home/wmaster/graficos"
43 #remotefolder = "/home/wmaster/graficos"
39 #######################################################################
44 #######################################################################
40 ################# RANGO DE PLOTEO######################################
45 ################# RANGO DE PLOTEO######################################
41 #######################################################################
46 #######################################################################
42 dBmin = '-5'
47 dBmin = '-5'
43 dBmax = '20'
48 dBmax = '20'
44 xmin = '0'
49 xmin = '0'
45 xmax ='24'
50 xmax ='24'
46 ymin = '0'
51 ymin = '0'
47 ymax = '600'
52 ymax = '600'
48 #######################################################################
53 #######################################################################
49 ########################FECHA##########################################
54 ########################FECHA##########################################
50 #######################################################################
55 #######################################################################
51 str = datetime.date.today()
56 str = datetime.date.today()
52 today = str.strftime("%Y/%m/%d")
57 today = str.strftime("%Y/%m/%d")
53 str2 = str - datetime.timedelta(days=1)
58 str2 = str - datetime.timedelta(days=1)
54 yesterday = str2.strftime("%Y/%m/%d")
59 yesterday = str2.strftime("%Y/%m/%d")
55 #######################################################################
60 #######################################################################
56 ######################## UNIDAD DE LECTURA#############################
61 ######################## UNIDAD DE LECTURA#############################
57 #######################################################################
62 #######################################################################
58 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
63 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
59 path=path,
64 path=path,
60 startDate="2021/01/01",#today,
65 startDate="2021/01/01",#today,
61 endDate="2021/12/30",#today,
66 endDate="2021/12/30",#today,
62 startTime='00:00:00',
67 startTime='00:00:00',
63 endTime='23:59:59',
68 endTime='23:59:59',
64 delay=0,
69 delay=0,
65 #set=0,
70 #set=0,
66 online=0,
71 online=0,
67 walk=1,
72 walk=1,
68 ippKm = 60)
73 ippKm = 60)
69
74
70 opObj11 = readUnitConfObj.addOperation(name='printInfo')
75 opObj11 = readUnitConfObj.addOperation(name='printInfo')
71 #opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
76 #opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
72 #######################################################################
77 #######################################################################
73 ################ OPERACIONES DOMINIO DEL TIEMPO########################
78 ################ OPERACIONES DOMINIO DEL TIEMPO########################
74 #######################################################################
79 #######################################################################
75
80
81
82 V=6
83 IPP=400*1e-6
84 n= int(1/(V*IPP))
85 print("n numero de Perfiles a procesar con nFFTPoints ", n)
86
76 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
87 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
77
88
78 procUnitConfObjB = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
89 procUnitConfObjB = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
79 procUnitConfObjB.addParameter(name='nFFTPoints', value=250, format='int')
90 procUnitConfObjB.addParameter(name='nFFTPoints', value=n, format='int')
80 procUnitConfObjB.addParameter(name='nProfiles' , value=250, format='int')
91 procUnitConfObjB.addParameter(name='nProfiles' , value=n, format='int')
81
92
82
93
83
94
84 #
95 #
85 # codigo64='1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,1,0,1,1,1,0,0,0,1,0,'+\
96 # codigo64='1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,1,0,1,1,1,0,0,0,1,0,'+\
86 # '1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1'
97 # '1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1'
87
98
88 #opObj11 = procUnitConfObjA.addOperation(name='setRadarFrequency')
99 #opObj11 = procUnitConfObjA.addOperation(name='setRadarFrequency')
89 #opObj11.addParameter(name='frequency', value='70312500')
100 #opObj11.addParameter(name='frequency', value='70312500')
90 #opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
101 #opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
91 #opObj11.addParameter(name='n', value='625', format='int')#10
102 #opObj11.addParameter(name='n', value='625', format='int')#10
92 #opObj11.addParameter(name='removeDC', value=1, format='int')
103 #opObj11.addParameter(name='removeDC', value=1, format='int')
93
104
94 # Ploteo TEST
105 # Ploteo TEST
95 '''
106 '''
96 opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')
107 opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')
97 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
108 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
98 opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
109 opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
99 #opObj11.addParameter(name='xmax', value=8)
110 #opObj11.addParameter(name='xmax', value=8)
100 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSpecwidthPlot', optype='other')
111 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSpecwidthPlot', optype='other')
101 '''
112 '''
102 # OJO SCOPE
113 # OJO SCOPE
103 #opObj10 = procUnitConfObjA.addOperation(name='ScopePlot', optype='external')
114 #opObj10 = procUnitConfObjA.addOperation(name='ScopePlot', optype='external')
104 #opObj10.addParameter(name='buffer_sizeid', value='10', format='int')
115 #opObj10.addParameter(name='buffer_sizeid', value='10', format='int')
105 ##opObj10.addParameter(name='xmin', value='0', format='int')
116 ##opObj10.addParameter(name='xmin', value='0', format='int')
106 ##opObj10.addParameter(name='xmax', value='50', format='int')
117 ##opObj10.addParameter(name='xmax', value='50', format='int')
107 #opObj10.addParameter(name='type', value='iq')
118 #opObj10.addParameter(name='type', value='iq')
108 ##opObj10.addParameter(name='ymin', value='-5000', format='int')
119 ##opObj10.addParameter(name='ymin', value='-5000', format='int')
109 ##opObj10.addParameter(name='ymax', value='8500', format='int')
120 ##opObj10.addParameter(name='ymax', value='8500', format='int')
110 #opObj11.addParameter(name='save', value=figpath, format='str')
121 #opObj11.addParameter(name='save', value=figpath, format='str')
111 #opObj11.addParameter(name='save_period', value=10, format='int')
122 #opObj11.addParameter(name='save_period', value=10, format='int')
112
123
113 #opObj10 = procUnitConfObjA.addOperation(name='setH0')
124 #opObj10 = procUnitConfObjA.addOperation(name='setH0')
114 #opObj10.addParameter(name='h0', value='-5000', format='float')
125 #opObj10.addParameter(name='h0', value='-5000', format='float')
115
126
116 #opObj11 = procUnitConfObjA.addOperation(name='filterByHeights')
127 #opObj11 = procUnitConfObjA.addOperation(name='filterByHeights')
117 #opObj11.addParameter(name='window', value='1', format='int')
128 #opObj11.addParameter(name='window', value='1', format='int')
118
129
119 #codigo='1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,1,1,1,-1,-1,-1'
130 #codigo='1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,1,1,1,-1,-1,-1'
120 #opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other')
131 #opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other')
121 #opObj11.addParameter(name='code', value=codigo, formatyesterday='floatlist')
132 #opObj11.addParameter(name='code', value=codigo, formatyesterday='floatlist')
122 #opObj11.addParameter(name='nCode', value='1', format='int')
133 #opObj11.addParameter(name='nCode', value='1', format='int')
123 #opObj11.addParameter(name='nBaud', value='28', format='int')
134 #opObj11.addParameter(name='nBaud', value='28', format='int')
124
135
125 #opObj11 = procUnitConfObjA.addOperation(name='CohInt', optype='other')
136 #opObj11 = procUnitConfObjA.addOperation(name='CohInt', optype='other')
126 #opObj11.addParameter(name='n', value='100', format='int')
137 #opObj11.addParameter(name='n', value='100', format='int')
127
138
128 #######################################################################
139 #######################################################################
129 ########## OPERACIONES ParametersProc########################
140 ########## OPERACIONES ParametersProc########################
130 #######################################################################
141 #######################################################################
131
142
132 procUnitConfObjC= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjB.getId())
143 procUnitConfObjC= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjB.getId())
133
144
134 procUnitConfObjC.addOperation(name='SpectralMoments')
145 procUnitConfObjC.addOperation(name='SpectralMoments')
135
146
136
147
137 opObj10 = procUnitConfObjC.addOperation(name='HDFWriter')
148 opObj10 = procUnitConfObjC.addOperation(name='HDFWriter')
138 opObj10.addParameter(name='path',value=path_pp)
149 opObj10.addParameter(name='path',value=path_pp)
139 #opObj10.addParameter(name='mode',value=0)
150 #opObj10.addParameter(name='mode',value=0)
140 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
151 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
141 #opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
152 #opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
142 opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
153 opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
143
154
144 opObj10.addParameter(name='dataList',value='data_pow,data_dop,utctime',format='list')#,format='list'
155 opObj10.addParameter(name='dataList',value='data_pow,data_dop,utctime',format='list')#,format='list'
145
156
146 controllerObj.start()
157 controllerObj.start()
@@ -1,64 +1,75
1 import os,sys
1 import os,sys
2 import datetime
2 import datetime
3 import time
3 import time
4 from schainpy.controller import Project
4 from schainpy.controller import Project
5 #path='/DATA_RM/TEST_HDF5/d2021200'
5 #path='/DATA_RM/TEST_HDF5/d2021200'
6 #path='/DATA_RM/TEST_HDF5/d2021200'
6 #path='/DATA_RM/TEST_HDF5/d2021200'
7 #path='/DATA_RM/TEST_HDF5/d2021214'
7 #path='/DATA_RM/TEST_HDF5/d2021214'
8 #path='/DATA_RM/TEST_HDF5/d2021229'
8 #path='/DATA_RM/TEST_HDF5/d2021229'
9
9
10 #path='/DATA_RM/TEST_HDF5/d2021231'
10 #path='/DATA_RM/TEST_HDF5/d2021231'
11 #path='/DATA_RM/TEST_HDF5/ADQ_OFFLINE/d2021231'
11 #path='/DATA_RM/TEST_HDF5/ADQ_OFFLINE/d2021231'
12 path='/DATA_RM/TEST_HDF5/d2021231'
12 path='/DATA_RM/TEST_HDF5/d2021231'
13
13 #path='/DATA_RM/TEST_14_HDF5/d2021257'
14 ## TEST ULTIMA PRUEBA 22 DE SEPTIEMBRE
15 path = '/DATA_RM/TEST_HDF5_PP_22/d2021265'
14 path_adq=path
16 path_adq=path
15 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021200'
17 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021200'
16 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021214'
18 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021214'
17 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021230'
19 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021230'
18 #path_ped='/DATA_RM/TEST_PEDESTAL/P20210819'
20 #path_ped='/DATA_RM/TEST_PEDESTAL/P20210819'
19 #path_ped='/DATA_RM/TEST_PEDESTAL/P20210819-154315'
21 #path_ped='/DATA_RM/TEST_PEDESTAL/P20210819-154315'
20 path_ped='/DATA_RM/TEST_PEDESTAL/PEDESTAL_OFFLINE/P20210819-161524'
22 #path_ped='/DATA_RM/TEST_PEDESTAL/P20210914-162434'
23 #path_ped='/DATA_RM/TEST_PEDESTAL/PEDESTAL_OFFLINE/P20210819-161524'
24 #pruebas con perdida de datos
25 #path_ped='/DATA_RM/TEST_PEDESTAL/PEDESTAL_OFFLINE/P20210819-161524_TEST'
26 ## TEST ULTIMA PRUEBA 22 DE SEPTIEMBRE
27 path_ped='/DATA_RM/TEST_PEDESTAL/P20210922-122731'
21
28
22
29
23 figpath = '/home/soporte/Pictures'
30 figpath = '/home/soporte/Pictures'
24 desc = "Simulator Test"
31 desc = "Simulator Test"
25
32
26 controllerObj = Project()
33 controllerObj = Project()
27 controllerObj.setup(id='10',name='Test Simulator',description=desc)
34 controllerObj.setup(id='10',name='Test Simulator',description=desc)
28 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
35 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
29 path=path,
36 path=path,
30 startDate="2021/01/01", #"2020/01/01",#today,
37 startDate="2021/01/01", #"2020/01/01",#today,
31 endDate= "2021/12/01", #"2020/12/30",#today,
38 endDate= "2021/12/01", #"2020/12/30",#today,
32 startTime='00:00:00',
39 startTime='00:00:00',
33 endTime='23:59:59',
40 endTime='23:59:59',
34 t_Interval_p=0.01,
41 t_Interval_p=0.01,
35 n_Muestras_p=100,
42 n_Muestras_p=100,
36 delay=30,
43 delay=30,
37 #set=0,
44 #set=0,
38 online=0,
45 online=0,
39 walk=0,
46 walk=0,
40 nTries=6)#1
47 nTries=6)#1
41
48
42 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
49 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
50 V=2
51 blocksPerfile=100
52 print("Velocidad del Pedestal",V)
53 f_a_p= int(blocksPerfile/V)
43
54
44 opObj11 = procUnitConfObjA.addOperation(name='PedestalInformation')
55 opObj11 = procUnitConfObjA.addOperation(name='PedestalInformation')
45 opObj11.addParameter(name='path_ped', value=path_ped)
56 opObj11.addParameter(name='path_ped', value=path_ped)
46 opObj11.addParameter(name='path_adq', value=path_adq)
57 opObj11.addParameter(name='path_adq', value=path_adq)
47 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
58 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
48 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
59 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
49 opObj11.addParameter(name='blocksPerfile', value='100', format='int')
60 opObj11.addParameter(name='blocksPerfile', value='100', format='int')
50 opObj11.addParameter(name='f_a_p', value='10', format='int')
61 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
51 opObj11.addParameter(name='online', value='0', format='int')# habilitar el enable aqui tambien
62 opObj11.addParameter(name='online', value='0', format='int')# habilitar el enable aqui tambien
52
63
53
64
54 opObj11 = procUnitConfObjA.addOperation(name='Block360')
65 opObj11 = procUnitConfObjA.addOperation(name='Block360')
55 opObj11.addParameter(name='n', value='10', format='int')
66 opObj11.addParameter(name='n', value='10', format='int')
56 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
67 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
57
68
58 opObj11= procUnitConfObjA.addOperation(name='WeatherPlot',optype='other')
69 opObj11= procUnitConfObjA.addOperation(name='WeatherPlot',optype='other')
59 opObj11.addParameter(name='save', value=figpath)
70 #opObj11.addParameter(name='save', value=figpath)
60 opObj11.addParameter(name='save_period', value=1)
71 #opObj11.addParameter(name='save_period', value=1)
61
72
62 controllerObj.start()
73 controllerObj.start()
63 #online 1 utc_adq 1617490240.48
74 #online 1 utc_adq 1617490240.48
64 #online 0 utc_adq 1617489815.4804
75 #online 0 utc_adq 1617489815.4804
@@ -1,89 +1,90
1 import os,sys,json
1 import os,sys,json
2 import datetime
2 import datetime
3 import time
3 import time
4 from schainpy.controller import Project
4 from schainpy.controller import Project
5 '''
5 '''
6 NOTA:
6 NOTA:
7 Este script de prueba.
7 Este script de prueba.
8 - Unidad del lectura 'HDFReader'.
8 - Unidad del lectura 'HDFReader'.
9 - Unidad de procesamiento ParametersProc
9 - Unidad de procesamiento ParametersProc
10 - Operacion SpectralMomentsPlot
10 - Operacion SpectralMomentsPlot
11
11
12 '''
12 '''
13 #path = '/home/soporte/Downloads/RAWDATA_PP'
13 #path = '/home/soporte/Downloads/RAWDATA_PP'
14 #path = '/DATA_RM/TEST_HDF5/d2021203'
14 #path = '/DATA_RM/TEST_HDF5/d2021203'
15 #######################################################################
15 #######################################################################
16 ################# RANGO DE PLOTEO######################################
16 ################# RANGO DE PLOTEO######################################
17 #######################################################################
17 #######################################################################
18 dBmin = '1'
18 dBmin = '1'
19 dBmax = '85'
19 dBmax = '85'
20 xmin = '0'
20 xmin = '0'
21 xmax ='24'
21 xmax ='24'
22 tmmin = 16.2
22 tmmin = 12.2
23 tmmax = 16.25
23 tmmax = 12.40
24 ymin = '0'
24 ymin = '0'
25 ymax = '600'
25 ymax = '600'
26 #######################################################################
26 #######################################################################
27 #######################################################################
27 #######################################################################
28 # este script lee los archivos pre-procesados pulse-pair y permite el
28 # este script lee los archivos pre-procesados pulse-pair y permite el
29 # el ploteo del rti, mostrando los valores de potencia de la senal.
29 # el ploteo del rti, mostrando los valores de potencia de la senal.
30 # el resultado del grafico depende del programa USRP_ADQ_PP.py
30 # el resultado del grafico depende del programa USRP_ADQ_PP.py
31 # debido al procesamiento del Pulse Pair.
31 # debido al procesamiento del Pulse Pair.
32
32
33 #######################################################################
33 #######################################################################
34 #######################################################################
34 #######################################################################
35
35 #path_pp = '/DATA_RM/TEST_HDF5_PP_22'
36 path='/DATA_RM/TEST_HDF5/d2021231'
36 path='/DATA_RM/TEST_HDF5_PP_22/d2021265'
37 #path='/DATA_RM/TEST_HDF5/d2021231'
37 figpath = '/home/soporte/Downloads/IMAGE'
38 figpath = '/home/soporte/Downloads/IMAGE'
38 desc = "Simulator Test"
39 desc = "Simulator Test"
39 desc_data = {
40 desc_data = {
40 'Data': {
41 'Data': {
41 'dataPP_POW': ['Data/dataPP_POW/channel00','Data/dataPP_POW/channel01'],
42 'dataPP_POW': ['Data/dataPP_POW/channel00','Data/dataPP_POW/channel01'],
42 'dataPP_DOP': ['Data/dataPP_DOP/channel00','Data/dataPP_DOP/channel01'],
43 'dataPP_DOP': ['Data/dataPP_DOP/channel00','Data/dataPP_DOP/channel01'],
43 'utctime':'Data/utctime'
44 'utctime':'Data/utctime'
44 },
45 },
45 'Metadata': {
46 'Metadata': {
46 'heightList' :'Metadata/heightList',
47 'heightList' :'Metadata/heightList',
47 'flagDataAsBlock':'Metadata/flagDataAsBlock',
48 'flagDataAsBlock':'Metadata/flagDataAsBlock',
48 'channelList' :'Metadata/channelList',
49 'channelList' :'Metadata/channelList',
49 'profileIndex' :'Metadata/profileIndex'
50 'profileIndex' :'Metadata/profileIndex'
50 }
51 }
51 }
52 }
52
53
53 controllerObj = Project()
54 controllerObj = Project()
54
55
55 controllerObj.setup(id='10',name='Test Simulator',description=desc)
56 controllerObj.setup(id='10',name='Test Simulator',description=desc)
56
57
57 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
58 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
58 path=path,
59 path=path,
59 startDate="2021/01/01", #"2020/01/01",#today,
60 startDate="2021/01/01", #"2020/01/01",#today,
60 endDate= "2021/12/01", #"2020/12/30",#today,
61 endDate= "2021/12/01", #"2020/12/30",#today,
61 startTime='00:00:00',
62 startTime='00:00:00',
62 endTime='23:59:59',
63 endTime='23:59:59',
63 delay=0,
64 delay=0,
64 #set=0,
65 #set=0,
65 online=0,
66 online=0,
66 walk=0,
67 walk=0,
67 description= json.dumps(desc_data))#1
68 description= json.dumps(desc_data))#1
68
69
69 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
70 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
70
71
71 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')#PulsepairPowerPlot
72 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')#PulsepairPowerPlot
72 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
73 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
73 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
74 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
74
75
75 opObj11 = procUnitConfObjA.addOperation(name='GenericRTIPlot',optype='external')
76 opObj11 = procUnitConfObjA.addOperation(name='GenericRTIPlot',optype='external')
76
77
77 opObj11.addParameter(name='attr_data', value='dataPP_POW')
78 opObj11.addParameter(name='attr_data', value='dataPP_POW')
78 opObj11.addParameter(name='colormap', value='jet')
79 opObj11.addParameter(name='colormap', value='jet')
79
80
80 opObj11.addParameter(name='xmin', value=tmmin)
81 opObj11.addParameter(name='xmin', value=tmmin)
81 opObj11.addParameter(name='xmax', value=tmmax)
82 opObj11.addParameter(name='xmax', value=tmmax)
82 opObj11.addParameter(name='zmin', value=dBmin)
83 opObj11.addParameter(name='zmin', value=dBmin)
83 opObj11.addParameter(name='zmax', value=dBmax)
84 opObj11.addParameter(name='zmax', value=dBmax)
84 opObj11.addParameter(name='save', value=figpath)
85 opObj11.addParameter(name='save', value=figpath)
85 opObj11.addParameter(name='showprofile', value=0)
86 opObj11.addParameter(name='showprofile', value=0)
86 opObj11.addParameter(name='save_period', value=10)
87 opObj11.addParameter(name='save_period', value=10)
87
88
88
89
89 controllerObj.start()
90 controllerObj.start()
@@ -1,75 +1,78
1 import os,sys,json
1 import os,sys,json
2 import datetime
2 import datetime
3 import time
3 import time
4 from schainpy.controller import Project
4 from schainpy.controller import Project
5 '''
5 '''
6 NOTA:
6 NOTA:
7 Este script de prueba.
7 Este script de prueba.
8 - Unidad del lectura 'HDFReader'.
8 - Unidad del lectura 'HDFReader'.
9 - Unidad de procesamiento ParametersProc
9 - Unidad de procesamiento ParametersProc
10 - Operacion SpectralMomentsPlot
10 - Operacion SpectralMomentsPlot
11
11
12 '''
12 '''
13
13
14 #######################################################################
14 #######################################################################
15 ################# RANGO DE PLOTEO######################################
15 ################# RANGO DE PLOTEO######################################
16 #######################################################################
16 #######################################################################
17 dBmin = '1'
17 dBmin = '1'
18 dBmax = '65'
18 dBmax = '65'
19 xmin = '0'
19 xmin = '0'
20 xmax ='24'
20 xmax ='24'
21 tmmin = 16.2
21 #tmmin = 16.2
22 tmmax = 16.25
22 #tmmax = 16.25
23 tmmin =15
24 tmmax =15.5
23 ymin = '0'
25 ymin = '0'
24 ymax = '600'
26 ymax = '600'
25 #######################################################################
27 #######################################################################
26 #######################################################################
28 #######################################################################
27 #######################################################################
29 #######################################################################
28 path = '/DATA_RM/TEST_HDF5_SPEC'
30 #path = '/DATA_RM/TEST_HDF5_SPEC'
29 figpath = '/home/soporte/Downloads/IMAGE'
31 path = '/DATA_RM/TEST_HDF5_SPEC_23/6v/'
32 figpath = '/home/soporte/Downloads/23/6v'
30 desc = "Simulator Test"
33 desc = "Simulator Test"
31 desc_data = {
34 desc_data = {
32 'Data': {
35 'Data': {
33 'data_pow': ['Data/data_pow/channel00','Data/data_pow/channel01'],
36 'data_pow': ['Data/data_pow/channel00','Data/data_pow/channel01'],
34 'data_dop': ['Data/data_dop/channel00','Data/data_dop/channel01'],
37 'data_dop': ['Data/data_dop/channel00','Data/data_dop/channel01'],
35 'utctime':'Data/utctime'
38 'utctime':'Data/utctime'
36 },
39 },
37 'Metadata': {
40 'Metadata': {
38 'heightList':'Metadata/heightList',
41 'heightList':'Metadata/heightList',
39 'nIncohInt' :'Metadata/nIncohInt',
42 'nIncohInt' :'Metadata/nIncohInt',
40 'nCohInt' :'Metadata/nCohInt',
43 'nCohInt' :'Metadata/nCohInt',
41 'nProfiles' :'Metadata/nProfiles',
44 'nProfiles' :'Metadata/nProfiles',
42 'channelList' :'Metadata/channelList',
45 'channelList' :'Metadata/channelList',
43 'utctimeInit' :'Metadata/utctimeInit'
46 'utctimeInit' :'Metadata/utctimeInit'
44
47
45 }
48 }
46 }
49 }
47
50
48 controllerObj = Project()
51 controllerObj = Project()
49
52
50 controllerObj.setup(id='10',name='Test Simulator',description=desc)
53 controllerObj.setup(id='10',name='Test Simulator',description=desc)
51
54
52 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
55 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
53 path=path,
56 path=path,
54 startDate="2021/01/01", #"2020/01/01",#today,
57 startDate="2021/01/01", #"2020/01/01",#today,
55 endDate= "2021/12/01", #"2020/12/30",#today,
58 endDate= "2021/12/01", #"2020/12/30",#today,
56 startTime='00:00:00',
59 startTime='00:00:00',
57 endTime='23:59:59',
60 endTime='23:59:59',
58 delay=0,
61 delay=0,
59 #set=0,
62 #set=0,
60 online=0,
63 online=0,
61 walk=1,
64 walk=1,
62 description= json.dumps(desc_data))#1
65 description= json.dumps(desc_data))#1
63
66
64 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
67 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
65
68
66 opObj11 = procUnitConfObjA.addOperation(name='PowerPlot',optype='external')
69 opObj11 = procUnitConfObjA.addOperation(name='PowerPlot',optype='external')
67 opObj11.addParameter(name='xmin', value=tmmin)
70 opObj11.addParameter(name='xmin', value=tmmin)
68 opObj11.addParameter(name='xmax', value=tmmax)
71 opObj11.addParameter(name='xmax', value=tmmax)
69 opObj11.addParameter(name='zmin', value=dBmin)
72 opObj11.addParameter(name='zmin', value=dBmin)
70 opObj11.addParameter(name='zmax', value=dBmax)
73 opObj11.addParameter(name='zmax', value=dBmax)
71 opObj11.addParameter(name='save', value=figpath)
74 opObj11.addParameter(name='save', value=figpath)
72 opObj11.addParameter(name='showprofile', value=0)
75 opObj11.addParameter(name='showprofile', value=0)
73 opObj11.addParameter(name='save_period', value=10)
76 opObj11.addParameter(name='save_period', value=10)
74
77
75 controllerObj.start()
78 controllerObj.start()
General Comments 0
You need to be logged in to leave comments. Login now