##// 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 1 import os
2 2 import datetime
3 3 import numpy
4 4
5 5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 7 from schainpy.utils import log
8 8 # libreria wradlib
9 9 import wradlib as wrl
10 10
11 11 EARTH_RADIUS = 6.3710e3
12 12
13 13
14 14 def ll2xy(lat1, lon1, lat2, lon2):
15 15
16 16 p = 0.017453292519943295
17 17 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
18 18 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
19 19 r = 12742 * numpy.arcsin(numpy.sqrt(a))
20 20 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
21 21 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
22 22 theta = -theta + numpy.pi/2
23 23 return r*numpy.cos(theta), r*numpy.sin(theta)
24 24
25 25
26 26 def km2deg(km):
27 27 '''
28 28 Convert distance in km to degrees
29 29 '''
30 30
31 31 return numpy.rad2deg(km/EARTH_RADIUS)
32 32
33 33
34 34
35 35 class SpectralMomentsPlot(SpectraPlot):
36 36 '''
37 37 Plot for Spectral Moments
38 38 '''
39 39 CODE = 'spc_moments'
40 40 # colormap = 'jet'
41 41 # plot_type = 'pcolor'
42 42
43 43 class DobleGaussianPlot(SpectraPlot):
44 44 '''
45 45 Plot for Double Gaussian Plot
46 46 '''
47 47 CODE = 'gaussian_fit'
48 48 # colormap = 'jet'
49 49 # plot_type = 'pcolor'
50 50
51 51 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
52 52 '''
53 53 Plot SpectraCut with Double Gaussian Fit
54 54 '''
55 55 CODE = 'cut_gaussian_fit'
56 56
57 57 class SnrPlot(RTIPlot):
58 58 '''
59 59 Plot for SNR Data
60 60 '''
61 61
62 62 CODE = 'snr'
63 63 colormap = 'jet'
64 64
65 65 def update(self, dataOut):
66 66
67 67 data = {
68 68 'snr': 10*numpy.log10(dataOut.data_snr)
69 69 }
70 70
71 71 return data, {}
72 72
73 73 class DopplerPlot(RTIPlot):
74 74 '''
75 75 Plot for DOPPLER Data (1st moment)
76 76 '''
77 77
78 78 CODE = 'dop'
79 79 colormap = 'jet'
80 80
81 81 def update(self, dataOut):
82 82
83 83 data = {
84 84 'dop': 10*numpy.log10(dataOut.data_dop)
85 85 }
86 86
87 87 return data, {}
88 88
89 89 class PowerPlot(RTIPlot):
90 90 '''
91 91 Plot for Power Data (0 moment)
92 92 '''
93 93
94 94 CODE = 'pow'
95 95 colormap = 'jet'
96 96
97 97 def update(self, dataOut):
98 98
99 99 data = {
100 100 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
101 101 }
102 102
103 103 return data, {}
104 104
105 105 class SpectralWidthPlot(RTIPlot):
106 106 '''
107 107 Plot for Spectral Width Data (2nd moment)
108 108 '''
109 109
110 110 CODE = 'width'
111 111 colormap = 'jet'
112 112
113 113 def update(self, dataOut):
114 114
115 115 data = {
116 116 'width': dataOut.data_width
117 117 }
118 118
119 119 return data, {}
120 120
121 121 class SkyMapPlot(Plot):
122 122 '''
123 123 Plot for meteors detection data
124 124 '''
125 125
126 126 CODE = 'param'
127 127
128 128 def setup(self):
129 129
130 130 self.ncols = 1
131 131 self.nrows = 1
132 132 self.width = 7.2
133 133 self.height = 7.2
134 134 self.nplots = 1
135 135 self.xlabel = 'Zonal Zenith Angle (deg)'
136 136 self.ylabel = 'Meridional Zenith Angle (deg)'
137 137 self.polar = True
138 138 self.ymin = -180
139 139 self.ymax = 180
140 140 self.colorbar = False
141 141
142 142 def plot(self):
143 143
144 144 arrayParameters = numpy.concatenate(self.data['param'])
145 145 error = arrayParameters[:, -1]
146 146 indValid = numpy.where(error == 0)[0]
147 147 finalMeteor = arrayParameters[indValid, :]
148 148 finalAzimuth = finalMeteor[:, 3]
149 149 finalZenith = finalMeteor[:, 4]
150 150
151 151 x = finalAzimuth * numpy.pi / 180
152 152 y = finalZenith
153 153
154 154 ax = self.axes[0]
155 155
156 156 if ax.firsttime:
157 157 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
158 158 else:
159 159 ax.plot.set_data(x, y)
160 160
161 161 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
162 162 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
163 163 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
164 164 dt2,
165 165 len(x))
166 166 self.titles[0] = title
167 167
168 168
169 169 class GenericRTIPlot(Plot):
170 170 '''
171 171 Plot for data_xxxx object
172 172 '''
173 173
174 174 CODE = 'param'
175 175 colormap = 'viridis'
176 176 plot_type = 'pcolorbuffer'
177 177
178 178 def setup(self):
179 179 self.xaxis = 'time'
180 180 self.ncols = 1
181 181 self.nrows = self.data.shape('param')[0]
182 182 self.nplots = self.nrows
183 183 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
184 184
185 185 if not self.xlabel:
186 186 self.xlabel = 'Time'
187 187
188 188 self.ylabel = 'Range [km]'
189 189 if not self.titles:
190 190 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
191 191
192 192 def update(self, dataOut):
193 193
194 194 data = {
195 195 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
196 196 }
197 197
198 198 meta = {}
199 199
200 200 return data, meta
201 201
202 202 def plot(self):
203 203 # self.data.normalize_heights()
204 204 self.x = self.data.times
205 205 self.y = self.data.yrange
206 206 self.z = self.data['param']
207 207
208 208 self.z = 10*numpy.log10(self.z)
209 209
210 210 self.z = numpy.ma.masked_invalid(self.z)
211 211
212 212 if self.decimation is None:
213 213 x, y, z = self.fill_gaps(self.x, self.y, self.z)
214 214 else:
215 215 x, y, z = self.fill_gaps(*self.decimate())
216 216
217 217 for n, ax in enumerate(self.axes):
218 218
219 219 self.zmax = self.zmax if self.zmax is not None else numpy.max(
220 220 self.z[n])
221 221 self.zmin = self.zmin if self.zmin is not None else numpy.min(
222 222 self.z[n])
223 223
224 224 if ax.firsttime:
225 225 if self.zlimits is not None:
226 226 self.zmin, self.zmax = self.zlimits[n]
227 227
228 228 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
229 229 vmin=self.zmin,
230 230 vmax=self.zmax,
231 231 cmap=self.cmaps[n]
232 232 )
233 233 else:
234 234 if self.zlimits is not None:
235 235 self.zmin, self.zmax = self.zlimits[n]
236 236 ax.collections.remove(ax.collections[0])
237 237 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
238 238 vmin=self.zmin,
239 239 vmax=self.zmax,
240 240 cmap=self.cmaps[n]
241 241 )
242 242
243 243
244 244 class PolarMapPlot(Plot):
245 245 '''
246 246 Plot for weather radar
247 247 '''
248 248
249 249 CODE = 'param'
250 250 colormap = 'seismic'
251 251
252 252 def setup(self):
253 253 self.ncols = 1
254 254 self.nrows = 1
255 255 self.width = 9
256 256 self.height = 8
257 257 self.mode = self.data.meta['mode']
258 258 if self.channels is not None:
259 259 self.nplots = len(self.channels)
260 260 self.nrows = len(self.channels)
261 261 else:
262 262 self.nplots = self.data.shape(self.CODE)[0]
263 263 self.nrows = self.nplots
264 264 self.channels = list(range(self.nplots))
265 265 if self.mode == 'E':
266 266 self.xlabel = 'Longitude'
267 267 self.ylabel = 'Latitude'
268 268 else:
269 269 self.xlabel = 'Range (km)'
270 270 self.ylabel = 'Height (km)'
271 271 self.bgcolor = 'white'
272 272 self.cb_labels = self.data.meta['units']
273 273 self.lat = self.data.meta['latitude']
274 274 self.lon = self.data.meta['longitude']
275 275 self.xmin, self.xmax = float(
276 276 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
277 277 self.ymin, self.ymax = float(
278 278 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
279 279 # self.polar = True
280 280
281 281 def plot(self):
282 282
283 283 for n, ax in enumerate(self.axes):
284 284 data = self.data['param'][self.channels[n]]
285 285
286 286 zeniths = numpy.linspace(
287 287 0, self.data.meta['max_range'], data.shape[1])
288 288 if self.mode == 'E':
289 289 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
290 290 r, theta = numpy.meshgrid(zeniths, azimuths)
291 291 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
292 292 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
293 293 x = km2deg(x) + self.lon
294 294 y = km2deg(y) + self.lat
295 295 else:
296 296 azimuths = numpy.radians(self.data.yrange)
297 297 r, theta = numpy.meshgrid(zeniths, azimuths)
298 298 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
299 299 self.y = zeniths
300 300
301 301 if ax.firsttime:
302 302 if self.zlimits is not None:
303 303 self.zmin, self.zmax = self.zlimits[n]
304 304 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
305 305 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
306 306 vmin=self.zmin,
307 307 vmax=self.zmax,
308 308 cmap=self.cmaps[n])
309 309 else:
310 310 if self.zlimits is not None:
311 311 self.zmin, self.zmax = self.zlimits[n]
312 312 ax.collections.remove(ax.collections[0])
313 313 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
314 314 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
315 315 vmin=self.zmin,
316 316 vmax=self.zmax,
317 317 cmap=self.cmaps[n])
318 318
319 319 if self.mode == 'A':
320 320 continue
321 321
322 322 # plot district names
323 323 f = open('/data/workspace/schain_scripts/distrito.csv')
324 324 for line in f:
325 325 label, lon, lat = [s.strip() for s in line.split(',') if s]
326 326 lat = float(lat)
327 327 lon = float(lon)
328 328 # ax.plot(lon, lat, '.b', ms=2)
329 329 ax.text(lon, lat, label.decode('utf8'), ha='center',
330 330 va='bottom', size='8', color='black')
331 331
332 332 # plot limites
333 333 limites = []
334 334 tmp = []
335 335 for line in open('/data/workspace/schain_scripts/lima.csv'):
336 336 if '#' in line:
337 337 if tmp:
338 338 limites.append(tmp)
339 339 tmp = []
340 340 continue
341 341 values = line.strip().split(',')
342 342 tmp.append((float(values[0]), float(values[1])))
343 343 for points in limites:
344 344 ax.add_patch(
345 345 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
346 346
347 347 # plot Cuencas
348 348 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
349 349 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
350 350 values = [line.strip().split(',') for line in f]
351 351 points = [(float(s[0]), float(s[1])) for s in values]
352 352 ax.add_patch(Polygon(points, ec='b', fc='none'))
353 353
354 354 # plot grid
355 355 for r in (15, 30, 45, 60):
356 356 ax.add_artist(plt.Circle((self.lon, self.lat),
357 357 km2deg(r), color='0.6', fill=False, lw=0.2))
358 358 ax.text(
359 359 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
360 360 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
361 361 '{}km'.format(r),
362 362 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
363 363
364 364 if self.mode == 'E':
365 365 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
366 366 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
367 367 else:
368 368 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
369 369 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
370 370
371 371 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
372 372 self.titles = ['{} {}'.format(
373 373 self.data.parameters[x], title) for x in self.channels]
374 374
375 375 class WeatherPlot(Plot):
376 376 CODE = 'weather'
377 377 plot_name = 'weather'
378 378 plot_type = 'ppistyle'
379 379 buffering = False
380 380
381 381 def setup(self):
382 382 self.ncols = 1
383 383 self.nrows = 1
384 384 self.nplots= 1
385 385 self.ylabel= 'Range [Km]'
386 386 self.titles= ['Weather']
387 387 self.colorbar=False
388 388 self.width =8
389 389 self.height =8
390 390 self.ini =0
391 391 self.len_azi =0
392 392 self.buffer_ini = None
393 393 self.buffer_azi = None
394 394 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
395 395 self.flag =0
396 396 self.indicador= 0
397 397
398 398 def update(self, dataOut):
399 399
400 400 data = {}
401 401 meta = {}
402 402 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(250**2))
403 print(data['weather'])
403 404 data['azi'] = dataOut.data_azi
404
405 print("UPDATE",data['azi'])
405 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 473 def plot(self):
408 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
409 474 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
475 #numpy.set_printoptions(suppress=True)
476 #print(self.data.times)
477 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
478 data = self.data[-1]
479 # ALTURA altura_tmp_h
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 482 rangestep = float(0.15)
417 483 r = numpy.arange(0, stoprange, rangestep)
418 484 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]))
485 # RADAR
486 #data_weather = data['weather']
487 # PEDESTAL
488 #data_azi = data['azi']
489 res = 1
490 # STEP
491 step = (360/(res*data['weather'].shape[0]))
492 #print("shape wr_data", wr_data.shape)
493 #print("shape wr_azi",wr_azi.shape)
430 494 #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
495 print("Time---->",self.data.times[-1],thisDatetime)
496 #print("alturas", len(self.y))
497 self.res_weather, self.res_azi = self.const_ploteo(data_weather=data['weather'],data_azi=data['azi'],step=step,res=res)
498 #numpy.set_printoptions(suppress=True)
499 #print("resultado",self.res_azi)
500 ##########################################################
501 ################# PLOTEO ###################
502 ##########################################################
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 504 for i,ax in enumerate(self.axes):
614 505 if ax.firsttime:
615 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 508 else:
618 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 511 caax = cgax.parasites[0]
621 512 paax = cgax.parasites[1]
622 513 cbar = plt.gcf().colorbar(pm, pad=0.075)
623 514 caax.set_xlabel('x_range [km]')
624 515 caax.set_ylabel('y_range [km]')
625 516 plt.text(1.0, 1.05, 'azimuth '+str(thisDatetime)+"step"+str(self.ini), transform=caax.transAxes, va='bottom',ha='right')
626 #import time
627 #time.sleep(0.5)
517
518 self.ini= self.ini+1
@@ -1,203 +1,206
1 1 '''
2 2 Base clases to create Processing units and operations, the MPDecorator
3 3 must be used in plotting and writing operations to allow to run as an
4 4 external process.
5 5 '''
6 6
7 7 import inspect
8 8 import zmq
9 9 import time
10 10 import pickle
11 11 import traceback
12 12 from threading import Thread
13 13 from multiprocessing import Process, Queue
14 14 from schainpy.utils import log
15 15
16 16
17 17 class ProcessingUnit(object):
18 18 '''
19 19 Base class to create Signal Chain Units
20 20 '''
21 21
22 22 proc_type = 'processing'
23 23
24 24 def __init__(self):
25 25
26 26 self.dataIn = None
27 27 self.dataOut = None
28 28 self.isConfig = False
29 29 self.operations = []
30
30
31 31 def setInput(self, unit):
32 32
33 33 self.dataIn = unit.dataOut
34
34
35 35 def getAllowedArgs(self):
36 36 if hasattr(self, '__attrs__'):
37 37 return self.__attrs__
38 38 else:
39 39 return inspect.getargspec(self.run).args
40 40
41 41 def addOperation(self, conf, operation):
42 42 '''
43 43 '''
44
44
45 45 self.operations.append((operation, conf.type, conf.getKwargs()))
46 46
47 47 def getOperationObj(self, objId):
48 48
49 49 if objId not in list(self.operations.keys()):
50 50 return None
51 51
52 52 return self.operations[objId]
53 53
54 54 def call(self, **kwargs):
55 55 '''
56 56 '''
57 57
58 58 try:
59 59 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
60 60 return self.dataIn.isReady()
61 61 elif self.dataIn is None or not self.dataIn.error:
62 62 self.run(**kwargs)
63 63 elif self.dataIn.error:
64 64 self.dataOut.error = self.dataIn.error
65 65 self.dataOut.flagNoData = True
66 66 except:
67 err = traceback.format_exc()
67 err = traceback.format_exc()
68 68 if 'SchainWarning' in err:
69 69 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
70 70 elif 'SchainError' in err:
71 71 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
72 72 else:
73 73 log.error(err, self.name)
74 74 self.dataOut.error = True
75
75 ##### correcion de la declaracion Out
76 76 for op, optype, opkwargs in self.operations:
77 aux = self.dataOut.copy()
77 78 if optype == 'other' and not self.dataOut.flagNoData:
78 79 self.dataOut = op.run(self.dataOut, **opkwargs)
79 80 elif optype == 'external' and not self.dataOut.flagNoData:
80 op.queue.put(self.dataOut)
81 elif optype == 'external' and self.dataOut.error:
82 op.queue.put(self.dataOut)
81 #op.queue.put(self.dataOut)
82 op.queue.put(aux)
83 elif optype == 'external' and self.dataOut.error:
84 #op.queue.put(self.dataOut)
85 op.queue.put(aux)
83 86
84 87 return 'Error' if self.dataOut.error else self.dataOut.isReady()
85 88
86 89 def setup(self):
87 90
88 91 raise NotImplementedError
89 92
90 93 def run(self):
91 94
92 95 raise NotImplementedError
93 96
94 97 def close(self):
95 98
96 99 return
97 100
98 101
99 102 class Operation(object):
100 103
101 104 '''
102 105 '''
103
106
104 107 proc_type = 'operation'
105 108
106 109 def __init__(self):
107 110
108 111 self.id = None
109 112 self.isConfig = False
110 113
111 114 if not hasattr(self, 'name'):
112 115 self.name = self.__class__.__name__
113 116
114 117 def getAllowedArgs(self):
115 118 if hasattr(self, '__attrs__'):
116 119 return self.__attrs__
117 120 else:
118 121 return inspect.getargspec(self.run).args
119 122
120 123 def setup(self):
121 124
122 125 self.isConfig = True
123 126
124 127 raise NotImplementedError
125 128
126 129 def run(self, dataIn, **kwargs):
127 130 """
128 131 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
129 132 atributos del objeto dataIn.
130 133
131 134 Input:
132 135
133 136 dataIn : objeto del tipo JROData
134 137
135 138 Return:
136 139
137 140 None
138 141
139 142 Affected:
140 143 __buffer : buffer de recepcion de datos.
141 144
142 145 """
143 146 if not self.isConfig:
144 147 self.setup(**kwargs)
145 148
146 149 raise NotImplementedError
147 150
148 151 def close(self):
149 152
150 153 return
151 154
152
155
153 156 def MPDecorator(BaseClass):
154 157 """
155 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 163 class MPClass(BaseClass, Process):
161 164
162 165 def __init__(self, *args, **kwargs):
163 166 super(MPClass, self).__init__()
164 167 Process.__init__(self)
165 168
166 169 self.args = args
167 170 self.kwargs = kwargs
168 171 self.t = time.time()
169 172 self.op_type = 'external'
170 173 self.name = BaseClass.__name__
171 174 self.__doc__ = BaseClass.__doc__
172
175
173 176 if 'plot' in self.name.lower() and not self.name.endswith('_'):
174 177 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
175
178
176 179 self.start_time = time.time()
177 180 self.err_queue = args[3]
178 181 self.queue = Queue(maxsize=1)
179 182 self.myrun = BaseClass.run
180 183
181 184 def run(self):
182
185
183 186 while True:
184 187
185 188 dataOut = self.queue.get()
186 189
187 190 if not dataOut.error:
188 191 try:
189 192 BaseClass.run(self, dataOut, **self.kwargs)
190 193 except:
191 err = traceback.format_exc()
194 err = traceback.format_exc()
192 195 log.error(err, self.name)
193 196 else:
194 197 break
195 198
196 199 self.close()
197 200
198 201 def close(self):
199 202
200 203 BaseClass.close(self)
201 204 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
202 205
203 206 return MPClass
@@ -1,4502 +1,4450
1 1 import numpy,os,h5py
2 2 import math
3 3 from scipy import optimize, interpolate, signal, stats, ndimage
4 4 import scipy
5 5 import re
6 6 import datetime
7 7 import copy
8 8 import sys
9 9 import importlib
10 10 import itertools
11 11 from multiprocessing import Pool, TimeoutError
12 12 from multiprocessing.pool import ThreadPool
13 13 import time
14 14
15 15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 18 from scipy import asarray as ar,exp
19 19 from scipy.optimize import curve_fit
20 20 from schainpy.utils import log
21 21 import warnings
22 22 from numpy import NaN
23 23 from scipy.optimize.optimize import OptimizeWarning
24 24 warnings.filterwarnings('ignore')
25 25
26 26 import matplotlib.pyplot as plt
27 27
28 28 SPEED_OF_LIGHT = 299792458
29 29
30 30 '''solving pickling issue'''
31 31
32 32 def _pickle_method(method):
33 33 func_name = method.__func__.__name__
34 34 obj = method.__self__
35 35 cls = method.__self__.__class__
36 36 return _unpickle_method, (func_name, obj, cls)
37 37
38 38 def _unpickle_method(func_name, obj, cls):
39 39 for cls in cls.mro():
40 40 try:
41 41 func = cls.__dict__[func_name]
42 42 except KeyError:
43 43 pass
44 44 else:
45 45 break
46 46 return func.__get__(obj, cls)
47 47
48 48 def isNumber(str):
49 49 try:
50 50 float(str)
51 51 return True
52 52 except:
53 53 return False
54 54
55 55 class ParametersProc(ProcessingUnit):
56 56
57 57 METHODS = {}
58 58 nSeconds = None
59 59
60 60 def __init__(self):
61 61 ProcessingUnit.__init__(self)
62 62
63 63 # self.objectDict = {}
64 64 self.buffer = None
65 65 self.firstdatatime = None
66 66 self.profIndex = 0
67 67 self.dataOut = Parameters()
68 68 self.setupReq = False #Agregar a todas las unidades de proc
69 69
70 70 def __updateObjFromInput(self):
71 71
72 72 self.dataOut.inputUnit = self.dataIn.type
73 73
74 74 self.dataOut.timeZone = self.dataIn.timeZone
75 75 self.dataOut.dstFlag = self.dataIn.dstFlag
76 76 self.dataOut.errorCount = self.dataIn.errorCount
77 77 self.dataOut.useLocalTime = self.dataIn.useLocalTime
78 78
79 79 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
80 80 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
81 81 self.dataOut.channelList = self.dataIn.channelList
82 82 self.dataOut.heightList = self.dataIn.heightList
83 83 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
84 84 # self.dataOut.nHeights = self.dataIn.nHeights
85 85 # self.dataOut.nChannels = self.dataIn.nChannels
86 86 # self.dataOut.nBaud = self.dataIn.nBaud
87 87 # self.dataOut.nCode = self.dataIn.nCode
88 88 # self.dataOut.code = self.dataIn.code
89 89 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
90 90 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
91 91 # self.dataOut.utctime = self.firstdatatime
92 92 self.dataOut.utctime = self.dataIn.utctime
93 93 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
94 94 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
95 95 self.dataOut.nCohInt = self.dataIn.nCohInt
96 96 # self.dataOut.nIncohInt = 1
97 97 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
98 98 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
99 99 self.dataOut.timeInterval1 = self.dataIn.timeInterval
100 100 self.dataOut.heightList = self.dataIn.heightList
101 101 self.dataOut.frequency = self.dataIn.frequency
102 102 # self.dataOut.noise = self.dataIn.noise
103 103
104 104 def run(self):
105 105
106 106
107 107 #print("HOLA MUNDO SOY YO")
108 108 #---------------------- Voltage Data ---------------------------
109 109
110 110 if self.dataIn.type == "Voltage":
111 111
112 112 self.__updateObjFromInput()
113 113 self.dataOut.data_pre = self.dataIn.data.copy()
114 114 self.dataOut.flagNoData = False
115 115 self.dataOut.utctimeInit = self.dataIn.utctime
116 116 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
117 117
118 118 if hasattr(self.dataIn, 'flagDataAsBlock'):
119 119 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
120 120
121 121 if hasattr(self.dataIn, 'profileIndex'):
122 122 self.dataOut.profileIndex = self.dataIn.profileIndex
123 123
124 124 if hasattr(self.dataIn, 'dataPP_POW'):
125 125 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
126 126
127 127 if hasattr(self.dataIn, 'dataPP_POWER'):
128 128 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
129 129
130 130 if hasattr(self.dataIn, 'dataPP_DOP'):
131 131 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
132 132
133 133 if hasattr(self.dataIn, 'dataPP_SNR'):
134 134 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
135 135
136 136 if hasattr(self.dataIn, 'dataPP_WIDTH'):
137 137 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
138 138 return
139 139
140 140 #---------------------- Spectra Data ---------------------------
141 141
142 142 if self.dataIn.type == "Spectra":
143 143 #print("que paso en spectra")
144 144 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
145 145 self.dataOut.data_spc = self.dataIn.data_spc
146 146 self.dataOut.data_cspc = self.dataIn.data_cspc
147 147 self.dataOut.nProfiles = self.dataIn.nProfiles
148 148 self.dataOut.nIncohInt = self.dataIn.nIncohInt
149 149 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
150 150 self.dataOut.ippFactor = self.dataIn.ippFactor
151 151 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
152 152 self.dataOut.spc_noise = self.dataIn.getNoise()
153 153 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
154 154 # self.dataOut.normFactor = self.dataIn.normFactor
155 155 self.dataOut.pairsList = self.dataIn.pairsList
156 156 self.dataOut.groupList = self.dataIn.pairsList
157 157 self.dataOut.flagNoData = False
158 158
159 159 if hasattr(self.dataIn, 'flagDataAsBlock'):
160 160 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
161 161
162 162 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
163 163 self.dataOut.ChanDist = self.dataIn.ChanDist
164 164 else: self.dataOut.ChanDist = None
165 165
166 166 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
167 167 # self.dataOut.VelRange = self.dataIn.VelRange
168 168 #else: self.dataOut.VelRange = None
169 169
170 170 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
171 171 self.dataOut.RadarConst = self.dataIn.RadarConst
172 172
173 173 if hasattr(self.dataIn, 'NPW'): #NPW
174 174 self.dataOut.NPW = self.dataIn.NPW
175 175
176 176 if hasattr(self.dataIn, 'COFA'): #COFA
177 177 self.dataOut.COFA = self.dataIn.COFA
178 178
179 179
180 180
181 181 #---------------------- Correlation Data ---------------------------
182 182
183 183 if self.dataIn.type == "Correlation":
184 184 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
185 185
186 186 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
187 187 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
188 188 self.dataOut.groupList = (acf_pairs, ccf_pairs)
189 189
190 190 self.dataOut.abscissaList = self.dataIn.lagRange
191 191 self.dataOut.noise = self.dataIn.noise
192 192 self.dataOut.data_snr = self.dataIn.SNR
193 193 self.dataOut.flagNoData = False
194 194 self.dataOut.nAvg = self.dataIn.nAvg
195 195
196 196 #---------------------- Parameters Data ---------------------------
197 197
198 198 if self.dataIn.type == "Parameters":
199 199 self.dataOut.copy(self.dataIn)
200 200 self.dataOut.flagNoData = False
201 201
202 202 return True
203 203
204 204 self.__updateObjFromInput()
205 205
206 206 self.dataOut.utctimeInit = self.dataIn.utctime
207 207 self.dataOut.paramInterval = self.dataIn.timeInterval
208 208 #print("soy spectra ",self.dataOut.utctimeInit)
209 209 return
210 210
211 211
212 212 def target(tups):
213 213
214 214 obj, args = tups
215 215
216 216 return obj.FitGau(args)
217 217
218 218 class RemoveWideGC(Operation):
219 219 ''' This class remove the wide clutter and replace it with a simple interpolation points
220 220 This mainly applies to CLAIRE radar
221 221
222 222 ClutterWidth : Width to look for the clutter peak
223 223
224 224 Input:
225 225
226 226 self.dataOut.data_pre : SPC and CSPC
227 227 self.dataOut.spc_range : To select wind and rainfall velocities
228 228
229 229 Affected:
230 230
231 231 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
232 232
233 233 Written by D. ScipiΓ³n 25.02.2021
234 234 '''
235 235 def __init__(self):
236 236 Operation.__init__(self)
237 237 self.i = 0
238 238 self.ich = 0
239 239 self.ir = 0
240 240
241 241 def run(self, dataOut, ClutterWidth=2.5):
242 242 # print ('Entering RemoveWideGC ... ')
243 243
244 244 self.spc = dataOut.data_pre[0].copy()
245 245 self.spc_out = dataOut.data_pre[0].copy()
246 246 self.Num_Chn = self.spc.shape[0]
247 247 self.Num_Hei = self.spc.shape[2]
248 248 VelRange = dataOut.spc_range[2][:-1]
249 249 dv = VelRange[1]-VelRange[0]
250 250
251 251 # Find the velocities that corresponds to zero
252 252 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
253 253
254 254 # Removing novalid data from the spectra
255 255 for ich in range(self.Num_Chn) :
256 256 for ir in range(self.Num_Hei) :
257 257 # Estimate the noise at each range
258 258 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
259 259
260 260 # Removing the noise floor at each range
261 261 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
262 262 self.spc[ich,novalid,ir] = HSn
263 263
264 264 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
265 265 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
266 266 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
267 267 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
268 268 continue
269 269 junk3 = numpy.squeeze(numpy.diff(j1index))
270 270 junk4 = numpy.squeeze(numpy.diff(j2index))
271 271
272 272 valleyindex = j2index[numpy.where(junk4>1)]
273 273 peakindex = j1index[numpy.where(junk3>1)]
274 274
275 275 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
276 276 if numpy.size(isvalid) == 0 :
277 277 continue
278 278 if numpy.size(isvalid) >1 :
279 279 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
280 280 isvalid = isvalid[vindex]
281 281
282 282 # clutter peak
283 283 gcpeak = peakindex[isvalid]
284 284 vl = numpy.where(valleyindex < gcpeak)
285 285 if numpy.size(vl) == 0:
286 286 continue
287 287 gcvl = valleyindex[vl[0][-1]]
288 288 vr = numpy.where(valleyindex > gcpeak)
289 289 if numpy.size(vr) == 0:
290 290 continue
291 291 gcvr = valleyindex[vr[0][0]]
292 292
293 293 # Removing the clutter
294 294 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
295 295 gcindex = gc_values[gcvl+1:gcvr-1]
296 296 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
297 297
298 298 dataOut.data_pre[0] = self.spc_out
299 299 #print ('Leaving RemoveWideGC ... ')
300 300 return dataOut
301 301
302 302 class SpectralFilters(Operation):
303 303 ''' This class allows to replace the novalid values with noise for each channel
304 304 This applies to CLAIRE RADAR
305 305
306 306 PositiveLimit : RightLimit of novalid data
307 307 NegativeLimit : LeftLimit of novalid data
308 308
309 309 Input:
310 310
311 311 self.dataOut.data_pre : SPC and CSPC
312 312 self.dataOut.spc_range : To select wind and rainfall velocities
313 313
314 314 Affected:
315 315
316 316 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
317 317
318 318 Written by D. ScipiΓ³n 29.01.2021
319 319 '''
320 320 def __init__(self):
321 321 Operation.__init__(self)
322 322 self.i = 0
323 323
324 324 def run(self, dataOut, ):
325 325
326 326 self.spc = dataOut.data_pre[0].copy()
327 327 self.Num_Chn = self.spc.shape[0]
328 328 VelRange = dataOut.spc_range[2]
329 329
330 330 # novalid corresponds to data within the Negative and PositiveLimit
331 331
332 332
333 333 # Removing novalid data from the spectra
334 334 for i in range(self.Num_Chn):
335 335 self.spc[i,novalid,:] = dataOut.noise[i]
336 336 dataOut.data_pre[0] = self.spc
337 337 return dataOut
338 338
339 339 class GaussianFit(Operation):
340 340
341 341 '''
342 342 Function that fit of one and two generalized gaussians (gg) based
343 343 on the PSD shape across an "power band" identified from a cumsum of
344 344 the measured spectrum - noise.
345 345
346 346 Input:
347 347 self.dataOut.data_pre : SelfSpectra
348 348
349 349 Output:
350 350 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
351 351
352 352 '''
353 353 def __init__(self):
354 354 Operation.__init__(self)
355 355 self.i=0
356 356
357 357
358 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 359 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
360 360 """This routine will find a couple of generalized Gaussians to a power spectrum
361 361 methods: generalized, squared
362 362 input: spc
363 363 output:
364 364 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
365 365 """
366 366 print ('Entering ',method,' double Gaussian fit')
367 367 self.spc = dataOut.data_pre[0].copy()
368 368 self.Num_Hei = self.spc.shape[2]
369 369 self.Num_Bin = self.spc.shape[1]
370 370 self.Num_Chn = self.spc.shape[0]
371 371
372 372 start_time = time.time()
373 373
374 374 pool = Pool(processes=self.Num_Chn)
375 375 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
376 376 objs = [self for __ in range(self.Num_Chn)]
377 377 attrs = list(zip(objs, args))
378 378 DGauFitParam = pool.map(target, attrs)
379 379 # Parameters:
380 380 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
381 381 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
382 382
383 383 # Double Gaussian Curves
384 384 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
385 385 gau0[:] = numpy.NaN
386 386 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
387 387 gau1[:] = numpy.NaN
388 388 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
389 389 for iCh in range(self.Num_Chn):
390 390 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
391 391 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
392 392 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
393 393 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
394 394 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
395 395 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
396 396 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
397 397 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
398 398 if method == 'genealized':
399 399 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
400 400 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
401 401 elif method == 'squared':
402 402 p0 = 2.
403 403 p1 = 2.
404 404 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
405 405 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
406 406 dataOut.GaussFit0 = gau0
407 407 dataOut.GaussFit1 = gau1
408 408
409 409 print('Leaving ',method ,' double Gaussian fit')
410 410 return dataOut
411 411
412 412 def FitGau(self, X):
413 413 # print('Entering FitGau')
414 414 # Assigning the variables
415 415 Vrange, ch, wnoise, num_intg, SNRlimit = X
416 416 # Noise Limits
417 417 noisebl = wnoise * 0.9
418 418 noisebh = wnoise * 1.1
419 419 # Radar Velocity
420 420 Va = max(Vrange)
421 421 deltav = Vrange[1] - Vrange[0]
422 422 x = numpy.arange(self.Num_Bin)
423 423
424 424 # print ('stop 0')
425 425
426 426 # 5 parameters, 2 Gaussians
427 427 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
428 428 DGauFitParam[:] = numpy.NaN
429 429
430 430 # SPCparam = []
431 431 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
432 432 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
433 433 # SPC_ch1[:] = 0 #numpy.NaN
434 434 # SPC_ch2[:] = 0 #numpy.NaN
435 435 # print ('stop 1')
436 436 for ht in range(self.Num_Hei):
437 437 # print (ht)
438 438 # print ('stop 2')
439 439 # Spectra at each range
440 440 spc = numpy.asarray(self.spc)[ch,:,ht]
441 441 snr = ( spc.mean() - wnoise ) / wnoise
442 442 snrdB = 10.*numpy.log10(snr)
443 443
444 444 #print ('stop 3')
445 445 if snrdB < SNRlimit :
446 446 # snr = numpy.NaN
447 447 # SPC_ch1[:,ht] = 0#numpy.NaN
448 448 # SPC_ch1[:,ht] = 0#numpy.NaN
449 449 # SPCparam = (SPC_ch1,SPC_ch2)
450 450 # print ('SNR less than SNRth')
451 451 continue
452 452 # wnoise = hildebrand_sekhon(spc,num_intg)
453 453 # print ('stop 2.01')
454 454 #############################################
455 455 # normalizing spc and noise
456 456 # This part differs from gg1
457 457 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
458 458 #spc = spc / spc_norm_max
459 459 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
460 460 #############################################
461 461
462 462 # print ('stop 2.1')
463 463 fatspectra=1.0
464 464 # noise per channel.... we might want to use the noise at each range
465 465
466 466 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
467 467 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
468 468 #if wnoise>1.1*pnoise: # to be tested later
469 469 # wnoise=pnoise
470 470 # noisebl = wnoise*0.9
471 471 # noisebh = wnoise*1.1
472 472 spc = spc - wnoise # signal
473 473
474 474 # print ('stop 2.2')
475 475 minx = numpy.argmin(spc)
476 476 #spcs=spc.copy()
477 477 spcs = numpy.roll(spc,-minx)
478 478 cum = numpy.cumsum(spcs)
479 479 # tot_noise = wnoise * self.Num_Bin #64;
480 480
481 481 # print ('stop 2.3')
482 482 # snr = sum(spcs) / tot_noise
483 483 # snrdB = 10.*numpy.log10(snr)
484 484 #print ('stop 3')
485 485 # if snrdB < SNRlimit :
486 486 # snr = numpy.NaN
487 487 # SPC_ch1[:,ht] = 0#numpy.NaN
488 488 # SPC_ch1[:,ht] = 0#numpy.NaN
489 489 # SPCparam = (SPC_ch1,SPC_ch2)
490 490 # print ('SNR less than SNRth')
491 491 # continue
492 492
493 493
494 494 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
495 495 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
496 496 # print ('stop 4')
497 497 cummax = max(cum)
498 498 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
499 499 cumlo = cummax * epsi
500 500 cumhi = cummax * (1-epsi)
501 501 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
502 502
503 503 # print ('stop 5')
504 504 if len(powerindex) < 1:# case for powerindex 0
505 505 # print ('powerindex < 1')
506 506 continue
507 507 powerlo = powerindex[0]
508 508 powerhi = powerindex[-1]
509 509 powerwidth = powerhi-powerlo
510 510 if powerwidth <= 1:
511 511 # print('powerwidth <= 1')
512 512 continue
513 513
514 514 # print ('stop 6')
515 515 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
516 516 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
517 517 midpeak = (firstpeak + secondpeak)/2.
518 518 firstamp = spcs[int(firstpeak)]
519 519 secondamp = spcs[int(secondpeak)]
520 520 midamp = spcs[int(midpeak)]
521 521
522 522 y_data = spc + wnoise
523 523
524 524 ''' single Gaussian '''
525 525 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
526 526 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
527 527 power0 = 2.
528 528 amplitude0 = midamp
529 529 state0 = [shift0,width0,amplitude0,power0,wnoise]
530 530 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
531 531 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
532 532 # print ('stop 7.1')
533 533 # print (bnds)
534 534
535 535 chiSq1=lsq1[1]
536 536
537 537 # print ('stop 8')
538 538 if fatspectra<1.0 and powerwidth<4:
539 539 choice=0
540 540 Amplitude0=lsq1[0][2]
541 541 shift0=lsq1[0][0]
542 542 width0=lsq1[0][1]
543 543 p0=lsq1[0][3]
544 544 Amplitude1=0.
545 545 shift1=0.
546 546 width1=0.
547 547 p1=0.
548 548 noise=lsq1[0][4]
549 549 #return (numpy.array([shift0,width0,Amplitude0,p0]),
550 550 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
551 551
552 552 # print ('stop 9')
553 553 ''' two Gaussians '''
554 554 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
555 555 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
556 556 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
557 557 width0 = powerwidth/6.
558 558 width1 = width0
559 559 power0 = 2.
560 560 power1 = power0
561 561 amplitude0 = firstamp
562 562 amplitude1 = secondamp
563 563 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
564 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 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 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 568 # print ('stop 10')
569 569 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
570 570
571 571 # print ('stop 11')
572 572 chiSq2 = lsq2[1]
573 573
574 574 # print ('stop 12')
575 575
576 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 578 # print ('stop 13')
579 579 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
580 580 if oneG:
581 581 choice = 0
582 582 else:
583 583 w1 = lsq2[0][1]; w2 = lsq2[0][5]
584 584 a1 = lsq2[0][2]; a2 = lsq2[0][6]
585 585 p1 = lsq2[0][3]; p2 = lsq2[0][7]
586 586 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
587 587 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
588 588 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
589 589
590 590 if gp1>gp2:
591 591 if a1>0.7*a2:
592 592 choice = 1
593 593 else:
594 594 choice = 2
595 595 elif gp2>gp1:
596 596 if a2>0.7*a1:
597 597 choice = 2
598 598 else:
599 599 choice = 1
600 600 else:
601 601 choice = numpy.argmax([a1,a2])+1
602 602 #else:
603 603 #choice=argmin([std2a,std2b])+1
604 604
605 605 else: # with low SNR go to the most energetic peak
606 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 608 # print ('stop 14')
609 609 shift0 = lsq2[0][0]
610 610 vel0 = Vrange[0] + shift0 * deltav
611 611 shift1 = lsq2[0][4]
612 612 # vel1=Vrange[0] + shift1 * deltav
613 613
614 614 # max_vel = 1.0
615 615 # Va = max(Vrange)
616 616 # deltav = Vrange[1]-Vrange[0]
617 617 # print ('stop 15')
618 618 #first peak will be 0, second peak will be 1
619 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 620 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
621 621 shift0 = lsq2[0][0]
622 622 width0 = lsq2[0][1]
623 623 Amplitude0 = lsq2[0][2]
624 624 p0 = lsq2[0][3]
625 625
626 626 shift1 = lsq2[0][4]
627 627 width1 = lsq2[0][5]
628 628 Amplitude1 = lsq2[0][6]
629 629 p1 = lsq2[0][7]
630 630 noise = lsq2[0][8]
631 631 else:
632 632 shift1 = lsq2[0][0]
633 633 width1 = lsq2[0][1]
634 634 Amplitude1 = lsq2[0][2]
635 635 p1 = lsq2[0][3]
636 636
637 637 shift0 = lsq2[0][4]
638 638 width0 = lsq2[0][5]
639 639 Amplitude0 = lsq2[0][6]
640 640 p0 = lsq2[0][7]
641 641 noise = lsq2[0][8]
642 642
643 643 if Amplitude0<0.05: # in case the peak is noise
644 644 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
645 645 if Amplitude1<0.05:
646 646 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
647 647
648 648 # print ('stop 16 ')
649 649 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
650 650 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
651 651 # SPCparam = (SPC_ch1,SPC_ch2)
652 652
653 653 DGauFitParam[0,ht,0] = noise
654 654 DGauFitParam[0,ht,1] = noise
655 655 DGauFitParam[1,ht,0] = Amplitude0
656 656 DGauFitParam[1,ht,1] = Amplitude1
657 657 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
658 658 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
659 659 DGauFitParam[3,ht,0] = width0 * deltav
660 660 DGauFitParam[3,ht,1] = width1 * deltav
661 661 DGauFitParam[4,ht,0] = p0
662 662 DGauFitParam[4,ht,1] = p1
663 663
664 664 # print (DGauFitParam.shape)
665 665 # print ('Leaving FitGau')
666 666 return DGauFitParam
667 667 # return SPCparam
668 668 # return GauSPC
669 669
670 670 def y_model1(self,x,state):
671 671 shift0, width0, amplitude0, power0, noise = state
672 672 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
673 673 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
674 674 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
675 675 return model0 + model0u + model0d + noise
676 676
677 677 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
678 678 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
679 679 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
680 680 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
681 681 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
682 682
683 683 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
684 684 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
685 685 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
686 686 return model0 + model0u + model0d + model1 + model1u + model1d + noise
687 687
688 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 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 692 def misfit2(self,state,y_data,x,num_intg):
693 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 697 class PrecipitationProc(Operation):
698 698
699 699 '''
700 700 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
701 701
702 702 Input:
703 703 self.dataOut.data_pre : SelfSpectra
704 704
705 705 Output:
706 706
707 707 self.dataOut.data_output : Reflectivity factor, rainfall Rate
708 708
709 709
710 710 Parameters affected:
711 711 '''
712 712
713 713 def __init__(self):
714 714 Operation.__init__(self)
715 715 self.i=0
716 716
717 717 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
718 718 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
719 719
720 720 # print ('Entering PrecepitationProc ... ')
721 721
722 722 if radar == "MIRA35C" :
723 723
724 724 self.spc = dataOut.data_pre[0].copy()
725 725 self.Num_Hei = self.spc.shape[2]
726 726 self.Num_Bin = self.spc.shape[1]
727 727 self.Num_Chn = self.spc.shape[0]
728 728 Ze = self.dBZeMODE2(dataOut)
729 729
730 730 else:
731 731
732 732 self.spc = dataOut.data_pre[0].copy()
733 733
734 734 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
735 735 self.spc[:,:,0:7]= numpy.NaN
736 736
737 737 self.Num_Hei = self.spc.shape[2]
738 738 self.Num_Bin = self.spc.shape[1]
739 739 self.Num_Chn = self.spc.shape[0]
740 740
741 741 VelRange = dataOut.spc_range[2]
742 742
743 743 ''' Se obtiene la constante del RADAR '''
744 744
745 745 self.Pt = Pt
746 746 self.Gt = Gt
747 747 self.Gr = Gr
748 748 self.Lambda = Lambda
749 749 self.aL = aL
750 750 self.tauW = tauW
751 751 self.ThetaT = ThetaT
752 752 self.ThetaR = ThetaR
753 753 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
754 754 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
755 755 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
756 756
757 757 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
758 758 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
759 759 RadarConstant = 10e-26 * Numerator / Denominator #
760 760 ExpConstant = 10**(40/10) #Constante Experimental
761 761
762 762 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
763 763 for i in range(self.Num_Chn):
764 764 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
765 765 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
766 766
767 767 SPCmean = numpy.mean(SignalPower, 0)
768 768 Pr = SPCmean[:,:]/dataOut.normFactor
769 769
770 770 # Declaring auxiliary variables
771 771 Range = dataOut.heightList*1000. #Range in m
772 772 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
773 773 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
774 774 zMtrx = rMtrx+Altitude
775 775 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
776 776 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
777 777
778 778 # height dependence to air density Foote and Du Toit (1969)
779 779 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
780 780 VMtrx = VelMtrx / delv_z #Normalized velocity
781 781 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
782 782 # Diameter is related to the fall speed of falling drops
783 783 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
784 784 # Only valid for D>= 0.16 mm
785 785 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
786 786
787 787 #Calculate Radar Reflectivity ETAn
788 788 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
789 789 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
790 790 # Radar Cross Section
791 791 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
792 792 # Drop Size Distribution
793 793 DSD = ETAn / sigmaD
794 794 # Equivalente Reflectivy
795 795 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
796 796 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
797 797 # RainFall Rate
798 798 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
799 799
800 800 # Censoring the data
801 801 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
802 802 SNRth = 10**(SNRdBlimit/10) #-30dB
803 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 804 W = numpy.nanmean(dataOut.data_dop,0)
805 805 W[novalid] = numpy.NaN
806 806 Ze_org[novalid] = numpy.NaN
807 807 RR[novalid] = numpy.NaN
808 808
809 809 dataOut.data_output = RR[8]
810 810 dataOut.data_param = numpy.ones([3,self.Num_Hei])
811 811 dataOut.channelList = [0,1,2]
812 812
813 813 dataOut.data_param[0]=10*numpy.log10(Ze_org)
814 814 dataOut.data_param[1]=-W
815 815 dataOut.data_param[2]=RR
816 816
817 817 # print ('Leaving PrecepitationProc ... ')
818 818 return dataOut
819 819
820 820 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
821 821
822 822 NPW = dataOut.NPW
823 823 COFA = dataOut.COFA
824 824
825 825 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
826 826 RadarConst = dataOut.RadarConst
827 827 #frequency = 34.85*10**9
828 828
829 829 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
830 830 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
831 831
832 832 ETA = numpy.sum(SNR,1)
833 833
834 834 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
835 835
836 836 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
837 837
838 838 for r in range(self.Num_Hei):
839 839
840 840 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
841 841 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
842 842
843 843 return Ze
844 844
845 845 # def GetRadarConstant(self):
846 846 #
847 847 # """
848 848 # Constants:
849 849 #
850 850 # Pt: Transmission Power dB 5kW 5000
851 851 # Gt: Transmission Gain dB 24.7 dB 295.1209
852 852 # Gr: Reception Gain dB 18.5 dB 70.7945
853 853 # Lambda: Wavelenght m 0.6741 m 0.6741
854 854 # aL: Attenuation loses dB 4dB 2.5118
855 855 # tauW: Width of transmission pulse s 4us 4e-6
856 856 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
857 857 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
858 858 #
859 859 # """
860 860 #
861 861 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
862 862 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
863 863 # RadarConstant = Numerator / Denominator
864 864 #
865 865 # return RadarConstant
866 866
867 867
868 868
869 869 class FullSpectralAnalysis(Operation):
870 870
871 871 """
872 872 Function that implements Full Spectral Analysis technique.
873 873
874 874 Input:
875 875 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
876 876 self.dataOut.groupList : Pairlist of channels
877 877 self.dataOut.ChanDist : Physical distance between receivers
878 878
879 879
880 880 Output:
881 881
882 882 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
883 883
884 884
885 885 Parameters affected: Winds, height range, SNR
886 886
887 887 """
888 888 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
889 889 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
890 890
891 891 spc = dataOut.data_pre[0].copy()
892 892 cspc = dataOut.data_pre[1]
893 893 nHeights = spc.shape[2]
894 894
895 895 # first_height = 0.75 #km (ref: data header 20170822)
896 896 # resolution_height = 0.075 #km
897 897 '''
898 898 finding height range. check this when radar parameters are changed!
899 899 '''
900 900 if maxheight is not None:
901 901 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
902 902 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
903 903 else:
904 904 range_max = nHeights
905 905 if minheight is not None:
906 906 # range_min = int((minheight - first_height) / resolution_height) # theoretical
907 907 range_min = int(13.26 * minheight - 5) # empirical, works better
908 908 if range_min < 0:
909 909 range_min = 0
910 910 else:
911 911 range_min = 0
912 912
913 913 pairsList = dataOut.groupList
914 914 if dataOut.ChanDist is not None :
915 915 ChanDist = dataOut.ChanDist
916 916 else:
917 917 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
918 918
919 919 # 4 variables: zonal, meridional, vertical, and average SNR
920 920 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
921 921 velocityX = numpy.zeros([nHeights]) * numpy.NaN
922 922 velocityY = numpy.zeros([nHeights]) * numpy.NaN
923 923 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
924 924
925 925 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
926 926
927 927 '''***********************************************WIND ESTIMATION**************************************'''
928 928 for Height in range(nHeights):
929 929
930 930 if Height >= range_min and Height < range_max:
931 931 # error_code will be useful in future analysis
932 932 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
933 933 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
934 934
935 935 if abs(Vzon) < 100. and abs(Vmer) < 100.:
936 936 velocityX[Height] = Vzon
937 937 velocityY[Height] = -Vmer
938 938 velocityZ[Height] = Vver
939 939
940 940 # Censoring data with SNR threshold
941 941 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
942 942
943 943 data_param[0] = velocityX
944 944 data_param[1] = velocityY
945 945 data_param[2] = velocityZ
946 946 data_param[3] = dbSNR
947 947 dataOut.data_param = data_param
948 948 return dataOut
949 949
950 950 def moving_average(self,x, N=2):
951 951 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
952 952 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
953 953
954 954 def gaus(self,xSamples,Amp,Mu,Sigma):
955 955 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
956 956
957 957 def Moments(self, ySamples, xSamples):
958 958 Power = numpy.nanmean(ySamples) # Power, 0th Moment
959 959 yNorm = ySamples / numpy.nansum(ySamples)
960 960 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
961 961 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
962 962 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
963 963 return numpy.array([Power,RadVel,StdDev])
964 964
965 965 def StopWindEstimation(self, error_code):
966 966 Vzon = numpy.NaN
967 967 Vmer = numpy.NaN
968 968 Vver = numpy.NaN
969 969 return Vzon, Vmer, Vver, error_code
970 970
971 971 def AntiAliasing(self, interval, maxstep):
972 972 """
973 973 function to prevent errors from aliased values when computing phaseslope
974 974 """
975 975 antialiased = numpy.zeros(len(interval))
976 976 copyinterval = interval.copy()
977 977
978 978 antialiased[0] = copyinterval[0]
979 979
980 980 for i in range(1,len(antialiased)):
981 981 step = interval[i] - interval[i-1]
982 982 if step > maxstep:
983 983 copyinterval -= 2*numpy.pi
984 984 antialiased[i] = copyinterval[i]
985 985 elif step < maxstep*(-1):
986 986 copyinterval += 2*numpy.pi
987 987 antialiased[i] = copyinterval[i]
988 988 else:
989 989 antialiased[i] = copyinterval[i].copy()
990 990
991 991 return antialiased
992 992
993 993 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
994 994 """
995 995 Function that Calculates Zonal, Meridional and Vertical wind velocities.
996 996 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
997 997
998 998 Input:
999 999 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1000 1000 pairsList : Pairlist of channels
1001 1001 ChanDist : array of xi_ij and eta_ij
1002 1002 Height : height at which data is processed
1003 1003 noise : noise in [channels] format for specific height
1004 1004 Abbsisarange : range of the frequencies or velocities
1005 1005 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1006 1006
1007 1007 Output:
1008 1008 Vzon, Vmer, Vver : wind velocities
1009 1009 error_code : int that states where code is terminated
1010 1010
1011 1011 0 : no error detected
1012 1012 1 : Gaussian of mean spc exceeds widthlimit
1013 1013 2 : no Gaussian of mean spc found
1014 1014 3 : SNR to low or velocity to high -> prec. e.g.
1015 1015 4 : at least one Gaussian of cspc exceeds widthlimit
1016 1016 5 : zero out of three cspc Gaussian fits converged
1017 1017 6 : phase slope fit could not be found
1018 1018 7 : arrays used to fit phase have different length
1019 1019 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1020 1020
1021 1021 """
1022 1022
1023 1023 error_code = 0
1024 1024
1025 1025 nChan = spc.shape[0]
1026 1026 nProf = spc.shape[1]
1027 1027 nPair = cspc.shape[0]
1028 1028
1029 1029 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1030 1030 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1031 1031 phase = numpy.zeros([nPair, nProf]) # phase between channels
1032 1032 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1033 1033 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1034 1034 xFrec = AbbsisaRange[0][:-1] # frequency range
1035 1035 xVel = AbbsisaRange[2][:-1] # velocity range
1036 1036 xSamples = xFrec # the frequency range is taken
1037 1037 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1038 1038
1039 1039 # only consider velocities with in NegativeLimit and PositiveLimit
1040 1040 if (NegativeLimit is None):
1041 1041 NegativeLimit = numpy.min(xVel)
1042 1042 if (PositiveLimit is None):
1043 1043 PositiveLimit = numpy.max(xVel)
1044 1044 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1045 1045 xSamples_zoom = xSamples[xvalid]
1046 1046
1047 1047 '''Getting Eij and Nij'''
1048 1048 Xi01, Xi02, Xi12 = ChanDist[:,0]
1049 1049 Eta01, Eta02, Eta12 = ChanDist[:,1]
1050 1050
1051 1051 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1052 1052 widthlimit = 10
1053 1053 '''************************* SPC is normalized ********************************'''
1054 1054 spc_norm = spc.copy()
1055 1055 # For each channel
1056 1056 for i in range(nChan):
1057 1057 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1058 1058 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1059 1059
1060 1060 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1061 1061
1062 1062 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1063 1063 you only fit the curve and don't need the absolute value of height for calculation,
1064 1064 only for estimation of width. for normalization of cross spectra, you need initial,
1065 1065 unnormalized self-spectra With noise.
1066 1066
1067 1067 Technically, you don't even need to normalize the self-spectra, as you only need the
1068 1068 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1069 1069 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1070 1070 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1071 1071 """
1072 1072 # initial conditions
1073 1073 popt = [1e-10,0,1e-10]
1074 1074 # Spectra average
1075 1075 SPCMean = numpy.average(SPC_Samples,0)
1076 1076 # Moments in frequency
1077 1077 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1078 1078
1079 1079 # Gauss Fit SPC in frequency domain
1080 1080 if dbSNR > SNRlimit: # only if SNR > SNRth
1081 1081 try:
1082 1082 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1083 1083 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1084 1084 return self.StopWindEstimation(error_code = 1)
1085 1085 FitGauss = self.gaus(xSamples_zoom,*popt)
1086 1086 except :#RuntimeError:
1087 1087 return self.StopWindEstimation(error_code = 2)
1088 1088 else:
1089 1089 return self.StopWindEstimation(error_code = 3)
1090 1090
1091 1091 '''***************************** CSPC Normalization *************************
1092 1092 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1093 1093 influence the norm which is not desired. First, a range is identified where the
1094 1094 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1095 1095 around it gets cut off and values replaced by mean determined by the boundary
1096 1096 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1097 1097
1098 1098 The sums are then added and multiplied by range/datapoints, because you need
1099 1099 an integral and not a sum for normalization.
1100 1100
1101 1101 A norm is found according to Briggs 92.
1102 1102 '''
1103 1103 # for each pair
1104 1104 for i in range(nPair):
1105 1105 cspc_norm = cspc[i,:].copy()
1106 1106 chan_index0 = pairsList[i][0]
1107 1107 chan_index1 = pairsList[i][1]
1108 1108 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1109 1109 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1110 1110
1111 1111 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1112 1112 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1113 1113 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1114 1114
1115 1115 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1116 1116 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1117 1117
1118 1118 '''*******************************FIT GAUSS CSPC************************************'''
1119 1119 try:
1120 1120 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1121 1121 if popt01[2] > widthlimit: # CONDITION
1122 1122 return self.StopWindEstimation(error_code = 4)
1123 1123 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1124 1124 if popt02[2] > widthlimit: # CONDITION
1125 1125 return self.StopWindEstimation(error_code = 4)
1126 1126 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1127 1127 if popt12[2] > widthlimit: # CONDITION
1128 1128 return self.StopWindEstimation(error_code = 4)
1129 1129
1130 1130 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1131 1131 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1132 1132 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1133 1133 except:
1134 1134 return self.StopWindEstimation(error_code = 5)
1135 1135
1136 1136
1137 1137 '''************* Getting Fij ***************'''
1138 1138 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1139 1139 GaussCenter = popt[1]
1140 1140 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1141 1141 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1142 1142
1143 1143 # Point where e^-1 is located in the gaussian
1144 1144 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1145 1145 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1146 1146 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1147 1147 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1148 1148
1149 1149 '''********** Taking frequency ranges from mean SPCs **********'''
1150 1150 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1151 1151 Range = numpy.empty(2)
1152 1152 Range[0] = GaussCenter - GauWidth
1153 1153 Range[1] = GaussCenter + GauWidth
1154 1154 # Point in x-axis where the bandwidth is located (min:max)
1155 1155 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1156 1156 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1157 1157 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1158 1158 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1159 1159 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1160 1160 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1161 1161
1162 1162 '''************************** Getting Phase Slope ***************************'''
1163 1163 for i in range(nPair):
1164 1164 if len(FrecRange) > 5:
1165 1165 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1166 1166 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1167 1167 if len(FrecRange) == len(PhaseRange):
1168 1168 try:
1169 1169 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1170 1170 PhaseSlope[i] = slope
1171 1171 PhaseInter[i] = intercept
1172 1172 except:
1173 1173 return self.StopWindEstimation(error_code = 6)
1174 1174 else:
1175 1175 return self.StopWindEstimation(error_code = 7)
1176 1176 else:
1177 1177 return self.StopWindEstimation(error_code = 8)
1178 1178
1179 1179 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1180 1180
1181 1181 '''Getting constant C'''
1182 1182 cC=(Fij*numpy.pi)**2
1183 1183
1184 1184 '''****** Getting constants F and G ******'''
1185 1185 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1186 1186 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1187 1187 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1188 1188 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1189 1189 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1190 1190 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1191 1191 MijResults = numpy.array([MijResult1, MijResult2])
1192 1192 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1193 1193
1194 1194 '''****** Getting constants A, B and H ******'''
1195 1195 W01 = numpy.nanmax( FitGauss01 )
1196 1196 W02 = numpy.nanmax( FitGauss02 )
1197 1197 W12 = numpy.nanmax( FitGauss12 )
1198 1198
1199 1199 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1200 1200 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1201 1201 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1202 1202 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1203 1203
1204 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 1205 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1206 1206
1207 1207 VxVy = numpy.array([[cA,cH],[cH,cB]])
1208 1208 VxVyResults = numpy.array([-cF,-cG])
1209 1209 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1210 1210 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1211 1211 error_code = 0
1212 1212
1213 1213 return Vzon, Vmer, Vver, error_code
1214 1214
1215 1215 class SpectralMoments(Operation):
1216 1216
1217 1217 '''
1218 1218 Function SpectralMoments()
1219 1219
1220 1220 Calculates moments (power, mean, standard deviation) and SNR of the signal
1221 1221
1222 1222 Type of dataIn: Spectra
1223 1223
1224 1224 Configuration Parameters:
1225 1225
1226 1226 dirCosx : Cosine director in X axis
1227 1227 dirCosy : Cosine director in Y axis
1228 1228
1229 1229 elevation :
1230 1230 azimuth :
1231 1231
1232 1232 Input:
1233 1233 channelList : simple channel list to select e.g. [2,3,7]
1234 1234 self.dataOut.data_pre : Spectral data
1235 1235 self.dataOut.abscissaList : List of frequencies
1236 1236 self.dataOut.noise : Noise level per channel
1237 1237
1238 1238 Affected:
1239 1239 self.dataOut.moments : Parameters per channel
1240 1240 self.dataOut.data_snr : SNR per channel
1241 1241
1242 1242 '''
1243 1243
1244 1244 def run(self, dataOut):
1245 1245
1246 1246 data = dataOut.data_pre[0]
1247 1247 absc = dataOut.abscissaList[:-1]
1248 1248 noise = dataOut.noise
1249 1249 nChannel = data.shape[0]
1250 1250 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1251 1251
1252 1252 for ind in range(nChannel):
1253 1253 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1254 1254
1255 1255 dataOut.moments = data_param[:,1:,:]
1256 1256 dataOut.data_snr = data_param[:,0]
1257 1257 dataOut.data_pow = data_param[:,1]
1258 1258 dataOut.data_dop = data_param[:,2]
1259 1259 dataOut.data_width = data_param[:,3]
1260 1260
1261 1261 return dataOut
1262 1262
1263 1263 def __calculateMoments(self, oldspec, oldfreq, n0,
1264 1264 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1265 1265
1266 1266 if (nicoh is None): nicoh = 1
1267 1267 if (graph is None): graph = 0
1268 1268 if (smooth is None): smooth = 0
1269 1269 elif (self.smooth < 3): smooth = 0
1270 1270
1271 1271 if (type1 is None): type1 = 0
1272 1272 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1273 1273 if (snrth is None): snrth = -3
1274 1274 if (dc is None): dc = 0
1275 1275 if (aliasing is None): aliasing = 0
1276 1276 if (oldfd is None): oldfd = 0
1277 1277 if (wwauto is None): wwauto = 0
1278 1278
1279 1279 if (n0 < 1.e-20): n0 = 1.e-20
1280 1280
1281 1281 freq = oldfreq
1282 1282 vec_power = numpy.zeros(oldspec.shape[1])
1283 1283 vec_fd = numpy.zeros(oldspec.shape[1])
1284 1284 vec_w = numpy.zeros(oldspec.shape[1])
1285 1285 vec_snr = numpy.zeros(oldspec.shape[1])
1286 1286
1287 1287 # oldspec = numpy.ma.masked_invalid(oldspec)
1288 1288
1289 1289 for ind in range(oldspec.shape[1]):
1290 1290
1291 1291 spec = oldspec[:,ind]
1292 1292 aux = spec*fwindow
1293 1293 max_spec = aux.max()
1294 1294 m = aux.tolist().index(max_spec)
1295 1295
1296 1296 # Smooth
1297 1297 if (smooth == 0):
1298 1298 spec2 = spec
1299 1299 else:
1300 1300 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1301 1301
1302 1302 # Moments Estimation
1303 1303 bb = spec2[numpy.arange(m,spec2.size)]
1304 1304 bb = (bb<n0).nonzero()
1305 1305 bb = bb[0]
1306 1306
1307 1307 ss = spec2[numpy.arange(0,m + 1)]
1308 1308 ss = (ss<n0).nonzero()
1309 1309 ss = ss[0]
1310 1310
1311 1311 if (bb.size == 0):
1312 1312 bb0 = spec.size - 1 - m
1313 1313 else:
1314 1314 bb0 = bb[0] - 1
1315 1315 if (bb0 < 0):
1316 1316 bb0 = 0
1317 1317
1318 1318 if (ss.size == 0):
1319 1319 ss1 = 1
1320 1320 else:
1321 1321 ss1 = max(ss) + 1
1322 1322
1323 1323 if (ss1 > m):
1324 1324 ss1 = m
1325 1325
1326 1326 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1327 1327
1328 1328 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1329 1329 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1330 1330 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1331 1331 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1332 1332 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1333 1333 snr = (spec2.mean()-n0)/n0
1334 1334 if (snr < 1.e-20) :
1335 1335 snr = 1.e-20
1336 1336
1337 1337 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1338 1338 vec_power[ind] = total_power
1339 1339 vec_fd[ind] = fd
1340 1340 vec_w[ind] = w
1341 1341 vec_snr[ind] = snr
1342 1342
1343 1343 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1344 1344
1345 1345 #------------------ Get SA Parameters --------------------------
1346 1346
1347 1347 def GetSAParameters(self):
1348 1348 #SA en frecuencia
1349 1349 pairslist = self.dataOut.groupList
1350 1350 num_pairs = len(pairslist)
1351 1351
1352 1352 vel = self.dataOut.abscissaList
1353 1353 spectra = self.dataOut.data_pre
1354 1354 cspectra = self.dataIn.data_cspc
1355 1355 delta_v = vel[1] - vel[0]
1356 1356
1357 1357 #Calculating the power spectrum
1358 1358 spc_pow = numpy.sum(spectra, 3)*delta_v
1359 1359 #Normalizing Spectra
1360 1360 norm_spectra = spectra/spc_pow
1361 1361 #Calculating the norm_spectra at peak
1362 1362 max_spectra = numpy.max(norm_spectra, 3)
1363 1363
1364 1364 #Normalizing Cross Spectra
1365 1365 norm_cspectra = numpy.zeros(cspectra.shape)
1366 1366
1367 1367 for i in range(num_chan):
1368 1368 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1369 1369
1370 1370 max_cspectra = numpy.max(norm_cspectra,2)
1371 1371 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1372 1372
1373 1373 for i in range(num_pairs):
1374 1374 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1375 1375 #------------------- Get Lags ----------------------------------
1376 1376
1377 1377 class SALags(Operation):
1378 1378 '''
1379 1379 Function GetMoments()
1380 1380
1381 1381 Input:
1382 1382 self.dataOut.data_pre
1383 1383 self.dataOut.abscissaList
1384 1384 self.dataOut.noise
1385 1385 self.dataOut.normFactor
1386 1386 self.dataOut.data_snr
1387 1387 self.dataOut.groupList
1388 1388 self.dataOut.nChannels
1389 1389
1390 1390 Affected:
1391 1391 self.dataOut.data_param
1392 1392
1393 1393 '''
1394 1394 def run(self, dataOut):
1395 1395 data_acf = dataOut.data_pre[0]
1396 1396 data_ccf = dataOut.data_pre[1]
1397 1397 normFactor_acf = dataOut.normFactor[0]
1398 1398 normFactor_ccf = dataOut.normFactor[1]
1399 1399 pairs_acf = dataOut.groupList[0]
1400 1400 pairs_ccf = dataOut.groupList[1]
1401 1401
1402 1402 nHeights = dataOut.nHeights
1403 1403 absc = dataOut.abscissaList
1404 1404 noise = dataOut.noise
1405 1405 SNR = dataOut.data_snr
1406 1406 nChannels = dataOut.nChannels
1407 1407 # pairsList = dataOut.groupList
1408 1408 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1409 1409
1410 1410 for l in range(len(pairs_acf)):
1411 1411 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1412 1412
1413 1413 for l in range(len(pairs_ccf)):
1414 1414 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1415 1415
1416 1416 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1417 1417 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1418 1418 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1419 1419 return
1420 1420
1421 1421 # def __getPairsAutoCorr(self, pairsList, nChannels):
1422 1422 #
1423 1423 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1424 1424 #
1425 1425 # for l in range(len(pairsList)):
1426 1426 # firstChannel = pairsList[l][0]
1427 1427 # secondChannel = pairsList[l][1]
1428 1428 #
1429 1429 # #Obteniendo pares de Autocorrelacion
1430 1430 # if firstChannel == secondChannel:
1431 1431 # pairsAutoCorr[firstChannel] = int(l)
1432 1432 #
1433 1433 # pairsAutoCorr = pairsAutoCorr.astype(int)
1434 1434 #
1435 1435 # pairsCrossCorr = range(len(pairsList))
1436 1436 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1437 1437 #
1438 1438 # return pairsAutoCorr, pairsCrossCorr
1439 1439
1440 1440 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1441 1441
1442 1442 lag0 = data_acf.shape[1]/2
1443 1443 #Funcion de Autocorrelacion
1444 1444 mean_acf = stats.nanmean(data_acf, axis = 0)
1445 1445
1446 1446 #Obtencion Indice de TauCross
1447 1447 ind_ccf = data_ccf.argmax(axis = 1)
1448 1448 #Obtencion Indice de TauAuto
1449 1449 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1450 1450 ccf_lag0 = data_ccf[:,lag0,:]
1451 1451
1452 1452 for i in range(ccf_lag0.shape[0]):
1453 1453 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1454 1454
1455 1455 #Obtencion de TauCross y TauAuto
1456 1456 tau_ccf = lagRange[ind_ccf]
1457 1457 tau_acf = lagRange[ind_acf]
1458 1458
1459 1459 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1460 1460
1461 1461 tau_ccf[Nan1,Nan2] = numpy.nan
1462 1462 tau_acf[Nan1,Nan2] = numpy.nan
1463 1463 tau = numpy.vstack((tau_ccf,tau_acf))
1464 1464
1465 1465 return tau
1466 1466
1467 1467 def __calculateLag1Phase(self, data, lagTRange):
1468 1468 data1 = stats.nanmean(data, axis = 0)
1469 1469 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1470 1470
1471 1471 phase = numpy.angle(data1[lag1,:])
1472 1472
1473 1473 return phase
1474 1474
1475 1475 class SpectralFitting(Operation):
1476 1476 '''
1477 1477 Function GetMoments()
1478 1478
1479 1479 Input:
1480 1480 Output:
1481 1481 Variables modified:
1482 1482 '''
1483 1483
1484 1484 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1485 1485
1486 1486
1487 1487 if path != None:
1488 1488 sys.path.append(path)
1489 1489 self.dataOut.library = importlib.import_module(file)
1490 1490
1491 1491 #To be inserted as a parameter
1492 1492 groupArray = numpy.array(groupList)
1493 1493 # groupArray = numpy.array([[0,1],[2,3]])
1494 1494 self.dataOut.groupList = groupArray
1495 1495
1496 1496 nGroups = groupArray.shape[0]
1497 1497 nChannels = self.dataIn.nChannels
1498 1498 nHeights=self.dataIn.heightList.size
1499 1499
1500 1500 #Parameters Array
1501 1501 self.dataOut.data_param = None
1502 1502
1503 1503 #Set constants
1504 1504 constants = self.dataOut.library.setConstants(self.dataIn)
1505 1505 self.dataOut.constants = constants
1506 1506 M = self.dataIn.normFactor
1507 1507 N = self.dataIn.nFFTPoints
1508 1508 ippSeconds = self.dataIn.ippSeconds
1509 1509 K = self.dataIn.nIncohInt
1510 1510 pairsArray = numpy.array(self.dataIn.pairsList)
1511 1511
1512 1512 #List of possible combinations
1513 1513 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1514 1514 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1515 1515
1516 1516 if getSNR:
1517 1517 listChannels = groupArray.reshape((groupArray.size))
1518 1518 listChannels.sort()
1519 1519 noise = self.dataIn.getNoise()
1520 1520 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1521 1521
1522 1522 for i in range(nGroups):
1523 1523 coord = groupArray[i,:]
1524 1524
1525 1525 #Input data array
1526 1526 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1527 1527 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1528 1528
1529 1529 #Cross Spectra data array for Covariance Matrixes
1530 1530 ind = 0
1531 1531 for pairs in listComb:
1532 1532 pairsSel = numpy.array([coord[x],coord[y]])
1533 1533 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1534 1534 ind += 1
1535 1535 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1536 1536 dataCross = dataCross**2/K
1537 1537
1538 1538 for h in range(nHeights):
1539 1539
1540 1540 #Input
1541 1541 d = data[:,h]
1542 1542
1543 1543 #Covariance Matrix
1544 1544 D = numpy.diag(d**2/K)
1545 1545 ind = 0
1546 1546 for pairs in listComb:
1547 1547 #Coordinates in Covariance Matrix
1548 1548 x = pairs[0]
1549 1549 y = pairs[1]
1550 1550 #Channel Index
1551 1551 S12 = dataCross[ind,:,h]
1552 1552 D12 = numpy.diag(S12)
1553 1553 #Completing Covariance Matrix with Cross Spectras
1554 1554 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1555 1555 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1556 1556 ind += 1
1557 1557 Dinv=numpy.linalg.inv(D)
1558 1558 L=numpy.linalg.cholesky(Dinv)
1559 1559 LT=L.T
1560 1560
1561 1561 dp = numpy.dot(LT,d)
1562 1562
1563 1563 #Initial values
1564 1564 data_spc = self.dataIn.data_spc[coord,:,h]
1565 1565
1566 1566 if (h>0)and(error1[3]<5):
1567 1567 p0 = self.dataOut.data_param[i,:,h-1]
1568 1568 else:
1569 1569 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1570 1570
1571 1571 try:
1572 1572 #Least Squares
1573 1573 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1574 1574 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1575 1575 #Chi square error
1576 1576 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1577 1577 #Error with Jacobian
1578 1578 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1579 1579 except:
1580 1580 minp = p0*numpy.nan
1581 1581 error0 = numpy.nan
1582 1582 error1 = p0*numpy.nan
1583 1583
1584 1584 #Save
1585 1585 if self.dataOut.data_param is None:
1586 1586 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1587 1587 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1588 1588
1589 1589 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1590 1590 self.dataOut.data_param[i,:,h] = minp
1591 1591 return
1592 1592
1593 1593 def __residFunction(self, p, dp, LT, constants):
1594 1594
1595 1595 fm = self.dataOut.library.modelFunction(p, constants)
1596 1596 fmp=numpy.dot(LT,fm)
1597 1597
1598 1598 return dp-fmp
1599 1599
1600 1600 def __getSNR(self, z, noise):
1601 1601
1602 1602 avg = numpy.average(z, axis=1)
1603 1603 SNR = (avg.T-noise)/noise
1604 1604 SNR = SNR.T
1605 1605 return SNR
1606 1606
1607 1607 def __chisq(p,chindex,hindex):
1608 1608 #similar to Resid but calculates CHI**2
1609 1609 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1610 1610 dp=numpy.dot(LT,d)
1611 1611 fmp=numpy.dot(LT,fm)
1612 1612 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1613 1613 return chisq
1614 1614
1615 1615 class WindProfiler(Operation):
1616 1616
1617 1617 __isConfig = False
1618 1618
1619 1619 __initime = None
1620 1620 __lastdatatime = None
1621 1621 __integrationtime = None
1622 1622
1623 1623 __buffer = None
1624 1624
1625 1625 __dataReady = False
1626 1626
1627 1627 __firstdata = None
1628 1628
1629 1629 n = None
1630 1630
1631 1631 def __init__(self):
1632 1632 Operation.__init__(self)
1633 1633
1634 1634 def __calculateCosDir(self, elev, azim):
1635 1635 zen = (90 - elev)*numpy.pi/180
1636 1636 azim = azim*numpy.pi/180
1637 1637 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1638 1638 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1639 1639
1640 1640 signX = numpy.sign(numpy.cos(azim))
1641 1641 signY = numpy.sign(numpy.sin(azim))
1642 1642
1643 1643 cosDirX = numpy.copysign(cosDirX, signX)
1644 1644 cosDirY = numpy.copysign(cosDirY, signY)
1645 1645 return cosDirX, cosDirY
1646 1646
1647 1647 def __calculateAngles(self, theta_x, theta_y, azimuth):
1648 1648
1649 1649 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1650 1650 zenith_arr = numpy.arccos(dir_cosw)
1651 1651 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1652 1652
1653 1653 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1654 1654 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1655 1655
1656 1656 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1657 1657
1658 1658 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1659 1659
1660 1660 #
1661 1661 if horOnly:
1662 1662 A = numpy.c_[dir_cosu,dir_cosv]
1663 1663 else:
1664 1664 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1665 1665 A = numpy.asmatrix(A)
1666 1666 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1667 1667
1668 1668 return A1
1669 1669
1670 1670 def __correctValues(self, heiRang, phi, velRadial, SNR):
1671 1671 listPhi = phi.tolist()
1672 1672 maxid = listPhi.index(max(listPhi))
1673 1673 minid = listPhi.index(min(listPhi))
1674 1674
1675 1675 rango = list(range(len(phi)))
1676 1676 # rango = numpy.delete(rango,maxid)
1677 1677
1678 1678 heiRang1 = heiRang*math.cos(phi[maxid])
1679 1679 heiRangAux = heiRang*math.cos(phi[minid])
1680 1680 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1681 1681 heiRang1 = numpy.delete(heiRang1,indOut)
1682 1682
1683 1683 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1684 1684 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1685 1685
1686 1686 for i in rango:
1687 1687 x = heiRang*math.cos(phi[i])
1688 1688 y1 = velRadial[i,:]
1689 1689 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1690 1690
1691 1691 x1 = heiRang1
1692 1692 y11 = f1(x1)
1693 1693
1694 1694 y2 = SNR[i,:]
1695 1695 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1696 1696 y21 = f2(x1)
1697 1697
1698 1698 velRadial1[i,:] = y11
1699 1699 SNR1[i,:] = y21
1700 1700
1701 1701 return heiRang1, velRadial1, SNR1
1702 1702
1703 1703 def __calculateVelUVW(self, A, velRadial):
1704 1704
1705 1705 #Operacion Matricial
1706 1706 # velUVW = numpy.zeros((velRadial.shape[1],3))
1707 1707 # for ind in range(velRadial.shape[1]):
1708 1708 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1709 1709 # velUVW = velUVW.transpose()
1710 1710 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1711 1711 velUVW[:,:] = numpy.dot(A,velRadial)
1712 1712
1713 1713
1714 1714 return velUVW
1715 1715
1716 1716 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1717 1717
1718 1718 def techniqueDBS(self, kwargs):
1719 1719 """
1720 1720 Function that implements Doppler Beam Swinging (DBS) technique.
1721 1721
1722 1722 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1723 1723 Direction correction (if necessary), Ranges and SNR
1724 1724
1725 1725 Output: Winds estimation (Zonal, Meridional and Vertical)
1726 1726
1727 1727 Parameters affected: Winds, height range, SNR
1728 1728 """
1729 1729 velRadial0 = kwargs['velRadial']
1730 1730 heiRang = kwargs['heightList']
1731 1731 SNR0 = kwargs['SNR']
1732 1732
1733 1733 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1734 1734 theta_x = numpy.array(kwargs['dirCosx'])
1735 1735 theta_y = numpy.array(kwargs['dirCosy'])
1736 1736 else:
1737 1737 elev = numpy.array(kwargs['elevation'])
1738 1738 azim = numpy.array(kwargs['azimuth'])
1739 1739 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1740 1740 azimuth = kwargs['correctAzimuth']
1741 1741 if 'horizontalOnly' in kwargs:
1742 1742 horizontalOnly = kwargs['horizontalOnly']
1743 1743 else: horizontalOnly = False
1744 1744 if 'correctFactor' in kwargs:
1745 1745 correctFactor = kwargs['correctFactor']
1746 1746 else: correctFactor = 1
1747 1747 if 'channelList' in kwargs:
1748 1748 channelList = kwargs['channelList']
1749 1749 if len(channelList) == 2:
1750 1750 horizontalOnly = True
1751 1751 arrayChannel = numpy.array(channelList)
1752 1752 param = param[arrayChannel,:,:]
1753 1753 theta_x = theta_x[arrayChannel]
1754 1754 theta_y = theta_y[arrayChannel]
1755 1755
1756 1756 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1757 1757 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1758 1758 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1759 1759
1760 1760 #Calculo de Componentes de la velocidad con DBS
1761 1761 winds = self.__calculateVelUVW(A,velRadial1)
1762 1762
1763 1763 return winds, heiRang1, SNR1
1764 1764
1765 1765 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1766 1766
1767 1767 nPairs = len(pairs_ccf)
1768 1768 posx = numpy.asarray(posx)
1769 1769 posy = numpy.asarray(posy)
1770 1770
1771 1771 #Rotacion Inversa para alinear con el azimuth
1772 1772 if azimuth!= None:
1773 1773 azimuth = azimuth*math.pi/180
1774 1774 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1775 1775 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1776 1776 else:
1777 1777 posx1 = posx
1778 1778 posy1 = posy
1779 1779
1780 1780 #Calculo de Distancias
1781 1781 distx = numpy.zeros(nPairs)
1782 1782 disty = numpy.zeros(nPairs)
1783 1783 dist = numpy.zeros(nPairs)
1784 1784 ang = numpy.zeros(nPairs)
1785 1785
1786 1786 for i in range(nPairs):
1787 1787 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1788 1788 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1789 1789 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1790 1790 ang[i] = numpy.arctan2(disty[i],distx[i])
1791 1791
1792 1792 return distx, disty, dist, ang
1793 1793 #Calculo de Matrices
1794 1794 # nPairs = len(pairs)
1795 1795 # ang1 = numpy.zeros((nPairs, 2, 1))
1796 1796 # dist1 = numpy.zeros((nPairs, 2, 1))
1797 1797 #
1798 1798 # for j in range(nPairs):
1799 1799 # dist1[j,0,0] = dist[pairs[j][0]]
1800 1800 # dist1[j,1,0] = dist[pairs[j][1]]
1801 1801 # ang1[j,0,0] = ang[pairs[j][0]]
1802 1802 # ang1[j,1,0] = ang[pairs[j][1]]
1803 1803 #
1804 1804 # return distx,disty, dist1,ang1
1805 1805
1806 1806
1807 1807 def __calculateVelVer(self, phase, lagTRange, _lambda):
1808 1808
1809 1809 Ts = lagTRange[1] - lagTRange[0]
1810 1810 velW = -_lambda*phase/(4*math.pi*Ts)
1811 1811
1812 1812 return velW
1813 1813
1814 1814 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1815 1815 nPairs = tau1.shape[0]
1816 1816 nHeights = tau1.shape[1]
1817 1817 vel = numpy.zeros((nPairs,3,nHeights))
1818 1818 dist1 = numpy.reshape(dist, (dist.size,1))
1819 1819
1820 1820 angCos = numpy.cos(ang)
1821 1821 angSin = numpy.sin(ang)
1822 1822
1823 1823 vel0 = dist1*tau1/(2*tau2**2)
1824 1824 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1825 1825 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1826 1826
1827 1827 ind = numpy.where(numpy.isinf(vel))
1828 1828 vel[ind] = numpy.nan
1829 1829
1830 1830 return vel
1831 1831
1832 1832 # def __getPairsAutoCorr(self, pairsList, nChannels):
1833 1833 #
1834 1834 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1835 1835 #
1836 1836 # for l in range(len(pairsList)):
1837 1837 # firstChannel = pairsList[l][0]
1838 1838 # secondChannel = pairsList[l][1]
1839 1839 #
1840 1840 # #Obteniendo pares de Autocorrelacion
1841 1841 # if firstChannel == secondChannel:
1842 1842 # pairsAutoCorr[firstChannel] = int(l)
1843 1843 #
1844 1844 # pairsAutoCorr = pairsAutoCorr.astype(int)
1845 1845 #
1846 1846 # pairsCrossCorr = range(len(pairsList))
1847 1847 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1848 1848 #
1849 1849 # return pairsAutoCorr, pairsCrossCorr
1850 1850
1851 1851 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1852 1852 def techniqueSA(self, kwargs):
1853 1853
1854 1854 """
1855 1855 Function that implements Spaced Antenna (SA) technique.
1856 1856
1857 1857 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1858 1858 Direction correction (if necessary), Ranges and SNR
1859 1859
1860 1860 Output: Winds estimation (Zonal, Meridional and Vertical)
1861 1861
1862 1862 Parameters affected: Winds
1863 1863 """
1864 1864 position_x = kwargs['positionX']
1865 1865 position_y = kwargs['positionY']
1866 1866 azimuth = kwargs['azimuth']
1867 1867
1868 1868 if 'correctFactor' in kwargs:
1869 1869 correctFactor = kwargs['correctFactor']
1870 1870 else:
1871 1871 correctFactor = 1
1872 1872
1873 1873 groupList = kwargs['groupList']
1874 1874 pairs_ccf = groupList[1]
1875 1875 tau = kwargs['tau']
1876 1876 _lambda = kwargs['_lambda']
1877 1877
1878 1878 #Cross Correlation pairs obtained
1879 1879 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1880 1880 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1881 1881 # pairsSelArray = numpy.array(pairsSelected)
1882 1882 # pairs = []
1883 1883 #
1884 1884 # #Wind estimation pairs obtained
1885 1885 # for i in range(pairsSelArray.shape[0]/2):
1886 1886 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1887 1887 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1888 1888 # pairs.append((ind1,ind2))
1889 1889
1890 1890 indtau = tau.shape[0]/2
1891 1891 tau1 = tau[:indtau,:]
1892 1892 tau2 = tau[indtau:-1,:]
1893 1893 # tau1 = tau1[pairs,:]
1894 1894 # tau2 = tau2[pairs,:]
1895 1895 phase1 = tau[-1,:]
1896 1896
1897 1897 #---------------------------------------------------------------------
1898 1898 #Metodo Directo
1899 1899 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1900 1900 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1901 1901 winds = stats.nanmean(winds, axis=0)
1902 1902 #---------------------------------------------------------------------
1903 1903 #Metodo General
1904 1904 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1905 1905 # #Calculo Coeficientes de Funcion de Correlacion
1906 1906 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1907 1907 # #Calculo de Velocidades
1908 1908 # winds = self.calculateVelUV(F,G,A,B,H)
1909 1909
1910 1910 #---------------------------------------------------------------------
1911 1911 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1912 1912 winds = correctFactor*winds
1913 1913 return winds
1914 1914
1915 1915 def __checkTime(self, currentTime, paramInterval, outputInterval):
1916 1916
1917 1917 dataTime = currentTime + paramInterval
1918 1918 deltaTime = dataTime - self.__initime
1919 1919
1920 1920 if deltaTime >= outputInterval or deltaTime < 0:
1921 1921 self.__dataReady = True
1922 1922 return
1923 1923
1924 1924 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1925 1925 '''
1926 1926 Function that implements winds estimation technique with detected meteors.
1927 1927
1928 1928 Input: Detected meteors, Minimum meteor quantity to wind estimation
1929 1929
1930 1930 Output: Winds estimation (Zonal and Meridional)
1931 1931
1932 1932 Parameters affected: Winds
1933 1933 '''
1934 1934 #Settings
1935 1935 nInt = (heightMax - heightMin)/2
1936 1936 nInt = int(nInt)
1937 1937 winds = numpy.zeros((2,nInt))*numpy.nan
1938 1938
1939 1939 #Filter errors
1940 1940 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1941 1941 finalMeteor = arrayMeteor[error,:]
1942 1942
1943 1943 #Meteor Histogram
1944 1944 finalHeights = finalMeteor[:,2]
1945 1945 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1946 1946 nMeteorsPerI = hist[0]
1947 1947 heightPerI = hist[1]
1948 1948
1949 1949 #Sort of meteors
1950 1950 indSort = finalHeights.argsort()
1951 1951 finalMeteor2 = finalMeteor[indSort,:]
1952 1952
1953 1953 # Calculating winds
1954 1954 ind1 = 0
1955 1955 ind2 = 0
1956 1956
1957 1957 for i in range(nInt):
1958 1958 nMet = nMeteorsPerI[i]
1959 1959 ind1 = ind2
1960 1960 ind2 = ind1 + nMet
1961 1961
1962 1962 meteorAux = finalMeteor2[ind1:ind2,:]
1963 1963
1964 1964 if meteorAux.shape[0] >= meteorThresh:
1965 1965 vel = meteorAux[:, 6]
1966 1966 zen = meteorAux[:, 4]*numpy.pi/180
1967 1967 azim = meteorAux[:, 3]*numpy.pi/180
1968 1968
1969 1969 n = numpy.cos(zen)
1970 1970 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1971 1971 # l = m*numpy.tan(azim)
1972 1972 l = numpy.sin(zen)*numpy.sin(azim)
1973 1973 m = numpy.sin(zen)*numpy.cos(azim)
1974 1974
1975 1975 A = numpy.vstack((l, m)).transpose()
1976 1976 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1977 1977 windsAux = numpy.dot(A1, vel)
1978 1978
1979 1979 winds[0,i] = windsAux[0]
1980 1980 winds[1,i] = windsAux[1]
1981 1981
1982 1982 return winds, heightPerI[:-1]
1983 1983
1984 1984 def techniqueNSM_SA(self, **kwargs):
1985 1985 metArray = kwargs['metArray']
1986 1986 heightList = kwargs['heightList']
1987 1987 timeList = kwargs['timeList']
1988 1988
1989 1989 rx_location = kwargs['rx_location']
1990 1990 groupList = kwargs['groupList']
1991 1991 azimuth = kwargs['azimuth']
1992 1992 dfactor = kwargs['dfactor']
1993 1993 k = kwargs['k']
1994 1994
1995 1995 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1996 1996 d = dist*dfactor
1997 1997 #Phase calculation
1998 1998 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1999 1999
2000 2000 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2001 2001
2002 2002 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2003 2003 azimuth1 = azimuth1*numpy.pi/180
2004 2004
2005 2005 for i in range(heightList.size):
2006 2006 h = heightList[i]
2007 2007 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2008 2008 metHeight = metArray1[indH,:]
2009 2009 if metHeight.shape[0] >= 2:
2010 2010 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2011 2011 iazim = metHeight[:,1].astype(int)
2012 2012 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2013 2013 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2014 2014 A = numpy.asmatrix(A)
2015 2015 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2016 2016 velHor = numpy.dot(A1,velAux)
2017 2017
2018 2018 velEst[i,:] = numpy.squeeze(velHor)
2019 2019 return velEst
2020 2020
2021 2021 def __getPhaseSlope(self, metArray, heightList, timeList):
2022 2022 meteorList = []
2023 2023 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2024 2024 #Putting back together the meteor matrix
2025 2025 utctime = metArray[:,0]
2026 2026 uniqueTime = numpy.unique(utctime)
2027 2027
2028 2028 phaseDerThresh = 0.5
2029 2029 ippSeconds = timeList[1] - timeList[0]
2030 2030 sec = numpy.where(timeList>1)[0][0]
2031 2031 nPairs = metArray.shape[1] - 6
2032 2032 nHeights = len(heightList)
2033 2033
2034 2034 for t in uniqueTime:
2035 2035 metArray1 = metArray[utctime==t,:]
2036 2036 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2037 2037 tmet = metArray1[:,1].astype(int)
2038 2038 hmet = metArray1[:,2].astype(int)
2039 2039
2040 2040 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2041 2041 metPhase[:,:] = numpy.nan
2042 2042 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2043 2043
2044 2044 #Delete short trails
2045 2045 metBool = ~numpy.isnan(metPhase[0,:,:])
2046 2046 heightVect = numpy.sum(metBool, axis = 1)
2047 2047 metBool[heightVect<sec,:] = False
2048 2048 metPhase[:,heightVect<sec,:] = numpy.nan
2049 2049
2050 2050 #Derivative
2051 2051 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2052 2052 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2053 2053 metPhase[phDerAux] = numpy.nan
2054 2054
2055 2055 #--------------------------METEOR DETECTION -----------------------------------------
2056 2056 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2057 2057
2058 2058 for p in numpy.arange(nPairs):
2059 2059 phase = metPhase[p,:,:]
2060 2060 phDer = metDer[p,:,:]
2061 2061
2062 2062 for h in indMet:
2063 2063 height = heightList[h]
2064 2064 phase1 = phase[h,:] #82
2065 2065 phDer1 = phDer[h,:]
2066 2066
2067 2067 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2068 2068
2069 2069 indValid = numpy.where(~numpy.isnan(phase1))[0]
2070 2070 initMet = indValid[0]
2071 2071 endMet = 0
2072 2072
2073 2073 for i in range(len(indValid)-1):
2074 2074
2075 2075 #Time difference
2076 2076 inow = indValid[i]
2077 2077 inext = indValid[i+1]
2078 2078 idiff = inext - inow
2079 2079 #Phase difference
2080 2080 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2081 2081
2082 2082 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2083 2083 sizeTrail = inow - initMet + 1
2084 2084 if sizeTrail>3*sec: #Too short meteors
2085 2085 x = numpy.arange(initMet,inow+1)*ippSeconds
2086 2086 y = phase1[initMet:inow+1]
2087 2087 ynnan = ~numpy.isnan(y)
2088 2088 x = x[ynnan]
2089 2089 y = y[ynnan]
2090 2090 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2091 2091 ylin = x*slope + intercept
2092 2092 rsq = r_value**2
2093 2093 if rsq > 0.5:
2094 2094 vel = slope#*height*1000/(k*d)
2095 2095 estAux = numpy.array([utctime,p,height, vel, rsq])
2096 2096 meteorList.append(estAux)
2097 2097 initMet = inext
2098 2098 metArray2 = numpy.array(meteorList)
2099 2099
2100 2100 return metArray2
2101 2101
2102 2102 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2103 2103
2104 2104 azimuth1 = numpy.zeros(len(pairslist))
2105 2105 dist = numpy.zeros(len(pairslist))
2106 2106
2107 2107 for i in range(len(rx_location)):
2108 2108 ch0 = pairslist[i][0]
2109 2109 ch1 = pairslist[i][1]
2110 2110
2111 2111 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2112 2112 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2113 2113 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2114 2114 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2115 2115
2116 2116 azimuth1 -= azimuth0
2117 2117 return azimuth1, dist
2118 2118
2119 2119 def techniqueNSM_DBS(self, **kwargs):
2120 2120 metArray = kwargs['metArray']
2121 2121 heightList = kwargs['heightList']
2122 2122 timeList = kwargs['timeList']
2123 2123 azimuth = kwargs['azimuth']
2124 2124 theta_x = numpy.array(kwargs['theta_x'])
2125 2125 theta_y = numpy.array(kwargs['theta_y'])
2126 2126
2127 2127 utctime = metArray[:,0]
2128 2128 cmet = metArray[:,1].astype(int)
2129 2129 hmet = metArray[:,3].astype(int)
2130 2130 SNRmet = metArray[:,4]
2131 2131 vmet = metArray[:,5]
2132 2132 spcmet = metArray[:,6]
2133 2133
2134 2134 nChan = numpy.max(cmet) + 1
2135 2135 nHeights = len(heightList)
2136 2136
2137 2137 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2138 2138 hmet = heightList[hmet]
2139 2139 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2140 2140
2141 2141 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2142 2142
2143 2143 for i in range(nHeights - 1):
2144 2144 hmin = heightList[i]
2145 2145 hmax = heightList[i + 1]
2146 2146
2147 2147 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2148 2148 indthisH = numpy.where(thisH)
2149 2149
2150 2150 if numpy.size(indthisH) > 3:
2151 2151
2152 2152 vel_aux = vmet[thisH]
2153 2153 chan_aux = cmet[thisH]
2154 2154 cosu_aux = dir_cosu[chan_aux]
2155 2155 cosv_aux = dir_cosv[chan_aux]
2156 2156 cosw_aux = dir_cosw[chan_aux]
2157 2157
2158 2158 nch = numpy.size(numpy.unique(chan_aux))
2159 2159 if nch > 1:
2160 2160 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2161 2161 velEst[i,:] = numpy.dot(A,vel_aux)
2162 2162
2163 2163 return velEst
2164 2164
2165 2165 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2166 2166
2167 2167 param = dataOut.data_param
2168 2168 if dataOut.abscissaList != None:
2169 2169 absc = dataOut.abscissaList[:-1]
2170 2170 # noise = dataOut.noise
2171 2171 heightList = dataOut.heightList
2172 2172 SNR = dataOut.data_snr
2173 2173
2174 2174 if technique == 'DBS':
2175 2175
2176 2176 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2177 2177 kwargs['heightList'] = heightList
2178 2178 kwargs['SNR'] = SNR
2179 2179
2180 2180 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2181 2181 dataOut.utctimeInit = dataOut.utctime
2182 2182 dataOut.outputInterval = dataOut.paramInterval
2183 2183
2184 2184 elif technique == 'SA':
2185 2185
2186 2186 #Parameters
2187 2187 # position_x = kwargs['positionX']
2188 2188 # position_y = kwargs['positionY']
2189 2189 # azimuth = kwargs['azimuth']
2190 2190 #
2191 2191 # if kwargs.has_key('crosspairsList'):
2192 2192 # pairs = kwargs['crosspairsList']
2193 2193 # else:
2194 2194 # pairs = None
2195 2195 #
2196 2196 # if kwargs.has_key('correctFactor'):
2197 2197 # correctFactor = kwargs['correctFactor']
2198 2198 # else:
2199 2199 # correctFactor = 1
2200 2200
2201 2201 # tau = dataOut.data_param
2202 2202 # _lambda = dataOut.C/dataOut.frequency
2203 2203 # pairsList = dataOut.groupList
2204 2204 # nChannels = dataOut.nChannels
2205 2205
2206 2206 kwargs['groupList'] = dataOut.groupList
2207 2207 kwargs['tau'] = dataOut.data_param
2208 2208 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2209 2209 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2210 2210 dataOut.data_output = self.techniqueSA(kwargs)
2211 2211 dataOut.utctimeInit = dataOut.utctime
2212 2212 dataOut.outputInterval = dataOut.timeInterval
2213 2213
2214 2214 elif technique == 'Meteors':
2215 2215 dataOut.flagNoData = True
2216 2216 self.__dataReady = False
2217 2217
2218 2218 if 'nHours' in kwargs:
2219 2219 nHours = kwargs['nHours']
2220 2220 else:
2221 2221 nHours = 1
2222 2222
2223 2223 if 'meteorsPerBin' in kwargs:
2224 2224 meteorThresh = kwargs['meteorsPerBin']
2225 2225 else:
2226 2226 meteorThresh = 6
2227 2227
2228 2228 if 'hmin' in kwargs:
2229 2229 hmin = kwargs['hmin']
2230 2230 else: hmin = 70
2231 2231 if 'hmax' in kwargs:
2232 2232 hmax = kwargs['hmax']
2233 2233 else: hmax = 110
2234 2234
2235 2235 dataOut.outputInterval = nHours*3600
2236 2236
2237 2237 if self.__isConfig == False:
2238 2238 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2239 2239 #Get Initial LTC time
2240 2240 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2241 2241 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2242 2242
2243 2243 self.__isConfig = True
2244 2244
2245 2245 if self.__buffer is None:
2246 2246 self.__buffer = dataOut.data_param
2247 2247 self.__firstdata = copy.copy(dataOut)
2248 2248
2249 2249 else:
2250 2250 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2251 2251
2252 2252 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2253 2253
2254 2254 if self.__dataReady:
2255 2255 dataOut.utctimeInit = self.__initime
2256 2256
2257 2257 self.__initime += dataOut.outputInterval #to erase time offset
2258 2258
2259 2259 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2260 2260 dataOut.flagNoData = False
2261 2261 self.__buffer = None
2262 2262
2263 2263 elif technique == 'Meteors1':
2264 2264 dataOut.flagNoData = True
2265 2265 self.__dataReady = False
2266 2266
2267 2267 if 'nMins' in kwargs:
2268 2268 nMins = kwargs['nMins']
2269 2269 else: nMins = 20
2270 2270 if 'rx_location' in kwargs:
2271 2271 rx_location = kwargs['rx_location']
2272 2272 else: rx_location = [(0,1),(1,1),(1,0)]
2273 2273 if 'azimuth' in kwargs:
2274 2274 azimuth = kwargs['azimuth']
2275 2275 else: azimuth = 51.06
2276 2276 if 'dfactor' in kwargs:
2277 2277 dfactor = kwargs['dfactor']
2278 2278 if 'mode' in kwargs:
2279 2279 mode = kwargs['mode']
2280 2280 if 'theta_x' in kwargs:
2281 2281 theta_x = kwargs['theta_x']
2282 2282 if 'theta_y' in kwargs:
2283 2283 theta_y = kwargs['theta_y']
2284 2284 else: mode = 'SA'
2285 2285
2286 2286 #Borrar luego esto
2287 2287 if dataOut.groupList is None:
2288 2288 dataOut.groupList = [(0,1),(0,2),(1,2)]
2289 2289 groupList = dataOut.groupList
2290 2290 C = 3e8
2291 2291 freq = 50e6
2292 2292 lamb = C/freq
2293 2293 k = 2*numpy.pi/lamb
2294 2294
2295 2295 timeList = dataOut.abscissaList
2296 2296 heightList = dataOut.heightList
2297 2297
2298 2298 if self.__isConfig == False:
2299 2299 dataOut.outputInterval = nMins*60
2300 2300 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2301 2301 #Get Initial LTC time
2302 2302 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2303 2303 minuteAux = initime.minute
2304 2304 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2305 2305 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2306 2306
2307 2307 self.__isConfig = True
2308 2308
2309 2309 if self.__buffer is None:
2310 2310 self.__buffer = dataOut.data_param
2311 2311 self.__firstdata = copy.copy(dataOut)
2312 2312
2313 2313 else:
2314 2314 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2315 2315
2316 2316 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2317 2317
2318 2318 if self.__dataReady:
2319 2319 dataOut.utctimeInit = self.__initime
2320 2320 self.__initime += dataOut.outputInterval #to erase time offset
2321 2321
2322 2322 metArray = self.__buffer
2323 2323 if mode == 'SA':
2324 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 2325 elif mode == 'DBS':
2326 2326 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2327 2327 dataOut.data_output = dataOut.data_output.T
2328 2328 dataOut.flagNoData = False
2329 2329 self.__buffer = None
2330 2330
2331 2331 return
2332 2332
2333 2333 class EWDriftsEstimation(Operation):
2334 2334
2335 2335 def __init__(self):
2336 2336 Operation.__init__(self)
2337 2337
2338 2338 def __correctValues(self, heiRang, phi, velRadial, SNR):
2339 2339 listPhi = phi.tolist()
2340 2340 maxid = listPhi.index(max(listPhi))
2341 2341 minid = listPhi.index(min(listPhi))
2342 2342
2343 2343 rango = list(range(len(phi)))
2344 2344 # rango = numpy.delete(rango,maxid)
2345 2345
2346 2346 heiRang1 = heiRang*math.cos(phi[maxid])
2347 2347 heiRangAux = heiRang*math.cos(phi[minid])
2348 2348 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2349 2349 heiRang1 = numpy.delete(heiRang1,indOut)
2350 2350
2351 2351 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2352 2352 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2353 2353
2354 2354 for i in rango:
2355 2355 x = heiRang*math.cos(phi[i])
2356 2356 y1 = velRadial[i,:]
2357 2357 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2358 2358
2359 2359 x1 = heiRang1
2360 2360 y11 = f1(x1)
2361 2361
2362 2362 y2 = SNR[i,:]
2363 2363 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2364 2364 y21 = f2(x1)
2365 2365
2366 2366 velRadial1[i,:] = y11
2367 2367 SNR1[i,:] = y21
2368 2368
2369 2369 return heiRang1, velRadial1, SNR1
2370 2370
2371 2371 def run(self, dataOut, zenith, zenithCorrection):
2372 2372 heiRang = dataOut.heightList
2373 2373 velRadial = dataOut.data_param[:,3,:]
2374 2374 SNR = dataOut.data_snr
2375 2375
2376 2376 zenith = numpy.array(zenith)
2377 2377 zenith -= zenithCorrection
2378 2378 zenith *= numpy.pi/180
2379 2379
2380 2380 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2381 2381
2382 2382 alp = zenith[0]
2383 2383 bet = zenith[1]
2384 2384
2385 2385 w_w = velRadial1[0,:]
2386 2386 w_e = velRadial1[1,:]
2387 2387
2388 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 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 2391 winds = numpy.vstack((u,w))
2392 2392
2393 2393 dataOut.heightList = heiRang1
2394 2394 dataOut.data_output = winds
2395 2395 dataOut.data_snr = SNR1
2396 2396
2397 2397 dataOut.utctimeInit = dataOut.utctime
2398 2398 dataOut.outputInterval = dataOut.timeInterval
2399 2399 return
2400 2400
2401 2401 #--------------- Non Specular Meteor ----------------
2402 2402
2403 2403 class NonSpecularMeteorDetection(Operation):
2404 2404
2405 2405 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2406 2406 data_acf = dataOut.data_pre[0]
2407 2407 data_ccf = dataOut.data_pre[1]
2408 2408 pairsList = dataOut.groupList[1]
2409 2409
2410 2410 lamb = dataOut.C/dataOut.frequency
2411 2411 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2412 2412 paramInterval = dataOut.paramInterval
2413 2413
2414 2414 nChannels = data_acf.shape[0]
2415 2415 nLags = data_acf.shape[1]
2416 2416 nProfiles = data_acf.shape[2]
2417 2417 nHeights = dataOut.nHeights
2418 2418 nCohInt = dataOut.nCohInt
2419 2419 sec = numpy.round(nProfiles/dataOut.paramInterval)
2420 2420 heightList = dataOut.heightList
2421 2421 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2422 2422 utctime = dataOut.utctime
2423 2423
2424 2424 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2425 2425
2426 2426 #------------------------ SNR --------------------------------------
2427 2427 power = data_acf[:,0,:,:].real
2428 2428 noise = numpy.zeros(nChannels)
2429 2429 SNR = numpy.zeros(power.shape)
2430 2430 for i in range(nChannels):
2431 2431 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2432 2432 SNR[i] = (power[i]-noise[i])/noise[i]
2433 2433 SNRm = numpy.nanmean(SNR, axis = 0)
2434 2434 SNRdB = 10*numpy.log10(SNR)
2435 2435
2436 2436 if mode == 'SA':
2437 2437 dataOut.groupList = dataOut.groupList[1]
2438 2438 nPairs = data_ccf.shape[0]
2439 2439 #---------------------- Coherence and Phase --------------------------
2440 2440 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2441 2441 # phase1 = numpy.copy(phase)
2442 2442 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2443 2443
2444 2444 for p in range(nPairs):
2445 2445 ch0 = pairsList[p][0]
2446 2446 ch1 = pairsList[p][1]
2447 2447 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2448 2448 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2449 2449 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2450 2450 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2451 2451 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2452 2452 coh = numpy.nanmax(coh1, axis = 0)
2453 2453 # struc = numpy.ones((5,1))
2454 2454 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2455 2455 #---------------------- Radial Velocity ----------------------------
2456 2456 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2457 2457 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2458 2458
2459 2459 if allData:
2460 2460 boolMetFin = ~numpy.isnan(SNRm)
2461 2461 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2462 2462 else:
2463 2463 #------------------------ Meteor mask ---------------------------------
2464 2464 # #SNR mask
2465 2465 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2466 2466 #
2467 2467 # #Erase small objects
2468 2468 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2469 2469 #
2470 2470 # auxEEJ = numpy.sum(boolMet1,axis=0)
2471 2471 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2472 2472 # indEEJ = numpy.where(indOver)[0]
2473 2473 # indNEEJ = numpy.where(~indOver)[0]
2474 2474 #
2475 2475 # boolMetFin = boolMet1
2476 2476 #
2477 2477 # if indEEJ.size > 0:
2478 2478 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2479 2479 #
2480 2480 # boolMet2 = coh > cohThresh
2481 2481 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2482 2482 #
2483 2483 # #Final Meteor mask
2484 2484 # boolMetFin = boolMet1|boolMet2
2485 2485
2486 2486 #Coherence mask
2487 2487 boolMet1 = coh > 0.75
2488 2488 struc = numpy.ones((30,1))
2489 2489 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2490 2490
2491 2491 #Derivative mask
2492 2492 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2493 2493 boolMet2 = derPhase < 0.2
2494 2494 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2495 2495 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2496 2496 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2497 2497 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2498 2498 # #Final mask
2499 2499 # boolMetFin = boolMet2
2500 2500 boolMetFin = boolMet1&boolMet2
2501 2501 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2502 2502 #Creating data_param
2503 2503 coordMet = numpy.where(boolMetFin)
2504 2504
2505 2505 tmet = coordMet[0]
2506 2506 hmet = coordMet[1]
2507 2507
2508 2508 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2509 2509 data_param[:,0] = utctime
2510 2510 data_param[:,1] = tmet
2511 2511 data_param[:,2] = hmet
2512 2512 data_param[:,3] = SNRm[tmet,hmet]
2513 2513 data_param[:,4] = velRad[tmet,hmet]
2514 2514 data_param[:,5] = coh[tmet,hmet]
2515 2515 data_param[:,6:] = phase[:,tmet,hmet].T
2516 2516
2517 2517 elif mode == 'DBS':
2518 2518 dataOut.groupList = numpy.arange(nChannels)
2519 2519
2520 2520 #Radial Velocities
2521 2521 phase = numpy.angle(data_acf[:,1,:,:])
2522 2522 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2523 2523 velRad = phase*lamb/(4*numpy.pi*tSamp)
2524 2524
2525 2525 #Spectral width
2526 2526 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2527 2527 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2528 2528 acf1 = data_acf[:,1,:,:]
2529 2529 acf2 = data_acf[:,2,:,:]
2530 2530
2531 2531 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2532 2532 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2533 2533 if allData:
2534 2534 boolMetFin = ~numpy.isnan(SNRdB)
2535 2535 else:
2536 2536 #SNR
2537 2537 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2538 2538 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2539 2539
2540 2540 #Radial velocity
2541 2541 boolMet2 = numpy.abs(velRad) < 20
2542 2542 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2543 2543
2544 2544 #Spectral Width
2545 2545 boolMet3 = spcWidth < 30
2546 2546 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2547 2547 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2548 2548 boolMetFin = boolMet1&boolMet2&boolMet3
2549 2549
2550 2550 #Creating data_param
2551 2551 coordMet = numpy.where(boolMetFin)
2552 2552
2553 2553 cmet = coordMet[0]
2554 2554 tmet = coordMet[1]
2555 2555 hmet = coordMet[2]
2556 2556
2557 2557 data_param = numpy.zeros((tmet.size, 7))
2558 2558 data_param[:,0] = utctime
2559 2559 data_param[:,1] = cmet
2560 2560 data_param[:,2] = tmet
2561 2561 data_param[:,3] = hmet
2562 2562 data_param[:,4] = SNR[cmet,tmet,hmet].T
2563 2563 data_param[:,5] = velRad[cmet,tmet,hmet].T
2564 2564 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2565 2565
2566 2566 # self.dataOut.data_param = data_int
2567 2567 if len(data_param) == 0:
2568 2568 dataOut.flagNoData = True
2569 2569 else:
2570 2570 dataOut.data_param = data_param
2571 2571
2572 2572 def __erase_small(self, binArray, threshX, threshY):
2573 2573 labarray, numfeat = ndimage.measurements.label(binArray)
2574 2574 binArray1 = numpy.copy(binArray)
2575 2575
2576 2576 for i in range(1,numfeat + 1):
2577 2577 auxBin = (labarray==i)
2578 2578 auxSize = auxBin.sum()
2579 2579
2580 2580 x,y = numpy.where(auxBin)
2581 2581 widthX = x.max() - x.min()
2582 2582 widthY = y.max() - y.min()
2583 2583
2584 2584 #width X: 3 seg -> 12.5*3
2585 2585 #width Y:
2586 2586
2587 2587 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2588 2588 binArray1[auxBin] = False
2589 2589
2590 2590 return binArray1
2591 2591
2592 2592 #--------------- Specular Meteor ----------------
2593 2593
2594 2594 class SMDetection(Operation):
2595 2595 '''
2596 2596 Function DetectMeteors()
2597 2597 Project developed with paper:
2598 2598 HOLDSWORTH ET AL. 2004
2599 2599
2600 2600 Input:
2601 2601 self.dataOut.data_pre
2602 2602
2603 2603 centerReceiverIndex: From the channels, which is the center receiver
2604 2604
2605 2605 hei_ref: Height reference for the Beacon signal extraction
2606 2606 tauindex:
2607 2607 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2608 2608
2609 2609 cohDetection: Whether to user Coherent detection or not
2610 2610 cohDet_timeStep: Coherent Detection calculation time step
2611 2611 cohDet_thresh: Coherent Detection phase threshold to correct phases
2612 2612
2613 2613 noise_timeStep: Noise calculation time step
2614 2614 noise_multiple: Noise multiple to define signal threshold
2615 2615
2616 2616 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2617 2617 multDet_rangeLimit: Multiple Detection Removal range limit in km
2618 2618
2619 2619 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2620 2620 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2621 2621
2622 2622 hmin: Minimum Height of the meteor to use it in the further wind estimations
2623 2623 hmax: Maximum Height of the meteor to use it in the further wind estimations
2624 2624 azimuth: Azimuth angle correction
2625 2625
2626 2626 Affected:
2627 2627 self.dataOut.data_param
2628 2628
2629 2629 Rejection Criteria (Errors):
2630 2630 0: No error; analysis OK
2631 2631 1: SNR < SNR threshold
2632 2632 2: angle of arrival (AOA) ambiguously determined
2633 2633 3: AOA estimate not feasible
2634 2634 4: Large difference in AOAs obtained from different antenna baselines
2635 2635 5: echo at start or end of time series
2636 2636 6: echo less than 5 examples long; too short for analysis
2637 2637 7: echo rise exceeds 0.3s
2638 2638 8: echo decay time less than twice rise time
2639 2639 9: large power level before echo
2640 2640 10: large power level after echo
2641 2641 11: poor fit to amplitude for estimation of decay time
2642 2642 12: poor fit to CCF phase variation for estimation of radial drift velocity
2643 2643 13: height unresolvable echo: not valid height within 70 to 110 km
2644 2644 14: height ambiguous echo: more then one possible height within 70 to 110 km
2645 2645 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2646 2646 16: oscilatory echo, indicating event most likely not an underdense echo
2647 2647
2648 2648 17: phase difference in meteor Reestimation
2649 2649
2650 2650 Data Storage:
2651 2651 Meteors for Wind Estimation (8):
2652 2652 Utc Time | Range Height
2653 2653 Azimuth Zenith errorCosDir
2654 2654 VelRad errorVelRad
2655 2655 Phase0 Phase1 Phase2 Phase3
2656 2656 TypeError
2657 2657
2658 2658 '''
2659 2659
2660 2660 def run(self, dataOut, hei_ref = None, tauindex = 0,
2661 2661 phaseOffsets = None,
2662 2662 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2663 2663 noise_timeStep = 4, noise_multiple = 4,
2664 2664 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2665 2665 phaseThresh = 20, SNRThresh = 5,
2666 2666 hmin = 50, hmax=150, azimuth = 0,
2667 2667 channelPositions = None) :
2668 2668
2669 2669
2670 2670 #Getting Pairslist
2671 2671 if channelPositions is None:
2672 2672 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2673 2673 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2674 2674 meteorOps = SMOperations()
2675 2675 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2676 2676 heiRang = dataOut.heightList
2677 2677 #Get Beacon signal - No Beacon signal anymore
2678 2678 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2679 2679 #
2680 2680 # if hei_ref != None:
2681 2681 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2682 2682 #
2683 2683
2684 2684
2685 2685 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2686 2686 # see if the user put in pre defined phase shifts
2687 2687 voltsPShift = dataOut.data_pre.copy()
2688 2688
2689 2689 # if predefinedPhaseShifts != None:
2690 2690 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2691 2691 #
2692 2692 # # elif beaconPhaseShifts:
2693 2693 # # #get hardware phase shifts using beacon signal
2694 2694 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2695 2695 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2696 2696 #
2697 2697 # else:
2698 2698 # hardwarePhaseShifts = numpy.zeros(5)
2699 2699 #
2700 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 2701 # for i in range(self.dataOut.data_pre.shape[0]):
2702 2702 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2703 2703
2704 2704 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2705 2705
2706 2706 #Remove DC
2707 2707 voltsDC = numpy.mean(voltsPShift,1)
2708 2708 voltsDC = numpy.mean(voltsDC,1)
2709 2709 for i in range(voltsDC.shape[0]):
2710 2710 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2711 2711
2712 2712 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2713 2713 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2714 2714
2715 2715 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2716 2716 #Coherent Detection
2717 2717 if cohDetection:
2718 2718 #use coherent detection to get the net power
2719 2719 cohDet_thresh = cohDet_thresh*numpy.pi/180
2720 2720 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2721 2721
2722 2722 #Non-coherent detection!
2723 2723 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2724 2724 #********** END OF COH/NON-COH POWER CALCULATION**********************
2725 2725
2726 2726 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2727 2727 #Get noise
2728 2728 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2729 2729 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2730 2730 #Get signal threshold
2731 2731 signalThresh = noise_multiple*noise
2732 2732 #Meteor echoes detection
2733 2733 listMeteors = self.__findMeteors(powerNet, signalThresh)
2734 2734 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2735 2735
2736 2736 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2737 2737 #Parameters
2738 2738 heiRange = dataOut.heightList
2739 2739 rangeInterval = heiRange[1] - heiRange[0]
2740 2740 rangeLimit = multDet_rangeLimit/rangeInterval
2741 2741 timeLimit = multDet_timeLimit/dataOut.timeInterval
2742 2742 #Multiple detection removals
2743 2743 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2744 2744 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2745 2745
2746 2746 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2747 2747 #Parameters
2748 2748 phaseThresh = phaseThresh*numpy.pi/180
2749 2749 thresh = [phaseThresh, noise_multiple, SNRThresh]
2750 2750 #Meteor reestimation (Errors N 1, 6, 12, 17)
2751 2751 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2752 2752 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2753 2753 #Estimation of decay times (Errors N 7, 8, 11)
2754 2754 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2755 2755 #******************* END OF METEOR REESTIMATION *******************
2756 2756
2757 2757 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2758 2758 #Calculating Radial Velocity (Error N 15)
2759 2759 radialStdThresh = 10
2760 2760 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2761 2761
2762 2762 if len(listMeteors4) > 0:
2763 2763 #Setting New Array
2764 2764 date = dataOut.utctime
2765 2765 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2766 2766
2767 2767 #Correcting phase offset
2768 2768 if phaseOffsets != None:
2769 2769 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2770 2770 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2771 2771
2772 2772 #Second Pairslist
2773 2773 pairsList = []
2774 2774 pairx = (0,1)
2775 2775 pairy = (2,3)
2776 2776 pairsList.append(pairx)
2777 2777 pairsList.append(pairy)
2778 2778
2779 2779 jph = numpy.array([0,0,0,0])
2780 2780 h = (hmin,hmax)
2781 2781 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2782 2782
2783 2783 # #Calculate AOA (Error N 3, 4)
2784 2784 # #JONES ET AL. 1998
2785 2785 # error = arrayParameters[:,-1]
2786 2786 # AOAthresh = numpy.pi/8
2787 2787 # phases = -arrayParameters[:,9:13]
2788 2788 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2789 2789 #
2790 2790 # #Calculate Heights (Error N 13 and 14)
2791 2791 # error = arrayParameters[:,-1]
2792 2792 # Ranges = arrayParameters[:,2]
2793 2793 # zenith = arrayParameters[:,5]
2794 2794 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2795 2795 # error = arrayParameters[:,-1]
2796 2796 #********************* END OF PARAMETERS CALCULATION **************************
2797 2797
2798 2798 #***************************+ PASS DATA TO NEXT STEP **********************
2799 2799 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2800 2800 dataOut.data_param = arrayParameters
2801 2801
2802 2802 if arrayParameters is None:
2803 2803 dataOut.flagNoData = True
2804 2804 else:
2805 2805 dataOut.flagNoData = True
2806 2806
2807 2807 return
2808 2808
2809 2809 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2810 2810
2811 2811 minIndex = min(newheis[0])
2812 2812 maxIndex = max(newheis[0])
2813 2813
2814 2814 voltage = voltage0[:,:,minIndex:maxIndex+1]
2815 2815 nLength = voltage.shape[1]/n
2816 2816 nMin = 0
2817 2817 nMax = 0
2818 2818 phaseOffset = numpy.zeros((len(pairslist),n))
2819 2819
2820 2820 for i in range(n):
2821 2821 nMax += nLength
2822 2822 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2823 2823 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2824 2824 phaseOffset[:,i] = phaseCCF.transpose()
2825 2825 nMin = nMax
2826 2826 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2827 2827
2828 2828 #Remove Outliers
2829 2829 factor = 2
2830 2830 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2831 2831 dw = numpy.std(wt,axis = 1)
2832 2832 dw = dw.reshape((dw.size,1))
2833 2833 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2834 2834 phaseOffset[ind] = numpy.nan
2835 2835 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2836 2836
2837 2837 return phaseOffset
2838 2838
2839 2839 def __shiftPhase(self, data, phaseShift):
2840 2840 #this will shift the phase of a complex number
2841 2841 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2842 2842 return dataShifted
2843 2843
2844 2844 def __estimatePhaseDifference(self, array, pairslist):
2845 2845 nChannel = array.shape[0]
2846 2846 nHeights = array.shape[2]
2847 2847 numPairs = len(pairslist)
2848 2848 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2849 2849 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2850 2850
2851 2851 #Correct phases
2852 2852 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2853 2853 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2854 2854
2855 2855 if indDer[0].shape[0] > 0:
2856 2856 for i in range(indDer[0].shape[0]):
2857 2857 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2858 2858 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2859 2859
2860 2860 # for j in range(numSides):
2861 2861 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2862 2862 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2863 2863 #
2864 2864 #Linear
2865 2865 phaseInt = numpy.zeros((numPairs,1))
2866 2866 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2867 2867 for j in range(numPairs):
2868 2868 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2869 2869 phaseInt[j] = fit[1]
2870 2870 #Phase Differences
2871 2871 phaseDiff = phaseInt - phaseCCF[:,2,:]
2872 2872 phaseArrival = phaseInt.reshape(phaseInt.size)
2873 2873
2874 2874 #Dealias
2875 2875 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2876 2876 # indAlias = numpy.where(phaseArrival > numpy.pi)
2877 2877 # phaseArrival[indAlias] -= 2*numpy.pi
2878 2878 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2879 2879 # phaseArrival[indAlias] += 2*numpy.pi
2880 2880
2881 2881 return phaseDiff, phaseArrival
2882 2882
2883 2883 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2884 2884 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2885 2885 #find the phase shifts of each channel over 1 second intervals
2886 2886 #only look at ranges below the beacon signal
2887 2887 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2888 2888 numBlocks = int(volts.shape[1]/numProfPerBlock)
2889 2889 numHeights = volts.shape[2]
2890 2890 nChannel = volts.shape[0]
2891 2891 voltsCohDet = volts.copy()
2892 2892
2893 2893 pairsarray = numpy.array(pairslist)
2894 2894 indSides = pairsarray[:,1]
2895 2895 # indSides = numpy.array(range(nChannel))
2896 2896 # indSides = numpy.delete(indSides, indCenter)
2897 2897 #
2898 2898 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2899 2899 listBlocks = numpy.array_split(volts, numBlocks, 1)
2900 2900
2901 2901 startInd = 0
2902 2902 endInd = 0
2903 2903
2904 2904 for i in range(numBlocks):
2905 2905 startInd = endInd
2906 2906 endInd = endInd + listBlocks[i].shape[1]
2907 2907
2908 2908 arrayBlock = listBlocks[i]
2909 2909 # arrayBlockCenter = listCenter[i]
2910 2910
2911 2911 #Estimate the Phase Difference
2912 2912 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2913 2913 #Phase Difference RMS
2914 2914 arrayPhaseRMS = numpy.abs(phaseDiff)
2915 2915 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2916 2916 indPhase = numpy.where(phaseRMSaux==4)
2917 2917 #Shifting
2918 2918 if indPhase[0].shape[0] > 0:
2919 2919 for j in range(indSides.size):
2920 2920 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2921 2921 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2922 2922
2923 2923 return voltsCohDet
2924 2924
2925 2925 def __calculateCCF(self, volts, pairslist ,laglist):
2926 2926
2927 2927 nHeights = volts.shape[2]
2928 2928 nPoints = volts.shape[1]
2929 2929 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2930 2930
2931 2931 for i in range(len(pairslist)):
2932 2932 volts1 = volts[pairslist[i][0]]
2933 2933 volts2 = volts[pairslist[i][1]]
2934 2934
2935 2935 for t in range(len(laglist)):
2936 2936 idxT = laglist[t]
2937 2937 if idxT >= 0:
2938 2938 vStacked = numpy.vstack((volts2[idxT:,:],
2939 2939 numpy.zeros((idxT, nHeights),dtype='complex')))
2940 2940 else:
2941 2941 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2942 2942 volts2[:(nPoints + idxT),:]))
2943 2943 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2944 2944
2945 2945 vStacked = None
2946 2946 return voltsCCF
2947 2947
2948 2948 def __getNoise(self, power, timeSegment, timeInterval):
2949 2949 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2950 2950 numBlocks = int(power.shape[0]/numProfPerBlock)
2951 2951 numHeights = power.shape[1]
2952 2952
2953 2953 listPower = numpy.array_split(power, numBlocks, 0)
2954 2954 noise = numpy.zeros((power.shape[0], power.shape[1]))
2955 2955 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2956 2956
2957 2957 startInd = 0
2958 2958 endInd = 0
2959 2959
2960 2960 for i in range(numBlocks): #split por canal
2961 2961 startInd = endInd
2962 2962 endInd = endInd + listPower[i].shape[0]
2963 2963
2964 2964 arrayBlock = listPower[i]
2965 2965 noiseAux = numpy.mean(arrayBlock, 0)
2966 2966 # noiseAux = numpy.median(noiseAux)
2967 2967 # noiseAux = numpy.mean(arrayBlock)
2968 2968 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2969 2969
2970 2970 noiseAux1 = numpy.mean(arrayBlock)
2971 2971 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2972 2972
2973 2973 return noise, noise1
2974 2974
2975 2975 def __findMeteors(self, power, thresh):
2976 2976 nProf = power.shape[0]
2977 2977 nHeights = power.shape[1]
2978 2978 listMeteors = []
2979 2979
2980 2980 for i in range(nHeights):
2981 2981 powerAux = power[:,i]
2982 2982 threshAux = thresh[:,i]
2983 2983
2984 2984 indUPthresh = numpy.where(powerAux > threshAux)[0]
2985 2985 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2986 2986
2987 2987 j = 0
2988 2988
2989 2989 while (j < indUPthresh.size - 2):
2990 2990 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2991 2991 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2992 2992 indDNthresh = indDNthresh[indDNAux]
2993 2993
2994 2994 if (indDNthresh.size > 0):
2995 2995 indEnd = indDNthresh[0] - 1
2996 2996 indInit = indUPthresh[j]
2997 2997
2998 2998 meteor = powerAux[indInit:indEnd + 1]
2999 2999 indPeak = meteor.argmax() + indInit
3000 3000 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3001 3001
3002 3002 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3003 3003 j = numpy.where(indUPthresh == indEnd)[0] + 1
3004 3004 else: j+=1
3005 3005 else: j+=1
3006 3006
3007 3007 return listMeteors
3008 3008
3009 3009 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3010 3010
3011 3011 arrayMeteors = numpy.asarray(listMeteors)
3012 3012 listMeteors1 = []
3013 3013
3014 3014 while arrayMeteors.shape[0] > 0:
3015 3015 FLAs = arrayMeteors[:,4]
3016 3016 maxFLA = FLAs.argmax()
3017 3017 listMeteors1.append(arrayMeteors[maxFLA,:])
3018 3018
3019 3019 MeteorInitTime = arrayMeteors[maxFLA,1]
3020 3020 MeteorEndTime = arrayMeteors[maxFLA,3]
3021 3021 MeteorHeight = arrayMeteors[maxFLA,0]
3022 3022
3023 3023 #Check neighborhood
3024 3024 maxHeightIndex = MeteorHeight + rangeLimit
3025 3025 minHeightIndex = MeteorHeight - rangeLimit
3026 3026 minTimeIndex = MeteorInitTime - timeLimit
3027 3027 maxTimeIndex = MeteorEndTime + timeLimit
3028 3028
3029 3029 #Check Heights
3030 3030 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3031 3031 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3032 3032 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3033 3033
3034 3034 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3035 3035
3036 3036 return listMeteors1
3037 3037
3038 3038 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3039 3039 numHeights = volts.shape[2]
3040 3040 nChannel = volts.shape[0]
3041 3041
3042 3042 thresholdPhase = thresh[0]
3043 3043 thresholdNoise = thresh[1]
3044 3044 thresholdDB = float(thresh[2])
3045 3045
3046 3046 thresholdDB1 = 10**(thresholdDB/10)
3047 3047 pairsarray = numpy.array(pairslist)
3048 3048 indSides = pairsarray[:,1]
3049 3049
3050 3050 pairslist1 = list(pairslist)
3051 3051 pairslist1.append((0,1))
3052 3052 pairslist1.append((3,4))
3053 3053
3054 3054 listMeteors1 = []
3055 3055 listPowerSeries = []
3056 3056 listVoltageSeries = []
3057 3057 #volts has the war data
3058 3058
3059 3059 if frequency == 30e6:
3060 3060 timeLag = 45*10**-3
3061 3061 else:
3062 3062 timeLag = 15*10**-3
3063 3063 lag = numpy.ceil(timeLag/timeInterval)
3064 3064
3065 3065 for i in range(len(listMeteors)):
3066 3066
3067 3067 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3068 3068 meteorAux = numpy.zeros(16)
3069 3069
3070 3070 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3071 3071 mHeight = listMeteors[i][0]
3072 3072 mStart = listMeteors[i][1]
3073 3073 mPeak = listMeteors[i][2]
3074 3074 mEnd = listMeteors[i][3]
3075 3075
3076 3076 #get the volt data between the start and end times of the meteor
3077 3077 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3078 3078 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3079 3079
3080 3080 #3.6. Phase Difference estimation
3081 3081 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3082 3082
3083 3083 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3084 3084 #meteorVolts0.- all Channels, all Profiles
3085 3085 meteorVolts0 = volts[:,:,mHeight]
3086 3086 meteorThresh = noise[:,mHeight]*thresholdNoise
3087 3087 meteorNoise = noise[:,mHeight]
3088 3088 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3089 3089 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3090 3090
3091 3091 #Times reestimation
3092 3092 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3093 3093 if mStart1.size > 0:
3094 3094 mStart1 = mStart1[-1] + 1
3095 3095
3096 3096 else:
3097 3097 mStart1 = mPeak
3098 3098
3099 3099 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3100 3100 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3101 3101 if mEndDecayTime1.size == 0:
3102 3102 mEndDecayTime1 = powerNet0.size
3103 3103 else:
3104 3104 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3105 3105 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3106 3106
3107 3107 #meteorVolts1.- all Channels, from start to end
3108 3108 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3109 3109 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3110 3110 if meteorVolts2.shape[1] == 0:
3111 3111 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3112 3112 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3113 3113 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3114 3114 ##################### END PARAMETERS REESTIMATION #########################
3115 3115
3116 3116 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3117 3117 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3118 3118 if meteorVolts2.shape[1] > 0:
3119 3119 #Phase Difference re-estimation
3120 3120 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3121 3121 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3122 3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3123 3123 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3124 3124 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3125 3125
3126 3126 #Phase Difference RMS
3127 3127 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3128 3128 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3129 3129 #Data from Meteor
3130 3130 mPeak1 = powerNet1.argmax() + mStart1
3131 3131 mPeakPower1 = powerNet1.max()
3132 3132 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3133 3133 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3134 3134 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3135 3135 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3136 3136 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3137 3137 #Vectorize
3138 3138 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3139 3139 meteorAux[7:11] = phaseDiffint[0:4]
3140 3140
3141 3141 #Rejection Criterions
3142 3142 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3143 3143 meteorAux[-1] = 17
3144 3144 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3145 3145 meteorAux[-1] = 1
3146 3146
3147 3147
3148 3148 else:
3149 3149 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3150 3150 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3151 3151 PowerSeries = 0
3152 3152
3153 3153 listMeteors1.append(meteorAux)
3154 3154 listPowerSeries.append(PowerSeries)
3155 3155 listVoltageSeries.append(meteorVolts1)
3156 3156
3157 3157 return listMeteors1, listPowerSeries, listVoltageSeries
3158 3158
3159 3159 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3160 3160
3161 3161 threshError = 10
3162 3162 #Depending if it is 30 or 50 MHz
3163 3163 if frequency == 30e6:
3164 3164 timeLag = 45*10**-3
3165 3165 else:
3166 3166 timeLag = 15*10**-3
3167 3167 lag = numpy.ceil(timeLag/timeInterval)
3168 3168
3169 3169 listMeteors1 = []
3170 3170
3171 3171 for i in range(len(listMeteors)):
3172 3172 meteorPower = listPower[i]
3173 3173 meteorAux = listMeteors[i]
3174 3174
3175 3175 if meteorAux[-1] == 0:
3176 3176
3177 3177 try:
3178 3178 indmax = meteorPower.argmax()
3179 3179 indlag = indmax + lag
3180 3180
3181 3181 y = meteorPower[indlag:]
3182 3182 x = numpy.arange(0, y.size)*timeLag
3183 3183
3184 3184 #first guess
3185 3185 a = y[0]
3186 3186 tau = timeLag
3187 3187 #exponential fit
3188 3188 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3189 3189 y1 = self.__exponential_function(x, *popt)
3190 3190 #error estimation
3191 3191 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3192 3192
3193 3193 decayTime = popt[1]
3194 3194 riseTime = indmax*timeInterval
3195 3195 meteorAux[11:13] = [decayTime, error]
3196 3196
3197 3197 #Table items 7, 8 and 11
3198 3198 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3199 3199 meteorAux[-1] = 7
3200 3200 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3201 3201 meteorAux[-1] = 8
3202 3202 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3203 3203 meteorAux[-1] = 11
3204 3204
3205 3205
3206 3206 except:
3207 3207 meteorAux[-1] = 11
3208 3208
3209 3209
3210 3210 listMeteors1.append(meteorAux)
3211 3211
3212 3212 return listMeteors1
3213 3213
3214 3214 #Exponential Function
3215 3215
3216 3216 def __exponential_function(self, x, a, tau):
3217 3217 y = a*numpy.exp(-x/tau)
3218 3218 return y
3219 3219
3220 3220 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3221 3221
3222 3222 pairslist1 = list(pairslist)
3223 3223 pairslist1.append((0,1))
3224 3224 pairslist1.append((3,4))
3225 3225 numPairs = len(pairslist1)
3226 3226 #Time Lag
3227 3227 timeLag = 45*10**-3
3228 3228 c = 3e8
3229 3229 lag = numpy.ceil(timeLag/timeInterval)
3230 3230 freq = 30e6
3231 3231
3232 3232 listMeteors1 = []
3233 3233
3234 3234 for i in range(len(listMeteors)):
3235 3235 meteorAux = listMeteors[i]
3236 3236 if meteorAux[-1] == 0:
3237 3237 mStart = listMeteors[i][1]
3238 3238 mPeak = listMeteors[i][2]
3239 3239 mLag = mPeak - mStart + lag
3240 3240
3241 3241 #get the volt data between the start and end times of the meteor
3242 3242 meteorVolts = listVolts[i]
3243 3243 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3244 3244
3245 3245 #Get CCF
3246 3246 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3247 3247
3248 3248 #Method 2
3249 3249 slopes = numpy.zeros(numPairs)
3250 3250 time = numpy.array([-2,-1,1,2])*timeInterval
3251 3251 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3252 3252
3253 3253 #Correct phases
3254 3254 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3255 3255 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3256 3256
3257 3257 if indDer[0].shape[0] > 0:
3258 3258 for i in range(indDer[0].shape[0]):
3259 3259 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3260 3260 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3261 3261
3262 3262 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3263 3263 for j in range(numPairs):
3264 3264 fit = stats.linregress(time, angAllCCF[j,:])
3265 3265 slopes[j] = fit[0]
3266 3266
3267 3267 #Remove Outlier
3268 3268 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3269 3269 # slopes = numpy.delete(slopes,indOut)
3270 3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3271 3271 # slopes = numpy.delete(slopes,indOut)
3272 3272
3273 3273 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3274 3274 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3275 3275 meteorAux[-2] = radialError
3276 3276 meteorAux[-3] = radialVelocity
3277 3277
3278 3278 #Setting Error
3279 3279 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3280 3280 if numpy.abs(radialVelocity) > 200:
3281 3281 meteorAux[-1] = 15
3282 3282 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3283 3283 elif radialError > radialStdThresh:
3284 3284 meteorAux[-1] = 12
3285 3285
3286 3286 listMeteors1.append(meteorAux)
3287 3287 return listMeteors1
3288 3288
3289 3289 def __setNewArrays(self, listMeteors, date, heiRang):
3290 3290
3291 3291 #New arrays
3292 3292 arrayMeteors = numpy.array(listMeteors)
3293 3293 arrayParameters = numpy.zeros((len(listMeteors), 13))
3294 3294
3295 3295 #Date inclusion
3296 3296 # date = re.findall(r'\((.*?)\)', date)
3297 3297 # date = date[0].split(',')
3298 3298 # date = map(int, date)
3299 3299 #
3300 3300 # if len(date)<6:
3301 3301 # date.append(0)
3302 3302 #
3303 3303 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3304 3304 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3305 3305 arrayDate = numpy.tile(date, (len(listMeteors)))
3306 3306
3307 3307 #Meteor array
3308 3308 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3309 3309 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3310 3310
3311 3311 #Parameters Array
3312 3312 arrayParameters[:,0] = arrayDate #Date
3313 3313 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3314 3314 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3315 3315 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3316 3316 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3317 3317
3318 3318
3319 3319 return arrayParameters
3320 3320
3321 3321 class CorrectSMPhases(Operation):
3322 3322
3323 3323 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3324 3324
3325 3325 arrayParameters = dataOut.data_param
3326 3326 pairsList = []
3327 3327 pairx = (0,1)
3328 3328 pairy = (2,3)
3329 3329 pairsList.append(pairx)
3330 3330 pairsList.append(pairy)
3331 3331 jph = numpy.zeros(4)
3332 3332
3333 3333 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3334 3334 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3335 3335 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3336 3336
3337 3337 meteorOps = SMOperations()
3338 3338 if channelPositions is None:
3339 3339 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3340 3340 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3341 3341
3342 3342 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3343 3343 h = (hmin,hmax)
3344 3344
3345 3345 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3346 3346
3347 3347 dataOut.data_param = arrayParameters
3348 3348 return
3349 3349
3350 3350 class SMPhaseCalibration(Operation):
3351 3351
3352 3352 __buffer = None
3353 3353
3354 3354 __initime = None
3355 3355
3356 3356 __dataReady = False
3357 3357
3358 3358 __isConfig = False
3359 3359
3360 3360 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3361 3361
3362 3362 dataTime = currentTime + paramInterval
3363 3363 deltaTime = dataTime - initTime
3364 3364
3365 3365 if deltaTime >= outputInterval or deltaTime < 0:
3366 3366 return True
3367 3367
3368 3368 return False
3369 3369
3370 3370 def __getGammas(self, pairs, d, phases):
3371 3371 gammas = numpy.zeros(2)
3372 3372
3373 3373 for i in range(len(pairs)):
3374 3374
3375 3375 pairi = pairs[i]
3376 3376
3377 3377 phip3 = phases[:,pairi[0]]
3378 3378 d3 = d[pairi[0]]
3379 3379 phip2 = phases[:,pairi[1]]
3380 3380 d2 = d[pairi[1]]
3381 3381 #Calculating gamma
3382 3382 # jdcos = alp1/(k*d1)
3383 3383 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3384 3384 jgamma = -phip2*d3/d2 - phip3
3385 3385 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3386 3386 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3387 3387 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3388 3388
3389 3389 #Revised distribution
3390 3390 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3391 3391
3392 3392 #Histogram
3393 3393 nBins = 64
3394 3394 rmin = -0.5*numpy.pi
3395 3395 rmax = 0.5*numpy.pi
3396 3396 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3397 3397
3398 3398 meteorsY = phaseHisto[0]
3399 3399 phasesX = phaseHisto[1][:-1]
3400 3400 width = phasesX[1] - phasesX[0]
3401 3401 phasesX += width/2
3402 3402
3403 3403 #Gaussian aproximation
3404 3404 bpeak = meteorsY.argmax()
3405 3405 peak = meteorsY.max()
3406 3406 jmin = bpeak - 5
3407 3407 jmax = bpeak + 5 + 1
3408 3408
3409 3409 if jmin<0:
3410 3410 jmin = 0
3411 3411 jmax = 6
3412 3412 elif jmax > meteorsY.size:
3413 3413 jmin = meteorsY.size - 6
3414 3414 jmax = meteorsY.size
3415 3415
3416 3416 x0 = numpy.array([peak,bpeak,50])
3417 3417 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3418 3418
3419 3419 #Gammas
3420 3420 gammas[i] = coeff[0][1]
3421 3421
3422 3422 return gammas
3423 3423
3424 3424 def __residualFunction(self, coeffs, y, t):
3425 3425
3426 3426 return y - self.__gauss_function(t, coeffs)
3427 3427
3428 3428 def __gauss_function(self, t, coeffs):
3429 3429
3430 3430 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3431 3431
3432 3432 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3433 3433 meteorOps = SMOperations()
3434 3434 nchan = 4
3435 3435 pairx = pairsList[0] #x es 0
3436 3436 pairy = pairsList[1] #y es 1
3437 3437 center_xangle = 0
3438 3438 center_yangle = 0
3439 3439 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3440 3440 ntimes = len(range_angle)
3441 3441
3442 3442 nstepsx = 20
3443 3443 nstepsy = 20
3444 3444
3445 3445 for iz in range(ntimes):
3446 3446 min_xangle = -range_angle[iz]/2 + center_xangle
3447 3447 max_xangle = range_angle[iz]/2 + center_xangle
3448 3448 min_yangle = -range_angle[iz]/2 + center_yangle
3449 3449 max_yangle = range_angle[iz]/2 + center_yangle
3450 3450
3451 3451 inc_x = (max_xangle-min_xangle)/nstepsx
3452 3452 inc_y = (max_yangle-min_yangle)/nstepsy
3453 3453
3454 3454 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3455 3455 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3456 3456 penalty = numpy.zeros((nstepsx,nstepsy))
3457 3457 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3458 3458 jph = numpy.zeros(nchan)
3459 3459
3460 3460 # Iterations looking for the offset
3461 3461 for iy in range(int(nstepsy)):
3462 3462 for ix in range(int(nstepsx)):
3463 3463 d3 = d[pairsList[1][0]]
3464 3464 d2 = d[pairsList[1][1]]
3465 3465 d5 = d[pairsList[0][0]]
3466 3466 d4 = d[pairsList[0][1]]
3467 3467
3468 3468 alp2 = alpha_y[iy] #gamma 1
3469 3469 alp4 = alpha_x[ix] #gamma 0
3470 3470
3471 3471 alp3 = -alp2*d3/d2 - gammas[1]
3472 3472 alp5 = -alp4*d5/d4 - gammas[0]
3473 3473 # jph[pairy[1]] = alpha_y[iy]
3474 3474 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3475 3475
3476 3476 # jph[pairx[1]] = alpha_x[ix]
3477 3477 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3478 3478 jph[pairsList[0][1]] = alp4
3479 3479 jph[pairsList[0][0]] = alp5
3480 3480 jph[pairsList[1][0]] = alp3
3481 3481 jph[pairsList[1][1]] = alp2
3482 3482 jph_array[:,ix,iy] = jph
3483 3483 # d = [2.0,2.5,2.5,2.0]
3484 3484 #falta chequear si va a leer bien los meteoros
3485 3485 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3486 3486 error = meteorsArray1[:,-1]
3487 3487 ind1 = numpy.where(error==0)[0]
3488 3488 penalty[ix,iy] = ind1.size
3489 3489
3490 3490 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3491 3491 phOffset = jph_array[:,i,j]
3492 3492
3493 3493 center_xangle = phOffset[pairx[1]]
3494 3494 center_yangle = phOffset[pairy[1]]
3495 3495
3496 3496 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3497 3497 phOffset = phOffset*180/numpy.pi
3498 3498 return phOffset
3499 3499
3500 3500
3501 3501 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3502 3502
3503 3503 dataOut.flagNoData = True
3504 3504 self.__dataReady = False
3505 3505 dataOut.outputInterval = nHours*3600
3506 3506
3507 3507 if self.__isConfig == False:
3508 3508 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3509 3509 #Get Initial LTC time
3510 3510 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3511 3511 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3512 3512
3513 3513 self.__isConfig = True
3514 3514
3515 3515 if self.__buffer is None:
3516 3516 self.__buffer = dataOut.data_param.copy()
3517 3517
3518 3518 else:
3519 3519 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3520 3520
3521 3521 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3522 3522
3523 3523 if self.__dataReady:
3524 3524 dataOut.utctimeInit = self.__initime
3525 3525 self.__initime += dataOut.outputInterval #to erase time offset
3526 3526
3527 3527 freq = dataOut.frequency
3528 3528 c = dataOut.C #m/s
3529 3529 lamb = c/freq
3530 3530 k = 2*numpy.pi/lamb
3531 3531 azimuth = 0
3532 3532 h = (hmin, hmax)
3533 3533 # pairs = ((0,1),(2,3)) #Estrella
3534 3534 # pairs = ((1,0),(2,3)) #T
3535 3535
3536 3536 if channelPositions is None:
3537 3537 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3538 3538 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3539 3539 meteorOps = SMOperations()
3540 3540 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3541 3541
3542 3542 #Checking correct order of pairs
3543 3543 pairs = []
3544 3544 if distances[1] > distances[0]:
3545 3545 pairs.append((1,0))
3546 3546 else:
3547 3547 pairs.append((0,1))
3548 3548
3549 3549 if distances[3] > distances[2]:
3550 3550 pairs.append((3,2))
3551 3551 else:
3552 3552 pairs.append((2,3))
3553 3553 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3554 3554
3555 3555 meteorsArray = self.__buffer
3556 3556 error = meteorsArray[:,-1]
3557 3557 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3558 3558 ind1 = numpy.where(boolError)[0]
3559 3559 meteorsArray = meteorsArray[ind1,:]
3560 3560 meteorsArray[:,-1] = 0
3561 3561 phases = meteorsArray[:,8:12]
3562 3562
3563 3563 #Calculate Gammas
3564 3564 gammas = self.__getGammas(pairs, distances, phases)
3565 3565 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3566 3566 #Calculate Phases
3567 3567 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3568 3568 phasesOff = phasesOff.reshape((1,phasesOff.size))
3569 3569 dataOut.data_output = -phasesOff
3570 3570 dataOut.flagNoData = False
3571 3571 self.__buffer = None
3572 3572
3573 3573
3574 3574 return
3575 3575
3576 3576 class SMOperations():
3577 3577
3578 3578 def __init__(self):
3579 3579
3580 3580 return
3581 3581
3582 3582 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3583 3583
3584 3584 arrayParameters = arrayParameters0.copy()
3585 3585 hmin = h[0]
3586 3586 hmax = h[1]
3587 3587
3588 3588 #Calculate AOA (Error N 3, 4)
3589 3589 #JONES ET AL. 1998
3590 3590 AOAthresh = numpy.pi/8
3591 3591 error = arrayParameters[:,-1]
3592 3592 phases = -arrayParameters[:,8:12] + jph
3593 3593 # phases = numpy.unwrap(phases)
3594 3594 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3595 3595
3596 3596 #Calculate Heights (Error N 13 and 14)
3597 3597 error = arrayParameters[:,-1]
3598 3598 Ranges = arrayParameters[:,1]
3599 3599 zenith = arrayParameters[:,4]
3600 3600 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3601 3601
3602 3602 #----------------------- Get Final data ------------------------------------
3603 3603 # error = arrayParameters[:,-1]
3604 3604 # ind1 = numpy.where(error==0)[0]
3605 3605 # arrayParameters = arrayParameters[ind1,:]
3606 3606
3607 3607 return arrayParameters
3608 3608
3609 3609 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3610 3610
3611 3611 arrayAOA = numpy.zeros((phases.shape[0],3))
3612 3612 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3613 3613
3614 3614 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3615 3615 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3616 3616 arrayAOA[:,2] = cosDirError
3617 3617
3618 3618 azimuthAngle = arrayAOA[:,0]
3619 3619 zenithAngle = arrayAOA[:,1]
3620 3620
3621 3621 #Setting Error
3622 3622 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3623 3623 error[indError] = 0
3624 3624 #Number 3: AOA not fesible
3625 3625 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3626 3626 error[indInvalid] = 3
3627 3627 #Number 4: Large difference in AOAs obtained from different antenna baselines
3628 3628 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3629 3629 error[indInvalid] = 4
3630 3630 return arrayAOA, error
3631 3631
3632 3632 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3633 3633
3634 3634 #Initializing some variables
3635 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 3636 ang_aux = ang_aux.reshape(1,ang_aux.size)
3637 3637
3638 3638 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3639 3639 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3640 3640
3641 3641
3642 3642 for i in range(2):
3643 3643 ph0 = arrayPhase[:,pairsList[i][0]]
3644 3644 ph1 = arrayPhase[:,pairsList[i][1]]
3645 3645 d0 = distances[pairsList[i][0]]
3646 3646 d1 = distances[pairsList[i][1]]
3647 3647
3648 3648 ph0_aux = ph0 + ph1
3649 3649 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3650 3650 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3651 3651 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3652 3652 #First Estimation
3653 3653 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3654 3654
3655 3655 #Most-Accurate Second Estimation
3656 3656 phi1_aux = ph0 - ph1
3657 3657 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3658 3658 #Direction Cosine 1
3659 3659 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3660 3660
3661 3661 #Searching the correct Direction Cosine
3662 3662 cosdir0_aux = cosdir0[:,i]
3663 3663 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3664 3664 #Minimum Distance
3665 3665 cosDiff = (cosdir1 - cosdir0_aux)**2
3666 3666 indcos = cosDiff.argmin(axis = 1)
3667 3667 #Saving Value obtained
3668 3668 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3669 3669
3670 3670 return cosdir0, cosdir
3671 3671
3672 3672 def __calculateAOA(self, cosdir, azimuth):
3673 3673 cosdirX = cosdir[:,0]
3674 3674 cosdirY = cosdir[:,1]
3675 3675
3676 3676 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3677 3677 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3678 3678 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3679 3679
3680 3680 return angles
3681 3681
3682 3682 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3683 3683
3684 3684 Ramb = 375 #Ramb = c/(2*PRF)
3685 3685 Re = 6371 #Earth Radius
3686 3686 heights = numpy.zeros(Ranges.shape)
3687 3687
3688 3688 R_aux = numpy.array([0,1,2])*Ramb
3689 3689 R_aux = R_aux.reshape(1,R_aux.size)
3690 3690
3691 3691 Ranges = Ranges.reshape(Ranges.size,1)
3692 3692
3693 3693 Ri = Ranges + R_aux
3694 3694 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3695 3695
3696 3696 #Check if there is a height between 70 and 110 km
3697 3697 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3698 3698 ind_h = numpy.where(h_bool == 1)[0]
3699 3699
3700 3700 hCorr = hi[ind_h, :]
3701 3701 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3702 3702
3703 3703 hCorr = hi[ind_hCorr][:len(ind_h)]
3704 3704 heights[ind_h] = hCorr
3705 3705
3706 3706 #Setting Error
3707 3707 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3708 3708 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3709 3709 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3710 3710 error[indError] = 0
3711 3711 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3712 3712 error[indInvalid2] = 14
3713 3713 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3714 3714 error[indInvalid1] = 13
3715 3715
3716 3716 return heights, error
3717 3717
3718 3718 def getPhasePairs(self, channelPositions):
3719 3719 chanPos = numpy.array(channelPositions)
3720 3720 listOper = list(itertools.combinations(list(range(5)),2))
3721 3721
3722 3722 distances = numpy.zeros(4)
3723 3723 axisX = []
3724 3724 axisY = []
3725 3725 distX = numpy.zeros(3)
3726 3726 distY = numpy.zeros(3)
3727 3727 ix = 0
3728 3728 iy = 0
3729 3729
3730 3730 pairX = numpy.zeros((2,2))
3731 3731 pairY = numpy.zeros((2,2))
3732 3732
3733 3733 for i in range(len(listOper)):
3734 3734 pairi = listOper[i]
3735 3735
3736 3736 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3737 3737
3738 3738 if posDif[0] == 0:
3739 3739 axisY.append(pairi)
3740 3740 distY[iy] = posDif[1]
3741 3741 iy += 1
3742 3742 elif posDif[1] == 0:
3743 3743 axisX.append(pairi)
3744 3744 distX[ix] = posDif[0]
3745 3745 ix += 1
3746 3746
3747 3747 for i in range(2):
3748 3748 if i==0:
3749 3749 dist0 = distX
3750 3750 axis0 = axisX
3751 3751 else:
3752 3752 dist0 = distY
3753 3753 axis0 = axisY
3754 3754
3755 3755 side = numpy.argsort(dist0)[:-1]
3756 3756 axis0 = numpy.array(axis0)[side,:]
3757 3757 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3758 3758 axis1 = numpy.unique(numpy.reshape(axis0,4))
3759 3759 side = axis1[axis1 != chanC]
3760 3760 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3761 3761 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3762 3762 if diff1<0:
3763 3763 chan2 = side[0]
3764 3764 d2 = numpy.abs(diff1)
3765 3765 chan1 = side[1]
3766 3766 d1 = numpy.abs(diff2)
3767 3767 else:
3768 3768 chan2 = side[1]
3769 3769 d2 = numpy.abs(diff2)
3770 3770 chan1 = side[0]
3771 3771 d1 = numpy.abs(diff1)
3772 3772
3773 3773 if i==0:
3774 3774 chanCX = chanC
3775 3775 chan1X = chan1
3776 3776 chan2X = chan2
3777 3777 distances[0:2] = numpy.array([d1,d2])
3778 3778 else:
3779 3779 chanCY = chanC
3780 3780 chan1Y = chan1
3781 3781 chan2Y = chan2
3782 3782 distances[2:4] = numpy.array([d1,d2])
3783 3783 # axisXsides = numpy.reshape(axisX[ix,:],4)
3784 3784 #
3785 3785 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3786 3786 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3787 3787 #
3788 3788 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3789 3789 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3790 3790 # channel25X = int(pairX[0,ind25X])
3791 3791 # channel20X = int(pairX[1,ind20X])
3792 3792 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3793 3793 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3794 3794 # channel25Y = int(pairY[0,ind25Y])
3795 3795 # channel20Y = int(pairY[1,ind20Y])
3796 3796
3797 3797 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3798 3798 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3799 3799
3800 3800 return pairslist, distances
3801 3801 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3802 3802 #
3803 3803 # arrayAOA = numpy.zeros((phases.shape[0],3))
3804 3804 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3805 3805 #
3806 3806 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3807 3807 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3808 3808 # arrayAOA[:,2] = cosDirError
3809 3809 #
3810 3810 # azimuthAngle = arrayAOA[:,0]
3811 3811 # zenithAngle = arrayAOA[:,1]
3812 3812 #
3813 3813 # #Setting Error
3814 3814 # #Number 3: AOA not fesible
3815 3815 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3816 3816 # error[indInvalid] = 3
3817 3817 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3818 3818 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3819 3819 # error[indInvalid] = 4
3820 3820 # return arrayAOA, error
3821 3821 #
3822 3822 # def __getDirectionCosines(self, arrayPhase, pairsList):
3823 3823 #
3824 3824 # #Initializing some variables
3825 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 3826 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3827 3827 #
3828 3828 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3829 3829 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3830 3830 #
3831 3831 #
3832 3832 # for i in range(2):
3833 3833 # #First Estimation
3834 3834 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3835 3835 # #Dealias
3836 3836 # indcsi = numpy.where(phi0_aux > numpy.pi)
3837 3837 # phi0_aux[indcsi] -= 2*numpy.pi
3838 3838 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3839 3839 # phi0_aux[indcsi] += 2*numpy.pi
3840 3840 # #Direction Cosine 0
3841 3841 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3842 3842 #
3843 3843 # #Most-Accurate Second Estimation
3844 3844 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3845 3845 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3846 3846 # #Direction Cosine 1
3847 3847 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3848 3848 #
3849 3849 # #Searching the correct Direction Cosine
3850 3850 # cosdir0_aux = cosdir0[:,i]
3851 3851 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3852 3852 # #Minimum Distance
3853 3853 # cosDiff = (cosdir1 - cosdir0_aux)**2
3854 3854 # indcos = cosDiff.argmin(axis = 1)
3855 3855 # #Saving Value obtained
3856 3856 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3857 3857 #
3858 3858 # return cosdir0, cosdir
3859 3859 #
3860 3860 # def __calculateAOA(self, cosdir, azimuth):
3861 3861 # cosdirX = cosdir[:,0]
3862 3862 # cosdirY = cosdir[:,1]
3863 3863 #
3864 3864 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3865 3865 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3866 3866 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3867 3867 #
3868 3868 # return angles
3869 3869 #
3870 3870 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3871 3871 #
3872 3872 # Ramb = 375 #Ramb = c/(2*PRF)
3873 3873 # Re = 6371 #Earth Radius
3874 3874 # heights = numpy.zeros(Ranges.shape)
3875 3875 #
3876 3876 # R_aux = numpy.array([0,1,2])*Ramb
3877 3877 # R_aux = R_aux.reshape(1,R_aux.size)
3878 3878 #
3879 3879 # Ranges = Ranges.reshape(Ranges.size,1)
3880 3880 #
3881 3881 # Ri = Ranges + R_aux
3882 3882 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3883 3883 #
3884 3884 # #Check if there is a height between 70 and 110 km
3885 3885 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3886 3886 # ind_h = numpy.where(h_bool == 1)[0]
3887 3887 #
3888 3888 # hCorr = hi[ind_h, :]
3889 3889 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3890 3890 #
3891 3891 # hCorr = hi[ind_hCorr]
3892 3892 # heights[ind_h] = hCorr
3893 3893 #
3894 3894 # #Setting Error
3895 3895 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3896 3896 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3897 3897 #
3898 3898 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3899 3899 # error[indInvalid2] = 14
3900 3900 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3901 3901 # error[indInvalid1] = 13
3902 3902 #
3903 3903 # return heights, error
3904 3904
3905 3905
3906 3906 class WeatherRadar(Operation):
3907 3907 '''
3908 3908 Function tat implements Weather Radar operations-
3909 3909 Input:
3910 3910 Output:
3911 3911 Parameters affected:
3912 3912 '''
3913 3913 isConfig = False
3914 3914
3915 3915 def __init__(self):
3916 3916 Operation.__init__(self)
3917 3917
3918 3918 def setup(self,dataOut,Pt=0,Gt=0,Gr=0,lambda_=0, aL=0,
3919 3919 tauW= 0,thetaT=0,thetaR=0,Km =0):
3920 3920 self.nCh = dataOut.nChannels
3921 3921 self.nHeis = dataOut.nHeights
3922 3922 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3923 3923 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3924 3924 self.Range = self.Range.reshape(1,self.nHeis)
3925 3925 self.Range = numpy.tile(self.Range,[self.nCh,1])
3926 3926 '''-----------1 Constante del Radar----------'''
3927 3927 self.Pt = Pt
3928 3928 self.Gt = Gt
3929 3929 self.Gr = Gr
3930 3930 self.lambda_ = lambda_
3931 3931 self.aL = aL
3932 3932 self.tauW = tauW
3933 3933 self.thetaT = thetaT
3934 3934 self.thetaR = thetaR
3935 3935 self.Km = Km
3936 3936 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3937 3937 Denominator = (Pt * Gt * Gr * lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3938 3938 self.RadarConstant = Numerator/Denominator
3939 3939 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3940 3940 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3941 3941 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3942 3942
3943 3943 def setMoments(self,dataOut,i):
3944 3944
3945 3945 type = dataOut.inputUnit
3946 3946 nCh = dataOut.nChannels
3947 3947 nHeis= dataOut.nHeights
3948 3948 data_param = numpy.zeros((nCh,4,nHeis))
3949 3949 if type == "Voltage":
3950 3950 data_param[:,0,:] = dataOut.dataPP_POW/(dataOut.nCohInt**2)
3951 3951 data_param[:,1,:] = dataOut.dataPP_DOP
3952 3952 data_param[:,2,:] = dataOut.dataPP_WIDTH
3953 3953 data_param[:,3,:] = dataOut.dataPP_SNR
3954 3954 if type == "Spectra":
3955 3955 data_param[:,0,:] = dataOut.data_POW
3956 3956 data_param[:,1,:] = dataOut.data_DOP
3957 3957 data_param[:,2,:] = dataOut.data_WIDTH
3958 3958 def setMoments(self,dataOut,i):
3959 3959 data_param[:,3,:] = dataOut.data_SNR
3960 3960
3961 3961 return data_param[:,i,:]
3962 3962
3963 3963
3964 3964 def run(self,dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3965 3965 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93):
3966 3966
3967 3967 if not self.isConfig:
3968 3968 self.setup(dataOut= dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3969 3969 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93)
3970 3970 self.isConfig = True
3971 3971 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3972 3972 Pr = self.setMoments(dataOut,0)
3973 3973
3974 3974 for R in range(self.nHeis):
3975 3975 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
3976 3976
3977 3977 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
3978 3978
3979 3979 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3980 3980 Zeh = self.Z_radar
3981 3981 dBZeh = 10*numpy.log10(Zeh)
3982 3982 dataOut.factor_Zeh= dBZeh
3983 3983 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3984 3984 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3985 3985
3986 3986 return dataOut
3987 3987
3988 3988 class PedestalInformation(Operation):
3989 3989 path_ped = None
3990 3990 path_adq = None
3991 3991 t_Interval_p = None
3992 3992 n_Muestras_p = None
3993 3993 isConfig = False
3994 3994 blocksPerfile= None
3995 3995 f_a_p = None
3996 3996 online = None
3997 3997 angulo_adq = None
3998 3998 nro_file = None
3999 3999 nro_key_p = None
4000 4000 tmp = None
4001 4001
4002 4002
4003 4003 def __init__(self):
4004 4004 Operation.__init__(self)
4005 4005
4006 4006 def getfirstFilefromPath(self,path,meta,ext):
4007 4007 validFilelist = []
4008 4008 #print("SEARH",path)
4009 4009 try:
4010 4010 fileList = os.listdir(path)
4011 4011 except:
4012 4012 print("check path - fileList")
4013 4013 if len(fileList)<1:
4014 4014 return None
4015 4015 # meta 1234 567 8-18 BCDE
4016 4016 # H,D,PE YYYY DDD EPOC .ext
4017 4017
4018 4018 for thisFile in fileList:
4019 4019 #print("HI",thisFile)
4020 4020 if meta =="PE":
4021 4021 try:
4022 4022 number= int(thisFile[len(meta)+7:len(meta)+17])
4023 4023 except:
4024 4024 print("There is a file or folder with different format")
4025 4025 if meta == "D":
4026 4026 try:
4027 4027 number= int(thisFile[8:11])
4028 4028 except:
4029 4029 print("There is a file or folder with different format")
4030 4030
4031 4031 if not isNumber(str=number):
4032 4032 continue
4033 4033 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4034 4034 continue
4035 4035 validFilelist.sort()
4036 4036 validFilelist.append(thisFile)
4037 4037 if len(validFilelist)>0:
4038 4038 validFilelist = sorted(validFilelist,key=str.lower)
4039 4039 return validFilelist
4040 4040 return None
4041 4041
4042 4042 def gettimeutcfromDirFilename(self,path,file):
4043 4043 dir_file= path+"/"+file
4044 4044 fp = h5py.File(dir_file,'r')
4045 4045 #epoc = fp['Metadata'].get('utctimeInit')[()]
4046 4046 epoc = fp['Data'].get('utc')[()]
4047 4047 fp.close()
4048 4048 return epoc
4049 4049
4050 4050 def gettimeutcadqfromDirFilename(self,path,file):
4051 4051 dir_file= path+"/"+file
4052 4052 fp = h5py.File(dir_file,'r')
4053 4053 epoc = fp['Metadata'].get('utctimeInit')[()]
4054 4054 #epoc = fp['Data'].get('utc')[()]
4055 4055 fp.close()
4056 4056 return epoc
4057 4057
4058 4058 def getDatavaluefromDirFilename(self,path,file,value):
4059 4059 dir_file= path+"/"+file
4060 4060 fp = h5py.File(dir_file,'r')
4061 4061 array = fp['Data'].get(value)[()]
4062 4062 fp.close()
4063 4063 return array
4064 4064
4065 4065 def getFile_KeyP(self,list_pedestal,list_adq):
4066 4066 print(list_pedestal)
4067 4067 print(list_adq)
4068 4068
4069 4069 def getNROFile(self,utc_adq,utc_ped_list):
4070 4070 c=0
4071 4071 print("insidegetNROFile")
4072 4072 print(utc_adq)
4073 4073 print(len(utc_ped_list))
4074 4074 for i in range(len(utc_ped_list)):
4075 4075 if utc_adq>utc_ped_list[i]:
4076 4076 #print("mayor")
4077 4077 #print("utc_ped_list",utc_ped_list[i])
4078 4078 c +=1
4079 4079
4080 4080 return c-1,utc_ped_list[c-1],utc_ped_list[c]
4081 4081
4082
4083 def setup_offline(self,list_pedestal,list_adq):
4082 def verificarNROFILE(self,dataOut,utc_ped,f_a_p,n_Muestras_p):
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 4092 print("SETUP OFFLINE")
4085 4093 print(self.path_ped)
4086 4094 print(self.path_adq)
4087 4095 print(len(self.list_pedestal))
4088 4096 print(len(self.list_adq))
4089 4097 utc_ped_list=[]
4090 4098 for i in range(len(self.list_pedestal)):
4091 4099 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4092 4100
4093 4101 #utc_ped_list= utc_ped_list
4094 4102 utc_adq = self.gettimeutcadqfromDirFilename(path=self.path_adq,file=self.list_adq[0])
4095 4103 print("dios existe donde esta")
4096 4104 #print("utc_ped_list",utc_ped_list)
4097 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 4112 print("nro_file",nro_file,"utc_ped",utc_ped)
4101 4113 print("nro_file",i)
4102 4114 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1 # ojito al -1 estimado alex
4103 4115 print("nro_key_p",nro_key_p)
4104 4116
4105 4117 ff_pedestal = self.list_pedestal[nro_file]
4106 4118 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4107 4119 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4108 4120
4109 4121 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4110 4122 print("angulo_array :",angulo[nro_key_p])
4111 4123 self.nro_file = nro_file
4112 4124 self.nro_key_p = nro_key_p
4113 4125
4114 4126 def setup_online(self,dataOut):
4115 4127 utc_adq =dataOut.utctime
4116 4128 print("Online-utc_adq",utc_adq)
4117 4129 print(len(self.list_pedestal))
4118 4130 utc_ped_list=[]
4119 4131 for i in range(len(self.list_pedestal)):
4120 4132 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4121 4133 print(utc_ped_list[:20])
4122 4134 #print(utc_ped_list[488:498])
4123 4135 print("ultimo UTC-PEDESTAL",utc_ped_list[-1])
4124 4136 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq, utc_ped_list= utc_ped_list)
4125 4137 print("nro_file",nro_file,"utc_ped",utc_ped,"utc_ped_1",utc_ped_1)
4126 4138 print("name_PEDESTAL",self.list_pedestal[nro_file])
4127 4139 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1
4128 4140 print("nro_key_p",nro_key_p)
4129 4141 ff_pedestal = self.list_pedestal[nro_file]
4130 4142 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4131 4143 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4132 4144
4133 4145 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4134 4146 print("angulo_array :",angulo[nro_key_p])
4135 4147 self.nro_file = nro_file
4136 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 4150 def setup(self,dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4215 4151 self.__dataReady = False
4216 4152 self.path_ped = path_ped
4217 4153 self.path_adq = path_adq
4218 4154 self.t_Interval_p = t_Interval_p
4219 4155 self.n_Muestras_p = n_Muestras_p
4220 4156 self.blocksPerfile= blocksPerfile
4221 4157 self.f_a_p = f_a_p
4222 4158 self.online = online
4223 4159 self.angulo_adq = numpy.zeros(self.blocksPerfile)
4224 4160 self.__profIndex = 0
4225 4161 self.tmp = 0
4226 4162 self.c_ped = 0
4227 4163 print(self.path_ped)
4228 4164 print(self.path_adq)
4229 4165 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4230 4166 print("LIST NEW", self.list_pedestal[:20])
4231 4167 self.list_adq = self.getfirstFilefromPath(path=self.path_adq,meta="D",ext=".hdf5")
4232 4168 print("*************Longitud list pedestal****************",len(self.list_pedestal))
4233 4169
4234 4170 if self.online:
4235 4171 print("Enable Online")
4236 4172 self.setup_online(dataOut)
4237 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 4176 def setNextFileP(self,dataOut):
4241 4177 if self.online:
4242 4178 data_pedestal = self.setNextFileonline()
4243 4179 else:
4244 data_pedestal = self.setNextFileoffline()
4180 data_pedestal = self.setNextFileoffline(dataOut)
4245 4181
4246 4182 return data_pedestal
4247 4183
4248 4184
4249 def setNextFileoffline(self):
4185 def setNextFileoffline(self,dataOut):
4250 4186 ##tmp=0
4251 4187 for j in range(self.blocksPerfile):
4252 4188 ###print("NUMERO DEL BLOQUE---->",j)
4253 4189 ###print("nro_key_p",self.nro_key_p)
4254 4190
4255 4191 #iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4256 4192 iterador = self.nro_key_p +self.f_a_p*self.c_ped
4257 4193 self.c_ped = self.c_ped +1
4258 4194
4259 4195 ###print("iterador------------->",iterador)
4260 4196 if iterador < self.n_Muestras_p:
4261 4197 self.nro_file = self.nro_file
4262 4198 else:
4263 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 4207 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(self.c_ped-2))
4265 4208 self.c_ped = 1
4266 4209 ##tmp = j
4267 4210 ##print("tmp else",tmp)
4268 4211 self.nro_key_p= self.f_a_p-dif
4269 4212 iterador = self.nro_key_p
4270 4213 ###print("iterador else",iterador)
4271 4214 #self.c_ped = self.c_ped +1
4272 4215
4273 4216 ###print("nro_file",self.nro_file)
4274 4217 #print("tmp",tmp)
4275 4218 try:
4276 4219 ff_pedestal = self.list_pedestal[self.nro_file]
4220 print("ff_pedestal",ff_pedestal)
4277 4221 except:
4222 print("############# EXCEPCION ######################")
4278 4223 return numpy.ones(self.blocksPerfile)*numpy.nan
4279 4224
4280 4225 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4281 4226 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4282 4227
4283 4228 self.angulo_adq[j]= angulo[iterador]
4284 4229
4285 4230 return self.angulo_adq
4286 4231
4287 4232 def setNextFileonline(self):
4288 4233 tmp = 0
4289 4234 self.nTries_p = 3
4290 4235 self.delay = 3
4291 4236 ready = 1
4292 4237 for j in range(self.blocksPerfile):
4293 4238 iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4294 4239 if iterador < self.n_Muestras_p:
4295 4240 self.nro_file = self.nro_file
4296 4241 else:
4297 4242 self.nro_file = self.nro_file+1
4298 4243 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(j-tmp-1))
4299 4244 tmp = j
4300 4245 self.nro_key_p= self.f_a_p-dif
4301 4246 iterador = self.nro_key_p
4302 4247 #print("nro_file---------------- :",self.nro_file)
4303 4248 try:
4304 4249 # update list_pedestal
4305 4250 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4306 4251 ff_pedestal = self.list_pedestal[self.nro_file]
4307 4252 except:
4308 4253 ff_pedestal = None
4309 4254 ready = 0
4310 4255 for nTries_p in range(self.nTries_p):
4311 4256 try:
4312 4257 # update list_pedestal
4313 4258 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4314 4259 ff_pedestal = self.list_pedestal[self.nro_file]
4315 4260 except:
4316 4261 ff_pedestal = None
4317 4262 if ff_pedestal is not None:
4318 4263 ready=1
4319 4264 break
4320 4265 log.warning("Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, self.nro_file, nTries_p + 1))
4321 4266 time.sleep(self.delay)
4322 4267 continue
4323 4268 #return numpy.ones(self.blocksPerfile)*numpy.nan
4324 4269
4325 4270 if ready == 1:
4326 4271 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4327 4272 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4328 4273
4329 4274 else:
4330 4275 print("there is no pedestal file")
4331 4276 angulo = numpy.ones(self.n_Muestras_p)*numpy.nan
4332 4277 self.angulo_adq[j]= angulo[iterador]
4333 4278 ####print("Angulo",self.angulo_adq)
4334 4279 ####print("Angulo",len(self.angulo_adq))
4335 4280 #self.nro_key_p=iterador + self.f_a_p
4336 4281 #if self.nro_key_p< self.n_Muestras_p:
4337 4282 # self.nro_file = self.nro_file
4338 4283 #else:
4339 4284 # self.nro_file = self.nro_file+1
4340 4285 # self.nro_key_p= self.nro_key_p
4341 4286 return self.angulo_adq
4342 4287
4343 4288
4344 4289 def run(self, dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4345 4290 if not self.isConfig:
4291 print("######################SETUP#########################################")
4346 4292 self.setup( dataOut, path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online)
4347 4293 self.isConfig = True
4348 4294
4349 4295 dataOut.flagNoData = True
4350 4296 #print("profIndex",self.__profIndex)
4351 4297
4352 4298 if self.__profIndex==0:
4353 4299 angulo_adq = self.setNextFileP(dataOut)
4354 4300 dataOut.azimuth = angulo_adq
4301 print("TIEMPO:",dataOut.utctime)
4355 4302 ##print("####################################################################")
4356 4303 ##print("angulos",dataOut.azimuth,len(dataOut.azimuth))
4357 4304 self.__dataReady = True
4358 4305 self.__profIndex += 1
4306 print("TIEMPO_bucle:",dataOut.utctime)
4359 4307 if self.__profIndex== blocksPerfile:
4360 4308 self.__profIndex = 0
4361 4309 if self.__dataReady:
4362 4310 #print(self.__profIndex,dataOut.azimuth[:10])
4363 4311 dataOut.flagNoData = False
4364 4312 return dataOut
4365 4313
4366 4314
4367 4315 class Block360(Operation):
4368 4316 '''
4369 4317 '''
4370 4318 isConfig = False
4371 4319 __profIndex = 0
4372 4320 __initime = None
4373 4321 __lastdatatime = None
4374 4322 __buffer = None
4375 4323 __dataReady = False
4376 4324 n = None
4377 4325 __nch = 0
4378 4326 __nHeis = 0
4379 4327 index = 0
4380 4328
4381 4329 def __init__(self,**kwargs):
4382 4330 Operation.__init__(self,**kwargs)
4383 4331
4384 4332 def setup(self, dataOut, n = None):
4385 4333 '''
4386 4334 n= Numero de PRF's de entrada
4387 4335 '''
4388 4336 self.__initime = None
4389 4337 self.__lastdatatime = 0
4390 4338 self.__dataReady = False
4391 4339 self.__buffer = 0
4392 4340 self.__buffer_1D = 0
4393 4341 self.__profIndex = 0
4394 4342 self.index = 0
4395 4343 self.__nch = dataOut.nChannels
4396 4344 self.__nHeis = dataOut.nHeights
4397 4345 ##print("ELVALOR DE n es:", n)
4398 4346 if n == None:
4399 4347 raise ValueError("n should be specified.")
4400 4348
4401 4349 if n != None:
4402 4350 if n<1:
4403 4351 print("n should be greater than 2")
4404 4352 raise ValueError("n should be greater than 2")
4405 4353
4406 4354 self.n = n
4407 4355 #print("nHeights")
4408 4356 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4409 4357 self.__buffer2= numpy.zeros(n)
4410 4358
4411 4359 def putData(self,data):
4412 4360 '''
4413 4361 Add a profile to he __buffer and increase in one the __profiel Index
4414 4362 '''
4415 4363 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4416 4364 #print("line 4049",data.azimuth.shape,data.azimuth)
4417 4365 self.__buffer[:,self.__profIndex,:]= data.dataPP_POW
4418 4366 #print("me casi",self.index,data.azimuth[self.index])
4419 4367 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4420 4368 #print("magic",data.profileIndex)
4421 4369 #print(data.azimuth[self.index])
4422 4370 #print("index",self.index)
4423 4371
4424 4372 self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4425 4373 #print("q pasa")
4426 4374 self.index+=1
4427 4375 #print("index",self.index,data.azimuth[:10])
4428 4376 self.__profIndex += 1
4429 4377 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4430 4378
4431 4379 def pushData(self,data):
4432 4380 '''
4433 4381 Return the PULSEPAIR and the profiles used in the operation
4434 4382 Affected : self.__profileIndex
4435 4383 '''
4436 4384 #print("pushData")
4437 4385
4438 4386 data_360 = self.__buffer
4439 4387 data_p = self.__buffer2
4440 4388 n = self.__profIndex
4441 4389
4442 4390 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4443 4391 self.__buffer2 = numpy.zeros(self.n)
4444 4392 self.__profIndex = 0
4445 4393 #print("pushData")
4446 4394 return data_360,n,data_p
4447 4395
4448 4396
4449 4397 def byProfiles(self,dataOut):
4450 4398
4451 4399 self.__dataReady = False
4452 4400 data_360 = None
4453 4401 data_p = None
4454 4402 #print("dataOu",dataOut.dataPP_POW)
4455 4403 self.putData(data=dataOut)
4456 4404 #print("profIndex",self.__profIndex)
4457 4405 if self.__profIndex == self.n:
4458 4406 data_360,n,data_p = self.pushData(data=dataOut)
4459 4407 self.__dataReady = True
4460 4408
4461 4409 return data_360,data_p
4462 4410
4463 4411
4464 4412 def blockOp(self, dataOut, datatime= None):
4465 4413 if self.__initime == None:
4466 4414 self.__initime = datatime
4467 4415 data_360,data_p = self.byProfiles(dataOut)
4468 4416 self.__lastdatatime = datatime
4469 4417
4470 4418 if data_360 is None:
4471 4419 return None, None,None
4472 4420
4473 4421 avgdatatime = self.__initime
4474 4422 deltatime = datatime - self.__lastdatatime
4475 4423 self.__initime = datatime
4476 4424 #print(data_360.shape,avgdatatime,data_p.shape)
4477 4425 return data_360,avgdatatime,data_p
4478 4426
4479 4427 def run(self, dataOut,n = None,**kwargs):
4480 4428
4481 4429 if not self.isConfig:
4482 4430 self.setup(dataOut = dataOut, n = n , **kwargs)
4483 4431 self.index = 0
4484 4432 #print("comova",self.isConfig)
4485 4433 self.isConfig = True
4486 4434 if self.index==dataOut.azimuth.shape[0]:
4487 4435 self.index=0
4488 4436 data_360, avgdatatime,data_p = self.blockOp(dataOut, dataOut.utctime)
4489 4437 dataOut.flagNoData = True
4490 4438
4491 4439 if self.__dataReady:
4492 4440 dataOut.data_360 = data_360 # S
4493 4441 ##print("---------------------------------------------------------------------------------")
4494 4442 ##print("---------------------------DATAREADY---------------------------------------------")
4495 4443 ##print("---------------------------------------------------------------------------------")
4496 4444 ##print("data_360",dataOut.data_360.shape)
4497 4445 dataOut.data_azi = data_p
4498 4446 ##print("azi: ",dataOut.data_azi)
4499 4447 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4500 4448 dataOut.utctime = avgdatatime
4501 4449 dataOut.flagNoData = False
4502 4450 return dataOut
@@ -1,127 +1,147
1 1 #!python
2 2 '''
3 3 '''
4 4
5 5 import os, sys
6 6 import datetime
7 7 import time
8 8
9 9 #path = os.path.dirname(os.getcwd())
10 10 #path = os.path.dirname(path)
11 11 #sys.path.insert(0, path)
12 12
13 13 from schainpy.controller import Project
14 14
15 15 desc = "USRP_test"
16 16 filename = "USRP_processing.xml"
17 17 controllerObj = Project()
18 18 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
19 19
20 20 ############## USED TO PLOT IQ VOLTAGE, POWER AND SPECTRA #############
21 21
22 22 #######################################################################
23 23 ######PATH DE LECTURA, ESCRITURA, GRAFICOS Y ENVIO WEB#################
24 24 #######################################################################
25 25 #path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman'
26 26 #path = '/DATA_RM/TEST_INTEGRACION'
27 27 #path = '/DATA_RM/TEST_ONLINE'
28 path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
29 path_pp = '/DATA_RM/TEST_HDF5'
28 #path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
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 51 figpath = '/home/soporte/Pictures/TEST_INTEGRACION_IMG'
32 52 #remotefolder = "/home/wmaster/graficos"
33 53 #######################################################################
34 54 ################# RANGO DE PLOTEO######################################
35 55 #######################################################################
36 56 dBmin = '-5'
37 57 dBmax = '20'
38 58 xmin = '0'
39 59 xmax ='24'
40 60 ymin = '0'
41 61 ymax = '600'
42 62 #######################################################################
43 63 ########################FECHA##########################################
44 64 #######################################################################
45 65 str = datetime.date.today()
46 66 today = str.strftime("%Y/%m/%d")
47 67 str2 = str - datetime.timedelta(days=1)
48 68 yesterday = str2.strftime("%Y/%m/%d")
49 69 #######################################################################
50 70 ######################## UNIDAD DE LECTURA#############################
51 71 #######################################################################
52 72 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
53 73 path=path,
54 74 startDate="2021/01/01",#today,
55 75 endDate="2021/12/30",#today,
56 76 startTime='00:00:00',
57 77 endTime='23:59:59',
58 78 delay=0,
59 79 #set=0,
60 80 online=0,
61 81 walk=1,
62 82 ippKm = 60)
63 83
64 84 opObj11 = readUnitConfObj.addOperation(name='printInfo')
65 85 #opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
66 86 #######################################################################
67 87 ################ OPERACIONES DOMINIO DEL TIEMPO########################
68 88 #######################################################################
69 89
70 90 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
71 91
72 92 #
73 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 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 96 #opObj11 = procUnitConfObjA.addOperation(name='setRadarFrequency')
77 97 #opObj11.addParameter(name='frequency', value='70312500')
78 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 100 opObj11.addParameter(name='removeDC', value=1, format='int')
81 101 # Ploteo TEST
82 102 '''
83 103 opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')
84 104 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
85 105 opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
86 106 #opObj11.addParameter(name='xmax', value=8)
87 107 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSpecwidthPlot', optype='other')
88 108 '''
89 109 # OJO SCOPE
90 110 #opObj10 = procUnitConfObjA.addOperation(name='ScopePlot', optype='external')
91 111 #opObj10.addParameter(name='id', value='10', format='int')
92 112 ##opObj10.addParameter(name='xmin', value='0', format='int')
93 113 ##opObj10.addParameter(name='xmax', value='50', format='int')
94 114 #opObj10.addParameter(name='type', value='iq')
95 115 ##opObj10.addParameter(name='ymin', value='-5000', format='int')
96 116 ##opObj10.addParameter(name='ymax', value='8500', format='int')
97 117 #opObj11.addParameter(name='save', value=figpath, format='str')
98 118 #opObj11.addParameter(name='save_period', value=10, format='int')
99 119
100 120 #opObj10 = procUnitConfObjA.addOperation(name='setH0')
101 121 #opObj10.addParameter(name='h0', value='-5000', format='float')
102 122
103 123 #opObj11 = procUnitConfObjA.addOperation(name='filterByHeights')
104 124 #opObj11.addParameter(name='window', value='1', format='int')
105 125
106 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 127 #opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other')
108 128 #opObj11.addParameter(name='code', value=codigo, formatyesterday='floatlist')
109 129 #opObj11.addParameter(name='nCode', value='1', format='int')
110 130 #opObj11.addParameter(name='nBaud', value='28', format='int')
111 131
112 132 #opObj11 = procUnitConfObjA.addOperation(name='CohInt', optype='other')
113 133 #opObj11.addParameter(name='n', value='100', format='int')
114 134
115 135 #######################################################################
116 136 ########## OPERACIONES ParametersProc########################
117 137 #######################################################################
118 138
119 139 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
120 140 opObj10 = procUnitConfObjB.addOperation(name='HDFWriter')
121 141 opObj10.addParameter(name='path',value=path_pp)
122 142 #opObj10.addParameter(name='mode',value=0)
123 143 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
124 144 opObj10.addParameter(name='metadataList',value='utctimeInit,timeZone,paramInterval,profileIndex,channelList,heightList,flagDataAsBlock',format='list')
125 145 opObj10.addParameter(name='dataList',value='dataPP_POW,dataPP_DOP,utctime',format='list')#,format='list'
126 146
127 147 controllerObj.start()
@@ -1,146 +1,157
1 1 #!python
2 2 '''
3 3 '''
4 4
5 5 import os, sys
6 6 import datetime
7 7 import time
8 8
9 9 #path = os.path.dirname(os.getcwd())
10 10 #path = os.path.dirname(path)
11 11 #sys.path.insert(0, path)
12 12
13 13 from schainpy.controller import Project
14 14
15 15 desc = "USRP_test"
16 16 filename = "USRP_processing.xml"
17 17 controllerObj = Project()
18 18 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
19 19
20 20 ############## USED TO PLOT IQ VOLTAGE, POWER AND SPECTRA #############
21 21
22 22 #######################################################################
23 23 ######PATH DE LECTURA, ESCRITURA, GRAFICOS Y ENVIO WEB#################
24 24 #######################################################################
25 25 #path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman'
26 26 #path = '/DATA_RM/TEST_INTEGRACION'
27 27 #path = '/DATA_RM/TEST_ONLINE'
28 28 #path_pp = '/DATA_RM/TEST_HDF5'
29 29
30 30 #figpath = '/home/soporte/Pictures/TEST_INTEGRACION_IMG'
31 path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
32 path_pp = '/DATA_RM/TEST_HDF5_SPEC'
33
34
31 ###path = '/DATA_RM/TEST_INTEGRACION/ADQ_OFFLINE/'
32 ###path_pp = '/DATA_RM/TEST_HDF5_SPEC'
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 43 #remotefolder = "/home/wmaster/graficos"
39 44 #######################################################################
40 45 ################# RANGO DE PLOTEO######################################
41 46 #######################################################################
42 47 dBmin = '-5'
43 48 dBmax = '20'
44 49 xmin = '0'
45 50 xmax ='24'
46 51 ymin = '0'
47 52 ymax = '600'
48 53 #######################################################################
49 54 ########################FECHA##########################################
50 55 #######################################################################
51 56 str = datetime.date.today()
52 57 today = str.strftime("%Y/%m/%d")
53 58 str2 = str - datetime.timedelta(days=1)
54 59 yesterday = str2.strftime("%Y/%m/%d")
55 60 #######################################################################
56 61 ######################## UNIDAD DE LECTURA#############################
57 62 #######################################################################
58 63 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
59 64 path=path,
60 65 startDate="2021/01/01",#today,
61 66 endDate="2021/12/30",#today,
62 67 startTime='00:00:00',
63 68 endTime='23:59:59',
64 69 delay=0,
65 70 #set=0,
66 71 online=0,
67 72 walk=1,
68 73 ippKm = 60)
69 74
70 75 opObj11 = readUnitConfObj.addOperation(name='printInfo')
71 76 #opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
72 77 #######################################################################
73 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 87 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
77 88
78 89 procUnitConfObjB = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
79 procUnitConfObjB.addParameter(name='nFFTPoints', value=250, format='int')
80 procUnitConfObjB.addParameter(name='nProfiles' , value=250, format='int')
90 procUnitConfObjB.addParameter(name='nFFTPoints', value=n, format='int')
91 procUnitConfObjB.addParameter(name='nProfiles' , value=n, format='int')
81 92
82 93
83 94
84 95 #
85 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 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 99 #opObj11 = procUnitConfObjA.addOperation(name='setRadarFrequency')
89 100 #opObj11.addParameter(name='frequency', value='70312500')
90 101 #opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
91 102 #opObj11.addParameter(name='n', value='625', format='int')#10
92 103 #opObj11.addParameter(name='removeDC', value=1, format='int')
93 104
94 105 # Ploteo TEST
95 106 '''
96 107 opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')
97 108 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
98 109 opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
99 110 #opObj11.addParameter(name='xmax', value=8)
100 111 opObj11 = procUnitConfObjA.addOperation(name='PulsepairSpecwidthPlot', optype='other')
101 112 '''
102 113 # OJO SCOPE
103 114 #opObj10 = procUnitConfObjA.addOperation(name='ScopePlot', optype='external')
104 115 #opObj10.addParameter(name='buffer_sizeid', value='10', format='int')
105 116 ##opObj10.addParameter(name='xmin', value='0', format='int')
106 117 ##opObj10.addParameter(name='xmax', value='50', format='int')
107 118 #opObj10.addParameter(name='type', value='iq')
108 119 ##opObj10.addParameter(name='ymin', value='-5000', format='int')
109 120 ##opObj10.addParameter(name='ymax', value='8500', format='int')
110 121 #opObj11.addParameter(name='save', value=figpath, format='str')
111 122 #opObj11.addParameter(name='save_period', value=10, format='int')
112 123
113 124 #opObj10 = procUnitConfObjA.addOperation(name='setH0')
114 125 #opObj10.addParameter(name='h0', value='-5000', format='float')
115 126
116 127 #opObj11 = procUnitConfObjA.addOperation(name='filterByHeights')
117 128 #opObj11.addParameter(name='window', value='1', format='int')
118 129
119 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 131 #opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other')
121 132 #opObj11.addParameter(name='code', value=codigo, formatyesterday='floatlist')
122 133 #opObj11.addParameter(name='nCode', value='1', format='int')
123 134 #opObj11.addParameter(name='nBaud', value='28', format='int')
124 135
125 136 #opObj11 = procUnitConfObjA.addOperation(name='CohInt', optype='other')
126 137 #opObj11.addParameter(name='n', value='100', format='int')
127 138
128 139 #######################################################################
129 140 ########## OPERACIONES ParametersProc########################
130 141 #######################################################################
131 142
132 143 procUnitConfObjC= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjB.getId())
133 144
134 145 procUnitConfObjC.addOperation(name='SpectralMoments')
135 146
136 147
137 148 opObj10 = procUnitConfObjC.addOperation(name='HDFWriter')
138 149 opObj10.addParameter(name='path',value=path_pp)
139 150 #opObj10.addParameter(name='mode',value=0)
140 151 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
141 152 #opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
142 153 opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
143 154
144 155 opObj10.addParameter(name='dataList',value='data_pow,data_dop,utctime',format='list')#,format='list'
145 156
146 157 controllerObj.start()
@@ -1,64 +1,75
1 1 import os,sys
2 2 import datetime
3 3 import time
4 4 from schainpy.controller import Project
5 5 #path='/DATA_RM/TEST_HDF5/d2021200'
6 6 #path='/DATA_RM/TEST_HDF5/d2021200'
7 7 #path='/DATA_RM/TEST_HDF5/d2021214'
8 8 #path='/DATA_RM/TEST_HDF5/d2021229'
9 9
10 10 #path='/DATA_RM/TEST_HDF5/d2021231'
11 11 #path='/DATA_RM/TEST_HDF5/ADQ_OFFLINE/d2021231'
12 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 16 path_adq=path
15 17 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021200'
16 18 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021214'
17 19 #path_ped='/DATA_RM/TEST_PEDESTAL/P2021230'
18 20 #path_ped='/DATA_RM/TEST_PEDESTAL/P20210819'
19 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 30 figpath = '/home/soporte/Pictures'
24 31 desc = "Simulator Test"
25 32
26 33 controllerObj = Project()
27 34 controllerObj.setup(id='10',name='Test Simulator',description=desc)
28 35 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
29 36 path=path,
30 37 startDate="2021/01/01", #"2020/01/01",#today,
31 38 endDate= "2021/12/01", #"2020/12/30",#today,
32 39 startTime='00:00:00',
33 40 endTime='23:59:59',
34 41 t_Interval_p=0.01,
35 42 n_Muestras_p=100,
36 43 delay=30,
37 44 #set=0,
38 45 online=0,
39 46 walk=0,
40 47 nTries=6)#1
41 48
42 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 55 opObj11 = procUnitConfObjA.addOperation(name='PedestalInformation')
45 56 opObj11.addParameter(name='path_ped', value=path_ped)
46 57 opObj11.addParameter(name='path_adq', value=path_adq)
47 58 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
48 59 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
49 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 62 opObj11.addParameter(name='online', value='0', format='int')# habilitar el enable aqui tambien
52 63
53 64
54 65 opObj11 = procUnitConfObjA.addOperation(name='Block360')
55 66 opObj11.addParameter(name='n', value='10', format='int')
56 67 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
57 68
58 69 opObj11= procUnitConfObjA.addOperation(name='WeatherPlot',optype='other')
59 opObj11.addParameter(name='save', value=figpath)
60 opObj11.addParameter(name='save_period', value=1)
70 #opObj11.addParameter(name='save', value=figpath)
71 #opObj11.addParameter(name='save_period', value=1)
61 72
62 73 controllerObj.start()
63 74 #online 1 utc_adq 1617490240.48
64 75 #online 0 utc_adq 1617489815.4804
@@ -1,89 +1,90
1 1 import os,sys,json
2 2 import datetime
3 3 import time
4 4 from schainpy.controller import Project
5 5 '''
6 6 NOTA:
7 7 Este script de prueba.
8 8 - Unidad del lectura 'HDFReader'.
9 9 - Unidad de procesamiento ParametersProc
10 10 - Operacion SpectralMomentsPlot
11 11
12 12 '''
13 13 #path = '/home/soporte/Downloads/RAWDATA_PP'
14 14 #path = '/DATA_RM/TEST_HDF5/d2021203'
15 15 #######################################################################
16 16 ################# RANGO DE PLOTEO######################################
17 17 #######################################################################
18 18 dBmin = '1'
19 19 dBmax = '85'
20 20 xmin = '0'
21 21 xmax ='24'
22 tmmin = 16.2
23 tmmax = 16.25
22 tmmin = 12.2
23 tmmax = 12.40
24 24 ymin = '0'
25 25 ymax = '600'
26 26 #######################################################################
27 27 #######################################################################
28 28 # este script lee los archivos pre-procesados pulse-pair y permite el
29 29 # el ploteo del rti, mostrando los valores de potencia de la senal.
30 30 # el resultado del grafico depende del programa USRP_ADQ_PP.py
31 31 # debido al procesamiento del Pulse Pair.
32 32
33 33 #######################################################################
34 34 #######################################################################
35
36 path='/DATA_RM/TEST_HDF5/d2021231'
35 #path_pp = '/DATA_RM/TEST_HDF5_PP_22'
36 path='/DATA_RM/TEST_HDF5_PP_22/d2021265'
37 #path='/DATA_RM/TEST_HDF5/d2021231'
37 38 figpath = '/home/soporte/Downloads/IMAGE'
38 39 desc = "Simulator Test"
39 40 desc_data = {
40 41 'Data': {
41 42 'dataPP_POW': ['Data/dataPP_POW/channel00','Data/dataPP_POW/channel01'],
42 43 'dataPP_DOP': ['Data/dataPP_DOP/channel00','Data/dataPP_DOP/channel01'],
43 44 'utctime':'Data/utctime'
44 45 },
45 46 'Metadata': {
46 47 'heightList' :'Metadata/heightList',
47 48 'flagDataAsBlock':'Metadata/flagDataAsBlock',
48 49 'channelList' :'Metadata/channelList',
49 50 'profileIndex' :'Metadata/profileIndex'
50 51 }
51 52 }
52 53
53 54 controllerObj = Project()
54 55
55 56 controllerObj.setup(id='10',name='Test Simulator',description=desc)
56 57
57 58 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
58 59 path=path,
59 60 startDate="2021/01/01", #"2020/01/01",#today,
60 61 endDate= "2021/12/01", #"2020/12/30",#today,
61 62 startTime='00:00:00',
62 63 endTime='23:59:59',
63 64 delay=0,
64 65 #set=0,
65 66 online=0,
66 67 walk=0,
67 68 description= json.dumps(desc_data))#1
68 69
69 70 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
70 71
71 72 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairPowerPlot', optype='other')#PulsepairPowerPlot
72 73 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairSignalPlot', optype='other')
73 74 #opObj11 = procUnitConfObjA.addOperation(name='PulsepairVelocityPlot', optype='other')
74 75
75 76 opObj11 = procUnitConfObjA.addOperation(name='GenericRTIPlot',optype='external')
76 77
77 78 opObj11.addParameter(name='attr_data', value='dataPP_POW')
78 79 opObj11.addParameter(name='colormap', value='jet')
79 80
80 81 opObj11.addParameter(name='xmin', value=tmmin)
81 82 opObj11.addParameter(name='xmax', value=tmmax)
82 83 opObj11.addParameter(name='zmin', value=dBmin)
83 84 opObj11.addParameter(name='zmax', value=dBmax)
84 85 opObj11.addParameter(name='save', value=figpath)
85 86 opObj11.addParameter(name='showprofile', value=0)
86 87 opObj11.addParameter(name='save_period', value=10)
87 88
88 89
89 90 controllerObj.start()
@@ -1,75 +1,78
1 1 import os,sys,json
2 2 import datetime
3 3 import time
4 4 from schainpy.controller import Project
5 5 '''
6 6 NOTA:
7 7 Este script de prueba.
8 8 - Unidad del lectura 'HDFReader'.
9 9 - Unidad de procesamiento ParametersProc
10 10 - Operacion SpectralMomentsPlot
11 11
12 12 '''
13 13
14 14 #######################################################################
15 15 ################# RANGO DE PLOTEO######################################
16 16 #######################################################################
17 17 dBmin = '1'
18 18 dBmax = '65'
19 19 xmin = '0'
20 20 xmax ='24'
21 tmmin = 16.2
22 tmmax = 16.25
21 #tmmin = 16.2
22 #tmmax = 16.25
23 tmmin =15
24 tmmax =15.5
23 25 ymin = '0'
24 26 ymax = '600'
25 27 #######################################################################
26 28 #######################################################################
27 29 #######################################################################
28 path = '/DATA_RM/TEST_HDF5_SPEC'
29 figpath = '/home/soporte/Downloads/IMAGE'
30 #path = '/DATA_RM/TEST_HDF5_SPEC'
31 path = '/DATA_RM/TEST_HDF5_SPEC_23/6v/'
32 figpath = '/home/soporte/Downloads/23/6v'
30 33 desc = "Simulator Test"
31 34 desc_data = {
32 35 'Data': {
33 36 'data_pow': ['Data/data_pow/channel00','Data/data_pow/channel01'],
34 37 'data_dop': ['Data/data_dop/channel00','Data/data_dop/channel01'],
35 38 'utctime':'Data/utctime'
36 39 },
37 40 'Metadata': {
38 41 'heightList':'Metadata/heightList',
39 42 'nIncohInt' :'Metadata/nIncohInt',
40 43 'nCohInt' :'Metadata/nCohInt',
41 44 'nProfiles' :'Metadata/nProfiles',
42 45 'channelList' :'Metadata/channelList',
43 46 'utctimeInit' :'Metadata/utctimeInit'
44 47
45 48 }
46 49 }
47 50
48 51 controllerObj = Project()
49 52
50 53 controllerObj.setup(id='10',name='Test Simulator',description=desc)
51 54
52 55 readUnitConfObj = controllerObj.addReadUnit(datatype='HDFReader',
53 56 path=path,
54 57 startDate="2021/01/01", #"2020/01/01",#today,
55 58 endDate= "2021/12/01", #"2020/12/30",#today,
56 59 startTime='00:00:00',
57 60 endTime='23:59:59',
58 61 delay=0,
59 62 #set=0,
60 63 online=0,
61 64 walk=1,
62 65 description= json.dumps(desc_data))#1
63 66
64 67 procUnitConfObjA = controllerObj.addProcUnit(datatype='ParametersProc',inputId=readUnitConfObj.getId())
65 68
66 69 opObj11 = procUnitConfObjA.addOperation(name='PowerPlot',optype='external')
67 70 opObj11.addParameter(name='xmin', value=tmmin)
68 71 opObj11.addParameter(name='xmax', value=tmmax)
69 72 opObj11.addParameter(name='zmin', value=dBmin)
70 73 opObj11.addParameter(name='zmax', value=dBmax)
71 74 opObj11.addParameter(name='save', value=figpath)
72 75 opObj11.addParameter(name='showprofile', value=0)
73 76 opObj11.addParameter(name='save_period', value=10)
74 77
75 78 controllerObj.start()
General Comments 0
You need to be logged in to leave comments. Login now