##// END OF EJS Templates
Fix publish and plots operations issue #929
Juan C. Espinoza -
r1062:8048843f4edf
parent child
Show More
@@ -1,1220 +1,1220
1 '''
1 '''
2
2
3 $Author: murco $
3 $Author: murco $
4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 '''
5 '''
6
6
7 import copy
7 import copy
8 import numpy
8 import numpy
9 import datetime
9 import datetime
10
10
11 from jroheaderIO import SystemHeader, RadarControllerHeader
11 from jroheaderIO import SystemHeader, RadarControllerHeader
12 from schainpy import cSchain
12 from schainpy import cSchain
13
13
14
14
15 def getNumpyDtype(dataTypeCode):
15 def getNumpyDtype(dataTypeCode):
16
16
17 if dataTypeCode == 0:
17 if dataTypeCode == 0:
18 numpyDtype = numpy.dtype([('real','<i1'),('imag','<i1')])
18 numpyDtype = numpy.dtype([('real','<i1'),('imag','<i1')])
19 elif dataTypeCode == 1:
19 elif dataTypeCode == 1:
20 numpyDtype = numpy.dtype([('real','<i2'),('imag','<i2')])
20 numpyDtype = numpy.dtype([('real','<i2'),('imag','<i2')])
21 elif dataTypeCode == 2:
21 elif dataTypeCode == 2:
22 numpyDtype = numpy.dtype([('real','<i4'),('imag','<i4')])
22 numpyDtype = numpy.dtype([('real','<i4'),('imag','<i4')])
23 elif dataTypeCode == 3:
23 elif dataTypeCode == 3:
24 numpyDtype = numpy.dtype([('real','<i8'),('imag','<i8')])
24 numpyDtype = numpy.dtype([('real','<i8'),('imag','<i8')])
25 elif dataTypeCode == 4:
25 elif dataTypeCode == 4:
26 numpyDtype = numpy.dtype([('real','<f4'),('imag','<f4')])
26 numpyDtype = numpy.dtype([('real','<f4'),('imag','<f4')])
27 elif dataTypeCode == 5:
27 elif dataTypeCode == 5:
28 numpyDtype = numpy.dtype([('real','<f8'),('imag','<f8')])
28 numpyDtype = numpy.dtype([('real','<f8'),('imag','<f8')])
29 else:
29 else:
30 raise ValueError, 'dataTypeCode was not defined'
30 raise ValueError, 'dataTypeCode was not defined'
31
31
32 return numpyDtype
32 return numpyDtype
33
33
34 def getDataTypeCode(numpyDtype):
34 def getDataTypeCode(numpyDtype):
35
35
36 if numpyDtype == numpy.dtype([('real','<i1'),('imag','<i1')]):
36 if numpyDtype == numpy.dtype([('real','<i1'),('imag','<i1')]):
37 datatype = 0
37 datatype = 0
38 elif numpyDtype == numpy.dtype([('real','<i2'),('imag','<i2')]):
38 elif numpyDtype == numpy.dtype([('real','<i2'),('imag','<i2')]):
39 datatype = 1
39 datatype = 1
40 elif numpyDtype == numpy.dtype([('real','<i4'),('imag','<i4')]):
40 elif numpyDtype == numpy.dtype([('real','<i4'),('imag','<i4')]):
41 datatype = 2
41 datatype = 2
42 elif numpyDtype == numpy.dtype([('real','<i8'),('imag','<i8')]):
42 elif numpyDtype == numpy.dtype([('real','<i8'),('imag','<i8')]):
43 datatype = 3
43 datatype = 3
44 elif numpyDtype == numpy.dtype([('real','<f4'),('imag','<f4')]):
44 elif numpyDtype == numpy.dtype([('real','<f4'),('imag','<f4')]):
45 datatype = 4
45 datatype = 4
46 elif numpyDtype == numpy.dtype([('real','<f8'),('imag','<f8')]):
46 elif numpyDtype == numpy.dtype([('real','<f8'),('imag','<f8')]):
47 datatype = 5
47 datatype = 5
48 else:
48 else:
49 datatype = None
49 datatype = None
50
50
51 return datatype
51 return datatype
52
52
53 def hildebrand_sekhon(data, navg):
53 def hildebrand_sekhon(data, navg):
54 """
54 """
55 This method is for the objective determination of the noise level in Doppler spectra. This
55 This method is for the objective determination of the noise level in Doppler spectra. This
56 implementation technique is based on the fact that the standard deviation of the spectral
56 implementation technique is based on the fact that the standard deviation of the spectral
57 densities is equal to the mean spectral density for white Gaussian noise
57 densities is equal to the mean spectral density for white Gaussian noise
58
58
59 Inputs:
59 Inputs:
60 Data : heights
60 Data : heights
61 navg : numbers of averages
61 navg : numbers of averages
62
62
63 Return:
63 Return:
64 -1 : any error
64 -1 : any error
65 anoise : noise's level
65 anoise : noise's level
66 """
66 """
67
67
68 sortdata = numpy.sort(data, axis=None)
68 sortdata = numpy.sort(data, axis=None)
69 # lenOfData = len(sortdata)
69 # lenOfData = len(sortdata)
70 # nums_min = lenOfData*0.2
70 # nums_min = lenOfData*0.2
71 #
71 #
72 # if nums_min <= 5:
72 # if nums_min <= 5:
73 # nums_min = 5
73 # nums_min = 5
74 #
74 #
75 # sump = 0.
75 # sump = 0.
76 #
76 #
77 # sumq = 0.
77 # sumq = 0.
78 #
78 #
79 # j = 0
79 # j = 0
80 #
80 #
81 # cont = 1
81 # cont = 1
82 #
82 #
83 # while((cont==1)and(j<lenOfData)):
83 # while((cont==1)and(j<lenOfData)):
84 #
84 #
85 # sump += sortdata[j]
85 # sump += sortdata[j]
86 #
86 #
87 # sumq += sortdata[j]**2
87 # sumq += sortdata[j]**2
88 #
88 #
89 # if j > nums_min:
89 # if j > nums_min:
90 # rtest = float(j)/(j-1) + 1.0/navg
90 # rtest = float(j)/(j-1) + 1.0/navg
91 # if ((sumq*j) > (rtest*sump**2)):
91 # if ((sumq*j) > (rtest*sump**2)):
92 # j = j - 1
92 # j = j - 1
93 # sump = sump - sortdata[j]
93 # sump = sump - sortdata[j]
94 # sumq = sumq - sortdata[j]**2
94 # sumq = sumq - sortdata[j]**2
95 # cont = 0
95 # cont = 0
96 #
96 #
97 # j += 1
97 # j += 1
98 #
98 #
99 # lnoise = sump /j
99 # lnoise = sump /j
100 #
100 #
101 # return lnoise
101 # return lnoise
102
102
103 return cSchain.hildebrand_sekhon(sortdata, navg)
103 return cSchain.hildebrand_sekhon(sortdata, navg)
104
104
105
105
106 class Beam:
106 class Beam:
107
107
108 def __init__(self):
108 def __init__(self):
109 self.codeList = []
109 self.codeList = []
110 self.azimuthList = []
110 self.azimuthList = []
111 self.zenithList = []
111 self.zenithList = []
112
112
113 class GenericData(object):
113 class GenericData(object):
114
114
115 flagNoData = True
115 flagNoData = True
116
116
117 def copy(self, inputObj=None):
117 def copy(self, inputObj=None):
118
118
119 if inputObj == None:
119 if inputObj == None:
120 return copy.deepcopy(self)
120 return copy.deepcopy(self)
121
121
122 for key in inputObj.__dict__.keys():
122 for key in inputObj.__dict__.keys():
123
123
124 attribute = inputObj.__dict__[key]
124 attribute = inputObj.__dict__[key]
125
125
126 #If this attribute is a tuple or list
126 #If this attribute is a tuple or list
127 if type(inputObj.__dict__[key]) in (tuple, list):
127 if type(inputObj.__dict__[key]) in (tuple, list):
128 self.__dict__[key] = attribute[:]
128 self.__dict__[key] = attribute[:]
129 continue
129 continue
130
130
131 #If this attribute is another object or instance
131 #If this attribute is another object or instance
132 if hasattr(attribute, '__dict__'):
132 if hasattr(attribute, '__dict__'):
133 self.__dict__[key] = attribute.copy()
133 self.__dict__[key] = attribute.copy()
134 continue
134 continue
135
135
136 self.__dict__[key] = inputObj.__dict__[key]
136 self.__dict__[key] = inputObj.__dict__[key]
137
137
138 def deepcopy(self):
138 def deepcopy(self):
139
139
140 return copy.deepcopy(self)
140 return copy.deepcopy(self)
141
141
142 def isEmpty(self):
142 def isEmpty(self):
143
143
144 return self.flagNoData
144 return self.flagNoData
145
145
146 class JROData(GenericData):
146 class JROData(GenericData):
147
147
148 # m_BasicHeader = BasicHeader()
148 # m_BasicHeader = BasicHeader()
149 # m_ProcessingHeader = ProcessingHeader()
149 # m_ProcessingHeader = ProcessingHeader()
150
150
151 systemHeaderObj = SystemHeader()
151 systemHeaderObj = SystemHeader()
152
152
153 radarControllerHeaderObj = RadarControllerHeader()
153 radarControllerHeaderObj = RadarControllerHeader()
154
154
155 # data = None
155 # data = None
156
156
157 type = None
157 type = None
158
158
159 datatype = None #dtype but in string
159 datatype = None #dtype but in string
160
160
161 # dtype = None
161 # dtype = None
162
162
163 # nChannels = None
163 # nChannels = None
164
164
165 # nHeights = None
165 # nHeights = None
166
166
167 nProfiles = None
167 nProfiles = None
168
168
169 heightList = None
169 heightList = None
170
170
171 channelList = None
171 channelList = None
172
172
173 flagDiscontinuousBlock = False
173 flagDiscontinuousBlock = False
174
174
175 useLocalTime = False
175 useLocalTime = False
176
176
177 utctime = None
177 utctime = None
178
178
179 timeZone = None
179 timeZone = None
180
180
181 dstFlag = None
181 dstFlag = None
182
182
183 errorCount = None
183 errorCount = None
184
184
185 blocksize = None
185 blocksize = None
186
186
187 # nCode = None
187 # nCode = None
188 #
188 #
189 # nBaud = None
189 # nBaud = None
190 #
190 #
191 # code = None
191 # code = None
192
192
193 flagDecodeData = False #asumo q la data no esta decodificada
193 flagDecodeData = False #asumo q la data no esta decodificada
194
194
195 flagDeflipData = False #asumo q la data no esta sin flip
195 flagDeflipData = False #asumo q la data no esta sin flip
196
196
197 flagShiftFFT = False
197 flagShiftFFT = False
198
198
199 # ippSeconds = None
199 # ippSeconds = None
200
200
201 # timeInterval = None
201 # timeInterval = None
202
202
203 nCohInt = None
203 nCohInt = None
204
204
205 # noise = None
205 # noise = None
206
206
207 windowOfFilter = 1
207 windowOfFilter = 1
208
208
209 #Speed of ligth
209 #Speed of ligth
210 C = 3e8
210 C = 3e8
211
211
212 frequency = 49.92e6
212 frequency = 49.92e6
213
213
214 realtime = False
214 realtime = False
215
215
216 beacon_heiIndexList = None
216 beacon_heiIndexList = None
217
217
218 last_block = None
218 last_block = None
219
219
220 blocknow = None
220 blocknow = None
221
221
222 azimuth = None
222 azimuth = None
223
223
224 zenith = None
224 zenith = None
225
225
226 beam = Beam()
226 beam = Beam()
227
227
228 profileIndex = None
228 profileIndex = None
229
229
230 def getNoise(self):
230 def getNoise(self):
231
231
232 raise NotImplementedError
232 raise NotImplementedError
233
233
234 def getNChannels(self):
234 def getNChannels(self):
235
235
236 return len(self.channelList)
236 return len(self.channelList)
237
237
238 def getChannelIndexList(self):
238 def getChannelIndexList(self):
239
239
240 return range(self.nChannels)
240 return range(self.nChannels)
241
241
242 def getNHeights(self):
242 def getNHeights(self):
243
243
244 return len(self.heightList)
244 return len(self.heightList)
245
245
246 def getHeiRange(self, extrapoints=0):
246 def getHeiRange(self, extrapoints=0):
247
247
248 heis = self.heightList
248 heis = self.heightList
249 # deltah = self.heightList[1] - self.heightList[0]
249 # deltah = self.heightList[1] - self.heightList[0]
250 #
250 #
251 # heis.append(self.heightList[-1])
251 # heis.append(self.heightList[-1])
252
252
253 return heis
253 return heis
254
254
255 def getDeltaH(self):
255 def getDeltaH(self):
256
256
257 delta = self.heightList[1] - self.heightList[0]
257 delta = self.heightList[1] - self.heightList[0]
258
258
259 return delta
259 return delta
260
260
261 def getltctime(self):
261 def getltctime(self):
262
262
263 if self.useLocalTime:
263 if self.useLocalTime:
264 return self.utctime - self.timeZone*60
264 return self.utctime - self.timeZone*60
265
265
266 return self.utctime
266 return self.utctime
267
267
268 def getDatatime(self):
268 def getDatatime(self):
269
269
270 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
270 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
271 return datatimeValue
271 return datatimeValue
272
272
273 def getTimeRange(self):
273 def getTimeRange(self):
274
274
275 datatime = []
275 datatime = []
276
276
277 datatime.append(self.ltctime)
277 datatime.append(self.ltctime)
278 datatime.append(self.ltctime + self.timeInterval+1)
278 datatime.append(self.ltctime + self.timeInterval+1)
279
279
280 datatime = numpy.array(datatime)
280 datatime = numpy.array(datatime)
281
281
282 return datatime
282 return datatime
283
283
284 def getFmaxTimeResponse(self):
284 def getFmaxTimeResponse(self):
285
285
286 period = (10**-6)*self.getDeltaH()/(0.15)
286 period = (10**-6)*self.getDeltaH()/(0.15)
287
287
288 PRF = 1./(period * self.nCohInt)
288 PRF = 1./(period * self.nCohInt)
289
289
290 fmax = PRF
290 fmax = PRF
291
291
292 return fmax
292 return fmax
293
293
294 def getFmax(self):
294 def getFmax(self):
295
295
296 PRF = 1./(self.ippSeconds * self.nCohInt)
296 PRF = 1./(self.ippSeconds * self.nCohInt)
297
297
298 fmax = PRF
298 fmax = PRF
299
299
300 return fmax
300 return fmax
301
301
302 def getVmax(self):
302 def getVmax(self):
303
303
304 _lambda = self.C/self.frequency
304 _lambda = self.C/self.frequency
305
305
306 vmax = self.getFmax() * _lambda/2
306 vmax = self.getFmax() * _lambda/2
307
307
308 return vmax
308 return vmax
309
309
310 def get_ippSeconds(self):
310 def get_ippSeconds(self):
311 '''
311 '''
312 '''
312 '''
313 return self.radarControllerHeaderObj.ippSeconds
313 return self.radarControllerHeaderObj.ippSeconds
314
314
315 def set_ippSeconds(self, ippSeconds):
315 def set_ippSeconds(self, ippSeconds):
316 '''
316 '''
317 '''
317 '''
318
318
319 self.radarControllerHeaderObj.ippSeconds = ippSeconds
319 self.radarControllerHeaderObj.ippSeconds = ippSeconds
320
320
321 return
321 return
322
322
323 def get_dtype(self):
323 def get_dtype(self):
324 '''
324 '''
325 '''
325 '''
326 return getNumpyDtype(self.datatype)
326 return getNumpyDtype(self.datatype)
327
327
328 def set_dtype(self, numpyDtype):
328 def set_dtype(self, numpyDtype):
329 '''
329 '''
330 '''
330 '''
331
331
332 self.datatype = getDataTypeCode(numpyDtype)
332 self.datatype = getDataTypeCode(numpyDtype)
333
333
334 def get_code(self):
334 def get_code(self):
335 '''
335 '''
336 '''
336 '''
337 return self.radarControllerHeaderObj.code
337 return self.radarControllerHeaderObj.code
338
338
339 def set_code(self, code):
339 def set_code(self, code):
340 '''
340 '''
341 '''
341 '''
342 self.radarControllerHeaderObj.code = code
342 self.radarControllerHeaderObj.code = code
343
343
344 return
344 return
345
345
346 def get_ncode(self):
346 def get_ncode(self):
347 '''
347 '''
348 '''
348 '''
349 return self.radarControllerHeaderObj.nCode
349 return self.radarControllerHeaderObj.nCode
350
350
351 def set_ncode(self, nCode):
351 def set_ncode(self, nCode):
352 '''
352 '''
353 '''
353 '''
354 self.radarControllerHeaderObj.nCode = nCode
354 self.radarControllerHeaderObj.nCode = nCode
355
355
356 return
356 return
357
357
358 def get_nbaud(self):
358 def get_nbaud(self):
359 '''
359 '''
360 '''
360 '''
361 return self.radarControllerHeaderObj.nBaud
361 return self.radarControllerHeaderObj.nBaud
362
362
363 def set_nbaud(self, nBaud):
363 def set_nbaud(self, nBaud):
364 '''
364 '''
365 '''
365 '''
366 self.radarControllerHeaderObj.nBaud = nBaud
366 self.radarControllerHeaderObj.nBaud = nBaud
367
367
368 return
368 return
369
369
370 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
370 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
371 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
371 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
372 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
372 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
373 #noise = property(getNoise, "I'm the 'nHeights' property.")
373 #noise = property(getNoise, "I'm the 'nHeights' property.")
374 datatime = property(getDatatime, "I'm the 'datatime' property")
374 datatime = property(getDatatime, "I'm the 'datatime' property")
375 ltctime = property(getltctime, "I'm the 'ltctime' property")
375 ltctime = property(getltctime, "I'm the 'ltctime' property")
376 ippSeconds = property(get_ippSeconds, set_ippSeconds)
376 ippSeconds = property(get_ippSeconds, set_ippSeconds)
377 dtype = property(get_dtype, set_dtype)
377 dtype = property(get_dtype, set_dtype)
378 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
378 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
379 code = property(get_code, set_code)
379 code = property(get_code, set_code)
380 nCode = property(get_ncode, set_ncode)
380 nCode = property(get_ncode, set_ncode)
381 nBaud = property(get_nbaud, set_nbaud)
381 nBaud = property(get_nbaud, set_nbaud)
382
382
383 class Voltage(JROData):
383 class Voltage(JROData):
384
384
385 #data es un numpy array de 2 dmensiones (canales, alturas)
385 #data es un numpy array de 2 dmensiones (canales, alturas)
386 data = None
386 data = None
387
387
388 def __init__(self):
388 def __init__(self):
389 '''
389 '''
390 Constructor
390 Constructor
391 '''
391 '''
392
392
393 self.useLocalTime = True
393 self.useLocalTime = True
394
394
395 self.radarControllerHeaderObj = RadarControllerHeader()
395 self.radarControllerHeaderObj = RadarControllerHeader()
396
396
397 self.systemHeaderObj = SystemHeader()
397 self.systemHeaderObj = SystemHeader()
398
398
399 self.type = "Voltage"
399 self.type = "Voltage"
400
400
401 self.data = None
401 self.data = None
402
402
403 # self.dtype = None
403 # self.dtype = None
404
404
405 # self.nChannels = 0
405 # self.nChannels = 0
406
406
407 # self.nHeights = 0
407 # self.nHeights = 0
408
408
409 self.nProfiles = None
409 self.nProfiles = None
410
410
411 self.heightList = None
411 self.heightList = None
412
412
413 self.channelList = None
413 self.channelList = None
414
414
415 # self.channelIndexList = None
415 # self.channelIndexList = None
416
416
417 self.flagNoData = True
417 self.flagNoData = True
418
418
419 self.flagDiscontinuousBlock = False
419 self.flagDiscontinuousBlock = False
420
420
421 self.utctime = None
421 self.utctime = None
422
422
423 self.timeZone = None
423 self.timeZone = None
424
424
425 self.dstFlag = None
425 self.dstFlag = None
426
426
427 self.errorCount = None
427 self.errorCount = None
428
428
429 self.nCohInt = None
429 self.nCohInt = None
430
430
431 self.blocksize = None
431 self.blocksize = None
432
432
433 self.flagDecodeData = False #asumo q la data no esta decodificada
433 self.flagDecodeData = False #asumo q la data no esta decodificada
434
434
435 self.flagDeflipData = False #asumo q la data no esta sin flip
435 self.flagDeflipData = False #asumo q la data no esta sin flip
436
436
437 self.flagShiftFFT = False
437 self.flagShiftFFT = False
438
438
439 self.flagDataAsBlock = False #Asumo que la data es leida perfil a perfil
439 self.flagDataAsBlock = False #Asumo que la data es leida perfil a perfil
440
440
441 self.profileIndex = 0
441 self.profileIndex = 0
442
442
443 def getNoisebyHildebrand(self, channel = None):
443 def getNoisebyHildebrand(self, channel = None):
444 """
444 """
445 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
445 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
446
446
447 Return:
447 Return:
448 noiselevel
448 noiselevel
449 """
449 """
450
450
451 if channel != None:
451 if channel != None:
452 data = self.data[channel]
452 data = self.data[channel]
453 nChannels = 1
453 nChannels = 1
454 else:
454 else:
455 data = self.data
455 data = self.data
456 nChannels = self.nChannels
456 nChannels = self.nChannels
457
457
458 noise = numpy.zeros(nChannels)
458 noise = numpy.zeros(nChannels)
459 power = data * numpy.conjugate(data)
459 power = data * numpy.conjugate(data)
460
460
461 for thisChannel in range(nChannels):
461 for thisChannel in range(nChannels):
462 if nChannels == 1:
462 if nChannels == 1:
463 daux = power[:].real
463 daux = power[:].real
464 else:
464 else:
465 daux = power[thisChannel,:].real
465 daux = power[thisChannel,:].real
466 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
466 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
467
467
468 return noise
468 return noise
469
469
470 def getNoise(self, type = 1, channel = None):
470 def getNoise(self, type = 1, channel = None):
471
471
472 if type == 1:
472 if type == 1:
473 noise = self.getNoisebyHildebrand(channel)
473 noise = self.getNoisebyHildebrand(channel)
474
474
475 return noise
475 return noise
476
476
477 def getPower(self, channel = None):
477 def getPower(self, channel = None):
478
478
479 if channel != None:
479 if channel != None:
480 data = self.data[channel]
480 data = self.data[channel]
481 else:
481 else:
482 data = self.data
482 data = self.data
483
483
484 power = data * numpy.conjugate(data)
484 power = data * numpy.conjugate(data)
485 powerdB = 10*numpy.log10(power.real)
485 powerdB = 10*numpy.log10(power.real)
486 powerdB = numpy.squeeze(powerdB)
486 powerdB = numpy.squeeze(powerdB)
487
487
488 return powerdB
488 return powerdB
489
489
490 def getTimeInterval(self):
490 def getTimeInterval(self):
491
491
492 timeInterval = self.ippSeconds * self.nCohInt
492 timeInterval = self.ippSeconds * self.nCohInt
493
493
494 return timeInterval
494 return timeInterval
495
495
496 noise = property(getNoise, "I'm the 'nHeights' property.")
496 noise = property(getNoise, "I'm the 'nHeights' property.")
497 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
497 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
498
498
499 class Spectra(JROData):
499 class Spectra(JROData):
500
500
501 #data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
501 #data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
502 data_spc = None
502 data_spc = None
503
503
504 #data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
504 #data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
505 data_cspc = None
505 data_cspc = None
506
506
507 #data dc es un numpy array de 2 dmensiones (canales, alturas)
507 #data dc es un numpy array de 2 dmensiones (canales, alturas)
508 data_dc = None
508 data_dc = None
509
509
510 #data power
510 #data power
511 data_pwr = None
511 data_pwr = None
512
512
513 nFFTPoints = None
513 nFFTPoints = None
514
514
515 # nPairs = None
515 # nPairs = None
516
516
517 pairsList = None
517 pairsList = None
518
518
519 nIncohInt = None
519 nIncohInt = None
520
520
521 wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia
521 wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia
522
522
523 nCohInt = None #se requiere para determinar el valor de timeInterval
523 nCohInt = None #se requiere para determinar el valor de timeInterval
524
524
525 ippFactor = None
525 ippFactor = None
526
526
527 profileIndex = 0
527 profileIndex = 0
528
528
529 plotting = "spectra"
529 plotting = "spectra"
530
530
531 def __init__(self):
531 def __init__(self):
532 '''
532 '''
533 Constructor
533 Constructor
534 '''
534 '''
535
535
536 self.useLocalTime = True
536 self.useLocalTime = True
537
537
538 self.radarControllerHeaderObj = RadarControllerHeader()
538 self.radarControllerHeaderObj = RadarControllerHeader()
539
539
540 self.systemHeaderObj = SystemHeader()
540 self.systemHeaderObj = SystemHeader()
541
541
542 self.type = "Spectra"
542 self.type = "Spectra"
543
543
544 # self.data = None
544 # self.data = None
545
545
546 # self.dtype = None
546 # self.dtype = None
547
547
548 # self.nChannels = 0
548 # self.nChannels = 0
549
549
550 # self.nHeights = 0
550 # self.nHeights = 0
551
551
552 self.nProfiles = None
552 self.nProfiles = None
553
553
554 self.heightList = None
554 self.heightList = None
555
555
556 self.channelList = None
556 self.channelList = None
557
557
558 # self.channelIndexList = None
558 # self.channelIndexList = None
559
559
560 self.pairsList = None
560 self.pairsList = None
561
561
562 self.flagNoData = True
562 self.flagNoData = True
563
563
564 self.flagDiscontinuousBlock = False
564 self.flagDiscontinuousBlock = False
565
565
566 self.utctime = None
566 self.utctime = None
567
567
568 self.nCohInt = None
568 self.nCohInt = None
569
569
570 self.nIncohInt = None
570 self.nIncohInt = None
571
571
572 self.blocksize = None
572 self.blocksize = None
573
573
574 self.nFFTPoints = None
574 self.nFFTPoints = None
575
575
576 self.wavelength = None
576 self.wavelength = None
577
577
578 self.flagDecodeData = False #asumo q la data no esta decodificada
578 self.flagDecodeData = False #asumo q la data no esta decodificada
579
579
580 self.flagDeflipData = False #asumo q la data no esta sin flip
580 self.flagDeflipData = False #asumo q la data no esta sin flip
581
581
582 self.flagShiftFFT = False
582 self.flagShiftFFT = False
583
583
584 self.ippFactor = 1
584 self.ippFactor = 1
585
585
586 #self.noise = None
586 #self.noise = None
587
587
588 self.beacon_heiIndexList = []
588 self.beacon_heiIndexList = []
589
589
590 self.noise_estimation = None
590 self.noise_estimation = None
591
591
592
592
593 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
593 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
594 """
594 """
595 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
595 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
596
596
597 Return:
597 Return:
598 noiselevel
598 noiselevel
599 """
599 """
600
600
601 noise = numpy.zeros(self.nChannels)
601 noise = numpy.zeros(self.nChannels)
602
602
603 for channel in range(self.nChannels):
603 for channel in range(self.nChannels):
604 daux = self.data_spc[channel,xmin_index:xmax_index,ymin_index:ymax_index]
604 daux = self.data_spc[channel,xmin_index:xmax_index,ymin_index:ymax_index]
605 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
605 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
606
606
607 return noise
607 return noise
608
608
609 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
609 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
610
610
611 if self.noise_estimation is not None:
611 if self.noise_estimation is not None:
612 return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py
612 return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py
613 else:
613 else:
614 noise = self.getNoisebyHildebrand(xmin_index, xmax_index, ymin_index, ymax_index)
614 noise = self.getNoisebyHildebrand(xmin_index, xmax_index, ymin_index, ymax_index)
615 return noise
615 return noise
616
616
617 def getFreqRangeTimeResponse(self, extrapoints=0):
617 def getFreqRangeTimeResponse(self, extrapoints=0):
618
618
619 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints*self.ippFactor)
619 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints*self.ippFactor)
620 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
620 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
621
621
622 return freqrange
622 return freqrange
623
623
624 def getAcfRange(self, extrapoints=0):
624 def getAcfRange(self, extrapoints=0):
625
625
626 deltafreq = 10./(self.getFmax() / (self.nFFTPoints*self.ippFactor))
626 deltafreq = 10./(self.getFmax() / (self.nFFTPoints*self.ippFactor))
627 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
627 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
628
628
629 return freqrange
629 return freqrange
630
630
631 def getFreqRange(self, extrapoints=0):
631 def getFreqRange(self, extrapoints=0):
632
632
633 deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor)
633 deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor)
634 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
634 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
635
635
636 return freqrange
636 return freqrange
637
637
638 def getVelRange(self, extrapoints=0):
638 def getVelRange(self, extrapoints=0):
639
639
640 deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor)
640 deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor)
641 velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) #- deltav/2
641 velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) #- deltav/2
642
642
643 return velrange
643 return velrange
644
644
645 def getNPairs(self):
645 def getNPairs(self):
646
646
647 return len(self.pairsList)
647 return len(self.pairsList)
648
648
649 def getPairsIndexList(self):
649 def getPairsIndexList(self):
650
650
651 return range(self.nPairs)
651 return range(self.nPairs)
652
652
653 def getNormFactor(self):
653 def getNormFactor(self):
654
654
655 pwcode = 1
655 pwcode = 1
656
656
657 if self.flagDecodeData:
657 if self.flagDecodeData:
658 pwcode = numpy.sum(self.code[0]**2)
658 pwcode = numpy.sum(self.code[0]**2)
659 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
659 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
660 normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
660 normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
661
661
662 return normFactor
662 return normFactor
663
663
664 def getFlagCspc(self):
664 def getFlagCspc(self):
665
665
666 if self.data_cspc is None:
666 if self.data_cspc is None:
667 return True
667 return True
668
668
669 return False
669 return False
670
670
671 def getFlagDc(self):
671 def getFlagDc(self):
672
672
673 if self.data_dc is None:
673 if self.data_dc is None:
674 return True
674 return True
675
675
676 return False
676 return False
677
677
678 def getTimeInterval(self):
678 def getTimeInterval(self):
679
679
680 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles
680 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles
681
681
682 return timeInterval
682 return timeInterval
683
683
684 def getPower(self):
684 def getPower(self):
685
685
686 factor = self.normFactor
686 factor = self.normFactor
687 z = self.data_spc/factor
687 z = self.data_spc/factor
688 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
688 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
689 avg = numpy.average(z, axis=1)
689 avg = numpy.average(z, axis=1)
690
690
691 return 10*numpy.log10(avg)
691 return 10*numpy.log10(avg)
692
692
693 def getCoherence(self, pairsList=None, phase=False):
693 def getCoherence(self, pairsList=None, phase=False):
694
694
695 z = []
695 z = []
696 if pairsList is None:
696 if pairsList is None:
697 pairsIndexList = self.pairsIndexList
697 pairsIndexList = self.pairsIndexList
698 else:
698 else:
699 pairsIndexList = []
699 pairsIndexList = []
700 for pair in pairsList:
700 for pair in pairsList:
701 if pair not in self.pairsList:
701 if pair not in self.pairsList:
702 raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair)
702 raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair)
703 pairsIndexList.append(self.pairsList.index(pair))
703 pairsIndexList.append(self.pairsList.index(pair))
704 for i in range(len(pairsIndexList)):
704 for i in range(len(pairsIndexList)):
705 pair = self.pairsList[pairsIndexList[i]]
705 pair = self.pairsList[pairsIndexList[i]]
706 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
706 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
707 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
707 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
708 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
708 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
709 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
709 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
710 if phase:
710 if phase:
711 data = numpy.arctan2(avgcoherenceComplex.imag,
711 data = numpy.arctan2(avgcoherenceComplex.imag,
712 avgcoherenceComplex.real)*180/numpy.pi
712 avgcoherenceComplex.real)*180/numpy.pi
713 else:
713 else:
714 data = numpy.abs(avgcoherenceComplex)
714 data = numpy.abs(avgcoherenceComplex)
715
715
716 z.append(data)
716 z.append(data)
717
717
718 return numpy.array(z)
718 return numpy.array(z)
719
719
720 def setValue(self, value):
720 def setValue(self, value):
721
721
722 print "This property should not be initialized"
722 print "This property should not be initialized"
723
723
724 return
724 return
725
725
726 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
726 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
727 pairsIndexList = property(getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
727 pairsIndexList = property(getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
728 normFactor = property(getNormFactor, setValue, "I'm the 'getNormFactor' property.")
728 normFactor = property(getNormFactor, setValue, "I'm the 'getNormFactor' property.")
729 flag_cspc = property(getFlagCspc, setValue)
729 flag_cspc = property(getFlagCspc, setValue)
730 flag_dc = property(getFlagDc, setValue)
730 flag_dc = property(getFlagDc, setValue)
731 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
731 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
732 timeInterval = property(getTimeInterval, setValue, "I'm the 'timeInterval' property")
732 timeInterval = property(getTimeInterval, setValue, "I'm the 'timeInterval' property")
733
733
734 class SpectraHeis(Spectra):
734 class SpectraHeis(Spectra):
735
735
736 data_spc = None
736 data_spc = None
737
737
738 data_cspc = None
738 data_cspc = None
739
739
740 data_dc = None
740 data_dc = None
741
741
742 nFFTPoints = None
742 nFFTPoints = None
743
743
744 # nPairs = None
744 # nPairs = None
745
745
746 pairsList = None
746 pairsList = None
747
747
748 nCohInt = None
748 nCohInt = None
749
749
750 nIncohInt = None
750 nIncohInt = None
751
751
752 def __init__(self):
752 def __init__(self):
753
753
754 self.radarControllerHeaderObj = RadarControllerHeader()
754 self.radarControllerHeaderObj = RadarControllerHeader()
755
755
756 self.systemHeaderObj = SystemHeader()
756 self.systemHeaderObj = SystemHeader()
757
757
758 self.type = "SpectraHeis"
758 self.type = "SpectraHeis"
759
759
760 # self.dtype = None
760 # self.dtype = None
761
761
762 # self.nChannels = 0
762 # self.nChannels = 0
763
763
764 # self.nHeights = 0
764 # self.nHeights = 0
765
765
766 self.nProfiles = None
766 self.nProfiles = None
767
767
768 self.heightList = None
768 self.heightList = None
769
769
770 self.channelList = None
770 self.channelList = None
771
771
772 # self.channelIndexList = None
772 # self.channelIndexList = None
773
773
774 self.flagNoData = True
774 self.flagNoData = True
775
775
776 self.flagDiscontinuousBlock = False
776 self.flagDiscontinuousBlock = False
777
777
778 # self.nPairs = 0
778 # self.nPairs = 0
779
779
780 self.utctime = None
780 self.utctime = None
781
781
782 self.blocksize = None
782 self.blocksize = None
783
783
784 self.profileIndex = 0
784 self.profileIndex = 0
785
785
786 self.nCohInt = 1
786 self.nCohInt = 1
787
787
788 self.nIncohInt = 1
788 self.nIncohInt = 1
789
789
790 def getNormFactor(self):
790 def getNormFactor(self):
791 pwcode = 1
791 pwcode = 1
792 if self.flagDecodeData:
792 if self.flagDecodeData:
793 pwcode = numpy.sum(self.code[0]**2)
793 pwcode = numpy.sum(self.code[0]**2)
794
794
795 normFactor = self.nIncohInt*self.nCohInt*pwcode
795 normFactor = self.nIncohInt*self.nCohInt*pwcode
796
796
797 return normFactor
797 return normFactor
798
798
799 def getTimeInterval(self):
799 def getTimeInterval(self):
800
800
801 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
801 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
802
802
803 return timeInterval
803 return timeInterval
804
804
805 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
805 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
806 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
806 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
807
807
808 class Fits(JROData):
808 class Fits(JROData):
809
809
810 heightList = None
810 heightList = None
811
811
812 channelList = None
812 channelList = None
813
813
814 flagNoData = True
814 flagNoData = True
815
815
816 flagDiscontinuousBlock = False
816 flagDiscontinuousBlock = False
817
817
818 useLocalTime = False
818 useLocalTime = False
819
819
820 utctime = None
820 utctime = None
821
821
822 timeZone = None
822 timeZone = None
823
823
824 # ippSeconds = None
824 # ippSeconds = None
825
825
826 # timeInterval = None
826 # timeInterval = None
827
827
828 nCohInt = None
828 nCohInt = None
829
829
830 nIncohInt = None
830 nIncohInt = None
831
831
832 noise = None
832 noise = None
833
833
834 windowOfFilter = 1
834 windowOfFilter = 1
835
835
836 #Speed of ligth
836 #Speed of ligth
837 C = 3e8
837 C = 3e8
838
838
839 frequency = 49.92e6
839 frequency = 49.92e6
840
840
841 realtime = False
841 realtime = False
842
842
843
843
844 def __init__(self):
844 def __init__(self):
845
845
846 self.type = "Fits"
846 self.type = "Fits"
847
847
848 self.nProfiles = None
848 self.nProfiles = None
849
849
850 self.heightList = None
850 self.heightList = None
851
851
852 self.channelList = None
852 self.channelList = None
853
853
854 # self.channelIndexList = None
854 # self.channelIndexList = None
855
855
856 self.flagNoData = True
856 self.flagNoData = True
857
857
858 self.utctime = None
858 self.utctime = None
859
859
860 self.nCohInt = 1
860 self.nCohInt = 1
861
861
862 self.nIncohInt = 1
862 self.nIncohInt = 1
863
863
864 self.useLocalTime = True
864 self.useLocalTime = True
865
865
866 self.profileIndex = 0
866 self.profileIndex = 0
867
867
868 # self.utctime = None
868 # self.utctime = None
869 # self.timeZone = None
869 # self.timeZone = None
870 # self.ltctime = None
870 # self.ltctime = None
871 # self.timeInterval = None
871 # self.timeInterval = None
872 # self.header = None
872 # self.header = None
873 # self.data_header = None
873 # self.data_header = None
874 # self.data = None
874 # self.data = None
875 # self.datatime = None
875 # self.datatime = None
876 # self.flagNoData = False
876 # self.flagNoData = False
877 # self.expName = ''
877 # self.expName = ''
878 # self.nChannels = None
878 # self.nChannels = None
879 # self.nSamples = None
879 # self.nSamples = None
880 # self.dataBlocksPerFile = None
880 # self.dataBlocksPerFile = None
881 # self.comments = ''
881 # self.comments = ''
882 #
882 #
883
883
884
884
885 def getltctime(self):
885 def getltctime(self):
886
886
887 if self.useLocalTime:
887 if self.useLocalTime:
888 return self.utctime - self.timeZone*60
888 return self.utctime - self.timeZone*60
889
889
890 return self.utctime
890 return self.utctime
891
891
892 def getDatatime(self):
892 def getDatatime(self):
893
893
894 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
894 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
895 return datatime
895 return datatime
896
896
897 def getTimeRange(self):
897 def getTimeRange(self):
898
898
899 datatime = []
899 datatime = []
900
900
901 datatime.append(self.ltctime)
901 datatime.append(self.ltctime)
902 datatime.append(self.ltctime + self.timeInterval)
902 datatime.append(self.ltctime + self.timeInterval)
903
903
904 datatime = numpy.array(datatime)
904 datatime = numpy.array(datatime)
905
905
906 return datatime
906 return datatime
907
907
908 def getHeiRange(self):
908 def getHeiRange(self):
909
909
910 heis = self.heightList
910 heis = self.heightList
911
911
912 return heis
912 return heis
913
913
914 def getNHeights(self):
914 def getNHeights(self):
915
915
916 return len(self.heightList)
916 return len(self.heightList)
917
917
918 def getNChannels(self):
918 def getNChannels(self):
919
919
920 return len(self.channelList)
920 return len(self.channelList)
921
921
922 def getChannelIndexList(self):
922 def getChannelIndexList(self):
923
923
924 return range(self.nChannels)
924 return range(self.nChannels)
925
925
926 def getNoise(self, type = 1):
926 def getNoise(self, type = 1):
927
927
928 #noise = numpy.zeros(self.nChannels)
928 #noise = numpy.zeros(self.nChannels)
929
929
930 if type == 1:
930 if type == 1:
931 noise = self.getNoisebyHildebrand()
931 noise = self.getNoisebyHildebrand()
932
932
933 if type == 2:
933 if type == 2:
934 noise = self.getNoisebySort()
934 noise = self.getNoisebySort()
935
935
936 if type == 3:
936 if type == 3:
937 noise = self.getNoisebyWindow()
937 noise = self.getNoisebyWindow()
938
938
939 return noise
939 return noise
940
940
941 def getTimeInterval(self):
941 def getTimeInterval(self):
942
942
943 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
943 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
944
944
945 return timeInterval
945 return timeInterval
946
946
947 datatime = property(getDatatime, "I'm the 'datatime' property")
947 datatime = property(getDatatime, "I'm the 'datatime' property")
948 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
948 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
949 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
949 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
950 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
950 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
951 noise = property(getNoise, "I'm the 'nHeights' property.")
951 noise = property(getNoise, "I'm the 'nHeights' property.")
952
952
953 ltctime = property(getltctime, "I'm the 'ltctime' property")
953 ltctime = property(getltctime, "I'm the 'ltctime' property")
954 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
954 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
955
955
956
956
957 class Correlation(JROData):
957 class Correlation(JROData):
958
958
959 noise = None
959 noise = None
960
960
961 SNR = None
961 SNR = None
962
962
963 #--------------------------------------------------
963 #--------------------------------------------------
964
964
965 mode = None
965 mode = None
966
966
967 split = False
967 split = False
968
968
969 data_cf = None
969 data_cf = None
970
970
971 lags = None
971 lags = None
972
972
973 lagRange = None
973 lagRange = None
974
974
975 pairsList = None
975 pairsList = None
976
976
977 normFactor = None
977 normFactor = None
978
978
979 #--------------------------------------------------
979 #--------------------------------------------------
980
980
981 # calculateVelocity = None
981 # calculateVelocity = None
982
982
983 nLags = None
983 nLags = None
984
984
985 nPairs = None
985 nPairs = None
986
986
987 nAvg = None
987 nAvg = None
988
988
989
989
990 def __init__(self):
990 def __init__(self):
991 '''
991 '''
992 Constructor
992 Constructor
993 '''
993 '''
994 self.radarControllerHeaderObj = RadarControllerHeader()
994 self.radarControllerHeaderObj = RadarControllerHeader()
995
995
996 self.systemHeaderObj = SystemHeader()
996 self.systemHeaderObj = SystemHeader()
997
997
998 self.type = "Correlation"
998 self.type = "Correlation"
999
999
1000 self.data = None
1000 self.data = None
1001
1001
1002 self.dtype = None
1002 self.dtype = None
1003
1003
1004 self.nProfiles = None
1004 self.nProfiles = None
1005
1005
1006 self.heightList = None
1006 self.heightList = None
1007
1007
1008 self.channelList = None
1008 self.channelList = None
1009
1009
1010 self.flagNoData = True
1010 self.flagNoData = True
1011
1011
1012 self.flagDiscontinuousBlock = False
1012 self.flagDiscontinuousBlock = False
1013
1013
1014 self.utctime = None
1014 self.utctime = None
1015
1015
1016 self.timeZone = None
1016 self.timeZone = None
1017
1017
1018 self.dstFlag = None
1018 self.dstFlag = None
1019
1019
1020 self.errorCount = None
1020 self.errorCount = None
1021
1021
1022 self.blocksize = None
1022 self.blocksize = None
1023
1023
1024 self.flagDecodeData = False #asumo q la data no esta decodificada
1024 self.flagDecodeData = False #asumo q la data no esta decodificada
1025
1025
1026 self.flagDeflipData = False #asumo q la data no esta sin flip
1026 self.flagDeflipData = False #asumo q la data no esta sin flip
1027
1027
1028 self.pairsList = None
1028 self.pairsList = None
1029
1029
1030 self.nPoints = None
1030 self.nPoints = None
1031
1031
1032 def getPairsList(self):
1032 def getPairsList(self):
1033
1033
1034 return self.pairsList
1034 return self.pairsList
1035
1035
1036 def getNoise(self, mode = 2):
1036 def getNoise(self, mode = 2):
1037
1037
1038 indR = numpy.where(self.lagR == 0)[0][0]
1038 indR = numpy.where(self.lagR == 0)[0][0]
1039 indT = numpy.where(self.lagT == 0)[0][0]
1039 indT = numpy.where(self.lagT == 0)[0][0]
1040
1040
1041 jspectra0 = self.data_corr[:,:,indR,:]
1041 jspectra0 = self.data_corr[:,:,indR,:]
1042 jspectra = copy.copy(jspectra0)
1042 jspectra = copy.copy(jspectra0)
1043
1043
1044 num_chan = jspectra.shape[0]
1044 num_chan = jspectra.shape[0]
1045 num_hei = jspectra.shape[2]
1045 num_hei = jspectra.shape[2]
1046
1046
1047 freq_dc = jspectra.shape[1]/2
1047 freq_dc = jspectra.shape[1]/2
1048 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
1048 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
1049
1049
1050 if ind_vel[0]<0:
1050 if ind_vel[0]<0:
1051 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
1051 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
1052
1052
1053 if mode == 1:
1053 if mode == 1:
1054 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
1054 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
1055
1055
1056 if mode == 2:
1056 if mode == 2:
1057
1057
1058 vel = numpy.array([-2,-1,1,2])
1058 vel = numpy.array([-2,-1,1,2])
1059 xx = numpy.zeros([4,4])
1059 xx = numpy.zeros([4,4])
1060
1060
1061 for fil in range(4):
1061 for fil in range(4):
1062 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
1062 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
1063
1063
1064 xx_inv = numpy.linalg.inv(xx)
1064 xx_inv = numpy.linalg.inv(xx)
1065 xx_aux = xx_inv[0,:]
1065 xx_aux = xx_inv[0,:]
1066
1066
1067 for ich in range(num_chan):
1067 for ich in range(num_chan):
1068 yy = jspectra[ich,ind_vel,:]
1068 yy = jspectra[ich,ind_vel,:]
1069 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
1069 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
1070
1070
1071 junkid = jspectra[ich,freq_dc,:]<=0
1071 junkid = jspectra[ich,freq_dc,:]<=0
1072 cjunkid = sum(junkid)
1072 cjunkid = sum(junkid)
1073
1073
1074 if cjunkid.any():
1074 if cjunkid.any():
1075 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
1075 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
1076
1076
1077 noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:]
1077 noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:]
1078
1078
1079 return noise
1079 return noise
1080
1080
1081 def getTimeInterval(self):
1081 def getTimeInterval(self):
1082
1082
1083 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1083 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1084
1084
1085 return timeInterval
1085 return timeInterval
1086
1086
1087 def splitFunctions(self):
1087 def splitFunctions(self):
1088
1088
1089 pairsList = self.pairsList
1089 pairsList = self.pairsList
1090 ccf_pairs = []
1090 ccf_pairs = []
1091 acf_pairs = []
1091 acf_pairs = []
1092 ccf_ind = []
1092 ccf_ind = []
1093 acf_ind = []
1093 acf_ind = []
1094 for l in range(len(pairsList)):
1094 for l in range(len(pairsList)):
1095 chan0 = pairsList[l][0]
1095 chan0 = pairsList[l][0]
1096 chan1 = pairsList[l][1]
1096 chan1 = pairsList[l][1]
1097
1097
1098 #Obteniendo pares de Autocorrelacion
1098 #Obteniendo pares de Autocorrelacion
1099 if chan0 == chan1:
1099 if chan0 == chan1:
1100 acf_pairs.append(chan0)
1100 acf_pairs.append(chan0)
1101 acf_ind.append(l)
1101 acf_ind.append(l)
1102 else:
1102 else:
1103 ccf_pairs.append(pairsList[l])
1103 ccf_pairs.append(pairsList[l])
1104 ccf_ind.append(l)
1104 ccf_ind.append(l)
1105
1105
1106 data_acf = self.data_cf[acf_ind]
1106 data_acf = self.data_cf[acf_ind]
1107 data_ccf = self.data_cf[ccf_ind]
1107 data_ccf = self.data_cf[ccf_ind]
1108
1108
1109 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1109 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1110
1110
1111 def getNormFactor(self):
1111 def getNormFactor(self):
1112 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1112 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1113 acf_pairs = numpy.array(acf_pairs)
1113 acf_pairs = numpy.array(acf_pairs)
1114 normFactor = numpy.zeros((self.nPairs,self.nHeights))
1114 normFactor = numpy.zeros((self.nPairs,self.nHeights))
1115
1115
1116 for p in range(self.nPairs):
1116 for p in range(self.nPairs):
1117 pair = self.pairsList[p]
1117 pair = self.pairsList[p]
1118
1118
1119 ch0 = pair[0]
1119 ch0 = pair[0]
1120 ch1 = pair[1]
1120 ch1 = pair[1]
1121
1121
1122 ch0_max = numpy.max(data_acf[acf_pairs==ch0,:,:], axis=1)
1122 ch0_max = numpy.max(data_acf[acf_pairs==ch0,:,:], axis=1)
1123 ch1_max = numpy.max(data_acf[acf_pairs==ch1,:,:], axis=1)
1123 ch1_max = numpy.max(data_acf[acf_pairs==ch1,:,:], axis=1)
1124 normFactor[p,:] = numpy.sqrt(ch0_max*ch1_max)
1124 normFactor[p,:] = numpy.sqrt(ch0_max*ch1_max)
1125
1125
1126 return normFactor
1126 return normFactor
1127
1127
1128 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1128 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1129 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1129 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1130
1130
1131 class Parameters(Spectra):
1131 class Parameters(Spectra):
1132
1132
1133 experimentInfo = None #Information about the experiment
1133 experimentInfo = None #Information about the experiment
1134
1134
1135 #Information from previous data
1135 #Information from previous data
1136
1136
1137 inputUnit = None #Type of data to be processed
1137 inputUnit = None #Type of data to be processed
1138
1138
1139 operation = None #Type of operation to parametrize
1139 operation = None #Type of operation to parametrize
1140
1140
1141 #normFactor = None #Normalization Factor
1141 #normFactor = None #Normalization Factor
1142
1142
1143 groupList = None #List of Pairs, Groups, etc
1143 groupList = None #List of Pairs, Groups, etc
1144
1144
1145 #Parameters
1145 #Parameters
1146
1146
1147 data_param = None #Parameters obtained
1147 data_param = None #Parameters obtained
1148
1148
1149 data_pre = None #Data Pre Parametrization
1149 data_pre = None #Data Pre Parametrization
1150
1150
1151 data_SNR = None #Signal to Noise Ratio
1151 data_SNR = None #Signal to Noise Ratio
1152
1152
1153 # heightRange = None #Heights
1153 # heightRange = None #Heights
1154
1154
1155 abscissaList = None #Abscissa, can be velocities, lags or time
1155 abscissaList = None #Abscissa, can be velocities, lags or time
1156
1156
1157 # noise = None #Noise Potency
1157 # noise = None #Noise Potency
1158
1158
1159 utctimeInit = None #Initial UTC time
1159 utctimeInit = None #Initial UTC time
1160
1160
1161 paramInterval = None #Time interval to calculate Parameters in seconds
1161 paramInterval = None #Time interval to calculate Parameters in seconds
1162
1162
1163 useLocalTime = True
1163 useLocalTime = True
1164
1164
1165 #Fitting
1165 #Fitting
1166
1166
1167 data_error = None #Error of the estimation
1167 data_error = None #Error of the estimation
1168
1168
1169 constants = None
1169 constants = None
1170
1170
1171 library = None
1171 library = None
1172
1172
1173 #Output signal
1173 #Output signal
1174
1174
1175 outputInterval = None #Time interval to calculate output signal in seconds
1175 outputInterval = None #Time interval to calculate output signal in seconds
1176
1176
1177 data_output = None #Out signal
1177 data_output = None #Out signal
1178
1178
1179 nAvg = None
1179 nAvg = None
1180
1180
1181 noise_estimation = None
1181 noise_estimation = None
1182
1182
1183
1183
1184 def __init__(self):
1184 def __init__(self):
1185 '''
1185 '''
1186 Constructor
1186 Constructor
1187 '''
1187 '''
1188 self.radarControllerHeaderObj = RadarControllerHeader()
1188 self.radarControllerHeaderObj = RadarControllerHeader()
1189
1189
1190 self.systemHeaderObj = SystemHeader()
1190 self.systemHeaderObj = SystemHeader()
1191
1191
1192 self.type = "Parameters"
1192 self.type = "Parameters"
1193
1193
1194 def getTimeRange1(self, interval):
1194 def getTimeRange1(self, interval):
1195
1195
1196 datatime = []
1196 datatime = []
1197
1197
1198 if self.useLocalTime:
1198 if self.useLocalTime:
1199 time1 = self.utctimeInit - self.timeZone*60
1199 time1 = self.utctimeInit - self.timeZone*60
1200 else:
1200 else:
1201 time1 = self.utctimeInit
1201 time1 = self.utctimeInit
1202
1202
1203 datatime.append(time1)
1203 datatime.append(time1)
1204 datatime.append(time1 + interval)
1204 datatime.append(time1 + interval)
1205 datatime = numpy.array(datatime)
1205 datatime = numpy.array(datatime)
1206
1206
1207 return datatime
1207 return datatime
1208
1208
1209 def getTimeInterval(self):
1209 def getTimeInterval(self):
1210
1210
1211 if hasattr(self, 'timeInterval1'):
1211 if hasattr(self, 'timeInterval1'):
1212 return self.timeInterval1
1212 return self.timeInterval1
1213 else:
1213 else:
1214 return self.paramInterval
1214 return self.paramInterval
1215
1215
1216 def getNoise(self):
1216 def getNoise(self):
1217
1217
1218 return self.spc_noise
1218 return self.spc_noise
1219
1219
1220 timeInterval = property(getTimeInterval)
1220 timeInterval = property(getTimeInterval)
This diff has been collapsed as it changes many lines, (1208 lines changed) Show them Hide them
@@ -1,964 +1,782
1
1
2 import os
2 import os
3 import zmq
4 import time
3 import time
5 import numpy
4 import glob
6 import datetime
5 import datetime
7 import numpy as np
6 from multiprocessing import Process
7
8 import zmq
9 import numpy
8 import matplotlib
10 import matplotlib
9 import glob
10 matplotlib.use('TkAgg')
11 import matplotlib.pyplot as plt
11 import matplotlib.pyplot as plt
12 from mpl_toolkits.axes_grid1 import make_axes_locatable
12 from mpl_toolkits.axes_grid1 import make_axes_locatable
13 from matplotlib.ticker import FuncFormatter, LinearLocator
13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
14 from multiprocessing import Process
15
14
16 from schainpy.model.proc.jroproc_base import Operation
15 from schainpy.model.proc.jroproc_base import Operation
17
16 from schainpy.utils import log
18 plt.ion()
19
17
20 func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M'))
18 func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M'))
21 fromtimestamp = lambda x, mintime : (datetime.datetime.utcfromtimestamp(mintime).replace(hour=(x + 5), minute=0) - d1970).total_seconds()
22
19
20 d1970 = datetime.datetime(1970, 1, 1)
23
21
24 d1970 = datetime.datetime(1970,1,1)
25
22
26 class PlotData(Operation, Process):
23 class PlotData(Operation, Process):
24 '''
25 Base class for Schain plotting operations
26 '''
27
27
28 CODE = 'Figure'
28 CODE = 'Figure'
29 colormap = 'jro'
29 colormap = 'jro'
30 bgcolor = 'white'
30 CONFLATE = False
31 CONFLATE = False
31 __MAXNUMX = 80
32 __MAXNUMX = 80
32 __missing = 1E30
33 __missing = 1E30
33
34
34 def __init__(self, **kwargs):
35 def __init__(self, **kwargs):
35
36
36 Operation.__init__(self, plot=True, **kwargs)
37 Operation.__init__(self, plot=True, **kwargs)
37 Process.__init__(self)
38 Process.__init__(self)
38 self.kwargs['code'] = self.CODE
39 self.kwargs['code'] = self.CODE
39 self.mp = False
40 self.mp = False
40 self.dataOut = None
41 self.data = None
41 self.isConfig = False
42 self.isConfig = False
42 self.figure = None
43 self.figures = []
43 self.axes = []
44 self.axes = []
45 self.cb_axes = []
44 self.localtime = kwargs.pop('localtime', True)
46 self.localtime = kwargs.pop('localtime', True)
45 self.show = kwargs.get('show', True)
47 self.show = kwargs.get('show', True)
46 self.save = kwargs.get('save', False)
48 self.save = kwargs.get('save', False)
47 self.colormap = kwargs.get('colormap', self.colormap)
49 self.colormap = kwargs.get('colormap', self.colormap)
48 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
50 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
49 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
51 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
50 self.showprofile = kwargs.get('showprofile', True)
52 self.colormaps = kwargs.get('colormaps', None)
51 self.title = kwargs.get('wintitle', '')
53 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
54 self.showprofile = kwargs.get('showprofile', False)
55 self.title = kwargs.get('wintitle', self.CODE.upper())
56 self.cb_label = kwargs.get('cb_label', None)
57 self.cb_labels = kwargs.get('cb_labels', None)
52 self.xaxis = kwargs.get('xaxis', 'frequency')
58 self.xaxis = kwargs.get('xaxis', 'frequency')
53 self.zmin = kwargs.get('zmin', None)
59 self.zmin = kwargs.get('zmin', None)
54 self.zmax = kwargs.get('zmax', None)
60 self.zmax = kwargs.get('zmax', None)
61 self.zlimits = kwargs.get('zlimits', None)
55 self.xmin = kwargs.get('xmin', None)
62 self.xmin = kwargs.get('xmin', None)
63 if self.xmin is not None:
64 self.xmin += 5
56 self.xmax = kwargs.get('xmax', None)
65 self.xmax = kwargs.get('xmax', None)
57 self.xrange = kwargs.get('xrange', 24)
66 self.xrange = kwargs.get('xrange', 24)
58 self.ymin = kwargs.get('ymin', None)
67 self.ymin = kwargs.get('ymin', None)
59 self.ymax = kwargs.get('ymax', None)
68 self.ymax = kwargs.get('ymax', None)
60 self.__MAXNUMY = kwargs.get('decimation', 5000)
69 self.xlabel = kwargs.get('xlabel', None)
61 self.throttle_value = 5
70 self.__MAXNUMY = kwargs.get('decimation', 100)
62 self.times = []
71 self.showSNR = kwargs.get('showSNR', False)
63 #self.interactive = self.kwargs['parent']
72 self.oneFigure = kwargs.get('oneFigure', True)
73 self.width = kwargs.get('width', None)
74 self.height = kwargs.get('height', None)
75 self.colorbar = kwargs.get('colorbar', True)
76 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
77 self.titles = ['' for __ in range(16)]
78
79 def __setup(self):
80 '''
81 Common setup for all figures, here figures and axes are created
82 '''
83
84 self.setup()
85
86 if self.width is None:
87 self.width = 8
64
88
89 self.figures = []
90 self.axes = []
91 self.cb_axes = []
92 self.pf_axes = []
93 self.cmaps = []
94
95 size = '15%' if self.ncols==1 else '30%'
96 pad = '4%' if self.ncols==1 else '8%'
97
98 if self.oneFigure:
99 if self.height is None:
100 self.height = 1.4*self.nrows + 1
101 fig = plt.figure(figsize=(self.width, self.height),
102 edgecolor='k',
103 facecolor='w')
104 self.figures.append(fig)
105 for n in range(self.nplots):
106 ax = fig.add_subplot(self.nrows, self.ncols, n+1)
107 ax.tick_params(labelsize=8)
108 ax.firsttime = True
109 self.axes.append(ax)
110 if self.showprofile:
111 cax = self.__add_axes(ax, size=size, pad=pad)
112 cax.tick_params(labelsize=8)
113 self.pf_axes.append(cax)
114 else:
115 if self.height is None:
116 self.height = 3
117 for n in range(self.nplots):
118 fig = plt.figure(figsize=(self.width, self.height),
119 edgecolor='k',
120 facecolor='w')
121 ax = fig.add_subplot(1, 1, 1)
122 ax.tick_params(labelsize=8)
123 ax.firsttime = True
124 self.figures.append(fig)
125 self.axes.append(ax)
126 if self.showprofile:
127 cax = self.__add_axes(ax, size=size, pad=pad)
128 cax.tick_params(labelsize=8)
129 self.pf_axes.append(cax)
130
131 for n in range(self.nrows):
132 if self.colormaps is not None:
133 cmap = plt.get_cmap(self.colormaps[n])
134 else:
135 cmap = plt.get_cmap(self.colormap)
136 cmap.set_bad(self.bgcolor, 1.)
137 self.cmaps.append(cmap)
138
139 def __add_axes(self, ax, size='30%', pad='8%'):
65 '''
140 '''
66 this new parameter is created to plot data from varius channels at different figures
141 Add new axes to the given figure
67 1. crear una lista de figuras donde se puedan plotear las figuras,
68 2. dar las opciones de configuracion a cada figura, estas opciones son iguales para ambas figuras
69 3. probar?
70 '''
142 '''
71 self.ind_plt_ch = kwargs.get('ind_plt_ch', False)
143 divider = make_axes_locatable(ax)
72 self.figurelist = None
144 nax = divider.new_horizontal(size=size, pad=pad)
145 ax.figure.add_axes(nax)
146 return nax
73
147
74
148
75 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
149 def setup(self):
150 '''
151 This method should be implemented in the child class, the following
152 attributes should be set:
153
154 self.nrows: number of rows
155 self.ncols: number of cols
156 self.nplots: number of plots (channels or pairs)
157 self.ylabel: label for Y axes
158 self.titles: list of axes title
159
160 '''
161 raise(NotImplementedError, 'Implement this method in child class')
76
162
163 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
164 '''
165 Create a masked array for missing data
166 '''
77 if x_buffer.shape[0] < 2:
167 if x_buffer.shape[0] < 2:
78 return x_buffer, y_buffer, z_buffer
168 return x_buffer, y_buffer, z_buffer
79
169
80 deltas = x_buffer[1:] - x_buffer[0:-1]
170 deltas = x_buffer[1:] - x_buffer[0:-1]
81 x_median = np.median(deltas)
171 x_median = numpy.median(deltas)
82
172
83 index = np.where(deltas > 5*x_median)
173 index = numpy.where(deltas > 5*x_median)
84
174
85 if len(index[0]) != 0:
175 if len(index[0]) != 0:
86 z_buffer[::, index[0], ::] = self.__missing
176 z_buffer[::, index[0], ::] = self.__missing
87 z_buffer = np.ma.masked_inside(z_buffer,
177 z_buffer = numpy.ma.masked_inside(z_buffer,
88 0.99*self.__missing,
178 0.99*self.__missing,
89 1.01*self.__missing)
179 1.01*self.__missing)
90
180
91 return x_buffer, y_buffer, z_buffer
181 return x_buffer, y_buffer, z_buffer
92
182
93 def decimate(self):
183 def decimate(self):
94
184
95 # dx = int(len(self.x)/self.__MAXNUMX) + 1
185 # dx = int(len(self.x)/self.__MAXNUMX) + 1
96 dy = int(len(self.y)/self.__MAXNUMY) + 1
186 dy = int(len(self.y)/self.__MAXNUMY) + 1
97
187
98 # x = self.x[::dx]
188 # x = self.x[::dx]
99 x = self.x
189 x = self.x
100 y = self.y[::dy]
190 y = self.y[::dy]
101 z = self.z[::, ::, ::dy]
191 z = self.z[::, ::, ::dy]
102
192
103 return x, y, z
193 return x, y, z
104
194
105 '''
195 def format(self):
106 JM:
196 '''
107 elimana las otras imagenes generadas debido a que lso workers no llegan en orden y le pueden
197 Set min and max values, labels, ticks and titles
108 poner otro tiempo a la figura q no necesariamente es el ultimo.
198 '''
109 Solo se realiza cuando termina la imagen.
110 Problemas:
111
199
112 File "/home/ci-81/workspace/schainv2.3/schainpy/model/graphics/jroplot_data.py", line 145, in __plot
200 if self.xmin is None:
113 for n, eachfigure in enumerate(self.figurelist):
201 xmin = self.min_time
114 TypeError: 'NoneType' object is not iterable
202 else:
203 if self.xaxis is 'time':
204 dt = datetime.datetime.fromtimestamp(self.min_time)
205 xmin = (datetime.datetime.combine(dt.date(),
206 datetime.time(int(self.xmin), 0, 0))-d1970).total_seconds()
207 else:
208 xmin = self.xmin
115
209
116 '''
210 if self.xmax is None:
117 def deleteanotherfiles(self):
211 xmax = xmin+self.xrange*60*60
118 figurenames=[]
212 else:
119 if self.figurelist != None:
213 if self.xaxis is 'time':
120 for n, eachfigure in enumerate(self.figurelist):
214 dt = datetime.datetime.fromtimestamp(self.min_time)
121 #add specific name for each channel in channelList
215 xmax = (datetime.datetime.combine(dt.date(),
122 ghostfigname = os.path.join(self.save, '{}_{}_{}'.format(self.titles[n].replace(' ',''),self.CODE,
216 datetime.time(int(self.xmax), 0, 0))-d1970).total_seconds()
123 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d')))
217 else:
124 figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n].replace(' ',''),self.CODE,
218 xmax = self.xmax
125 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
219
126
220 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
127 for ghostfigure in glob.glob(ghostfigname+'*'): #ghostfigure will adopt all posible names of figures
221 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
128 if ghostfigure != figname:
222
129 os.remove(ghostfigure)
223 ystep = 200 if ymax>= 800 else 100 if ymax>=400 else 50 if ymax>=200 else 20
130 print 'Removing GhostFigures:' , figname
224
131 else :
225 for n, ax in enumerate(self.axes):
132 '''Erasing ghost images for just on******************'''
226 if ax.firsttime:
133 ghostfigname = os.path.join(self.save, '{}_{}'.format(self.CODE,datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d')))
227 ax.set_facecolor(self.bgcolor)
134 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
228 ax.yaxis.set_major_locator(MultipleLocator(ystep))
135 for ghostfigure in glob.glob(ghostfigname+'*'): #ghostfigure will adopt all posible names of figures
229 if self.xaxis is 'time':
136 if ghostfigure != figname:
230 ax.xaxis.set_major_formatter(FuncFormatter(func))
137 os.remove(ghostfigure)
231 ax.xaxis.set_major_locator(LinearLocator(9))
138 print 'Removing GhostFigures:' , figname
232 if self.xlabel is not None:
233 ax.set_xlabel(self.xlabel)
234 ax.set_ylabel(self.ylabel)
235 ax.firsttime = False
236 if self.showprofile:
237 self.pf_axes[n].set_ylim(ymin, ymax)
238 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
239 self.pf_axes[n].set_xlabel('dB')
240 self.pf_axes[n].grid(b=True, axis='x')
241 [tick.set_visible(False) for tick in self.pf_axes[n].get_yticklabels()]
242 if self.colorbar:
243 cb = plt.colorbar(ax.plt, ax=ax, pad=0.02)
244 cb.ax.tick_params(labelsize=8)
245 if self.cb_label:
246 cb.set_label(self.cb_label, size=8)
247 elif self.cb_labels:
248 cb.set_label(self.cb_labels[n], size=8)
249
250 ax.set_title('{} - {} UTC'.format(
251 self.titles[n],
252 datetime.datetime.fromtimestamp(self.max_time).strftime('%H:%M:%S')),
253 size=8)
254 ax.set_xlim(xmin, xmax)
255 ax.set_ylim(ymin, ymax)
256
139
257
140 def __plot(self):
258 def __plot(self):
141
259 '''
142 print 'plotting...{}'.format(self.CODE)
260 '''
143 if self.ind_plt_ch is False : #standard
261 log.success('Plotting', self.name)
262
263 self.plot()
264 self.format()
265
266 for n, fig in enumerate(self.figures):
267 if self.nrows == 0 or self.nplots == 0:
268 log.warning('No data', self.name)
269 continue
144 if self.show:
270 if self.show:
145 self.figure.show()
271 fig.show()
146 self.plot()
272
147 plt.tight_layout()
273 fig.tight_layout()
148 self.figure.canvas.manager.set_window_title('{} {} - {}'.format(self.title, self.CODE.upper(),
274 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
149 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
275 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
150 else :
276 # fig.canvas.draw()
151 print 'len(self.figurelist): ',len(self.figurelist)
277
152 for n, eachfigure in enumerate(self.figurelist):
278 if self.save and self.data.ended:
153 if self.show:
279 channels = range(self.nrows)
154 eachfigure.show()
280 if self.oneFigure:
155
281 label = ''
156 self.plot()
282 else:
157 eachfigure.tight_layout() # ajuste de cada subplot
283 label = '_{}'.format(channels[n])
158 eachfigure.canvas.manager.set_window_title('{} {} - {}'.format(self.title[n], self.CODE.upper(),
284 figname = os.path.join(
159 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
285 self.save,
160
286 '{}{}_{}.png'.format(
161 # if self.save:
287 self.CODE,
162 # if self.ind_plt_ch is False : #standard
288 label,
163 # figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
289 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')
164 # datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
290 )
165 # print 'Saving figure: {}'.format(figname)
291 )
166 # self.figure.savefig(figname)
167 # else :
168 # for n, eachfigure in enumerate(self.figurelist):
169 # #add specific name for each channel in channelList
170 # figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n],self.CODE,
171 # datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
172 #
173 # print 'Saving figure: {}'.format(figname)
174 # eachfigure.savefig(figname)
175
176 if self.ind_plt_ch is False :
177 self.figure.canvas.draw()
178 else :
179 for eachfigure in self.figurelist:
180 eachfigure.canvas.draw()
181
182 if self.save:
183 if self.ind_plt_ch is False : #standard
184 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
185 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
186 print 'Saving figure: {}'.format(figname)
292 print 'Saving figure: {}'.format(figname)
187 self.figure.savefig(figname)
293 fig.savefig(figname)
188 else :
189 for n, eachfigure in enumerate(self.figurelist):
190 #add specific name for each channel in channelList
191 figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n].replace(' ',''),self.CODE,
192 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
193
194 print 'Saving figure: {}'.format(figname)
195 eachfigure.savefig(figname)
196
197
294
198 def plot(self):
295 def plot(self):
199
296 '''
200 print 'plotting...{}'.format(self.CODE.upper())
297 '''
201 return
298 raise(NotImplementedError, 'Implement this method in child class')
202
299
203 def run(self):
300 def run(self):
204
301
205 print '[Starting] {}'.format(self.name)
302 log.success('Starting', self.name)
206
303
207 context = zmq.Context()
304 context = zmq.Context()
208 receiver = context.socket(zmq.SUB)
305 receiver = context.socket(zmq.SUB)
209 receiver.setsockopt(zmq.SUBSCRIBE, '')
306 receiver.setsockopt(zmq.SUBSCRIBE, '')
210 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
307 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
211
308
212 if 'server' in self.kwargs['parent']:
309 if 'server' in self.kwargs['parent']:
213 receiver.connect('ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
310 receiver.connect('ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
214 else:
311 else:
215 receiver.connect("ipc:///tmp/zmq.plots")
312 receiver.connect("ipc:///tmp/zmq.plots")
216
217 seconds_passed = 0
218
313
219 while True:
314 while True:
220 try:
315 try:
221 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)#flags=zmq.NOBLOCK
316 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
222 self.started = self.data['STARTED']
317
223 self.dataOut = self.data['dataOut']
318 self.min_time = self.data.times[0]
224
319 self.max_time = self.data.times[-1]
225 if (len(self.times) < len(self.data['times']) and not self.started and self.data['ENDED']):
226 continue
227
228 self.times = self.data['times']
229 self.times.sort()
230 self.throttle_value = self.data['throttle']
231 self.min_time = self.times[0]
232 self.max_time = self.times[-1]
233
320
234 if self.isConfig is False:
321 if self.isConfig is False:
235 print 'setting up'
322 self.__setup()
236 self.setup()
237 self.isConfig = True
323 self.isConfig = True
238 self.__plot()
324
239
325 self.__plot()
240 if self.data['ENDED'] is True:
241 print '********GRAPHIC ENDED********'
242 self.ended = True
243 self.isConfig = False
244 self.__plot()
245 self.deleteanotherfiles() #CLPDG
246 elif seconds_passed >= self.data['throttle']:
247 print 'passed', seconds_passed
248 self.__plot()
249 seconds_passed = 0
250
326
251 except zmq.Again as e:
327 except zmq.Again as e:
252 print 'Waiting for data...'
328 log.log('Waiting for data...')
253 plt.pause(2)
329 if self.data:
254 seconds_passed += 2
330 plt.pause(self.data.throttle)
331 else:
332 time.sleep(2)
255
333
256 def close(self):
334 def close(self):
257 if self.dataOut:
335 if self.data:
258 self.__plot()
336 self.__plot()
259
337
260
338
261 class PlotSpectraData(PlotData):
339 class PlotSpectraData(PlotData):
340 '''
341 Plot for Spectra data
342 '''
262
343
263 CODE = 'spc'
344 CODE = 'spc'
264 colormap = 'jro'
345 colormap = 'jro'
265 CONFLATE = False
266
346
267 def setup(self):
347 def setup(self):
268
348 self.nplots = len(self.data.channels)
269 ncolspan = 1
349 self.ncols = int(numpy.sqrt(self.nplots)+ 0.9)
270 colspan = 1
350 self.nrows = int((1.0*self.nplots/self.ncols) + 0.9)
271 self.ncols = int(numpy.sqrt(self.dataOut.nChannels)+0.9)
351 self.width = 3.4*self.ncols
272 self.nrows = int(self.dataOut.nChannels*1./self.ncols + 0.9)
352 self.height = 3*self.nrows
273 self.width = 3.6*self.ncols
353 self.cb_label = 'dB'
274 self.height = 3.2*self.nrows
354 if self.showprofile:
275 if self.showprofile:
355 self.width += 0.8*self.ncols
276 ncolspan = 3
277 colspan = 2
278 self.width += 1.2*self.ncols
279
356
280 self.ylabel = 'Range [Km]'
357 self.ylabel = 'Range [Km]'
281 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
282
283 if self.figure is None:
284 self.figure = plt.figure(figsize=(self.width, self.height),
285 edgecolor='k',
286 facecolor='w')
287 else:
288 self.figure.clf()
289
290 n = 0
291 for y in range(self.nrows):
292 for x in range(self.ncols):
293 if n >= self.dataOut.nChannels:
294 break
295 ax = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan), 1, colspan)
296 if self.showprofile:
297 ax.ax_profile = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan+colspan), 1, 1)
298
299 ax.firsttime = True
300 self.axes.append(ax)
301 n += 1
302
358
303 def plot(self):
359 def plot(self):
304
305 if self.xaxis == "frequency":
360 if self.xaxis == "frequency":
306 x = self.dataOut.getFreqRange(1)/1000.
361 x = self.data.xrange[0]
307 xlabel = "Frequency (kHz)"
362 self.xlabel = "Frequency (kHz)"
308 elif self.xaxis == "time":
363 elif self.xaxis == "time":
309 x = self.dataOut.getAcfRange(1)
364 x = self.data.xrange[1]
310 xlabel = "Time (ms)"
365 self.xlabel = "Time (ms)"
311 else:
366 else:
312 x = self.dataOut.getVelRange(1)
367 x = self.data.xrange[2]
313 xlabel = "Velocity (m/s)"
368 self.xlabel = "Velocity (m/s)"
369
370 if self.CODE == 'spc_mean':
371 x = self.data.xrange[2]
372 self.xlabel = "Velocity (m/s)"
314
373
315 y = self.dataOut.getHeiRange()
374 self.titles = []
316 z = self.data[self.CODE]
317
375
376 y = self.data.heights
377 self.y = y
378 z = self.data['spc']
379
318 for n, ax in enumerate(self.axes):
380 for n, ax in enumerate(self.axes):
381 noise = self.data['noise'][n][-1]
382 if self.CODE == 'spc_mean':
383 mean = self.data['mean'][n][-1]
319 if ax.firsttime:
384 if ax.firsttime:
320 self.xmax = self.xmax if self.xmax else np.nanmax(x)
385 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
321 self.xmin = self.xmin if self.xmin else -self.xmax
386 self.xmin = self.xmin if self.xmin else -self.xmax
322 self.ymin = self.ymin if self.ymin else np.nanmin(y)
387 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
323 self.ymax = self.ymax if self.ymax else np.nanmax(y)
388 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
324 self.zmin = self.zmin if self.zmin else np.nanmin(z)
389 ax.plt = ax.pcolormesh(x, y, z[n].T,
325 self.zmax = self.zmax if self.zmax else np.nanmax(z)
390 vmin=self.zmin,
326 ax.plot = ax.pcolormesh(x, y, z[n].T,
391 vmax=self.zmax,
327 vmin=self.zmin,
392 cmap=plt.get_cmap(self.colormap)
328 vmax=self.zmax,
393 )
329 cmap=plt.get_cmap(self.colormap)
330 )
331 divider = make_axes_locatable(ax)
332 cax = divider.new_horizontal(size='3%', pad=0.05)
333 self.figure.add_axes(cax)
334 plt.colorbar(ax.plot, cax)
335
336 ax.set_xlim(self.xmin, self.xmax)
337 ax.set_ylim(self.ymin, self.ymax)
338
339 ax.set_ylabel(self.ylabel)
340 ax.set_xlabel(xlabel)
341
342 ax.firsttime = False
343
394
344 if self.showprofile:
395 if self.showprofile:
345 ax.plot_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
396 ax.plt_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], y)[0]
346 ax.ax_profile.set_xlim(self.zmin, self.zmax)
397 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
347 ax.ax_profile.set_ylim(self.ymin, self.ymax)
398 color="k", linestyle="dashed", lw=1)[0]
348 ax.ax_profile.set_xlabel('dB')
399 if self.CODE == 'spc_mean':
349 ax.ax_profile.grid(b=True, axis='x')
400 ax.plt_mean = ax.plot(mean, y, color='k')[0]
350 ax.plot_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
351 color="k", linestyle="dashed", lw=2)[0]
352 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
353 else:
401 else:
354 ax.plot.set_array(z[n].T.ravel())
402 ax.plt.set_array(z[n].T.ravel())
355 if self.showprofile:
403 if self.showprofile:
356 ax.plot_profile.set_data(self.data['rti'][self.max_time][n], y)
404 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
357 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
405 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
406 if self.CODE == 'spc_mean':
407 ax.plt_mean.set_data(mean, y)
358
408
359 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
409 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
360 size=8)
361 self.saveTime = self.max_time
410 self.saveTime = self.max_time
362
411
363
412
364 class PlotCrossSpectraData(PlotData):
413 class PlotCrossSpectraData(PlotData):
365
414
366 CODE = 'cspc'
415 CODE = 'cspc'
367 zmin_coh = None
416 zmin_coh = None
368 zmax_coh = None
417 zmax_coh = None
369 zmin_phase = None
418 zmin_phase = None
370 zmax_phase = None
419 zmax_phase = None
371 CONFLATE = False
372
420
373 def setup(self):
421 def setup(self):
374
422
375 ncolspan = 1
423 self.ncols = 4
376 colspan = 1
424 self.nrows = len(self.data.pairs)
377 self.ncols = 2
425 self.nplots = self.nrows*4
378 self.nrows = self.dataOut.nPairs
426 self.width = 3.4*self.ncols
379 self.width = 3.6*self.ncols
427 self.height = 3*self.nrows
380 self.height = 3.2*self.nrows
381
382 self.ylabel = 'Range [Km]'
428 self.ylabel = 'Range [Km]'
383 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
429 self.showprofile = False
384
385 if self.figure is None:
386 self.figure = plt.figure(figsize=(self.width, self.height),
387 edgecolor='k',
388 facecolor='w')
389 else:
390 self.figure.clf()
391
392 for y in range(self.nrows):
393 for x in range(self.ncols):
394 ax = plt.subplot2grid((self.nrows, self.ncols), (y, x), 1, 1)
395 ax.firsttime = True
396 self.axes.append(ax)
397
430
398 def plot(self):
431 def plot(self):
399
432
400 if self.xaxis == "frequency":
433 if self.xaxis == "frequency":
401 x = self.dataOut.getFreqRange(1)/1000.
434 x = self.data.xrange[0]
402 xlabel = "Frequency (kHz)"
435 self.xlabel = "Frequency (kHz)"
403 elif self.xaxis == "time":
436 elif self.xaxis == "time":
404 x = self.dataOut.getAcfRange(1)
437 x = self.data.xrange[1]
405 xlabel = "Time (ms)"
438 self.xlabel = "Time (ms)"
406 else:
439 else:
407 x = self.dataOut.getVelRange(1)
440 x = self.data.xrange[2]
408 xlabel = "Velocity (m/s)"
441 self.xlabel = "Velocity (m/s)"
442
443 self.titles = []
409
444
410 y = self.dataOut.getHeiRange()
445 y = self.data.heights
411 z_coh = self.data['cspc_coh']
446 self.y = y
412 z_phase = self.data['cspc_phase']
447 spc = self.data['spc']
448 cspc = self.data['cspc']
413
449
414 for n in range(self.nrows):
450 for n in range(self.nrows):
415 ax = self.axes[2*n]
451 noise = self.data['noise'][n][-1]
416 ax1 = self.axes[2*n+1]
452 pair = self.data.pairs[n]
453 ax = self.axes[4*n]
454 ax3 = self.axes[4*n+3]
417 if ax.firsttime:
455 if ax.firsttime:
418 self.xmax = self.xmax if self.xmax else np.nanmax(x)
456 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
419 self.xmin = self.xmin if self.xmin else -self.xmax
457 self.xmin = self.xmin if self.xmin else -self.xmax
420 self.ymin = self.ymin if self.ymin else np.nanmin(y)
458 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
421 self.ymax = self.ymax if self.ymax else np.nanmax(y)
459 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
422 self.zmin_coh = self.zmin_coh if self.zmin_coh else 0.0
460 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
423 self.zmax_coh = self.zmax_coh if self.zmax_coh else 1.0
461 vmin=self.zmin,
424 self.zmin_phase = self.zmin_phase if self.zmin_phase else -180
462 vmax=self.zmax,
425 self.zmax_phase = self.zmax_phase if self.zmax_phase else 180
463 cmap=plt.get_cmap(self.colormap)
426
464 )
427 ax.plot = ax.pcolormesh(x, y, z_coh[n].T,
428 vmin=self.zmin_coh,
429 vmax=self.zmax_coh,
430 cmap=plt.get_cmap(self.colormap_coh)
431 )
432 divider = make_axes_locatable(ax)
433 cax = divider.new_horizontal(size='3%', pad=0.05)
434 self.figure.add_axes(cax)
435 plt.colorbar(ax.plot, cax)
436
437 ax.set_xlim(self.xmin, self.xmax)
438 ax.set_ylim(self.ymin, self.ymax)
439
440 ax.set_ylabel(self.ylabel)
441 ax.set_xlabel(xlabel)
442 ax.firsttime = False
443
444 ax1.plot = ax1.pcolormesh(x, y, z_phase[n].T,
445 vmin=self.zmin_phase,
446 vmax=self.zmax_phase,
447 cmap=plt.get_cmap(self.colormap_phase)
448 )
449 divider = make_axes_locatable(ax1)
450 cax = divider.new_horizontal(size='3%', pad=0.05)
451 self.figure.add_axes(cax)
452 plt.colorbar(ax1.plot, cax)
453
454 ax1.set_xlim(self.xmin, self.xmax)
455 ax1.set_ylim(self.ymin, self.ymax)
456
457 ax1.set_ylabel(self.ylabel)
458 ax1.set_xlabel(xlabel)
459 ax1.firsttime = False
460 else:
465 else:
461 ax.plot.set_array(z_coh[n].T.ravel())
466 ax.plt.set_array(spc[pair[0]].T.ravel())
462 ax1.plot.set_array(z_phase[n].T.ravel())
467 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
463
464 ax.set_title('Coherence Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
465 ax1.set_title('Phase Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
466 self.saveTime = self.max_time
467
468
468
469 class PlotSpectraMeanData(PlotSpectraData):
469 ax = self.axes[4*n+1]
470
470 if ax.firsttime:
471 CODE = 'spc_mean'
471 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
472 colormap = 'jet'
473
474 def plot(self):
475
476 if self.xaxis == "frequency":
477 x = self.dataOut.getFreqRange(1)/1000.
478 xlabel = "Frequency (kHz)"
479 elif self.xaxis == "time":
480 x = self.dataOut.getAcfRange(1)
481 xlabel = "Time (ms)"
482 else:
483 x = self.dataOut.getVelRange(1)
484 xlabel = "Velocity (m/s)"
485
486 y = self.dataOut.getHeiRange()
487 z = self.data['spc']
488 mean = self.data['mean'][self.max_time]
489
490 for n, ax in enumerate(self.axes):
491
492 if ax.firsttime:
493 self.xmax = self.xmax if self.xmax else np.nanmax(x)
494 self.xmin = self.xmin if self.xmin else -self.xmax
495 self.ymin = self.ymin if self.ymin else np.nanmin(y)
496 self.ymax = self.ymax if self.ymax else np.nanmax(y)
497 self.zmin = self.zmin if self.zmin else np.nanmin(z)
498 self.zmax = self.zmax if self.zmax else np.nanmax(z)
499 ax.plt = ax.pcolormesh(x, y, z[n].T,
500 vmin=self.zmin,
472 vmin=self.zmin,
501 vmax=self.zmax,
473 vmax=self.zmax,
502 cmap=plt.get_cmap(self.colormap)
474 cmap=plt.get_cmap(self.colormap)
503 )
475 )
504 ax.plt_dop = ax.plot(mean[n], y,
505 color='k')[0]
506
507 divider = make_axes_locatable(ax)
508 cax = divider.new_horizontal(size='3%', pad=0.05)
509 self.figure.add_axes(cax)
510 plt.colorbar(ax.plt, cax)
511
512 ax.set_xlim(self.xmin, self.xmax)
513 ax.set_ylim(self.ymin, self.ymax)
514
515 ax.set_ylabel(self.ylabel)
516 ax.set_xlabel(xlabel)
517
518 ax.firsttime = False
519
520 if self.showprofile:
521 ax.plt_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
522 ax.ax_profile.set_xlim(self.zmin, self.zmax)
523 ax.ax_profile.set_ylim(self.ymin, self.ymax)
524 ax.ax_profile.set_xlabel('dB')
525 ax.ax_profile.grid(b=True, axis='x')
526 ax.plt_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
527 color="k", linestyle="dashed", lw=2)[0]
528 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
529 else:
476 else:
530 ax.plt.set_array(z[n].T.ravel())
477 ax.plt.set_array(spc[pair[1]].T.ravel())
531 ax.plt_dop.set_data(mean[n], y)
478 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
532 if self.showprofile:
479
533 ax.plt_profile.set_data(self.data['rti'][self.max_time][n], y)
480 out = cspc[n]/numpy.sqrt(spc[pair[0]]*spc[pair[1]])
534 ax.plt_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
481 coh = numpy.abs(out)
482 phase = numpy.arctan2(out.imag, out.real)*180/numpy.pi
483
484 ax = self.axes[4*n+2]
485 if ax.firsttime:
486 ax.plt = ax.pcolormesh(x, y, coh.T,
487 vmin=0,
488 vmax=1,
489 cmap=plt.get_cmap(self.colormap_coh)
490 )
491 else:
492 ax.plt.set_array(coh.T.ravel())
493 self.titles.append('Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
535
494
536 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
495 ax = self.axes[4*n+3]
537 size=8)
496 if ax.firsttime:
497 ax.plt = ax.pcolormesh(x, y, phase.T,
498 vmin=-180,
499 vmax=180,
500 cmap=plt.get_cmap(self.colormap_phase)
501 )
502 else:
503 ax.plt.set_array(phase.T.ravel())
504 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
505
538 self.saveTime = self.max_time
506 self.saveTime = self.max_time
539
507
540
508
509 class PlotSpectraMeanData(PlotSpectraData):
510 '''
511 Plot for Spectra and Mean
512 '''
513 CODE = 'spc_mean'
514 colormap = 'jro'
515
516
541 class PlotRTIData(PlotData):
517 class PlotRTIData(PlotData):
518 '''
519 Plot for RTI data
520 '''
542
521
543 CODE = 'rti'
522 CODE = 'rti'
544 colormap = 'jro'
523 colormap = 'jro'
545
524
546 def setup(self):
525 def setup(self):
547 self.ncols = 1
526 self.xaxis = 'time'
548 self.nrows = self.dataOut.nChannels
527 self.ncols = 1
549 self.width = 10
528 self.nrows = len(self.data.channels)
550 #TODO : arreglar la altura de la figura, esta hardcodeada.
529 self.nplots = len(self.data.channels)
551 #Se arreglo, testear!
552 if self.ind_plt_ch:
553 self.height = 3.2#*self.nrows if self.nrows<6 else 12
554 else:
555 self.height = 2.2*self.nrows if self.nrows<6 else 12
556
557 '''
558 if self.nrows==1:
559 self.height += 1
560 '''
561 self.ylabel = 'Range [Km]'
530 self.ylabel = 'Range [Km]'
562 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
531 self.cb_label = 'dB'
563
532 self.titles = ['{} Channel {}'.format(self.CODE.upper(), x) for x in range(self.nrows)]
564 '''
565 Logica:
566 1) Si la variable ind_plt_ch es True, va a crear mas de 1 figura
567 2) guardamos "Figures" en una lista y "axes" en otra, quizas se deberia guardar el
568 axis dentro de "Figures" como un diccionario.
569 '''
570 if self.ind_plt_ch is False: #standard mode
571
572 if self.figure is None: #solo para la priemra vez
573 self.figure = plt.figure(figsize=(self.width, self.height),
574 edgecolor='k',
575 facecolor='w')
576 else:
577 self.figure.clf()
578 self.axes = []
579
580
581 for n in range(self.nrows):
582 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
583 #ax = self.figure(n+1)
584 ax.firsttime = True
585 self.axes.append(ax)
586
587 else : #append one figure foreach channel in channelList
588 if self.figurelist == None:
589 self.figurelist = []
590 for n in range(self.nrows):
591 self.figure = plt.figure(figsize=(self.width, self.height),
592 edgecolor='k',
593 facecolor='w')
594 #add always one subplot
595 self.figurelist.append(self.figure)
596
597 else : # cada dia nuevo limpia el axes, pero mantiene el figure
598 for eachfigure in self.figurelist:
599 eachfigure.clf() # eliminaria todas las figuras de la lista?
600 self.axes = []
601
602 for eachfigure in self.figurelist:
603 ax = eachfigure.add_subplot(1,1,1) #solo 1 axis por figura
604 #ax = self.figure(n+1)
605 ax.firsttime = True
606 #Cada figura tiene un distinto puntero
607 self.axes.append(ax)
608 #plt.close(eachfigure)
609
610
533
611 def plot(self):
534 def plot(self):
535 self.x = self.data.times
536 self.y = self.data.heights
537 self.z = self.data[self.CODE]
538 self.z = numpy.ma.masked_invalid(self.z)
612
539
613 if self.ind_plt_ch is False: #standard mode
540 for n, ax in enumerate(self.axes):
614 self.x = np.array(self.times)
541 x, y, z = self.fill_gaps(*self.decimate())
615 self.y = self.dataOut.getHeiRange()
542 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
616 self.z = []
543 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
617
544 if ax.firsttime:
618 for ch in range(self.nrows):
545 ax.plt = ax.pcolormesh(x, y, z[n].T,
619 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
546 vmin=self.zmin,
620
547 vmax=self.zmax,
621 self.z = np.array(self.z)
548 cmap=plt.get_cmap(self.colormap)
622 for n, ax in enumerate(self.axes):
549 )
623 x, y, z = self.fill_gaps(*self.decimate())
550 if self.showprofile:
624 if self.xmin is None:
551 ax.plot_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], self.y)[0]
625 xmin = self.min_time
552 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
626 else:
553 color="k", linestyle="dashed", lw=1)[0]
627 xmin = fromtimestamp(int(self.xmin), self.min_time)
554 else:
628 if self.xmax is None:
555 ax.collections.remove(ax.collections[0])
629 xmax = xmin + self.xrange*60*60
556 ax.plt = ax.pcolormesh(x, y, z[n].T,
630 else:
557 vmin=self.zmin,
631 xmax = xmin + (self.xmax - self.xmin) * 60 * 60
558 vmax=self.zmax,
632 self.zmin = self.zmin if self.zmin else np.min(self.z)
559 cmap=plt.get_cmap(self.colormap)
633 self.zmax = self.zmax if self.zmax else np.max(self.z)
560 )
634 if ax.firsttime:
561 if self.showprofile:
635 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
562 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
636 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
563 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y)
637 plot = ax.pcolormesh(x, y, z[n].T,
638 vmin=self.zmin,
639 vmax=self.zmax,
640 cmap=plt.get_cmap(self.colormap)
641 )
642 divider = make_axes_locatable(ax)
643 cax = divider.new_horizontal(size='2%', pad=0.05)
644 self.figure.add_axes(cax)
645 plt.colorbar(plot, cax)
646 ax.set_ylim(self.ymin, self.ymax)
647 ax.xaxis.set_major_formatter(FuncFormatter(func))
648 ax.xaxis.set_major_locator(LinearLocator(6))
649 ax.set_ylabel(self.ylabel)
650 # if self.xmin is None:
651 # xmin = self.min_time
652 # else:
653 # xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
654 # datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
655
656 ax.set_xlim(xmin, xmax)
657 ax.firsttime = False
658 else:
659 ax.collections.remove(ax.collections[0])
660 ax.set_xlim(xmin, xmax)
661 plot = ax.pcolormesh(x, y, z[n].T,
662 vmin=self.zmin,
663 vmax=self.zmax,
664 cmap=plt.get_cmap(self.colormap)
665 )
666 ax.set_title('{} {}'.format(self.titles[n],
667 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
668 size=8)
669
670 self.saveTime = self.min_time
671 else :
672 self.x = np.array(self.times)
673 self.y = self.dataOut.getHeiRange()
674 self.z = []
675
676 for ch in range(self.nrows):
677 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
678
679 self.z = np.array(self.z)
680 for n, eachfigure in enumerate(self.figurelist): #estaba ax in axes
681
682 x, y, z = self.fill_gaps(*self.decimate())
683 xmin = self.min_time
684 xmax = xmin+self.xrange*60*60
685 self.zmin = self.zmin if self.zmin else np.min(self.z)
686 self.zmax = self.zmax if self.zmax else np.max(self.z)
687 if self.axes[n].firsttime:
688 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
689 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
690 plot = self.axes[n].pcolormesh(x, y, z[n].T,
691 vmin=self.zmin,
692 vmax=self.zmax,
693 cmap=plt.get_cmap(self.colormap)
694 )
695 divider = make_axes_locatable(self.axes[n])
696 cax = divider.new_horizontal(size='2%', pad=0.05)
697 eachfigure.add_axes(cax)
698 #self.figure2.add_axes(cax)
699 plt.colorbar(plot, cax)
700 self.axes[n].set_ylim(self.ymin, self.ymax)
701
702 self.axes[n].xaxis.set_major_formatter(FuncFormatter(func))
703 self.axes[n].xaxis.set_major_locator(LinearLocator(6))
704
705 self.axes[n].set_ylabel(self.ylabel)
706
707 if self.xmin is None:
708 xmin = self.min_time
709 else:
710 xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
711 datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
712
713 self.axes[n].set_xlim(xmin, xmax)
714 self.axes[n].firsttime = False
715 else:
716 self.axes[n].collections.remove(self.axes[n].collections[0])
717 self.axes[n].set_xlim(xmin, xmax)
718 plot = self.axes[n].pcolormesh(x, y, z[n].T,
719 vmin=self.zmin,
720 vmax=self.zmax,
721 cmap=plt.get_cmap(self.colormap)
722 )
723 self.axes[n].set_title('{} {}'.format(self.titles[n],
724 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
725 size=8)
726
564
727 self.saveTime = self.min_time
565 self.saveTime = self.min_time
728
566
729
567
730 class PlotCOHData(PlotRTIData):
568 class PlotCOHData(PlotRTIData):
569 '''
570 Plot for Coherence data
571 '''
731
572
732 CODE = 'coh'
573 CODE = 'coh'
733
574
734 def setup(self):
575 def setup(self):
735
576 self.xaxis = 'time'
736 self.ncols = 1
577 self.ncols = 1
737 self.nrows = self.dataOut.nPairs
578 self.nrows = len(self.data.pairs)
738 self.width = 10
579 self.nplots = len(self.data.pairs)
739 self.height = 2.2*self.nrows if self.nrows<6 else 12
580 self.ylabel = 'Range [Km]'
740 self.ind_plt_ch = False #just for coherence and phase
581 if self.CODE == 'coh':
741 if self.nrows==1:
582 self.cb_label = ''
742 self.height += 1
583 self.titles = ['Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
743 self.ylabel = 'Range [Km]'
744 self.titles = ['{} Ch{} * Ch{}'.format(self.CODE.upper(), x[0], x[1]) for x in self.dataOut.pairsList]
745
746 if self.figure is None:
747 self.figure = plt.figure(figsize=(self.width, self.height),
748 edgecolor='k',
749 facecolor='w')
750 else:
584 else:
751 self.figure.clf()
585 self.cb_label = 'Degrees'
752 self.axes = []
586 self.titles = ['Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
753
587
754 for n in range(self.nrows):
588
755 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
589 class PlotPHASEData(PlotCOHData):
756 ax.firsttime = True
590 '''
757 self.axes.append(ax)
591 Plot for Phase map data
592 '''
593
594 CODE = 'phase'
595 colormap = 'seismic'
758
596
759
597
760 class PlotNoiseData(PlotData):
598 class PlotNoiseData(PlotData):
599 '''
600 Plot for noise
601 '''
602
761 CODE = 'noise'
603 CODE = 'noise'
762
604
763 def setup(self):
605 def setup(self):
764
606 self.xaxis = 'time'
765 self.ncols = 1
607 self.ncols = 1
766 self.nrows = 1
608 self.nrows = 1
767 self.width = 10
609 self.nplots = 1
768 self.height = 3.2
769 self.ylabel = 'Intensity [dB]'
610 self.ylabel = 'Intensity [dB]'
770 self.titles = ['Noise']
611 self.titles = ['Noise']
771
612 self.colorbar = False
772 if self.figure is None:
773 self.figure = plt.figure(figsize=(self.width, self.height),
774 edgecolor='k',
775 facecolor='w')
776 else:
777 self.figure.clf()
778 self.axes = []
779
780 self.ax = self.figure.add_subplot(self.nrows, self.ncols, 1)
781 self.ax.firsttime = True
782
613
783 def plot(self):
614 def plot(self):
784
615
785 x = self.times
616 x = self.data.times
786 xmin = self.min_time
617 xmin = self.min_time
787 xmax = xmin+self.xrange*60*60
618 xmax = xmin+self.xrange*60*60
788 if self.ax.firsttime:
619 Y = self.data[self.CODE]
789 for ch in self.dataOut.channelList:
620
790 y = [self.data[self.CODE][t][ch] for t in self.times]
621 if self.axes[0].firsttime:
791 self.ax.plot(x, y, lw=1, label='Ch{}'.format(ch))
622 for ch in self.data.channels:
792 self.ax.firsttime = False
623 y = Y[ch]
793 self.ax.xaxis.set_major_formatter(FuncFormatter(func))
624 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
794 self.ax.xaxis.set_major_locator(LinearLocator(6))
795 self.ax.set_ylabel(self.ylabel)
796 plt.legend()
625 plt.legend()
797 else:
626 else:
798 for ch in self.dataOut.channelList:
627 for ch in self.data.channels:
799 y = [self.data[self.CODE][t][ch] for t in self.times]
628 y = Y[ch]
800 self.ax.lines[ch].set_data(x, y)
629 self.axes[0].lines[ch].set_data(x, y)
801
630
802 self.ax.set_xlim(xmin, xmax)
631 self.ymin = numpy.nanmin(Y) - 5
803 self.ax.set_ylim(min(y)-5, max(y)+5)
632 self.ymax = numpy.nanmax(Y) + 5
804 self.saveTime = self.min_time
633 self.saveTime = self.min_time
805
634
806
635
807 class PlotWindProfilerData(PlotRTIData):
808
809 CODE = 'wind'
810 colormap = 'seismic'
811
812 def setup(self):
813 self.ncols = 1
814 self.nrows = self.dataOut.data_output.shape[0]
815 self.width = 10
816 self.height = 2.2*self.nrows
817 self.ylabel = 'Height [Km]'
818 self.titles = ['Zonal Wind' ,'Meridional Wind', 'Vertical Wind']
819 self.clabels = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
820 self.windFactor = [1, 1, 100]
821
822 if self.figure is None:
823 self.figure = plt.figure(figsize=(self.width, self.height),
824 edgecolor='k',
825 facecolor='w')
826 else:
827 self.figure.clf()
828 self.axes = []
829
830 for n in range(self.nrows):
831 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
832 ax.firsttime = True
833 self.axes.append(ax)
834
835 def plot(self):
836
837 self.x = np.array(self.times)
838 self.y = self.dataOut.heightList
839 self.z = []
840
841 for ch in range(self.nrows):
842 self.z.append([self.data['output'][t][ch] for t in self.times])
843
844 self.z = np.array(self.z)
845 self.z = numpy.ma.masked_invalid(self.z)
846
847 cmap=plt.get_cmap(self.colormap)
848 cmap.set_bad('black', 1.)
849
850 for n, ax in enumerate(self.axes):
851 x, y, z = self.fill_gaps(*self.decimate())
852 xmin = self.min_time
853 xmax = xmin+self.xrange*60*60
854 if ax.firsttime:
855 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
856 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
857 self.zmax = self.zmax if self.zmax else numpy.nanmax(abs(self.z[:-1, :]))
858 self.zmin = self.zmin if self.zmin else -self.zmax
859
860 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
861 vmin=self.zmin,
862 vmax=self.zmax,
863 cmap=cmap
864 )
865 divider = make_axes_locatable(ax)
866 cax = divider.new_horizontal(size='2%', pad=0.05)
867 self.figure.add_axes(cax)
868 cb = plt.colorbar(plot, cax)
869 cb.set_label(self.clabels[n])
870 ax.set_ylim(self.ymin, self.ymax)
871
872 ax.xaxis.set_major_formatter(FuncFormatter(func))
873 ax.xaxis.set_major_locator(LinearLocator(6))
874
875 ax.set_ylabel(self.ylabel)
876
877 ax.set_xlim(xmin, xmax)
878 ax.firsttime = False
879 else:
880 ax.collections.remove(ax.collections[0])
881 ax.set_xlim(xmin, xmax)
882 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
883 vmin=self.zmin,
884 vmax=self.zmax,
885 cmap=plt.get_cmap(self.colormap)
886 )
887 ax.set_title('{} {}'.format(self.titles[n],
888 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
889 size=8)
890
891 self.saveTime = self.min_time
892
893
894 class PlotSNRData(PlotRTIData):
636 class PlotSNRData(PlotRTIData):
637 '''
638 Plot for SNR Data
639 '''
640
895 CODE = 'snr'
641 CODE = 'snr'
896 colormap = 'jet'
642 colormap = 'jet'
897
643
644
898 class PlotDOPData(PlotRTIData):
645 class PlotDOPData(PlotRTIData):
646 '''
647 Plot for DOPPLER Data
648 '''
649
899 CODE = 'dop'
650 CODE = 'dop'
900 colormap = 'jet'
651 colormap = 'jet'
901
652
902
653
903 class PlotPHASEData(PlotCOHData):
904 CODE = 'phase'
905 colormap = 'seismic'
906
907
908 class PlotSkyMapData(PlotData):
654 class PlotSkyMapData(PlotData):
655 '''
656 Plot for meteors detection data
657 '''
909
658
910 CODE = 'met'
659 CODE = 'met'
911
660
912 def setup(self):
661 def setup(self):
913
662
914 self.ncols = 1
663 self.ncols = 1
915 self.nrows = 1
664 self.nrows = 1
916 self.width = 7.2
665 self.width = 7.2
917 self.height = 7.2
666 self.height = 7.2
918
667
919 self.xlabel = 'Zonal Zenith Angle (deg)'
668 self.xlabel = 'Zonal Zenith Angle (deg)'
920 self.ylabel = 'Meridional Zenith Angle (deg)'
669 self.ylabel = 'Meridional Zenith Angle (deg)'
921
670
922 if self.figure is None:
671 if self.figure is None:
923 self.figure = plt.figure(figsize=(self.width, self.height),
672 self.figure = plt.figure(figsize=(self.width, self.height),
924 edgecolor='k',
673 edgecolor='k',
925 facecolor='w')
674 facecolor='w')
926 else:
675 else:
927 self.figure.clf()
676 self.figure.clf()
928
677
929 self.ax = plt.subplot2grid((self.nrows, self.ncols), (0, 0), 1, 1, polar=True)
678 self.ax = plt.subplot2grid((self.nrows, self.ncols), (0, 0), 1, 1, polar=True)
930 self.ax.firsttime = True
679 self.ax.firsttime = True
931
680
932
681
933 def plot(self):
682 def plot(self):
934
683
935 arrayParameters = np.concatenate([self.data['param'][t] for t in self.times])
684 arrayParameters = numpy.concatenate([self.data['param'][t] for t in self.data.times])
936 error = arrayParameters[:,-1]
685 error = arrayParameters[:,-1]
937 indValid = numpy.where(error == 0)[0]
686 indValid = numpy.where(error == 0)[0]
938 finalMeteor = arrayParameters[indValid,:]
687 finalMeteor = arrayParameters[indValid,:]
939 finalAzimuth = finalMeteor[:,3]
688 finalAzimuth = finalMeteor[:,3]
940 finalZenith = finalMeteor[:,4]
689 finalZenith = finalMeteor[:,4]
941
690
942 x = finalAzimuth*numpy.pi/180
691 x = finalAzimuth*numpy.pi/180
943 y = finalZenith
692 y = finalZenith
944
693
945 if self.ax.firsttime:
694 if self.ax.firsttime:
946 self.ax.plot = self.ax.plot(x, y, 'bo', markersize=5)[0]
695 self.ax.plot = self.ax.plot(x, y, 'bo', markersize=5)[0]
947 self.ax.set_ylim(0,90)
696 self.ax.set_ylim(0,90)
948 self.ax.set_yticks(numpy.arange(0,90,20))
697 self.ax.set_yticks(numpy.arange(0,90,20))
949 self.ax.set_xlabel(self.xlabel)
698 self.ax.set_xlabel(self.xlabel)
950 self.ax.set_ylabel(self.ylabel)
699 self.ax.set_ylabel(self.ylabel)
951 self.ax.yaxis.labelpad = 40
700 self.ax.yaxis.labelpad = 40
952 self.ax.firsttime = False
701 self.ax.firsttime = False
953 else:
702 else:
954 self.ax.plot.set_data(x, y)
703 self.ax.plot.set_data(x, y)
955
704
956
705
957 dt1 = datetime.datetime.fromtimestamp(self.min_time).strftime('%y/%m/%d %H:%M:%S')
706 dt1 = datetime.datetime.fromtimestamp(self.min_time).strftime('%y/%m/%d %H:%M:%S')
958 dt2 = datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')
707 dt2 = datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')
959 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
708 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
960 dt2,
709 dt2,
961 len(x))
710 len(x))
962 self.ax.set_title(title, size=8)
711 self.ax.set_title(title, size=8)
963
712
964 self.saveTime = self.max_time
713 self.saveTime = self.max_time
714
715 class PlotParamData(PlotRTIData):
716 '''
717 Plot for data_param object
718 '''
719
720 CODE = 'param'
721 colormap = 'seismic'
722
723 def setup(self):
724 self.xaxis = 'time'
725 self.ncols = 1
726 self.nrows = self.data.shape(self.CODE)[0]
727 self.nplots = self.nrows
728 if self.showSNR:
729 self.nrows += 1
730
731 self.ylabel = 'Height [Km]'
732 self.titles = self.data.parameters \
733 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
734 if self.showSNR:
735 self.titles.append('SNR')
736
737 def plot(self):
738 self.data.normalize_heights()
739 self.x = self.data.times
740 self.y = self.data.heights
741 if self.showSNR:
742 self.z = numpy.concatenate(
743 (self.data[self.CODE], self.data['snr'])
744 )
745 else:
746 self.z = self.data[self.CODE]
747
748 self.z = numpy.ma.masked_invalid(self.z)
749
750 for n, ax in enumerate(self.axes):
751
752 x, y, z = self.fill_gaps(*self.decimate())
753
754 if ax.firsttime:
755 if self.zlimits is not None:
756 self.zmin, self.zmax = self.zlimits[n]
757 self.zmax = self.zmax if self.zmax is not None else numpy.nanmax(abs(self.z[:-1, :]))
758 self.zmin = self.zmin if self.zmin is not None else -self.zmax
759 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
760 vmin=self.zmin,
761 vmax=self.zmax,
762 cmap=self.cmaps[n]
763 )
764 else:
765 if self.zlimits is not None:
766 self.zmin, self.zmax = self.zlimits[n]
767 ax.collections.remove(ax.collections[0])
768 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
769 vmin=self.zmin,
770 vmax=self.zmax,
771 cmap=self.cmaps[n]
772 )
773
774 self.saveTime = self.min_time
775
776 class PlotOuputData(PlotParamData):
777 '''
778 Plot data_output object
779 '''
780
781 CODE = 'output'
782 colormap = 'seismic' No newline at end of file
This diff has been collapsed as it changes many lines, (2660 lines changed) Show them Hide them
@@ -1,2805 +1,4045
1 import numpy
1 import numpy
2 import math
2 import math
3 from scipy import optimize, interpolate, signal, stats, ndimage
3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 import re
5 import re
5 import datetime
6 import datetime
6 import copy
7 import copy
7 import sys
8 import sys
8 import importlib
9 import importlib
9 import itertools
10 import itertools
10
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
13 import copy_reg
14 import cPickle
15 import types
16 from functools import partial
17 import time
18 #from sklearn.cluster import KMeans
19
20 import matplotlib.pyplot as plt
21
22 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
11 from jroproc_base import ProcessingUnit, Operation
23 from jroproc_base import ProcessingUnit, Operation
12 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
24 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
25 from scipy import asarray as ar,exp
26 from scipy.optimize import curve_fit
13
27
28 import warnings
29 from numpy import NaN
30 from scipy.optimize.optimize import OptimizeWarning
31 warnings.filterwarnings('ignore')
14
32
15 class ParametersProc(ProcessingUnit):
16
33
34 SPEED_OF_LIGHT = 299792458
35
36
37 '''solving pickling issue'''
38
39 def _pickle_method(method):
40 func_name = method.im_func.__name__
41 obj = method.im_self
42 cls = method.im_class
43 return _unpickle_method, (func_name, obj, cls)
44
45 def _unpickle_method(func_name, obj, cls):
46 for cls in cls.mro():
47 try:
48 func = cls.__dict__[func_name]
49 except KeyError:
50 pass
51 else:
52 break
53 return func.__get__(obj, cls)
54
55 class ParametersProc(ProcessingUnit):
56
17 nSeconds = None
57 nSeconds = None
18
58
19 def __init__(self):
59 def __init__(self):
20 ProcessingUnit.__init__(self)
60 ProcessingUnit.__init__(self)
21
61
22 # self.objectDict = {}
62 # self.objectDict = {}
23 self.buffer = None
63 self.buffer = None
24 self.firstdatatime = None
64 self.firstdatatime = None
25 self.profIndex = 0
65 self.profIndex = 0
26 self.dataOut = Parameters()
66 self.dataOut = Parameters()
27
67
28 def __updateObjFromInput(self):
68 def __updateObjFromInput(self):
29
69
30 self.dataOut.inputUnit = self.dataIn.type
70 self.dataOut.inputUnit = self.dataIn.type
31
71
32 self.dataOut.timeZone = self.dataIn.timeZone
72 self.dataOut.timeZone = self.dataIn.timeZone
33 self.dataOut.dstFlag = self.dataIn.dstFlag
73 self.dataOut.dstFlag = self.dataIn.dstFlag
34 self.dataOut.errorCount = self.dataIn.errorCount
74 self.dataOut.errorCount = self.dataIn.errorCount
35 self.dataOut.useLocalTime = self.dataIn.useLocalTime
75 self.dataOut.useLocalTime = self.dataIn.useLocalTime
36
76
37 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
77 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
38 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
78 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
39 self.dataOut.channelList = self.dataIn.channelList
79 self.dataOut.channelList = self.dataIn.channelList
40 self.dataOut.heightList = self.dataIn.heightList
80 self.dataOut.heightList = self.dataIn.heightList
41 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
81 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
42 # self.dataOut.nHeights = self.dataIn.nHeights
82 # self.dataOut.nHeights = self.dataIn.nHeights
43 # self.dataOut.nChannels = self.dataIn.nChannels
83 # self.dataOut.nChannels = self.dataIn.nChannels
44 self.dataOut.nBaud = self.dataIn.nBaud
84 self.dataOut.nBaud = self.dataIn.nBaud
45 self.dataOut.nCode = self.dataIn.nCode
85 self.dataOut.nCode = self.dataIn.nCode
46 self.dataOut.code = self.dataIn.code
86 self.dataOut.code = self.dataIn.code
47 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
87 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
48 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
88 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
49 # self.dataOut.utctime = self.firstdatatime
89 # self.dataOut.utctime = self.firstdatatime
50 self.dataOut.utctime = self.dataIn.utctime
90 self.dataOut.utctime = self.dataIn.utctime
51 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
91 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
52 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
92 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
53 self.dataOut.nCohInt = self.dataIn.nCohInt
93 self.dataOut.nCohInt = self.dataIn.nCohInt
54 # self.dataOut.nIncohInt = 1
94 # self.dataOut.nIncohInt = 1
55 self.dataOut.ippSeconds = self.dataIn.ippSeconds
95 self.dataOut.ippSeconds = self.dataIn.ippSeconds
56 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
96 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
57 self.dataOut.timeInterval1 = self.dataIn.timeInterval
97 self.dataOut.timeInterval1 = self.dataIn.timeInterval
58 self.dataOut.heightList = self.dataIn.getHeiRange()
98 self.dataOut.heightList = self.dataIn.getHeiRange()
59 self.dataOut.frequency = self.dataIn.frequency
99 self.dataOut.frequency = self.dataIn.frequency
60 #self.dataOut.noise = self.dataIn.noise
100 # self.dataOut.noise = self.dataIn.noise
61
101
62 def run(self):
102 def run(self):
63
103
64 #---------------------- Voltage Data ---------------------------
104 #---------------------- Voltage Data ---------------------------
65
105
66 if self.dataIn.type == "Voltage":
106 if self.dataIn.type == "Voltage":
67
107
68 self.__updateObjFromInput()
108 self.__updateObjFromInput()
69 self.dataOut.data_pre = self.dataIn.data.copy()
109 self.dataOut.data_pre = self.dataIn.data.copy()
70 self.dataOut.flagNoData = False
110 self.dataOut.flagNoData = False
71 self.dataOut.utctimeInit = self.dataIn.utctime
111 self.dataOut.utctimeInit = self.dataIn.utctime
72 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
112 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
73 return
113 return
74
114
75 #---------------------- Spectra Data ---------------------------
115 #---------------------- Spectra Data ---------------------------
76
116
77 if self.dataIn.type == "Spectra":
117 if self.dataIn.type == "Spectra":
78
118
79 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
119 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
80 self.dataOut.data_spc = self.dataIn.data_spc
120 self.dataOut.data_spc = self.dataIn.data_spc
81 self.dataOut.data_cspc = self.dataIn.data_cspc
121 self.dataOut.data_cspc = self.dataIn.data_cspc
82 self.dataOut.nProfiles = self.dataIn.nProfiles
122 self.dataOut.nProfiles = self.dataIn.nProfiles
83 self.dataOut.nIncohInt = self.dataIn.nIncohInt
123 self.dataOut.nIncohInt = self.dataIn.nIncohInt
84 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
124 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
85 self.dataOut.ippFactor = self.dataIn.ippFactor
125 self.dataOut.ippFactor = self.dataIn.ippFactor
86 #self.dataOut.normFactor = self.dataIn.getNormFactor()
87 self.dataOut.pairsList = self.dataIn.pairsList
88 self.dataOut.groupList = self.dataIn.pairsList
89 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
126 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
127 self.dataOut.spc_noise = self.dataIn.getNoise()
128 self.dataOut.spc_range = (self.dataIn.getFreqRange(1)/1000. , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
129 self.dataOut.pairsList = self.dataIn.pairsList
130 self.dataOut.groupList = self.dataIn.pairsList
90 self.dataOut.flagNoData = False
131 self.dataOut.flagNoData = False
91
132
133 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
134 self.dataOut.ChanDist = self.dataIn.ChanDist
135 else: self.dataOut.ChanDist = None
136
137 if hasattr(self.dataIn, 'VelRange'): #Velocities range
138 self.dataOut.VelRange = self.dataIn.VelRange
139 else: self.dataOut.VelRange = None
140
141 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
142 self.dataOut.RadarConst = self.dataIn.RadarConst
143
144 if hasattr(self.dataIn, 'NPW'): #NPW
145 self.dataOut.NPW = self.dataIn.NPW
146
147 if hasattr(self.dataIn, 'COFA'): #COFA
148 self.dataOut.COFA = self.dataIn.COFA
149
150
151
92 #---------------------- Correlation Data ---------------------------
152 #---------------------- Correlation Data ---------------------------
93
153
94 if self.dataIn.type == "Correlation":
154 if self.dataIn.type == "Correlation":
95 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
155 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
96
156
97 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
157 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
98 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
158 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
99 self.dataOut.groupList = (acf_pairs, ccf_pairs)
159 self.dataOut.groupList = (acf_pairs, ccf_pairs)
100
160
101 self.dataOut.abscissaList = self.dataIn.lagRange
161 self.dataOut.abscissaList = self.dataIn.lagRange
102 self.dataOut.noise = self.dataIn.noise
162 self.dataOut.noise = self.dataIn.noise
103 self.dataOut.data_SNR = self.dataIn.SNR
163 self.dataOut.data_SNR = self.dataIn.SNR
104 self.dataOut.flagNoData = False
164 self.dataOut.flagNoData = False
105 self.dataOut.nAvg = self.dataIn.nAvg
165 self.dataOut.nAvg = self.dataIn.nAvg
106
166
107 #---------------------- Parameters Data ---------------------------
167 #---------------------- Parameters Data ---------------------------
108
168
109 if self.dataIn.type == "Parameters":
169 if self.dataIn.type == "Parameters":
110 self.dataOut.copy(self.dataIn)
170 self.dataOut.copy(self.dataIn)
111 self.dataOut.utctimeInit = self.dataIn.utctime
112 self.dataOut.flagNoData = False
171 self.dataOut.flagNoData = False
113
172
114 return True
173 return True
115
174
116 self.__updateObjFromInput()
175 self.__updateObjFromInput()
117 self.dataOut.utctimeInit = self.dataIn.utctime
176 self.dataOut.utctimeInit = self.dataIn.utctime
118 self.dataOut.paramInterval = self.dataIn.timeInterval
177 self.dataOut.paramInterval = self.dataIn.timeInterval
119
178
120 return
179 return
121
180
122 class SpectralMoments(Operation):
123
181
182 def target(tups):
183
184 obj, args = tups
185 #print 'TARGETTT', obj, args
186 return obj.FitGau(args)
187
188 class GaussianFit(Operation):
189
124 '''
190 '''
125 Function SpectralMoments()
191 Function that fit of one and two generalized gaussians (gg) based
192 on the PSD shape across an "power band" identified from a cumsum of
193 the measured spectrum - noise.
194
195 Input:
196 self.dataOut.data_pre : SelfSpectra
197
198 Output:
199 self.dataOut.GauSPC : SPC_ch1, SPC_ch2
200
201 '''
202 def __init__(self, **kwargs):
203 Operation.__init__(self, **kwargs)
204 self.i=0
205
206
207 def run(self, dataOut, num_intg=7, pnoise=1., vel_arr=None, SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
208 """This routine will find a couple of generalized Gaussians to a power spectrum
209 input: spc
210 output:
211 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
212 """
213
214 self.spc = dataOut.data_pre[0].copy()
215
216
217 print 'SelfSpectra Shape', numpy.asarray(self.spc).shape
218
219
220 #plt.figure(50)
221 #plt.subplot(121)
222 #plt.plot(self.spc,'k',label='spc(66)')
223 #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
224 #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
225 #plt.plot(xFrec,FitGauss,'yo:',label='fit')
226 #plt.legend()
227 #plt.title('DATOS A ALTURA DE 7500 METROS')
228 #plt.show()
229
230 self.Num_Hei = self.spc.shape[2]
231 #self.Num_Bin = len(self.spc)
232 self.Num_Bin = self.spc.shape[1]
233 self.Num_Chn = self.spc.shape[0]
234
235 Vrange = dataOut.abscissaList
236
237 #print 'self.spc2', numpy.asarray(self.spc).shape
238
239 GauSPC = numpy.empty([2,self.Num_Bin,self.Num_Hei])
240 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
241 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
242 SPC_ch1[:] = numpy.NaN
243 SPC_ch2[:] = numpy.NaN
126
244
127 Calculates moments (power, mean, standard deviation) and SNR of the signal
245
246 start_time = time.time()
247
248 noise_ = dataOut.spc_noise[0].copy()
249
250
251
252 pool = Pool(processes=self.Num_Chn)
253 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
254 objs = [self for __ in range(self.Num_Chn)]
255 attrs = zip(objs, args)
256 gauSPC = pool.map(target, attrs)
257 dataOut.GauSPC = numpy.asarray(gauSPC)
258 # ret = []
259 # for n in range(self.Num_Chn):
260 # self.FitGau(args[n])
261 # dataOut.GauSPC = ret
262
263
264
265 # for ch in range(self.Num_Chn):
266 #
267 # for ht in range(self.Num_Hei):
268 # #print (numpy.asarray(self.spc).shape)
269 # spc = numpy.asarray(self.spc)[ch,:,ht]
270 #
271 # #############################################
272 # # normalizing spc and noise
273 # # This part differs from gg1
274 # spc_norm_max = max(spc)
275 # spc = spc / spc_norm_max
276 # pnoise = pnoise / spc_norm_max
277 # #############################################
278 #
279 # if abs(vel_arr[0])<15.0: # this switch is for spectra collected with different length IPP's
280 # fatspectra=1.0
281 # else:
282 # fatspectra=0.5
283 #
284 # wnoise = noise_ / spc_norm_max
285 # #print 'wnoise', noise_, dataOut.spc_noise[0], wnoise
286 # #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
287 # #if wnoise>1.1*pnoise: # to be tested later
288 # # wnoise=pnoise
289 # noisebl=wnoise*0.9; noisebh=wnoise*1.1
290 # spc=spc-wnoise
291 #
292 # minx=numpy.argmin(spc)
293 # spcs=numpy.roll(spc,-minx)
294 # cum=numpy.cumsum(spcs)
295 # tot_noise=wnoise * self.Num_Bin #64;
296 # #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
297 # #snr=tot_signal/tot_noise
298 # #snr=cum[-1]/tot_noise
299 #
300 # #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
301 #
302 # snr = sum(spcs)/tot_noise
303 # snrdB=10.*numpy.log10(snr)
304 #
305 # #if snrdB < -9 :
306 # # snrdB = numpy.NaN
307 # # continue
308 #
309 # #print 'snr',snrdB # , sum(spcs) , tot_noise
310 #
311 #
312 # #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
313 # # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
314 #
315 # cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
316 # cumlo=cummax*epsi;
317 # cumhi=cummax*(1-epsi)
318 # powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
319 #
320 # #if len(powerindex)==1:
321 # ##return [numpy.mod(powerindex[0]+minx,64),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
322 # #return [numpy.mod(powerindex[0]+minx, self.Num_Bin ),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
323 # #elif len(powerindex)<4*fatspectra:
324 # #return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
325 #
326 # if len(powerindex) < 1:# case for powerindex 0
327 # continue
328 # powerlo=powerindex[0]
329 # powerhi=powerindex[-1]
330 # powerwidth=powerhi-powerlo
331 #
332 # firstpeak=powerlo+powerwidth/10.# first gaussian energy location
333 # secondpeak=powerhi-powerwidth/10.#second gaussian energy location
334 # midpeak=(firstpeak+secondpeak)/2.
335 # firstamp=spcs[int(firstpeak)]
336 # secondamp=spcs[int(secondpeak)]
337 # midamp=spcs[int(midpeak)]
338 # #x=numpy.spc.shape[1]
339 #
340 # #x=numpy.arange(64)
341 # x=numpy.arange( self.Num_Bin )
342 # y_data=spc+wnoise
343 #
344 # # single gaussian
345 # #shift0=numpy.mod(midpeak+minx,64)
346 # shift0=numpy.mod(midpeak+minx, self.Num_Bin )
347 # width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
348 # power0=2.
349 # amplitude0=midamp
350 # state0=[shift0,width0,amplitude0,power0,wnoise]
351 # #bnds=((0,63),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
352 # bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
353 # #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(0.1,0.5))
354 # # bnds = range of fft, power width, amplitude, power, noise
355 # lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
356 #
357 # chiSq1=lsq1[1];
358 # jack1= self.y_jacobian1(x,lsq1[0])
359 #
360 #
361 # try:
362 # sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
363 # except:
364 # std1=32.; sigmas1=numpy.ones(5)
365 # else:
366 # std1=sigmas1[0]
367 #
368 #
369 # if fatspectra<1.0 and powerwidth<4:
370 # choice=0
371 # Amplitude0=lsq1[0][2]
372 # shift0=lsq1[0][0]
373 # width0=lsq1[0][1]
374 # p0=lsq1[0][3]
375 # Amplitude1=0.
376 # shift1=0.
377 # width1=0.
378 # p1=0.
379 # noise=lsq1[0][4]
380 # #return (numpy.array([shift0,width0,Amplitude0,p0]),
381 # # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
382 #
383 # # two gaussians
384 # #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
385 # shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
386 # shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
387 # width0=powerwidth/6.;
388 # width1=width0
389 # power0=2.;
390 # power1=power0
391 # amplitude0=firstamp;
392 # amplitude1=secondamp
393 # state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
394 # #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
395 # bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
396 # #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
397 #
398 # lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
399 #
400 #
401 # chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
402 #
403 #
404 # try:
405 # sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
406 # except:
407 # std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
408 # else:
409 # std2a=sigmas2[0]; std2b=sigmas2[4]
410 #
411 #
412 #
413 # oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
414 #
415 # if snrdB>-9: # when SNR is strong pick the peak with least shift (LOS velocity) error
416 # if oneG:
417 # choice=0
418 # else:
419 # w1=lsq2[0][1]; w2=lsq2[0][5]
420 # a1=lsq2[0][2]; a2=lsq2[0][6]
421 # p1=lsq2[0][3]; p2=lsq2[0][7]
422 # s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1; s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
423 # gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
424 #
425 # if gp1>gp2:
426 # if a1>0.7*a2:
427 # choice=1
428 # else:
429 # choice=2
430 # elif gp2>gp1:
431 # if a2>0.7*a1:
432 # choice=2
433 # else:
434 # choice=1
435 # else:
436 # choice=numpy.argmax([a1,a2])+1
437 # #else:
438 # #choice=argmin([std2a,std2b])+1
439 #
440 # else: # with low SNR go to the most energetic peak
441 # choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
442 #
443 # #print 'choice',choice
444 #
445 # if choice==0: # pick the single gaussian fit
446 # Amplitude0=lsq1[0][2]
447 # shift0=lsq1[0][0]
448 # width0=lsq1[0][1]
449 # p0=lsq1[0][3]
450 # Amplitude1=0.
451 # shift1=0.
452 # width1=0.
453 # p1=0.
454 # noise=lsq1[0][4]
455 # elif choice==1: # take the first one of the 2 gaussians fitted
456 # Amplitude0 = lsq2[0][2]
457 # shift0 = lsq2[0][0]
458 # width0 = lsq2[0][1]
459 # p0 = lsq2[0][3]
460 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
461 # shift1 = lsq2[0][4] # This is 0 in gg1
462 # width1 = lsq2[0][5] # This is 0 in gg1
463 # p1 = lsq2[0][7] # This is 0 in gg1
464 # noise = lsq2[0][8]
465 # else: # the second one
466 # Amplitude0 = lsq2[0][6]
467 # shift0 = lsq2[0][4]
468 # width0 = lsq2[0][5]
469 # p0 = lsq2[0][7]
470 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
471 # shift1 = lsq2[0][0] # This is 0 in gg1
472 # width1 = lsq2[0][1] # This is 0 in gg1
473 # p1 = lsq2[0][3] # This is 0 in gg1
474 # noise = lsq2[0][8]
475 #
476 # #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
477 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
478 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
479 # #print 'SPC_ch1.shape',SPC_ch1.shape
480 # #print 'SPC_ch2.shape',SPC_ch2.shape
481 # #dataOut.data_param = SPC_ch1
482 # GauSPC[0] = SPC_ch1
483 # GauSPC[1] = SPC_ch2
484
485 # #plt.gcf().clear()
486 # plt.figure(50+self.i)
487 # self.i=self.i+1
488 # #plt.subplot(121)
489 # plt.plot(self.spc,'k')#,label='spc(66)')
490 # plt.plot(SPC_ch1[ch,ht],'b')#,label='gg1')
491 # #plt.plot(SPC_ch2,'r')#,label='gg2')
492 # #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
493 # #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
494 # #plt.plot(xFrec,FitGauss,'yo:',label='fit')
495 # plt.legend()
496 # plt.title('DATOS A ALTURA DE 7500 METROS')
497 # plt.show()
498 # print 'shift0', shift0
499 # print 'Amplitude0', Amplitude0
500 # print 'width0', width0
501 # print 'p0', p0
502 # print '========================'
503 # print 'shift1', shift1
504 # print 'Amplitude1', Amplitude1
505 # print 'width1', width1
506 # print 'p1', p1
507 # print 'noise', noise
508 # print 's_noise', wnoise
509
510 print '========================================================'
511 print 'total_time: ', time.time()-start_time
512
513 # re-normalizing spc and noise
514 # This part differs from gg1
515
516
517
518 ''' Parameters:
519 1. Amplitude
520 2. Shift
521 3. Width
522 4. Power
523 '''
524
525
526 ###############################################################################
527 def FitGau(self, X):
528
529 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
530 #print 'VARSSSS', ch, pnoise, noise, num_intg
531
532 #print 'HEIGHTS', self.Num_Hei
533
534 GauSPC = []
535 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
536 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
537 SPC_ch1[:] = 0#numpy.NaN
538 SPC_ch2[:] = 0#numpy.NaN
539
540
541
542 for ht in range(self.Num_Hei):
543 #print (numpy.asarray(self.spc).shape)
544
545 #print 'TTTTT', ch , ht
546 #print self.spc.shape
547
548
549 spc = numpy.asarray(self.spc)[ch,:,ht]
550
551 #############################################
552 # normalizing spc and noise
553 # This part differs from gg1
554 spc_norm_max = max(spc)
555 spc = spc / spc_norm_max
556 pnoise = pnoise / spc_norm_max
557 #############################################
558
559 fatspectra=1.0
560
561 wnoise = noise_ / spc_norm_max
562 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
563 #if wnoise>1.1*pnoise: # to be tested later
564 # wnoise=pnoise
565 noisebl=wnoise*0.9; noisebh=wnoise*1.1
566 spc=spc-wnoise
567 # print 'wnoise', noise_[0], spc_norm_max, wnoise
568 minx=numpy.argmin(spc)
569 spcs=numpy.roll(spc,-minx)
570 cum=numpy.cumsum(spcs)
571 tot_noise=wnoise * self.Num_Bin #64;
572 #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
573 #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
574 #snr=tot_signal/tot_noise
575 #snr=cum[-1]/tot_noise
576 snr = sum(spcs)/tot_noise
577 snrdB=10.*numpy.log10(snr)
578
579 if snrdB < SNRlimit :
580 snr = numpy.NaN
581 SPC_ch1[:,ht] = 0#numpy.NaN
582 SPC_ch1[:,ht] = 0#numpy.NaN
583 GauSPC = (SPC_ch1,SPC_ch2)
584 continue
585 #print 'snr',snrdB #, sum(spcs) , tot_noise
586
587
588
589 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
590 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
591
592 cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
593 cumlo=cummax*epsi;
594 cumhi=cummax*(1-epsi)
595 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
596
597
598 if len(powerindex) < 1:# case for powerindex 0
599 continue
600 powerlo=powerindex[0]
601 powerhi=powerindex[-1]
602 powerwidth=powerhi-powerlo
603
604 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
605 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
606 midpeak=(firstpeak+secondpeak)/2.
607 firstamp=spcs[int(firstpeak)]
608 secondamp=spcs[int(secondpeak)]
609 midamp=spcs[int(midpeak)]
610
611 x=numpy.arange( self.Num_Bin )
612 y_data=spc+wnoise
613
614 # single gaussian
615 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
616 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
617 power0=2.
618 amplitude0=midamp
619 state0=[shift0,width0,amplitude0,power0,wnoise]
620 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
621 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
622
623 chiSq1=lsq1[1];
624 jack1= self.y_jacobian1(x,lsq1[0])
625
626
627 try:
628 sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
629 except:
630 std1=32.; sigmas1=numpy.ones(5)
631 else:
632 std1=sigmas1[0]
633
634
635 if fatspectra<1.0 and powerwidth<4:
636 choice=0
637 Amplitude0=lsq1[0][2]
638 shift0=lsq1[0][0]
639 width0=lsq1[0][1]
640 p0=lsq1[0][3]
641 Amplitude1=0.
642 shift1=0.
643 width1=0.
644 p1=0.
645 noise=lsq1[0][4]
646 #return (numpy.array([shift0,width0,Amplitude0,p0]),
647 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
648
649 # two gaussians
650 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
651 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
652 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
653 width0=powerwidth/6.;
654 width1=width0
655 power0=2.;
656 power1=power0
657 amplitude0=firstamp;
658 amplitude1=secondamp
659 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
660 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
661 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
662 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
663
664 lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
665
666
667 chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
668
669
670 try:
671 sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
672 except:
673 std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
674 else:
675 std2a=sigmas2[0]; std2b=sigmas2[4]
676
677
678
679 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
680
681 if snrdB>-6: # when SNR is strong pick the peak with least shift (LOS velocity) error
682 if oneG:
683 choice=0
684 else:
685 w1=lsq2[0][1]; w2=lsq2[0][5]
686 a1=lsq2[0][2]; a2=lsq2[0][6]
687 p1=lsq2[0][3]; p2=lsq2[0][7]
688 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
689 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
690 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
691
692 if gp1>gp2:
693 if a1>0.7*a2:
694 choice=1
695 else:
696 choice=2
697 elif gp2>gp1:
698 if a2>0.7*a1:
699 choice=2
700 else:
701 choice=1
702 else:
703 choice=numpy.argmax([a1,a2])+1
704 #else:
705 #choice=argmin([std2a,std2b])+1
706
707 else: # with low SNR go to the most energetic peak
708 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
709
710
711 shift0=lsq2[0][0]; vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
712 shift1=lsq2[0][4]; vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
713
714 max_vel = 20
715
716 #first peak will be 0, second peak will be 1
717 if vel0 > 0 and vel0 < max_vel : #first peak is in the correct range
718 shift0=lsq2[0][0]
719 width0=lsq2[0][1]
720 Amplitude0=lsq2[0][2]
721 p0=lsq2[0][3]
722
723 shift1=lsq2[0][4]
724 width1=lsq2[0][5]
725 Amplitude1=lsq2[0][6]
726 p1=lsq2[0][7]
727 noise=lsq2[0][8]
728 else:
729 shift1=lsq2[0][0]
730 width1=lsq2[0][1]
731 Amplitude1=lsq2[0][2]
732 p1=lsq2[0][3]
733
734 shift0=lsq2[0][4]
735 width0=lsq2[0][5]
736 Amplitude0=lsq2[0][6]
737 p0=lsq2[0][7]
738 noise=lsq2[0][8]
739
740 if Amplitude0<0.1: # in case the peak is noise
741 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
742 if Amplitude1<0.1:
743 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
744
745
746 # if choice==0: # pick the single gaussian fit
747 # Amplitude0=lsq1[0][2]
748 # shift0=lsq1[0][0]
749 # width0=lsq1[0][1]
750 # p0=lsq1[0][3]
751 # Amplitude1=0.
752 # shift1=0.
753 # width1=0.
754 # p1=0.
755 # noise=lsq1[0][4]
756 # elif choice==1: # take the first one of the 2 gaussians fitted
757 # Amplitude0 = lsq2[0][2]
758 # shift0 = lsq2[0][0]
759 # width0 = lsq2[0][1]
760 # p0 = lsq2[0][3]
761 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
762 # shift1 = lsq2[0][4] # This is 0 in gg1
763 # width1 = lsq2[0][5] # This is 0 in gg1
764 # p1 = lsq2[0][7] # This is 0 in gg1
765 # noise = lsq2[0][8]
766 # else: # the second one
767 # Amplitude0 = lsq2[0][6]
768 # shift0 = lsq2[0][4]
769 # width0 = lsq2[0][5]
770 # p0 = lsq2[0][7]
771 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
772 # shift1 = lsq2[0][0] # This is 0 in gg1
773 # width1 = lsq2[0][1] # This is 0 in gg1
774 # p1 = lsq2[0][3] # This is 0 in gg1
775 # noise = lsq2[0][8]
776
777 #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
778 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
779 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
780 #print 'SPC_ch1.shape',SPC_ch1.shape
781 #print 'SPC_ch2.shape',SPC_ch2.shape
782 #dataOut.data_param = SPC_ch1
783 GauSPC = (SPC_ch1,SPC_ch2)
784 #GauSPC[1] = SPC_ch2
785
786 # print 'shift0', shift0
787 # print 'Amplitude0', Amplitude0
788 # print 'width0', width0
789 # print 'p0', p0
790 # print '========================'
791 # print 'shift1', shift1
792 # print 'Amplitude1', Amplitude1
793 # print 'width1', width1
794 # print 'p1', p1
795 # print 'noise', noise
796 # print 's_noise', wnoise
797
798 return GauSPC
799
800
801 def y_jacobian1(self,x,state): # This function is for further analysis of generalized Gaussians, it is not too importan for the signal discrimination.
802 y_model=self.y_model1(x,state)
803 s0,w0,a0,p0,n=state
804 e0=((x-s0)/w0)**2;
805
806 e0u=((x-s0-self.Num_Bin)/w0)**2;
807
808 e0d=((x-s0+self.Num_Bin)/w0)**2
809 m0=numpy.exp(-0.5*e0**(p0/2.));
810 m0u=numpy.exp(-0.5*e0u**(p0/2.));
811 m0d=numpy.exp(-0.5*e0d**(p0/2.))
812 JA=m0+m0u+m0d
813 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
814
815 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
816
817 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
818 jack1=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,1./y_model])
819 return jack1.T
820
821 def y_jacobian2(self,x,state):
822 y_model=self.y_model2(x,state)
823 s0,w0,a0,p0,s1,w1,a1,p1,n=state
824 e0=((x-s0)/w0)**2;
825
826 e0u=((x-s0- self.Num_Bin )/w0)**2;
827
828 e0d=((x-s0+ self.Num_Bin )/w0)**2
829 e1=((x-s1)/w1)**2;
830
831 e1u=((x-s1- self.Num_Bin )/w1)**2;
832
833 e1d=((x-s1+ self.Num_Bin )/w1)**2
834 m0=numpy.exp(-0.5*e0**(p0/2.));
835 m0u=numpy.exp(-0.5*e0u**(p0/2.));
836 m0d=numpy.exp(-0.5*e0d**(p0/2.))
837 m1=numpy.exp(-0.5*e1**(p1/2.));
838 m1u=numpy.exp(-0.5*e1u**(p1/2.));
839 m1d=numpy.exp(-0.5*e1d**(p1/2.))
840 JA=m0+m0u+m0d
841 JA1=m1+m1u+m1d
842 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
843 JP1=(-1/4.)*a1*m1*e1**(p1/2.)*numpy.log(e1)+(-1/4.)*a1*m1u*e1u**(p1/2.)*numpy.log(e1u)+(-1/4.)*a1*m1d*e1d**(p1/2.)*numpy.log(e1d)
844
845 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
846
847 JS1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)
848
849 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
850
851 JW1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)**2+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)**2+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)**2
852 jack2=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,JS1/y_model,JW1/y_model,JA1/y_model,JP1/y_model,1./y_model])
853 return jack2.T
854
855 def y_model1(self,x,state):
856 shift0,width0,amplitude0,power0,noise=state
857 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
858
859 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
860
861 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
862 return model0+model0u+model0d+noise
863
864 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
865 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
866 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
867
868 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
869
870 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
871 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
872
873 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
874
875 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
876 return model0+model0u+model0d+model1+model1u+model1d+noise
877
878 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
128
879
129 Type of dataIn: Spectra
880 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
881
882 def misfit2(self,state,y_data,x,num_intg):
883 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
884
130
885
131 Configuration Parameters:
886 class PrecipitationProc(Operation):
887
888 '''
889 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
890
891 Input:
892 self.dataOut.data_pre : SelfSpectra
893
894 Output:
895
896 self.dataOut.data_output : Reflectivity factor, rainfall Rate
897
898
899 Parameters affected:
900 '''
901
902
903 def run(self, dataOut, radar=None, Pt=None, Gt=None, Gr=None, Lambda=None, aL=None,
904 tauW=None, ThetaT=None, ThetaR=None, Km = 0.93, Altitude=None):
905
906 self.spc = dataOut.data_pre[0].copy()
907 self.Num_Hei = self.spc.shape[2]
908 self.Num_Bin = self.spc.shape[1]
909 self.Num_Chn = self.spc.shape[0]
910
911 Velrange = dataOut.abscissaList
912
913 if radar == "MIRA35C" :
914
915 Ze = self.dBZeMODE2(dataOut)
916
917 else:
918
919 self.Pt = Pt
920 self.Gt = Gt
921 self.Gr = Gr
922 self.Lambda = Lambda
923 self.aL = aL
924 self.tauW = tauW
925 self.ThetaT = ThetaT
926 self.ThetaR = ThetaR
927
928 RadarConstant = GetRadarConstant()
929 SPCmean = numpy.mean(self.spc,0)
930 ETA = numpy.zeros(self.Num_Hei)
931 Pr = numpy.sum(SPCmean,0)
932
933 #for R in range(self.Num_Hei):
934 # ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
935
936 D_range = numpy.zeros(self.Num_Hei)
937 EqSec = numpy.zeros(self.Num_Hei)
938 del_V = numpy.zeros(self.Num_Hei)
939
940 for R in range(self.Num_Hei):
941 ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
942
943 h = R + Altitude #Range from ground to radar pulse altitude
944 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
945
946 D_range[R] = numpy.log( (9.65 - (Velrange[R]/del_V[R])) / 10.3 ) / -0.6 #Range of Diameter of drops related to velocity
947 SIGMA[R] = numpy.pi**5 / Lambda**4 * Km * D_range[R]**6 #Equivalent Section of drops (sigma)
948
949 N_dist[R] = ETA[R] / SIGMA[R]
950
951 Ze = (ETA * Lambda**4) / (numpy.pi * Km)
952 Z = numpy.sum( N_dist * D_range**6 )
953 RR = 6*10**-4*numpy.pi * numpy.sum( D_range**3 * N_dist * Velrange ) #Rainfall rate
954
955
956 RR = (Ze/200)**(1/1.6)
957 dBRR = 10*numpy.log10(RR)
958
959 dBZe = 10*numpy.log10(Ze)
960 dataOut.data_output = Ze
961 dataOut.data_param = numpy.ones([2,self.Num_Hei])
962 dataOut.channelList = [0,1]
963 print 'channelList', dataOut.channelList
964 dataOut.data_param[0]=dBZe
965 dataOut.data_param[1]=dBRR
966 print 'RR SHAPE', dBRR.shape
967 print 'Ze SHAPE', dBZe.shape
968 print 'dataOut.data_param SHAPE', dataOut.data_param.shape
969
970
971 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
972
973 NPW = dataOut.NPW
974 COFA = dataOut.COFA
975
976 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
977 RadarConst = dataOut.RadarConst
978 #frequency = 34.85*10**9
979
980 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
981 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
982
983 ETA = numpy.sum(SNR,1)
984 print 'ETA' , ETA
985 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
986
987 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
988
989 for r in range(self.Num_Hei):
990
991 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
992 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
993
994 return Ze
995
996 def GetRadarConstant(self):
997
998 """
999 Constants:
1000
1001 Pt: Transmission Power dB
1002 Gt: Transmission Gain dB
1003 Gr: Reception Gain dB
1004 Lambda: Wavelenght m
1005 aL: Attenuation loses dB
1006 tauW: Width of transmission pulse s
1007 ThetaT: Transmission antenna bean angle rad
1008 ThetaR: Reception antenna beam angle rad
1009
1010 """
1011 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1012 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1013 RadarConstant = Numerator / Denominator
1014
1015 return RadarConstant
1016
1017
1018
1019 class FullSpectralAnalysis(Operation):
1020
1021 """
1022 Function that implements Full Spectral Analisys technique.
1023
1024 Input:
1025 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
1026 self.dataOut.groupList : Pairlist of channels
1027 self.dataOut.ChanDist : Physical distance between receivers
1028
1029
1030 Output:
1031
1032 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
1033
1034
1035 Parameters affected: Winds, height range, SNR
1036
1037 """
1038 def run(self, dataOut, E01=None, E02=None, E12=None, N01=None, N02=None, N12=None, SNRlimit=7):
1039
1040 spc = dataOut.data_pre[0].copy()
1041 cspc = dataOut.data_pre[1].copy()
1042
1043 nChannel = spc.shape[0]
1044 nProfiles = spc.shape[1]
1045 nHeights = spc.shape[2]
1046
1047 pairsList = dataOut.groupList
1048 if dataOut.ChanDist is not None :
1049 ChanDist = dataOut.ChanDist
1050 else:
1051 ChanDist = numpy.array([[E01, N01],[E02,N02],[E12,N12]])
1052
1053 #print 'ChanDist', ChanDist
1054
1055 if dataOut.VelRange is not None:
1056 VelRange= dataOut.VelRange
1057 else:
1058 VelRange= dataOut.abscissaList
1059
1060 ySamples=numpy.ones([nChannel,nProfiles])
1061 phase=numpy.ones([nChannel,nProfiles])
1062 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
1063 coherence=numpy.ones([nChannel,nProfiles])
1064 PhaseSlope=numpy.ones(nChannel)
1065 PhaseInter=numpy.ones(nChannel)
1066 dataSNR = dataOut.data_SNR
1067
1068
1069
1070 data = dataOut.data_pre
1071 noise = dataOut.noise
1072 print 'noise',noise
1073 #SNRdB = 10*numpy.log10(dataOut.data_SNR)
1074
1075 FirstMoment = numpy.average(dataOut.data_param[:,1,:],0)
1076 #SNRdBMean = []
132
1077
1078
1079 #for j in range(nHeights):
1080 # FirstMoment = numpy.append(FirstMoment,numpy.mean([dataOut.data_param[0,1,j],dataOut.data_param[1,1,j],dataOut.data_param[2,1,j]]))
1081 # SNRdBMean = numpy.append(SNRdBMean,numpy.mean([SNRdB[0,j],SNRdB[1,j],SNRdB[2,j]]))
1082
1083 data_output=numpy.ones([3,spc.shape[2]])*numpy.NaN
1084
1085 velocityX=[]
1086 velocityY=[]
1087 velocityV=[]
1088
1089 dbSNR = 10*numpy.log10(dataSNR)
1090 dbSNR = numpy.average(dbSNR,0)
1091 for Height in range(nHeights):
1092
1093 [Vzon,Vmer,Vver, GaussCenter]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR[Height], SNRlimit)
1094
1095 if abs(Vzon)<100. and abs(Vzon)> 0.:
1096 velocityX=numpy.append(velocityX, Vzon)#Vmag
1097
1098 else:
1099 print 'Vzon',Vzon
1100 velocityX=numpy.append(velocityX, numpy.NaN)
1101
1102 if abs(Vmer)<100. and abs(Vmer) > 0.:
1103 velocityY=numpy.append(velocityY, Vmer)#Vang
1104
1105 else:
1106 print 'Vmer',Vmer
1107 velocityY=numpy.append(velocityY, numpy.NaN)
1108
1109 if dbSNR[Height] > SNRlimit:
1110 velocityV=numpy.append(velocityV, FirstMoment[Height])
1111 else:
1112 velocityV=numpy.append(velocityV, numpy.NaN)
1113 #FirstMoment[Height]= numpy.NaN
1114 # if SNRdBMean[Height] <12:
1115 # FirstMoment[Height] = numpy.NaN
1116 # velocityX[Height] = numpy.NaN
1117 # velocityY[Height] = numpy.NaN
1118
1119
1120 data_output[0]=numpy.array(velocityX)
1121 data_output[1]=numpy.array(velocityY)
1122 data_output[2]=-velocityV#FirstMoment
1123
1124 print ' '
1125 #print 'FirstMoment'
1126 #print FirstMoment
1127 print 'velocityX',data_output[0]
1128 print ' '
1129 print 'velocityY',data_output[1]
1130 #print numpy.array(velocityY)
1131 print ' '
1132 #print 'SNR'
1133 #print 10*numpy.log10(dataOut.data_SNR)
1134 #print numpy.shape(10*numpy.log10(dataOut.data_SNR))
1135 print ' '
1136
1137
1138 dataOut.data_output=data_output
1139 return
1140
1141
1142 def moving_average(self,x, N=2):
1143 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1144
1145 def gaus(self,xSamples,a,x0,sigma):
1146 return a*numpy.exp(-(xSamples-x0)**2/(2*sigma**2))
1147
1148 def Find(self,x,value):
1149 for index in range(len(x)):
1150 if x[index]==value:
1151 return index
1152
1153 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR, SNRlimit):
1154
1155 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
1156 phase=numpy.ones([spc.shape[0],spc.shape[1]])
1157 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
1158 coherence=numpy.ones([spc.shape[0],spc.shape[1]])
1159 PhaseSlope=numpy.ones(spc.shape[0])
1160 PhaseInter=numpy.ones(spc.shape[0])
1161 xFrec=VelRange
1162
1163 '''Getting Eij and Nij'''
1164
1165 E01=ChanDist[0][0]
1166 N01=ChanDist[0][1]
1167
1168 E02=ChanDist[1][0]
1169 N02=ChanDist[1][1]
1170
1171 E12=ChanDist[2][0]
1172 N12=ChanDist[2][1]
1173
1174 z = spc.copy()
1175 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1176
1177 for i in range(spc.shape[0]):
1178
1179 '''****** Line of Data SPC ******'''
1180 zline=z[i,:,Height]
1181
1182 '''****** SPC is normalized ******'''
1183 FactNorm= (zline.copy()-noise[i]) / numpy.sum(zline.copy())
1184 FactNorm= FactNorm/numpy.sum(FactNorm)
1185
1186 SmoothSPC=self.moving_average(FactNorm,N=3)
1187
1188 xSamples = ar(range(len(SmoothSPC)))
1189 ySamples[i] = SmoothSPC
1190
1191 #dbSNR=10*numpy.log10(dataSNR)
1192 print ' '
1193 print ' '
1194 print ' '
1195
1196 #print 'dataSNR', dbSNR.shape, dbSNR[0,40:120]
1197 print 'SmoothSPC', SmoothSPC.shape, SmoothSPC[0:20]
1198 print 'noise',noise
1199 print 'zline',zline.shape, zline[0:20]
1200 print 'FactNorm',FactNorm.shape, FactNorm[0:20]
1201 print 'FactNorm suma', numpy.sum(FactNorm)
1202
1203 for i in range(spc.shape[0]):
1204
1205 '''****** Line of Data CSPC ******'''
1206 cspcLine=cspc[i,:,Height].copy()
1207
1208 '''****** CSPC is normalized ******'''
1209 chan_index0 = pairsList[i][0]
1210 chan_index1 = pairsList[i][1]
1211 CSPCFactor= abs(numpy.sum(ySamples[chan_index0]) * numpy.sum(ySamples[chan_index1])) #
1212
1213 CSPCNorm = (cspcLine.copy() -noise[i]) / numpy.sqrt(CSPCFactor)
1214
1215 CSPCSamples[i] = CSPCNorm
1216 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
1217
1218 coherence[i]= self.moving_average(coherence[i],N=2)
1219
1220 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
1221
1222 print 'cspcLine', cspcLine.shape, cspcLine[0:20]
1223 print 'CSPCFactor', CSPCFactor#, CSPCFactor[0:20]
1224 print numpy.sum(ySamples[chan_index0]), numpy.sum(ySamples[chan_index1]), -noise[i]
1225 print 'CSPCNorm', CSPCNorm.shape, CSPCNorm[0:20]
1226 print 'CSPCNorm suma', numpy.sum(CSPCNorm)
1227 print 'CSPCSamples', CSPCSamples.shape, CSPCSamples[0,0:20]
1228
1229 '''****** Getting fij width ******'''
1230
1231 yMean=[]
1232 yMean2=[]
1233
1234 for j in range(len(ySamples[1])):
1235 yMean=numpy.append(yMean,numpy.mean([ySamples[0,j],ySamples[1,j],ySamples[2,j]]))
1236
1237 '''******* Getting fitting Gaussian ******'''
1238 meanGauss=sum(xSamples*yMean) / len(xSamples)
1239 sigma=sum(yMean*(xSamples-meanGauss)**2) / len(xSamples)
1240
1241 print '****************************'
1242 print 'len(xSamples): ',len(xSamples)
1243 print 'yMean: ', yMean.shape, yMean[0:20]
1244 print 'ySamples', ySamples.shape, ySamples[0,0:20]
1245 print 'xSamples: ',xSamples.shape, xSamples[0:20]
1246
1247 print 'meanGauss',meanGauss
1248 print 'sigma',sigma
1249
1250 #if (abs(meanGauss/sigma**2) > 0.0001) : #0.000000001):
1251 if dbSNR > SNRlimit :
1252 try:
1253 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=[1,meanGauss,sigma])
1254
1255 if numpy.amax(popt)>numpy.amax(yMean)*0.3:
1256 FitGauss=self.gaus(xSamples,*popt)
1257
1258 else:
1259 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1260 print 'Verificador: Dentro', Height
1261 except :#RuntimeError:
1262 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1263
1264
1265 else:
1266 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1267
1268 Maximun=numpy.amax(yMean)
1269 eMinus1=Maximun*numpy.exp(-1)#*0.8
1270
1271 HWpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1)))
1272 HalfWidth= xFrec[HWpos]
1273 GCpos=self.Find(FitGauss, numpy.amax(FitGauss))
1274 Vpos=self.Find(FactNorm, numpy.amax(FactNorm))
1275
1276 #Vpos=FirstMoment[]
1277
1278 '''****** Getting Fij ******'''
1279
1280 GaussCenter=xFrec[GCpos]
1281 if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0):
1282 Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001
1283 else:
1284 Fij=abs(GaussCenter-HalfWidth)+0.0000001
1285
1286 '''****** Getting Frecuency range of significant data ******'''
1287
1288 Rangpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10)))
1289
1290 if Rangpos<GCpos:
1291 Range=numpy.array([Rangpos,2*GCpos-Rangpos])
1292 elif Rangpos< ( len(xFrec)- len(xFrec)*0.1):
1293 Range=numpy.array([2*GCpos-Rangpos,Rangpos])
1294 else:
1295 Range = numpy.array([0,0])
1296
1297 print ' '
1298 print 'GCpos',GCpos, ( len(xFrec)- len(xFrec)*0.1)
1299 print 'Rangpos',Rangpos
1300 print 'RANGE: ', Range
1301 FrecRange=xFrec[Range[0]:Range[1]]
1302
1303 '''****** Getting SCPC Slope ******'''
1304
1305 for i in range(spc.shape[0]):
1306
1307 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.5:
1308 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1309
1310 print 'FrecRange', len(FrecRange) , FrecRange
1311 print 'PhaseRange', len(PhaseRange), PhaseRange
1312 print ' '
1313 if len(FrecRange) == len(PhaseRange):
1314 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange,PhaseRange)
1315 PhaseSlope[i]=slope
1316 PhaseInter[i]=intercept
1317 else:
1318 PhaseSlope[i]=0
1319 PhaseInter[i]=0
1320 else:
1321 PhaseSlope[i]=0
1322 PhaseInter[i]=0
1323
1324 '''Getting constant C'''
1325 cC=(Fij*numpy.pi)**2
1326
1327 '''****** Getting constants F and G ******'''
1328 MijEijNij=numpy.array([[E02,N02], [E12,N12]])
1329 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1330 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1331 MijResults=numpy.array([MijResult0,MijResult1])
1332 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1333
1334 '''****** Getting constants A, B and H ******'''
1335 W01=numpy.amax(coherence[0])
1336 W02=numpy.amax(coherence[1])
1337 W12=numpy.amax(coherence[2])
1338
1339 WijResult0=((cF*E01+cG*N01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1340 WijResult1=((cF*E02+cG*N02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1341 WijResult2=((cF*E12+cG*N12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1342
1343 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1344
1345 WijEijNij=numpy.array([ [E01**2, N01**2, 2*E01*N01] , [E02**2, N02**2, 2*E02*N02] , [E12**2, N12**2, 2*E12*N12] ])
1346 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1347
1348 VxVy=numpy.array([[cA,cH],[cH,cB]])
1349
1350 VxVyResults=numpy.array([-cF,-cG])
1351 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1352
1353 Vzon = Vy
1354 Vmer = Vx
1355 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
1356 Vang=numpy.arctan2(Vmer,Vzon)
1357 Vver=xFrec[Vpos]
1358 print 'vzon y vmer', Vzon, Vmer
1359 return Vzon, Vmer, Vver, GaussCenter
1360
1361 class SpectralMoments(Operation):
1362
1363 '''
1364 Function SpectralMoments()
1365
1366 Calculates moments (power, mean, standard deviation) and SNR of the signal
1367
1368 Type of dataIn: Spectra
1369
1370 Configuration Parameters:
1371
133 dirCosx : Cosine director in X axis
1372 dirCosx : Cosine director in X axis
134 dirCosy : Cosine director in Y axis
1373 dirCosy : Cosine director in Y axis
135
1374
136 elevation :
1375 elevation :
137 azimuth :
1376 azimuth :
138
1377
139 Input:
1378 Input:
140 channelList : simple channel list to select e.g. [2,3,7]
1379 channelList : simple channel list to select e.g. [2,3,7]
141 self.dataOut.data_pre : Spectral data
1380 self.dataOut.data_pre : Spectral data
142 self.dataOut.abscissaList : List of frequencies
1381 self.dataOut.abscissaList : List of frequencies
143 self.dataOut.noise : Noise level per channel
1382 self.dataOut.noise : Noise level per channel
144
1383
145 Affected:
1384 Affected:
146 self.dataOut.data_param : Parameters per channel
1385 self.dataOut.data_param : Parameters per channel
147 self.dataOut.data_SNR : SNR per channel
1386 self.dataOut.data_SNR : SNR per channel
148
1387
149 '''
1388 '''
150
1389
151 def run(self, dataOut):
1390 def run(self, dataOut):
152
1391
153 #dataOut.data_pre = dataOut.data_pre[0]
1392 #dataOut.data_pre = dataOut.data_pre[0]
154 data = dataOut.data_pre[0]
1393 data = dataOut.data_pre[0]
155 absc = dataOut.abscissaList[:-1]
1394 absc = dataOut.abscissaList[:-1]
156 noise = dataOut.noise
1395 noise = dataOut.noise
157 nChannel = data.shape[0]
1396 nChannel = data.shape[0]
158 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1397 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
159
1398
160 for ind in range(nChannel):
1399 for ind in range(nChannel):
161 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:], absc, noise[ind])
1400 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
162
1401
163 dataOut.data_param = data_param[:,1:,:]
1402 dataOut.data_param = data_param[:,1:,:]
164 dataOut.data_SNR = data_param[:,0]
1403 dataOut.data_SNR = data_param[:,0]
165 dataOut.data_DOP = data_param[:,1]
1404 dataOut.data_DOP = data_param[:,1]
166 dataOut.data_MEAN = data_param[:,2]
1405 dataOut.data_MEAN = data_param[:,2]
167 dataOut.data_STD = data_param[:,3]
1406 dataOut.data_STD = data_param[:,3]
168 return
1407 return
169
1408
170 def __calculateMoments(self, oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1409 def __calculateMoments(self, oldspec, oldfreq, n0,
171
1410 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
172 if (nicoh is None): nicoh = 1
1411
173 if (graph is None): graph = 0
1412 if (nicoh == None): nicoh = 1
174 if (smooth is None): smooth = 0
1413 if (graph == None): graph = 0
1414 if (smooth == None): smooth = 0
175 elif (self.smooth < 3): smooth = 0
1415 elif (self.smooth < 3): smooth = 0
176
1416
177 if (type1 is None): type1 = 0
1417 if (type1 == None): type1 = 0
178 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1418 if (fwindow == None): fwindow = numpy.zeros(oldfreq.size) + 1
179 if (snrth is None): snrth = -3
1419 if (snrth == None): snrth = -3
180 if (dc is None): dc = 0
1420 if (dc == None): dc = 0
181 if (aliasing is None): aliasing = 0
1421 if (aliasing == None): aliasing = 0
182 if (oldfd is None): oldfd = 0
1422 if (oldfd == None): oldfd = 0
183 if (wwauto is None): wwauto = 0
1423 if (wwauto == None): wwauto = 0
184
1424
185 if (n0 < 1.e-20): n0 = 1.e-20
1425 if (n0 < 1.e-20): n0 = 1.e-20
186
1426
187 freq = oldfreq
1427 freq = oldfreq
188 vec_power = numpy.zeros(oldspec.shape[1])
1428 vec_power = numpy.zeros(oldspec.shape[1])
189 vec_fd = numpy.zeros(oldspec.shape[1])
1429 vec_fd = numpy.zeros(oldspec.shape[1])
190 vec_w = numpy.zeros(oldspec.shape[1])
1430 vec_w = numpy.zeros(oldspec.shape[1])
191 vec_snr = numpy.zeros(oldspec.shape[1])
1431 vec_snr = numpy.zeros(oldspec.shape[1])
192
1432
193 for ind in range(oldspec.shape[1]):
1433 for ind in range(oldspec.shape[1]):
194
1434
195 spec = oldspec[:,ind]
1435 spec = oldspec[:,ind]
196 aux = spec*fwindow
1436 aux = spec*fwindow
197 max_spec = aux.max()
1437 max_spec = aux.max()
198 m = list(aux).index(max_spec)
1438 m = list(aux).index(max_spec)
199
1439
200 #Smooth
1440 #Smooth
201 if (smooth == 0): spec2 = spec
1441 if (smooth == 0): spec2 = spec
202 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1442 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
203
1443
204 # Calculo de Momentos
1444 # Calculo de Momentos
205 bb = spec2[range(m,spec2.size)]
1445 bb = spec2[range(m,spec2.size)]
206 bb = (bb<n0).nonzero()
1446 bb = (bb<n0).nonzero()
207 bb = bb[0]
1447 bb = bb[0]
208
1448
209 ss = spec2[range(0,m + 1)]
1449 ss = spec2[range(0,m + 1)]
210 ss = (ss<n0).nonzero()
1450 ss = (ss<n0).nonzero()
211 ss = ss[0]
1451 ss = ss[0]
212
1452
213 if (bb.size == 0):
1453 if (bb.size == 0):
214 bb0 = spec.size - 1 - m
1454 bb0 = spec.size - 1 - m
215 else:
1455 else:
216 bb0 = bb[0] - 1
1456 bb0 = bb[0] - 1
217 if (bb0 < 0):
1457 if (bb0 < 0):
218 bb0 = 0
1458 bb0 = 0
219
1459
220 if (ss.size == 0): ss1 = 1
1460 if (ss.size == 0): ss1 = 1
221 else: ss1 = max(ss) + 1
1461 else: ss1 = max(ss) + 1
222
1462
223 if (ss1 > m): ss1 = m
1463 if (ss1 > m): ss1 = m
224
1464
225 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
1465 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
226 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
1466 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
227 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
1467 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
228 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1468 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
229 snr = (spec2.mean()-n0)/n0
1469 snr = (spec2.mean()-n0)/n0
230
1470
231 if (snr < 1.e-20) :
1471 if (snr < 1.e-20) :
232 snr = 1.e-20
1472 snr = 1.e-20
233
1473
234 vec_power[ind] = power
1474 vec_power[ind] = power
235 vec_fd[ind] = fd
1475 vec_fd[ind] = fd
236 vec_w[ind] = w
1476 vec_w[ind] = w
237 vec_snr[ind] = snr
1477 vec_snr[ind] = snr
238
1478
239 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1479 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
240 return moments
1480 return moments
241
1481
242 #------------------ Get SA Parameters --------------------------
1482 #------------------ Get SA Parameters --------------------------
243
1483
244 def GetSAParameters(self):
1484 def GetSAParameters(self):
245 #SA en frecuencia
1485 #SA en frecuencia
246 pairslist = self.dataOut.groupList
1486 pairslist = self.dataOut.groupList
247 num_pairs = len(pairslist)
1487 num_pairs = len(pairslist)
248
1488
249 vel = self.dataOut.abscissaList
1489 vel = self.dataOut.abscissaList
250 spectra = self.dataOut.data_pre[0]
1490 spectra = self.dataOut.data_pre
251 cspectra = self.dataOut.data_pre[1]
1491 cspectra = self.dataIn.data_cspc
252 delta_v = vel[1] - vel[0]
1492 delta_v = vel[1] - vel[0]
253
1493
254 #Calculating the power spectrum
1494 #Calculating the power spectrum
255 spc_pow = numpy.sum(spectra, 3)*delta_v
1495 spc_pow = numpy.sum(spectra, 3)*delta_v
256 #Normalizing Spectra
1496 #Normalizing Spectra
257 norm_spectra = spectra/spc_pow
1497 norm_spectra = spectra/spc_pow
258 #Calculating the norm_spectra at peak
1498 #Calculating the norm_spectra at peak
259 max_spectra = numpy.max(norm_spectra, 3)
1499 max_spectra = numpy.max(norm_spectra, 3)
260
1500
261 #Normalizing Cross Spectra
1501 #Normalizing Cross Spectra
262 norm_cspectra = numpy.zeros(cspectra.shape)
1502 norm_cspectra = numpy.zeros(cspectra.shape)
263
1503
264 for i in range(num_chan):
1504 for i in range(num_chan):
265 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1505 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
266
1506
267 max_cspectra = numpy.max(norm_cspectra,2)
1507 max_cspectra = numpy.max(norm_cspectra,2)
268 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1508 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
269
1509
270 for i in range(num_pairs):
1510 for i in range(num_pairs):
271 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1511 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
272 #------------------- Get Lags ----------------------------------
1512 #------------------- Get Lags ----------------------------------
273
1513
274 class SALags(Operation):
1514 class SALags(Operation):
275 '''
1515 '''
276 Function GetMoments()
1516 Function GetMoments()
277
1517
278 Input:
1518 Input:
279 self.dataOut.data_pre
1519 self.dataOut.data_pre
280 self.dataOut.abscissaList
1520 self.dataOut.abscissaList
281 self.dataOut.noise
1521 self.dataOut.noise
282 self.dataOut.normFactor
1522 self.dataOut.normFactor
283 self.dataOut.data_SNR
1523 self.dataOut.data_SNR
284 self.dataOut.groupList
1524 self.dataOut.groupList
285 self.dataOut.nChannels
1525 self.dataOut.nChannels
286
1526
287 Affected:
1527 Affected:
288 self.dataOut.data_param
1528 self.dataOut.data_param
289
1529
290 '''
1530 '''
291 def run(self, dataOut):
1531 def run(self, dataOut):
292 data_acf = dataOut.data_pre[0]
1532 data_acf = dataOut.data_pre[0]
293 data_ccf = dataOut.data_pre[1]
1533 data_ccf = dataOut.data_pre[1]
294 normFactor_acf = dataOut.normFactor[0]
1534 normFactor_acf = dataOut.normFactor[0]
295 normFactor_ccf = dataOut.normFactor[1]
1535 normFactor_ccf = dataOut.normFactor[1]
296 pairs_acf = dataOut.groupList[0]
1536 pairs_acf = dataOut.groupList[0]
297 pairs_ccf = dataOut.groupList[1]
1537 pairs_ccf = dataOut.groupList[1]
298
1538
299 nHeights = dataOut.nHeights
1539 nHeights = dataOut.nHeights
300 absc = dataOut.abscissaList
1540 absc = dataOut.abscissaList
301 noise = dataOut.noise
1541 noise = dataOut.noise
302 SNR = dataOut.data_SNR
1542 SNR = dataOut.data_SNR
303 nChannels = dataOut.nChannels
1543 nChannels = dataOut.nChannels
304 # pairsList = dataOut.groupList
1544 # pairsList = dataOut.groupList
305 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1545 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
306
1546
307 for l in range(len(pairs_acf)):
1547 for l in range(len(pairs_acf)):
308 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1548 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
309
1549
310 for l in range(len(pairs_ccf)):
1550 for l in range(len(pairs_ccf)):
311 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1551 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
312
1552
313 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1553 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
314 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1554 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
315 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1555 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
316 return
1556 return
317
1557
318 # def __getPairsAutoCorr(self, pairsList, nChannels):
1558 # def __getPairsAutoCorr(self, pairsList, nChannels):
319 #
1559 #
320 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1560 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
321 #
1561 #
322 # for l in range(len(pairsList)):
1562 # for l in range(len(pairsList)):
323 # firstChannel = pairsList[l][0]
1563 # firstChannel = pairsList[l][0]
324 # secondChannel = pairsList[l][1]
1564 # secondChannel = pairsList[l][1]
325 #
1565 #
326 # #Obteniendo pares de Autocorrelacion
1566 # #Obteniendo pares de Autocorrelacion
327 # if firstChannel == secondChannel:
1567 # if firstChannel == secondChannel:
328 # pairsAutoCorr[firstChannel] = int(l)
1568 # pairsAutoCorr[firstChannel] = int(l)
329 #
1569 #
330 # pairsAutoCorr = pairsAutoCorr.astype(int)
1570 # pairsAutoCorr = pairsAutoCorr.astype(int)
331 #
1571 #
332 # pairsCrossCorr = range(len(pairsList))
1572 # pairsCrossCorr = range(len(pairsList))
333 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1573 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
334 #
1574 #
335 # return pairsAutoCorr, pairsCrossCorr
1575 # return pairsAutoCorr, pairsCrossCorr
336
1576
337 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1577 def __calculateTaus(self, data_acf, data_ccf, lagRange):
338
1578
339 lag0 = data_acf.shape[1]/2
1579 lag0 = data_acf.shape[1]/2
340 #Funcion de Autocorrelacion
1580 #Funcion de Autocorrelacion
341 mean_acf = stats.nanmean(data_acf, axis = 0)
1581 mean_acf = stats.nanmean(data_acf, axis = 0)
342
1582
343 #Obtencion Indice de TauCross
1583 #Obtencion Indice de TauCross
344 ind_ccf = data_ccf.argmax(axis = 1)
1584 ind_ccf = data_ccf.argmax(axis = 1)
345 #Obtencion Indice de TauAuto
1585 #Obtencion Indice de TauAuto
346 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1586 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
347 ccf_lag0 = data_ccf[:,lag0,:]
1587 ccf_lag0 = data_ccf[:,lag0,:]
348
1588
349 for i in range(ccf_lag0.shape[0]):
1589 for i in range(ccf_lag0.shape[0]):
350 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1590 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
351
1591
352 #Obtencion de TauCross y TauAuto
1592 #Obtencion de TauCross y TauAuto
353 tau_ccf = lagRange[ind_ccf]
1593 tau_ccf = lagRange[ind_ccf]
354 tau_acf = lagRange[ind_acf]
1594 tau_acf = lagRange[ind_acf]
355
1595
356 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1596 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
357
1597
358 tau_ccf[Nan1,Nan2] = numpy.nan
1598 tau_ccf[Nan1,Nan2] = numpy.nan
359 tau_acf[Nan1,Nan2] = numpy.nan
1599 tau_acf[Nan1,Nan2] = numpy.nan
360 tau = numpy.vstack((tau_ccf,tau_acf))
1600 tau = numpy.vstack((tau_ccf,tau_acf))
361
1601
362 return tau
1602 return tau
363
1603
364 def __calculateLag1Phase(self, data, lagTRange):
1604 def __calculateLag1Phase(self, data, lagTRange):
365 data1 = stats.nanmean(data, axis = 0)
1605 data1 = stats.nanmean(data, axis = 0)
366 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1606 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
367
1607
368 phase = numpy.angle(data1[lag1,:])
1608 phase = numpy.angle(data1[lag1,:])
369
1609
370 return phase
1610 return phase
371
1611
372 class SpectralFitting(Operation):
1612 class SpectralFitting(Operation):
373 '''
1613 '''
374 Function GetMoments()
1614 Function GetMoments()
375
1615
376 Input:
1616 Input:
377 Output:
1617 Output:
378 Variables modified:
1618 Variables modified:
379 '''
1619 '''
380
1620
381 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1621 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
382
1622
383
1623
384 if path != None:
1624 if path != None:
385 sys.path.append(path)
1625 sys.path.append(path)
386 self.dataOut.library = importlib.import_module(file)
1626 self.dataOut.library = importlib.import_module(file)
387
1627
388 #To be inserted as a parameter
1628 #To be inserted as a parameter
389 groupArray = numpy.array(groupList)
1629 groupArray = numpy.array(groupList)
390 # groupArray = numpy.array([[0,1],[2,3]])
1630 # groupArray = numpy.array([[0,1],[2,3]])
391 self.dataOut.groupList = groupArray
1631 self.dataOut.groupList = groupArray
392
1632
393 nGroups = groupArray.shape[0]
1633 nGroups = groupArray.shape[0]
394 nChannels = self.dataIn.nChannels
1634 nChannels = self.dataIn.nChannels
395 nHeights=self.dataIn.heightList.size
1635 nHeights=self.dataIn.heightList.size
396
1636
397 #Parameters Array
1637 #Parameters Array
398 self.dataOut.data_param = None
1638 self.dataOut.data_param = None
399
1639
400 #Set constants
1640 #Set constants
401 constants = self.dataOut.library.setConstants(self.dataIn)
1641 constants = self.dataOut.library.setConstants(self.dataIn)
402 self.dataOut.constants = constants
1642 self.dataOut.constants = constants
403 M = self.dataIn.normFactor
1643 M = self.dataIn.normFactor
404 N = self.dataIn.nFFTPoints
1644 N = self.dataIn.nFFTPoints
405 ippSeconds = self.dataIn.ippSeconds
1645 ippSeconds = self.dataIn.ippSeconds
406 K = self.dataIn.nIncohInt
1646 K = self.dataIn.nIncohInt
407 pairsArray = numpy.array(self.dataIn.pairsList)
1647 pairsArray = numpy.array(self.dataIn.pairsList)
408
1648
409 #List of possible combinations
1649 #List of possible combinations
410 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1650 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
411 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1651 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
412
1652
413 if getSNR:
1653 if getSNR:
414 listChannels = groupArray.reshape((groupArray.size))
1654 listChannels = groupArray.reshape((groupArray.size))
415 listChannels.sort()
1655 listChannels.sort()
416 noise = self.dataIn.getNoise()
1656 noise = self.dataIn.getNoise()
417 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1657 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
418
1658
419 for i in range(nGroups):
1659 for i in range(nGroups):
420 coord = groupArray[i,:]
1660 coord = groupArray[i,:]
421
1661
422 #Input data array
1662 #Input data array
423 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1663 data = self.dataIn.data_spc[coord,:,:]/(M*N)
424 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1664 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
425
1665
426 #Cross Spectra data array for Covariance Matrixes
1666 #Cross Spectra data array for Covariance Matrixes
427 ind = 0
1667 ind = 0
428 for pairs in listComb:
1668 for pairs in listComb:
429 pairsSel = numpy.array([coord[x],coord[y]])
1669 pairsSel = numpy.array([coord[x],coord[y]])
430 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1670 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
431 ind += 1
1671 ind += 1
432 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1672 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
433 dataCross = dataCross**2/K
1673 dataCross = dataCross**2/K
434
1674
435 for h in range(nHeights):
1675 for h in range(nHeights):
436 # print self.dataOut.heightList[h]
1676 # print self.dataOut.heightList[h]
437
1677
438 #Input
1678 #Input
439 d = data[:,h]
1679 d = data[:,h]
440
1680
441 #Covariance Matrix
1681 #Covariance Matrix
442 D = numpy.diag(d**2/K)
1682 D = numpy.diag(d**2/K)
443 ind = 0
1683 ind = 0
444 for pairs in listComb:
1684 for pairs in listComb:
445 #Coordinates in Covariance Matrix
1685 #Coordinates in Covariance Matrix
446 x = pairs[0]
1686 x = pairs[0]
447 y = pairs[1]
1687 y = pairs[1]
448 #Channel Index
1688 #Channel Index
449 S12 = dataCross[ind,:,h]
1689 S12 = dataCross[ind,:,h]
450 D12 = numpy.diag(S12)
1690 D12 = numpy.diag(S12)
451 #Completing Covariance Matrix with Cross Spectras
1691 #Completing Covariance Matrix with Cross Spectras
452 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1692 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
453 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1693 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
454 ind += 1
1694 ind += 1
455 Dinv=numpy.linalg.inv(D)
1695 Dinv=numpy.linalg.inv(D)
456 L=numpy.linalg.cholesky(Dinv)
1696 L=numpy.linalg.cholesky(Dinv)
457 LT=L.T
1697 LT=L.T
458
1698
459 dp = numpy.dot(LT,d)
1699 dp = numpy.dot(LT,d)
460
1700
461 #Initial values
1701 #Initial values
462 data_spc = self.dataIn.data_spc[coord,:,h]
1702 data_spc = self.dataIn.data_spc[coord,:,h]
463
1703
464 if (h>0)and(error1[3]<5):
1704 if (h>0)and(error1[3]<5):
465 p0 = self.dataOut.data_param[i,:,h-1]
1705 p0 = self.dataOut.data_param[i,:,h-1]
466 else:
1706 else:
467 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1707 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
468
1708
469 try:
1709 try:
470 #Least Squares
1710 #Least Squares
471 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1711 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
472 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1712 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
473 #Chi square error
1713 #Chi square error
474 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1714 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
475 #Error with Jacobian
1715 #Error with Jacobian
476 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1716 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
477 except:
1717 except:
478 minp = p0*numpy.nan
1718 minp = p0*numpy.nan
479 error0 = numpy.nan
1719 error0 = numpy.nan
480 error1 = p0*numpy.nan
1720 error1 = p0*numpy.nan
481
1721
482 #Save
1722 #Save
483 if self.dataOut.data_param is None:
1723 if self.dataOut.data_param == None:
484 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1724 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
485 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1725 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
486
1726
487 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1727 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
488 self.dataOut.data_param[i,:,h] = minp
1728 self.dataOut.data_param[i,:,h] = minp
489 return
1729 return
490
1730
491 def __residFunction(self, p, dp, LT, constants):
1731 def __residFunction(self, p, dp, LT, constants):
492
1732
493 fm = self.dataOut.library.modelFunction(p, constants)
1733 fm = self.dataOut.library.modelFunction(p, constants)
494 fmp=numpy.dot(LT,fm)
1734 fmp=numpy.dot(LT,fm)
495
1735
496 return dp-fmp
1736 return dp-fmp
497
1737
498 def __getSNR(self, z, noise):
1738 def __getSNR(self, z, noise):
499
1739
500 avg = numpy.average(z, axis=1)
1740 avg = numpy.average(z, axis=1)
501 SNR = (avg.T-noise)/noise
1741 SNR = (avg.T-noise)/noise
502 SNR = SNR.T
1742 SNR = SNR.T
503 return SNR
1743 return SNR
504
1744
505 def __chisq(p,chindex,hindex):
1745 def __chisq(p,chindex,hindex):
506 #similar to Resid but calculates CHI**2
1746 #similar to Resid but calculates CHI**2
507 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1747 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
508 dp=numpy.dot(LT,d)
1748 dp=numpy.dot(LT,d)
509 fmp=numpy.dot(LT,fm)
1749 fmp=numpy.dot(LT,fm)
510 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1750 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
511 return chisq
1751 return chisq
512
1752
513 class WindProfiler(Operation):
1753 class WindProfiler(Operation):
514
1754
515 __isConfig = False
1755 __isConfig = False
516
1756
517 __initime = None
1757 __initime = None
518 __lastdatatime = None
1758 __lastdatatime = None
519 __integrationtime = None
1759 __integrationtime = None
520
1760
521 __buffer = None
1761 __buffer = None
522
1762
523 __dataReady = False
1763 __dataReady = False
524
1764
525 __firstdata = None
1765 __firstdata = None
526
1766
527 n = None
1767 n = None
528
1768
1769 def __init__(self):
1770 Operation.__init__(self)
1771
529 def __calculateCosDir(self, elev, azim):
1772 def __calculateCosDir(self, elev, azim):
530 zen = (90 - elev)*numpy.pi/180
1773 zen = (90 - elev)*numpy.pi/180
531 azim = azim*numpy.pi/180
1774 azim = azim*numpy.pi/180
532 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1775 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
533 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1776 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
534
1777
535 signX = numpy.sign(numpy.cos(azim))
1778 signX = numpy.sign(numpy.cos(azim))
536 signY = numpy.sign(numpy.sin(azim))
1779 signY = numpy.sign(numpy.sin(azim))
537
1780
538 cosDirX = numpy.copysign(cosDirX, signX)
1781 cosDirX = numpy.copysign(cosDirX, signX)
539 cosDirY = numpy.copysign(cosDirY, signY)
1782 cosDirY = numpy.copysign(cosDirY, signY)
540 return cosDirX, cosDirY
1783 return cosDirX, cosDirY
541
1784
542 def __calculateAngles(self, theta_x, theta_y, azimuth):
1785 def __calculateAngles(self, theta_x, theta_y, azimuth):
543
1786
544 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1787 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
545 zenith_arr = numpy.arccos(dir_cosw)
1788 zenith_arr = numpy.arccos(dir_cosw)
546 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1789 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
547
1790
548 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1791 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
549 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1792 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
550
1793
551 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1794 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
552
1795
553 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1796 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
554
1797
555 #
1798 #
556 if horOnly:
1799 if horOnly:
557 A = numpy.c_[dir_cosu,dir_cosv]
1800 A = numpy.c_[dir_cosu,dir_cosv]
558 else:
1801 else:
559 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1802 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
560 A = numpy.asmatrix(A)
1803 A = numpy.asmatrix(A)
561 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1804 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
562
1805
563 return A1
1806 return A1
564
1807
565 def __correctValues(self, heiRang, phi, velRadial, SNR):
1808 def __correctValues(self, heiRang, phi, velRadial, SNR):
566 listPhi = phi.tolist()
1809 listPhi = phi.tolist()
567 maxid = listPhi.index(max(listPhi))
1810 maxid = listPhi.index(max(listPhi))
568 minid = listPhi.index(min(listPhi))
1811 minid = listPhi.index(min(listPhi))
569
1812
570 rango = range(len(phi))
1813 rango = range(len(phi))
571 # rango = numpy.delete(rango,maxid)
1814 # rango = numpy.delete(rango,maxid)
572
1815
573 heiRang1 = heiRang*math.cos(phi[maxid])
1816 heiRang1 = heiRang*math.cos(phi[maxid])
574 heiRangAux = heiRang*math.cos(phi[minid])
1817 heiRangAux = heiRang*math.cos(phi[minid])
575 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1818 indOut = (heiRang1 < heiRangAux[0]).nonzero()
576 heiRang1 = numpy.delete(heiRang1,indOut)
1819 heiRang1 = numpy.delete(heiRang1,indOut)
577
1820
578 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1821 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
579 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1822 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
580
1823
581 for i in rango:
1824 for i in rango:
582 x = heiRang*math.cos(phi[i])
1825 x = heiRang*math.cos(phi[i])
583 y1 = velRadial[i,:]
1826 y1 = velRadial[i,:]
584 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1827 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
585
1828
586 x1 = heiRang1
1829 x1 = heiRang1
587 y11 = f1(x1)
1830 y11 = f1(x1)
588
1831
589 y2 = SNR[i,:]
1832 y2 = SNR[i,:]
590 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1833 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
591 y21 = f2(x1)
1834 y21 = f2(x1)
592
1835
593 velRadial1[i,:] = y11
1836 velRadial1[i,:] = y11
594 SNR1[i,:] = y21
1837 SNR1[i,:] = y21
595
1838
596 return heiRang1, velRadial1, SNR1
1839 return heiRang1, velRadial1, SNR1
597
1840
598 def __calculateVelUVW(self, A, velRadial):
1841 def __calculateVelUVW(self, A, velRadial):
599
1842
600 #Operacion Matricial
1843 #Operacion Matricial
601 # velUVW = numpy.zeros((velRadial.shape[1],3))
1844 # velUVW = numpy.zeros((velRadial.shape[1],3))
602 # for ind in range(velRadial.shape[1]):
1845 # for ind in range(velRadial.shape[1]):
603 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1846 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
604 # velUVW = velUVW.transpose()
1847 # velUVW = velUVW.transpose()
605 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1848 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
606 velUVW[:,:] = numpy.dot(A,velRadial)
1849 velUVW[:,:] = numpy.dot(A,velRadial)
607
1850
608
1851
609 return velUVW
1852 return velUVW
610
1853
611 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1854 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
612
1855
613 def techniqueDBS(self, kwargs):
1856 def techniqueDBS(self, kwargs):
614 """
1857 """
615 Function that implements Doppler Beam Swinging (DBS) technique.
1858 Function that implements Doppler Beam Swinging (DBS) technique.
616
1859
617 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1860 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
618 Direction correction (if necessary), Ranges and SNR
1861 Direction correction (if necessary), Ranges and SNR
619
1862
620 Output: Winds estimation (Zonal, Meridional and Vertical)
1863 Output: Winds estimation (Zonal, Meridional and Vertical)
621
1864
622 Parameters affected: Winds, height range, SNR
1865 Parameters affected: Winds, height range, SNR
623 """
1866 """
624 velRadial0 = kwargs['velRadial']
1867 velRadial0 = kwargs['velRadial']
625 heiRang = kwargs['heightList']
1868 heiRang = kwargs['heightList']
626 SNR0 = kwargs['SNR']
1869 SNR0 = kwargs['SNR']
627
1870
628 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
1871 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
629 theta_x = numpy.array(kwargs['dirCosx'])
1872 theta_x = numpy.array(kwargs['dirCosx'])
630 theta_y = numpy.array(kwargs['dirCosy'])
1873 theta_y = numpy.array(kwargs['dirCosy'])
631 else:
1874 else:
632 elev = numpy.array(kwargs['elevation'])
1875 elev = numpy.array(kwargs['elevation'])
633 azim = numpy.array(kwargs['azimuth'])
1876 azim = numpy.array(kwargs['azimuth'])
634 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1877 theta_x, theta_y = self.__calculateCosDir(elev, azim)
635 azimuth = kwargs['correctAzimuth']
1878 azimuth = kwargs['correctAzimuth']
636 if kwargs.has_key('horizontalOnly'):
1879 if kwargs.has_key('horizontalOnly'):
637 horizontalOnly = kwargs['horizontalOnly']
1880 horizontalOnly = kwargs['horizontalOnly']
638 else: horizontalOnly = False
1881 else: horizontalOnly = False
639 if kwargs.has_key('correctFactor'):
1882 if kwargs.has_key('correctFactor'):
640 correctFactor = kwargs['correctFactor']
1883 correctFactor = kwargs['correctFactor']
641 else: correctFactor = 1
1884 else: correctFactor = 1
642 if kwargs.has_key('channelList'):
1885 if kwargs.has_key('channelList'):
643 channelList = kwargs['channelList']
1886 channelList = kwargs['channelList']
644 if len(channelList) == 2:
1887 if len(channelList) == 2:
645 horizontalOnly = True
1888 horizontalOnly = True
646 arrayChannel = numpy.array(channelList)
1889 arrayChannel = numpy.array(channelList)
647 param = param[arrayChannel,:,:]
1890 param = param[arrayChannel,:,:]
648 theta_x = theta_x[arrayChannel]
1891 theta_x = theta_x[arrayChannel]
649 theta_y = theta_y[arrayChannel]
1892 theta_y = theta_y[arrayChannel]
650
1893
651 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1894 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
652 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1895 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
653 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1896 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
654
1897
655 #Calculo de Componentes de la velocidad con DBS
1898 #Calculo de Componentes de la velocidad con DBS
656 winds = self.__calculateVelUVW(A,velRadial1)
1899 winds = self.__calculateVelUVW(A,velRadial1)
657
1900
658 return winds, heiRang1, SNR1
1901 return winds, heiRang1, SNR1
659
1902
660 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1903 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
661
1904
662 nPairs = len(pairs_ccf)
1905 nPairs = len(pairs_ccf)
663 posx = numpy.asarray(posx)
1906 posx = numpy.asarray(posx)
664 posy = numpy.asarray(posy)
1907 posy = numpy.asarray(posy)
665
1908
666 #Rotacion Inversa para alinear con el azimuth
1909 #Rotacion Inversa para alinear con el azimuth
667 if azimuth!= None:
1910 if azimuth!= None:
668 azimuth = azimuth*math.pi/180
1911 azimuth = azimuth*math.pi/180
669 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1912 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
670 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1913 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
671 else:
1914 else:
672 posx1 = posx
1915 posx1 = posx
673 posy1 = posy
1916 posy1 = posy
674
1917
675 #Calculo de Distancias
1918 #Calculo de Distancias
676 distx = numpy.zeros(nPairs)
1919 distx = numpy.zeros(nPairs)
677 disty = numpy.zeros(nPairs)
1920 disty = numpy.zeros(nPairs)
678 dist = numpy.zeros(nPairs)
1921 dist = numpy.zeros(nPairs)
679 ang = numpy.zeros(nPairs)
1922 ang = numpy.zeros(nPairs)
680
1923
681 for i in range(nPairs):
1924 for i in range(nPairs):
682 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1925 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
683 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1926 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
684 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1927 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
685 ang[i] = numpy.arctan2(disty[i],distx[i])
1928 ang[i] = numpy.arctan2(disty[i],distx[i])
686
1929
687 return distx, disty, dist, ang
1930 return distx, disty, dist, ang
688 #Calculo de Matrices
1931 #Calculo de Matrices
689 # nPairs = len(pairs)
1932 # nPairs = len(pairs)
690 # ang1 = numpy.zeros((nPairs, 2, 1))
1933 # ang1 = numpy.zeros((nPairs, 2, 1))
691 # dist1 = numpy.zeros((nPairs, 2, 1))
1934 # dist1 = numpy.zeros((nPairs, 2, 1))
692 #
1935 #
693 # for j in range(nPairs):
1936 # for j in range(nPairs):
694 # dist1[j,0,0] = dist[pairs[j][0]]
1937 # dist1[j,0,0] = dist[pairs[j][0]]
695 # dist1[j,1,0] = dist[pairs[j][1]]
1938 # dist1[j,1,0] = dist[pairs[j][1]]
696 # ang1[j,0,0] = ang[pairs[j][0]]
1939 # ang1[j,0,0] = ang[pairs[j][0]]
697 # ang1[j,1,0] = ang[pairs[j][1]]
1940 # ang1[j,1,0] = ang[pairs[j][1]]
698 #
1941 #
699 # return distx,disty, dist1,ang1
1942 # return distx,disty, dist1,ang1
700
1943
701
1944
702 def __calculateVelVer(self, phase, lagTRange, _lambda):
1945 def __calculateVelVer(self, phase, lagTRange, _lambda):
703
1946
704 Ts = lagTRange[1] - lagTRange[0]
1947 Ts = lagTRange[1] - lagTRange[0]
705 velW = -_lambda*phase/(4*math.pi*Ts)
1948 velW = -_lambda*phase/(4*math.pi*Ts)
706
1949
707 return velW
1950 return velW
708
1951
709 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1952 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
710 nPairs = tau1.shape[0]
1953 nPairs = tau1.shape[0]
711 nHeights = tau1.shape[1]
1954 nHeights = tau1.shape[1]
712 vel = numpy.zeros((nPairs,3,nHeights))
1955 vel = numpy.zeros((nPairs,3,nHeights))
713 dist1 = numpy.reshape(dist, (dist.size,1))
1956 dist1 = numpy.reshape(dist, (dist.size,1))
714
1957
715 angCos = numpy.cos(ang)
1958 angCos = numpy.cos(ang)
716 angSin = numpy.sin(ang)
1959 angSin = numpy.sin(ang)
717
1960
718 vel0 = dist1*tau1/(2*tau2**2)
1961 vel0 = dist1*tau1/(2*tau2**2)
719 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1962 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
720 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1963 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
721
1964
722 ind = numpy.where(numpy.isinf(vel))
1965 ind = numpy.where(numpy.isinf(vel))
723 vel[ind] = numpy.nan
1966 vel[ind] = numpy.nan
724
1967
725 return vel
1968 return vel
726
1969
727 # def __getPairsAutoCorr(self, pairsList, nChannels):
1970 # def __getPairsAutoCorr(self, pairsList, nChannels):
728 #
1971 #
729 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1972 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
730 #
1973 #
731 # for l in range(len(pairsList)):
1974 # for l in range(len(pairsList)):
732 # firstChannel = pairsList[l][0]
1975 # firstChannel = pairsList[l][0]
733 # secondChannel = pairsList[l][1]
1976 # secondChannel = pairsList[l][1]
734 #
1977 #
735 # #Obteniendo pares de Autocorrelacion
1978 # #Obteniendo pares de Autocorrelacion
736 # if firstChannel == secondChannel:
1979 # if firstChannel == secondChannel:
737 # pairsAutoCorr[firstChannel] = int(l)
1980 # pairsAutoCorr[firstChannel] = int(l)
738 #
1981 #
739 # pairsAutoCorr = pairsAutoCorr.astype(int)
1982 # pairsAutoCorr = pairsAutoCorr.astype(int)
740 #
1983 #
741 # pairsCrossCorr = range(len(pairsList))
1984 # pairsCrossCorr = range(len(pairsList))
742 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1985 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
743 #
1986 #
744 # return pairsAutoCorr, pairsCrossCorr
1987 # return pairsAutoCorr, pairsCrossCorr
745
1988
746 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1989 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
747 def techniqueSA(self, kwargs):
1990 def techniqueSA(self, kwargs):
748
1991
749 """
1992 """
750 Function that implements Spaced Antenna (SA) technique.
1993 Function that implements Spaced Antenna (SA) technique.
751
1994
752 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1995 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
753 Direction correction (if necessary), Ranges and SNR
1996 Direction correction (if necessary), Ranges and SNR
754
1997
755 Output: Winds estimation (Zonal, Meridional and Vertical)
1998 Output: Winds estimation (Zonal, Meridional and Vertical)
756
1999
757 Parameters affected: Winds
2000 Parameters affected: Winds
758 """
2001 """
759 position_x = kwargs['positionX']
2002 position_x = kwargs['positionX']
760 position_y = kwargs['positionY']
2003 position_y = kwargs['positionY']
761 azimuth = kwargs['azimuth']
2004 azimuth = kwargs['azimuth']
762
2005
763 if kwargs.has_key('correctFactor'):
2006 if kwargs.has_key('correctFactor'):
764 correctFactor = kwargs['correctFactor']
2007 correctFactor = kwargs['correctFactor']
765 else:
2008 else:
766 correctFactor = 1
2009 correctFactor = 1
767
2010
768 groupList = kwargs['groupList']
2011 groupList = kwargs['groupList']
769 pairs_ccf = groupList[1]
2012 pairs_ccf = groupList[1]
770 tau = kwargs['tau']
2013 tau = kwargs['tau']
771 _lambda = kwargs['_lambda']
2014 _lambda = kwargs['_lambda']
772
2015
773 #Cross Correlation pairs obtained
2016 #Cross Correlation pairs obtained
774 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
2017 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
775 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
2018 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
776 # pairsSelArray = numpy.array(pairsSelected)
2019 # pairsSelArray = numpy.array(pairsSelected)
777 # pairs = []
2020 # pairs = []
778 #
2021 #
779 # #Wind estimation pairs obtained
2022 # #Wind estimation pairs obtained
780 # for i in range(pairsSelArray.shape[0]/2):
2023 # for i in range(pairsSelArray.shape[0]/2):
781 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
2024 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
782 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
2025 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
783 # pairs.append((ind1,ind2))
2026 # pairs.append((ind1,ind2))
784
2027
785 indtau = tau.shape[0]/2
2028 indtau = tau.shape[0]/2
786 tau1 = tau[:indtau,:]
2029 tau1 = tau[:indtau,:]
787 tau2 = tau[indtau:-1,:]
2030 tau2 = tau[indtau:-1,:]
788 # tau1 = tau1[pairs,:]
2031 # tau1 = tau1[pairs,:]
789 # tau2 = tau2[pairs,:]
2032 # tau2 = tau2[pairs,:]
790 phase1 = tau[-1,:]
2033 phase1 = tau[-1,:]
791
2034
792 #---------------------------------------------------------------------
2035 #---------------------------------------------------------------------
793 #Metodo Directo
2036 #Metodo Directo
794 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
2037 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
795 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
2038 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
796 winds = stats.nanmean(winds, axis=0)
2039 winds = stats.nanmean(winds, axis=0)
797 #---------------------------------------------------------------------
2040 #---------------------------------------------------------------------
798 #Metodo General
2041 #Metodo General
799 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
2042 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
800 # #Calculo Coeficientes de Funcion de Correlacion
2043 # #Calculo Coeficientes de Funcion de Correlacion
801 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
2044 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
802 # #Calculo de Velocidades
2045 # #Calculo de Velocidades
803 # winds = self.calculateVelUV(F,G,A,B,H)
2046 # winds = self.calculateVelUV(F,G,A,B,H)
804
2047
805 #---------------------------------------------------------------------
2048 #---------------------------------------------------------------------
806 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
2049 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
807 winds = correctFactor*winds
2050 winds = correctFactor*winds
808 return winds
2051 return winds
809
2052
810 def __checkTime(self, currentTime, paramInterval, outputInterval):
2053 def __checkTime(self, currentTime, paramInterval, outputInterval):
811
2054
812 dataTime = currentTime + paramInterval
2055 dataTime = currentTime + paramInterval
813 deltaTime = dataTime - self.__initime
2056 deltaTime = dataTime - self.__initime
814
2057
815 if deltaTime >= outputInterval or deltaTime < 0:
2058 if deltaTime >= outputInterval or deltaTime < 0:
816 self.__dataReady = True
2059 self.__dataReady = True
817 return
2060 return
818
2061
819 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax, binkm=2):
2062 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
820 '''
2063 '''
821 Function that implements winds estimation technique with detected meteors.
2064 Function that implements winds estimation technique with detected meteors.
822
2065
823 Input: Detected meteors, Minimum meteor quantity to wind estimation
2066 Input: Detected meteors, Minimum meteor quantity to wind estimation
824
2067
825 Output: Winds estimation (Zonal and Meridional)
2068 Output: Winds estimation (Zonal and Meridional)
826
2069
827 Parameters affected: Winds
2070 Parameters affected: Winds
828 '''
2071 '''
829 # print arrayMeteor.shape
2072 # print arrayMeteor.shape
830 #Settings
2073 #Settings
831 nInt = (heightMax - heightMin)/binkm
2074 nInt = (heightMax - heightMin)/2
832 # print nInt
2075 # print nInt
833 nInt = int(nInt)
2076 nInt = int(nInt)
834 # print nInt
2077 # print nInt
835 winds = numpy.zeros((2,nInt))*numpy.nan
2078 winds = numpy.zeros((2,nInt))*numpy.nan
836
2079
837 #Filter errors
2080 #Filter errors
838 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
2081 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
839 finalMeteor = arrayMeteor[error,:]
2082 finalMeteor = arrayMeteor[error,:]
840
2083
841 #Meteor Histogram
2084 #Meteor Histogram
842 finalHeights = finalMeteor[:,2]
2085 finalHeights = finalMeteor[:,2]
843 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
2086 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
844 nMeteorsPerI = hist[0]
2087 nMeteorsPerI = hist[0]
845 heightPerI = hist[1]
2088 heightPerI = hist[1]
846
2089
847 #Sort of meteors
2090 #Sort of meteors
848 indSort = finalHeights.argsort()
2091 indSort = finalHeights.argsort()
849 finalMeteor2 = finalMeteor[indSort,:]
2092 finalMeteor2 = finalMeteor[indSort,:]
850
2093
851 # Calculating winds
2094 # Calculating winds
852 ind1 = 0
2095 ind1 = 0
853 ind2 = 0
2096 ind2 = 0
854
2097
855 for i in range(nInt):
2098 for i in range(nInt):
856 nMet = nMeteorsPerI[i]
2099 nMet = nMeteorsPerI[i]
857 ind1 = ind2
2100 ind1 = ind2
858 ind2 = ind1 + nMet
2101 ind2 = ind1 + nMet
859
2102
860 meteorAux = finalMeteor2[ind1:ind2,:]
2103 meteorAux = finalMeteor2[ind1:ind2,:]
861
2104
862 if meteorAux.shape[0] >= meteorThresh:
2105 if meteorAux.shape[0] >= meteorThresh:
863 vel = meteorAux[:, 6]
2106 vel = meteorAux[:, 6]
864 zen = meteorAux[:, 4]*numpy.pi/180
2107 zen = meteorAux[:, 4]*numpy.pi/180
865 azim = meteorAux[:, 3]*numpy.pi/180
2108 azim = meteorAux[:, 3]*numpy.pi/180
866
2109
867 n = numpy.cos(zen)
2110 n = numpy.cos(zen)
868 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
2111 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
869 # l = m*numpy.tan(azim)
2112 # l = m*numpy.tan(azim)
870 l = numpy.sin(zen)*numpy.sin(azim)
2113 l = numpy.sin(zen)*numpy.sin(azim)
871 m = numpy.sin(zen)*numpy.cos(azim)
2114 m = numpy.sin(zen)*numpy.cos(azim)
872
2115
873 A = numpy.vstack((l, m)).transpose()
2116 A = numpy.vstack((l, m)).transpose()
874 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
2117 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
875 windsAux = numpy.dot(A1, vel)
2118 windsAux = numpy.dot(A1, vel)
876
2119
877 winds[0,i] = windsAux[0]
2120 winds[0,i] = windsAux[0]
878 winds[1,i] = windsAux[1]
2121 winds[1,i] = windsAux[1]
879
2122
880 return winds, heightPerI[:-1]
2123 return winds, heightPerI[:-1]
881
2124
882 def techniqueNSM_SA(self, **kwargs):
2125 def techniqueNSM_SA(self, **kwargs):
883 metArray = kwargs['metArray']
2126 metArray = kwargs['metArray']
884 heightList = kwargs['heightList']
2127 heightList = kwargs['heightList']
885 timeList = kwargs['timeList']
2128 timeList = kwargs['timeList']
886
2129
887 rx_location = kwargs['rx_location']
2130 rx_location = kwargs['rx_location']
888 groupList = kwargs['groupList']
2131 groupList = kwargs['groupList']
889 azimuth = kwargs['azimuth']
2132 azimuth = kwargs['azimuth']
890 dfactor = kwargs['dfactor']
2133 dfactor = kwargs['dfactor']
891 k = kwargs['k']
2134 k = kwargs['k']
892
2135
893 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
2136 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
894 d = dist*dfactor
2137 d = dist*dfactor
895 #Phase calculation
2138 #Phase calculation
896 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2139 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
897
2140
898 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2141 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
899
2142
900 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2143 velEst = numpy.zeros((heightList.size,2))*numpy.nan
901 azimuth1 = azimuth1*numpy.pi/180
2144 azimuth1 = azimuth1*numpy.pi/180
902
2145
903 for i in range(heightList.size):
2146 for i in range(heightList.size):
904 h = heightList[i]
2147 h = heightList[i]
905 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2148 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
906 metHeight = metArray1[indH,:]
2149 metHeight = metArray1[indH,:]
907 if metHeight.shape[0] >= 2:
2150 if metHeight.shape[0] >= 2:
908 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2151 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
909 iazim = metHeight[:,1].astype(int)
2152 iazim = metHeight[:,1].astype(int)
910 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2153 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
911 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2154 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
912 A = numpy.asmatrix(A)
2155 A = numpy.asmatrix(A)
913 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2156 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
914 velHor = numpy.dot(A1,velAux)
2157 velHor = numpy.dot(A1,velAux)
915
2158
916 velEst[i,:] = numpy.squeeze(velHor)
2159 velEst[i,:] = numpy.squeeze(velHor)
917 return velEst
2160 return velEst
918
2161
919 def __getPhaseSlope(self, metArray, heightList, timeList):
2162 def __getPhaseSlope(self, metArray, heightList, timeList):
920 meteorList = []
2163 meteorList = []
921 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2164 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
922 #Putting back together the meteor matrix
2165 #Putting back together the meteor matrix
923 utctime = metArray[:,0]
2166 utctime = metArray[:,0]
924 uniqueTime = numpy.unique(utctime)
2167 uniqueTime = numpy.unique(utctime)
925
2168
926 phaseDerThresh = 0.5
2169 phaseDerThresh = 0.5
927 ippSeconds = timeList[1] - timeList[0]
2170 ippSeconds = timeList[1] - timeList[0]
928 sec = numpy.where(timeList>1)[0][0]
2171 sec = numpy.where(timeList>1)[0][0]
929 nPairs = metArray.shape[1] - 6
2172 nPairs = metArray.shape[1] - 6
930 nHeights = len(heightList)
2173 nHeights = len(heightList)
931
2174
932 for t in uniqueTime:
2175 for t in uniqueTime:
933 metArray1 = metArray[utctime==t,:]
2176 metArray1 = metArray[utctime==t,:]
934 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2177 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
935 tmet = metArray1[:,1].astype(int)
2178 tmet = metArray1[:,1].astype(int)
936 hmet = metArray1[:,2].astype(int)
2179 hmet = metArray1[:,2].astype(int)
937
2180
938 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2181 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
939 metPhase[:,:] = numpy.nan
2182 metPhase[:,:] = numpy.nan
940 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2183 metPhase[:,hmet,tmet] = metArray1[:,6:].T
941
2184
942 #Delete short trails
2185 #Delete short trails
943 metBool = ~numpy.isnan(metPhase[0,:,:])
2186 metBool = ~numpy.isnan(metPhase[0,:,:])
944 heightVect = numpy.sum(metBool, axis = 1)
2187 heightVect = numpy.sum(metBool, axis = 1)
945 metBool[heightVect<sec,:] = False
2188 metBool[heightVect<sec,:] = False
946 metPhase[:,heightVect<sec,:] = numpy.nan
2189 metPhase[:,heightVect<sec,:] = numpy.nan
947
2190
948 #Derivative
2191 #Derivative
949 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2192 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
950 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2193 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
951 metPhase[phDerAux] = numpy.nan
2194 metPhase[phDerAux] = numpy.nan
952
2195
953 #--------------------------METEOR DETECTION -----------------------------------------
2196 #--------------------------METEOR DETECTION -----------------------------------------
954 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2197 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
955
2198
956 for p in numpy.arange(nPairs):
2199 for p in numpy.arange(nPairs):
957 phase = metPhase[p,:,:]
2200 phase = metPhase[p,:,:]
958 phDer = metDer[p,:,:]
2201 phDer = metDer[p,:,:]
959
2202
960 for h in indMet:
2203 for h in indMet:
961 height = heightList[h]
2204 height = heightList[h]
962 phase1 = phase[h,:] #82
2205 phase1 = phase[h,:] #82
963 phDer1 = phDer[h,:]
2206 phDer1 = phDer[h,:]
964
2207
965 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2208 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
966
2209
967 indValid = numpy.where(~numpy.isnan(phase1))[0]
2210 indValid = numpy.where(~numpy.isnan(phase1))[0]
968 initMet = indValid[0]
2211 initMet = indValid[0]
969 endMet = 0
2212 endMet = 0
970
2213
971 for i in range(len(indValid)-1):
2214 for i in range(len(indValid)-1):
972
2215
973 #Time difference
2216 #Time difference
974 inow = indValid[i]
2217 inow = indValid[i]
975 inext = indValid[i+1]
2218 inext = indValid[i+1]
976 idiff = inext - inow
2219 idiff = inext - inow
977 #Phase difference
2220 #Phase difference
978 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2221 phDiff = numpy.abs(phase1[inext] - phase1[inow])
979
2222
980 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2223 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
981 sizeTrail = inow - initMet + 1
2224 sizeTrail = inow - initMet + 1
982 if sizeTrail>3*sec: #Too short meteors
2225 if sizeTrail>3*sec: #Too short meteors
983 x = numpy.arange(initMet,inow+1)*ippSeconds
2226 x = numpy.arange(initMet,inow+1)*ippSeconds
984 y = phase1[initMet:inow+1]
2227 y = phase1[initMet:inow+1]
985 ynnan = ~numpy.isnan(y)
2228 ynnan = ~numpy.isnan(y)
986 x = x[ynnan]
2229 x = x[ynnan]
987 y = y[ynnan]
2230 y = y[ynnan]
988 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2231 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
989 ylin = x*slope + intercept
2232 ylin = x*slope + intercept
990 rsq = r_value**2
2233 rsq = r_value**2
991 if rsq > 0.5:
2234 if rsq > 0.5:
992 vel = slope#*height*1000/(k*d)
2235 vel = slope#*height*1000/(k*d)
993 estAux = numpy.array([utctime,p,height, vel, rsq])
2236 estAux = numpy.array([utctime,p,height, vel, rsq])
994 meteorList.append(estAux)
2237 meteorList.append(estAux)
995 initMet = inext
2238 initMet = inext
996 metArray2 = numpy.array(meteorList)
2239 metArray2 = numpy.array(meteorList)
997
2240
998 return metArray2
2241 return metArray2
999
2242
1000 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2243 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
1001
2244
1002 azimuth1 = numpy.zeros(len(pairslist))
2245 azimuth1 = numpy.zeros(len(pairslist))
1003 dist = numpy.zeros(len(pairslist))
2246 dist = numpy.zeros(len(pairslist))
1004
2247
1005 for i in range(len(rx_location)):
2248 for i in range(len(rx_location)):
1006 ch0 = pairslist[i][0]
2249 ch0 = pairslist[i][0]
1007 ch1 = pairslist[i][1]
2250 ch1 = pairslist[i][1]
1008
2251
1009 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2252 diffX = rx_location[ch0][0] - rx_location[ch1][0]
1010 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2253 diffY = rx_location[ch0][1] - rx_location[ch1][1]
1011 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2254 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
1012 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2255 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
1013
2256
1014 azimuth1 -= azimuth0
2257 azimuth1 -= azimuth0
1015 return azimuth1, dist
2258 return azimuth1, dist
1016
2259
1017 def techniqueNSM_DBS(self, **kwargs):
2260 def techniqueNSM_DBS(self, **kwargs):
1018 metArray = kwargs['metArray']
2261 metArray = kwargs['metArray']
1019 heightList = kwargs['heightList']
2262 heightList = kwargs['heightList']
1020 timeList = kwargs['timeList']
2263 timeList = kwargs['timeList']
1021 azimuth = kwargs['azimuth']
2264 azimuth = kwargs['azimuth']
1022 theta_x = numpy.array(kwargs['theta_x'])
2265 theta_x = numpy.array(kwargs['theta_x'])
1023 theta_y = numpy.array(kwargs['theta_y'])
2266 theta_y = numpy.array(kwargs['theta_y'])
1024
2267
1025 utctime = metArray[:,0]
2268 utctime = metArray[:,0]
1026 cmet = metArray[:,1].astype(int)
2269 cmet = metArray[:,1].astype(int)
1027 hmet = metArray[:,3].astype(int)
2270 hmet = metArray[:,3].astype(int)
1028 SNRmet = metArray[:,4]
2271 SNRmet = metArray[:,4]
1029 vmet = metArray[:,5]
2272 vmet = metArray[:,5]
1030 spcmet = metArray[:,6]
2273 spcmet = metArray[:,6]
1031
2274
1032 nChan = numpy.max(cmet) + 1
2275 nChan = numpy.max(cmet) + 1
1033 nHeights = len(heightList)
2276 nHeights = len(heightList)
1034
2277
1035 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2278 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1036 hmet = heightList[hmet]
2279 hmet = heightList[hmet]
1037 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2280 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
1038
2281
1039 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2282 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1040
2283
1041 for i in range(nHeights - 1):
2284 for i in range(nHeights - 1):
1042 hmin = heightList[i]
2285 hmin = heightList[i]
1043 hmax = heightList[i + 1]
2286 hmax = heightList[i + 1]
1044
2287
1045 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2288 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
1046 indthisH = numpy.where(thisH)
2289 indthisH = numpy.where(thisH)
1047
2290
1048 if numpy.size(indthisH) > 3:
2291 if numpy.size(indthisH) > 3:
1049
2292
1050 vel_aux = vmet[thisH]
2293 vel_aux = vmet[thisH]
1051 chan_aux = cmet[thisH]
2294 chan_aux = cmet[thisH]
1052 cosu_aux = dir_cosu[chan_aux]
2295 cosu_aux = dir_cosu[chan_aux]
1053 cosv_aux = dir_cosv[chan_aux]
2296 cosv_aux = dir_cosv[chan_aux]
1054 cosw_aux = dir_cosw[chan_aux]
2297 cosw_aux = dir_cosw[chan_aux]
1055
2298
1056 nch = numpy.size(numpy.unique(chan_aux))
2299 nch = numpy.size(numpy.unique(chan_aux))
1057 if nch > 1:
2300 if nch > 1:
1058 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2301 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
1059 velEst[i,:] = numpy.dot(A,vel_aux)
2302 velEst[i,:] = numpy.dot(A,vel_aux)
1060
2303
1061 return velEst
2304 return velEst
1062
2305
1063 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2306 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
1064
2307
1065 param = dataOut.data_param
2308 param = dataOut.data_param
1066 if dataOut.abscissaList != None:
2309 if dataOut.abscissaList != None:
1067 absc = dataOut.abscissaList[:-1]
2310 absc = dataOut.abscissaList[:-1]
1068 # noise = dataOut.noise
2311 # noise = dataOut.noise
1069 heightList = dataOut.heightList
2312 heightList = dataOut.heightList
1070 SNR = dataOut.data_SNR
2313 SNR = dataOut.data_SNR
1071
2314
1072 if technique == 'DBS':
2315 if technique == 'DBS':
1073
2316
1074 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2317 kwargs['velRadial'] = param[:,1,:] #Radial velocity
1075 kwargs['heightList'] = heightList
2318 kwargs['heightList'] = heightList
1076 kwargs['SNR'] = SNR
2319 kwargs['SNR'] = SNR
1077
2320
1078 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
2321 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
1079 dataOut.utctimeInit = dataOut.utctime
2322 dataOut.utctimeInit = dataOut.utctime
1080 dataOut.outputInterval = dataOut.paramInterval
2323 dataOut.outputInterval = dataOut.paramInterval
1081
2324
1082 elif technique == 'SA':
2325 elif technique == 'SA':
1083
2326
1084 #Parameters
2327 #Parameters
1085 # position_x = kwargs['positionX']
2328 # position_x = kwargs['positionX']
1086 # position_y = kwargs['positionY']
2329 # position_y = kwargs['positionY']
1087 # azimuth = kwargs['azimuth']
2330 # azimuth = kwargs['azimuth']
1088 #
2331 #
1089 # if kwargs.has_key('crosspairsList'):
2332 # if kwargs.has_key('crosspairsList'):
1090 # pairs = kwargs['crosspairsList']
2333 # pairs = kwargs['crosspairsList']
1091 # else:
2334 # else:
1092 # pairs = None
2335 # pairs = None
1093 #
2336 #
1094 # if kwargs.has_key('correctFactor'):
2337 # if kwargs.has_key('correctFactor'):
1095 # correctFactor = kwargs['correctFactor']
2338 # correctFactor = kwargs['correctFactor']
1096 # else:
2339 # else:
1097 # correctFactor = 1
2340 # correctFactor = 1
1098
2341
1099 # tau = dataOut.data_param
2342 # tau = dataOut.data_param
1100 # _lambda = dataOut.C/dataOut.frequency
2343 # _lambda = dataOut.C/dataOut.frequency
1101 # pairsList = dataOut.groupList
2344 # pairsList = dataOut.groupList
1102 # nChannels = dataOut.nChannels
2345 # nChannels = dataOut.nChannels
1103
2346
1104 kwargs['groupList'] = dataOut.groupList
2347 kwargs['groupList'] = dataOut.groupList
1105 kwargs['tau'] = dataOut.data_param
2348 kwargs['tau'] = dataOut.data_param
1106 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2349 kwargs['_lambda'] = dataOut.C/dataOut.frequency
1107 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2350 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1108 dataOut.data_output = self.techniqueSA(kwargs)
2351 dataOut.data_output = self.techniqueSA(kwargs)
1109 dataOut.utctimeInit = dataOut.utctime
2352 dataOut.utctimeInit = dataOut.utctime
1110 dataOut.outputInterval = dataOut.timeInterval
2353 dataOut.outputInterval = dataOut.timeInterval
1111
2354
1112 elif technique == 'Meteors':
2355 elif technique == 'Meteors':
1113 dataOut.flagNoData = True
2356 dataOut.flagNoData = True
1114 self.__dataReady = False
2357 self.__dataReady = False
1115
2358
1116 if kwargs.has_key('nHours'):
2359 if kwargs.has_key('nHours'):
1117 nHours = kwargs['nHours']
2360 nHours = kwargs['nHours']
1118 else:
2361 else:
1119 nHours = 1
2362 nHours = 1
1120
2363
1121 if kwargs.has_key('meteorsPerBin'):
2364 if kwargs.has_key('meteorsPerBin'):
1122 meteorThresh = kwargs['meteorsPerBin']
2365 meteorThresh = kwargs['meteorsPerBin']
1123 else:
2366 else:
1124 meteorThresh = 6
2367 meteorThresh = 6
1125
2368
1126 if kwargs.has_key('hmin'):
2369 if kwargs.has_key('hmin'):
1127 hmin = kwargs['hmin']
2370 hmin = kwargs['hmin']
1128 else: hmin = 70
2371 else: hmin = 70
1129 if kwargs.has_key('hmax'):
2372 if kwargs.has_key('hmax'):
1130 hmax = kwargs['hmax']
2373 hmax = kwargs['hmax']
1131 else: hmax = 110
2374 else: hmax = 110
1132
2375
1133 if kwargs.has_key('BinKm'):
1134 binkm = kwargs['BinKm']
1135 else:
1136 binkm = 2
1137
1138 dataOut.outputInterval = nHours*3600
2376 dataOut.outputInterval = nHours*3600
1139
2377
1140 if self.__isConfig == False:
2378 if self.__isConfig == False:
1141 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2379 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1142 #Get Initial LTC time
2380 #Get Initial LTC time
1143 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2381 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1144 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2382 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1145
2383
1146 self.__isConfig = True
2384 self.__isConfig = True
1147
2385
1148 if self.__buffer is None:
2386 if self.__buffer == None:
1149 self.__buffer = dataOut.data_param
2387 self.__buffer = dataOut.data_param
1150 self.__firstdata = copy.copy(dataOut)
2388 self.__firstdata = copy.copy(dataOut)
1151
2389
1152 else:
2390 else:
1153 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2391 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1154
2392
1155 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2393 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1156
2394
1157 if self.__dataReady:
2395 if self.__dataReady:
1158 dataOut.utctimeInit = self.__initime
2396 dataOut.utctimeInit = self.__initime
1159
2397
1160 self.__initime += dataOut.outputInterval #to erase time offset
2398 self.__initime += dataOut.outputInterval #to erase time offset
1161
2399
1162 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax, binkm)
2400 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
1163 dataOut.flagNoData = False
2401 dataOut.flagNoData = False
1164 self.__buffer = None
2402 self.__buffer = None
1165
2403
1166 elif technique == 'Meteors1':
2404 elif technique == 'Meteors1':
1167 dataOut.flagNoData = True
2405 dataOut.flagNoData = True
1168 self.__dataReady = False
2406 self.__dataReady = False
1169
2407
1170 if kwargs.has_key('nMins'):
2408 if kwargs.has_key('nMins'):
1171 nMins = kwargs['nMins']
2409 nMins = kwargs['nMins']
1172 else: nMins = 20
2410 else: nMins = 20
1173 if kwargs.has_key('rx_location'):
2411 if kwargs.has_key('rx_location'):
1174 rx_location = kwargs['rx_location']
2412 rx_location = kwargs['rx_location']
1175 else: rx_location = [(0,1),(1,1),(1,0)]
2413 else: rx_location = [(0,1),(1,1),(1,0)]
1176 if kwargs.has_key('azimuth'):
2414 if kwargs.has_key('azimuth'):
1177 azimuth = kwargs['azimuth']
2415 azimuth = kwargs['azimuth']
1178 else: azimuth = 51.06
2416 else: azimuth = 51.06
1179 if kwargs.has_key('dfactor'):
2417 if kwargs.has_key('dfactor'):
1180 dfactor = kwargs['dfactor']
2418 dfactor = kwargs['dfactor']
1181 if kwargs.has_key('mode'):
2419 if kwargs.has_key('mode'):
1182 mode = kwargs['mode']
2420 mode = kwargs['mode']
1183 if kwargs.has_key('theta_x'):
2421 if kwargs.has_key('theta_x'):
1184 theta_x = kwargs['theta_x']
2422 theta_x = kwargs['theta_x']
1185 if kwargs.has_key('theta_y'):
2423 if kwargs.has_key('theta_y'):
1186 theta_y = kwargs['theta_y']
2424 theta_y = kwargs['theta_y']
1187 else: mode = 'SA'
2425 else: mode = 'SA'
1188
2426
1189 #Borrar luego esto
2427 #Borrar luego esto
1190 if dataOut.groupList is None:
2428 if dataOut.groupList == None:
1191 dataOut.groupList = [(0,1),(0,2),(1,2)]
2429 dataOut.groupList = [(0,1),(0,2),(1,2)]
1192 groupList = dataOut.groupList
2430 groupList = dataOut.groupList
1193 C = 3e8
2431 C = 3e8
1194 freq = 50e6
2432 freq = 50e6
1195 lamb = C/freq
2433 lamb = C/freq
1196 k = 2*numpy.pi/lamb
2434 k = 2*numpy.pi/lamb
1197
2435
1198 timeList = dataOut.abscissaList
2436 timeList = dataOut.abscissaList
1199 heightList = dataOut.heightList
2437 heightList = dataOut.heightList
1200
2438
1201 if self.__isConfig == False:
2439 if self.__isConfig == False:
1202 dataOut.outputInterval = nMins*60
2440 dataOut.outputInterval = nMins*60
1203 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2441 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1204 #Get Initial LTC time
2442 #Get Initial LTC time
1205 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2443 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1206 minuteAux = initime.minute
2444 minuteAux = initime.minute
1207 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2445 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
1208 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2446 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1209
2447
1210 self.__isConfig = True
2448 self.__isConfig = True
1211
2449
1212 if self.__buffer is None:
2450 if self.__buffer == None:
1213 self.__buffer = dataOut.data_param
2451 self.__buffer = dataOut.data_param
1214 self.__firstdata = copy.copy(dataOut)
2452 self.__firstdata = copy.copy(dataOut)
1215
2453
1216 else:
2454 else:
1217 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2455 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1218
2456
1219 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2457 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1220
2458
1221 if self.__dataReady:
2459 if self.__dataReady:
1222 dataOut.utctimeInit = self.__initime
2460 dataOut.utctimeInit = self.__initime
1223 self.__initime += dataOut.outputInterval #to erase time offset
2461 self.__initime += dataOut.outputInterval #to erase time offset
1224
2462
1225 metArray = self.__buffer
2463 metArray = self.__buffer
1226 if mode == 'SA':
2464 if mode == 'SA':
1227 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2465 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
1228 elif mode == 'DBS':
2466 elif mode == 'DBS':
1229 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2467 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
1230 dataOut.data_output = dataOut.data_output.T
2468 dataOut.data_output = dataOut.data_output.T
1231 dataOut.flagNoData = False
2469 dataOut.flagNoData = False
1232 self.__buffer = None
2470 self.__buffer = None
1233
2471
1234 return
2472 return
1235
2473
1236 class EWDriftsEstimation(Operation):
2474 class EWDriftsEstimation(Operation):
1237
2475
1238
2476 def __init__(self):
2477 Operation.__init__(self)
2478
1239 def __correctValues(self, heiRang, phi, velRadial, SNR):
2479 def __correctValues(self, heiRang, phi, velRadial, SNR):
1240 listPhi = phi.tolist()
2480 listPhi = phi.tolist()
1241 maxid = listPhi.index(max(listPhi))
2481 maxid = listPhi.index(max(listPhi))
1242 minid = listPhi.index(min(listPhi))
2482 minid = listPhi.index(min(listPhi))
1243
2483
1244 rango = range(len(phi))
2484 rango = range(len(phi))
1245 # rango = numpy.delete(rango,maxid)
2485 # rango = numpy.delete(rango,maxid)
1246
2486
1247 heiRang1 = heiRang*math.cos(phi[maxid])
2487 heiRang1 = heiRang*math.cos(phi[maxid])
1248 heiRangAux = heiRang*math.cos(phi[minid])
2488 heiRangAux = heiRang*math.cos(phi[minid])
1249 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2489 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1250 heiRang1 = numpy.delete(heiRang1,indOut)
2490 heiRang1 = numpy.delete(heiRang1,indOut)
1251
2491
1252 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2492 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1253 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2493 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1254
2494
1255 for i in rango:
2495 for i in rango:
1256 x = heiRang*math.cos(phi[i])
2496 x = heiRang*math.cos(phi[i])
1257 y1 = velRadial[i,:]
2497 y1 = velRadial[i,:]
1258 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2498 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1259
2499
1260 x1 = heiRang1
2500 x1 = heiRang1
1261 y11 = f1(x1)
2501 y11 = f1(x1)
1262
2502
1263 y2 = SNR[i,:]
2503 y2 = SNR[i,:]
1264 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2504 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1265 y21 = f2(x1)
2505 y21 = f2(x1)
1266
2506
1267 velRadial1[i,:] = y11
2507 velRadial1[i,:] = y11
1268 SNR1[i,:] = y21
2508 SNR1[i,:] = y21
1269
2509
1270 return heiRang1, velRadial1, SNR1
2510 return heiRang1, velRadial1, SNR1
1271
2511
1272 def run(self, dataOut, zenith, zenithCorrection):
2512 def run(self, dataOut, zenith, zenithCorrection):
1273 heiRang = dataOut.heightList
2513 heiRang = dataOut.heightList
1274 velRadial = dataOut.data_param[:,3,:]
2514 velRadial = dataOut.data_param[:,3,:]
1275 SNR = dataOut.data_SNR
2515 SNR = dataOut.data_SNR
1276
2516
1277 zenith = numpy.array(zenith)
2517 zenith = numpy.array(zenith)
1278 zenith -= zenithCorrection
2518 zenith -= zenithCorrection
1279 zenith *= numpy.pi/180
2519 zenith *= numpy.pi/180
1280
2520
1281 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2521 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
1282
2522
1283 alp = zenith[0]
2523 alp = zenith[0]
1284 bet = zenith[1]
2524 bet = zenith[1]
1285
2525
1286 w_w = velRadial1[0,:]
2526 w_w = velRadial1[0,:]
1287 w_e = velRadial1[1,:]
2527 w_e = velRadial1[1,:]
1288
2528
1289 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2529 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
1290 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2530 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
1291
2531
1292 winds = numpy.vstack((u,w))
2532 winds = numpy.vstack((u,w))
1293
2533
1294 dataOut.heightList = heiRang1
2534 dataOut.heightList = heiRang1
1295 dataOut.data_output = winds
2535 dataOut.data_output = winds
1296 dataOut.data_SNR = SNR1
2536 dataOut.data_SNR = SNR1
1297
2537
1298 dataOut.utctimeInit = dataOut.utctime
2538 dataOut.utctimeInit = dataOut.utctime
1299 dataOut.outputInterval = dataOut.timeInterval
2539 dataOut.outputInterval = dataOut.timeInterval
1300 return
2540 return
1301
2541
1302 #--------------- Non Specular Meteor ----------------
2542 #--------------- Non Specular Meteor ----------------
1303
2543
1304 class NonSpecularMeteorDetection(Operation):
2544 class NonSpecularMeteorDetection(Operation):
1305
2545
1306 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2546 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
1307 data_acf = dataOut.data_pre[0]
2547 data_acf = dataOut.data_pre[0]
1308 data_ccf = dataOut.data_pre[1]
2548 data_ccf = dataOut.data_pre[1]
1309 pairsList = dataOut.groupList[1]
2549 pairsList = dataOut.groupList[1]
1310
2550
1311 lamb = dataOut.C/dataOut.frequency
2551 lamb = dataOut.C/dataOut.frequency
1312 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2552 tSamp = dataOut.ippSeconds*dataOut.nCohInt
1313 paramInterval = dataOut.paramInterval
2553 paramInterval = dataOut.paramInterval
1314
2554
1315 nChannels = data_acf.shape[0]
2555 nChannels = data_acf.shape[0]
1316 nLags = data_acf.shape[1]
2556 nLags = data_acf.shape[1]
1317 nProfiles = data_acf.shape[2]
2557 nProfiles = data_acf.shape[2]
1318 nHeights = dataOut.nHeights
2558 nHeights = dataOut.nHeights
1319 nCohInt = dataOut.nCohInt
2559 nCohInt = dataOut.nCohInt
1320 sec = numpy.round(nProfiles/dataOut.paramInterval)
2560 sec = numpy.round(nProfiles/dataOut.paramInterval)
1321 heightList = dataOut.heightList
2561 heightList = dataOut.heightList
1322 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2562 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
1323 utctime = dataOut.utctime
2563 utctime = dataOut.utctime
1324
2564
1325 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2565 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
1326
2566
1327 #------------------------ SNR --------------------------------------
2567 #------------------------ SNR --------------------------------------
1328 power = data_acf[:,0,:,:].real
2568 power = data_acf[:,0,:,:].real
1329 noise = numpy.zeros(nChannels)
2569 noise = numpy.zeros(nChannels)
1330 SNR = numpy.zeros(power.shape)
2570 SNR = numpy.zeros(power.shape)
1331 for i in range(nChannels):
2571 for i in range(nChannels):
1332 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2572 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
1333 SNR[i] = (power[i]-noise[i])/noise[i]
2573 SNR[i] = (power[i]-noise[i])/noise[i]
1334 SNRm = numpy.nanmean(SNR, axis = 0)
2574 SNRm = numpy.nanmean(SNR, axis = 0)
1335 SNRdB = 10*numpy.log10(SNR)
2575 SNRdB = 10*numpy.log10(SNR)
1336
2576
1337 if mode == 'SA':
2577 if mode == 'SA':
1338 dataOut.groupList = dataOut.groupList[1]
2578 dataOut.groupList = dataOut.groupList[1]
1339 nPairs = data_ccf.shape[0]
2579 nPairs = data_ccf.shape[0]
1340 #---------------------- Coherence and Phase --------------------------
2580 #---------------------- Coherence and Phase --------------------------
1341 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2581 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
1342 # phase1 = numpy.copy(phase)
2582 # phase1 = numpy.copy(phase)
1343 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2583 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
1344
2584
1345 for p in range(nPairs):
2585 for p in range(nPairs):
1346 ch0 = pairsList[p][0]
2586 ch0 = pairsList[p][0]
1347 ch1 = pairsList[p][1]
2587 ch1 = pairsList[p][1]
1348 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2588 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
1349 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2589 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
1350 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2590 # phase1[p,:,:] = numpy.angle(ccf) #median filter
1351 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2591 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
1352 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2592 # coh1[p,:,:] = numpy.abs(ccf) #median filter
1353 coh = numpy.nanmax(coh1, axis = 0)
2593 coh = numpy.nanmax(coh1, axis = 0)
1354 # struc = numpy.ones((5,1))
2594 # struc = numpy.ones((5,1))
1355 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2595 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
1356 #---------------------- Radial Velocity ----------------------------
2596 #---------------------- Radial Velocity ----------------------------
1357 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2597 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
1358 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2598 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
1359
2599
1360 if allData:
2600 if allData:
1361 boolMetFin = ~numpy.isnan(SNRm)
2601 boolMetFin = ~numpy.isnan(SNRm)
1362 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2602 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1363 else:
2603 else:
1364 #------------------------ Meteor mask ---------------------------------
2604 #------------------------ Meteor mask ---------------------------------
1365 # #SNR mask
2605 # #SNR mask
1366 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2606 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
1367 #
2607 #
1368 # #Erase small objects
2608 # #Erase small objects
1369 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2609 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
1370 #
2610 #
1371 # auxEEJ = numpy.sum(boolMet1,axis=0)
2611 # auxEEJ = numpy.sum(boolMet1,axis=0)
1372 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2612 # indOver = auxEEJ>nProfiles*0.8 #Use this later
1373 # indEEJ = numpy.where(indOver)[0]
2613 # indEEJ = numpy.where(indOver)[0]
1374 # indNEEJ = numpy.where(~indOver)[0]
2614 # indNEEJ = numpy.where(~indOver)[0]
1375 #
2615 #
1376 # boolMetFin = boolMet1
2616 # boolMetFin = boolMet1
1377 #
2617 #
1378 # if indEEJ.size > 0:
2618 # if indEEJ.size > 0:
1379 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2619 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
1380 #
2620 #
1381 # boolMet2 = coh > cohThresh
2621 # boolMet2 = coh > cohThresh
1382 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2622 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
1383 #
2623 #
1384 # #Final Meteor mask
2624 # #Final Meteor mask
1385 # boolMetFin = boolMet1|boolMet2
2625 # boolMetFin = boolMet1|boolMet2
1386
2626
1387 #Coherence mask
2627 #Coherence mask
1388 boolMet1 = coh > 0.75
2628 boolMet1 = coh > 0.75
1389 struc = numpy.ones((30,1))
2629 struc = numpy.ones((30,1))
1390 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2630 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
1391
2631
1392 #Derivative mask
2632 #Derivative mask
1393 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2633 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1394 boolMet2 = derPhase < 0.2
2634 boolMet2 = derPhase < 0.2
1395 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2635 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
1396 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2636 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
1397 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2637 boolMet2 = ndimage.median_filter(boolMet2,size=5)
1398 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2638 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
1399 # #Final mask
2639 # #Final mask
1400 # boolMetFin = boolMet2
2640 # boolMetFin = boolMet2
1401 boolMetFin = boolMet1&boolMet2
2641 boolMetFin = boolMet1&boolMet2
1402 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2642 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
1403 #Creating data_param
2643 #Creating data_param
1404 coordMet = numpy.where(boolMetFin)
2644 coordMet = numpy.where(boolMetFin)
1405
2645
1406 tmet = coordMet[0]
2646 tmet = coordMet[0]
1407 hmet = coordMet[1]
2647 hmet = coordMet[1]
1408
2648
1409 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2649 data_param = numpy.zeros((tmet.size, 6 + nPairs))
1410 data_param[:,0] = utctime
2650 data_param[:,0] = utctime
1411 data_param[:,1] = tmet
2651 data_param[:,1] = tmet
1412 data_param[:,2] = hmet
2652 data_param[:,2] = hmet
1413 data_param[:,3] = SNRm[tmet,hmet]
2653 data_param[:,3] = SNRm[tmet,hmet]
1414 data_param[:,4] = velRad[tmet,hmet]
2654 data_param[:,4] = velRad[tmet,hmet]
1415 data_param[:,5] = coh[tmet,hmet]
2655 data_param[:,5] = coh[tmet,hmet]
1416 data_param[:,6:] = phase[:,tmet,hmet].T
2656 data_param[:,6:] = phase[:,tmet,hmet].T
1417
2657
1418 elif mode == 'DBS':
2658 elif mode == 'DBS':
1419 dataOut.groupList = numpy.arange(nChannels)
2659 dataOut.groupList = numpy.arange(nChannels)
1420
2660
1421 #Radial Velocities
2661 #Radial Velocities
1422 phase = numpy.angle(data_acf[:,1,:,:])
2662 phase = numpy.angle(data_acf[:,1,:,:])
1423 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2663 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
1424 velRad = phase*lamb/(4*numpy.pi*tSamp)
2664 velRad = phase*lamb/(4*numpy.pi*tSamp)
1425
2665
1426 #Spectral width
2666 #Spectral width
1427 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2667 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
1428 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2668 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
1429 acf1 = data_acf[:,1,:,:]
2669 acf1 = data_acf[:,1,:,:]
1430 acf2 = data_acf[:,2,:,:]
2670 acf2 = data_acf[:,2,:,:]
1431
2671
1432 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2672 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
1433 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2673 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
1434 if allData:
2674 if allData:
1435 boolMetFin = ~numpy.isnan(SNRdB)
2675 boolMetFin = ~numpy.isnan(SNRdB)
1436 else:
2676 else:
1437 #SNR
2677 #SNR
1438 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2678 boolMet1 = (SNRdB>SNRthresh) #SNR mask
1439 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2679 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
1440
2680
1441 #Radial velocity
2681 #Radial velocity
1442 boolMet2 = numpy.abs(velRad) < 20
2682 boolMet2 = numpy.abs(velRad) < 20
1443 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2683 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
1444
2684
1445 #Spectral Width
2685 #Spectral Width
1446 boolMet3 = spcWidth < 30
2686 boolMet3 = spcWidth < 30
1447 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2687 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
1448 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2688 # boolMetFin = self.__erase_small(boolMet1, 10,5)
1449 boolMetFin = boolMet1&boolMet2&boolMet3
2689 boolMetFin = boolMet1&boolMet2&boolMet3
1450
2690
1451 #Creating data_param
2691 #Creating data_param
1452 coordMet = numpy.where(boolMetFin)
2692 coordMet = numpy.where(boolMetFin)
1453
2693
1454 cmet = coordMet[0]
2694 cmet = coordMet[0]
1455 tmet = coordMet[1]
2695 tmet = coordMet[1]
1456 hmet = coordMet[2]
2696 hmet = coordMet[2]
1457
2697
1458 data_param = numpy.zeros((tmet.size, 7))
2698 data_param = numpy.zeros((tmet.size, 7))
1459 data_param[:,0] = utctime
2699 data_param[:,0] = utctime
1460 data_param[:,1] = cmet
2700 data_param[:,1] = cmet
1461 data_param[:,2] = tmet
2701 data_param[:,2] = tmet
1462 data_param[:,3] = hmet
2702 data_param[:,3] = hmet
1463 data_param[:,4] = SNR[cmet,tmet,hmet].T
2703 data_param[:,4] = SNR[cmet,tmet,hmet].T
1464 data_param[:,5] = velRad[cmet,tmet,hmet].T
2704 data_param[:,5] = velRad[cmet,tmet,hmet].T
1465 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2705 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
1466
2706
1467 # self.dataOut.data_param = data_int
2707 # self.dataOut.data_param = data_int
1468 if len(data_param) == 0:
2708 if len(data_param) == 0:
1469 dataOut.flagNoData = True
2709 dataOut.flagNoData = True
1470 else:
2710 else:
1471 dataOut.data_param = data_param
2711 dataOut.data_param = data_param
1472
2712
1473 def __erase_small(self, binArray, threshX, threshY):
2713 def __erase_small(self, binArray, threshX, threshY):
1474 labarray, numfeat = ndimage.measurements.label(binArray)
2714 labarray, numfeat = ndimage.measurements.label(binArray)
1475 binArray1 = numpy.copy(binArray)
2715 binArray1 = numpy.copy(binArray)
1476
2716
1477 for i in range(1,numfeat + 1):
2717 for i in range(1,numfeat + 1):
1478 auxBin = (labarray==i)
2718 auxBin = (labarray==i)
1479 auxSize = auxBin.sum()
2719 auxSize = auxBin.sum()
1480
2720
1481 x,y = numpy.where(auxBin)
2721 x,y = numpy.where(auxBin)
1482 widthX = x.max() - x.min()
2722 widthX = x.max() - x.min()
1483 widthY = y.max() - y.min()
2723 widthY = y.max() - y.min()
1484
2724
1485 #width X: 3 seg -> 12.5*3
2725 #width X: 3 seg -> 12.5*3
1486 #width Y:
2726 #width Y:
1487
2727
1488 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2728 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
1489 binArray1[auxBin] = False
2729 binArray1[auxBin] = False
1490
2730
1491 return binArray1
2731 return binArray1
1492
2732
1493 #--------------- Specular Meteor ----------------
2733 #--------------- Specular Meteor ----------------
1494
2734
1495 class SMDetection(Operation):
2735 class SMDetection(Operation):
1496 '''
2736 '''
1497 Function DetectMeteors()
2737 Function DetectMeteors()
1498 Project developed with paper:
2738 Project developed with paper:
1499 HOLDSWORTH ET AL. 2004
2739 HOLDSWORTH ET AL. 2004
1500
2740
1501 Input:
2741 Input:
1502 self.dataOut.data_pre
2742 self.dataOut.data_pre
1503
2743
1504 centerReceiverIndex: From the channels, which is the center receiver
2744 centerReceiverIndex: From the channels, which is the center receiver
1505
2745
1506 hei_ref: Height reference for the Beacon signal extraction
2746 hei_ref: Height reference for the Beacon signal extraction
1507 tauindex:
2747 tauindex:
1508 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2748 predefinedPhaseShifts: Predefined phase offset for the voltge signals
1509
2749
1510 cohDetection: Whether to user Coherent detection or not
2750 cohDetection: Whether to user Coherent detection or not
1511 cohDet_timeStep: Coherent Detection calculation time step
2751 cohDet_timeStep: Coherent Detection calculation time step
1512 cohDet_thresh: Coherent Detection phase threshold to correct phases
2752 cohDet_thresh: Coherent Detection phase threshold to correct phases
1513
2753
1514 noise_timeStep: Noise calculation time step
2754 noise_timeStep: Noise calculation time step
1515 noise_multiple: Noise multiple to define signal threshold
2755 noise_multiple: Noise multiple to define signal threshold
1516
2756
1517 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2757 multDet_timeLimit: Multiple Detection Removal time limit in seconds
1518 multDet_rangeLimit: Multiple Detection Removal range limit in km
2758 multDet_rangeLimit: Multiple Detection Removal range limit in km
1519
2759
1520 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2760 phaseThresh: Maximum phase difference between receiver to be consider a meteor
1521 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2761 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
1522
2762
1523 hmin: Minimum Height of the meteor to use it in the further wind estimations
2763 hmin: Minimum Height of the meteor to use it in the further wind estimations
1524 hmax: Maximum Height of the meteor to use it in the further wind estimations
2764 hmax: Maximum Height of the meteor to use it in the further wind estimations
1525 azimuth: Azimuth angle correction
2765 azimuth: Azimuth angle correction
1526
2766
1527 Affected:
2767 Affected:
1528 self.dataOut.data_param
2768 self.dataOut.data_param
1529
2769
1530 Rejection Criteria (Errors):
2770 Rejection Criteria (Errors):
1531 0: No error; analysis OK
2771 0: No error; analysis OK
1532 1: SNR < SNR threshold
2772 1: SNR < SNR threshold
1533 2: angle of arrival (AOA) ambiguously determined
2773 2: angle of arrival (AOA) ambiguously determined
1534 3: AOA estimate not feasible
2774 3: AOA estimate not feasible
1535 4: Large difference in AOAs obtained from different antenna baselines
2775 4: Large difference in AOAs obtained from different antenna baselines
1536 5: echo at start or end of time series
2776 5: echo at start or end of time series
1537 6: echo less than 5 examples long; too short for analysis
2777 6: echo less than 5 examples long; too short for analysis
1538 7: echo rise exceeds 0.3s
2778 7: echo rise exceeds 0.3s
1539 8: echo decay time less than twice rise time
2779 8: echo decay time less than twice rise time
1540 9: large power level before echo
2780 9: large power level before echo
1541 10: large power level after echo
2781 10: large power level after echo
1542 11: poor fit to amplitude for estimation of decay time
2782 11: poor fit to amplitude for estimation of decay time
1543 12: poor fit to CCF phase variation for estimation of radial drift velocity
2783 12: poor fit to CCF phase variation for estimation of radial drift velocity
1544 13: height unresolvable echo: not valid height within 70 to 110 km
2784 13: height unresolvable echo: not valid height within 70 to 110 km
1545 14: height ambiguous echo: more then one possible height within 70 to 110 km
2785 14: height ambiguous echo: more then one possible height within 70 to 110 km
1546 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2786 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
1547 16: oscilatory echo, indicating event most likely not an underdense echo
2787 16: oscilatory echo, indicating event most likely not an underdense echo
1548
2788
1549 17: phase difference in meteor Reestimation
2789 17: phase difference in meteor Reestimation
1550
2790
1551 Data Storage:
2791 Data Storage:
1552 Meteors for Wind Estimation (8):
2792 Meteors for Wind Estimation (8):
1553 Utc Time | Range Height
2793 Utc Time | Range Height
1554 Azimuth Zenith errorCosDir
2794 Azimuth Zenith errorCosDir
1555 VelRad errorVelRad
2795 VelRad errorVelRad
1556 Phase0 Phase1 Phase2 Phase3
2796 Phase0 Phase1 Phase2 Phase3
1557 TypeError
2797 TypeError
1558
2798
1559 '''
2799 '''
1560
2800
1561 def run(self, dataOut, hei_ref = None, tauindex = 0,
2801 def run(self, dataOut, hei_ref = None, tauindex = 0,
1562 phaseOffsets = None,
2802 phaseOffsets = None,
1563 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2803 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
1564 noise_timeStep = 4, noise_multiple = 4,
2804 noise_timeStep = 4, noise_multiple = 4,
1565 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2805 multDet_timeLimit = 1, multDet_rangeLimit = 3,
1566 phaseThresh = 20, SNRThresh = 5,
2806 phaseThresh = 20, SNRThresh = 5,
1567 hmin = 50, hmax=150, azimuth = 0,
2807 hmin = 50, hmax=150, azimuth = 0,
1568 channelPositions = None) :
2808 channelPositions = None) :
1569
2809
1570
2810
1571 #Getting Pairslist
2811 #Getting Pairslist
1572 if channelPositions is None:
2812 if channelPositions == None:
1573 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2813 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
1574 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2814 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
1575 meteorOps = SMOperations()
2815 meteorOps = SMOperations()
1576 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2816 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
1577 heiRang = dataOut.getHeiRange()
2817 heiRang = dataOut.getHeiRange()
1578 #Get Beacon signal - No Beacon signal anymore
2818 #Get Beacon signal - No Beacon signal anymore
1579 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2819 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
1580 #
2820 #
1581 # if hei_ref != None:
2821 # if hei_ref != None:
1582 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2822 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
1583 #
2823 #
1584
2824
1585
2825
1586 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2826 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
1587 # see if the user put in pre defined phase shifts
2827 # see if the user put in pre defined phase shifts
1588 voltsPShift = dataOut.data_pre.copy()
2828 voltsPShift = dataOut.data_pre.copy()
1589
2829
1590 # if predefinedPhaseShifts != None:
2830 # if predefinedPhaseShifts != None:
1591 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2831 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
1592 #
2832 #
1593 # # elif beaconPhaseShifts:
2833 # # elif beaconPhaseShifts:
1594 # # #get hardware phase shifts using beacon signal
2834 # # #get hardware phase shifts using beacon signal
1595 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2835 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
1596 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2836 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
1597 #
2837 #
1598 # else:
2838 # else:
1599 # hardwarePhaseShifts = numpy.zeros(5)
2839 # hardwarePhaseShifts = numpy.zeros(5)
1600 #
2840 #
1601 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2841 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
1602 # for i in range(self.dataOut.data_pre.shape[0]):
2842 # for i in range(self.dataOut.data_pre.shape[0]):
1603 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2843 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
1604
2844
1605 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2845 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
1606
2846
1607 #Remove DC
2847 #Remove DC
1608 voltsDC = numpy.mean(voltsPShift,1)
2848 voltsDC = numpy.mean(voltsPShift,1)
1609 voltsDC = numpy.mean(voltsDC,1)
2849 voltsDC = numpy.mean(voltsDC,1)
1610 for i in range(voltsDC.shape[0]):
2850 for i in range(voltsDC.shape[0]):
1611 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2851 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
1612
2852
1613 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2853 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
1614 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2854 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
1615
2855
1616 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2856 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
1617 #Coherent Detection
2857 #Coherent Detection
1618 if cohDetection:
2858 if cohDetection:
1619 #use coherent detection to get the net power
2859 #use coherent detection to get the net power
1620 cohDet_thresh = cohDet_thresh*numpy.pi/180
2860 cohDet_thresh = cohDet_thresh*numpy.pi/180
1621 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2861 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
1622
2862
1623 #Non-coherent detection!
2863 #Non-coherent detection!
1624 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2864 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
1625 #********** END OF COH/NON-COH POWER CALCULATION**********************
2865 #********** END OF COH/NON-COH POWER CALCULATION**********************
1626
2866
1627 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2867 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
1628 #Get noise
2868 #Get noise
1629 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2869 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
1630 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2870 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
1631 #Get signal threshold
2871 #Get signal threshold
1632 signalThresh = noise_multiple*noise
2872 signalThresh = noise_multiple*noise
1633 #Meteor echoes detection
2873 #Meteor echoes detection
1634 listMeteors = self.__findMeteors(powerNet, signalThresh)
2874 listMeteors = self.__findMeteors(powerNet, signalThresh)
1635 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2875 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
1636
2876
1637 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2877 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
1638 #Parameters
2878 #Parameters
1639 heiRange = dataOut.getHeiRange()
2879 heiRange = dataOut.getHeiRange()
1640 rangeInterval = heiRange[1] - heiRange[0]
2880 rangeInterval = heiRange[1] - heiRange[0]
1641 rangeLimit = multDet_rangeLimit/rangeInterval
2881 rangeLimit = multDet_rangeLimit/rangeInterval
1642 timeLimit = multDet_timeLimit/dataOut.timeInterval
2882 timeLimit = multDet_timeLimit/dataOut.timeInterval
1643 #Multiple detection removals
2883 #Multiple detection removals
1644 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2884 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
1645 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2885 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
1646
2886
1647 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2887 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
1648 #Parameters
2888 #Parameters
1649 phaseThresh = phaseThresh*numpy.pi/180
2889 phaseThresh = phaseThresh*numpy.pi/180
1650 thresh = [phaseThresh, noise_multiple, SNRThresh]
2890 thresh = [phaseThresh, noise_multiple, SNRThresh]
1651 #Meteor reestimation (Errors N 1, 6, 12, 17)
2891 #Meteor reestimation (Errors N 1, 6, 12, 17)
1652 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2892 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
1653 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2893 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
1654 #Estimation of decay times (Errors N 7, 8, 11)
2894 #Estimation of decay times (Errors N 7, 8, 11)
1655 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2895 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
1656 #******************* END OF METEOR REESTIMATION *******************
2896 #******************* END OF METEOR REESTIMATION *******************
1657
2897
1658 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2898 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
1659 #Calculating Radial Velocity (Error N 15)
2899 #Calculating Radial Velocity (Error N 15)
1660 radialStdThresh = 10
2900 radialStdThresh = 10
1661 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2901 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
1662
2902
1663 if len(listMeteors4) > 0:
2903 if len(listMeteors4) > 0:
1664 #Setting New Array
2904 #Setting New Array
1665 date = dataOut.utctime
2905 date = dataOut.utctime
1666 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2906 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
1667
2907
1668 #Correcting phase offset
2908 #Correcting phase offset
1669 if phaseOffsets != None:
2909 if phaseOffsets != None:
1670 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2910 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
1671 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2911 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
1672
2912
1673 #Second Pairslist
2913 #Second Pairslist
1674 pairsList = []
2914 pairsList = []
1675 pairx = (0,1)
2915 pairx = (0,1)
1676 pairy = (2,3)
2916 pairy = (2,3)
1677 pairsList.append(pairx)
2917 pairsList.append(pairx)
1678 pairsList.append(pairy)
2918 pairsList.append(pairy)
1679
2919
1680 jph = numpy.array([0,0,0,0])
2920 jph = numpy.array([0,0,0,0])
1681 h = (hmin,hmax)
2921 h = (hmin,hmax)
1682 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2922 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
1683
2923
1684 # #Calculate AOA (Error N 3, 4)
2924 # #Calculate AOA (Error N 3, 4)
1685 # #JONES ET AL. 1998
2925 # #JONES ET AL. 1998
1686 # error = arrayParameters[:,-1]
2926 # error = arrayParameters[:,-1]
1687 # AOAthresh = numpy.pi/8
2927 # AOAthresh = numpy.pi/8
1688 # phases = -arrayParameters[:,9:13]
2928 # phases = -arrayParameters[:,9:13]
1689 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2929 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
1690 #
2930 #
1691 # #Calculate Heights (Error N 13 and 14)
2931 # #Calculate Heights (Error N 13 and 14)
1692 # error = arrayParameters[:,-1]
2932 # error = arrayParameters[:,-1]
1693 # Ranges = arrayParameters[:,2]
2933 # Ranges = arrayParameters[:,2]
1694 # zenith = arrayParameters[:,5]
2934 # zenith = arrayParameters[:,5]
1695 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2935 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
1696 # error = arrayParameters[:,-1]
2936 # error = arrayParameters[:,-1]
1697 #********************* END OF PARAMETERS CALCULATION **************************
2937 #********************* END OF PARAMETERS CALCULATION **************************
1698
2938
1699 #***************************+ PASS DATA TO NEXT STEP **********************
2939 #***************************+ PASS DATA TO NEXT STEP **********************
1700 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2940 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
1701 dataOut.data_param = arrayParameters
2941 dataOut.data_param = arrayParameters
1702
2942
1703 if arrayParameters is None:
2943 if arrayParameters == None:
1704 dataOut.flagNoData = True
2944 dataOut.flagNoData = True
1705 else:
2945 else:
1706 dataOut.flagNoData = True
2946 dataOut.flagNoData = True
1707
2947
1708 return
2948 return
1709
2949
1710 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2950 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
1711
2951
1712 minIndex = min(newheis[0])
2952 minIndex = min(newheis[0])
1713 maxIndex = max(newheis[0])
2953 maxIndex = max(newheis[0])
1714
2954
1715 voltage = voltage0[:,:,minIndex:maxIndex+1]
2955 voltage = voltage0[:,:,minIndex:maxIndex+1]
1716 nLength = voltage.shape[1]/n
2956 nLength = voltage.shape[1]/n
1717 nMin = 0
2957 nMin = 0
1718 nMax = 0
2958 nMax = 0
1719 phaseOffset = numpy.zeros((len(pairslist),n))
2959 phaseOffset = numpy.zeros((len(pairslist),n))
1720
2960
1721 for i in range(n):
2961 for i in range(n):
1722 nMax += nLength
2962 nMax += nLength
1723 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2963 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
1724 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2964 phaseCCF = numpy.mean(phaseCCF, axis = 2)
1725 phaseOffset[:,i] = phaseCCF.transpose()
2965 phaseOffset[:,i] = phaseCCF.transpose()
1726 nMin = nMax
2966 nMin = nMax
1727 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2967 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
1728
2968
1729 #Remove Outliers
2969 #Remove Outliers
1730 factor = 2
2970 factor = 2
1731 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2971 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
1732 dw = numpy.std(wt,axis = 1)
2972 dw = numpy.std(wt,axis = 1)
1733 dw = dw.reshape((dw.size,1))
2973 dw = dw.reshape((dw.size,1))
1734 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2974 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
1735 phaseOffset[ind] = numpy.nan
2975 phaseOffset[ind] = numpy.nan
1736 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2976 phaseOffset = stats.nanmean(phaseOffset, axis=1)
1737
2977
1738 return phaseOffset
2978 return phaseOffset
1739
2979
1740 def __shiftPhase(self, data, phaseShift):
2980 def __shiftPhase(self, data, phaseShift):
1741 #this will shift the phase of a complex number
2981 #this will shift the phase of a complex number
1742 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2982 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
1743 return dataShifted
2983 return dataShifted
1744
2984
1745 def __estimatePhaseDifference(self, array, pairslist):
2985 def __estimatePhaseDifference(self, array, pairslist):
1746 nChannel = array.shape[0]
2986 nChannel = array.shape[0]
1747 nHeights = array.shape[2]
2987 nHeights = array.shape[2]
1748 numPairs = len(pairslist)
2988 numPairs = len(pairslist)
1749 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2989 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
1750 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2990 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
1751
2991
1752 #Correct phases
2992 #Correct phases
1753 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2993 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
1754 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2994 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
1755
2995
1756 if indDer[0].shape[0] > 0:
2996 if indDer[0].shape[0] > 0:
1757 for i in range(indDer[0].shape[0]):
2997 for i in range(indDer[0].shape[0]):
1758 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2998 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
1759 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2999 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
1760
3000
1761 # for j in range(numSides):
3001 # for j in range(numSides):
1762 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
3002 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
1763 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
3003 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
1764 #
3004 #
1765 #Linear
3005 #Linear
1766 phaseInt = numpy.zeros((numPairs,1))
3006 phaseInt = numpy.zeros((numPairs,1))
1767 angAllCCF = phaseCCF[:,[0,1,3,4],0]
3007 angAllCCF = phaseCCF[:,[0,1,3,4],0]
1768 for j in range(numPairs):
3008 for j in range(numPairs):
1769 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
3009 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
1770 phaseInt[j] = fit[1]
3010 phaseInt[j] = fit[1]
1771 #Phase Differences
3011 #Phase Differences
1772 phaseDiff = phaseInt - phaseCCF[:,2,:]
3012 phaseDiff = phaseInt - phaseCCF[:,2,:]
1773 phaseArrival = phaseInt.reshape(phaseInt.size)
3013 phaseArrival = phaseInt.reshape(phaseInt.size)
1774
3014
1775 #Dealias
3015 #Dealias
1776 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
3016 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
1777 # indAlias = numpy.where(phaseArrival > numpy.pi)
3017 # indAlias = numpy.where(phaseArrival > numpy.pi)
1778 # phaseArrival[indAlias] -= 2*numpy.pi
3018 # phaseArrival[indAlias] -= 2*numpy.pi
1779 # indAlias = numpy.where(phaseArrival < -numpy.pi)
3019 # indAlias = numpy.where(phaseArrival < -numpy.pi)
1780 # phaseArrival[indAlias] += 2*numpy.pi
3020 # phaseArrival[indAlias] += 2*numpy.pi
1781
3021
1782 return phaseDiff, phaseArrival
3022 return phaseDiff, phaseArrival
1783
3023
1784 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
3024 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
1785 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
3025 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
1786 #find the phase shifts of each channel over 1 second intervals
3026 #find the phase shifts of each channel over 1 second intervals
1787 #only look at ranges below the beacon signal
3027 #only look at ranges below the beacon signal
1788 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
3028 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1789 numBlocks = int(volts.shape[1]/numProfPerBlock)
3029 numBlocks = int(volts.shape[1]/numProfPerBlock)
1790 numHeights = volts.shape[2]
3030 numHeights = volts.shape[2]
1791 nChannel = volts.shape[0]
3031 nChannel = volts.shape[0]
1792 voltsCohDet = volts.copy()
3032 voltsCohDet = volts.copy()
1793
3033
1794 pairsarray = numpy.array(pairslist)
3034 pairsarray = numpy.array(pairslist)
1795 indSides = pairsarray[:,1]
3035 indSides = pairsarray[:,1]
1796 # indSides = numpy.array(range(nChannel))
3036 # indSides = numpy.array(range(nChannel))
1797 # indSides = numpy.delete(indSides, indCenter)
3037 # indSides = numpy.delete(indSides, indCenter)
1798 #
3038 #
1799 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
3039 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
1800 listBlocks = numpy.array_split(volts, numBlocks, 1)
3040 listBlocks = numpy.array_split(volts, numBlocks, 1)
1801
3041
1802 startInd = 0
3042 startInd = 0
1803 endInd = 0
3043 endInd = 0
1804
3044
1805 for i in range(numBlocks):
3045 for i in range(numBlocks):
1806 startInd = endInd
3046 startInd = endInd
1807 endInd = endInd + listBlocks[i].shape[1]
3047 endInd = endInd + listBlocks[i].shape[1]
1808
3048
1809 arrayBlock = listBlocks[i]
3049 arrayBlock = listBlocks[i]
1810 # arrayBlockCenter = listCenter[i]
3050 # arrayBlockCenter = listCenter[i]
1811
3051
1812 #Estimate the Phase Difference
3052 #Estimate the Phase Difference
1813 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
3053 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
1814 #Phase Difference RMS
3054 #Phase Difference RMS
1815 arrayPhaseRMS = numpy.abs(phaseDiff)
3055 arrayPhaseRMS = numpy.abs(phaseDiff)
1816 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
3056 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
1817 indPhase = numpy.where(phaseRMSaux==4)
3057 indPhase = numpy.where(phaseRMSaux==4)
1818 #Shifting
3058 #Shifting
1819 if indPhase[0].shape[0] > 0:
3059 if indPhase[0].shape[0] > 0:
1820 for j in range(indSides.size):
3060 for j in range(indSides.size):
1821 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
3061 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
1822 voltsCohDet[:,startInd:endInd,:] = arrayBlock
3062 voltsCohDet[:,startInd:endInd,:] = arrayBlock
1823
3063
1824 return voltsCohDet
3064 return voltsCohDet
1825
3065
1826 def __calculateCCF(self, volts, pairslist ,laglist):
3066 def __calculateCCF(self, volts, pairslist ,laglist):
1827
3067
1828 nHeights = volts.shape[2]
3068 nHeights = volts.shape[2]
1829 nPoints = volts.shape[1]
3069 nPoints = volts.shape[1]
1830 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
3070 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
1831
3071
1832 for i in range(len(pairslist)):
3072 for i in range(len(pairslist)):
1833 volts1 = volts[pairslist[i][0]]
3073 volts1 = volts[pairslist[i][0]]
1834 volts2 = volts[pairslist[i][1]]
3074 volts2 = volts[pairslist[i][1]]
1835
3075
1836 for t in range(len(laglist)):
3076 for t in range(len(laglist)):
1837 idxT = laglist[t]
3077 idxT = laglist[t]
1838 if idxT >= 0:
3078 if idxT >= 0:
1839 vStacked = numpy.vstack((volts2[idxT:,:],
3079 vStacked = numpy.vstack((volts2[idxT:,:],
1840 numpy.zeros((idxT, nHeights),dtype='complex')))
3080 numpy.zeros((idxT, nHeights),dtype='complex')))
1841 else:
3081 else:
1842 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
3082 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
1843 volts2[:(nPoints + idxT),:]))
3083 volts2[:(nPoints + idxT),:]))
1844 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
3084 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
1845
3085
1846 vStacked = None
3086 vStacked = None
1847 return voltsCCF
3087 return voltsCCF
1848
3088
1849 def __getNoise(self, power, timeSegment, timeInterval):
3089 def __getNoise(self, power, timeSegment, timeInterval):
1850 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
3090 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1851 numBlocks = int(power.shape[0]/numProfPerBlock)
3091 numBlocks = int(power.shape[0]/numProfPerBlock)
1852 numHeights = power.shape[1]
3092 numHeights = power.shape[1]
1853
3093
1854 listPower = numpy.array_split(power, numBlocks, 0)
3094 listPower = numpy.array_split(power, numBlocks, 0)
1855 noise = numpy.zeros((power.shape[0], power.shape[1]))
3095 noise = numpy.zeros((power.shape[0], power.shape[1]))
1856 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
3096 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
1857
3097
1858 startInd = 0
3098 startInd = 0
1859 endInd = 0
3099 endInd = 0
1860
3100
1861 for i in range(numBlocks): #split por canal
3101 for i in range(numBlocks): #split por canal
1862 startInd = endInd
3102 startInd = endInd
1863 endInd = endInd + listPower[i].shape[0]
3103 endInd = endInd + listPower[i].shape[0]
1864
3104
1865 arrayBlock = listPower[i]
3105 arrayBlock = listPower[i]
1866 noiseAux = numpy.mean(arrayBlock, 0)
3106 noiseAux = numpy.mean(arrayBlock, 0)
1867 # noiseAux = numpy.median(noiseAux)
3107 # noiseAux = numpy.median(noiseAux)
1868 # noiseAux = numpy.mean(arrayBlock)
3108 # noiseAux = numpy.mean(arrayBlock)
1869 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
3109 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
1870
3110
1871 noiseAux1 = numpy.mean(arrayBlock)
3111 noiseAux1 = numpy.mean(arrayBlock)
1872 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
3112 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
1873
3113
1874 return noise, noise1
3114 return noise, noise1
1875
3115
1876 def __findMeteors(self, power, thresh):
3116 def __findMeteors(self, power, thresh):
1877 nProf = power.shape[0]
3117 nProf = power.shape[0]
1878 nHeights = power.shape[1]
3118 nHeights = power.shape[1]
1879 listMeteors = []
3119 listMeteors = []
1880
3120
1881 for i in range(nHeights):
3121 for i in range(nHeights):
1882 powerAux = power[:,i]
3122 powerAux = power[:,i]
1883 threshAux = thresh[:,i]
3123 threshAux = thresh[:,i]
1884
3124
1885 indUPthresh = numpy.where(powerAux > threshAux)[0]
3125 indUPthresh = numpy.where(powerAux > threshAux)[0]
1886 indDNthresh = numpy.where(powerAux <= threshAux)[0]
3126 indDNthresh = numpy.where(powerAux <= threshAux)[0]
1887
3127
1888 j = 0
3128 j = 0
1889
3129
1890 while (j < indUPthresh.size - 2):
3130 while (j < indUPthresh.size - 2):
1891 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
3131 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
1892 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
3132 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
1893 indDNthresh = indDNthresh[indDNAux]
3133 indDNthresh = indDNthresh[indDNAux]
1894
3134
1895 if (indDNthresh.size > 0):
3135 if (indDNthresh.size > 0):
1896 indEnd = indDNthresh[0] - 1
3136 indEnd = indDNthresh[0] - 1
1897 indInit = indUPthresh[j] if isinstance(indUPthresh[j], (int, float)) else indUPthresh[j][0] ##CHECK!!!!
3137 indInit = indUPthresh[j]
1898
3138
1899 meteor = powerAux[indInit:indEnd + 1]
3139 meteor = powerAux[indInit:indEnd + 1]
1900 indPeak = meteor.argmax() + indInit
3140 indPeak = meteor.argmax() + indInit
1901 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3141 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
1902
3142
1903 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3143 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
1904 j = numpy.where(indUPthresh == indEnd)[0] + 1
3144 j = numpy.where(indUPthresh == indEnd)[0] + 1
1905 else: j+=1
3145 else: j+=1
1906 else: j+=1
3146 else: j+=1
1907
3147
1908 return listMeteors
3148 return listMeteors
1909
3149
1910 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3150 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
1911
3151
1912 arrayMeteors = numpy.asarray(listMeteors)
3152 arrayMeteors = numpy.asarray(listMeteors)
1913 listMeteors1 = []
3153 listMeteors1 = []
1914
3154
1915 while arrayMeteors.shape[0] > 0:
3155 while arrayMeteors.shape[0] > 0:
1916 FLAs = arrayMeteors[:,4]
3156 FLAs = arrayMeteors[:,4]
1917 maxFLA = FLAs.argmax()
3157 maxFLA = FLAs.argmax()
1918 listMeteors1.append(arrayMeteors[maxFLA,:])
3158 listMeteors1.append(arrayMeteors[maxFLA,:])
1919
3159
1920 MeteorInitTime = arrayMeteors[maxFLA,1]
3160 MeteorInitTime = arrayMeteors[maxFLA,1]
1921 MeteorEndTime = arrayMeteors[maxFLA,3]
3161 MeteorEndTime = arrayMeteors[maxFLA,3]
1922 MeteorHeight = arrayMeteors[maxFLA,0]
3162 MeteorHeight = arrayMeteors[maxFLA,0]
1923
3163
1924 #Check neighborhood
3164 #Check neighborhood
1925 maxHeightIndex = MeteorHeight + rangeLimit
3165 maxHeightIndex = MeteorHeight + rangeLimit
1926 minHeightIndex = MeteorHeight - rangeLimit
3166 minHeightIndex = MeteorHeight - rangeLimit
1927 minTimeIndex = MeteorInitTime - timeLimit
3167 minTimeIndex = MeteorInitTime - timeLimit
1928 maxTimeIndex = MeteorEndTime + timeLimit
3168 maxTimeIndex = MeteorEndTime + timeLimit
1929
3169
1930 #Check Heights
3170 #Check Heights
1931 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3171 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
1932 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3172 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
1933 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3173 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
1934
3174
1935 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3175 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
1936
3176
1937 return listMeteors1
3177 return listMeteors1
1938
3178
1939 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3179 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
1940 numHeights = volts.shape[2]
3180 numHeights = volts.shape[2]
1941 nChannel = volts.shape[0]
3181 nChannel = volts.shape[0]
1942
3182
1943 thresholdPhase = thresh[0]
3183 thresholdPhase = thresh[0]
1944 thresholdNoise = thresh[1]
3184 thresholdNoise = thresh[1]
1945 thresholdDB = float(thresh[2])
3185 thresholdDB = float(thresh[2])
1946
3186
1947 thresholdDB1 = 10**(thresholdDB/10)
3187 thresholdDB1 = 10**(thresholdDB/10)
1948 pairsarray = numpy.array(pairslist)
3188 pairsarray = numpy.array(pairslist)
1949 indSides = pairsarray[:,1]
3189 indSides = pairsarray[:,1]
1950
3190
1951 pairslist1 = list(pairslist)
3191 pairslist1 = list(pairslist)
1952 pairslist1.append((0,4))
3192 pairslist1.append((0,1))
1953 pairslist1.append((1,3))
3193 pairslist1.append((3,4))
1954
3194
1955 listMeteors1 = []
3195 listMeteors1 = []
1956 listPowerSeries = []
3196 listPowerSeries = []
1957 listVoltageSeries = []
3197 listVoltageSeries = []
1958 #volts has the war data
3198 #volts has the war data
1959
3199
1960 if frequency == 30.175e6:
3200 if frequency == 30e6:
1961 timeLag = 45*10**-3
3201 timeLag = 45*10**-3
1962 else:
3202 else:
1963 timeLag = 15*10**-3
3203 timeLag = 15*10**-3
1964 lag = int(numpy.ceil(timeLag/timeInterval))
3204 lag = numpy.ceil(timeLag/timeInterval)
1965
3205
1966 for i in range(len(listMeteors)):
3206 for i in range(len(listMeteors)):
1967
3207
1968 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3208 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
1969 meteorAux = numpy.zeros(16)
3209 meteorAux = numpy.zeros(16)
1970
3210
1971 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3211 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
1972 mHeight = int(listMeteors[i][0])
3212 mHeight = listMeteors[i][0]
1973 mStart = int(listMeteors[i][1])
3213 mStart = listMeteors[i][1]
1974 mPeak = int(listMeteors[i][2])
3214 mPeak = listMeteors[i][2]
1975 mEnd = int(listMeteors[i][3])
3215 mEnd = listMeteors[i][3]
1976
3216
1977 #get the volt data between the start and end times of the meteor
3217 #get the volt data between the start and end times of the meteor
1978 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3218 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
1979 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3219 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
1980
3220
1981 #3.6. Phase Difference estimation
3221 #3.6. Phase Difference estimation
1982 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3222 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
1983
3223
1984 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3224 #3.7. Phase difference removal & meteor start, peak and end times reestimated
1985 #meteorVolts0.- all Channels, all Profiles
3225 #meteorVolts0.- all Channels, all Profiles
1986 meteorVolts0 = volts[:,:,mHeight]
3226 meteorVolts0 = volts[:,:,mHeight]
1987 meteorThresh = noise[:,mHeight]*thresholdNoise
3227 meteorThresh = noise[:,mHeight]*thresholdNoise
1988 meteorNoise = noise[:,mHeight]
3228 meteorNoise = noise[:,mHeight]
1989 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3229 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
1990 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3230 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
1991
3231
1992 #Times reestimation
3232 #Times reestimation
1993 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3233 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
1994 if mStart1.size > 0:
3234 if mStart1.size > 0:
1995 mStart1 = mStart1[-1] + 1
3235 mStart1 = mStart1[-1] + 1
1996
3236
1997 else:
3237 else:
1998 mStart1 = mPeak
3238 mStart1 = mPeak
1999
3239
2000 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3240 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
2001 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3241 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
2002 if mEndDecayTime1.size == 0:
3242 if mEndDecayTime1.size == 0:
2003 mEndDecayTime1 = powerNet0.size
3243 mEndDecayTime1 = powerNet0.size
2004 else:
3244 else:
2005 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3245 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
2006 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3246 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
2007
3247
2008 #meteorVolts1.- all Channels, from start to end
3248 #meteorVolts1.- all Channels, from start to end
2009 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3249 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
2010 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3250 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
2011 if meteorVolts2.shape[1] == 0:
3251 if meteorVolts2.shape[1] == 0:
2012 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3252 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
2013 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3253 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
2014 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3254 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
2015 ##################### END PARAMETERS REESTIMATION #########################
3255 ##################### END PARAMETERS REESTIMATION #########################
2016
3256
2017 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3257 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
2018 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3258 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
2019 if meteorVolts2.shape[1] > 0:
3259 if meteorVolts2.shape[1] > 0:
2020 #Phase Difference re-estimation
3260 #Phase Difference re-estimation
2021 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3261 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
2022 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3262 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
2023 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3263 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
2024 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3264 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
2025 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3265 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
2026
3266
2027 #Phase Difference RMS
3267 #Phase Difference RMS
2028 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3268 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
2029 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3269 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
2030 #Data from Meteor
3270 #Data from Meteor
2031 mPeak1 = powerNet1.argmax() + mStart1
3271 mPeak1 = powerNet1.argmax() + mStart1
2032 mPeakPower1 = powerNet1.max()
3272 mPeakPower1 = powerNet1.max()
2033 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3273 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
2034 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3274 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
2035 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3275 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
2036 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3276 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
2037 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3277 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
2038 #Vectorize
3278 #Vectorize
2039 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3279 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
2040 meteorAux[7:11] = phaseDiffint[0:4]
3280 meteorAux[7:11] = phaseDiffint[0:4]
2041
3281
2042 #Rejection Criterions
3282 #Rejection Criterions
2043 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3283 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
2044 meteorAux[-1] = 17
3284 meteorAux[-1] = 17
2045 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3285 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
2046 meteorAux[-1] = 1
3286 meteorAux[-1] = 1
2047
3287
2048
3288
2049 else:
3289 else:
2050 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3290 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
2051 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3291 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
2052 PowerSeries = 0
3292 PowerSeries = 0
2053
3293
2054 listMeteors1.append(meteorAux)
3294 listMeteors1.append(meteorAux)
2055 listPowerSeries.append(PowerSeries)
3295 listPowerSeries.append(PowerSeries)
2056 listVoltageSeries.append(meteorVolts1)
3296 listVoltageSeries.append(meteorVolts1)
2057
3297
2058 return listMeteors1, listPowerSeries, listVoltageSeries
3298 return listMeteors1, listPowerSeries, listVoltageSeries
2059
3299
2060 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3300 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
2061
3301
2062 threshError = 10
3302 threshError = 10
2063 #Depending if it is 30 or 50 MHz
3303 #Depending if it is 30 or 50 MHz
2064 if frequency == 30.175e6:
3304 if frequency == 30e6:
2065 timeLag = 45*10**-3
3305 timeLag = 45*10**-3
2066 else:
3306 else:
2067 timeLag = 15*10**-3
3307 timeLag = 15*10**-3
2068 lag = int(numpy.ceil(timeLag/timeInterval))
3308 lag = numpy.ceil(timeLag/timeInterval)
2069
3309
2070 listMeteors1 = []
3310 listMeteors1 = []
2071
3311
2072 for i in range(len(listMeteors)):
3312 for i in range(len(listMeteors)):
2073 meteorPower = listPower[i]
3313 meteorPower = listPower[i]
2074 meteorAux = listMeteors[i]
3314 meteorAux = listMeteors[i]
2075
3315
2076 if meteorAux[-1] == 0:
3316 if meteorAux[-1] == 0:
2077
3317
2078 try:
3318 try:
2079 indmax = meteorPower.argmax()
3319 indmax = meteorPower.argmax()
2080 indlag = indmax + lag
3320 indlag = indmax + lag
2081
3321
2082 y = meteorPower[indlag:]
3322 y = meteorPower[indlag:]
2083 x = numpy.arange(0, y.size)*timeLag
3323 x = numpy.arange(0, y.size)*timeLag
2084
3324
2085 #first guess
3325 #first guess
2086 a = y[0]
3326 a = y[0]
2087 tau = timeLag
3327 tau = timeLag
2088 #exponential fit
3328 #exponential fit
2089 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3329 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
2090 y1 = self.__exponential_function(x, *popt)
3330 y1 = self.__exponential_function(x, *popt)
2091 #error estimation
3331 #error estimation
2092 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3332 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
2093
3333
2094 decayTime = popt[1]
3334 decayTime = popt[1]
2095 riseTime = indmax*timeInterval
3335 riseTime = indmax*timeInterval
2096 meteorAux[11:13] = [decayTime, error]
3336 meteorAux[11:13] = [decayTime, error]
2097
3337
2098 #Table items 7, 8 and 11
3338 #Table items 7, 8 and 11
2099 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3339 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
2100 meteorAux[-1] = 7
3340 meteorAux[-1] = 7
2101 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3341 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
2102 meteorAux[-1] = 8
3342 meteorAux[-1] = 8
2103 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3343 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
2104 meteorAux[-1] = 11
3344 meteorAux[-1] = 11
2105
3345
2106
3346
2107 except:
3347 except:
2108 meteorAux[-1] = 11
3348 meteorAux[-1] = 11
2109
3349
2110
3350
2111 listMeteors1.append(meteorAux)
3351 listMeteors1.append(meteorAux)
2112
3352
2113 return listMeteors1
3353 return listMeteors1
2114
3354
2115 #Exponential Function
3355 #Exponential Function
2116
3356
2117 def __exponential_function(self, x, a, tau):
3357 def __exponential_function(self, x, a, tau):
2118 y = a*numpy.exp(-x/tau)
3358 y = a*numpy.exp(-x/tau)
2119 return y
3359 return y
2120
3360
2121 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3361 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
2122
3362
2123 pairslist1 = list(pairslist)
3363 pairslist1 = list(pairslist)
2124 pairslist1.append((0,4))
3364 pairslist1.append((0,1))
2125 pairslist1.append((1,3))
3365 pairslist1.append((3,4))
2126 numPairs = len(pairslist1)
3366 numPairs = len(pairslist1)
2127 #Time Lag
3367 #Time Lag
2128 timeLag = 45*10**-3
3368 timeLag = 45*10**-3
2129 c = 3e8
3369 c = 3e8
2130 lag = numpy.ceil(timeLag/timeInterval)
3370 lag = numpy.ceil(timeLag/timeInterval)
2131 freq = 30.175e6
3371 freq = 30e6
2132
3372
2133 listMeteors1 = []
3373 listMeteors1 = []
2134
3374
2135 for i in range(len(listMeteors)):
3375 for i in range(len(listMeteors)):
2136 meteorAux = listMeteors[i]
3376 meteorAux = listMeteors[i]
2137 if meteorAux[-1] == 0:
3377 if meteorAux[-1] == 0:
2138 mStart = listMeteors[i][1]
3378 mStart = listMeteors[i][1]
2139 mPeak = listMeteors[i][2]
3379 mPeak = listMeteors[i][2]
2140 mLag = mPeak - mStart + lag
3380 mLag = mPeak - mStart + lag
2141
3381
2142 #get the volt data between the start and end times of the meteor
3382 #get the volt data between the start and end times of the meteor
2143 meteorVolts = listVolts[i]
3383 meteorVolts = listVolts[i]
2144 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3384 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
2145
3385
2146 #Get CCF
3386 #Get CCF
2147 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3387 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
2148
3388
2149 #Method 2
3389 #Method 2
2150 slopes = numpy.zeros(numPairs)
3390 slopes = numpy.zeros(numPairs)
2151 time = numpy.array([-2,-1,1,2])*timeInterval
3391 time = numpy.array([-2,-1,1,2])*timeInterval
2152 angAllCCF = numpy.angle(allCCFs[:,[0,4,2,3],0])
3392 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
2153
3393
2154 #Correct phases
3394 #Correct phases
2155 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3395 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
2156 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3396 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2157
3397
2158 if indDer[0].shape[0] > 0:
3398 if indDer[0].shape[0] > 0:
2159 for i in range(indDer[0].shape[0]):
3399 for i in range(indDer[0].shape[0]):
2160 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3400 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
2161 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3401 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
2162
3402
2163 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3403 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
2164 for j in range(numPairs):
3404 for j in range(numPairs):
2165 fit = stats.linregress(time, angAllCCF[j,:])
3405 fit = stats.linregress(time, angAllCCF[j,:])
2166 slopes[j] = fit[0]
3406 slopes[j] = fit[0]
2167
3407
2168 #Remove Outlier
3408 #Remove Outlier
2169 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3409 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2170 # slopes = numpy.delete(slopes,indOut)
3410 # slopes = numpy.delete(slopes,indOut)
2171 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3411 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2172 # slopes = numpy.delete(slopes,indOut)
3412 # slopes = numpy.delete(slopes,indOut)
2173
3413
2174 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3414 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
2175 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3415 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
2176 meteorAux[-2] = radialError
3416 meteorAux[-2] = radialError
2177 meteorAux[-3] = radialVelocity
3417 meteorAux[-3] = radialVelocity
2178
3418
2179 #Setting Error
3419 #Setting Error
2180 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3420 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
2181 if numpy.abs(radialVelocity) > 200:
3421 if numpy.abs(radialVelocity) > 200:
2182 meteorAux[-1] = 15
3422 meteorAux[-1] = 15
2183 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3423 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
2184 elif radialError > radialStdThresh:
3424 elif radialError > radialStdThresh:
2185 meteorAux[-1] = 12
3425 meteorAux[-1] = 12
2186
3426
2187 listMeteors1.append(meteorAux)
3427 listMeteors1.append(meteorAux)
2188 return listMeteors1
3428 return listMeteors1
2189
3429
2190 def __setNewArrays(self, listMeteors, date, heiRang):
3430 def __setNewArrays(self, listMeteors, date, heiRang):
2191
3431
2192 #New arrays
3432 #New arrays
2193 arrayMeteors = numpy.array(listMeteors)
3433 arrayMeteors = numpy.array(listMeteors)
2194 arrayParameters = numpy.zeros((len(listMeteors), 13))
3434 arrayParameters = numpy.zeros((len(listMeteors), 13))
2195
3435
2196 #Date inclusion
3436 #Date inclusion
2197 # date = re.findall(r'\((.*?)\)', date)
3437 # date = re.findall(r'\((.*?)\)', date)
2198 # date = date[0].split(',')
3438 # date = date[0].split(',')
2199 # date = map(int, date)
3439 # date = map(int, date)
2200 #
3440 #
2201 # if len(date)<6:
3441 # if len(date)<6:
2202 # date.append(0)
3442 # date.append(0)
2203 #
3443 #
2204 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3444 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
2205 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3445 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
2206 arrayDate = numpy.tile(date, (len(listMeteors)))
3446 arrayDate = numpy.tile(date, (len(listMeteors)))
2207
3447
2208 #Meteor array
3448 #Meteor array
2209 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3449 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
2210 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3450 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
2211
3451
2212 #Parameters Array
3452 #Parameters Array
2213 arrayParameters[:,0] = arrayDate #Date
3453 arrayParameters[:,0] = arrayDate #Date
2214 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3454 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
2215 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3455 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
2216 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3456 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
2217 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3457 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
2218
3458
2219
3459
2220 return arrayParameters
3460 return arrayParameters
2221
3461
2222 class CorrectSMPhases(Operation):
3462 class CorrectSMPhases(Operation):
2223
3463
2224 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3464 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
2225
3465
2226 arrayParameters = dataOut.data_param
3466 arrayParameters = dataOut.data_param
2227 pairsList = []
3467 pairsList = []
2228 pairx = (0,1)
3468 pairx = (0,1)
2229 pairy = (2,3)
3469 pairy = (2,3)
2230 pairsList.append(pairx)
3470 pairsList.append(pairx)
2231 pairsList.append(pairy)
3471 pairsList.append(pairy)
2232 jph = numpy.zeros(4)
3472 jph = numpy.zeros(4)
2233
3473
2234 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3474 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2235 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3475 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2236 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3476 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
2237
3477
2238 meteorOps = SMOperations()
3478 meteorOps = SMOperations()
2239 if channelPositions is None:
3479 if channelPositions == None:
2240 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3480 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2241 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3481 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2242
3482
2243 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3483 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2244 h = (hmin,hmax)
3484 h = (hmin,hmax)
2245
3485
2246 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3486 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2247
3487
2248 dataOut.data_param = arrayParameters
3488 dataOut.data_param = arrayParameters
2249 return
3489 return
2250
3490
2251 class SMPhaseCalibration(Operation):
3491 class SMPhaseCalibration(Operation):
2252
3492
2253 __buffer = None
3493 __buffer = None
2254
3494
2255 __initime = None
3495 __initime = None
2256
3496
2257 __dataReady = False
3497 __dataReady = False
2258
3498
2259 __isConfig = False
3499 __isConfig = False
2260
3500
2261 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3501 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
2262
3502
2263 dataTime = currentTime + paramInterval
3503 dataTime = currentTime + paramInterval
2264 deltaTime = dataTime - initTime
3504 deltaTime = dataTime - initTime
2265
3505
2266 if deltaTime >= outputInterval or deltaTime < 0:
3506 if deltaTime >= outputInterval or deltaTime < 0:
2267 return True
3507 return True
2268
3508
2269 return False
3509 return False
2270
3510
2271 def __getGammas(self, pairs, d, phases):
3511 def __getGammas(self, pairs, d, phases):
2272 gammas = numpy.zeros(2)
3512 gammas = numpy.zeros(2)
2273
3513
2274 for i in range(len(pairs)):
3514 for i in range(len(pairs)):
2275
3515
2276 pairi = pairs[i]
3516 pairi = pairs[i]
2277
3517
2278 phip3 = phases[:,pairi[0]]
3518 phip3 = phases[:,pairi[0]]
2279 d3 = d[pairi[0]]
3519 d3 = d[pairi[0]]
2280 phip2 = phases[:,pairi[1]]
3520 phip2 = phases[:,pairi[1]]
2281 d2 = d[pairi[1]]
3521 d2 = d[pairi[1]]
2282 #Calculating gamma
3522 #Calculating gamma
2283 # jdcos = alp1/(k*d1)
3523 # jdcos = alp1/(k*d1)
2284 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3524 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
2285 jgamma = -phip2*d3/d2 - phip3
3525 jgamma = -phip2*d3/d2 - phip3
2286 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3526 jgamma = numpy.angle(numpy.exp(1j*jgamma))
2287 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3527 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
2288 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3528 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
2289
3529
2290 #Revised distribution
3530 #Revised distribution
2291 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3531 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
2292
3532
2293 #Histogram
3533 #Histogram
2294 nBins = 64
3534 nBins = 64
2295 rmin = -0.5*numpy.pi
3535 rmin = -0.5*numpy.pi
2296 rmax = 0.5*numpy.pi
3536 rmax = 0.5*numpy.pi
2297 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3537 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
2298
3538
2299 meteorsY = phaseHisto[0]
3539 meteorsY = phaseHisto[0]
2300 phasesX = phaseHisto[1][:-1]
3540 phasesX = phaseHisto[1][:-1]
2301 width = phasesX[1] - phasesX[0]
3541 width = phasesX[1] - phasesX[0]
2302 phasesX += width/2
3542 phasesX += width/2
2303
3543
2304 #Gaussian aproximation
3544 #Gaussian aproximation
2305 bpeak = meteorsY.argmax()
3545 bpeak = meteorsY.argmax()
2306 peak = meteorsY.max()
3546 peak = meteorsY.max()
2307 jmin = bpeak - 5
3547 jmin = bpeak - 5
2308 jmax = bpeak + 5 + 1
3548 jmax = bpeak + 5 + 1
2309
3549
2310 if jmin<0:
3550 if jmin<0:
2311 jmin = 0
3551 jmin = 0
2312 jmax = 6
3552 jmax = 6
2313 elif jmax > meteorsY.size:
3553 elif jmax > meteorsY.size:
2314 jmin = meteorsY.size - 6
3554 jmin = meteorsY.size - 6
2315 jmax = meteorsY.size
3555 jmax = meteorsY.size
2316
3556
2317 x0 = numpy.array([peak,bpeak,50])
3557 x0 = numpy.array([peak,bpeak,50])
2318 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3558 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
2319
3559
2320 #Gammas
3560 #Gammas
2321 gammas[i] = coeff[0][1]
3561 gammas[i] = coeff[0][1]
2322
3562
2323 return gammas
3563 return gammas
2324
3564
2325 def __residualFunction(self, coeffs, y, t):
3565 def __residualFunction(self, coeffs, y, t):
2326
3566
2327 return y - self.__gauss_function(t, coeffs)
3567 return y - self.__gauss_function(t, coeffs)
2328
3568
2329 def __gauss_function(self, t, coeffs):
3569 def __gauss_function(self, t, coeffs):
2330
3570
2331 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3571 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
2332
3572
2333 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3573 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
2334 meteorOps = SMOperations()
3574 meteorOps = SMOperations()
2335 nchan = 4
3575 nchan = 4
2336 pairx = pairsList[0] #x es 0
3576 pairx = pairsList[0] #x es 0
2337 pairy = pairsList[1] #y es 1
3577 pairy = pairsList[1] #y es 1
2338 center_xangle = 0
3578 center_xangle = 0
2339 center_yangle = 0
3579 center_yangle = 0
2340 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3580 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
2341 ntimes = len(range_angle)
3581 ntimes = len(range_angle)
2342
3582
2343 nstepsx = 20
3583 nstepsx = 20
2344 nstepsy = 20
3584 nstepsy = 20
2345
3585
2346 for iz in range(ntimes):
3586 for iz in range(ntimes):
2347 min_xangle = -range_angle[iz]/2 + center_xangle
3587 min_xangle = -range_angle[iz]/2 + center_xangle
2348 max_xangle = range_angle[iz]/2 + center_xangle
3588 max_xangle = range_angle[iz]/2 + center_xangle
2349 min_yangle = -range_angle[iz]/2 + center_yangle
3589 min_yangle = -range_angle[iz]/2 + center_yangle
2350 max_yangle = range_angle[iz]/2 + center_yangle
3590 max_yangle = range_angle[iz]/2 + center_yangle
2351
3591
2352 inc_x = (max_xangle-min_xangle)/nstepsx
3592 inc_x = (max_xangle-min_xangle)/nstepsx
2353 inc_y = (max_yangle-min_yangle)/nstepsy
3593 inc_y = (max_yangle-min_yangle)/nstepsy
2354
3594
2355 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3595 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
2356 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3596 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
2357 penalty = numpy.zeros((nstepsx,nstepsy))
3597 penalty = numpy.zeros((nstepsx,nstepsy))
2358 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3598 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
2359 jph = numpy.zeros(nchan)
3599 jph = numpy.zeros(nchan)
2360
3600
2361 # Iterations looking for the offset
3601 # Iterations looking for the offset
2362 for iy in range(int(nstepsy)):
3602 for iy in range(int(nstepsy)):
2363 for ix in range(int(nstepsx)):
3603 for ix in range(int(nstepsx)):
2364 d3 = d[pairsList[1][0]]
3604 d3 = d[pairsList[1][0]]
2365 d2 = d[pairsList[1][1]]
3605 d2 = d[pairsList[1][1]]
2366 d5 = d[pairsList[0][0]]
3606 d5 = d[pairsList[0][0]]
2367 d4 = d[pairsList[0][1]]
3607 d4 = d[pairsList[0][1]]
2368
3608
2369 alp2 = alpha_y[iy] #gamma 1
3609 alp2 = alpha_y[iy] #gamma 1
2370 alp4 = alpha_x[ix] #gamma 0
3610 alp4 = alpha_x[ix] #gamma 0
2371
3611
2372 alp3 = -alp2*d3/d2 - gammas[1]
3612 alp3 = -alp2*d3/d2 - gammas[1]
2373 alp5 = -alp4*d5/d4 - gammas[0]
3613 alp5 = -alp4*d5/d4 - gammas[0]
2374 # jph[pairy[1]] = alpha_y[iy]
3614 # jph[pairy[1]] = alpha_y[iy]
2375 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3615 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
2376
3616
2377 # jph[pairx[1]] = alpha_x[ix]
3617 # jph[pairx[1]] = alpha_x[ix]
2378 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3618 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
2379 jph[pairsList[0][1]] = alp4
3619 jph[pairsList[0][1]] = alp4
2380 jph[pairsList[0][0]] = alp5
3620 jph[pairsList[0][0]] = alp5
2381 jph[pairsList[1][0]] = alp3
3621 jph[pairsList[1][0]] = alp3
2382 jph[pairsList[1][1]] = alp2
3622 jph[pairsList[1][1]] = alp2
2383 jph_array[:,ix,iy] = jph
3623 jph_array[:,ix,iy] = jph
2384 # d = [2.0,2.5,2.5,2.0]
3624 # d = [2.0,2.5,2.5,2.0]
2385 #falta chequear si va a leer bien los meteoros
3625 #falta chequear si va a leer bien los meteoros
2386 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3626 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
2387 error = meteorsArray1[:,-1]
3627 error = meteorsArray1[:,-1]
2388 ind1 = numpy.where(error==0)[0]
3628 ind1 = numpy.where(error==0)[0]
2389 penalty[ix,iy] = ind1.size
3629 penalty[ix,iy] = ind1.size
2390
3630
2391 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3631 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
2392 phOffset = jph_array[:,i,j]
3632 phOffset = jph_array[:,i,j]
2393
3633
2394 center_xangle = phOffset[pairx[1]]
3634 center_xangle = phOffset[pairx[1]]
2395 center_yangle = phOffset[pairy[1]]
3635 center_yangle = phOffset[pairy[1]]
2396
3636
2397 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3637 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
2398 phOffset = phOffset*180/numpy.pi
3638 phOffset = phOffset*180/numpy.pi
2399 return phOffset
3639 return phOffset
2400
3640
2401
3641
2402 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3642 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
2403
3643
2404 dataOut.flagNoData = True
3644 dataOut.flagNoData = True
2405 self.__dataReady = False
3645 self.__dataReady = False
2406 dataOut.outputInterval = nHours*3600
3646 dataOut.outputInterval = nHours*3600
2407
3647
2408 if self.__isConfig == False:
3648 if self.__isConfig == False:
2409 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3649 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2410 #Get Initial LTC time
3650 #Get Initial LTC time
2411 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3651 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2412 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3652 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2413
3653
2414 self.__isConfig = True
3654 self.__isConfig = True
2415
3655
2416 if self.__buffer is None:
3656 if self.__buffer == None:
2417 self.__buffer = dataOut.data_param.copy()
3657 self.__buffer = dataOut.data_param.copy()
2418
3658
2419 else:
3659 else:
2420 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3660 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2421
3661
2422 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3662 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2423
3663
2424 if self.__dataReady:
3664 if self.__dataReady:
2425 dataOut.utctimeInit = self.__initime
3665 dataOut.utctimeInit = self.__initime
2426 self.__initime += dataOut.outputInterval #to erase time offset
3666 self.__initime += dataOut.outputInterval #to erase time offset
2427
3667
2428 freq = dataOut.frequency
3668 freq = dataOut.frequency
2429 c = dataOut.C #m/s
3669 c = dataOut.C #m/s
2430 lamb = c/freq
3670 lamb = c/freq
2431 k = 2*numpy.pi/lamb
3671 k = 2*numpy.pi/lamb
2432 azimuth = 0
3672 azimuth = 0
2433 h = (hmin, hmax)
3673 h = (hmin, hmax)
2434 # pairs = ((0,1),(2,3)) #Estrella
3674 # pairs = ((0,1),(2,3)) #Estrella
2435 # pairs = ((1,0),(2,3)) #T
3675 # pairs = ((1,0),(2,3)) #T
2436
3676
2437 if channelPositions is None:
3677 if channelPositions is None:
2438 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3678 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2439 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3679 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2440 meteorOps = SMOperations()
3680 meteorOps = SMOperations()
2441 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3681 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2442
3682
2443 #Checking correct order of pairs
3683 #Checking correct order of pairs
2444 pairs = []
3684 pairs = []
2445 if distances[1] > distances[0]:
3685 if distances[1] > distances[0]:
2446 pairs.append((1,0))
3686 pairs.append((1,0))
2447 else:
3687 else:
2448 pairs.append((0,1))
3688 pairs.append((0,1))
2449
3689
2450 if distances[3] > distances[2]:
3690 if distances[3] > distances[2]:
2451 pairs.append((3,2))
3691 pairs.append((3,2))
2452 else:
3692 else:
2453 pairs.append((2,3))
3693 pairs.append((2,3))
2454 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3694 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
2455
3695
2456 meteorsArray = self.__buffer
3696 meteorsArray = self.__buffer
2457 error = meteorsArray[:,-1]
3697 error = meteorsArray[:,-1]
2458 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3698 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
2459 ind1 = numpy.where(boolError)[0]
3699 ind1 = numpy.where(boolError)[0]
2460 meteorsArray = meteorsArray[ind1,:]
3700 meteorsArray = meteorsArray[ind1,:]
2461 meteorsArray[:,-1] = 0
3701 meteorsArray[:,-1] = 0
2462 phases = meteorsArray[:,8:12]
3702 phases = meteorsArray[:,8:12]
2463
3703
2464 #Calculate Gammas
3704 #Calculate Gammas
2465 gammas = self.__getGammas(pairs, distances, phases)
3705 gammas = self.__getGammas(pairs, distances, phases)
2466 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3706 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
2467 #Calculate Phases
3707 #Calculate Phases
2468 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3708 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
2469 phasesOff = phasesOff.reshape((1,phasesOff.size))
3709 phasesOff = phasesOff.reshape((1,phasesOff.size))
2470 dataOut.data_output = -phasesOff
3710 dataOut.data_output = -phasesOff
2471 dataOut.flagNoData = False
3711 dataOut.flagNoData = False
2472 dataOut.channelList = pairslist0
2473 self.__buffer = None
3712 self.__buffer = None
2474
3713
2475
3714
2476 return
3715 return
2477
3716
2478 class SMOperations():
3717 class SMOperations():
2479
3718
2480 def __init__(self):
3719 def __init__(self):
2481
3720
2482 return
3721 return
2483
3722
2484 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3723 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
2485
3724
2486 arrayParameters = arrayParameters0.copy()
3725 arrayParameters = arrayParameters0.copy()
2487 hmin = h[0]
3726 hmin = h[0]
2488 hmax = h[1]
3727 hmax = h[1]
2489
3728
2490 #Calculate AOA (Error N 3, 4)
3729 #Calculate AOA (Error N 3, 4)
2491 #JONES ET AL. 1998
3730 #JONES ET AL. 1998
2492 AOAthresh = numpy.pi/8
3731 AOAthresh = numpy.pi/8
2493 error = arrayParameters[:,-1]
3732 error = arrayParameters[:,-1]
2494 phases = -arrayParameters[:,8:12] + jph
3733 phases = -arrayParameters[:,8:12] + jph
2495 # phases = numpy.unwrap(phases)
3734 # phases = numpy.unwrap(phases)
2496 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3735 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
2497
3736
2498 #Calculate Heights (Error N 13 and 14)
3737 #Calculate Heights (Error N 13 and 14)
2499 error = arrayParameters[:,-1]
3738 error = arrayParameters[:,-1]
2500 Ranges = arrayParameters[:,1]
3739 Ranges = arrayParameters[:,1]
2501 zenith = arrayParameters[:,4]
3740 zenith = arrayParameters[:,4]
2502 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3741 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
2503
3742
2504 #----------------------- Get Final data ------------------------------------
3743 #----------------------- Get Final data ------------------------------------
2505 # error = arrayParameters[:,-1]
3744 # error = arrayParameters[:,-1]
2506 # ind1 = numpy.where(error==0)[0]
3745 # ind1 = numpy.where(error==0)[0]
2507 # arrayParameters = arrayParameters[ind1,:]
3746 # arrayParameters = arrayParameters[ind1,:]
2508
3747
2509 return arrayParameters
3748 return arrayParameters
2510
3749
2511 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3750 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
2512
3751
2513 arrayAOA = numpy.zeros((phases.shape[0],3))
3752 arrayAOA = numpy.zeros((phases.shape[0],3))
2514 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3753 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
2515
3754
2516 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3755 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2517 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3756 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2518 arrayAOA[:,2] = cosDirError
3757 arrayAOA[:,2] = cosDirError
2519
3758
2520 azimuthAngle = arrayAOA[:,0]
3759 azimuthAngle = arrayAOA[:,0]
2521 zenithAngle = arrayAOA[:,1]
3760 zenithAngle = arrayAOA[:,1]
2522
3761
2523 #Setting Error
3762 #Setting Error
2524 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3763 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
2525 error[indError] = 0
3764 error[indError] = 0
2526 #Number 3: AOA not fesible
3765 #Number 3: AOA not fesible
2527 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3766 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2528 error[indInvalid] = 3
3767 error[indInvalid] = 3
2529 #Number 4: Large difference in AOAs obtained from different antenna baselines
3768 #Number 4: Large difference in AOAs obtained from different antenna baselines
2530 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3769 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2531 error[indInvalid] = 4
3770 error[indInvalid] = 4
2532 return arrayAOA, error
3771 return arrayAOA, error
2533
3772
2534 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3773 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
2535
3774
2536 #Initializing some variables
3775 #Initializing some variables
2537 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3776 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2538 ang_aux = ang_aux.reshape(1,ang_aux.size)
3777 ang_aux = ang_aux.reshape(1,ang_aux.size)
2539
3778
2540 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3779 cosdir = numpy.zeros((arrayPhase.shape[0],2))
2541 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3780 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2542
3781
2543
3782
2544 for i in range(2):
3783 for i in range(2):
2545 ph0 = arrayPhase[:,pairsList[i][0]]
3784 ph0 = arrayPhase[:,pairsList[i][0]]
2546 ph1 = arrayPhase[:,pairsList[i][1]]
3785 ph1 = arrayPhase[:,pairsList[i][1]]
2547 d0 = distances[pairsList[i][0]]
3786 d0 = distances[pairsList[i][0]]
2548 d1 = distances[pairsList[i][1]]
3787 d1 = distances[pairsList[i][1]]
2549
3788
2550 ph0_aux = ph0 + ph1
3789 ph0_aux = ph0 + ph1
2551 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3790 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
2552 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3791 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
2553 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3792 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
2554 #First Estimation
3793 #First Estimation
2555 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3794 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
2556
3795
2557 #Most-Accurate Second Estimation
3796 #Most-Accurate Second Estimation
2558 phi1_aux = ph0 - ph1
3797 phi1_aux = ph0 - ph1
2559 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3798 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2560 #Direction Cosine 1
3799 #Direction Cosine 1
2561 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3800 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
2562
3801
2563 #Searching the correct Direction Cosine
3802 #Searching the correct Direction Cosine
2564 cosdir0_aux = cosdir0[:,i]
3803 cosdir0_aux = cosdir0[:,i]
2565 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3804 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2566 #Minimum Distance
3805 #Minimum Distance
2567 cosDiff = (cosdir1 - cosdir0_aux)**2
3806 cosDiff = (cosdir1 - cosdir0_aux)**2
2568 indcos = cosDiff.argmin(axis = 1)
3807 indcos = cosDiff.argmin(axis = 1)
2569 #Saving Value obtained
3808 #Saving Value obtained
2570 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3809 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2571
3810
2572 return cosdir0, cosdir
3811 return cosdir0, cosdir
2573
3812
2574 def __calculateAOA(self, cosdir, azimuth):
3813 def __calculateAOA(self, cosdir, azimuth):
2575 cosdirX = cosdir[:,0]
3814 cosdirX = cosdir[:,0]
2576 cosdirY = cosdir[:,1]
3815 cosdirY = cosdir[:,1]
2577
3816
2578 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3817 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2579 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3818 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
2580 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3819 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2581
3820
2582 return angles
3821 return angles
2583
3822
2584 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3823 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2585
3824
2586 Ramb = 375 #Ramb = c/(2*PRF)
3825 Ramb = 375 #Ramb = c/(2*PRF)
2587 Re = 6371 #Earth Radius
3826 Re = 6371 #Earth Radius
2588 heights = numpy.zeros(Ranges.shape)
3827 heights = numpy.zeros(Ranges.shape)
2589
3828
2590 R_aux = numpy.array([0,1,2])*Ramb
3829 R_aux = numpy.array([0,1,2])*Ramb
2591 R_aux = R_aux.reshape(1,R_aux.size)
3830 R_aux = R_aux.reshape(1,R_aux.size)
2592
3831
2593 Ranges = Ranges.reshape(Ranges.size,1)
3832 Ranges = Ranges.reshape(Ranges.size,1)
2594
3833
2595 Ri = Ranges + R_aux
3834 Ri = Ranges + R_aux
2596 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3835 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2597
3836
2598 #Check if there is a height between 70 and 110 km
3837 #Check if there is a height between 70 and 110 km
2599 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3838 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2600 ind_h = numpy.where(h_bool == 1)[0]
3839 ind_h = numpy.where(h_bool == 1)[0]
2601
3840
2602 hCorr = hi[ind_h, :]
3841 hCorr = hi[ind_h, :]
2603 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3842 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2604
3843
2605 hCorr = hi[ind_hCorr][:len(ind_h)]
3844 hCorr = hi[ind_hCorr][:len(ind_h)]
2606 heights[ind_h] = hCorr
3845 heights[ind_h] = hCorr
2607
3846
2608 #Setting Error
3847 #Setting Error
2609 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3848 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2610 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3849 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2611 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3850 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
2612 error[indError] = 0
3851 error[indError] = 0
2613 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3852 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2614 error[indInvalid2] = 14
3853 error[indInvalid2] = 14
2615 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3854 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2616 error[indInvalid1] = 13
3855 error[indInvalid1] = 13
2617
3856
2618 return heights, error
3857 return heights, error
2619
3858
2620 def getPhasePairs(self, channelPositions):
3859 def getPhasePairs(self, channelPositions):
2621 chanPos = numpy.array(channelPositions)
3860 chanPos = numpy.array(channelPositions)
2622 listOper = list(itertools.combinations(range(5),2))
3861 listOper = list(itertools.combinations(range(5),2))
2623
3862
2624 distances = numpy.zeros(4)
3863 distances = numpy.zeros(4)
2625 axisX = []
3864 axisX = []
2626 axisY = []
3865 axisY = []
2627 distX = numpy.zeros(3)
3866 distX = numpy.zeros(3)
2628 distY = numpy.zeros(3)
3867 distY = numpy.zeros(3)
2629 ix = 0
3868 ix = 0
2630 iy = 0
3869 iy = 0
2631
3870
2632 pairX = numpy.zeros((2,2))
3871 pairX = numpy.zeros((2,2))
2633 pairY = numpy.zeros((2,2))
3872 pairY = numpy.zeros((2,2))
2634
3873
2635 for i in range(len(listOper)):
3874 for i in range(len(listOper)):
2636 pairi = listOper[i]
3875 pairi = listOper[i]
2637
3876
2638 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3877 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
2639
3878
2640 if posDif[0] == 0:
3879 if posDif[0] == 0:
2641 axisY.append(pairi)
3880 axisY.append(pairi)
2642 distY[iy] = posDif[1]
3881 distY[iy] = posDif[1]
2643 iy += 1
3882 iy += 1
2644 elif posDif[1] == 0:
3883 elif posDif[1] == 0:
2645 axisX.append(pairi)
3884 axisX.append(pairi)
2646 distX[ix] = posDif[0]
3885 distX[ix] = posDif[0]
2647 ix += 1
3886 ix += 1
2648
3887
2649 for i in range(2):
3888 for i in range(2):
2650 if i==0:
3889 if i==0:
2651 dist0 = distX
3890 dist0 = distX
2652 axis0 = axisX
3891 axis0 = axisX
2653 else:
3892 else:
2654 dist0 = distY
3893 dist0 = distY
2655 axis0 = axisY
3894 axis0 = axisY
2656
3895
2657 side = numpy.argsort(dist0)[:-1]
3896 side = numpy.argsort(dist0)[:-1]
2658 axis0 = numpy.array(axis0)[side,:]
3897 axis0 = numpy.array(axis0)[side,:]
2659 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3898 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
2660 axis1 = numpy.unique(numpy.reshape(axis0,4))
3899 axis1 = numpy.unique(numpy.reshape(axis0,4))
2661 side = axis1[axis1 != chanC]
3900 side = axis1[axis1 != chanC]
2662 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3901 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
2663 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3902 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
2664 if diff1<0:
3903 if diff1<0:
2665 chan2 = side[0]
3904 chan2 = side[0]
2666 d2 = numpy.abs(diff1)
3905 d2 = numpy.abs(diff1)
2667 chan1 = side[1]
3906 chan1 = side[1]
2668 d1 = numpy.abs(diff2)
3907 d1 = numpy.abs(diff2)
2669 else:
3908 else:
2670 chan2 = side[1]
3909 chan2 = side[1]
2671 d2 = numpy.abs(diff2)
3910 d2 = numpy.abs(diff2)
2672 chan1 = side[0]
3911 chan1 = side[0]
2673 d1 = numpy.abs(diff1)
3912 d1 = numpy.abs(diff1)
2674
3913
2675 if i==0:
3914 if i==0:
2676 chanCX = chanC
3915 chanCX = chanC
2677 chan1X = chan1
3916 chan1X = chan1
2678 chan2X = chan2
3917 chan2X = chan2
2679 distances[0:2] = numpy.array([d1,d2])
3918 distances[0:2] = numpy.array([d1,d2])
2680 else:
3919 else:
2681 chanCY = chanC
3920 chanCY = chanC
2682 chan1Y = chan1
3921 chan1Y = chan1
2683 chan2Y = chan2
3922 chan2Y = chan2
2684 distances[2:4] = numpy.array([d1,d2])
3923 distances[2:4] = numpy.array([d1,d2])
2685 # axisXsides = numpy.reshape(axisX[ix,:],4)
3924 # axisXsides = numpy.reshape(axisX[ix,:],4)
2686 #
3925 #
2687 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3926 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
2688 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3927 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
2689 #
3928 #
2690 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3929 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
2691 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3930 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
2692 # channel25X = int(pairX[0,ind25X])
3931 # channel25X = int(pairX[0,ind25X])
2693 # channel20X = int(pairX[1,ind20X])
3932 # channel20X = int(pairX[1,ind20X])
2694 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3933 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
2695 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3934 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
2696 # channel25Y = int(pairY[0,ind25Y])
3935 # channel25Y = int(pairY[0,ind25Y])
2697 # channel20Y = int(pairY[1,ind20Y])
3936 # channel20Y = int(pairY[1,ind20Y])
2698
3937
2699 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3938 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
2700 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3939 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
2701
3940
2702 return pairslist, distances
3941 return pairslist, distances
2703 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3942 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
2704 #
3943 #
2705 # arrayAOA = numpy.zeros((phases.shape[0],3))
3944 # arrayAOA = numpy.zeros((phases.shape[0],3))
2706 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3945 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
2707 #
3946 #
2708 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3947 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2709 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3948 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2710 # arrayAOA[:,2] = cosDirError
3949 # arrayAOA[:,2] = cosDirError
2711 #
3950 #
2712 # azimuthAngle = arrayAOA[:,0]
3951 # azimuthAngle = arrayAOA[:,0]
2713 # zenithAngle = arrayAOA[:,1]
3952 # zenithAngle = arrayAOA[:,1]
2714 #
3953 #
2715 # #Setting Error
3954 # #Setting Error
2716 # #Number 3: AOA not fesible
3955 # #Number 3: AOA not fesible
2717 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3956 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2718 # error[indInvalid] = 3
3957 # error[indInvalid] = 3
2719 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3958 # #Number 4: Large difference in AOAs obtained from different antenna baselines
2720 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3959 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2721 # error[indInvalid] = 4
3960 # error[indInvalid] = 4
2722 # return arrayAOA, error
3961 # return arrayAOA, error
2723 #
3962 #
2724 # def __getDirectionCosines(self, arrayPhase, pairsList):
3963 # def __getDirectionCosines(self, arrayPhase, pairsList):
2725 #
3964 #
2726 # #Initializing some variables
3965 # #Initializing some variables
2727 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3966 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2728 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3967 # ang_aux = ang_aux.reshape(1,ang_aux.size)
2729 #
3968 #
2730 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3969 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
2731 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3970 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2732 #
3971 #
2733 #
3972 #
2734 # for i in range(2):
3973 # for i in range(2):
2735 # #First Estimation
3974 # #First Estimation
2736 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3975 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
2737 # #Dealias
3976 # #Dealias
2738 # indcsi = numpy.where(phi0_aux > numpy.pi)
3977 # indcsi = numpy.where(phi0_aux > numpy.pi)
2739 # phi0_aux[indcsi] -= 2*numpy.pi
3978 # phi0_aux[indcsi] -= 2*numpy.pi
2740 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3979 # indcsi = numpy.where(phi0_aux < -numpy.pi)
2741 # phi0_aux[indcsi] += 2*numpy.pi
3980 # phi0_aux[indcsi] += 2*numpy.pi
2742 # #Direction Cosine 0
3981 # #Direction Cosine 0
2743 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3982 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
2744 #
3983 #
2745 # #Most-Accurate Second Estimation
3984 # #Most-Accurate Second Estimation
2746 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3985 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
2747 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3986 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2748 # #Direction Cosine 1
3987 # #Direction Cosine 1
2749 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3988 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
2750 #
3989 #
2751 # #Searching the correct Direction Cosine
3990 # #Searching the correct Direction Cosine
2752 # cosdir0_aux = cosdir0[:,i]
3991 # cosdir0_aux = cosdir0[:,i]
2753 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3992 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2754 # #Minimum Distance
3993 # #Minimum Distance
2755 # cosDiff = (cosdir1 - cosdir0_aux)**2
3994 # cosDiff = (cosdir1 - cosdir0_aux)**2
2756 # indcos = cosDiff.argmin(axis = 1)
3995 # indcos = cosDiff.argmin(axis = 1)
2757 # #Saving Value obtained
3996 # #Saving Value obtained
2758 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3997 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2759 #
3998 #
2760 # return cosdir0, cosdir
3999 # return cosdir0, cosdir
2761 #
4000 #
2762 # def __calculateAOA(self, cosdir, azimuth):
4001 # def __calculateAOA(self, cosdir, azimuth):
2763 # cosdirX = cosdir[:,0]
4002 # cosdirX = cosdir[:,0]
2764 # cosdirY = cosdir[:,1]
4003 # cosdirY = cosdir[:,1]
2765 #
4004 #
2766 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
4005 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2767 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
4006 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
2768 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
4007 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2769 #
4008 #
2770 # return angles
4009 # return angles
2771 #
4010 #
2772 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
4011 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2773 #
4012 #
2774 # Ramb = 375 #Ramb = c/(2*PRF)
4013 # Ramb = 375 #Ramb = c/(2*PRF)
2775 # Re = 6371 #Earth Radius
4014 # Re = 6371 #Earth Radius
2776 # heights = numpy.zeros(Ranges.shape)
4015 # heights = numpy.zeros(Ranges.shape)
2777 #
4016 #
2778 # R_aux = numpy.array([0,1,2])*Ramb
4017 # R_aux = numpy.array([0,1,2])*Ramb
2779 # R_aux = R_aux.reshape(1,R_aux.size)
4018 # R_aux = R_aux.reshape(1,R_aux.size)
2780 #
4019 #
2781 # Ranges = Ranges.reshape(Ranges.size,1)
4020 # Ranges = Ranges.reshape(Ranges.size,1)
2782 #
4021 #
2783 # Ri = Ranges + R_aux
4022 # Ri = Ranges + R_aux
2784 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
4023 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2785 #
4024 #
2786 # #Check if there is a height between 70 and 110 km
4025 # #Check if there is a height between 70 and 110 km
2787 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
4026 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2788 # ind_h = numpy.where(h_bool == 1)[0]
4027 # ind_h = numpy.where(h_bool == 1)[0]
2789 #
4028 #
2790 # hCorr = hi[ind_h, :]
4029 # hCorr = hi[ind_h, :]
2791 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
4030 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2792 #
4031 #
2793 # hCorr = hi[ind_hCorr]
4032 # hCorr = hi[ind_hCorr]
2794 # heights[ind_h] = hCorr
4033 # heights[ind_h] = hCorr
2795 #
4034 #
2796 # #Setting Error
4035 # #Setting Error
2797 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
4036 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2798 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
4037 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2799 #
4038 #
2800 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
4039 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2801 # error[indInvalid2] = 14
4040 # error[indInvalid2] = 14
2802 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
4041 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2803 # error[indInvalid1] = 13
4042 # error[indInvalid1] = 13
2804 #
4043 #
2805 # return heights, error
4044 # return heights, error
4045 No newline at end of file
@@ -1,904 +1,903
1 import itertools
2
1 import numpy
3 import numpy
2
4
3 from jroproc_base import ProcessingUnit, Operation
5 from jroproc_base import ProcessingUnit, Operation
4 from schainpy.model.data.jrodata import Spectra
6 from schainpy.model.data.jrodata import Spectra
5 from schainpy.model.data.jrodata import hildebrand_sekhon
7 from schainpy.model.data.jrodata import hildebrand_sekhon
6
8
7 class SpectraProc(ProcessingUnit):
9 class SpectraProc(ProcessingUnit):
8
10
9 def __init__(self, **kwargs):
11 def __init__(self, **kwargs):
10
12
11 ProcessingUnit.__init__(self, **kwargs)
13 ProcessingUnit.__init__(self, **kwargs)
12
14
13 self.buffer = None
15 self.buffer = None
14 self.firstdatatime = None
16 self.firstdatatime = None
15 self.profIndex = 0
17 self.profIndex = 0
16 self.dataOut = Spectra()
18 self.dataOut = Spectra()
17 self.id_min = None
19 self.id_min = None
18 self.id_max = None
20 self.id_max = None
19
21
20 def __updateSpecFromVoltage(self):
22 def __updateSpecFromVoltage(self):
21
23
22 self.dataOut.timeZone = self.dataIn.timeZone
24 self.dataOut.timeZone = self.dataIn.timeZone
23 self.dataOut.dstFlag = self.dataIn.dstFlag
25 self.dataOut.dstFlag = self.dataIn.dstFlag
24 self.dataOut.errorCount = self.dataIn.errorCount
26 self.dataOut.errorCount = self.dataIn.errorCount
25 self.dataOut.useLocalTime = self.dataIn.useLocalTime
27 self.dataOut.useLocalTime = self.dataIn.useLocalTime
26
28
27 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
29 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
28 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
30 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
29 self.dataOut.channelList = self.dataIn.channelList
31 self.dataOut.channelList = self.dataIn.channelList
30 self.dataOut.heightList = self.dataIn.heightList
32 self.dataOut.heightList = self.dataIn.heightList
31 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
33 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
32
34
33 self.dataOut.nBaud = self.dataIn.nBaud
35 self.dataOut.nBaud = self.dataIn.nBaud
34 self.dataOut.nCode = self.dataIn.nCode
36 self.dataOut.nCode = self.dataIn.nCode
35 self.dataOut.code = self.dataIn.code
37 self.dataOut.code = self.dataIn.code
36 self.dataOut.nProfiles = self.dataOut.nFFTPoints
38 self.dataOut.nProfiles = self.dataOut.nFFTPoints
37
39
38 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
40 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
39 self.dataOut.utctime = self.firstdatatime
41 self.dataOut.utctime = self.firstdatatime
40 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
42 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
41 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
43 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
42 self.dataOut.flagShiftFFT = False
44 self.dataOut.flagShiftFFT = False
43
45
44 self.dataOut.nCohInt = self.dataIn.nCohInt
46 self.dataOut.nCohInt = self.dataIn.nCohInt
45 self.dataOut.nIncohInt = 1
47 self.dataOut.nIncohInt = 1
46
48
47 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
49 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
48
50
49 self.dataOut.frequency = self.dataIn.frequency
51 self.dataOut.frequency = self.dataIn.frequency
50 self.dataOut.realtime = self.dataIn.realtime
52 self.dataOut.realtime = self.dataIn.realtime
51
53
52 self.dataOut.azimuth = self.dataIn.azimuth
54 self.dataOut.azimuth = self.dataIn.azimuth
53 self.dataOut.zenith = self.dataIn.zenith
55 self.dataOut.zenith = self.dataIn.zenith
54
56
55 self.dataOut.beam.codeList = self.dataIn.beam.codeList
57 self.dataOut.beam.codeList = self.dataIn.beam.codeList
56 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
58 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
57 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
59 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
58
60
59 def __getFft(self):
61 def __getFft(self):
60 """
62 """
61 Convierte valores de Voltaje a Spectra
63 Convierte valores de Voltaje a Spectra
62
64
63 Affected:
65 Affected:
64 self.dataOut.data_spc
66 self.dataOut.data_spc
65 self.dataOut.data_cspc
67 self.dataOut.data_cspc
66 self.dataOut.data_dc
68 self.dataOut.data_dc
67 self.dataOut.heightList
69 self.dataOut.heightList
68 self.profIndex
70 self.profIndex
69 self.buffer
71 self.buffer
70 self.dataOut.flagNoData
72 self.dataOut.flagNoData
71 """
73 """
72 fft_volt = numpy.fft.fft(self.buffer,n=self.dataOut.nFFTPoints,axis=1)
74 fft_volt = numpy.fft.fft(self.buffer,n=self.dataOut.nFFTPoints,axis=1)
73 fft_volt = fft_volt.astype(numpy.dtype('complex'))
75 fft_volt = fft_volt.astype(numpy.dtype('complex'))
74 dc = fft_volt[:,0,:]
76 dc = fft_volt[:,0,:]
75
77
76 #calculo de self-spectra
78 #calculo de self-spectra
77 fft_volt = numpy.fft.fftshift(fft_volt,axes=(1,))
79 fft_volt = numpy.fft.fftshift(fft_volt,axes=(1,))
78 spc = fft_volt * numpy.conjugate(fft_volt)
80 spc = fft_volt * numpy.conjugate(fft_volt)
79 spc = spc.real
81 spc = spc.real
80
82
81 blocksize = 0
83 blocksize = 0
82 blocksize += dc.size
84 blocksize += dc.size
83 blocksize += spc.size
85 blocksize += spc.size
84
86
85 cspc = None
87 cspc = None
86 pairIndex = 0
88 pairIndex = 0
87 if self.dataOut.pairsList != None:
89 if self.dataOut.pairsList != None:
88 #calculo de cross-spectra
90 #calculo de cross-spectra
89 cspc = numpy.zeros((self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
91 cspc = numpy.zeros((self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
90 for pair in self.dataOut.pairsList:
92 for pair in self.dataOut.pairsList:
91 if pair[0] not in self.dataOut.channelList:
93 if pair[0] not in self.dataOut.channelList:
92 raise ValueError, "Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" %(str(pair), str(self.dataOut.channelList))
94 raise ValueError, "Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" %(str(pair), str(self.dataOut.channelList))
93 if pair[1] not in self.dataOut.channelList:
95 if pair[1] not in self.dataOut.channelList:
94 raise ValueError, "Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" %(str(pair), str(self.dataOut.channelList))
96 raise ValueError, "Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" %(str(pair), str(self.dataOut.channelList))
95
97
96 cspc[pairIndex,:,:] = fft_volt[pair[0],:,:] * numpy.conjugate(fft_volt[pair[1],:,:])
98 cspc[pairIndex,:,:] = fft_volt[pair[0],:,:] * numpy.conjugate(fft_volt[pair[1],:,:])
97 pairIndex += 1
99 pairIndex += 1
98 blocksize += cspc.size
100 blocksize += cspc.size
99
101
100 self.dataOut.data_spc = spc
102 self.dataOut.data_spc = spc
101 self.dataOut.data_cspc = cspc
103 self.dataOut.data_cspc = cspc
102 self.dataOut.data_dc = dc
104 self.dataOut.data_dc = dc
103 self.dataOut.blockSize = blocksize
105 self.dataOut.blockSize = blocksize
104 self.dataOut.flagShiftFFT = True
106 self.dataOut.flagShiftFFT = True
105
107
106 def run(self, nProfiles=None, nFFTPoints=None, pairsList=[], ippFactor=None):
108 def run(self, nProfiles=None, nFFTPoints=None, pairsList=[], ippFactor=None):
107
109
108 self.dataOut.flagNoData = True
110 self.dataOut.flagNoData = True
109
111
110 if self.dataIn.type == "Spectra":
112 if self.dataIn.type == "Spectra":
111 self.dataOut.copy(self.dataIn)
113 self.dataOut.copy(self.dataIn)
112 # self.__selectPairs(pairsList)
114 if not pairsList:
115 pairsList = itertools.combinations(self.dataOut.channelList, 2)
116 if self.dataOut.data_cspc is not None:
117 self.__selectPairs(pairsList)
113 return True
118 return True
114
119
115 if self.dataIn.type == "Voltage":
120 if self.dataIn.type == "Voltage":
116
121
117 if nFFTPoints == None:
122 if nFFTPoints == None:
118 raise ValueError, "This SpectraProc.run() need nFFTPoints input variable"
123 raise ValueError, "This SpectraProc.run() need nFFTPoints input variable"
119
124
120 if nProfiles == None:
125 if nProfiles == None:
121 nProfiles = nFFTPoints
126 nProfiles = nFFTPoints
122
127
123 if ippFactor == None:
128 if ippFactor == None:
124 ippFactor = 1
129 ippFactor = 1
125
130
126 self.dataOut.ippFactor = ippFactor
131 self.dataOut.ippFactor = ippFactor
127
132
128 self.dataOut.nFFTPoints = nFFTPoints
133 self.dataOut.nFFTPoints = nFFTPoints
129 self.dataOut.pairsList = pairsList
134 self.dataOut.pairsList = pairsList
130
135
131 if self.buffer is None:
136 if self.buffer is None:
132 self.buffer = numpy.zeros( (self.dataIn.nChannels,
137 self.buffer = numpy.zeros( (self.dataIn.nChannels,
133 nProfiles,
138 nProfiles,
134 self.dataIn.nHeights),
139 self.dataIn.nHeights),
135 dtype='complex')
140 dtype='complex')
136
141
137 if self.dataIn.flagDataAsBlock:
142 if self.dataIn.flagDataAsBlock:
138 #data dimension: [nChannels, nProfiles, nSamples]
143 #data dimension: [nChannels, nProfiles, nSamples]
139 nVoltProfiles = self.dataIn.data.shape[1]
144 nVoltProfiles = self.dataIn.data.shape[1]
140 # nVoltProfiles = self.dataIn.nProfiles
145 # nVoltProfiles = self.dataIn.nProfiles
141
146
142 if nVoltProfiles == nProfiles:
147 if nVoltProfiles == nProfiles:
143 self.buffer = self.dataIn.data.copy()
148 self.buffer = self.dataIn.data.copy()
144 self.profIndex = nVoltProfiles
149 self.profIndex = nVoltProfiles
145
150
146 elif nVoltProfiles < nProfiles:
151 elif nVoltProfiles < nProfiles:
147
152
148 if self.profIndex == 0:
153 if self.profIndex == 0:
149 self.id_min = 0
154 self.id_min = 0
150 self.id_max = nVoltProfiles
155 self.id_max = nVoltProfiles
151
156
152 self.buffer[:,self.id_min:self.id_max,:] = self.dataIn.data
157 self.buffer[:,self.id_min:self.id_max,:] = self.dataIn.data
153 self.profIndex += nVoltProfiles
158 self.profIndex += nVoltProfiles
154 self.id_min += nVoltProfiles
159 self.id_min += nVoltProfiles
155 self.id_max += nVoltProfiles
160 self.id_max += nVoltProfiles
156 else:
161 else:
157 raise ValueError, "The type object %s has %d profiles, it should just has %d profiles"%(self.dataIn.type,self.dataIn.data.shape[1],nProfiles)
162 raise ValueError, "The type object %s has %d profiles, it should just has %d profiles"%(self.dataIn.type,self.dataIn.data.shape[1],nProfiles)
158 self.dataOut.flagNoData = True
163 self.dataOut.flagNoData = True
159 return 0
164 return 0
160 else:
165 else:
161 self.buffer[:,self.profIndex,:] = self.dataIn.data.copy()
166 self.buffer[:,self.profIndex,:] = self.dataIn.data.copy()
162 self.profIndex += 1
167 self.profIndex += 1
163
168
164 if self.firstdatatime == None:
169 if self.firstdatatime == None:
165 self.firstdatatime = self.dataIn.utctime
170 self.firstdatatime = self.dataIn.utctime
166
171
167 if self.profIndex == nProfiles:
172 if self.profIndex == nProfiles:
168 self.__updateSpecFromVoltage()
173 self.__updateSpecFromVoltage()
169 self.__getFft()
174 self.__getFft()
170
175
171 self.dataOut.flagNoData = False
176 self.dataOut.flagNoData = False
172 self.firstdatatime = None
177 self.firstdatatime = None
173 self.profIndex = 0
178 self.profIndex = 0
174
179
175 return True
180 return True
176
181
177 raise ValueError, "The type of input object '%s' is not valid"%(self.dataIn.type)
182 raise ValueError, "The type of input object '%s' is not valid"%(self.dataIn.type)
178
183
179 def __selectPairs(self, pairsList):
184 def __selectPairs(self, pairsList):
180
185
181 if channelList == None:
186 if not pairsList:
182 return
187 return
183
188
184 pairsIndexListSelected = []
189 pairs = []
185
190 pairsIndex = []
186 for thisPair in pairsList:
187
191
188 if thisPair not in self.dataOut.pairsList:
192 for pair in pairsList:
193 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
189 continue
194 continue
190
195 pairs.append(pair)
191 pairIndex = self.dataOut.pairsList.index(thisPair)
196 pairsIndex.append(pairs.index(pair))
192
197
193 pairsIndexListSelected.append(pairIndex)
198 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
194
199 self.dataOut.pairsList = pairs
195 if not pairsIndexListSelected:
200 self.dataOut.pairsIndexList = pairsIndex
196 self.dataOut.data_cspc = None
197 self.dataOut.pairsList = []
198 return
199
200 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
201 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
202
201
203 return
202 return
204
203
205 def __selectPairsByChannel(self, channelList=None):
204 def __selectPairsByChannel(self, channelList=None):
206
205
207 if channelList == None:
206 if channelList == None:
208 return
207 return
209
208
210 pairsIndexListSelected = []
209 pairsIndexListSelected = []
211 for pairIndex in self.dataOut.pairsIndexList:
210 for pairIndex in self.dataOut.pairsIndexList:
212 #First pair
211 #First pair
213 if self.dataOut.pairsList[pairIndex][0] not in channelList:
212 if self.dataOut.pairsList[pairIndex][0] not in channelList:
214 continue
213 continue
215 #Second pair
214 #Second pair
216 if self.dataOut.pairsList[pairIndex][1] not in channelList:
215 if self.dataOut.pairsList[pairIndex][1] not in channelList:
217 continue
216 continue
218
217
219 pairsIndexListSelected.append(pairIndex)
218 pairsIndexListSelected.append(pairIndex)
220
219
221 if not pairsIndexListSelected:
220 if not pairsIndexListSelected:
222 self.dataOut.data_cspc = None
221 self.dataOut.data_cspc = None
223 self.dataOut.pairsList = []
222 self.dataOut.pairsList = []
224 return
223 return
225
224
226 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
225 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
227 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
226 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
228
227
229 return
228 return
230
229
231 def selectChannels(self, channelList):
230 def selectChannels(self, channelList):
232
231
233 channelIndexList = []
232 channelIndexList = []
234
233
235 for channel in channelList:
234 for channel in channelList:
236 if channel not in self.dataOut.channelList:
235 if channel not in self.dataOut.channelList:
237 raise ValueError, "Error selecting channels, Channel %d is not valid.\nAvailable channels = %s" %(channel, str(self.dataOut.channelList))
236 raise ValueError, "Error selecting channels, Channel %d is not valid.\nAvailable channels = %s" %(channel, str(self.dataOut.channelList))
238
237
239 index = self.dataOut.channelList.index(channel)
238 index = self.dataOut.channelList.index(channel)
240 channelIndexList.append(index)
239 channelIndexList.append(index)
241
240
242 self.selectChannelsByIndex(channelIndexList)
241 self.selectChannelsByIndex(channelIndexList)
243
242
244 def selectChannelsByIndex(self, channelIndexList):
243 def selectChannelsByIndex(self, channelIndexList):
245 """
244 """
246 Selecciona un bloque de datos en base a canales segun el channelIndexList
245 Selecciona un bloque de datos en base a canales segun el channelIndexList
247
246
248 Input:
247 Input:
249 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
248 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
250
249
251 Affected:
250 Affected:
252 self.dataOut.data_spc
251 self.dataOut.data_spc
253 self.dataOut.channelIndexList
252 self.dataOut.channelIndexList
254 self.dataOut.nChannels
253 self.dataOut.nChannels
255
254
256 Return:
255 Return:
257 None
256 None
258 """
257 """
259
258
260 for channelIndex in channelIndexList:
259 for channelIndex in channelIndexList:
261 if channelIndex not in self.dataOut.channelIndexList:
260 if channelIndex not in self.dataOut.channelIndexList:
262 raise ValueError, "Error selecting channels: The value %d in channelIndexList is not valid.\nAvailable channel indexes = " %(channelIndex, self.dataOut.channelIndexList)
261 raise ValueError, "Error selecting channels: The value %d in channelIndexList is not valid.\nAvailable channel indexes = " %(channelIndex, self.dataOut.channelIndexList)
263
262
264 # nChannels = len(channelIndexList)
263 # nChannels = len(channelIndexList)
265
264
266 data_spc = self.dataOut.data_spc[channelIndexList,:]
265 data_spc = self.dataOut.data_spc[channelIndexList,:]
267 data_dc = self.dataOut.data_dc[channelIndexList,:]
266 data_dc = self.dataOut.data_dc[channelIndexList,:]
268
267
269 self.dataOut.data_spc = data_spc
268 self.dataOut.data_spc = data_spc
270 self.dataOut.data_dc = data_dc
269 self.dataOut.data_dc = data_dc
271
270
272 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
271 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
273 # self.dataOut.nChannels = nChannels
272 # self.dataOut.nChannels = nChannels
274
273
275 self.__selectPairsByChannel(self.dataOut.channelList)
274 self.__selectPairsByChannel(self.dataOut.channelList)
276
275
277 return 1
276 return 1
278
277
279 def selectHeights(self, minHei, maxHei):
278 def selectHeights(self, minHei, maxHei):
280 """
279 """
281 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
280 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
282 minHei <= height <= maxHei
281 minHei <= height <= maxHei
283
282
284 Input:
283 Input:
285 minHei : valor minimo de altura a considerar
284 minHei : valor minimo de altura a considerar
286 maxHei : valor maximo de altura a considerar
285 maxHei : valor maximo de altura a considerar
287
286
288 Affected:
287 Affected:
289 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
288 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
290
289
291 Return:
290 Return:
292 1 si el metodo se ejecuto con exito caso contrario devuelve 0
291 1 si el metodo se ejecuto con exito caso contrario devuelve 0
293 """
292 """
294
293
295 if (minHei > maxHei):
294 if (minHei > maxHei):
296 raise ValueError, "Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei)
295 raise ValueError, "Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei)
297
296
298 if (minHei < self.dataOut.heightList[0]):
297 if (minHei < self.dataOut.heightList[0]):
299 minHei = self.dataOut.heightList[0]
298 minHei = self.dataOut.heightList[0]
300
299
301 if (maxHei > self.dataOut.heightList[-1]):
300 if (maxHei > self.dataOut.heightList[-1]):
302 maxHei = self.dataOut.heightList[-1]
301 maxHei = self.dataOut.heightList[-1]
303
302
304 minIndex = 0
303 minIndex = 0
305 maxIndex = 0
304 maxIndex = 0
306 heights = self.dataOut.heightList
305 heights = self.dataOut.heightList
307
306
308 inda = numpy.where(heights >= minHei)
307 inda = numpy.where(heights >= minHei)
309 indb = numpy.where(heights <= maxHei)
308 indb = numpy.where(heights <= maxHei)
310
309
311 try:
310 try:
312 minIndex = inda[0][0]
311 minIndex = inda[0][0]
313 except:
312 except:
314 minIndex = 0
313 minIndex = 0
315
314
316 try:
315 try:
317 maxIndex = indb[0][-1]
316 maxIndex = indb[0][-1]
318 except:
317 except:
319 maxIndex = len(heights)
318 maxIndex = len(heights)
320
319
321 self.selectHeightsByIndex(minIndex, maxIndex)
320 self.selectHeightsByIndex(minIndex, maxIndex)
322
321
323 return 1
322 return 1
324
323
325 def getBeaconSignal(self, tauindex = 0, channelindex = 0, hei_ref=None):
324 def getBeaconSignal(self, tauindex = 0, channelindex = 0, hei_ref=None):
326 newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
325 newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
327
326
328 if hei_ref != None:
327 if hei_ref != None:
329 newheis = numpy.where(self.dataOut.heightList>hei_ref)
328 newheis = numpy.where(self.dataOut.heightList>hei_ref)
330
329
331 minIndex = min(newheis[0])
330 minIndex = min(newheis[0])
332 maxIndex = max(newheis[0])
331 maxIndex = max(newheis[0])
333 data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1]
332 data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1]
334 heightList = self.dataOut.heightList[minIndex:maxIndex+1]
333 heightList = self.dataOut.heightList[minIndex:maxIndex+1]
335
334
336 # determina indices
335 # determina indices
337 nheis = int(self.dataOut.radarControllerHeaderObj.txB/(self.dataOut.heightList[1]-self.dataOut.heightList[0]))
336 nheis = int(self.dataOut.radarControllerHeaderObj.txB/(self.dataOut.heightList[1]-self.dataOut.heightList[0]))
338 avg_dB = 10*numpy.log10(numpy.sum(data_spc[channelindex,:,:],axis=0))
337 avg_dB = 10*numpy.log10(numpy.sum(data_spc[channelindex,:,:],axis=0))
339 beacon_dB = numpy.sort(avg_dB)[-nheis:]
338 beacon_dB = numpy.sort(avg_dB)[-nheis:]
340 beacon_heiIndexList = []
339 beacon_heiIndexList = []
341 for val in avg_dB.tolist():
340 for val in avg_dB.tolist():
342 if val >= beacon_dB[0]:
341 if val >= beacon_dB[0]:
343 beacon_heiIndexList.append(avg_dB.tolist().index(val))
342 beacon_heiIndexList.append(avg_dB.tolist().index(val))
344
343
345 #data_spc = data_spc[:,:,beacon_heiIndexList]
344 #data_spc = data_spc[:,:,beacon_heiIndexList]
346 data_cspc = None
345 data_cspc = None
347 if self.dataOut.data_cspc is not None:
346 if self.dataOut.data_cspc is not None:
348 data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1]
347 data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1]
349 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
348 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
350
349
351 data_dc = None
350 data_dc = None
352 if self.dataOut.data_dc is not None:
351 if self.dataOut.data_dc is not None:
353 data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1]
352 data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1]
354 #data_dc = data_dc[:,beacon_heiIndexList]
353 #data_dc = data_dc[:,beacon_heiIndexList]
355
354
356 self.dataOut.data_spc = data_spc
355 self.dataOut.data_spc = data_spc
357 self.dataOut.data_cspc = data_cspc
356 self.dataOut.data_cspc = data_cspc
358 self.dataOut.data_dc = data_dc
357 self.dataOut.data_dc = data_dc
359 self.dataOut.heightList = heightList
358 self.dataOut.heightList = heightList
360 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
359 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
361
360
362 return 1
361 return 1
363
362
364
363
365 def selectHeightsByIndex(self, minIndex, maxIndex):
364 def selectHeightsByIndex(self, minIndex, maxIndex):
366 """
365 """
367 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
366 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
368 minIndex <= index <= maxIndex
367 minIndex <= index <= maxIndex
369
368
370 Input:
369 Input:
371 minIndex : valor de indice minimo de altura a considerar
370 minIndex : valor de indice minimo de altura a considerar
372 maxIndex : valor de indice maximo de altura a considerar
371 maxIndex : valor de indice maximo de altura a considerar
373
372
374 Affected:
373 Affected:
375 self.dataOut.data_spc
374 self.dataOut.data_spc
376 self.dataOut.data_cspc
375 self.dataOut.data_cspc
377 self.dataOut.data_dc
376 self.dataOut.data_dc
378 self.dataOut.heightList
377 self.dataOut.heightList
379
378
380 Return:
379 Return:
381 1 si el metodo se ejecuto con exito caso contrario devuelve 0
380 1 si el metodo se ejecuto con exito caso contrario devuelve 0
382 """
381 """
383
382
384 if (minIndex < 0) or (minIndex > maxIndex):
383 if (minIndex < 0) or (minIndex > maxIndex):
385 raise ValueError, "Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex)
384 raise ValueError, "Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex)
386
385
387 if (maxIndex >= self.dataOut.nHeights):
386 if (maxIndex >= self.dataOut.nHeights):
388 maxIndex = self.dataOut.nHeights-1
387 maxIndex = self.dataOut.nHeights-1
389
388
390 #Spectra
389 #Spectra
391 data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1]
390 data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1]
392
391
393 data_cspc = None
392 data_cspc = None
394 if self.dataOut.data_cspc is not None:
393 if self.dataOut.data_cspc is not None:
395 data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1]
394 data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1]
396
395
397 data_dc = None
396 data_dc = None
398 if self.dataOut.data_dc is not None:
397 if self.dataOut.data_dc is not None:
399 data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1]
398 data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1]
400
399
401 self.dataOut.data_spc = data_spc
400 self.dataOut.data_spc = data_spc
402 self.dataOut.data_cspc = data_cspc
401 self.dataOut.data_cspc = data_cspc
403 self.dataOut.data_dc = data_dc
402 self.dataOut.data_dc = data_dc
404
403
405 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex+1]
404 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex+1]
406
405
407 return 1
406 return 1
408
407
409 def removeDC(self, mode = 2):
408 def removeDC(self, mode = 2):
410 jspectra = self.dataOut.data_spc
409 jspectra = self.dataOut.data_spc
411 jcspectra = self.dataOut.data_cspc
410 jcspectra = self.dataOut.data_cspc
412
411
413
412
414 num_chan = jspectra.shape[0]
413 num_chan = jspectra.shape[0]
415 num_hei = jspectra.shape[2]
414 num_hei = jspectra.shape[2]
416
415
417 if jcspectra is not None:
416 if jcspectra is not None:
418 jcspectraExist = True
417 jcspectraExist = True
419 num_pairs = jcspectra.shape[0]
418 num_pairs = jcspectra.shape[0]
420 else: jcspectraExist = False
419 else: jcspectraExist = False
421
420
422 freq_dc = jspectra.shape[1]/2
421 freq_dc = jspectra.shape[1]/2
423 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
422 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
424
423
425 if ind_vel[0]<0:
424 if ind_vel[0]<0:
426 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
425 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
427
426
428 if mode == 1:
427 if mode == 1:
429 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
428 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
430
429
431 if jcspectraExist:
430 if jcspectraExist:
432 jcspectra[:,freq_dc,:] = (jcspectra[:,ind_vel[1],:] + jcspectra[:,ind_vel[2],:])/2
431 jcspectra[:,freq_dc,:] = (jcspectra[:,ind_vel[1],:] + jcspectra[:,ind_vel[2],:])/2
433
432
434 if mode == 2:
433 if mode == 2:
435
434
436 vel = numpy.array([-2,-1,1,2])
435 vel = numpy.array([-2,-1,1,2])
437 xx = numpy.zeros([4,4])
436 xx = numpy.zeros([4,4])
438
437
439 for fil in range(4):
438 for fil in range(4):
440 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
439 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
441
440
442 xx_inv = numpy.linalg.inv(xx)
441 xx_inv = numpy.linalg.inv(xx)
443 xx_aux = xx_inv[0,:]
442 xx_aux = xx_inv[0,:]
444
443
445 for ich in range(num_chan):
444 for ich in range(num_chan):
446 yy = jspectra[ich,ind_vel,:]
445 yy = jspectra[ich,ind_vel,:]
447 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
446 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
448
447
449 junkid = jspectra[ich,freq_dc,:]<=0
448 junkid = jspectra[ich,freq_dc,:]<=0
450 cjunkid = sum(junkid)
449 cjunkid = sum(junkid)
451
450
452 if cjunkid.any():
451 if cjunkid.any():
453 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
452 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
454
453
455 if jcspectraExist:
454 if jcspectraExist:
456 for ip in range(num_pairs):
455 for ip in range(num_pairs):
457 yy = jcspectra[ip,ind_vel,:]
456 yy = jcspectra[ip,ind_vel,:]
458 jcspectra[ip,freq_dc,:] = numpy.dot(xx_aux,yy)
457 jcspectra[ip,freq_dc,:] = numpy.dot(xx_aux,yy)
459
458
460
459
461 self.dataOut.data_spc = jspectra
460 self.dataOut.data_spc = jspectra
462 self.dataOut.data_cspc = jcspectra
461 self.dataOut.data_cspc = jcspectra
463
462
464 return 1
463 return 1
465
464
466 def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None):
465 def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None):
467
466
468 jspectra = self.dataOut.data_spc
467 jspectra = self.dataOut.data_spc
469 jcspectra = self.dataOut.data_cspc
468 jcspectra = self.dataOut.data_cspc
470 jnoise = self.dataOut.getNoise()
469 jnoise = self.dataOut.getNoise()
471 num_incoh = self.dataOut.nIncohInt
470 num_incoh = self.dataOut.nIncohInt
472
471
473 num_channel = jspectra.shape[0]
472 num_channel = jspectra.shape[0]
474 num_prof = jspectra.shape[1]
473 num_prof = jspectra.shape[1]
475 num_hei = jspectra.shape[2]
474 num_hei = jspectra.shape[2]
476
475
477 #hei_interf
476 #hei_interf
478 if hei_interf is None:
477 if hei_interf is None:
479 count_hei = num_hei/2 #Como es entero no importa
478 count_hei = num_hei/2 #Como es entero no importa
480 hei_interf = numpy.asmatrix(range(count_hei)) + num_hei - count_hei
479 hei_interf = numpy.asmatrix(range(count_hei)) + num_hei - count_hei
481 hei_interf = numpy.asarray(hei_interf)[0]
480 hei_interf = numpy.asarray(hei_interf)[0]
482 #nhei_interf
481 #nhei_interf
483 if (nhei_interf == None):
482 if (nhei_interf == None):
484 nhei_interf = 5
483 nhei_interf = 5
485 if (nhei_interf < 1):
484 if (nhei_interf < 1):
486 nhei_interf = 1
485 nhei_interf = 1
487 if (nhei_interf > count_hei):
486 if (nhei_interf > count_hei):
488 nhei_interf = count_hei
487 nhei_interf = count_hei
489 if (offhei_interf == None):
488 if (offhei_interf == None):
490 offhei_interf = 0
489 offhei_interf = 0
491
490
492 ind_hei = range(num_hei)
491 ind_hei = range(num_hei)
493 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
492 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
494 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
493 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
495 mask_prof = numpy.asarray(range(num_prof))
494 mask_prof = numpy.asarray(range(num_prof))
496 num_mask_prof = mask_prof.size
495 num_mask_prof = mask_prof.size
497 comp_mask_prof = [0, num_prof/2]
496 comp_mask_prof = [0, num_prof/2]
498
497
499
498
500 #noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
499 #noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
501 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
500 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
502 jnoise = numpy.nan
501 jnoise = numpy.nan
503 noise_exist = jnoise[0] < numpy.Inf
502 noise_exist = jnoise[0] < numpy.Inf
504
503
505 #Subrutina de Remocion de la Interferencia
504 #Subrutina de Remocion de la Interferencia
506 for ich in range(num_channel):
505 for ich in range(num_channel):
507 #Se ordena los espectros segun su potencia (menor a mayor)
506 #Se ordena los espectros segun su potencia (menor a mayor)
508 power = jspectra[ich,mask_prof,:]
507 power = jspectra[ich,mask_prof,:]
509 power = power[:,hei_interf]
508 power = power[:,hei_interf]
510 power = power.sum(axis = 0)
509 power = power.sum(axis = 0)
511 psort = power.ravel().argsort()
510 psort = power.ravel().argsort()
512
511
513 #Se estima la interferencia promedio en los Espectros de Potencia empleando
512 #Se estima la interferencia promedio en los Espectros de Potencia empleando
514 junkspc_interf = jspectra[ich,:,hei_interf[psort[range(offhei_interf, nhei_interf + offhei_interf)]]]
513 junkspc_interf = jspectra[ich,:,hei_interf[psort[range(offhei_interf, nhei_interf + offhei_interf)]]]
515
514
516 if noise_exist:
515 if noise_exist:
517 # tmp_noise = jnoise[ich] / num_prof
516 # tmp_noise = jnoise[ich] / num_prof
518 tmp_noise = jnoise[ich]
517 tmp_noise = jnoise[ich]
519 junkspc_interf = junkspc_interf - tmp_noise
518 junkspc_interf = junkspc_interf - tmp_noise
520 #junkspc_interf[:,comp_mask_prof] = 0
519 #junkspc_interf[:,comp_mask_prof] = 0
521
520
522 jspc_interf = junkspc_interf.sum(axis = 0) / nhei_interf
521 jspc_interf = junkspc_interf.sum(axis = 0) / nhei_interf
523 jspc_interf = jspc_interf.transpose()
522 jspc_interf = jspc_interf.transpose()
524 #Calculando el espectro de interferencia promedio
523 #Calculando el espectro de interferencia promedio
525 noiseid = numpy.where(jspc_interf <= tmp_noise/ numpy.sqrt(num_incoh))
524 noiseid = numpy.where(jspc_interf <= tmp_noise/ numpy.sqrt(num_incoh))
526 noiseid = noiseid[0]
525 noiseid = noiseid[0]
527 cnoiseid = noiseid.size
526 cnoiseid = noiseid.size
528 interfid = numpy.where(jspc_interf > tmp_noise/ numpy.sqrt(num_incoh))
527 interfid = numpy.where(jspc_interf > tmp_noise/ numpy.sqrt(num_incoh))
529 interfid = interfid[0]
528 interfid = interfid[0]
530 cinterfid = interfid.size
529 cinterfid = interfid.size
531
530
532 if (cnoiseid > 0): jspc_interf[noiseid] = 0
531 if (cnoiseid > 0): jspc_interf[noiseid] = 0
533
532
534 #Expandiendo los perfiles a limpiar
533 #Expandiendo los perfiles a limpiar
535 if (cinterfid > 0):
534 if (cinterfid > 0):
536 new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof)%num_prof
535 new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof)%num_prof
537 new_interfid = numpy.asarray(new_interfid)
536 new_interfid = numpy.asarray(new_interfid)
538 new_interfid = {x for x in new_interfid}
537 new_interfid = {x for x in new_interfid}
539 new_interfid = numpy.array(list(new_interfid))
538 new_interfid = numpy.array(list(new_interfid))
540 new_cinterfid = new_interfid.size
539 new_cinterfid = new_interfid.size
541 else: new_cinterfid = 0
540 else: new_cinterfid = 0
542
541
543 for ip in range(new_cinterfid):
542 for ip in range(new_cinterfid):
544 ind = junkspc_interf[:,new_interfid[ip]].ravel().argsort()
543 ind = junkspc_interf[:,new_interfid[ip]].ravel().argsort()
545 jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf/2],new_interfid[ip]]
544 jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf/2],new_interfid[ip]]
546
545
547
546
548 jspectra[ich,:,ind_hei] = jspectra[ich,:,ind_hei] - jspc_interf #Corregir indices
547 jspectra[ich,:,ind_hei] = jspectra[ich,:,ind_hei] - jspc_interf #Corregir indices
549
548
550 #Removiendo la interferencia del punto de mayor interferencia
549 #Removiendo la interferencia del punto de mayor interferencia
551 ListAux = jspc_interf[mask_prof].tolist()
550 ListAux = jspc_interf[mask_prof].tolist()
552 maxid = ListAux.index(max(ListAux))
551 maxid = ListAux.index(max(ListAux))
553
552
554
553
555 if cinterfid > 0:
554 if cinterfid > 0:
556 for ip in range(cinterfid*(interf == 2) - 1):
555 for ip in range(cinterfid*(interf == 2) - 1):
557 ind = (jspectra[ich,interfid[ip],:] < tmp_noise*(1 + 1/numpy.sqrt(num_incoh))).nonzero()
556 ind = (jspectra[ich,interfid[ip],:] < tmp_noise*(1 + 1/numpy.sqrt(num_incoh))).nonzero()
558 cind = len(ind)
557 cind = len(ind)
559
558
560 if (cind > 0):
559 if (cind > 0):
561 jspectra[ich,interfid[ip],ind] = tmp_noise*(1 + (numpy.random.uniform(cind) - 0.5)/numpy.sqrt(num_incoh))
560 jspectra[ich,interfid[ip],ind] = tmp_noise*(1 + (numpy.random.uniform(cind) - 0.5)/numpy.sqrt(num_incoh))
562
561
563 ind = numpy.array([-2,-1,1,2])
562 ind = numpy.array([-2,-1,1,2])
564 xx = numpy.zeros([4,4])
563 xx = numpy.zeros([4,4])
565
564
566 for id1 in range(4):
565 for id1 in range(4):
567 xx[:,id1] = ind[id1]**numpy.asarray(range(4))
566 xx[:,id1] = ind[id1]**numpy.asarray(range(4))
568
567
569 xx_inv = numpy.linalg.inv(xx)
568 xx_inv = numpy.linalg.inv(xx)
570 xx = xx_inv[:,0]
569 xx = xx_inv[:,0]
571 ind = (ind + maxid + num_mask_prof)%num_mask_prof
570 ind = (ind + maxid + num_mask_prof)%num_mask_prof
572 yy = jspectra[ich,mask_prof[ind],:]
571 yy = jspectra[ich,mask_prof[ind],:]
573 jspectra[ich,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx)
572 jspectra[ich,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx)
574
573
575
574
576 indAux = (jspectra[ich,:,:] < tmp_noise*(1-1/numpy.sqrt(num_incoh))).nonzero()
575 indAux = (jspectra[ich,:,:] < tmp_noise*(1-1/numpy.sqrt(num_incoh))).nonzero()
577 jspectra[ich,indAux[0],indAux[1]] = tmp_noise * (1 - 1/numpy.sqrt(num_incoh))
576 jspectra[ich,indAux[0],indAux[1]] = tmp_noise * (1 - 1/numpy.sqrt(num_incoh))
578
577
579 #Remocion de Interferencia en el Cross Spectra
578 #Remocion de Interferencia en el Cross Spectra
580 if jcspectra is None: return jspectra, jcspectra
579 if jcspectra is None: return jspectra, jcspectra
581 num_pairs = jcspectra.size/(num_prof*num_hei)
580 num_pairs = jcspectra.size/(num_prof*num_hei)
582 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
581 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
583
582
584 for ip in range(num_pairs):
583 for ip in range(num_pairs):
585
584
586 #-------------------------------------------
585 #-------------------------------------------
587
586
588 cspower = numpy.abs(jcspectra[ip,mask_prof,:])
587 cspower = numpy.abs(jcspectra[ip,mask_prof,:])
589 cspower = cspower[:,hei_interf]
588 cspower = cspower[:,hei_interf]
590 cspower = cspower.sum(axis = 0)
589 cspower = cspower.sum(axis = 0)
591
590
592 cspsort = cspower.ravel().argsort()
591 cspsort = cspower.ravel().argsort()
593 junkcspc_interf = jcspectra[ip,:,hei_interf[cspsort[range(offhei_interf, nhei_interf + offhei_interf)]]]
592 junkcspc_interf = jcspectra[ip,:,hei_interf[cspsort[range(offhei_interf, nhei_interf + offhei_interf)]]]
594 junkcspc_interf = junkcspc_interf.transpose()
593 junkcspc_interf = junkcspc_interf.transpose()
595 jcspc_interf = junkcspc_interf.sum(axis = 1)/nhei_interf
594 jcspc_interf = junkcspc_interf.sum(axis = 1)/nhei_interf
596
595
597 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
596 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
598
597
599 median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:]))
598 median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:]))
600 median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:]))
599 median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:]))
601 junkcspc_interf[comp_mask_prof,:] = numpy.complex(median_real, median_imag)
600 junkcspc_interf[comp_mask_prof,:] = numpy.complex(median_real, median_imag)
602
601
603 for iprof in range(num_prof):
602 for iprof in range(num_prof):
604 ind = numpy.abs(junkcspc_interf[iprof,:]).ravel().argsort()
603 ind = numpy.abs(junkcspc_interf[iprof,:]).ravel().argsort()
605 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf/2]]
604 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf/2]]
606
605
607 #Removiendo la Interferencia
606 #Removiendo la Interferencia
608 jcspectra[ip,:,ind_hei] = jcspectra[ip,:,ind_hei] - jcspc_interf
607 jcspectra[ip,:,ind_hei] = jcspectra[ip,:,ind_hei] - jcspc_interf
609
608
610 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
609 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
611 maxid = ListAux.index(max(ListAux))
610 maxid = ListAux.index(max(ListAux))
612
611
613 ind = numpy.array([-2,-1,1,2])
612 ind = numpy.array([-2,-1,1,2])
614 xx = numpy.zeros([4,4])
613 xx = numpy.zeros([4,4])
615
614
616 for id1 in range(4):
615 for id1 in range(4):
617 xx[:,id1] = ind[id1]**numpy.asarray(range(4))
616 xx[:,id1] = ind[id1]**numpy.asarray(range(4))
618
617
619 xx_inv = numpy.linalg.inv(xx)
618 xx_inv = numpy.linalg.inv(xx)
620 xx = xx_inv[:,0]
619 xx = xx_inv[:,0]
621
620
622 ind = (ind + maxid + num_mask_prof)%num_mask_prof
621 ind = (ind + maxid + num_mask_prof)%num_mask_prof
623 yy = jcspectra[ip,mask_prof[ind],:]
622 yy = jcspectra[ip,mask_prof[ind],:]
624 jcspectra[ip,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx)
623 jcspectra[ip,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx)
625
624
626 #Guardar Resultados
625 #Guardar Resultados
627 self.dataOut.data_spc = jspectra
626 self.dataOut.data_spc = jspectra
628 self.dataOut.data_cspc = jcspectra
627 self.dataOut.data_cspc = jcspectra
629
628
630 return 1
629 return 1
631
630
632 def setRadarFrequency(self, frequency=None):
631 def setRadarFrequency(self, frequency=None):
633
632
634 if frequency != None:
633 if frequency != None:
635 self.dataOut.frequency = frequency
634 self.dataOut.frequency = frequency
636
635
637 return 1
636 return 1
638
637
639 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
638 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
640 #validacion de rango
639 #validacion de rango
641 if minHei == None:
640 if minHei == None:
642 minHei = self.dataOut.heightList[0]
641 minHei = self.dataOut.heightList[0]
643
642
644 if maxHei == None:
643 if maxHei == None:
645 maxHei = self.dataOut.heightList[-1]
644 maxHei = self.dataOut.heightList[-1]
646
645
647 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
646 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
648 print 'minHei: %.2f is out of the heights range'%(minHei)
647 print 'minHei: %.2f is out of the heights range'%(minHei)
649 print 'minHei is setting to %.2f'%(self.dataOut.heightList[0])
648 print 'minHei is setting to %.2f'%(self.dataOut.heightList[0])
650 minHei = self.dataOut.heightList[0]
649 minHei = self.dataOut.heightList[0]
651
650
652 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
651 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
653 print 'maxHei: %.2f is out of the heights range'%(maxHei)
652 print 'maxHei: %.2f is out of the heights range'%(maxHei)
654 print 'maxHei is setting to %.2f'%(self.dataOut.heightList[-1])
653 print 'maxHei is setting to %.2f'%(self.dataOut.heightList[-1])
655 maxHei = self.dataOut.heightList[-1]
654 maxHei = self.dataOut.heightList[-1]
656
655
657 # validacion de velocidades
656 # validacion de velocidades
658 velrange = self.dataOut.getVelRange(1)
657 velrange = self.dataOut.getVelRange(1)
659
658
660 if minVel == None:
659 if minVel == None:
661 minVel = velrange[0]
660 minVel = velrange[0]
662
661
663 if maxVel == None:
662 if maxVel == None:
664 maxVel = velrange[-1]
663 maxVel = velrange[-1]
665
664
666 if (minVel < velrange[0]) or (minVel > maxVel):
665 if (minVel < velrange[0]) or (minVel > maxVel):
667 print 'minVel: %.2f is out of the velocity range'%(minVel)
666 print 'minVel: %.2f is out of the velocity range'%(minVel)
668 print 'minVel is setting to %.2f'%(velrange[0])
667 print 'minVel is setting to %.2f'%(velrange[0])
669 minVel = velrange[0]
668 minVel = velrange[0]
670
669
671 if (maxVel > velrange[-1]) or (maxVel < minVel):
670 if (maxVel > velrange[-1]) or (maxVel < minVel):
672 print 'maxVel: %.2f is out of the velocity range'%(maxVel)
671 print 'maxVel: %.2f is out of the velocity range'%(maxVel)
673 print 'maxVel is setting to %.2f'%(velrange[-1])
672 print 'maxVel is setting to %.2f'%(velrange[-1])
674 maxVel = velrange[-1]
673 maxVel = velrange[-1]
675
674
676 # seleccion de indices para rango
675 # seleccion de indices para rango
677 minIndex = 0
676 minIndex = 0
678 maxIndex = 0
677 maxIndex = 0
679 heights = self.dataOut.heightList
678 heights = self.dataOut.heightList
680
679
681 inda = numpy.where(heights >= minHei)
680 inda = numpy.where(heights >= minHei)
682 indb = numpy.where(heights <= maxHei)
681 indb = numpy.where(heights <= maxHei)
683
682
684 try:
683 try:
685 minIndex = inda[0][0]
684 minIndex = inda[0][0]
686 except:
685 except:
687 minIndex = 0
686 minIndex = 0
688
687
689 try:
688 try:
690 maxIndex = indb[0][-1]
689 maxIndex = indb[0][-1]
691 except:
690 except:
692 maxIndex = len(heights)
691 maxIndex = len(heights)
693
692
694 if (minIndex < 0) or (minIndex > maxIndex):
693 if (minIndex < 0) or (minIndex > maxIndex):
695 raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex)
694 raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex)
696
695
697 if (maxIndex >= self.dataOut.nHeights):
696 if (maxIndex >= self.dataOut.nHeights):
698 maxIndex = self.dataOut.nHeights-1
697 maxIndex = self.dataOut.nHeights-1
699
698
700 # seleccion de indices para velocidades
699 # seleccion de indices para velocidades
701 indminvel = numpy.where(velrange >= minVel)
700 indminvel = numpy.where(velrange >= minVel)
702 indmaxvel = numpy.where(velrange <= maxVel)
701 indmaxvel = numpy.where(velrange <= maxVel)
703 try:
702 try:
704 minIndexVel = indminvel[0][0]
703 minIndexVel = indminvel[0][0]
705 except:
704 except:
706 minIndexVel = 0
705 minIndexVel = 0
707
706
708 try:
707 try:
709 maxIndexVel = indmaxvel[0][-1]
708 maxIndexVel = indmaxvel[0][-1]
710 except:
709 except:
711 maxIndexVel = len(velrange)
710 maxIndexVel = len(velrange)
712
711
713 #seleccion del espectro
712 #seleccion del espectro
714 data_spc = self.dataOut.data_spc[:,minIndexVel:maxIndexVel+1,minIndex:maxIndex+1]
713 data_spc = self.dataOut.data_spc[:,minIndexVel:maxIndexVel+1,minIndex:maxIndex+1]
715 #estimacion de ruido
714 #estimacion de ruido
716 noise = numpy.zeros(self.dataOut.nChannels)
715 noise = numpy.zeros(self.dataOut.nChannels)
717
716
718 for channel in range(self.dataOut.nChannels):
717 for channel in range(self.dataOut.nChannels):
719 daux = data_spc[channel,:,:]
718 daux = data_spc[channel,:,:]
720 noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt)
719 noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt)
721
720
722 self.dataOut.noise_estimation = noise.copy()
721 self.dataOut.noise_estimation = noise.copy()
723
722
724 return 1
723 return 1
725
724
726 class IncohInt(Operation):
725 class IncohInt(Operation):
727
726
728
727
729 __profIndex = 0
728 __profIndex = 0
730 __withOverapping = False
729 __withOverapping = False
731
730
732 __byTime = False
731 __byTime = False
733 __initime = None
732 __initime = None
734 __lastdatatime = None
733 __lastdatatime = None
735 __integrationtime = None
734 __integrationtime = None
736
735
737 __buffer_spc = None
736 __buffer_spc = None
738 __buffer_cspc = None
737 __buffer_cspc = None
739 __buffer_dc = None
738 __buffer_dc = None
740
739
741 __dataReady = False
740 __dataReady = False
742
741
743 __timeInterval = None
742 __timeInterval = None
744
743
745 n = None
744 n = None
746
745
747
746
748
747
749 def __init__(self, **kwargs):
748 def __init__(self, **kwargs):
750
749
751 Operation.__init__(self, **kwargs)
750 Operation.__init__(self, **kwargs)
752 # self.isConfig = False
751 # self.isConfig = False
753
752
754 def setup(self, n=None, timeInterval=None, overlapping=False):
753 def setup(self, n=None, timeInterval=None, overlapping=False):
755 """
754 """
756 Set the parameters of the integration class.
755 Set the parameters of the integration class.
757
756
758 Inputs:
757 Inputs:
759
758
760 n : Number of coherent integrations
759 n : Number of coherent integrations
761 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
760 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
762 overlapping :
761 overlapping :
763
762
764 """
763 """
765
764
766 self.__initime = None
765 self.__initime = None
767 self.__lastdatatime = 0
766 self.__lastdatatime = 0
768
767
769 self.__buffer_spc = 0
768 self.__buffer_spc = 0
770 self.__buffer_cspc = 0
769 self.__buffer_cspc = 0
771 self.__buffer_dc = 0
770 self.__buffer_dc = 0
772
771
773 self.__profIndex = 0
772 self.__profIndex = 0
774 self.__dataReady = False
773 self.__dataReady = False
775 self.__byTime = False
774 self.__byTime = False
776
775
777 if n is None and timeInterval is None:
776 if n is None and timeInterval is None:
778 raise ValueError, "n or timeInterval should be specified ..."
777 raise ValueError, "n or timeInterval should be specified ..."
779
778
780 if n is not None:
779 if n is not None:
781 self.n = int(n)
780 self.n = int(n)
782 else:
781 else:
783 self.__integrationtime = int(timeInterval) #if (type(timeInterval)!=integer) -> change this line
782 self.__integrationtime = int(timeInterval) #if (type(timeInterval)!=integer) -> change this line
784 self.n = None
783 self.n = None
785 self.__byTime = True
784 self.__byTime = True
786
785
787 def putData(self, data_spc, data_cspc, data_dc):
786 def putData(self, data_spc, data_cspc, data_dc):
788
787
789 """
788 """
790 Add a profile to the __buffer_spc and increase in one the __profileIndex
789 Add a profile to the __buffer_spc and increase in one the __profileIndex
791
790
792 """
791 """
793
792
794 self.__buffer_spc += data_spc
793 self.__buffer_spc += data_spc
795
794
796 if data_cspc is None:
795 if data_cspc is None:
797 self.__buffer_cspc = None
796 self.__buffer_cspc = None
798 else:
797 else:
799 self.__buffer_cspc += data_cspc
798 self.__buffer_cspc += data_cspc
800
799
801 if data_dc is None:
800 if data_dc is None:
802 self.__buffer_dc = None
801 self.__buffer_dc = None
803 else:
802 else:
804 self.__buffer_dc += data_dc
803 self.__buffer_dc += data_dc
805
804
806 self.__profIndex += 1
805 self.__profIndex += 1
807
806
808 return
807 return
809
808
810 def pushData(self):
809 def pushData(self):
811 """
810 """
812 Return the sum of the last profiles and the profiles used in the sum.
811 Return the sum of the last profiles and the profiles used in the sum.
813
812
814 Affected:
813 Affected:
815
814
816 self.__profileIndex
815 self.__profileIndex
817
816
818 """
817 """
819
818
820 data_spc = self.__buffer_spc
819 data_spc = self.__buffer_spc
821 data_cspc = self.__buffer_cspc
820 data_cspc = self.__buffer_cspc
822 data_dc = self.__buffer_dc
821 data_dc = self.__buffer_dc
823 n = self.__profIndex
822 n = self.__profIndex
824
823
825 self.__buffer_spc = 0
824 self.__buffer_spc = 0
826 self.__buffer_cspc = 0
825 self.__buffer_cspc = 0
827 self.__buffer_dc = 0
826 self.__buffer_dc = 0
828 self.__profIndex = 0
827 self.__profIndex = 0
829
828
830 return data_spc, data_cspc, data_dc, n
829 return data_spc, data_cspc, data_dc, n
831
830
832 def byProfiles(self, *args):
831 def byProfiles(self, *args):
833
832
834 self.__dataReady = False
833 self.__dataReady = False
835 avgdata_spc = None
834 avgdata_spc = None
836 avgdata_cspc = None
835 avgdata_cspc = None
837 avgdata_dc = None
836 avgdata_dc = None
838
837
839 self.putData(*args)
838 self.putData(*args)
840
839
841 if self.__profIndex == self.n:
840 if self.__profIndex == self.n:
842
841
843 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
842 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
844 self.n = n
843 self.n = n
845 self.__dataReady = True
844 self.__dataReady = True
846
845
847 return avgdata_spc, avgdata_cspc, avgdata_dc
846 return avgdata_spc, avgdata_cspc, avgdata_dc
848
847
849 def byTime(self, datatime, *args):
848 def byTime(self, datatime, *args):
850
849
851 self.__dataReady = False
850 self.__dataReady = False
852 avgdata_spc = None
851 avgdata_spc = None
853 avgdata_cspc = None
852 avgdata_cspc = None
854 avgdata_dc = None
853 avgdata_dc = None
855
854
856 self.putData(*args)
855 self.putData(*args)
857
856
858 if (datatime - self.__initime) >= self.__integrationtime:
857 if (datatime - self.__initime) >= self.__integrationtime:
859 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
858 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
860 self.n = n
859 self.n = n
861 self.__dataReady = True
860 self.__dataReady = True
862
861
863 return avgdata_spc, avgdata_cspc, avgdata_dc
862 return avgdata_spc, avgdata_cspc, avgdata_dc
864
863
865 def integrate(self, datatime, *args):
864 def integrate(self, datatime, *args):
866
865
867 if self.__profIndex == 0:
866 if self.__profIndex == 0:
868 self.__initime = datatime
867 self.__initime = datatime
869
868
870 if self.__byTime:
869 if self.__byTime:
871 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(datatime, *args)
870 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(datatime, *args)
872 else:
871 else:
873 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
872 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
874
873
875 if not self.__dataReady:
874 if not self.__dataReady:
876 return None, None, None, None
875 return None, None, None, None
877
876
878 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
877 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
879
878
880 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
879 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
881
880
882 if n==1:
881 if n==1:
883 return
882 return
884
883
885 dataOut.flagNoData = True
884 dataOut.flagNoData = True
886
885
887 if not self.isConfig:
886 if not self.isConfig:
888 self.setup(n, timeInterval, overlapping)
887 self.setup(n, timeInterval, overlapping)
889 self.isConfig = True
888 self.isConfig = True
890
889
891 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
890 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
892 dataOut.data_spc,
891 dataOut.data_spc,
893 dataOut.data_cspc,
892 dataOut.data_cspc,
894 dataOut.data_dc)
893 dataOut.data_dc)
895
894
896 if self.__dataReady:
895 if self.__dataReady:
897
896
898 dataOut.data_spc = avgdata_spc
897 dataOut.data_spc = avgdata_spc
899 dataOut.data_cspc = avgdata_cspc
898 dataOut.data_cspc = avgdata_cspc
900 dataOut.data_dc = avgdata_dc
899 dataOut.data_dc = avgdata_dc
901
900
902 dataOut.nIncohInt *= self.n
901 dataOut.nIncohInt *= self.n
903 dataOut.utctime = avgdatatime
902 dataOut.utctime = avgdatatime
904 dataOut.flagNoData = False
903 dataOut.flagNoData = False
@@ -1,501 +1,604
1 '''
1 '''
2 @author: Juan C. Espinoza
2 @author: Juan C. Espinoza
3 '''
3 '''
4
4
5 import time
5 import time
6 import json
6 import json
7 import numpy
7 import numpy
8 import paho.mqtt.client as mqtt
8 import paho.mqtt.client as mqtt
9 import zmq
9 import zmq
10 import datetime
10 import datetime
11 from zmq.utils.monitor import recv_monitor_message
11 from zmq.utils.monitor import recv_monitor_message
12 from functools import wraps
12 from functools import wraps
13 from threading import Thread
13 from threading import Thread
14 from multiprocessing import Process
14 from multiprocessing import Process
15
15
16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 from schainpy.model.data.jrodata import JROData
17 from schainpy.model.data.jrodata import JROData
18 from schainpy.utils import log
18
19
19 MAXNUMX = 100
20 MAXNUMX = 100
20 MAXNUMY = 100
21 MAXNUMY = 100
21
22
22 class PrettyFloat(float):
23 class PrettyFloat(float):
23 def __repr__(self):
24 def __repr__(self):
24 return '%.2f' % self
25 return '%.2f' % self
25
26
26 def roundFloats(obj):
27 def roundFloats(obj):
27 if isinstance(obj, list):
28 if isinstance(obj, list):
28 return map(roundFloats, obj)
29 return map(roundFloats, obj)
29 elif isinstance(obj, float):
30 elif isinstance(obj, float):
30 return round(obj, 2)
31 return round(obj, 2)
31
32
32 def decimate(z, MAXNUMY):
33 def decimate(z, MAXNUMY):
33 # dx = int(len(self.x)/self.__MAXNUMX) + 1
34
35 dy = int(len(z[0])/MAXNUMY) + 1
34 dy = int(len(z[0])/MAXNUMY) + 1
36
35
37 return z[::, ::dy]
36 return z[::, ::dy]
38
37
39 class throttle(object):
38 class throttle(object):
40 """Decorator that prevents a function from being called more than once every
39 '''
40 Decorator that prevents a function from being called more than once every
41 time period.
41 time period.
42 To create a function that cannot be called more than once a minute, but
42 To create a function that cannot be called more than once a minute, but
43 will sleep until it can be called:
43 will sleep until it can be called:
44 @throttle(minutes=1)
44 @throttle(minutes=1)
45 def foo():
45 def foo():
46 pass
46 pass
47
47
48 for i in range(10):
48 for i in range(10):
49 foo()
49 foo()
50 print "This function has run %s times." % i
50 print "This function has run %s times." % i
51 """
51 '''
52
52
53 def __init__(self, seconds=0, minutes=0, hours=0):
53 def __init__(self, seconds=0, minutes=0, hours=0):
54 self.throttle_period = datetime.timedelta(
54 self.throttle_period = datetime.timedelta(
55 seconds=seconds, minutes=minutes, hours=hours
55 seconds=seconds, minutes=minutes, hours=hours
56 )
56 )
57
57
58 self.time_of_last_call = datetime.datetime.min
58 self.time_of_last_call = datetime.datetime.min
59
59
60 def __call__(self, fn):
60 def __call__(self, fn):
61 @wraps(fn)
61 @wraps(fn)
62 def wrapper(*args, **kwargs):
62 def wrapper(*args, **kwargs):
63 now = datetime.datetime.now()
63 now = datetime.datetime.now()
64 time_since_last_call = now - self.time_of_last_call
64 time_since_last_call = now - self.time_of_last_call
65 time_left = self.throttle_period - time_since_last_call
65 time_left = self.throttle_period - time_since_last_call
66
66
67 if time_left > datetime.timedelta(seconds=0):
67 if time_left > datetime.timedelta(seconds=0):
68 return
68 return
69
69
70 self.time_of_last_call = datetime.datetime.now()
70 self.time_of_last_call = datetime.datetime.now()
71 return fn(*args, **kwargs)
71 return fn(*args, **kwargs)
72
72
73 return wrapper
73 return wrapper
74
74
75 class Data(object):
76 '''
77 Object to hold data to be plotted
78 '''
79
80 def __init__(self, plottypes, throttle_value):
81 self.plottypes = plottypes
82 self.throttle = throttle_value
83 self.ended = False
84 self.__times = []
85
86 def __str__(self):
87 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
88 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
89
90 def __len__(self):
91 return len(self.__times)
92
93 def __getitem__(self, key):
94 if key not in self.data:
95 raise KeyError(log.error('Missing key: {}'.format(key)))
96
97 if 'spc' in key:
98 ret = self.data[key]
99 else:
100 ret = numpy.array([self.data[key][x] for x in self.times])
101 if ret.ndim > 1:
102 ret = numpy.swapaxes(ret, 0, 1)
103 return ret
104
105 def setup(self):
106 '''
107 Configure object
108 '''
109
110 self.ended = False
111 self.data = {}
112 self.__times = []
113 self.__heights = []
114 self.__all_heights = set()
115 for plot in self.plottypes:
116 self.data[plot] = {}
117
118 def shape(self, key):
119 '''
120 Get the shape of the one-element data for the given key
121 '''
122
123 if len(self.data[key]):
124 if 'spc' in key:
125 return self.data[key].shape
126 return self.data[key][self.__times[0]].shape
127 return (0,)
128
129 def update(self, dataOut):
130 '''
131 Update data object with new dataOut
132 '''
133
134 tm = dataOut.utctime
135 if tm in self.__times:
136 return
137
138 self.parameters = getattr(dataOut, 'parameters', [])
139 self.pairs = dataOut.pairsList
140 self.channels = dataOut.channelList
141 self.xrange = (dataOut.getFreqRange(1)/1000. , dataOut.getAcfRange(1) , dataOut.getVelRange(1))
142 self.interval = dataOut.getTimeInterval()
143 self.__heights.append(dataOut.heightList)
144 self.__all_heights.update(dataOut.heightList)
145 self.__times.append(tm)
146
147 for plot in self.plottypes:
148 if plot == 'spc':
149 z = dataOut.data_spc/dataOut.normFactor
150 self.data[plot] = 10*numpy.log10(z)
151 if plot == 'cspc':
152 self.data[plot] = dataOut.data_cspc
153 if plot == 'noise':
154 self.data[plot][tm] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
155 if plot == 'rti':
156 self.data[plot][tm] = dataOut.getPower()
157 if plot == 'snr_db':
158 self.data['snr'][tm] = dataOut.data_SNR
159 if plot == 'snr':
160 self.data[plot][tm] = 10*numpy.log10(dataOut.data_SNR)
161 if plot == 'dop':
162 self.data[plot][tm] = 10*numpy.log10(dataOut.data_DOP)
163 if plot == 'mean':
164 self.data[plot][tm] = dataOut.data_MEAN
165 if plot == 'std':
166 self.data[plot][tm] = dataOut.data_STD
167 if plot == 'coh':
168 self.data[plot][tm] = dataOut.getCoherence()
169 if plot == 'phase':
170 self.data[plot][tm] = dataOut.getCoherence(phase=True)
171 if plot == 'output':
172 self.data[plot][tm] = dataOut.data_output
173 if plot == 'param':
174 self.data[plot][tm] = dataOut.data_param
175
176 def normalize_heights(self):
177 '''
178 Ensure same-dimension of the data for different heighList
179 '''
180
181 H = numpy.array(list(self.__all_heights))
182 H.sort()
183 for key in self.data:
184 shape = self.shape(key)[:-1] + H.shape
185 for tm, obj in self.data[key].items():
186 h = self.__heights[self.__times.index(tm)]
187 if H.size == h.size:
188 continue
189 index = numpy.where(numpy.in1d(H, h))[0]
190 dummy = numpy.zeros(shape) + numpy.nan
191 if len(shape) == 2:
192 dummy[:, index] = obj
193 else:
194 dummy[index] = obj
195 self.data[key][tm] = dummy
196
197 self.__heights = [H for tm in self.__times]
198
199 def jsonify(self, decimate=False):
200 '''
201 Convert data to json
202 '''
203
204 ret = {}
205 tm = self.times[-1]
206
207 for key, value in self.data:
208 if key in ('spc', 'cspc'):
209 ret[key] = roundFloats(self.data[key].to_list())
210 else:
211 ret[key] = roundFloats(self.data[key][tm].to_list())
212
213 ret['timestamp'] = tm
214 ret['interval'] = self.interval
215
216 @property
217 def times(self):
218 '''
219 Return the list of times of the current data
220 '''
221
222 ret = numpy.array(self.__times)
223 ret.sort()
224 return ret
225
226 @property
227 def heights(self):
228 '''
229 Return the list of heights of the current data
230 '''
231
232 return numpy.array(self.__heights[-1])
75
233
76 class PublishData(Operation):
234 class PublishData(Operation):
77 """Clase publish."""
235 '''
236 Operation to send data over zmq.
237 '''
78
238
79 def __init__(self, **kwargs):
239 def __init__(self, **kwargs):
80 """Inicio."""
240 """Inicio."""
81 Operation.__init__(self, **kwargs)
241 Operation.__init__(self, **kwargs)
82 self.isConfig = False
242 self.isConfig = False
83 self.client = None
243 self.client = None
84 self.zeromq = None
244 self.zeromq = None
85 self.mqtt = None
245 self.mqtt = None
86
246
87 def on_disconnect(self, client, userdata, rc):
247 def on_disconnect(self, client, userdata, rc):
88 if rc != 0:
248 if rc != 0:
89 print("Unexpected disconnection.")
249 log.warning('Unexpected disconnection.')
90 self.connect()
250 self.connect()
91
251
92 def connect(self):
252 def connect(self):
93 print 'trying to connect'
253 log.warning('trying to connect')
94 try:
254 try:
95 self.client.connect(
255 self.client.connect(
96 host=self.host,
256 host=self.host,
97 port=self.port,
257 port=self.port,
98 keepalive=60*10,
258 keepalive=60*10,
99 bind_address='')
259 bind_address='')
100 self.client.loop_start()
260 self.client.loop_start()
101 # self.client.publish(
261 # self.client.publish(
102 # self.topic + 'SETUP',
262 # self.topic + 'SETUP',
103 # json.dumps(setup),
263 # json.dumps(setup),
104 # retain=True
264 # retain=True
105 # )
265 # )
106 except:
266 except:
107 print "MQTT Conection error."
267 log.error('MQTT Conection error.')
108 self.client = False
268 self.client = False
109
269
110 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
270 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
111 self.counter = 0
271 self.counter = 0
112 self.topic = kwargs.get('topic', 'schain')
272 self.topic = kwargs.get('topic', 'schain')
113 self.delay = kwargs.get('delay', 0)
273 self.delay = kwargs.get('delay', 0)
114 self.plottype = kwargs.get('plottype', 'spectra')
274 self.plottype = kwargs.get('plottype', 'spectra')
115 self.host = kwargs.get('host', "10.10.10.82")
275 self.host = kwargs.get('host', "10.10.10.82")
116 self.port = kwargs.get('port', 3000)
276 self.port = kwargs.get('port', 3000)
117 self.clientId = clientId
277 self.clientId = clientId
118 self.cnt = 0
278 self.cnt = 0
119 self.zeromq = zeromq
279 self.zeromq = zeromq
120 self.mqtt = kwargs.get('plottype', 0)
280 self.mqtt = kwargs.get('plottype', 0)
121 self.client = None
281 self.client = None
122 self.verbose = verbose
282 self.verbose = verbose
123 self.dataOut.firstdata = True
124 setup = []
283 setup = []
125 if mqtt is 1:
284 if mqtt is 1:
126 self.client = mqtt.Client(
285 self.client = mqtt.Client(
127 client_id=self.clientId + self.topic + 'SCHAIN',
286 client_id=self.clientId + self.topic + 'SCHAIN',
128 clean_session=True)
287 clean_session=True)
129 self.client.on_disconnect = self.on_disconnect
288 self.client.on_disconnect = self.on_disconnect
130 self.connect()
289 self.connect()
131 for plot in self.plottype:
290 for plot in self.plottype:
132 setup.append({
291 setup.append({
133 'plot': plot,
292 'plot': plot,
134 'topic': self.topic + plot,
293 'topic': self.topic + plot,
135 'title': getattr(self, plot + '_' + 'title', False),
294 'title': getattr(self, plot + '_' + 'title', False),
136 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
295 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
137 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
296 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
138 'xrange': getattr(self, plot + '_' + 'xrange', False),
297 'xrange': getattr(self, plot + '_' + 'xrange', False),
139 'yrange': getattr(self, plot + '_' + 'yrange', False),
298 'yrange': getattr(self, plot + '_' + 'yrange', False),
140 'zrange': getattr(self, plot + '_' + 'zrange', False),
299 'zrange': getattr(self, plot + '_' + 'zrange', False),
141 })
300 })
142 if zeromq is 1:
301 if zeromq is 1:
143 context = zmq.Context()
302 context = zmq.Context()
144 self.zmq_socket = context.socket(zmq.PUSH)
303 self.zmq_socket = context.socket(zmq.PUSH)
145 server = kwargs.get('server', 'zmq.pipe')
304 server = kwargs.get('server', 'zmq.pipe')
146
305
147 if 'tcp://' in server:
306 if 'tcp://' in server:
148 address = server
307 address = server
149 else:
308 else:
150 address = 'ipc:///tmp/%s' % server
309 address = 'ipc:///tmp/%s' % server
151
310
152 self.zmq_socket.connect(address)
311 self.zmq_socket.connect(address)
153 time.sleep(1)
312 time.sleep(1)
154
313
155
314
156 def publish_data(self):
315 def publish_data(self):
157 self.dataOut.finished = False
316 self.dataOut.finished = False
158 if self.mqtt is 1:
317 if self.mqtt is 1:
159 yData = self.dataOut.heightList[:2].tolist()
318 yData = self.dataOut.heightList[:2].tolist()
160 if self.plottype == 'spectra':
319 if self.plottype == 'spectra':
161 data = getattr(self.dataOut, 'data_spc')
320 data = getattr(self.dataOut, 'data_spc')
162 z = data/self.dataOut.normFactor
321 z = data/self.dataOut.normFactor
163 zdB = 10*numpy.log10(z)
322 zdB = 10*numpy.log10(z)
164 xlen, ylen = zdB[0].shape
323 xlen, ylen = zdB[0].shape
165 dx = int(xlen/MAXNUMX) + 1
324 dx = int(xlen/MAXNUMX) + 1
166 dy = int(ylen/MAXNUMY) + 1
325 dy = int(ylen/MAXNUMY) + 1
167 Z = [0 for i in self.dataOut.channelList]
326 Z = [0 for i in self.dataOut.channelList]
168 for i in self.dataOut.channelList:
327 for i in self.dataOut.channelList:
169 Z[i] = zdB[i][::dx, ::dy].tolist()
328 Z[i] = zdB[i][::dx, ::dy].tolist()
170 payload = {
329 payload = {
171 'timestamp': self.dataOut.utctime,
330 'timestamp': self.dataOut.utctime,
172 'data': roundFloats(Z),
331 'data': roundFloats(Z),
173 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
332 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
174 'interval': self.dataOut.getTimeInterval(),
333 'interval': self.dataOut.getTimeInterval(),
175 'type': self.plottype,
334 'type': self.plottype,
176 'yData': yData
335 'yData': yData
177 }
336 }
178 # print payload
179
337
180 elif self.plottype in ('rti', 'power'):
338 elif self.plottype in ('rti', 'power'):
181 data = getattr(self.dataOut, 'data_spc')
339 data = getattr(self.dataOut, 'data_spc')
182 z = data/self.dataOut.normFactor
340 z = data/self.dataOut.normFactor
183 avg = numpy.average(z, axis=1)
341 avg = numpy.average(z, axis=1)
184 avgdB = 10*numpy.log10(avg)
342 avgdB = 10*numpy.log10(avg)
185 xlen, ylen = z[0].shape
343 xlen, ylen = z[0].shape
186 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
344 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
187 AVG = [0 for i in self.dataOut.channelList]
345 AVG = [0 for i in self.dataOut.channelList]
188 for i in self.dataOut.channelList:
346 for i in self.dataOut.channelList:
189 AVG[i] = avgdB[i][::dy].tolist()
347 AVG[i] = avgdB[i][::dy].tolist()
190 payload = {
348 payload = {
191 'timestamp': self.dataOut.utctime,
349 'timestamp': self.dataOut.utctime,
192 'data': roundFloats(AVG),
350 'data': roundFloats(AVG),
193 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
351 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
194 'interval': self.dataOut.getTimeInterval(),
352 'interval': self.dataOut.getTimeInterval(),
195 'type': self.plottype,
353 'type': self.plottype,
196 'yData': yData
354 'yData': yData
197 }
355 }
198 elif self.plottype == 'noise':
356 elif self.plottype == 'noise':
199 noise = self.dataOut.getNoise()/self.dataOut.normFactor
357 noise = self.dataOut.getNoise()/self.dataOut.normFactor
200 noisedB = 10*numpy.log10(noise)
358 noisedB = 10*numpy.log10(noise)
201 payload = {
359 payload = {
202 'timestamp': self.dataOut.utctime,
360 'timestamp': self.dataOut.utctime,
203 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
361 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
204 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
362 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
205 'interval': self.dataOut.getTimeInterval(),
363 'interval': self.dataOut.getTimeInterval(),
206 'type': self.plottype,
364 'type': self.plottype,
207 'yData': yData
365 'yData': yData
208 }
366 }
209 elif self.plottype == 'snr':
367 elif self.plottype == 'snr':
210 data = getattr(self.dataOut, 'data_SNR')
368 data = getattr(self.dataOut, 'data_SNR')
211 avgdB = 10*numpy.log10(data)
369 avgdB = 10*numpy.log10(data)
212
370
213 ylen = data[0].size
371 ylen = data[0].size
214 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
372 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
215 AVG = [0 for i in self.dataOut.channelList]
373 AVG = [0 for i in self.dataOut.channelList]
216 for i in self.dataOut.channelList:
374 for i in self.dataOut.channelList:
217 AVG[i] = avgdB[i][::dy].tolist()
375 AVG[i] = avgdB[i][::dy].tolist()
218 payload = {
376 payload = {
219 'timestamp': self.dataOut.utctime,
377 'timestamp': self.dataOut.utctime,
220 'data': roundFloats(AVG),
378 'data': roundFloats(AVG),
221 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
379 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
222 'type': self.plottype,
380 'type': self.plottype,
223 'yData': yData
381 'yData': yData
224 }
382 }
225 else:
383 else:
226 print "Tipo de grafico invalido"
384 print "Tipo de grafico invalido"
227 payload = {
385 payload = {
228 'data': 'None',
386 'data': 'None',
229 'timestamp': 'None',
387 'timestamp': 'None',
230 'type': None
388 'type': None
231 }
389 }
232 # print 'Publishing data to {}'.format(self.host)
390
233 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
391 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
234
392
235 if self.zeromq is 1:
393 if self.zeromq is 1:
236 if self.verbose:
394 if self.verbose:
237 print '[Sending] {} - {}'.format(self.dataOut.type, self.dataOut.datatime)
395 log.log(
396 '{} - {}'.format(self.dataOut.type, self.dataOut.datatime),
397 'Sending'
398 )
238 self.zmq_socket.send_pyobj(self.dataOut)
399 self.zmq_socket.send_pyobj(self.dataOut)
239 self.dataOut.firstdata = False
240
241
400
242 def run(self, dataOut, **kwargs):
401 def run(self, dataOut, **kwargs):
243 self.dataOut = dataOut
402 self.dataOut = dataOut
244 if not self.isConfig:
403 if not self.isConfig:
245 self.setup(**kwargs)
404 self.setup(**kwargs)
246 self.isConfig = True
405 self.isConfig = True
247
406
248 self.publish_data()
407 self.publish_data()
249 time.sleep(self.delay)
408 time.sleep(self.delay)
250
409
251 def close(self):
410 def close(self):
252 if self.zeromq is 1:
411 if self.zeromq is 1:
253 self.dataOut.finished = True
412 self.dataOut.finished = True
254 self.zmq_socket.send_pyobj(self.dataOut)
413 self.zmq_socket.send_pyobj(self.dataOut)
414 time.sleep(0.1)
255 self.zmq_socket.close()
415 self.zmq_socket.close()
256 if self.client:
416 if self.client:
257 self.client.loop_stop()
417 self.client.loop_stop()
258 self.client.disconnect()
418 self.client.disconnect()
259
419
260
420
261 class ReceiverData(ProcessingUnit):
421 class ReceiverData(ProcessingUnit):
262
422
263 def __init__(self, **kwargs):
423 def __init__(self, **kwargs):
264
424
265 ProcessingUnit.__init__(self, **kwargs)
425 ProcessingUnit.__init__(self, **kwargs)
266
426
267 self.isConfig = False
427 self.isConfig = False
268 server = kwargs.get('server', 'zmq.pipe')
428 server = kwargs.get('server', 'zmq.pipe')
269 if 'tcp://' in server:
429 if 'tcp://' in server:
270 address = server
430 address = server
271 else:
431 else:
272 address = 'ipc:///tmp/%s' % server
432 address = 'ipc:///tmp/%s' % server
273
433
274 self.address = address
434 self.address = address
275 self.dataOut = JROData()
435 self.dataOut = JROData()
276
436
277 def setup(self):
437 def setup(self):
278
438
279 self.context = zmq.Context()
439 self.context = zmq.Context()
280 self.receiver = self.context.socket(zmq.PULL)
440 self.receiver = self.context.socket(zmq.PULL)
281 self.receiver.bind(self.address)
441 self.receiver.bind(self.address)
282 time.sleep(0.5)
442 time.sleep(0.5)
283 print '[Starting] ReceiverData from {}'.format(self.address)
443 log.success('ReceiverData from {}'.format(self.address))
284
444
285
445
286 def run(self):
446 def run(self):
287
447
288 if not self.isConfig:
448 if not self.isConfig:
289 self.setup()
449 self.setup()
290 self.isConfig = True
450 self.isConfig = True
291
451
292 self.dataOut = self.receiver.recv_pyobj()
452 self.dataOut = self.receiver.recv_pyobj()
293 print '[Receiving] {} - {}'.format(self.dataOut.type,
453 log.log('{} - {}'.format(self.dataOut.type,
294 self.dataOut.datatime.ctime())
454 self.dataOut.datatime.ctime(),),
455 'Receiving')
295
456
296
457
297 class PlotterReceiver(ProcessingUnit, Process):
458 class PlotterReceiver(ProcessingUnit, Process):
298
459
299 throttle_value = 5
460 throttle_value = 5
300
461
301 def __init__(self, **kwargs):
462 def __init__(self, **kwargs):
302
463
303 ProcessingUnit.__init__(self, **kwargs)
464 ProcessingUnit.__init__(self, **kwargs)
304 Process.__init__(self)
465 Process.__init__(self)
305 self.mp = False
466 self.mp = False
306 self.isConfig = False
467 self.isConfig = False
307 self.isWebConfig = False
468 self.isWebConfig = False
308 self.plottypes = []
309 self.connections = 0
469 self.connections = 0
310 server = kwargs.get('server', 'zmq.pipe')
470 server = kwargs.get('server', 'zmq.pipe')
311 plot_server = kwargs.get('plot_server', 'zmq.web')
471 plot_server = kwargs.get('plot_server', 'zmq.web')
312 if 'tcp://' in server:
472 if 'tcp://' in server:
313 address = server
473 address = server
314 else:
474 else:
315 address = 'ipc:///tmp/%s' % server
475 address = 'ipc:///tmp/%s' % server
316
476
317 if 'tcp://' in plot_server:
477 if 'tcp://' in plot_server:
318 plot_address = plot_server
478 plot_address = plot_server
319 else:
479 else:
320 plot_address = 'ipc:///tmp/%s' % plot_server
480 plot_address = 'ipc:///tmp/%s' % plot_server
321
481
322 self.address = address
482 self.address = address
323 self.plot_address = plot_address
483 self.plot_address = plot_address
324 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
484 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
325 self.realtime = kwargs.get('realtime', False)
485 self.realtime = kwargs.get('realtime', False)
326 self.throttle_value = kwargs.get('throttle', 5)
486 self.throttle_value = kwargs.get('throttle', 5)
327 self.sendData = self.initThrottle(self.throttle_value)
487 self.sendData = self.initThrottle(self.throttle_value)
488 self.dates = []
328 self.setup()
489 self.setup()
329
490
330 def setup(self):
491 def setup(self):
331
492
332 self.data = {}
493 self.data = Data(self.plottypes, self.throttle_value)
333 self.data['times'] = []
494 self.isConfig = True
334 for plottype in self.plottypes:
335 self.data[plottype] = {}
336 self.data['noise'] = {}
337 self.data['throttle'] = self.throttle_value
338 self.data['ENDED'] = False
339 self.isConfig = True
340 self.data_web = {}
341
495
342 def event_monitor(self, monitor):
496 def event_monitor(self, monitor):
343
497
344 events = {}
498 events = {}
345
499
346 for name in dir(zmq):
500 for name in dir(zmq):
347 if name.startswith('EVENT_'):
501 if name.startswith('EVENT_'):
348 value = getattr(zmq, name)
502 value = getattr(zmq, name)
349 events[value] = name
503 events[value] = name
350
504
351 while monitor.poll():
505 while monitor.poll():
352 evt = recv_monitor_message(monitor)
506 evt = recv_monitor_message(monitor)
353 if evt['event'] == 32:
507 if evt['event'] == 32:
354 self.connections += 1
508 self.connections += 1
355 if evt['event'] == 512:
509 if evt['event'] == 512:
356 pass
510 pass
357 if self.connections == 0 and self.started is True:
358 self.ended = True
359
511
360 evt.update({'description': events[evt['event']]})
512 evt.update({'description': events[evt['event']]})
361
513
362 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
514 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
363 break
515 break
364 monitor.close()
516 monitor.close()
365 print("event monitor thread done!")
517 print('event monitor thread done!')
366
518
367 def initThrottle(self, throttle_value):
519 def initThrottle(self, throttle_value):
368
520
369 @throttle(seconds=throttle_value)
521 @throttle(seconds=throttle_value)
370 def sendDataThrottled(fn_sender, data):
522 def sendDataThrottled(fn_sender, data):
371 fn_sender(data)
523 fn_sender(data)
372
524
373 return sendDataThrottled
525 return sendDataThrottled
374
526
375
376 def send(self, data):
527 def send(self, data):
377 # print '[sending] data=%s size=%s' % (data.keys(), len(data['times']))
528 log.success('Sending {}'.format(data), self.name)
378 self.sender.send_pyobj(data)
529 self.sender.send_pyobj(data)
379
530
380
381 def update(self):
382 t = self.dataOut.utctime
383
384 if t in self.data['times']:
385 return
386
387 self.data['times'].append(t)
388 self.data['dataOut'] = self.dataOut
389
390 for plottype in self.plottypes:
391 if plottype == 'spc':
392 z = self.dataOut.data_spc/self.dataOut.normFactor
393 self.data[plottype] = 10*numpy.log10(z)
394 self.data['noise'][t] = 10*numpy.log10(self.dataOut.getNoise()/self.dataOut.normFactor)
395 if plottype == 'cspc':
396 jcoherence = self.dataOut.data_cspc/numpy.sqrt(self.dataOut.data_spc*self.dataOut.data_spc)
397 self.data['cspc_coh'] = numpy.abs(jcoherence)
398 self.data['cspc_phase'] = numpy.arctan2(jcoherence.imag, jcoherence.real)*180/numpy.pi
399 if plottype == 'rti':
400 self.data[plottype][t] = self.dataOut.getPower()
401 if plottype == 'snr':
402 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_SNR)
403 if plottype == 'dop':
404 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_DOP)
405 if plottype == 'mean':
406 self.data[plottype][t] = self.dataOut.data_MEAN
407 if plottype == 'std':
408 self.data[plottype][t] = self.dataOut.data_STD
409 if plottype == 'coh':
410 self.data[plottype][t] = self.dataOut.getCoherence()
411 if plottype == 'phase':
412 self.data[plottype][t] = self.dataOut.getCoherence(phase=True)
413 if plottype == 'output':
414 self.data[plottype][t] = self.dataOut.data_output
415 if plottype == 'param':
416 self.data[plottype][t] = self.dataOut.data_param
417 if self.realtime:
418 self.data_web['timestamp'] = t
419 if plottype == 'spc':
420 self.data_web[plottype] = roundFloats(decimate(self.data[plottype]).tolist())
421 elif plottype == 'cspc':
422 self.data_web['cspc_coh'] = roundFloats(decimate(self.data['cspc_coh']).tolist())
423 self.data_web['cspc_phase'] = roundFloats(decimate(self.data['cspc_phase']).tolist())
424 elif plottype == 'noise':
425 self.data_web['noise'] = roundFloats(self.data['noise'][t].tolist())
426 else:
427 self.data_web[plottype] = roundFloats(decimate(self.data[plottype][t]).tolist())
428 self.data_web['interval'] = self.dataOut.getTimeInterval()
429 self.data_web['type'] = plottype
430
431 def run(self):
531 def run(self):
432
532
433 print '[Starting] {} from {}'.format(self.name, self.address)
533 log.success(
534 'Starting from {}'.format(self.address),
535 self.name
536 )
434
537
435 self.context = zmq.Context()
538 self.context = zmq.Context()
436 self.receiver = self.context.socket(zmq.PULL)
539 self.receiver = self.context.socket(zmq.PULL)
437 self.receiver.bind(self.address)
540 self.receiver.bind(self.address)
438 monitor = self.receiver.get_monitor_socket()
541 monitor = self.receiver.get_monitor_socket()
439 self.sender = self.context.socket(zmq.PUB)
542 self.sender = self.context.socket(zmq.PUB)
440 if self.realtime:
543 if self.realtime:
441 self.sender_web = self.context.socket(zmq.PUB)
544 self.sender_web = self.context.socket(zmq.PUB)
442 self.sender_web.connect(self.plot_address)
545 self.sender_web.connect(self.plot_address)
443 time.sleep(1)
546 time.sleep(1)
444
547
445 if 'server' in self.kwargs:
548 if 'server' in self.kwargs:
446 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
549 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
447 else:
550 else:
448 self.sender.bind("ipc:///tmp/zmq.plots")
551 self.sender.bind("ipc:///tmp/zmq.plots")
449
552
450 time.sleep(3)
553 time.sleep(2)
451
554
452 t = Thread(target=self.event_monitor, args=(monitor,))
555 t = Thread(target=self.event_monitor, args=(monitor,))
453 t.start()
556 t.start()
454
557
455 while True:
558 while True:
456 self.dataOut = self.receiver.recv_pyobj()
559 dataOut = self.receiver.recv_pyobj()
457 # print '[Receiving] {} - {}'.format(self.dataOut.type,
560 dt = datetime.datetime.fromtimestamp(dataOut.utctime).date()
458 # self.dataOut.datatime.ctime())
561 sended = False
459
562 if dt not in self.dates:
460 self.update()
563 if self.data:
564 self.data.ended = True
565 self.send(self.data)
566 sended = True
567 self.data.setup()
568 self.dates.append(dt)
461
569
462 if self.dataOut.firstdata is True:
570 self.data.update(dataOut)
463 self.data['STARTED'] = True
464
571
465 if self.dataOut.finished is True:
572 if dataOut.finished is True:
466 self.send(self.data)
467 self.connections -= 1
573 self.connections -= 1
468 if self.connections == 0 and self.started:
574 if self.connections == 0 and dt in self.dates:
469 self.ended = True
575 self.data.ended = True
470 self.data['ENDED'] = True
471 self.send(self.data)
576 self.send(self.data)
472 self.setup()
577 self.data.setup()
473 self.started = False
474 else:
578 else:
475 if self.realtime:
579 if self.realtime:
476 self.send(self.data)
580 self.send(self.data)
477 self.sender_web.send_string(json.dumps(self.data_web))
581 # self.sender_web.send_string(self.data.jsonify())
478 else:
582 else:
479 self.sendData(self.send, self.data)
583 if not sended:
480 self.started = True
584 self.sendData(self.send, self.data)
481
585
482 self.data['STARTED'] = False
483 return
586 return
484
587
485 def sendToWeb(self):
588 def sendToWeb(self):
486
589
487 if not self.isWebConfig:
590 if not self.isWebConfig:
488 context = zmq.Context()
591 context = zmq.Context()
489 sender_web_config = context.socket(zmq.PUB)
592 sender_web_config = context.socket(zmq.PUB)
490 if 'tcp://' in self.plot_address:
593 if 'tcp://' in self.plot_address:
491 dum, address, port = self.plot_address.split(':')
594 dum, address, port = self.plot_address.split(':')
492 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
595 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
493 else:
596 else:
494 conf_address = self.plot_address + '.config'
597 conf_address = self.plot_address + '.config'
495 sender_web_config.bind(conf_address)
598 sender_web_config.bind(conf_address)
496 time.sleep(1)
599 time.sleep(1)
497 for kwargs in self.operationKwargs.values():
600 for kwargs in self.operationKwargs.values():
498 if 'plot' in kwargs:
601 if 'plot' in kwargs:
499 print '[Sending] Config data to web for {}'.format(kwargs['code'].upper())
602 log.success('[Sending] Config data to web for {}'.format(kwargs['code'].upper()))
500 sender_web_config.send_string(json.dumps(kwargs))
603 sender_web_config.send_string(json.dumps(kwargs))
501 self.isWebConfig = True
604 self.isWebConfig = True No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now