##// END OF EJS Templates
Fix all PlotData, add SpectraMean, CrossSpectra plots, now Parameters extends Spectra fix bugs in ParametersProc
jespinoza -
r922:d680543828ae
parent child
Show More
@@ -1,1216 +1,1218
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 __init__(self):
117 def __init__(self):
118
118
119 raise NotImplementedError
119 raise NotImplementedError
120
120
121 def copy(self, inputObj=None):
121 def copy(self, inputObj=None):
122
122
123 if inputObj == None:
123 if inputObj == None:
124 return copy.deepcopy(self)
124 return copy.deepcopy(self)
125
125
126 for key in inputObj.__dict__.keys():
126 for key in inputObj.__dict__.keys():
127
127
128 attribute = inputObj.__dict__[key]
128 attribute = inputObj.__dict__[key]
129
129
130 #If this attribute is a tuple or list
130 #If this attribute is a tuple or list
131 if type(inputObj.__dict__[key]) in (tuple, list):
131 if type(inputObj.__dict__[key]) in (tuple, list):
132 self.__dict__[key] = attribute[:]
132 self.__dict__[key] = attribute[:]
133 continue
133 continue
134
134
135 #If this attribute is another object or instance
135 #If this attribute is another object or instance
136 if hasattr(attribute, '__dict__'):
136 if hasattr(attribute, '__dict__'):
137 self.__dict__[key] = attribute.copy()
137 self.__dict__[key] = attribute.copy()
138 continue
138 continue
139
139
140 self.__dict__[key] = inputObj.__dict__[key]
140 self.__dict__[key] = inputObj.__dict__[key]
141
141
142 def deepcopy(self):
142 def deepcopy(self):
143
143
144 return copy.deepcopy(self)
144 return copy.deepcopy(self)
145
145
146 def isEmpty(self):
146 def isEmpty(self):
147
147
148 return self.flagNoData
148 return self.flagNoData
149
149
150 class JROData(GenericData):
150 class JROData(GenericData):
151
151
152 # m_BasicHeader = BasicHeader()
152 # m_BasicHeader = BasicHeader()
153 # m_ProcessingHeader = ProcessingHeader()
153 # m_ProcessingHeader = ProcessingHeader()
154
154
155 systemHeaderObj = SystemHeader()
155 systemHeaderObj = SystemHeader()
156
156
157 radarControllerHeaderObj = RadarControllerHeader()
157 radarControllerHeaderObj = RadarControllerHeader()
158
158
159 # data = None
159 # data = None
160
160
161 type = None
161 type = None
162
162
163 datatype = None #dtype but in string
163 datatype = None #dtype but in string
164
164
165 # dtype = None
165 # dtype = None
166
166
167 # nChannels = None
167 # nChannels = None
168
168
169 # nHeights = None
169 # nHeights = None
170
170
171 nProfiles = None
171 nProfiles = None
172
172
173 heightList = None
173 heightList = None
174
174
175 channelList = None
175 channelList = None
176
176
177 flagDiscontinuousBlock = False
177 flagDiscontinuousBlock = False
178
178
179 useLocalTime = False
179 useLocalTime = False
180
180
181 utctime = None
181 utctime = None
182
182
183 timeZone = None
183 timeZone = None
184
184
185 dstFlag = None
185 dstFlag = None
186
186
187 errorCount = None
187 errorCount = None
188
188
189 blocksize = None
189 blocksize = None
190
190
191 # nCode = None
191 # nCode = None
192 #
192 #
193 # nBaud = None
193 # nBaud = None
194 #
194 #
195 # code = None
195 # code = None
196
196
197 flagDecodeData = False #asumo q la data no esta decodificada
197 flagDecodeData = False #asumo q la data no esta decodificada
198
198
199 flagDeflipData = False #asumo q la data no esta sin flip
199 flagDeflipData = False #asumo q la data no esta sin flip
200
200
201 flagShiftFFT = False
201 flagShiftFFT = False
202
202
203 # ippSeconds = None
203 # ippSeconds = None
204
204
205 # timeInterval = None
205 # timeInterval = None
206
206
207 nCohInt = None
207 nCohInt = None
208
208
209 # noise = None
209 # noise = None
210
210
211 windowOfFilter = 1
211 windowOfFilter = 1
212
212
213 #Speed of ligth
213 #Speed of ligth
214 C = 3e8
214 C = 3e8
215
215
216 frequency = 49.92e6
216 frequency = 49.92e6
217
217
218 realtime = False
218 realtime = False
219
219
220 beacon_heiIndexList = None
220 beacon_heiIndexList = None
221
221
222 last_block = None
222 last_block = None
223
223
224 blocknow = None
224 blocknow = None
225
225
226 azimuth = None
226 azimuth = None
227
227
228 zenith = None
228 zenith = None
229
229
230 beam = Beam()
230 beam = Beam()
231
231
232 profileIndex = None
232 profileIndex = None
233
233
234 def __init__(self):
234 def __init__(self):
235
235
236 raise NotImplementedError
236 raise NotImplementedError
237
237
238 def getNoise(self):
238 def getNoise(self):
239
239
240 raise NotImplementedError
240 raise NotImplementedError
241
241
242 def getNChannels(self):
242 def getNChannels(self):
243
243
244 return len(self.channelList)
244 return len(self.channelList)
245
245
246 def getChannelIndexList(self):
246 def getChannelIndexList(self):
247
247
248 return range(self.nChannels)
248 return range(self.nChannels)
249
249
250 def getNHeights(self):
250 def getNHeights(self):
251
251
252 return len(self.heightList)
252 return len(self.heightList)
253
253
254 def getHeiRange(self, extrapoints=0):
254 def getHeiRange(self, extrapoints=0):
255
255
256 heis = self.heightList
256 heis = self.heightList
257 # deltah = self.heightList[1] - self.heightList[0]
257 # deltah = self.heightList[1] - self.heightList[0]
258 #
258 #
259 # heis.append(self.heightList[-1])
259 # heis.append(self.heightList[-1])
260
260
261 return heis
261 return heis
262
262
263 def getDeltaH(self):
263 def getDeltaH(self):
264
264
265 delta = self.heightList[1] - self.heightList[0]
265 delta = self.heightList[1] - self.heightList[0]
266
266
267 return delta
267 return delta
268
268
269 def getltctime(self):
269 def getltctime(self):
270
270
271 if self.useLocalTime:
271 if self.useLocalTime:
272 return self.utctime - self.timeZone*60
272 return self.utctime - self.timeZone*60
273
273
274 return self.utctime
274 return self.utctime
275
275
276 def getDatatime(self):
276 def getDatatime(self):
277
277
278 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
278 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
279 return datatimeValue
279 return datatimeValue
280
280
281 def getTimeRange(self):
281 def getTimeRange(self):
282
282
283 datatime = []
283 datatime = []
284
284
285 datatime.append(self.ltctime)
285 datatime.append(self.ltctime)
286 datatime.append(self.ltctime + self.timeInterval+1)
286 datatime.append(self.ltctime + self.timeInterval+1)
287
287
288 datatime = numpy.array(datatime)
288 datatime = numpy.array(datatime)
289
289
290 return datatime
290 return datatime
291
291
292 def getFmaxTimeResponse(self):
292 def getFmaxTimeResponse(self):
293
293
294 period = (10**-6)*self.getDeltaH()/(0.15)
294 period = (10**-6)*self.getDeltaH()/(0.15)
295
295
296 PRF = 1./(period * self.nCohInt)
296 PRF = 1./(period * self.nCohInt)
297
297
298 fmax = PRF
298 fmax = PRF
299
299
300 return fmax
300 return fmax
301
301
302 def getFmax(self):
302 def getFmax(self):
303
303
304 PRF = 1./(self.ippSeconds * self.nCohInt)
304 PRF = 1./(self.ippSeconds * self.nCohInt)
305
305
306 fmax = PRF
306 fmax = PRF
307
307
308 return fmax
308 return fmax
309
309
310 def getVmax(self):
310 def getVmax(self):
311
311
312 _lambda = self.C/self.frequency
312 _lambda = self.C/self.frequency
313
313
314 vmax = self.getFmax() * _lambda/2
314 vmax = self.getFmax() * _lambda/2
315
315
316 return vmax
316 return vmax
317
317
318 def get_ippSeconds(self):
318 def get_ippSeconds(self):
319 '''
319 '''
320 '''
320 '''
321 return self.radarControllerHeaderObj.ippSeconds
321 return self.radarControllerHeaderObj.ippSeconds
322
322
323 def set_ippSeconds(self, ippSeconds):
323 def set_ippSeconds(self, ippSeconds):
324 '''
324 '''
325 '''
325 '''
326
326
327 self.radarControllerHeaderObj.ippSeconds = ippSeconds
327 self.radarControllerHeaderObj.ippSeconds = ippSeconds
328
328
329 return
329 return
330
330
331 def get_dtype(self):
331 def get_dtype(self):
332 '''
332 '''
333 '''
333 '''
334 return getNumpyDtype(self.datatype)
334 return getNumpyDtype(self.datatype)
335
335
336 def set_dtype(self, numpyDtype):
336 def set_dtype(self, numpyDtype):
337 '''
337 '''
338 '''
338 '''
339
339
340 self.datatype = getDataTypeCode(numpyDtype)
340 self.datatype = getDataTypeCode(numpyDtype)
341
341
342 def get_code(self):
342 def get_code(self):
343 '''
343 '''
344 '''
344 '''
345 return self.radarControllerHeaderObj.code
345 return self.radarControllerHeaderObj.code
346
346
347 def set_code(self, code):
347 def set_code(self, code):
348 '''
348 '''
349 '''
349 '''
350 self.radarControllerHeaderObj.code = code
350 self.radarControllerHeaderObj.code = code
351
351
352 return
352 return
353
353
354 def get_ncode(self):
354 def get_ncode(self):
355 '''
355 '''
356 '''
356 '''
357 return self.radarControllerHeaderObj.nCode
357 return self.radarControllerHeaderObj.nCode
358
358
359 def set_ncode(self, nCode):
359 def set_ncode(self, nCode):
360 '''
360 '''
361 '''
361 '''
362 self.radarControllerHeaderObj.nCode = nCode
362 self.radarControllerHeaderObj.nCode = nCode
363
363
364 return
364 return
365
365
366 def get_nbaud(self):
366 def get_nbaud(self):
367 '''
367 '''
368 '''
368 '''
369 return self.radarControllerHeaderObj.nBaud
369 return self.radarControllerHeaderObj.nBaud
370
370
371 def set_nbaud(self, nBaud):
371 def set_nbaud(self, nBaud):
372 '''
372 '''
373 '''
373 '''
374 self.radarControllerHeaderObj.nBaud = nBaud
374 self.radarControllerHeaderObj.nBaud = nBaud
375
375
376 return
376 return
377
377
378 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
378 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
379 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
379 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
380 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
380 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
381 #noise = property(getNoise, "I'm the 'nHeights' property.")
381 #noise = property(getNoise, "I'm the 'nHeights' property.")
382 datatime = property(getDatatime, "I'm the 'datatime' property")
382 datatime = property(getDatatime, "I'm the 'datatime' property")
383 ltctime = property(getltctime, "I'm the 'ltctime' property")
383 ltctime = property(getltctime, "I'm the 'ltctime' property")
384 ippSeconds = property(get_ippSeconds, set_ippSeconds)
384 ippSeconds = property(get_ippSeconds, set_ippSeconds)
385 dtype = property(get_dtype, set_dtype)
385 dtype = property(get_dtype, set_dtype)
386 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
386 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
387 code = property(get_code, set_code)
387 code = property(get_code, set_code)
388 nCode = property(get_ncode, set_ncode)
388 nCode = property(get_ncode, set_ncode)
389 nBaud = property(get_nbaud, set_nbaud)
389 nBaud = property(get_nbaud, set_nbaud)
390
390
391 class Voltage(JROData):
391 class Voltage(JROData):
392
392
393 #data es un numpy array de 2 dmensiones (canales, alturas)
393 #data es un numpy array de 2 dmensiones (canales, alturas)
394 data = None
394 data = None
395
395
396 def __init__(self):
396 def __init__(self):
397 '''
397 '''
398 Constructor
398 Constructor
399 '''
399 '''
400
400
401 self.useLocalTime = True
401 self.useLocalTime = True
402
402
403 self.radarControllerHeaderObj = RadarControllerHeader()
403 self.radarControllerHeaderObj = RadarControllerHeader()
404
404
405 self.systemHeaderObj = SystemHeader()
405 self.systemHeaderObj = SystemHeader()
406
406
407 self.type = "Voltage"
407 self.type = "Voltage"
408
408
409 self.data = None
409 self.data = None
410
410
411 # self.dtype = None
411 # self.dtype = None
412
412
413 # self.nChannels = 0
413 # self.nChannels = 0
414
414
415 # self.nHeights = 0
415 # self.nHeights = 0
416
416
417 self.nProfiles = None
417 self.nProfiles = None
418
418
419 self.heightList = None
419 self.heightList = None
420
420
421 self.channelList = None
421 self.channelList = None
422
422
423 # self.channelIndexList = None
423 # self.channelIndexList = None
424
424
425 self.flagNoData = True
425 self.flagNoData = True
426
426
427 self.flagDiscontinuousBlock = False
427 self.flagDiscontinuousBlock = False
428
428
429 self.utctime = None
429 self.utctime = None
430
430
431 self.timeZone = None
431 self.timeZone = None
432
432
433 self.dstFlag = None
433 self.dstFlag = None
434
434
435 self.errorCount = None
435 self.errorCount = None
436
436
437 self.nCohInt = None
437 self.nCohInt = None
438
438
439 self.blocksize = None
439 self.blocksize = None
440
440
441 self.flagDecodeData = False #asumo q la data no esta decodificada
441 self.flagDecodeData = False #asumo q la data no esta decodificada
442
442
443 self.flagDeflipData = False #asumo q la data no esta sin flip
443 self.flagDeflipData = False #asumo q la data no esta sin flip
444
444
445 self.flagShiftFFT = False
445 self.flagShiftFFT = False
446
446
447 self.flagDataAsBlock = False #Asumo que la data es leida perfil a perfil
447 self.flagDataAsBlock = False #Asumo que la data es leida perfil a perfil
448
448
449 self.profileIndex = 0
449 self.profileIndex = 0
450
450
451 def getNoisebyHildebrand(self, channel = None):
451 def getNoisebyHildebrand(self, channel = None):
452 """
452 """
453 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
453 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
454
454
455 Return:
455 Return:
456 noiselevel
456 noiselevel
457 """
457 """
458
458
459 if channel != None:
459 if channel != None:
460 data = self.data[channel]
460 data = self.data[channel]
461 nChannels = 1
461 nChannels = 1
462 else:
462 else:
463 data = self.data
463 data = self.data
464 nChannels = self.nChannels
464 nChannels = self.nChannels
465
465
466 noise = numpy.zeros(nChannels)
466 noise = numpy.zeros(nChannels)
467 power = data * numpy.conjugate(data)
467 power = data * numpy.conjugate(data)
468
468
469 for thisChannel in range(nChannels):
469 for thisChannel in range(nChannels):
470 if nChannels == 1:
470 if nChannels == 1:
471 daux = power[:].real
471 daux = power[:].real
472 else:
472 else:
473 daux = power[thisChannel,:].real
473 daux = power[thisChannel,:].real
474 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
474 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
475
475
476 return noise
476 return noise
477
477
478 def getNoise(self, type = 1, channel = None):
478 def getNoise(self, type = 1, channel = None):
479
479
480 if type == 1:
480 if type == 1:
481 noise = self.getNoisebyHildebrand(channel)
481 noise = self.getNoisebyHildebrand(channel)
482
482
483 return noise
483 return noise
484
484
485 def getPower(self, channel = None):
485 def getPower(self, channel = None):
486
486
487 if channel != None:
487 if channel != None:
488 data = self.data[channel]
488 data = self.data[channel]
489 else:
489 else:
490 data = self.data
490 data = self.data
491
491
492 power = data * numpy.conjugate(data)
492 power = data * numpy.conjugate(data)
493 powerdB = 10*numpy.log10(power.real)
493 powerdB = 10*numpy.log10(power.real)
494 powerdB = numpy.squeeze(powerdB)
494 powerdB = numpy.squeeze(powerdB)
495
495
496 return powerdB
496 return powerdB
497
497
498 def getTimeInterval(self):
498 def getTimeInterval(self):
499
499
500 timeInterval = self.ippSeconds * self.nCohInt
500 timeInterval = self.ippSeconds * self.nCohInt
501
501
502 return timeInterval
502 return timeInterval
503
503
504 noise = property(getNoise, "I'm the 'nHeights' property.")
504 noise = property(getNoise, "I'm the 'nHeights' property.")
505 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
505 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
506
506
507 class Spectra(JROData):
507 class Spectra(JROData):
508
508
509 #data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
509 #data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
510 data_spc = None
510 data_spc = None
511
511
512 #data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
512 #data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
513 data_cspc = None
513 data_cspc = None
514
514
515 #data dc es un numpy array de 2 dmensiones (canales, alturas)
515 #data dc es un numpy array de 2 dmensiones (canales, alturas)
516 data_dc = None
516 data_dc = None
517
517
518 #data power
518 #data power
519 data_pwr = None
519 data_pwr = None
520
520
521 nFFTPoints = None
521 nFFTPoints = None
522
522
523 # nPairs = None
523 # nPairs = None
524
524
525 pairsList = None
525 pairsList = None
526
526
527 nIncohInt = None
527 nIncohInt = None
528
528
529 wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia
529 wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia
530
530
531 nCohInt = None #se requiere para determinar el valor de timeInterval
531 nCohInt = None #se requiere para determinar el valor de timeInterval
532
532
533 ippFactor = None
533 ippFactor = None
534
534
535 profileIndex = 0
535 profileIndex = 0
536
536
537 plotting = "spectra"
537 plotting = "spectra"
538
538
539 def __init__(self):
539 def __init__(self):
540 '''
540 '''
541 Constructor
541 Constructor
542 '''
542 '''
543
543
544 self.useLocalTime = True
544 self.useLocalTime = True
545
545
546 self.radarControllerHeaderObj = RadarControllerHeader()
546 self.radarControllerHeaderObj = RadarControllerHeader()
547
547
548 self.systemHeaderObj = SystemHeader()
548 self.systemHeaderObj = SystemHeader()
549
549
550 self.type = "Spectra"
550 self.type = "Spectra"
551
551
552 # self.data = None
552 # self.data = None
553
553
554 # self.dtype = None
554 # self.dtype = None
555
555
556 # self.nChannels = 0
556 # self.nChannels = 0
557
557
558 # self.nHeights = 0
558 # self.nHeights = 0
559
559
560 self.nProfiles = None
560 self.nProfiles = None
561
561
562 self.heightList = None
562 self.heightList = None
563
563
564 self.channelList = None
564 self.channelList = None
565
565
566 # self.channelIndexList = None
566 # self.channelIndexList = None
567
567
568 self.pairsList = None
568 self.pairsList = None
569
569
570 self.flagNoData = True
570 self.flagNoData = True
571
571
572 self.flagDiscontinuousBlock = False
572 self.flagDiscontinuousBlock = False
573
573
574 self.utctime = None
574 self.utctime = None
575
575
576 self.nCohInt = None
576 self.nCohInt = None
577
577
578 self.nIncohInt = None
578 self.nIncohInt = None
579
579
580 self.blocksize = None
580 self.blocksize = None
581
581
582 self.nFFTPoints = None
582 self.nFFTPoints = None
583
583
584 self.wavelength = None
584 self.wavelength = None
585
585
586 self.flagDecodeData = False #asumo q la data no esta decodificada
586 self.flagDecodeData = False #asumo q la data no esta decodificada
587
587
588 self.flagDeflipData = False #asumo q la data no esta sin flip
588 self.flagDeflipData = False #asumo q la data no esta sin flip
589
589
590 self.flagShiftFFT = False
590 self.flagShiftFFT = False
591
591
592 self.ippFactor = 1
592 self.ippFactor = 1
593
593
594 #self.noise = None
594 #self.noise = None
595
595
596 self.beacon_heiIndexList = []
596 self.beacon_heiIndexList = []
597
597
598 self.noise_estimation = None
598 self.noise_estimation = None
599
599
600
600
601 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
601 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
602 """
602 """
603 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
603 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
604
604
605 Return:
605 Return:
606 noiselevel
606 noiselevel
607 """
607 """
608
608
609 noise = numpy.zeros(self.nChannels)
609 noise = numpy.zeros(self.nChannels)
610
610
611 for channel in range(self.nChannels):
611 for channel in range(self.nChannels):
612 daux = self.data_spc[channel,xmin_index:xmax_index,ymin_index:ymax_index]
612 daux = self.data_spc[channel,xmin_index:xmax_index,ymin_index:ymax_index]
613 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
613 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
614
614
615 return noise
615 return noise
616
616
617 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
617 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
618
618
619 if self.noise_estimation is not None:
619 if self.noise_estimation is not None:
620 return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py
620 return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py
621 else:
621 else:
622 noise = self.getNoisebyHildebrand(xmin_index, xmax_index, ymin_index, ymax_index)
622 noise = self.getNoisebyHildebrand(xmin_index, xmax_index, ymin_index, ymax_index)
623 return noise
623 return noise
624
624
625 def getFreqRangeTimeResponse(self, extrapoints=0):
625 def getFreqRangeTimeResponse(self, extrapoints=0):
626
626
627 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints*self.ippFactor)
627 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints*self.ippFactor)
628 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
628 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
629
629
630 return freqrange
630 return freqrange
631
631
632 def getAcfRange(self, extrapoints=0):
632 def getAcfRange(self, extrapoints=0):
633
633
634 deltafreq = 10./(self.getFmax() / (self.nFFTPoints*self.ippFactor))
634 deltafreq = 10./(self.getFmax() / (self.nFFTPoints*self.ippFactor))
635 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
635 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
636
636
637 return freqrange
637 return freqrange
638
638
639 def getFreqRange(self, extrapoints=0):
639 def getFreqRange(self, extrapoints=0):
640
640
641 deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor)
641 deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor)
642 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
642 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
643
643
644 return freqrange
644 return freqrange
645
645
646 def getVelRange(self, extrapoints=0):
646 def getVelRange(self, extrapoints=0):
647
647
648 deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor)
648 deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor)
649 velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) #- deltav/2
649 velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) #- deltav/2
650
650
651 return velrange
651 return velrange
652
652
653 def getNPairs(self):
653 def getNPairs(self):
654
654
655 return len(self.pairsList)
655 return len(self.pairsList)
656
656
657 def getPairsIndexList(self):
657 def getPairsIndexList(self):
658
658
659 return range(self.nPairs)
659 return range(self.nPairs)
660
660
661 def getNormFactor(self):
661 def getNormFactor(self):
662
662
663 pwcode = 1
663 pwcode = 1
664
664
665 if self.flagDecodeData:
665 if self.flagDecodeData:
666 pwcode = numpy.sum(self.code[0]**2)
666 pwcode = numpy.sum(self.code[0]**2)
667 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
667 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
668 normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
668 normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
669
669
670 return normFactor
670 return normFactor
671
671
672 def getFlagCspc(self):
672 def getFlagCspc(self):
673
673
674 if self.data_cspc is None:
674 if self.data_cspc is None:
675 return True
675 return True
676
676
677 return False
677 return False
678
678
679 def getFlagDc(self):
679 def getFlagDc(self):
680
680
681 if self.data_dc is None:
681 if self.data_dc is None:
682 return True
682 return True
683
683
684 return False
684 return False
685
685
686 def getTimeInterval(self):
686 def getTimeInterval(self):
687
687
688 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles
688 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles
689
689
690 return timeInterval
690 return timeInterval
691
691
692 def getPower(self):
692 def getPower(self):
693
693
694 factor = self.normFactor
694 factor = self.normFactor
695 z = self.data_spc/factor
695 z = self.data_spc/factor
696 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
696 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
697 avg = numpy.average(z, axis=1)
697 avg = numpy.average(z, axis=1)
698
698
699 return 10*numpy.log10(avg)
699 return 10*numpy.log10(avg)
700
700
701 def getCoherence(self, pairsList=None, phase=False):
701 def getCoherence(self, pairsList=None, phase=False):
702
702
703 z = []
703 z = []
704 if pairsList is None:
704 if pairsList is None:
705 pairsIndexList = self.pairsIndexList
705 pairsIndexList = self.pairsIndexList
706 else:
706 else:
707 pairsIndexList = []
707 pairsIndexList = []
708 for pair in pairsList:
708 for pair in pairsList:
709 if pair not in self.pairsList:
709 if pair not in self.pairsList:
710 raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair)
710 raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair)
711 pairsIndexList.append(self.pairsList.index(pair))
711 pairsIndexList.append(self.pairsList.index(pair))
712 for i in range(len(pairsIndexList)):
712 for i in range(len(pairsIndexList)):
713 pair = self.pairsList[pairsIndexList[i]]
713 pair = self.pairsList[pairsIndexList[i]]
714 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
714 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
715 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
715 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
716 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
716 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
717 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
717 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
718 if phase:
718 if phase:
719 data = numpy.arctan2(avgcoherenceComplex.imag,
719 data = numpy.arctan2(avgcoherenceComplex.imag,
720 avgcoherenceComplex.real)*180/numpy.pi
720 avgcoherenceComplex.real)*180/numpy.pi
721 else:
721 else:
722 data = numpy.abs(avgcoherenceComplex)
722 data = numpy.abs(avgcoherenceComplex)
723
723
724 z.append(data)
724 z.append(data)
725
725
726 return numpy.array(z)
726 return numpy.array(z)
727
727
728 def setValue(self, value):
728 def setValue(self, value):
729
729
730 print "This property should not be initialized"
730 print "This property should not be initialized"
731
731
732 return
732 return
733
733
734 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
734 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
735 pairsIndexList = property(getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
735 pairsIndexList = property(getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
736 normFactor = property(getNormFactor, setValue, "I'm the 'getNormFactor' property.")
736 normFactor = property(getNormFactor, setValue, "I'm the 'getNormFactor' property.")
737 flag_cspc = property(getFlagCspc, setValue)
737 flag_cspc = property(getFlagCspc, setValue)
738 flag_dc = property(getFlagDc, setValue)
738 flag_dc = property(getFlagDc, setValue)
739 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
739 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
740 timeInterval = property(getTimeInterval, setValue, "I'm the 'timeInterval' property")
740 timeInterval = property(getTimeInterval, setValue, "I'm the 'timeInterval' property")
741
741
742 class SpectraHeis(Spectra):
742 class SpectraHeis(Spectra):
743
743
744 data_spc = None
744 data_spc = None
745
745
746 data_cspc = None
746 data_cspc = None
747
747
748 data_dc = None
748 data_dc = None
749
749
750 nFFTPoints = None
750 nFFTPoints = None
751
751
752 # nPairs = None
752 # nPairs = None
753
753
754 pairsList = None
754 pairsList = None
755
755
756 nCohInt = None
756 nCohInt = None
757
757
758 nIncohInt = None
758 nIncohInt = None
759
759
760 def __init__(self):
760 def __init__(self):
761
761
762 self.radarControllerHeaderObj = RadarControllerHeader()
762 self.radarControllerHeaderObj = RadarControllerHeader()
763
763
764 self.systemHeaderObj = SystemHeader()
764 self.systemHeaderObj = SystemHeader()
765
765
766 self.type = "SpectraHeis"
766 self.type = "SpectraHeis"
767
767
768 # self.dtype = None
768 # self.dtype = None
769
769
770 # self.nChannels = 0
770 # self.nChannels = 0
771
771
772 # self.nHeights = 0
772 # self.nHeights = 0
773
773
774 self.nProfiles = None
774 self.nProfiles = None
775
775
776 self.heightList = None
776 self.heightList = None
777
777
778 self.channelList = None
778 self.channelList = None
779
779
780 # self.channelIndexList = None
780 # self.channelIndexList = None
781
781
782 self.flagNoData = True
782 self.flagNoData = True
783
783
784 self.flagDiscontinuousBlock = False
784 self.flagDiscontinuousBlock = False
785
785
786 # self.nPairs = 0
786 # self.nPairs = 0
787
787
788 self.utctime = None
788 self.utctime = None
789
789
790 self.blocksize = None
790 self.blocksize = None
791
791
792 self.profileIndex = 0
792 self.profileIndex = 0
793
793
794 self.nCohInt = 1
794 self.nCohInt = 1
795
795
796 self.nIncohInt = 1
796 self.nIncohInt = 1
797
797
798 def getNormFactor(self):
798 def getNormFactor(self):
799 pwcode = 1
799 pwcode = 1
800 if self.flagDecodeData:
800 if self.flagDecodeData:
801 pwcode = numpy.sum(self.code[0]**2)
801 pwcode = numpy.sum(self.code[0]**2)
802
802
803 normFactor = self.nIncohInt*self.nCohInt*pwcode
803 normFactor = self.nIncohInt*self.nCohInt*pwcode
804
804
805 return normFactor
805 return normFactor
806
806
807 def getTimeInterval(self):
807 def getTimeInterval(self):
808
808
809 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
809 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
810
810
811 return timeInterval
811 return timeInterval
812
812
813 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
813 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
814 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
814 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
815
815
816 class Fits(JROData):
816 class Fits(JROData):
817
817
818 heightList = None
818 heightList = None
819
819
820 channelList = None
820 channelList = None
821
821
822 flagNoData = True
822 flagNoData = True
823
823
824 flagDiscontinuousBlock = False
824 flagDiscontinuousBlock = False
825
825
826 useLocalTime = False
826 useLocalTime = False
827
827
828 utctime = None
828 utctime = None
829
829
830 timeZone = None
830 timeZone = None
831
831
832 # ippSeconds = None
832 # ippSeconds = None
833
833
834 # timeInterval = None
834 # timeInterval = None
835
835
836 nCohInt = None
836 nCohInt = None
837
837
838 nIncohInt = None
838 nIncohInt = None
839
839
840 noise = None
840 noise = None
841
841
842 windowOfFilter = 1
842 windowOfFilter = 1
843
843
844 #Speed of ligth
844 #Speed of ligth
845 C = 3e8
845 C = 3e8
846
846
847 frequency = 49.92e6
847 frequency = 49.92e6
848
848
849 realtime = False
849 realtime = False
850
850
851
851
852 def __init__(self):
852 def __init__(self):
853
853
854 self.type = "Fits"
854 self.type = "Fits"
855
855
856 self.nProfiles = None
856 self.nProfiles = None
857
857
858 self.heightList = None
858 self.heightList = None
859
859
860 self.channelList = None
860 self.channelList = None
861
861
862 # self.channelIndexList = None
862 # self.channelIndexList = None
863
863
864 self.flagNoData = True
864 self.flagNoData = True
865
865
866 self.utctime = None
866 self.utctime = None
867
867
868 self.nCohInt = 1
868 self.nCohInt = 1
869
869
870 self.nIncohInt = 1
870 self.nIncohInt = 1
871
871
872 self.useLocalTime = True
872 self.useLocalTime = True
873
873
874 self.profileIndex = 0
874 self.profileIndex = 0
875
875
876 # self.utctime = None
876 # self.utctime = None
877 # self.timeZone = None
877 # self.timeZone = None
878 # self.ltctime = None
878 # self.ltctime = None
879 # self.timeInterval = None
879 # self.timeInterval = None
880 # self.header = None
880 # self.header = None
881 # self.data_header = None
881 # self.data_header = None
882 # self.data = None
882 # self.data = None
883 # self.datatime = None
883 # self.datatime = None
884 # self.flagNoData = False
884 # self.flagNoData = False
885 # self.expName = ''
885 # self.expName = ''
886 # self.nChannels = None
886 # self.nChannels = None
887 # self.nSamples = None
887 # self.nSamples = None
888 # self.dataBlocksPerFile = None
888 # self.dataBlocksPerFile = None
889 # self.comments = ''
889 # self.comments = ''
890 #
890 #
891
891
892
892
893 def getltctime(self):
893 def getltctime(self):
894
894
895 if self.useLocalTime:
895 if self.useLocalTime:
896 return self.utctime - self.timeZone*60
896 return self.utctime - self.timeZone*60
897
897
898 return self.utctime
898 return self.utctime
899
899
900 def getDatatime(self):
900 def getDatatime(self):
901
901
902 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
902 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
903 return datatime
903 return datatime
904
904
905 def getTimeRange(self):
905 def getTimeRange(self):
906
906
907 datatime = []
907 datatime = []
908
908
909 datatime.append(self.ltctime)
909 datatime.append(self.ltctime)
910 datatime.append(self.ltctime + self.timeInterval)
910 datatime.append(self.ltctime + self.timeInterval)
911
911
912 datatime = numpy.array(datatime)
912 datatime = numpy.array(datatime)
913
913
914 return datatime
914 return datatime
915
915
916 def getHeiRange(self):
916 def getHeiRange(self):
917
917
918 heis = self.heightList
918 heis = self.heightList
919
919
920 return heis
920 return heis
921
921
922 def getNHeights(self):
922 def getNHeights(self):
923
923
924 return len(self.heightList)
924 return len(self.heightList)
925
925
926 def getNChannels(self):
926 def getNChannels(self):
927
927
928 return len(self.channelList)
928 return len(self.channelList)
929
929
930 def getChannelIndexList(self):
930 def getChannelIndexList(self):
931
931
932 return range(self.nChannels)
932 return range(self.nChannels)
933
933
934 def getNoise(self, type = 1):
934 def getNoise(self, type = 1):
935
935
936 #noise = numpy.zeros(self.nChannels)
936 #noise = numpy.zeros(self.nChannels)
937
937
938 if type == 1:
938 if type == 1:
939 noise = self.getNoisebyHildebrand()
939 noise = self.getNoisebyHildebrand()
940
940
941 if type == 2:
941 if type == 2:
942 noise = self.getNoisebySort()
942 noise = self.getNoisebySort()
943
943
944 if type == 3:
944 if type == 3:
945 noise = self.getNoisebyWindow()
945 noise = self.getNoisebyWindow()
946
946
947 return noise
947 return noise
948
948
949 def getTimeInterval(self):
949 def getTimeInterval(self):
950
950
951 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
951 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
952
952
953 return timeInterval
953 return timeInterval
954
954
955 datatime = property(getDatatime, "I'm the 'datatime' property")
955 datatime = property(getDatatime, "I'm the 'datatime' property")
956 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
956 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
957 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
957 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
958 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
958 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
959 noise = property(getNoise, "I'm the 'nHeights' property.")
959 noise = property(getNoise, "I'm the 'nHeights' property.")
960
960
961 ltctime = property(getltctime, "I'm the 'ltctime' property")
961 ltctime = property(getltctime, "I'm the 'ltctime' property")
962 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
962 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
963
963
964
964
965 class Correlation(JROData):
965 class Correlation(JROData):
966
966
967 noise = None
967 noise = None
968
968
969 SNR = None
969 SNR = None
970
970
971 #--------------------------------------------------
971 #--------------------------------------------------
972
972
973 mode = None
973 mode = None
974
974
975 split = False
975 split = False
976
976
977 data_cf = None
977 data_cf = None
978
978
979 lags = None
979 lags = None
980
980
981 lagRange = None
981 lagRange = None
982
982
983 pairsList = None
983 pairsList = None
984
984
985 normFactor = None
985 normFactor = None
986
986
987 #--------------------------------------------------
987 #--------------------------------------------------
988
988
989 # calculateVelocity = None
989 # calculateVelocity = None
990
990
991 nLags = None
991 nLags = None
992
992
993 nPairs = None
993 nPairs = None
994
994
995 nAvg = None
995 nAvg = None
996
996
997
997
998 def __init__(self):
998 def __init__(self):
999 '''
999 '''
1000 Constructor
1000 Constructor
1001 '''
1001 '''
1002 self.radarControllerHeaderObj = RadarControllerHeader()
1002 self.radarControllerHeaderObj = RadarControllerHeader()
1003
1003
1004 self.systemHeaderObj = SystemHeader()
1004 self.systemHeaderObj = SystemHeader()
1005
1005
1006 self.type = "Correlation"
1006 self.type = "Correlation"
1007
1007
1008 self.data = None
1008 self.data = None
1009
1009
1010 self.dtype = None
1010 self.dtype = None
1011
1011
1012 self.nProfiles = None
1012 self.nProfiles = None
1013
1013
1014 self.heightList = None
1014 self.heightList = None
1015
1015
1016 self.channelList = None
1016 self.channelList = None
1017
1017
1018 self.flagNoData = True
1018 self.flagNoData = True
1019
1019
1020 self.flagDiscontinuousBlock = False
1020 self.flagDiscontinuousBlock = False
1021
1021
1022 self.utctime = None
1022 self.utctime = None
1023
1023
1024 self.timeZone = None
1024 self.timeZone = None
1025
1025
1026 self.dstFlag = None
1026 self.dstFlag = None
1027
1027
1028 self.errorCount = None
1028 self.errorCount = None
1029
1029
1030 self.blocksize = None
1030 self.blocksize = None
1031
1031
1032 self.flagDecodeData = False #asumo q la data no esta decodificada
1032 self.flagDecodeData = False #asumo q la data no esta decodificada
1033
1033
1034 self.flagDeflipData = False #asumo q la data no esta sin flip
1034 self.flagDeflipData = False #asumo q la data no esta sin flip
1035
1035
1036 self.pairsList = None
1036 self.pairsList = None
1037
1037
1038 self.nPoints = None
1038 self.nPoints = None
1039
1039
1040 def getPairsList(self):
1040 def getPairsList(self):
1041
1041
1042 return self.pairsList
1042 return self.pairsList
1043
1043
1044 def getNoise(self, mode = 2):
1044 def getNoise(self, mode = 2):
1045
1045
1046 indR = numpy.where(self.lagR == 0)[0][0]
1046 indR = numpy.where(self.lagR == 0)[0][0]
1047 indT = numpy.where(self.lagT == 0)[0][0]
1047 indT = numpy.where(self.lagT == 0)[0][0]
1048
1048
1049 jspectra0 = self.data_corr[:,:,indR,:]
1049 jspectra0 = self.data_corr[:,:,indR,:]
1050 jspectra = copy.copy(jspectra0)
1050 jspectra = copy.copy(jspectra0)
1051
1051
1052 num_chan = jspectra.shape[0]
1052 num_chan = jspectra.shape[0]
1053 num_hei = jspectra.shape[2]
1053 num_hei = jspectra.shape[2]
1054
1054
1055 freq_dc = jspectra.shape[1]/2
1055 freq_dc = jspectra.shape[1]/2
1056 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
1056 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
1057
1057
1058 if ind_vel[0]<0:
1058 if ind_vel[0]<0:
1059 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
1059 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
1060
1060
1061 if mode == 1:
1061 if mode == 1:
1062 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
1062 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
1063
1063
1064 if mode == 2:
1064 if mode == 2:
1065
1065
1066 vel = numpy.array([-2,-1,1,2])
1066 vel = numpy.array([-2,-1,1,2])
1067 xx = numpy.zeros([4,4])
1067 xx = numpy.zeros([4,4])
1068
1068
1069 for fil in range(4):
1069 for fil in range(4):
1070 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
1070 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
1071
1071
1072 xx_inv = numpy.linalg.inv(xx)
1072 xx_inv = numpy.linalg.inv(xx)
1073 xx_aux = xx_inv[0,:]
1073 xx_aux = xx_inv[0,:]
1074
1074
1075 for ich in range(num_chan):
1075 for ich in range(num_chan):
1076 yy = jspectra[ich,ind_vel,:]
1076 yy = jspectra[ich,ind_vel,:]
1077 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
1077 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
1078
1078
1079 junkid = jspectra[ich,freq_dc,:]<=0
1079 junkid = jspectra[ich,freq_dc,:]<=0
1080 cjunkid = sum(junkid)
1080 cjunkid = sum(junkid)
1081
1081
1082 if cjunkid.any():
1082 if cjunkid.any():
1083 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
1083 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
1084
1084
1085 noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:]
1085 noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:]
1086
1086
1087 return noise
1087 return noise
1088
1088
1089 def getTimeInterval(self):
1089 def getTimeInterval(self):
1090
1090
1091 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1091 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1092
1092
1093 return timeInterval
1093 return timeInterval
1094
1094
1095 def splitFunctions(self):
1095 def splitFunctions(self):
1096
1096
1097 pairsList = self.pairsList
1097 pairsList = self.pairsList
1098 ccf_pairs = []
1098 ccf_pairs = []
1099 acf_pairs = []
1099 acf_pairs = []
1100 ccf_ind = []
1100 ccf_ind = []
1101 acf_ind = []
1101 acf_ind = []
1102 for l in range(len(pairsList)):
1102 for l in range(len(pairsList)):
1103 chan0 = pairsList[l][0]
1103 chan0 = pairsList[l][0]
1104 chan1 = pairsList[l][1]
1104 chan1 = pairsList[l][1]
1105
1105
1106 #Obteniendo pares de Autocorrelacion
1106 #Obteniendo pares de Autocorrelacion
1107 if chan0 == chan1:
1107 if chan0 == chan1:
1108 acf_pairs.append(chan0)
1108 acf_pairs.append(chan0)
1109 acf_ind.append(l)
1109 acf_ind.append(l)
1110 else:
1110 else:
1111 ccf_pairs.append(pairsList[l])
1111 ccf_pairs.append(pairsList[l])
1112 ccf_ind.append(l)
1112 ccf_ind.append(l)
1113
1113
1114 data_acf = self.data_cf[acf_ind]
1114 data_acf = self.data_cf[acf_ind]
1115 data_ccf = self.data_cf[ccf_ind]
1115 data_ccf = self.data_cf[ccf_ind]
1116
1116
1117 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1117 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1118
1118
1119 def getNormFactor(self):
1119 def getNormFactor(self):
1120 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1120 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1121 acf_pairs = numpy.array(acf_pairs)
1121 acf_pairs = numpy.array(acf_pairs)
1122 normFactor = numpy.zeros((self.nPairs,self.nHeights))
1122 normFactor = numpy.zeros((self.nPairs,self.nHeights))
1123
1123
1124 for p in range(self.nPairs):
1124 for p in range(self.nPairs):
1125 pair = self.pairsList[p]
1125 pair = self.pairsList[p]
1126
1126
1127 ch0 = pair[0]
1127 ch0 = pair[0]
1128 ch1 = pair[1]
1128 ch1 = pair[1]
1129
1129
1130 ch0_max = numpy.max(data_acf[acf_pairs==ch0,:,:], axis=1)
1130 ch0_max = numpy.max(data_acf[acf_pairs==ch0,:,:], axis=1)
1131 ch1_max = numpy.max(data_acf[acf_pairs==ch1,:,:], axis=1)
1131 ch1_max = numpy.max(data_acf[acf_pairs==ch1,:,:], axis=1)
1132 normFactor[p,:] = numpy.sqrt(ch0_max*ch1_max)
1132 normFactor[p,:] = numpy.sqrt(ch0_max*ch1_max)
1133
1133
1134 return normFactor
1134 return normFactor
1135
1135
1136 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1136 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1137 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1137 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1138
1138
1139 class Parameters(JROData):
1139 class Parameters(Spectra):
1140
1140
1141 experimentInfo = None #Information about the experiment
1141 experimentInfo = None #Information about the experiment
1142
1142
1143 #Information from previous data
1143 #Information from previous data
1144
1144
1145 inputUnit = None #Type of data to be processed
1145 inputUnit = None #Type of data to be processed
1146
1146
1147 operation = None #Type of operation to parametrize
1147 operation = None #Type of operation to parametrize
1148
1148
1149 normFactor = None #Normalization Factor
1149 #normFactor = None #Normalization Factor
1150
1150
1151 groupList = None #List of Pairs, Groups, etc
1151 groupList = None #List of Pairs, Groups, etc
1152
1152
1153 #Parameters
1153 #Parameters
1154
1154
1155 data_param = None #Parameters obtained
1155 data_param = None #Parameters obtained
1156
1156
1157 data_pre = None #Data Pre Parametrization
1157 data_pre = None #Data Pre Parametrization
1158
1158
1159 data_SNR = None #Signal to Noise Ratio
1159 data_SNR = None #Signal to Noise Ratio
1160
1160
1161 # heightRange = None #Heights
1161 # heightRange = None #Heights
1162
1162
1163 abscissaList = None #Abscissa, can be velocities, lags or time
1163 abscissaList = None #Abscissa, can be velocities, lags or time
1164
1164
1165 noise = None #Noise Potency
1165 #noise = None #Noise Potency
1166
1166
1167 utctimeInit = None #Initial UTC time
1167 utctimeInit = None #Initial UTC time
1168
1168
1169 paramInterval = None #Time interval to calculate Parameters in seconds
1169 paramInterval = None #Time interval to calculate Parameters in seconds
1170
1170
1171 useLocalTime = True
1171 useLocalTime = True
1172
1172
1173 #Fitting
1173 #Fitting
1174
1174
1175 data_error = None #Error of the estimation
1175 data_error = None #Error of the estimation
1176
1176
1177 constants = None
1177 constants = None
1178
1178
1179 library = None
1179 library = None
1180
1180
1181 #Output signal
1181 #Output signal
1182
1182
1183 outputInterval = None #Time interval to calculate output signal in seconds
1183 outputInterval = None #Time interval to calculate output signal in seconds
1184
1184
1185 data_output = None #Out signal
1185 data_output = None #Out signal
1186
1186
1187 nAvg = None
1187 nAvg = None
1188
1188
1189 noise_estimation = None
1190
1189
1191
1190 def __init__(self):
1192 def __init__(self):
1191 '''
1193 '''
1192 Constructor
1194 Constructor
1193 '''
1195 '''
1194 self.radarControllerHeaderObj = RadarControllerHeader()
1196 self.radarControllerHeaderObj = RadarControllerHeader()
1195
1197
1196 self.systemHeaderObj = SystemHeader()
1198 self.systemHeaderObj = SystemHeader()
1197
1199
1198 self.type = "Parameters"
1200 self.type = "Parameters"
1199
1201
1200 def getTimeRange1(self, interval):
1202 def getTimeRange1(self, interval):
1201
1203
1202 datatime = []
1204 datatime = []
1203
1205
1204 if self.useLocalTime:
1206 if self.useLocalTime:
1205 time1 = self.utctimeInit - self.timeZone*60
1207 time1 = self.utctimeInit - self.timeZone*60
1206 else:
1208 else:
1207 time1 = self.utctimeInit
1209 time1 = self.utctimeInit
1208
1210
1209 # datatime.append(self.utctimeInit)
1211 # datatime.append(self.utctimeInit)
1210 # datatime.append(self.utctimeInit + self.outputInterval)
1212 # datatime.append(self.utctimeInit + self.outputInterval)
1211 datatime.append(time1)
1213 datatime.append(time1)
1212 datatime.append(time1 + interval)
1214 datatime.append(time1 + interval)
1213
1215
1214 datatime = numpy.array(datatime)
1216 datatime = numpy.array(datatime)
1215
1217
1216 return datatime
1218 return datatime
@@ -1,426 +1,604
1
1
2 import os
2 import os
3 import zmq
3 import zmq
4 import time
4 import time
5 import numpy
5 import numpy
6 import datetime
6 import datetime
7 import numpy as np
7 import numpy as np
8 import matplotlib.pyplot as plt
8 import matplotlib.pyplot as plt
9 from mpl_toolkits.axes_grid1 import make_axes_locatable
9 from mpl_toolkits.axes_grid1 import make_axes_locatable
10 from matplotlib.ticker import FuncFormatter, LinearLocator
10 from matplotlib.ticker import FuncFormatter, LinearLocator
11 from multiprocessing import Process
11 from multiprocessing import Process
12
12
13 from schainpy.model.proc.jroproc_base import Operation
13 from schainpy.model.proc.jroproc_base import Operation
14
14
15 #plt.ion()
15 #plt.ion()
16
16
17 func = lambda x, pos: ('%s') %(datetime.datetime.utcfromtimestamp(x).strftime('%H:%M'))
17 func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M'))
18
18
19 d1970 = datetime.datetime(1970,1,1)
19 d1970 = datetime.datetime(1970,1,1)
20
20
21 class PlotData(Operation, Process):
21 class PlotData(Operation, Process):
22
22
23 CODE = 'Figure'
23 CODE = 'Figure'
24 colormap = 'jet'
24 colormap = 'jro'
25 CONFLATE = True
25 CONFLATE = True
26 __MAXNUMX = 80
26 __MAXNUMX = 80
27 __MAXNUMY = 80
27 __MAXNUMY = 80
28 __missing = 1E30
28 __missing = 1E30
29
29
30 def __init__(self, **kwargs):
30 def __init__(self, **kwargs):
31
31
32 Operation.__init__(self, plot=True, **kwargs)
32 Operation.__init__(self, plot=True, **kwargs)
33 Process.__init__(self)
33 Process.__init__(self)
34 self.kwargs['code'] = self.CODE
34 self.kwargs['code'] = self.CODE
35 self.mp = False
35 self.mp = False
36 self.dataOut = None
36 self.dataOut = None
37 self.isConfig = False
37 self.isConfig = False
38 self.figure = None
38 self.figure = None
39 self.axes = []
39 self.axes = []
40 self.localtime = kwargs.pop('localtime', True)
40 self.localtime = kwargs.pop('localtime', True)
41 self.show = kwargs.get('show', True)
41 self.show = kwargs.get('show', True)
42 self.save = kwargs.get('save', False)
42 self.save = kwargs.get('save', False)
43 self.colormap = kwargs.get('colormap', self.colormap)
43 self.colormap = kwargs.get('colormap', self.colormap)
44 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
45 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
44 self.showprofile = kwargs.get('showprofile', True)
46 self.showprofile = kwargs.get('showprofile', True)
45 self.title = kwargs.get('wintitle', '')
47 self.title = kwargs.get('wintitle', '')
46 self.xaxis = kwargs.get('xaxis', 'time')
48 self.xaxis = kwargs.get('xaxis', 'frequency')
47 self.zmin = kwargs.get('zmin', None)
49 self.zmin = kwargs.get('zmin', None)
48 self.zmax = kwargs.get('zmax', None)
50 self.zmax = kwargs.get('zmax', None)
49 self.xmin = kwargs.get('xmin', None)
51 self.xmin = kwargs.get('xmin', None)
50 self.xmax = kwargs.get('xmax', None)
52 self.xmax = kwargs.get('xmax', None)
51 self.xrange = kwargs.get('xrange', 24)
53 self.xrange = kwargs.get('xrange', 24)
52 self.ymin = kwargs.get('ymin', None)
54 self.ymin = kwargs.get('ymin', None)
53 self.ymax = kwargs.get('ymax', None)
55 self.ymax = kwargs.get('ymax', None)
54 self.throttle_value = 5
56 self.throttle_value = 5
57
55 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
58 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
56
59
57 if x_buffer.shape[0] < 2:
60 if x_buffer.shape[0] < 2:
58 return x_buffer, y_buffer, z_buffer
61 return x_buffer, y_buffer, z_buffer
59
62
60 deltas = x_buffer[1:] - x_buffer[0:-1]
63 deltas = x_buffer[1:] - x_buffer[0:-1]
61 x_median = np.median(deltas)
64 x_median = np.median(deltas)
62
65
63 index = np.where(deltas > 5*x_median)
66 index = np.where(deltas > 5*x_median)
64
67
65 if len(index[0]) != 0:
68 if len(index[0]) != 0:
66 z_buffer[::, index[0], ::] = self.__missing
69 z_buffer[::, index[0], ::] = self.__missing
67 z_buffer = np.ma.masked_inside(z_buffer,
70 z_buffer = np.ma.masked_inside(z_buffer,
68 0.99*self.__missing,
71 0.99*self.__missing,
69 1.01*self.__missing)
72 1.01*self.__missing)
70
73
71 return x_buffer, y_buffer, z_buffer
74 return x_buffer, y_buffer, z_buffer
72
75
73 def decimate(self):
76 def decimate(self):
74
77
75 # dx = int(len(self.x)/self.__MAXNUMX) + 1
78 # dx = int(len(self.x)/self.__MAXNUMX) + 1
76 dy = int(len(self.y)/self.__MAXNUMY) + 1
79 dy = int(len(self.y)/self.__MAXNUMY) + 1
77
80
78 # x = self.x[::dx]
81 # x = self.x[::dx]
79 x = self.x
82 x = self.x
80 y = self.y[::dy]
83 y = self.y[::dy]
81 z = self.z[::, ::, ::dy]
84 z = self.z[::, ::, ::dy]
82
85
83 return x, y, z
86 return x, y, z
84
87
85 def __plot(self):
88 def __plot(self):
86
89
87 print 'plotting...{}'.format(self.CODE)
90 print 'plotting...{}'.format(self.CODE)
88
91
89 if self.show:
92 if self.show:
90 self.figure.show()
93 self.figure.show()
91
94
92 self.plot()
95 self.plot()
93 self.figure.suptitle('{} {} - Date:{}'.format(self.title, self.CODE.upper(),
96 plt.tight_layout()
94 datetime.datetime.utcfromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')))
97 self.figure.canvas.manager.set_window_title('{} {} - Date:{}'.format(self.title, self.CODE.upper(),
98 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')))
95
99
96 if self.save:
100 if self.save:
97 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
101 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
98 datetime.datetime.utcfromtimestamp(self.times[0]).strftime('%y%m%d_%H%M%S')))
102 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
99 print 'Saving figure: {}'.format(figname)
103 print 'Saving figure: {}'.format(figname)
100 self.figure.savefig(figname)
104 self.figure.savefig(figname)
101
105
102 self.figure.canvas.draw()
106 self.figure.canvas.draw()
103
107
104 def plot(self):
108 def plot(self):
105
109
106 print 'plotting...{}'.format(self.CODE.upper())
110 print 'plotting...{}'.format(self.CODE.upper())
107 return
111 return
108
112
109 def run(self):
113 def run(self):
110
114
111 print '[Starting] {}'.format(self.name)
115 print '[Starting] {}'.format(self.name)
112 context = zmq.Context()
116 context = zmq.Context()
113 receiver = context.socket(zmq.SUB)
117 receiver = context.socket(zmq.SUB)
114 receiver.setsockopt(zmq.SUBSCRIBE, '')
118 receiver.setsockopt(zmq.SUBSCRIBE, '')
115 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
119 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
116 receiver.connect("ipc:///tmp/zmq.plots")
120 receiver.connect("ipc:///tmp/zmq.plots")
117
121
118 while True:
122 while True:
119 try:
123 try:
120 #if True:
121 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
124 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
122 self.dataOut = self.data['dataOut']
125 self.dataOut = self.data['dataOut']
123 self.times = self.data['times']
126 self.times = self.data['times']
124 self.times.sort()
127 self.times.sort()
125 self.throttle_value = self.data['throttle']
128 self.throttle_value = self.data['throttle']
126 self.min_time = self.times[0]
129 self.min_time = self.times[0]
127 self.max_time = self.times[-1]
130 self.max_time = self.times[-1]
128
131
129 if self.isConfig is False:
132 if self.isConfig is False:
130 self.setup()
133 self.setup()
131 self.isConfig = True
134 self.isConfig = True
132 self.__plot()
135 self.__plot()
133
136
134 if self.data['ENDED'] is True:
137 if self.data['ENDED'] is True:
135 # self.__plot()
136 self.isConfig = False
138 self.isConfig = False
137
139
138 except zmq.Again as e:
140 except zmq.Again as e:
139 print 'Waiting for data...'
141 print 'Waiting for data...'
140 plt.pause(self.throttle_value)
142 plt.pause(self.throttle_value)
141 # time.sleep(3)
142
143
143 def close(self):
144 def close(self):
144 if self.dataOut:
145 if self.dataOut:
145 self._plot()
146 self.__plot()
146
147
147
148
148 class PlotSpectraData(PlotData):
149 class PlotSpectraData(PlotData):
149
150
150 CODE = 'spc'
151 CODE = 'spc'
151 colormap = 'jro'
152 colormap = 'jro'
152 CONFLATE = False
153 CONFLATE = False
154
153 def setup(self):
155 def setup(self):
154
156
155 ncolspan = 1
157 ncolspan = 1
156 colspan = 1
158 colspan = 1
157 self.ncols = int(numpy.sqrt(self.dataOut.nChannels)+0.9)
159 self.ncols = int(numpy.sqrt(self.dataOut.nChannels)+0.9)
158 self.nrows = int(self.dataOut.nChannels*1./self.ncols + 0.9)
160 self.nrows = int(self.dataOut.nChannels*1./self.ncols + 0.9)
159 self.width = 3.6*self.ncols
161 self.width = 3.6*self.ncols
160 self.height = 3.2*self.nrows
162 self.height = 3.2*self.nrows
161 if self.showprofile:
163 if self.showprofile:
162 ncolspan = 3
164 ncolspan = 3
163 colspan = 2
165 colspan = 2
164 self.width += 1.2*self.ncols
166 self.width += 1.2*self.ncols
165
167
166 self.ylabel = 'Range [Km]'
168 self.ylabel = 'Range [Km]'
167 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
169 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
168
170
169 if self.figure is None:
171 if self.figure is None:
170 self.figure = plt.figure(figsize=(self.width, self.height),
172 self.figure = plt.figure(figsize=(self.width, self.height),
171 edgecolor='k',
173 edgecolor='k',
172 facecolor='w')
174 facecolor='w')
173 else:
175 else:
174 self.figure.clf()
176 self.figure.clf()
175
177
176 n = 0
178 n = 0
177 for y in range(self.nrows):
179 for y in range(self.nrows):
178 for x in range(self.ncols):
180 for x in range(self.ncols):
179 if n >= self.dataOut.nChannels:
181 if n >= self.dataOut.nChannels:
180 break
182 break
181 ax = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan), 1, colspan)
183 ax = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan), 1, colspan)
182 if self.showprofile:
184 if self.showprofile:
183 ax.ax_profile = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan+colspan), 1, 1)
185 ax.ax_profile = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan+colspan), 1, 1)
184
186
185 ax.firsttime = True
187 ax.firsttime = True
186 self.axes.append(ax)
188 self.axes.append(ax)
187 n += 1
189 n += 1
188
190
189 self.figure.subplots_adjust(left=0.1, right=0.95, bottom=0.15, top=0.85, wspace=0.9, hspace=0.5)
190
191 def plot(self):
191 def plot(self):
192
192
193 if self.xaxis == "frequency":
193 if self.xaxis == "frequency":
194 x = self.dataOut.getFreqRange(1)/1000.
194 x = self.dataOut.getFreqRange(1)/1000.
195 xlabel = "Frequency (kHz)"
195 xlabel = "Frequency (kHz)"
196 elif self.xaxis == "time":
196 elif self.xaxis == "time":
197 x = self.dataOut.getAcfRange(1)
197 x = self.dataOut.getAcfRange(1)
198 xlabel = "Time (ms)"
198 xlabel = "Time (ms)"
199 else:
199 else:
200 x = self.dataOut.getVelRange(1)
200 x = self.dataOut.getVelRange(1)
201 xlabel = "Velocity (m/s)"
201 xlabel = "Velocity (m/s)"
202
202
203 y = self.dataOut.getHeiRange()
203 y = self.dataOut.getHeiRange()
204 z = self.data[self.CODE]
204 z = self.data[self.CODE]
205
205
206 for n, ax in enumerate(self.axes):
206 for n, ax in enumerate(self.axes):
207
207
208 if ax.firsttime:
208 if ax.firsttime:
209 self.xmax = self.xmax if self.xmax else np.nanmax(x)
209 self.xmax = self.xmax if self.xmax else np.nanmax(x)
210 self.xmin = self.xmin if self.xmin else -self.xmax
210 self.xmin = self.xmin if self.xmin else -self.xmax
211 self.ymin = self.ymin if self.ymin else np.nanmin(y)
211 self.ymin = self.ymin if self.ymin else np.nanmin(y)
212 self.ymax = self.ymax if self.ymax else np.nanmax(y)
212 self.ymax = self.ymax if self.ymax else np.nanmax(y)
213 self.zmin = self.zmin if self.zmin else np.nanmin(z)
213 self.zmin = self.zmin if self.zmin else np.nanmin(z)
214 self.zmax = self.zmax if self.zmax else np.nanmax(z)
214 self.zmax = self.zmax if self.zmax else np.nanmax(z)
215 ax.plot = ax.pcolormesh(x, y, z[n].T,
215 ax.plot = ax.pcolormesh(x, y, z[n].T,
216 vmin=self.zmin,
216 vmin=self.zmin,
217 vmax=self.zmax,
217 vmax=self.zmax,
218 cmap=plt.get_cmap(self.colormap)
218 cmap=plt.get_cmap(self.colormap)
219 )
219 )
220 divider = make_axes_locatable(ax)
220 divider = make_axes_locatable(ax)
221 cax = divider.new_horizontal(size='3%', pad=0.05)
221 cax = divider.new_horizontal(size='3%', pad=0.05)
222 self.figure.add_axes(cax)
222 self.figure.add_axes(cax)
223 plt.colorbar(ax.plot, cax)
223 plt.colorbar(ax.plot, cax)
224
224
225 ax.set_xlim(self.xmin, self.xmax)
225 ax.set_xlim(self.xmin, self.xmax)
226 ax.set_ylim(self.ymin, self.ymax)
226 ax.set_ylim(self.ymin, self.ymax)
227
227
228 ax.xaxis.set_major_locator(LinearLocator(5))
229 #ax.yaxis.set_major_locator(LinearLocator(4))
230
231 ax.set_ylabel(self.ylabel)
228 ax.set_ylabel(self.ylabel)
232 ax.set_xlabel(xlabel)
229 ax.set_xlabel(xlabel)
233
230
234 ax.firsttime = False
231 ax.firsttime = False
235
232
236 if self.showprofile:
233 if self.showprofile:
237 ax.plot_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
234 ax.plot_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
238 ax.ax_profile.set_xlim(self.zmin, self.zmax)
235 ax.ax_profile.set_xlim(self.zmin, self.zmax)
239 ax.ax_profile.set_ylim(self.ymin, self.ymax)
236 ax.ax_profile.set_ylim(self.ymin, self.ymax)
240 ax.ax_profile.set_xlabel('dB')
237 ax.ax_profile.set_xlabel('dB')
241 ax.ax_profile.grid(b=True, axis='x')
238 ax.ax_profile.grid(b=True, axis='x')
242 ax.plot_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
239 ax.plot_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
243 color="k", linestyle="dashed", lw=2)[0]
240 color="k", linestyle="dashed", lw=2)[0]
244 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
241 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
245 else:
242 else:
246 ax.plot.set_array(z[n].T.ravel())
243 ax.plot.set_array(z[n].T.ravel())
247 if self.showprofile:
244 if self.showprofile:
248 ax.plot_profile.set_data(self.data['rti'][self.max_time][n], y)
245 ax.plot_profile.set_data(self.data['rti'][self.max_time][n], y)
249 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
246 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
250
247
251 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
248 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
252 size=8)
249 size=8)
250 self.saveTime = self.max_time
251
252
253 class PlotCrossSpectraData(PlotData):
254
255 CODE = 'cspc'
256 zmin_coh = None
257 zmax_coh = None
258 zmin_phase = None
259 zmax_phase = None
260 CONFLATE = False
261
262 def setup(self):
263
264 ncolspan = 1
265 colspan = 1
266 self.ncols = 2
267 self.nrows = self.dataOut.nPairs
268 self.width = 3.6*self.ncols
269 self.height = 3.2*self.nrows
270
271 self.ylabel = 'Range [Km]'
272 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
273
274 if self.figure is None:
275 self.figure = plt.figure(figsize=(self.width, self.height),
276 edgecolor='k',
277 facecolor='w')
278 else:
279 self.figure.clf()
280
281 for y in range(self.nrows):
282 for x in range(self.ncols):
283 ax = plt.subplot2grid((self.nrows, self.ncols), (y, x), 1, 1)
284 ax.firsttime = True
285 self.axes.append(ax)
286
287 def plot(self):
288
289 if self.xaxis == "frequency":
290 x = self.dataOut.getFreqRange(1)/1000.
291 xlabel = "Frequency (kHz)"
292 elif self.xaxis == "time":
293 x = self.dataOut.getAcfRange(1)
294 xlabel = "Time (ms)"
295 else:
296 x = self.dataOut.getVelRange(1)
297 xlabel = "Velocity (m/s)"
298
299 y = self.dataOut.getHeiRange()
300 z_coh = self.data['cspc_coh']
301 z_phase = self.data['cspc_phase']
302
303 for n in range(self.nrows):
304 ax = self.axes[2*n]
305 ax1 = self.axes[2*n+1]
306 if ax.firsttime:
307 self.xmax = self.xmax if self.xmax else np.nanmax(x)
308 self.xmin = self.xmin if self.xmin else -self.xmax
309 self.ymin = self.ymin if self.ymin else np.nanmin(y)
310 self.ymax = self.ymax if self.ymax else np.nanmax(y)
311 self.zmin_coh = self.zmin_coh if self.zmin_coh else 0.0
312 self.zmax_coh = self.zmax_coh if self.zmax_coh else 1.0
313 self.zmin_phase = self.zmin_phase if self.zmin_phase else -180
314 self.zmax_phase = self.zmax_phase if self.zmax_phase else 180
315
316 ax.plot = ax.pcolormesh(x, y, z_coh[n].T,
317 vmin=self.zmin_coh,
318 vmax=self.zmax_coh,
319 cmap=plt.get_cmap(self.colormap_coh)
320 )
321 divider = make_axes_locatable(ax)
322 cax = divider.new_horizontal(size='3%', pad=0.05)
323 self.figure.add_axes(cax)
324 plt.colorbar(ax.plot, cax)
325
326 ax.set_xlim(self.xmin, self.xmax)
327 ax.set_ylim(self.ymin, self.ymax)
328
329 ax.set_ylabel(self.ylabel)
330 ax.set_xlabel(xlabel)
331 ax.firsttime = False
332
333 ax1.plot = ax1.pcolormesh(x, y, z_phase[n].T,
334 vmin=self.zmin_phase,
335 vmax=self.zmax_phase,
336 cmap=plt.get_cmap(self.colormap_phase)
337 )
338 divider = make_axes_locatable(ax1)
339 cax = divider.new_horizontal(size='3%', pad=0.05)
340 self.figure.add_axes(cax)
341 plt.colorbar(ax1.plot, cax)
342
343 ax1.set_xlim(self.xmin, self.xmax)
344 ax1.set_ylim(self.ymin, self.ymax)
345
346 ax1.set_ylabel(self.ylabel)
347 ax1.set_xlabel(xlabel)
348 ax1.firsttime = False
349 else:
350 ax.plot.set_array(z_coh[n].T.ravel())
351 ax1.plot.set_array(z_phase[n].T.ravel())
352
353 ax.set_title('Coherence Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
354 ax1.set_title('Phase Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
355 self.saveTime = self.max_time
356
357
358 class PlotSpectraMeanData(PlotSpectraData):
359
360 CODE = 'spc_mean'
361 colormap = 'jet'
362
363 def plot(self):
364
365 if self.xaxis == "frequency":
366 x = self.dataOut.getFreqRange(1)/1000.
367 xlabel = "Frequency (kHz)"
368 elif self.xaxis == "time":
369 x = self.dataOut.getAcfRange(1)
370 xlabel = "Time (ms)"
371 else:
372 x = self.dataOut.getVelRange(1)
373 xlabel = "Velocity (m/s)"
374
375 y = self.dataOut.getHeiRange()
376 z = self.data['spc']
377 mean = self.data['mean'][self.max_time]
378
379 for n, ax in enumerate(self.axes):
380
381 if ax.firsttime:
382 self.xmax = self.xmax if self.xmax else np.nanmax(x)
383 self.xmin = self.xmin if self.xmin else -self.xmax
384 self.ymin = self.ymin if self.ymin else np.nanmin(y)
385 self.ymax = self.ymax if self.ymax else np.nanmax(y)
386 self.zmin = self.zmin if self.zmin else np.nanmin(z)
387 self.zmax = self.zmax if self.zmax else np.nanmax(z)
388 ax.plt = ax.pcolormesh(x, y, z[n].T,
389 vmin=self.zmin,
390 vmax=self.zmax,
391 cmap=plt.get_cmap(self.colormap)
392 )
393 ax.plt_dop = ax.plot(mean[n], y,
394 color='k')[0]
395
396 divider = make_axes_locatable(ax)
397 cax = divider.new_horizontal(size='3%', pad=0.05)
398 self.figure.add_axes(cax)
399 plt.colorbar(ax.plt, cax)
400
401 ax.set_xlim(self.xmin, self.xmax)
402 ax.set_ylim(self.ymin, self.ymax)
403
404 ax.set_ylabel(self.ylabel)
405 ax.set_xlabel(xlabel)
406
407 ax.firsttime = False
408
409 if self.showprofile:
410 ax.plt_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
411 ax.ax_profile.set_xlim(self.zmin, self.zmax)
412 ax.ax_profile.set_ylim(self.ymin, self.ymax)
413 ax.ax_profile.set_xlabel('dB')
414 ax.ax_profile.grid(b=True, axis='x')
415 ax.plt_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
416 color="k", linestyle="dashed", lw=2)[0]
417 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
418 else:
419 ax.plt.set_array(z[n].T.ravel())
420 ax.plt_dop.set_data(mean[n], y)
421 if self.showprofile:
422 ax.plt_profile.set_data(self.data['rti'][self.max_time][n], y)
423 ax.plt_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
424
425 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
426 size=8)
427 self.saveTime = self.max_time
428
253
429
254 class PlotRTIData(PlotData):
430 class PlotRTIData(PlotData):
255
431
256 CODE = 'rti'
432 CODE = 'rti'
257 colormap = 'jro'
433 colormap = 'jro'
258
434
259 def setup(self):
435 def setup(self):
260 self.ncols = 1
436 self.ncols = 1
261 self.nrows = self.dataOut.nChannels
437 self.nrows = self.dataOut.nChannels
262 self.width = 10
438 self.width = 10
263 self.height = 2.2*self.nrows
439 self.height = 2.2*self.nrows if self.nrows<6 else 12
264 if self.nrows==1:
440 if self.nrows==1:
265 self.height += 1
441 self.height += 1
266 self.ylabel = 'Range [Km]'
442 self.ylabel = 'Range [Km]'
267 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
443 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
268
444
269 if self.figure is None:
445 if self.figure is None:
270 self.figure = plt.figure(figsize=(self.width, self.height),
446 self.figure = plt.figure(figsize=(self.width, self.height),
271 edgecolor='k',
447 edgecolor='k',
272 facecolor='w')
448 facecolor='w')
273 else:
449 else:
274 self.figure.clf()
450 self.figure.clf()
275 self.axes = []
451 self.axes = []
276
452
277 for n in range(self.nrows):
453 for n in range(self.nrows):
278 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
454 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
279 ax.firsttime = True
455 ax.firsttime = True
280 self.axes.append(ax)
456 self.axes.append(ax)
281 self.figure.subplots_adjust(hspace=0.5)
282
457
283 def plot(self):
458 def plot(self):
284
459
285 self.x = np.array(self.times)
460 self.x = np.array(self.times)
286 self.y = self.dataOut.getHeiRange()
461 self.y = self.dataOut.getHeiRange()
287 self.z = []
462 self.z = []
288
463
289 for ch in range(self.nrows):
464 for ch in range(self.nrows):
290 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
465 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
291
466
292 self.z = np.array(self.z)
467 self.z = np.array(self.z)
293 for n, ax in enumerate(self.axes):
468 for n, ax in enumerate(self.axes):
294
469
295 x, y, z = self.fill_gaps(*self.decimate())
470 x, y, z = self.fill_gaps(*self.decimate())
296 xmin = self.min_time
471 xmin = self.min_time
297 xmax = xmin+self.xrange*60*60
472 xmax = xmin+self.xrange*60*60
298 if ax.firsttime:
473 if ax.firsttime:
299 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
474 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
300 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
475 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
301 self.zmin = self.zmin if self.zmin else np.nanmin(self.z)
476 self.zmin = self.zmin if self.zmin else np.nanmin(self.z)
302 self.zmax = self.zmax if self.zmax else np.nanmax(self.z)
477 self.zmax = self.zmax if self.zmax else np.nanmax(self.z)
303 plot = ax.pcolormesh(x, y, z[n].T,
478 plot = ax.pcolormesh(x, y, z[n].T,
304 vmin=self.zmin,
479 vmin=self.zmin,
305 vmax=self.zmax,
480 vmax=self.zmax,
306 cmap=plt.get_cmap(self.colormap)
481 cmap=plt.get_cmap(self.colormap)
307 )
482 )
308 divider = make_axes_locatable(ax)
483 divider = make_axes_locatable(ax)
309 cax = divider.new_horizontal(size='2%', pad=0.05)
484 cax = divider.new_horizontal(size='2%', pad=0.05)
310 self.figure.add_axes(cax)
485 self.figure.add_axes(cax)
311 plt.colorbar(plot, cax)
486 plt.colorbar(plot, cax)
312 ax.set_ylim(self.ymin, self.ymax)
487 ax.set_ylim(self.ymin, self.ymax)
313 if self.xaxis == 'time':
314 ax.xaxis.set_major_formatter(FuncFormatter(func))
315 ax.xaxis.set_major_locator(LinearLocator(6))
316
488
317 # ax.yaxis.set_major_locator(LinearLocator(4))
489 ax.xaxis.set_major_formatter(FuncFormatter(func))
490 ax.xaxis.set_major_locator(LinearLocator(6))
318
491
319 ax.set_ylabel(self.ylabel)
492 ax.set_ylabel(self.ylabel)
320
493
321 # if self.xmin is None:
494 # if self.xmin is None:
322 # xmin = self.min_time
495 # xmin = self.min_time
323 # else:
496 # else:
324 # xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
497 # xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
325 # datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
498 # datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
326
499
327 ax.set_xlim(xmin, xmax)
500 ax.set_xlim(xmin, xmax)
328 ax.firsttime = False
501 ax.firsttime = False
329 else:
502 else:
330 ax.collections.remove(ax.collections[0])
503 ax.collections.remove(ax.collections[0])
331 ax.set_xlim(xmin, xmax)
504 ax.set_xlim(xmin, xmax)
332 plot = ax.pcolormesh(x, y, z[n].T,
505 plot = ax.pcolormesh(x, y, z[n].T,
333 vmin=self.zmin,
506 vmin=self.zmin,
334 vmax=self.zmax,
507 vmax=self.zmax,
335 cmap=plt.get_cmap(self.colormap)
508 cmap=plt.get_cmap(self.colormap)
336 )
509 )
337 ax.set_title('{} {}'.format(self.titles[n],
510 ax.set_title('{} {}'.format(self.titles[n],
338 datetime.datetime.utcfromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
511 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
339 size=8)
512 size=8)
513
514 self.saveTime = self.min_time
340
515
341
516
342 class PlotCOHData(PlotRTIData):
517 class PlotCOHData(PlotRTIData):
343
518
344 CODE = 'coh'
519 CODE = 'coh'
345
520
346 def setup(self):
521 def setup(self):
347
522
348 self.ncols = 1
523 self.ncols = 1
349 self.nrows = self.dataOut.nPairs
524 self.nrows = self.dataOut.nPairs
350 self.width = 10
525 self.width = 10
351 self.height = 2.2*self.nrows
526 self.height = 2.2*self.nrows if self.nrows<6 else 12
352 if self.nrows==1:
527 if self.nrows==1:
353 self.height += 1
528 self.height += 1
354 self.ylabel = 'Range [Km]'
529 self.ylabel = 'Range [Km]'
355 self.titles = ['Channels {}'.format(x) for x in self.dataOut.pairsList]
530 self.titles = ['{} Ch{} * Ch{}'.format(self.CODE.upper(), x[0], x[1]) for x in self.dataOut.pairsList]
356
531
357 if self.figure is None:
532 if self.figure is None:
358 self.figure = plt.figure(figsize=(self.width, self.height),
533 self.figure = plt.figure(figsize=(self.width, self.height),
359 edgecolor='k',
534 edgecolor='k',
360 facecolor='w')
535 facecolor='w')
361 else:
536 else:
362 self.figure.clf()
537 self.figure.clf()
363 self.axes = []
538 self.axes = []
364
539
365 for n in range(self.nrows):
540 for n in range(self.nrows):
366 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
541 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
367 ax.firsttime = True
542 ax.firsttime = True
368 self.axes.append(ax)
543 self.axes.append(ax)
369
544
370 self.figure.subplots_adjust(hspace=0.5)
371
545
372 class PlotNoiseData(PlotData):
546 class PlotNoiseData(PlotData):
373 CODE = 'noise'
547 CODE = 'noise'
374
548
375 def setup(self):
549 def setup(self):
376
550
377 self.ncols = 1
551 self.ncols = 1
378 self.nrows = 1
552 self.nrows = 1
379 self.width = 10
553 self.width = 10
380 self.height = 3.2
554 self.height = 3.2
381 self.ylabel = 'Intensity [dB]'
555 self.ylabel = 'Intensity [dB]'
382 self.titles = ['Noise']
556 self.titles = ['Noise']
383
557
384 if self.figure is None:
558 if self.figure is None:
385 self.figure = plt.figure(figsize=(self.width, self.height),
559 self.figure = plt.figure(figsize=(self.width, self.height),
386 edgecolor='k',
560 edgecolor='k',
387 facecolor='w')
561 facecolor='w')
388 else:
562 else:
389 self.figure.clf()
563 self.figure.clf()
390 self.axes = []
564 self.axes = []
391
565
392 self.ax = self.figure.add_subplot(self.nrows, self.ncols, 1)
566 self.ax = self.figure.add_subplot(self.nrows, self.ncols, 1)
393 self.ax.firsttime = True
567 self.ax.firsttime = True
394
568
395 def plot(self):
569 def plot(self):
396
570
397 x = self.times
571 x = self.times
398 xmin = self.min_time
572 xmin = self.min_time
399 xmax = xmin+self.xrange*60*60
573 xmax = xmin+self.xrange*60*60
400 if self.ax.firsttime:
574 if self.ax.firsttime:
401 for ch in self.dataOut.channelList:
575 for ch in self.dataOut.channelList:
402 y = [self.data[self.CODE][t][ch] for t in self.times]
576 y = [self.data[self.CODE][t][ch] for t in self.times]
403 self.ax.plot(x, y, lw=1, label='Ch{}'.format(ch))
577 self.ax.plot(x, y, lw=1, label='Ch{}'.format(ch))
404 self.ax.firsttime = False
578 self.ax.firsttime = False
405 self.ax.xaxis.set_major_formatter(FuncFormatter(func))
579 self.ax.xaxis.set_major_formatter(FuncFormatter(func))
406 self.ax.xaxis.set_major_locator(LinearLocator(6))
580 self.ax.xaxis.set_major_locator(LinearLocator(6))
407 self.ax.set_ylabel(self.ylabel)
581 self.ax.set_ylabel(self.ylabel)
408 plt.legend()
582 plt.legend()
409 else:
583 else:
410 for ch in self.dataOut.channelList:
584 for ch in self.dataOut.channelList:
411 y = [self.data[self.CODE][t][ch] for t in self.times]
585 y = [self.data[self.CODE][t][ch] for t in self.times]
412 self.ax.lines[ch].set_data(x, y)
586 self.ax.lines[ch].set_data(x, y)
413
587
414 self.ax.set_xlim(xmin, xmax)
588 self.ax.set_xlim(xmin, xmax)
415 self.ax.set_ylim(min(y)-5, max(y)+5)
589 self.ax.set_ylim(min(y)-5, max(y)+5)
590 self.saveTime = self.min_time
591
416
592
417 class PlotSNRData(PlotRTIData):
593 class PlotSNRData(PlotRTIData):
418 CODE = 'snr'
594 CODE = 'snr'
595 colormap = 'jet'
419
596
420 class PlotDOPData(PlotRTIData):
597 class PlotDOPData(PlotRTIData):
421 CODE = 'dop'
598 CODE = 'dop'
422 colormap = 'jet'
599 colormap = 'jet'
423
600
601
424 class PlotPHASEData(PlotCOHData):
602 class PlotPHASEData(PlotCOHData):
425 CODE = 'phase'
603 CODE = 'phase'
426 colormap = 'seismic'
604 colormap = 'seismic'
@@ -1,2741 +1,2749
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 re
4 import re
5 import datetime
5 import datetime
6 import copy
6 import copy
7 import sys
7 import sys
8 import importlib
8 import importlib
9 import itertools
9 import itertools
10
10
11 from jroproc_base import ProcessingUnit, Operation
11 from jroproc_base import ProcessingUnit, Operation
12 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
12 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
13
13
14
14
15 class ParametersProc(ProcessingUnit):
15 class ParametersProc(ProcessingUnit):
16
16
17 nSeconds = None
17 nSeconds = None
18
18
19 def __init__(self):
19 def __init__(self):
20 ProcessingUnit.__init__(self)
20 ProcessingUnit.__init__(self)
21
21
22 # self.objectDict = {}
22 # self.objectDict = {}
23 self.buffer = None
23 self.buffer = None
24 self.firstdatatime = None
24 self.firstdatatime = None
25 self.profIndex = 0
25 self.profIndex = 0
26 self.dataOut = Parameters()
26 self.dataOut = Parameters()
27
27
28 def __updateObjFromInput(self):
28 def __updateObjFromInput(self):
29
29
30 self.dataOut.inputUnit = self.dataIn.type
30 self.dataOut.inputUnit = self.dataIn.type
31
31
32 self.dataOut.timeZone = self.dataIn.timeZone
32 self.dataOut.timeZone = self.dataIn.timeZone
33 self.dataOut.dstFlag = self.dataIn.dstFlag
33 self.dataOut.dstFlag = self.dataIn.dstFlag
34 self.dataOut.errorCount = self.dataIn.errorCount
34 self.dataOut.errorCount = self.dataIn.errorCount
35 self.dataOut.useLocalTime = self.dataIn.useLocalTime
35 self.dataOut.useLocalTime = self.dataIn.useLocalTime
36
36
37 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
37 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
38 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
38 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
39 self.dataOut.channelList = self.dataIn.channelList
39 self.dataOut.channelList = self.dataIn.channelList
40 self.dataOut.heightList = self.dataIn.heightList
40 self.dataOut.heightList = self.dataIn.heightList
41 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
41 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
42 # self.dataOut.nHeights = self.dataIn.nHeights
42 # self.dataOut.nHeights = self.dataIn.nHeights
43 # self.dataOut.nChannels = self.dataIn.nChannels
43 # self.dataOut.nChannels = self.dataIn.nChannels
44 self.dataOut.nBaud = self.dataIn.nBaud
44 self.dataOut.nBaud = self.dataIn.nBaud
45 self.dataOut.nCode = self.dataIn.nCode
45 self.dataOut.nCode = self.dataIn.nCode
46 self.dataOut.code = self.dataIn.code
46 self.dataOut.code = self.dataIn.code
47 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
47 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
48 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
48 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
49 # self.dataOut.utctime = self.firstdatatime
49 # self.dataOut.utctime = self.firstdatatime
50 self.dataOut.utctime = self.dataIn.utctime
50 self.dataOut.utctime = self.dataIn.utctime
51 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
51 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
52 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
53 self.dataOut.nCohInt = self.dataIn.nCohInt
53 self.dataOut.nCohInt = self.dataIn.nCohInt
54 # self.dataOut.nIncohInt = 1
54 # self.dataOut.nIncohInt = 1
55 self.dataOut.ippSeconds = self.dataIn.ippSeconds
55 self.dataOut.ippSeconds = self.dataIn.ippSeconds
56 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
56 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
57 self.dataOut.timeInterval = self.dataIn.timeInterval
57 # self.dataOut.timeInterval = self.dataIn.timeInterval
58 self.dataOut.heightList = self.dataIn.getHeiRange()
58 self.dataOut.heightList = self.dataIn.getHeiRange()
59 self.dataOut.frequency = self.dataIn.frequency
59 self.dataOut.frequency = self.dataIn.frequency
60 self.dataOut.noise = self.dataIn.noise
60 #self.dataOut.noise = self.dataIn.noise
61
61
62 def run(self):
62 def run(self):
63
63
64 #---------------------- Voltage Data ---------------------------
64 #---------------------- Voltage Data ---------------------------
65
65
66 if self.dataIn.type == "Voltage":
66 if self.dataIn.type == "Voltage":
67
67
68 self.__updateObjFromInput()
68 self.__updateObjFromInput()
69 self.dataOut.data_pre = self.dataIn.data.copy()
69 self.dataOut.data_pre = self.dataIn.data.copy()
70 self.dataOut.flagNoData = False
70 self.dataOut.flagNoData = False
71 self.dataOut.utctimeInit = self.dataIn.utctime
71 self.dataOut.utctimeInit = self.dataIn.utctime
72 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
72 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
73 return
73 return
74
74
75 #---------------------- Spectra Data ---------------------------
75 #---------------------- Spectra Data ---------------------------
76
76
77 if self.dataIn.type == "Spectra":
77 if self.dataIn.type == "Spectra":
78
78
79 self.dataOut.data_pre = (self.dataIn.data_spc,self.dataIn.data_cspc)
79 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
80 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
80 self.dataOut.data_spc = self.dataIn.data_spc
81 # self.dataOut.noise = self.dataIn.getNoise()
81 self.dataOut.data_cspc = self.dataIn.data_cspc
82 self.dataOut.normFactor = self.dataIn.normFactor
82 self.dataOut.nProfiles = self.dataIn.nProfiles
83 self.dataOut.nIncohInt = self.dataIn.nIncohInt
84 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
85 self.dataOut.ippFactor = self.dataIn.ippFactor
86 #self.dataOut.normFactor = self.dataIn.getNormFactor()
87 self.dataOut.pairsList = self.dataIn.pairsList
83 self.dataOut.groupList = self.dataIn.pairsList
88 self.dataOut.groupList = self.dataIn.pairsList
89 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
84 self.dataOut.flagNoData = False
90 self.dataOut.flagNoData = False
85
91
86 #---------------------- Correlation Data ---------------------------
92 #---------------------- Correlation Data ---------------------------
87
93
88 if self.dataIn.type == "Correlation":
94 if self.dataIn.type == "Correlation":
89 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
95 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
90
96
91 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
97 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
92 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
98 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
93 self.dataOut.groupList = (acf_pairs, ccf_pairs)
99 self.dataOut.groupList = (acf_pairs, ccf_pairs)
94
100
95 self.dataOut.abscissaList = self.dataIn.lagRange
101 self.dataOut.abscissaList = self.dataIn.lagRange
96 self.dataOut.noise = self.dataIn.noise
102 self.dataOut.noise = self.dataIn.noise
97 self.dataOut.data_SNR = self.dataIn.SNR
103 self.dataOut.data_SNR = self.dataIn.SNR
98 self.dataOut.flagNoData = False
104 self.dataOut.flagNoData = False
99 self.dataOut.nAvg = self.dataIn.nAvg
105 self.dataOut.nAvg = self.dataIn.nAvg
100
106
101 #---------------------- Parameters Data ---------------------------
107 #---------------------- Parameters Data ---------------------------
102
108
103 if self.dataIn.type == "Parameters":
109 if self.dataIn.type == "Parameters":
104 self.dataOut.copy(self.dataIn)
110 self.dataOut.copy(self.dataIn)
105 self.dataOut.utctimeInit = self.dataIn.utctime
111 self.dataOut.utctimeInit = self.dataIn.utctime
106 self.dataOut.flagNoData = False
112 self.dataOut.flagNoData = False
107
113
108 return True
114 return True
109
115
110 self.__updateObjFromInput()
116 self.__updateObjFromInput()
111 self.dataOut.utctimeInit = self.dataIn.utctime
117 self.dataOut.utctimeInit = self.dataIn.utctime
112 self.dataOut.paramInterval = self.dataIn.timeInterval
118 self.dataOut.paramInterval = self.dataIn.timeInterval
113
119
114 return
120 return
115
121
116 class SpectralMoments(Operation):
122 class SpectralMoments(Operation):
117
123
118 '''
124 '''
119 Function SpectralMoments()
125 Function SpectralMoments()
120
126
121 Calculates moments (power, mean, standard deviation) and SNR of the signal
127 Calculates moments (power, mean, standard deviation) and SNR of the signal
122
128
123 Type of dataIn: Spectra
129 Type of dataIn: Spectra
124
130
125 Configuration Parameters:
131 Configuration Parameters:
126
132
127 dirCosx : Cosine director in X axis
133 dirCosx : Cosine director in X axis
128 dirCosy : Cosine director in Y axis
134 dirCosy : Cosine director in Y axis
129
135
130 elevation :
136 elevation :
131 azimuth :
137 azimuth :
132
138
133 Input:
139 Input:
134 channelList : simple channel list to select e.g. [2,3,7]
140 channelList : simple channel list to select e.g. [2,3,7]
135 self.dataOut.data_pre : Spectral data
141 self.dataOut.data_pre : Spectral data
136 self.dataOut.abscissaList : List of frequencies
142 self.dataOut.abscissaList : List of frequencies
137 self.dataOut.noise : Noise level per channel
143 self.dataOut.noise : Noise level per channel
138
144
139 Affected:
145 Affected:
140 self.dataOut.data_param : Parameters per channel
146 self.dataOut.data_param : Parameters per channel
141 self.dataOut.data_SNR : SNR per channel
147 self.dataOut.data_SNR : SNR per channel
142
148
143 '''
149 '''
144
150
145 def run(self, dataOut):
151 def run(self, dataOut):
146
152
147 dataOut.data_pre = dataOut.data_pre[0]
153 #dataOut.data_pre = dataOut.data_pre[0]
148 data = dataOut.data_pre
154 data = dataOut.data_pre[0]
149 absc = dataOut.abscissaList[:-1]
155 absc = dataOut.abscissaList[:-1]
150 noise = dataOut.noise
156 noise = dataOut.noise
151 nChannel = data.shape[0]
157 nChannel = data.shape[0]
152 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
158 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
153
159
154 for ind in range(nChannel):
160 for ind in range(nChannel):
155 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:], absc, noise[ind])
161 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:], absc, noise[ind])
156
162
157 dataOut.data_param = data_param[:,1:,:]
163 dataOut.data_param = data_param[:,1:,:]
158 dataOut.data_SNR = data_param[:,0]
164 dataOut.data_SNR = data_param[:,0]
159 dataOut.data_DOP = data_param[:,1]
165 dataOut.data_DOP = data_param[:,1]
166 dataOut.data_MEAN = data_param[:,2]
167 dataOut.data_STD = data_param[:,3]
160 return
168 return
161
169
162 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):
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):
163
171
164 if (nicoh is None): nicoh = 1
172 if (nicoh is None): nicoh = 1
165 if (graph is None): graph = 0
173 if (graph is None): graph = 0
166 if (smooth is None): smooth = 0
174 if (smooth is None): smooth = 0
167 elif (self.smooth < 3): smooth = 0
175 elif (self.smooth < 3): smooth = 0
168
176
169 if (type1 is None): type1 = 0
177 if (type1 is None): type1 = 0
170 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
178 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
171 if (snrth is None): snrth = -3
179 if (snrth is None): snrth = -3
172 if (dc is None): dc = 0
180 if (dc is None): dc = 0
173 if (aliasing is None): aliasing = 0
181 if (aliasing is None): aliasing = 0
174 if (oldfd is None): oldfd = 0
182 if (oldfd is None): oldfd = 0
175 if (wwauto is None): wwauto = 0
183 if (wwauto is None): wwauto = 0
176
184
177 if (n0 < 1.e-20): n0 = 1.e-20
185 if (n0 < 1.e-20): n0 = 1.e-20
178
186
179 freq = oldfreq
187 freq = oldfreq
180 vec_power = numpy.zeros(oldspec.shape[1])
188 vec_power = numpy.zeros(oldspec.shape[1])
181 vec_fd = numpy.zeros(oldspec.shape[1])
189 vec_fd = numpy.zeros(oldspec.shape[1])
182 vec_w = numpy.zeros(oldspec.shape[1])
190 vec_w = numpy.zeros(oldspec.shape[1])
183 vec_snr = numpy.zeros(oldspec.shape[1])
191 vec_snr = numpy.zeros(oldspec.shape[1])
184
192
185 for ind in range(oldspec.shape[1]):
193 for ind in range(oldspec.shape[1]):
186
194
187 spec = oldspec[:,ind]
195 spec = oldspec[:,ind]
188 aux = spec*fwindow
196 aux = spec*fwindow
189 max_spec = aux.max()
197 max_spec = aux.max()
190 m = list(aux).index(max_spec)
198 m = list(aux).index(max_spec)
191
199
192 #Smooth
200 #Smooth
193 if (smooth == 0): spec2 = spec
201 if (smooth == 0): spec2 = spec
194 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
202 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
195
203
196 # Calculo de Momentos
204 # Calculo de Momentos
197 bb = spec2[range(m,spec2.size)]
205 bb = spec2[range(m,spec2.size)]
198 bb = (bb<n0).nonzero()
206 bb = (bb<n0).nonzero()
199 bb = bb[0]
207 bb = bb[0]
200
208
201 ss = spec2[range(0,m + 1)]
209 ss = spec2[range(0,m + 1)]
202 ss = (ss<n0).nonzero()
210 ss = (ss<n0).nonzero()
203 ss = ss[0]
211 ss = ss[0]
204
212
205 if (bb.size == 0):
213 if (bb.size == 0):
206 bb0 = spec.size - 1 - m
214 bb0 = spec.size - 1 - m
207 else:
215 else:
208 bb0 = bb[0] - 1
216 bb0 = bb[0] - 1
209 if (bb0 < 0):
217 if (bb0 < 0):
210 bb0 = 0
218 bb0 = 0
211
219
212 if (ss.size == 0): ss1 = 1
220 if (ss.size == 0): ss1 = 1
213 else: ss1 = max(ss) + 1
221 else: ss1 = max(ss) + 1
214
222
215 if (ss1 > m): ss1 = m
223 if (ss1 > m): ss1 = m
216
224
217 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
225 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
218 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
226 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
219 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
227 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
220 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
228 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
221 snr = (spec2.mean()-n0)/n0
229 snr = (spec2.mean()-n0)/n0
222
230
223 if (snr < 1.e-20) :
231 if (snr < 1.e-20) :
224 snr = 1.e-20
232 snr = 1.e-20
225
233
226 vec_power[ind] = power
234 vec_power[ind] = power
227 vec_fd[ind] = fd
235 vec_fd[ind] = fd
228 vec_w[ind] = w
236 vec_w[ind] = w
229 vec_snr[ind] = snr
237 vec_snr[ind] = snr
230
238
231 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
239 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
232 return moments
240 return moments
233
241
234 #------------------ Get SA Parameters --------------------------
242 #------------------ Get SA Parameters --------------------------
235
243
236 def GetSAParameters(self):
244 def GetSAParameters(self):
237 #SA en frecuencia
245 #SA en frecuencia
238 pairslist = self.dataOut.groupList
246 pairslist = self.dataOut.groupList
239 num_pairs = len(pairslist)
247 num_pairs = len(pairslist)
240
248
241 vel = self.dataOut.abscissaList
249 vel = self.dataOut.abscissaList
242 spectra = self.dataOut.data_pre
250 spectra = self.dataOut.data_pre[0]
243 cspectra = self.dataIn.data_cspc
251 cspectra = self.dataOut.data_pre[1]
244 delta_v = vel[1] - vel[0]
252 delta_v = vel[1] - vel[0]
245
253
246 #Calculating the power spectrum
254 #Calculating the power spectrum
247 spc_pow = numpy.sum(spectra, 3)*delta_v
255 spc_pow = numpy.sum(spectra, 3)*delta_v
248 #Normalizing Spectra
256 #Normalizing Spectra
249 norm_spectra = spectra/spc_pow
257 norm_spectra = spectra/spc_pow
250 #Calculating the norm_spectra at peak
258 #Calculating the norm_spectra at peak
251 max_spectra = numpy.max(norm_spectra, 3)
259 max_spectra = numpy.max(norm_spectra, 3)
252
260
253 #Normalizing Cross Spectra
261 #Normalizing Cross Spectra
254 norm_cspectra = numpy.zeros(cspectra.shape)
262 norm_cspectra = numpy.zeros(cspectra.shape)
255
263
256 for i in range(num_chan):
264 for i in range(num_chan):
257 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
265 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
258
266
259 max_cspectra = numpy.max(norm_cspectra,2)
267 max_cspectra = numpy.max(norm_cspectra,2)
260 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
268 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
261
269
262 for i in range(num_pairs):
270 for i in range(num_pairs):
263 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
271 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
264 #------------------- Get Lags ----------------------------------
272 #------------------- Get Lags ----------------------------------
265
273
266 class SALags(Operation):
274 class SALags(Operation):
267 '''
275 '''
268 Function GetMoments()
276 Function GetMoments()
269
277
270 Input:
278 Input:
271 self.dataOut.data_pre
279 self.dataOut.data_pre
272 self.dataOut.abscissaList
280 self.dataOut.abscissaList
273 self.dataOut.noise
281 self.dataOut.noise
274 self.dataOut.normFactor
282 self.dataOut.normFactor
275 self.dataOut.data_SNR
283 self.dataOut.data_SNR
276 self.dataOut.groupList
284 self.dataOut.groupList
277 self.dataOut.nChannels
285 self.dataOut.nChannels
278
286
279 Affected:
287 Affected:
280 self.dataOut.data_param
288 self.dataOut.data_param
281
289
282 '''
290 '''
283 def run(self, dataOut):
291 def run(self, dataOut):
284 data_acf = dataOut.data_pre[0]
292 data_acf = dataOut.data_pre[0]
285 data_ccf = dataOut.data_pre[1]
293 data_ccf = dataOut.data_pre[1]
286 normFactor_acf = dataOut.normFactor[0]
294 normFactor_acf = dataOut.normFactor[0]
287 normFactor_ccf = dataOut.normFactor[1]
295 normFactor_ccf = dataOut.normFactor[1]
288 pairs_acf = dataOut.groupList[0]
296 pairs_acf = dataOut.groupList[0]
289 pairs_ccf = dataOut.groupList[1]
297 pairs_ccf = dataOut.groupList[1]
290
298
291 nHeights = dataOut.nHeights
299 nHeights = dataOut.nHeights
292 absc = dataOut.abscissaList
300 absc = dataOut.abscissaList
293 noise = dataOut.noise
301 noise = dataOut.noise
294 SNR = dataOut.data_SNR
302 SNR = dataOut.data_SNR
295 nChannels = dataOut.nChannels
303 nChannels = dataOut.nChannels
296 # pairsList = dataOut.groupList
304 # pairsList = dataOut.groupList
297 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
305 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
298
306
299 for l in range(len(pairs_acf)):
307 for l in range(len(pairs_acf)):
300 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
308 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
301
309
302 for l in range(len(pairs_ccf)):
310 for l in range(len(pairs_ccf)):
303 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
311 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
304
312
305 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
313 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
306 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
314 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
307 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
315 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
308 return
316 return
309
317
310 # def __getPairsAutoCorr(self, pairsList, nChannels):
318 # def __getPairsAutoCorr(self, pairsList, nChannels):
311 #
319 #
312 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
320 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
313 #
321 #
314 # for l in range(len(pairsList)):
322 # for l in range(len(pairsList)):
315 # firstChannel = pairsList[l][0]
323 # firstChannel = pairsList[l][0]
316 # secondChannel = pairsList[l][1]
324 # secondChannel = pairsList[l][1]
317 #
325 #
318 # #Obteniendo pares de Autocorrelacion
326 # #Obteniendo pares de Autocorrelacion
319 # if firstChannel == secondChannel:
327 # if firstChannel == secondChannel:
320 # pairsAutoCorr[firstChannel] = int(l)
328 # pairsAutoCorr[firstChannel] = int(l)
321 #
329 #
322 # pairsAutoCorr = pairsAutoCorr.astype(int)
330 # pairsAutoCorr = pairsAutoCorr.astype(int)
323 #
331 #
324 # pairsCrossCorr = range(len(pairsList))
332 # pairsCrossCorr = range(len(pairsList))
325 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
333 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
326 #
334 #
327 # return pairsAutoCorr, pairsCrossCorr
335 # return pairsAutoCorr, pairsCrossCorr
328
336
329 def __calculateTaus(self, data_acf, data_ccf, lagRange):
337 def __calculateTaus(self, data_acf, data_ccf, lagRange):
330
338
331 lag0 = data_acf.shape[1]/2
339 lag0 = data_acf.shape[1]/2
332 #Funcion de Autocorrelacion
340 #Funcion de Autocorrelacion
333 mean_acf = stats.nanmean(data_acf, axis = 0)
341 mean_acf = stats.nanmean(data_acf, axis = 0)
334
342
335 #Obtencion Indice de TauCross
343 #Obtencion Indice de TauCross
336 ind_ccf = data_ccf.argmax(axis = 1)
344 ind_ccf = data_ccf.argmax(axis = 1)
337 #Obtencion Indice de TauAuto
345 #Obtencion Indice de TauAuto
338 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
346 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
339 ccf_lag0 = data_ccf[:,lag0,:]
347 ccf_lag0 = data_ccf[:,lag0,:]
340
348
341 for i in range(ccf_lag0.shape[0]):
349 for i in range(ccf_lag0.shape[0]):
342 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
350 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
343
351
344 #Obtencion de TauCross y TauAuto
352 #Obtencion de TauCross y TauAuto
345 tau_ccf = lagRange[ind_ccf]
353 tau_ccf = lagRange[ind_ccf]
346 tau_acf = lagRange[ind_acf]
354 tau_acf = lagRange[ind_acf]
347
355
348 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
356 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
349
357
350 tau_ccf[Nan1,Nan2] = numpy.nan
358 tau_ccf[Nan1,Nan2] = numpy.nan
351 tau_acf[Nan1,Nan2] = numpy.nan
359 tau_acf[Nan1,Nan2] = numpy.nan
352 tau = numpy.vstack((tau_ccf,tau_acf))
360 tau = numpy.vstack((tau_ccf,tau_acf))
353
361
354 return tau
362 return tau
355
363
356 def __calculateLag1Phase(self, data, lagTRange):
364 def __calculateLag1Phase(self, data, lagTRange):
357 data1 = stats.nanmean(data, axis = 0)
365 data1 = stats.nanmean(data, axis = 0)
358 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
366 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
359
367
360 phase = numpy.angle(data1[lag1,:])
368 phase = numpy.angle(data1[lag1,:])
361
369
362 return phase
370 return phase
363
371
364 class SpectralFitting(Operation):
372 class SpectralFitting(Operation):
365 '''
373 '''
366 Function GetMoments()
374 Function GetMoments()
367
375
368 Input:
376 Input:
369 Output:
377 Output:
370 Variables modified:
378 Variables modified:
371 '''
379 '''
372
380
373 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
381 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
374
382
375
383
376 if path != None:
384 if path != None:
377 sys.path.append(path)
385 sys.path.append(path)
378 self.dataOut.library = importlib.import_module(file)
386 self.dataOut.library = importlib.import_module(file)
379
387
380 #To be inserted as a parameter
388 #To be inserted as a parameter
381 groupArray = numpy.array(groupList)
389 groupArray = numpy.array(groupList)
382 # groupArray = numpy.array([[0,1],[2,3]])
390 # groupArray = numpy.array([[0,1],[2,3]])
383 self.dataOut.groupList = groupArray
391 self.dataOut.groupList = groupArray
384
392
385 nGroups = groupArray.shape[0]
393 nGroups = groupArray.shape[0]
386 nChannels = self.dataIn.nChannels
394 nChannels = self.dataIn.nChannels
387 nHeights=self.dataIn.heightList.size
395 nHeights=self.dataIn.heightList.size
388
396
389 #Parameters Array
397 #Parameters Array
390 self.dataOut.data_param = None
398 self.dataOut.data_param = None
391
399
392 #Set constants
400 #Set constants
393 constants = self.dataOut.library.setConstants(self.dataIn)
401 constants = self.dataOut.library.setConstants(self.dataIn)
394 self.dataOut.constants = constants
402 self.dataOut.constants = constants
395 M = self.dataIn.normFactor
403 M = self.dataIn.normFactor
396 N = self.dataIn.nFFTPoints
404 N = self.dataIn.nFFTPoints
397 ippSeconds = self.dataIn.ippSeconds
405 ippSeconds = self.dataIn.ippSeconds
398 K = self.dataIn.nIncohInt
406 K = self.dataIn.nIncohInt
399 pairsArray = numpy.array(self.dataIn.pairsList)
407 pairsArray = numpy.array(self.dataIn.pairsList)
400
408
401 #List of possible combinations
409 #List of possible combinations
402 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
410 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
403 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
411 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
404
412
405 if getSNR:
413 if getSNR:
406 listChannels = groupArray.reshape((groupArray.size))
414 listChannels = groupArray.reshape((groupArray.size))
407 listChannels.sort()
415 listChannels.sort()
408 noise = self.dataIn.getNoise()
416 noise = self.dataIn.getNoise()
409 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
417 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
410
418
411 for i in range(nGroups):
419 for i in range(nGroups):
412 coord = groupArray[i,:]
420 coord = groupArray[i,:]
413
421
414 #Input data array
422 #Input data array
415 data = self.dataIn.data_spc[coord,:,:]/(M*N)
423 data = self.dataIn.data_spc[coord,:,:]/(M*N)
416 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
424 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
417
425
418 #Cross Spectra data array for Covariance Matrixes
426 #Cross Spectra data array for Covariance Matrixes
419 ind = 0
427 ind = 0
420 for pairs in listComb:
428 for pairs in listComb:
421 pairsSel = numpy.array([coord[x],coord[y]])
429 pairsSel = numpy.array([coord[x],coord[y]])
422 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
430 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
423 ind += 1
431 ind += 1
424 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
432 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
425 dataCross = dataCross**2/K
433 dataCross = dataCross**2/K
426
434
427 for h in range(nHeights):
435 for h in range(nHeights):
428 # print self.dataOut.heightList[h]
436 # print self.dataOut.heightList[h]
429
437
430 #Input
438 #Input
431 d = data[:,h]
439 d = data[:,h]
432
440
433 #Covariance Matrix
441 #Covariance Matrix
434 D = numpy.diag(d**2/K)
442 D = numpy.diag(d**2/K)
435 ind = 0
443 ind = 0
436 for pairs in listComb:
444 for pairs in listComb:
437 #Coordinates in Covariance Matrix
445 #Coordinates in Covariance Matrix
438 x = pairs[0]
446 x = pairs[0]
439 y = pairs[1]
447 y = pairs[1]
440 #Channel Index
448 #Channel Index
441 S12 = dataCross[ind,:,h]
449 S12 = dataCross[ind,:,h]
442 D12 = numpy.diag(S12)
450 D12 = numpy.diag(S12)
443 #Completing Covariance Matrix with Cross Spectras
451 #Completing Covariance Matrix with Cross Spectras
444 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
452 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
445 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
453 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
446 ind += 1
454 ind += 1
447 Dinv=numpy.linalg.inv(D)
455 Dinv=numpy.linalg.inv(D)
448 L=numpy.linalg.cholesky(Dinv)
456 L=numpy.linalg.cholesky(Dinv)
449 LT=L.T
457 LT=L.T
450
458
451 dp = numpy.dot(LT,d)
459 dp = numpy.dot(LT,d)
452
460
453 #Initial values
461 #Initial values
454 data_spc = self.dataIn.data_spc[coord,:,h]
462 data_spc = self.dataIn.data_spc[coord,:,h]
455
463
456 if (h>0)and(error1[3]<5):
464 if (h>0)and(error1[3]<5):
457 p0 = self.dataOut.data_param[i,:,h-1]
465 p0 = self.dataOut.data_param[i,:,h-1]
458 else:
466 else:
459 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
467 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
460
468
461 try:
469 try:
462 #Least Squares
470 #Least Squares
463 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
471 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
464 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
472 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
465 #Chi square error
473 #Chi square error
466 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
474 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
467 #Error with Jacobian
475 #Error with Jacobian
468 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
476 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
469 except:
477 except:
470 minp = p0*numpy.nan
478 minp = p0*numpy.nan
471 error0 = numpy.nan
479 error0 = numpy.nan
472 error1 = p0*numpy.nan
480 error1 = p0*numpy.nan
473
481
474 #Save
482 #Save
475 if self.dataOut.data_param is None:
483 if self.dataOut.data_param is None:
476 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
484 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
477 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
485 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
478
486
479 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
487 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
480 self.dataOut.data_param[i,:,h] = minp
488 self.dataOut.data_param[i,:,h] = minp
481 return
489 return
482
490
483 def __residFunction(self, p, dp, LT, constants):
491 def __residFunction(self, p, dp, LT, constants):
484
492
485 fm = self.dataOut.library.modelFunction(p, constants)
493 fm = self.dataOut.library.modelFunction(p, constants)
486 fmp=numpy.dot(LT,fm)
494 fmp=numpy.dot(LT,fm)
487
495
488 return dp-fmp
496 return dp-fmp
489
497
490 def __getSNR(self, z, noise):
498 def __getSNR(self, z, noise):
491
499
492 avg = numpy.average(z, axis=1)
500 avg = numpy.average(z, axis=1)
493 SNR = (avg.T-noise)/noise
501 SNR = (avg.T-noise)/noise
494 SNR = SNR.T
502 SNR = SNR.T
495 return SNR
503 return SNR
496
504
497 def __chisq(p,chindex,hindex):
505 def __chisq(p,chindex,hindex):
498 #similar to Resid but calculates CHI**2
506 #similar to Resid but calculates CHI**2
499 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
507 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
500 dp=numpy.dot(LT,d)
508 dp=numpy.dot(LT,d)
501 fmp=numpy.dot(LT,fm)
509 fmp=numpy.dot(LT,fm)
502 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
510 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
503 return chisq
511 return chisq
504
512
505 class WindProfiler(Operation):
513 class WindProfiler(Operation):
506
514
507 __isConfig = False
515 __isConfig = False
508
516
509 __initime = None
517 __initime = None
510 __lastdatatime = None
518 __lastdatatime = None
511 __integrationtime = None
519 __integrationtime = None
512
520
513 __buffer = None
521 __buffer = None
514
522
515 __dataReady = False
523 __dataReady = False
516
524
517 __firstdata = None
525 __firstdata = None
518
526
519 n = None
527 n = None
520
528
521 def __calculateCosDir(self, elev, azim):
529 def __calculateCosDir(self, elev, azim):
522 zen = (90 - elev)*numpy.pi/180
530 zen = (90 - elev)*numpy.pi/180
523 azim = azim*numpy.pi/180
531 azim = azim*numpy.pi/180
524 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
532 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
525 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
533 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
526
534
527 signX = numpy.sign(numpy.cos(azim))
535 signX = numpy.sign(numpy.cos(azim))
528 signY = numpy.sign(numpy.sin(azim))
536 signY = numpy.sign(numpy.sin(azim))
529
537
530 cosDirX = numpy.copysign(cosDirX, signX)
538 cosDirX = numpy.copysign(cosDirX, signX)
531 cosDirY = numpy.copysign(cosDirY, signY)
539 cosDirY = numpy.copysign(cosDirY, signY)
532 return cosDirX, cosDirY
540 return cosDirX, cosDirY
533
541
534 def __calculateAngles(self, theta_x, theta_y, azimuth):
542 def __calculateAngles(self, theta_x, theta_y, azimuth):
535
543
536 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
544 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
537 zenith_arr = numpy.arccos(dir_cosw)
545 zenith_arr = numpy.arccos(dir_cosw)
538 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
546 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
539
547
540 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
548 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
541 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
549 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
542
550
543 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
551 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
544
552
545 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
553 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
546
554
547 #
555 #
548 if horOnly:
556 if horOnly:
549 A = numpy.c_[dir_cosu,dir_cosv]
557 A = numpy.c_[dir_cosu,dir_cosv]
550 else:
558 else:
551 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
559 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
552 A = numpy.asmatrix(A)
560 A = numpy.asmatrix(A)
553 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
561 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
554
562
555 return A1
563 return A1
556
564
557 def __correctValues(self, heiRang, phi, velRadial, SNR):
565 def __correctValues(self, heiRang, phi, velRadial, SNR):
558 listPhi = phi.tolist()
566 listPhi = phi.tolist()
559 maxid = listPhi.index(max(listPhi))
567 maxid = listPhi.index(max(listPhi))
560 minid = listPhi.index(min(listPhi))
568 minid = listPhi.index(min(listPhi))
561
569
562 rango = range(len(phi))
570 rango = range(len(phi))
563 # rango = numpy.delete(rango,maxid)
571 # rango = numpy.delete(rango,maxid)
564
572
565 heiRang1 = heiRang*math.cos(phi[maxid])
573 heiRang1 = heiRang*math.cos(phi[maxid])
566 heiRangAux = heiRang*math.cos(phi[minid])
574 heiRangAux = heiRang*math.cos(phi[minid])
567 indOut = (heiRang1 < heiRangAux[0]).nonzero()
575 indOut = (heiRang1 < heiRangAux[0]).nonzero()
568 heiRang1 = numpy.delete(heiRang1,indOut)
576 heiRang1 = numpy.delete(heiRang1,indOut)
569
577
570 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
578 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
571 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
579 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
572
580
573 for i in rango:
581 for i in rango:
574 x = heiRang*math.cos(phi[i])
582 x = heiRang*math.cos(phi[i])
575 y1 = velRadial[i,:]
583 y1 = velRadial[i,:]
576 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
584 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
577
585
578 x1 = heiRang1
586 x1 = heiRang1
579 y11 = f1(x1)
587 y11 = f1(x1)
580
588
581 y2 = SNR[i,:]
589 y2 = SNR[i,:]
582 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
590 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
583 y21 = f2(x1)
591 y21 = f2(x1)
584
592
585 velRadial1[i,:] = y11
593 velRadial1[i,:] = y11
586 SNR1[i,:] = y21
594 SNR1[i,:] = y21
587
595
588 return heiRang1, velRadial1, SNR1
596 return heiRang1, velRadial1, SNR1
589
597
590 def __calculateVelUVW(self, A, velRadial):
598 def __calculateVelUVW(self, A, velRadial):
591
599
592 #Operacion Matricial
600 #Operacion Matricial
593 # velUVW = numpy.zeros((velRadial.shape[1],3))
601 # velUVW = numpy.zeros((velRadial.shape[1],3))
594 # for ind in range(velRadial.shape[1]):
602 # for ind in range(velRadial.shape[1]):
595 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
603 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
596 # velUVW = velUVW.transpose()
604 # velUVW = velUVW.transpose()
597 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
605 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
598 velUVW[:,:] = numpy.dot(A,velRadial)
606 velUVW[:,:] = numpy.dot(A,velRadial)
599
607
600
608
601 return velUVW
609 return velUVW
602
610
603 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
611 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
604
612
605 def techniqueDBS(self, kwargs):
613 def techniqueDBS(self, kwargs):
606 """
614 """
607 Function that implements Doppler Beam Swinging (DBS) technique.
615 Function that implements Doppler Beam Swinging (DBS) technique.
608
616
609 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
617 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
610 Direction correction (if necessary), Ranges and SNR
618 Direction correction (if necessary), Ranges and SNR
611
619
612 Output: Winds estimation (Zonal, Meridional and Vertical)
620 Output: Winds estimation (Zonal, Meridional and Vertical)
613
621
614 Parameters affected: Winds, height range, SNR
622 Parameters affected: Winds, height range, SNR
615 """
623 """
616 velRadial0 = kwargs['velRadial']
624 velRadial0 = kwargs['velRadial']
617 heiRang = kwargs['heightList']
625 heiRang = kwargs['heightList']
618 SNR0 = kwargs['SNR']
626 SNR0 = kwargs['SNR']
619
627
620 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
628 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
621 theta_x = numpy.array(kwargs['dirCosx'])
629 theta_x = numpy.array(kwargs['dirCosx'])
622 theta_y = numpy.array(kwargs['dirCosy'])
630 theta_y = numpy.array(kwargs['dirCosy'])
623 else:
631 else:
624 elev = numpy.array(kwargs['elevation'])
632 elev = numpy.array(kwargs['elevation'])
625 azim = numpy.array(kwargs['azimuth'])
633 azim = numpy.array(kwargs['azimuth'])
626 theta_x, theta_y = self.__calculateCosDir(elev, azim)
634 theta_x, theta_y = self.__calculateCosDir(elev, azim)
627 azimuth = kwargs['correctAzimuth']
635 azimuth = kwargs['correctAzimuth']
628 if kwargs.has_key('horizontalOnly'):
636 if kwargs.has_key('horizontalOnly'):
629 horizontalOnly = kwargs['horizontalOnly']
637 horizontalOnly = kwargs['horizontalOnly']
630 else: horizontalOnly = False
638 else: horizontalOnly = False
631 if kwargs.has_key('correctFactor'):
639 if kwargs.has_key('correctFactor'):
632 correctFactor = kwargs['correctFactor']
640 correctFactor = kwargs['correctFactor']
633 else: correctFactor = 1
641 else: correctFactor = 1
634 if kwargs.has_key('channelList'):
642 if kwargs.has_key('channelList'):
635 channelList = kwargs['channelList']
643 channelList = kwargs['channelList']
636 if len(channelList) == 2:
644 if len(channelList) == 2:
637 horizontalOnly = True
645 horizontalOnly = True
638 arrayChannel = numpy.array(channelList)
646 arrayChannel = numpy.array(channelList)
639 param = param[arrayChannel,:,:]
647 param = param[arrayChannel,:,:]
640 theta_x = theta_x[arrayChannel]
648 theta_x = theta_x[arrayChannel]
641 theta_y = theta_y[arrayChannel]
649 theta_y = theta_y[arrayChannel]
642
650
643 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
651 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
644 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
652 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
645 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
653 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
646
654
647 #Calculo de Componentes de la velocidad con DBS
655 #Calculo de Componentes de la velocidad con DBS
648 winds = self.__calculateVelUVW(A,velRadial1)
656 winds = self.__calculateVelUVW(A,velRadial1)
649
657
650 return winds, heiRang1, SNR1
658 return winds, heiRang1, SNR1
651
659
652 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
660 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
653
661
654 nPairs = len(pairs_ccf)
662 nPairs = len(pairs_ccf)
655 posx = numpy.asarray(posx)
663 posx = numpy.asarray(posx)
656 posy = numpy.asarray(posy)
664 posy = numpy.asarray(posy)
657
665
658 #Rotacion Inversa para alinear con el azimuth
666 #Rotacion Inversa para alinear con el azimuth
659 if azimuth!= None:
667 if azimuth!= None:
660 azimuth = azimuth*math.pi/180
668 azimuth = azimuth*math.pi/180
661 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
669 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
662 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
670 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
663 else:
671 else:
664 posx1 = posx
672 posx1 = posx
665 posy1 = posy
673 posy1 = posy
666
674
667 #Calculo de Distancias
675 #Calculo de Distancias
668 distx = numpy.zeros(nPairs)
676 distx = numpy.zeros(nPairs)
669 disty = numpy.zeros(nPairs)
677 disty = numpy.zeros(nPairs)
670 dist = numpy.zeros(nPairs)
678 dist = numpy.zeros(nPairs)
671 ang = numpy.zeros(nPairs)
679 ang = numpy.zeros(nPairs)
672
680
673 for i in range(nPairs):
681 for i in range(nPairs):
674 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
682 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
675 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
683 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
676 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
684 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
677 ang[i] = numpy.arctan2(disty[i],distx[i])
685 ang[i] = numpy.arctan2(disty[i],distx[i])
678
686
679 return distx, disty, dist, ang
687 return distx, disty, dist, ang
680 #Calculo de Matrices
688 #Calculo de Matrices
681 # nPairs = len(pairs)
689 # nPairs = len(pairs)
682 # ang1 = numpy.zeros((nPairs, 2, 1))
690 # ang1 = numpy.zeros((nPairs, 2, 1))
683 # dist1 = numpy.zeros((nPairs, 2, 1))
691 # dist1 = numpy.zeros((nPairs, 2, 1))
684 #
692 #
685 # for j in range(nPairs):
693 # for j in range(nPairs):
686 # dist1[j,0,0] = dist[pairs[j][0]]
694 # dist1[j,0,0] = dist[pairs[j][0]]
687 # dist1[j,1,0] = dist[pairs[j][1]]
695 # dist1[j,1,0] = dist[pairs[j][1]]
688 # ang1[j,0,0] = ang[pairs[j][0]]
696 # ang1[j,0,0] = ang[pairs[j][0]]
689 # ang1[j,1,0] = ang[pairs[j][1]]
697 # ang1[j,1,0] = ang[pairs[j][1]]
690 #
698 #
691 # return distx,disty, dist1,ang1
699 # return distx,disty, dist1,ang1
692
700
693
701
694 def __calculateVelVer(self, phase, lagTRange, _lambda):
702 def __calculateVelVer(self, phase, lagTRange, _lambda):
695
703
696 Ts = lagTRange[1] - lagTRange[0]
704 Ts = lagTRange[1] - lagTRange[0]
697 velW = -_lambda*phase/(4*math.pi*Ts)
705 velW = -_lambda*phase/(4*math.pi*Ts)
698
706
699 return velW
707 return velW
700
708
701 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
709 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
702 nPairs = tau1.shape[0]
710 nPairs = tau1.shape[0]
703 nHeights = tau1.shape[1]
711 nHeights = tau1.shape[1]
704 vel = numpy.zeros((nPairs,3,nHeights))
712 vel = numpy.zeros((nPairs,3,nHeights))
705 dist1 = numpy.reshape(dist, (dist.size,1))
713 dist1 = numpy.reshape(dist, (dist.size,1))
706
714
707 angCos = numpy.cos(ang)
715 angCos = numpy.cos(ang)
708 angSin = numpy.sin(ang)
716 angSin = numpy.sin(ang)
709
717
710 vel0 = dist1*tau1/(2*tau2**2)
718 vel0 = dist1*tau1/(2*tau2**2)
711 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
719 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
712 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
720 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
713
721
714 ind = numpy.where(numpy.isinf(vel))
722 ind = numpy.where(numpy.isinf(vel))
715 vel[ind] = numpy.nan
723 vel[ind] = numpy.nan
716
724
717 return vel
725 return vel
718
726
719 # def __getPairsAutoCorr(self, pairsList, nChannels):
727 # def __getPairsAutoCorr(self, pairsList, nChannels):
720 #
728 #
721 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
729 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
722 #
730 #
723 # for l in range(len(pairsList)):
731 # for l in range(len(pairsList)):
724 # firstChannel = pairsList[l][0]
732 # firstChannel = pairsList[l][0]
725 # secondChannel = pairsList[l][1]
733 # secondChannel = pairsList[l][1]
726 #
734 #
727 # #Obteniendo pares de Autocorrelacion
735 # #Obteniendo pares de Autocorrelacion
728 # if firstChannel == secondChannel:
736 # if firstChannel == secondChannel:
729 # pairsAutoCorr[firstChannel] = int(l)
737 # pairsAutoCorr[firstChannel] = int(l)
730 #
738 #
731 # pairsAutoCorr = pairsAutoCorr.astype(int)
739 # pairsAutoCorr = pairsAutoCorr.astype(int)
732 #
740 #
733 # pairsCrossCorr = range(len(pairsList))
741 # pairsCrossCorr = range(len(pairsList))
734 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
742 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
735 #
743 #
736 # return pairsAutoCorr, pairsCrossCorr
744 # return pairsAutoCorr, pairsCrossCorr
737
745
738 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
746 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
739 def techniqueSA(self, kwargs):
747 def techniqueSA(self, kwargs):
740
748
741 """
749 """
742 Function that implements Spaced Antenna (SA) technique.
750 Function that implements Spaced Antenna (SA) technique.
743
751
744 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
752 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
745 Direction correction (if necessary), Ranges and SNR
753 Direction correction (if necessary), Ranges and SNR
746
754
747 Output: Winds estimation (Zonal, Meridional and Vertical)
755 Output: Winds estimation (Zonal, Meridional and Vertical)
748
756
749 Parameters affected: Winds
757 Parameters affected: Winds
750 """
758 """
751 position_x = kwargs['positionX']
759 position_x = kwargs['positionX']
752 position_y = kwargs['positionY']
760 position_y = kwargs['positionY']
753 azimuth = kwargs['azimuth']
761 azimuth = kwargs['azimuth']
754
762
755 if kwargs.has_key('correctFactor'):
763 if kwargs.has_key('correctFactor'):
756 correctFactor = kwargs['correctFactor']
764 correctFactor = kwargs['correctFactor']
757 else:
765 else:
758 correctFactor = 1
766 correctFactor = 1
759
767
760 groupList = kwargs['groupList']
768 groupList = kwargs['groupList']
761 pairs_ccf = groupList[1]
769 pairs_ccf = groupList[1]
762 tau = kwargs['tau']
770 tau = kwargs['tau']
763 _lambda = kwargs['_lambda']
771 _lambda = kwargs['_lambda']
764
772
765 #Cross Correlation pairs obtained
773 #Cross Correlation pairs obtained
766 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
774 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
767 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
775 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
768 # pairsSelArray = numpy.array(pairsSelected)
776 # pairsSelArray = numpy.array(pairsSelected)
769 # pairs = []
777 # pairs = []
770 #
778 #
771 # #Wind estimation pairs obtained
779 # #Wind estimation pairs obtained
772 # for i in range(pairsSelArray.shape[0]/2):
780 # for i in range(pairsSelArray.shape[0]/2):
773 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
781 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
774 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
782 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
775 # pairs.append((ind1,ind2))
783 # pairs.append((ind1,ind2))
776
784
777 indtau = tau.shape[0]/2
785 indtau = tau.shape[0]/2
778 tau1 = tau[:indtau,:]
786 tau1 = tau[:indtau,:]
779 tau2 = tau[indtau:-1,:]
787 tau2 = tau[indtau:-1,:]
780 # tau1 = tau1[pairs,:]
788 # tau1 = tau1[pairs,:]
781 # tau2 = tau2[pairs,:]
789 # tau2 = tau2[pairs,:]
782 phase1 = tau[-1,:]
790 phase1 = tau[-1,:]
783
791
784 #---------------------------------------------------------------------
792 #---------------------------------------------------------------------
785 #Metodo Directo
793 #Metodo Directo
786 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
794 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
787 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
795 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
788 winds = stats.nanmean(winds, axis=0)
796 winds = stats.nanmean(winds, axis=0)
789 #---------------------------------------------------------------------
797 #---------------------------------------------------------------------
790 #Metodo General
798 #Metodo General
791 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
799 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
792 # #Calculo Coeficientes de Funcion de Correlacion
800 # #Calculo Coeficientes de Funcion de Correlacion
793 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
801 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
794 # #Calculo de Velocidades
802 # #Calculo de Velocidades
795 # winds = self.calculateVelUV(F,G,A,B,H)
803 # winds = self.calculateVelUV(F,G,A,B,H)
796
804
797 #---------------------------------------------------------------------
805 #---------------------------------------------------------------------
798 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
806 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
799 winds = correctFactor*winds
807 winds = correctFactor*winds
800 return winds
808 return winds
801
809
802 def __checkTime(self, currentTime, paramInterval, outputInterval):
810 def __checkTime(self, currentTime, paramInterval, outputInterval):
803
811
804 dataTime = currentTime + paramInterval
812 dataTime = currentTime + paramInterval
805 deltaTime = dataTime - self.__initime
813 deltaTime = dataTime - self.__initime
806
814
807 if deltaTime >= outputInterval or deltaTime < 0:
815 if deltaTime >= outputInterval or deltaTime < 0:
808 self.__dataReady = True
816 self.__dataReady = True
809 return
817 return
810
818
811 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax, binkm=2):
819 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax, binkm=2):
812 '''
820 '''
813 Function that implements winds estimation technique with detected meteors.
821 Function that implements winds estimation technique with detected meteors.
814
822
815 Input: Detected meteors, Minimum meteor quantity to wind estimation
823 Input: Detected meteors, Minimum meteor quantity to wind estimation
816
824
817 Output: Winds estimation (Zonal and Meridional)
825 Output: Winds estimation (Zonal and Meridional)
818
826
819 Parameters affected: Winds
827 Parameters affected: Winds
820 '''
828 '''
821 # print arrayMeteor.shape
829 # print arrayMeteor.shape
822 #Settings
830 #Settings
823 nInt = (heightMax - heightMin)/binkm
831 nInt = (heightMax - heightMin)/binkm
824 # print nInt
832 # print nInt
825 nInt = int(nInt)
833 nInt = int(nInt)
826 # print nInt
834 # print nInt
827 winds = numpy.zeros((2,nInt))*numpy.nan
835 winds = numpy.zeros((2,nInt))*numpy.nan
828
836
829 #Filter errors
837 #Filter errors
830 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
838 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
831 finalMeteor = arrayMeteor[error,:]
839 finalMeteor = arrayMeteor[error,:]
832
840
833 #Meteor Histogram
841 #Meteor Histogram
834 finalHeights = finalMeteor[:,2]
842 finalHeights = finalMeteor[:,2]
835 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
843 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
836 nMeteorsPerI = hist[0]
844 nMeteorsPerI = hist[0]
837 heightPerI = hist[1]
845 heightPerI = hist[1]
838
846
839 #Sort of meteors
847 #Sort of meteors
840 indSort = finalHeights.argsort()
848 indSort = finalHeights.argsort()
841 finalMeteor2 = finalMeteor[indSort,:]
849 finalMeteor2 = finalMeteor[indSort,:]
842
850
843 # Calculating winds
851 # Calculating winds
844 ind1 = 0
852 ind1 = 0
845 ind2 = 0
853 ind2 = 0
846
854
847 for i in range(nInt):
855 for i in range(nInt):
848 nMet = nMeteorsPerI[i]
856 nMet = nMeteorsPerI[i]
849 ind1 = ind2
857 ind1 = ind2
850 ind2 = ind1 + nMet
858 ind2 = ind1 + nMet
851
859
852 meteorAux = finalMeteor2[ind1:ind2,:]
860 meteorAux = finalMeteor2[ind1:ind2,:]
853
861
854 if meteorAux.shape[0] >= meteorThresh:
862 if meteorAux.shape[0] >= meteorThresh:
855 vel = meteorAux[:, 6]
863 vel = meteorAux[:, 6]
856 zen = meteorAux[:, 4]*numpy.pi/180
864 zen = meteorAux[:, 4]*numpy.pi/180
857 azim = meteorAux[:, 3]*numpy.pi/180
865 azim = meteorAux[:, 3]*numpy.pi/180
858
866
859 n = numpy.cos(zen)
867 n = numpy.cos(zen)
860 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
868 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
861 # l = m*numpy.tan(azim)
869 # l = m*numpy.tan(azim)
862 l = numpy.sin(zen)*numpy.sin(azim)
870 l = numpy.sin(zen)*numpy.sin(azim)
863 m = numpy.sin(zen)*numpy.cos(azim)
871 m = numpy.sin(zen)*numpy.cos(azim)
864
872
865 A = numpy.vstack((l, m)).transpose()
873 A = numpy.vstack((l, m)).transpose()
866 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
874 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
867 windsAux = numpy.dot(A1, vel)
875 windsAux = numpy.dot(A1, vel)
868
876
869 winds[0,i] = windsAux[0]
877 winds[0,i] = windsAux[0]
870 winds[1,i] = windsAux[1]
878 winds[1,i] = windsAux[1]
871
879
872 return winds, heightPerI[:-1]
880 return winds, heightPerI[:-1]
873
881
874 def techniqueNSM_SA(self, **kwargs):
882 def techniqueNSM_SA(self, **kwargs):
875 metArray = kwargs['metArray']
883 metArray = kwargs['metArray']
876 heightList = kwargs['heightList']
884 heightList = kwargs['heightList']
877 timeList = kwargs['timeList']
885 timeList = kwargs['timeList']
878
886
879 rx_location = kwargs['rx_location']
887 rx_location = kwargs['rx_location']
880 groupList = kwargs['groupList']
888 groupList = kwargs['groupList']
881 azimuth = kwargs['azimuth']
889 azimuth = kwargs['azimuth']
882 dfactor = kwargs['dfactor']
890 dfactor = kwargs['dfactor']
883 k = kwargs['k']
891 k = kwargs['k']
884
892
885 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
893 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
886 d = dist*dfactor
894 d = dist*dfactor
887 #Phase calculation
895 #Phase calculation
888 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
896 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
889
897
890 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
898 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
891
899
892 velEst = numpy.zeros((heightList.size,2))*numpy.nan
900 velEst = numpy.zeros((heightList.size,2))*numpy.nan
893 azimuth1 = azimuth1*numpy.pi/180
901 azimuth1 = azimuth1*numpy.pi/180
894
902
895 for i in range(heightList.size):
903 for i in range(heightList.size):
896 h = heightList[i]
904 h = heightList[i]
897 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
905 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
898 metHeight = metArray1[indH,:]
906 metHeight = metArray1[indH,:]
899 if metHeight.shape[0] >= 2:
907 if metHeight.shape[0] >= 2:
900 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
908 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
901 iazim = metHeight[:,1].astype(int)
909 iazim = metHeight[:,1].astype(int)
902 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
910 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
903 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
911 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
904 A = numpy.asmatrix(A)
912 A = numpy.asmatrix(A)
905 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
913 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
906 velHor = numpy.dot(A1,velAux)
914 velHor = numpy.dot(A1,velAux)
907
915
908 velEst[i,:] = numpy.squeeze(velHor)
916 velEst[i,:] = numpy.squeeze(velHor)
909 return velEst
917 return velEst
910
918
911 def __getPhaseSlope(self, metArray, heightList, timeList):
919 def __getPhaseSlope(self, metArray, heightList, timeList):
912 meteorList = []
920 meteorList = []
913 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
921 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
914 #Putting back together the meteor matrix
922 #Putting back together the meteor matrix
915 utctime = metArray[:,0]
923 utctime = metArray[:,0]
916 uniqueTime = numpy.unique(utctime)
924 uniqueTime = numpy.unique(utctime)
917
925
918 phaseDerThresh = 0.5
926 phaseDerThresh = 0.5
919 ippSeconds = timeList[1] - timeList[0]
927 ippSeconds = timeList[1] - timeList[0]
920 sec = numpy.where(timeList>1)[0][0]
928 sec = numpy.where(timeList>1)[0][0]
921 nPairs = metArray.shape[1] - 6
929 nPairs = metArray.shape[1] - 6
922 nHeights = len(heightList)
930 nHeights = len(heightList)
923
931
924 for t in uniqueTime:
932 for t in uniqueTime:
925 metArray1 = metArray[utctime==t,:]
933 metArray1 = metArray[utctime==t,:]
926 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
934 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
927 tmet = metArray1[:,1].astype(int)
935 tmet = metArray1[:,1].astype(int)
928 hmet = metArray1[:,2].astype(int)
936 hmet = metArray1[:,2].astype(int)
929
937
930 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
938 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
931 metPhase[:,:] = numpy.nan
939 metPhase[:,:] = numpy.nan
932 metPhase[:,hmet,tmet] = metArray1[:,6:].T
940 metPhase[:,hmet,tmet] = metArray1[:,6:].T
933
941
934 #Delete short trails
942 #Delete short trails
935 metBool = ~numpy.isnan(metPhase[0,:,:])
943 metBool = ~numpy.isnan(metPhase[0,:,:])
936 heightVect = numpy.sum(metBool, axis = 1)
944 heightVect = numpy.sum(metBool, axis = 1)
937 metBool[heightVect<sec,:] = False
945 metBool[heightVect<sec,:] = False
938 metPhase[:,heightVect<sec,:] = numpy.nan
946 metPhase[:,heightVect<sec,:] = numpy.nan
939
947
940 #Derivative
948 #Derivative
941 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
949 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
942 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
950 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
943 metPhase[phDerAux] = numpy.nan
951 metPhase[phDerAux] = numpy.nan
944
952
945 #--------------------------METEOR DETECTION -----------------------------------------
953 #--------------------------METEOR DETECTION -----------------------------------------
946 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
954 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
947
955
948 for p in numpy.arange(nPairs):
956 for p in numpy.arange(nPairs):
949 phase = metPhase[p,:,:]
957 phase = metPhase[p,:,:]
950 phDer = metDer[p,:,:]
958 phDer = metDer[p,:,:]
951
959
952 for h in indMet:
960 for h in indMet:
953 height = heightList[h]
961 height = heightList[h]
954 phase1 = phase[h,:] #82
962 phase1 = phase[h,:] #82
955 phDer1 = phDer[h,:]
963 phDer1 = phDer[h,:]
956
964
957 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
965 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
958
966
959 indValid = numpy.where(~numpy.isnan(phase1))[0]
967 indValid = numpy.where(~numpy.isnan(phase1))[0]
960 initMet = indValid[0]
968 initMet = indValid[0]
961 endMet = 0
969 endMet = 0
962
970
963 for i in range(len(indValid)-1):
971 for i in range(len(indValid)-1):
964
972
965 #Time difference
973 #Time difference
966 inow = indValid[i]
974 inow = indValid[i]
967 inext = indValid[i+1]
975 inext = indValid[i+1]
968 idiff = inext - inow
976 idiff = inext - inow
969 #Phase difference
977 #Phase difference
970 phDiff = numpy.abs(phase1[inext] - phase1[inow])
978 phDiff = numpy.abs(phase1[inext] - phase1[inow])
971
979
972 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
980 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
973 sizeTrail = inow - initMet + 1
981 sizeTrail = inow - initMet + 1
974 if sizeTrail>3*sec: #Too short meteors
982 if sizeTrail>3*sec: #Too short meteors
975 x = numpy.arange(initMet,inow+1)*ippSeconds
983 x = numpy.arange(initMet,inow+1)*ippSeconds
976 y = phase1[initMet:inow+1]
984 y = phase1[initMet:inow+1]
977 ynnan = ~numpy.isnan(y)
985 ynnan = ~numpy.isnan(y)
978 x = x[ynnan]
986 x = x[ynnan]
979 y = y[ynnan]
987 y = y[ynnan]
980 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
988 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
981 ylin = x*slope + intercept
989 ylin = x*slope + intercept
982 rsq = r_value**2
990 rsq = r_value**2
983 if rsq > 0.5:
991 if rsq > 0.5:
984 vel = slope#*height*1000/(k*d)
992 vel = slope#*height*1000/(k*d)
985 estAux = numpy.array([utctime,p,height, vel, rsq])
993 estAux = numpy.array([utctime,p,height, vel, rsq])
986 meteorList.append(estAux)
994 meteorList.append(estAux)
987 initMet = inext
995 initMet = inext
988 metArray2 = numpy.array(meteorList)
996 metArray2 = numpy.array(meteorList)
989
997
990 return metArray2
998 return metArray2
991
999
992 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
1000 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
993
1001
994 azimuth1 = numpy.zeros(len(pairslist))
1002 azimuth1 = numpy.zeros(len(pairslist))
995 dist = numpy.zeros(len(pairslist))
1003 dist = numpy.zeros(len(pairslist))
996
1004
997 for i in range(len(rx_location)):
1005 for i in range(len(rx_location)):
998 ch0 = pairslist[i][0]
1006 ch0 = pairslist[i][0]
999 ch1 = pairslist[i][1]
1007 ch1 = pairslist[i][1]
1000
1008
1001 diffX = rx_location[ch0][0] - rx_location[ch1][0]
1009 diffX = rx_location[ch0][0] - rx_location[ch1][0]
1002 diffY = rx_location[ch0][1] - rx_location[ch1][1]
1010 diffY = rx_location[ch0][1] - rx_location[ch1][1]
1003 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
1011 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
1004 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
1012 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
1005
1013
1006 azimuth1 -= azimuth0
1014 azimuth1 -= azimuth0
1007 return azimuth1, dist
1015 return azimuth1, dist
1008
1016
1009 def techniqueNSM_DBS(self, **kwargs):
1017 def techniqueNSM_DBS(self, **kwargs):
1010 metArray = kwargs['metArray']
1018 metArray = kwargs['metArray']
1011 heightList = kwargs['heightList']
1019 heightList = kwargs['heightList']
1012 timeList = kwargs['timeList']
1020 timeList = kwargs['timeList']
1013 zenithList = kwargs['zenithList']
1021 zenithList = kwargs['zenithList']
1014 nChan = numpy.max(cmet) + 1
1022 nChan = numpy.max(cmet) + 1
1015 nHeights = len(heightList)
1023 nHeights = len(heightList)
1016
1024
1017 utctime = metArray[:,0]
1025 utctime = metArray[:,0]
1018 cmet = metArray[:,1]
1026 cmet = metArray[:,1]
1019 hmet = metArray1[:,3].astype(int)
1027 hmet = metArray1[:,3].astype(int)
1020 h1met = heightList[hmet]*zenithList[cmet]
1028 h1met = heightList[hmet]*zenithList[cmet]
1021 vmet = metArray1[:,5]
1029 vmet = metArray1[:,5]
1022
1030
1023 for i in range(nHeights - 1):
1031 for i in range(nHeights - 1):
1024 hmin = heightList[i]
1032 hmin = heightList[i]
1025 hmax = heightList[i + 1]
1033 hmax = heightList[i + 1]
1026
1034
1027 vthisH = vmet[(h1met>=hmin) & (h1met<hmax)]
1035 vthisH = vmet[(h1met>=hmin) & (h1met<hmax)]
1028
1036
1029
1037
1030
1038
1031 return data_output
1039 return data_output
1032
1040
1033 def run(self, dataOut, technique, **kwargs):
1041 def run(self, dataOut, technique, **kwargs):
1034
1042
1035 param = dataOut.data_param
1043 param = dataOut.data_param
1036 if dataOut.abscissaList != None:
1044 if dataOut.abscissaList != None:
1037 absc = dataOut.abscissaList[:-1]
1045 absc = dataOut.abscissaList[:-1]
1038 noise = dataOut.noise
1046 noise = dataOut.noise
1039 heightList = dataOut.heightList
1047 heightList = dataOut.heightList
1040 SNR = dataOut.data_SNR
1048 SNR = dataOut.data_SNR
1041
1049
1042 if technique == 'DBS':
1050 if technique == 'DBS':
1043
1051
1044 kwargs['velRadial'] = param[:,1,:] #Radial velocity
1052 kwargs['velRadial'] = param[:,1,:] #Radial velocity
1045 kwargs['heightList'] = heightList
1053 kwargs['heightList'] = heightList
1046 kwargs['SNR'] = SNR
1054 kwargs['SNR'] = SNR
1047
1055
1048 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
1056 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
1049 dataOut.utctimeInit = dataOut.utctime
1057 dataOut.utctimeInit = dataOut.utctime
1050 dataOut.outputInterval = dataOut.paramInterval
1058 dataOut.outputInterval = dataOut.paramInterval
1051
1059
1052 elif technique == 'SA':
1060 elif technique == 'SA':
1053
1061
1054 #Parameters
1062 #Parameters
1055 # position_x = kwargs['positionX']
1063 # position_x = kwargs['positionX']
1056 # position_y = kwargs['positionY']
1064 # position_y = kwargs['positionY']
1057 # azimuth = kwargs['azimuth']
1065 # azimuth = kwargs['azimuth']
1058 #
1066 #
1059 # if kwargs.has_key('crosspairsList'):
1067 # if kwargs.has_key('crosspairsList'):
1060 # pairs = kwargs['crosspairsList']
1068 # pairs = kwargs['crosspairsList']
1061 # else:
1069 # else:
1062 # pairs = None
1070 # pairs = None
1063 #
1071 #
1064 # if kwargs.has_key('correctFactor'):
1072 # if kwargs.has_key('correctFactor'):
1065 # correctFactor = kwargs['correctFactor']
1073 # correctFactor = kwargs['correctFactor']
1066 # else:
1074 # else:
1067 # correctFactor = 1
1075 # correctFactor = 1
1068
1076
1069 # tau = dataOut.data_param
1077 # tau = dataOut.data_param
1070 # _lambda = dataOut.C/dataOut.frequency
1078 # _lambda = dataOut.C/dataOut.frequency
1071 # pairsList = dataOut.groupList
1079 # pairsList = dataOut.groupList
1072 # nChannels = dataOut.nChannels
1080 # nChannels = dataOut.nChannels
1073
1081
1074 kwargs['groupList'] = dataOut.groupList
1082 kwargs['groupList'] = dataOut.groupList
1075 kwargs['tau'] = dataOut.data_param
1083 kwargs['tau'] = dataOut.data_param
1076 kwargs['_lambda'] = dataOut.C/dataOut.frequency
1084 kwargs['_lambda'] = dataOut.C/dataOut.frequency
1077 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1085 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1078 dataOut.data_output = self.techniqueSA(kwargs)
1086 dataOut.data_output = self.techniqueSA(kwargs)
1079 dataOut.utctimeInit = dataOut.utctime
1087 dataOut.utctimeInit = dataOut.utctime
1080 dataOut.outputInterval = dataOut.timeInterval
1088 dataOut.outputInterval = dataOut.timeInterval
1081
1089
1082 elif technique == 'Meteors':
1090 elif technique == 'Meteors':
1083 dataOut.flagNoData = True
1091 dataOut.flagNoData = True
1084 self.__dataReady = False
1092 self.__dataReady = False
1085
1093
1086 if kwargs.has_key('nHours'):
1094 if kwargs.has_key('nHours'):
1087 nHours = kwargs['nHours']
1095 nHours = kwargs['nHours']
1088 else:
1096 else:
1089 nHours = 1
1097 nHours = 1
1090
1098
1091 if kwargs.has_key('meteorsPerBin'):
1099 if kwargs.has_key('meteorsPerBin'):
1092 meteorThresh = kwargs['meteorsPerBin']
1100 meteorThresh = kwargs['meteorsPerBin']
1093 else:
1101 else:
1094 meteorThresh = 6
1102 meteorThresh = 6
1095
1103
1096 if kwargs.has_key('hmin'):
1104 if kwargs.has_key('hmin'):
1097 hmin = kwargs['hmin']
1105 hmin = kwargs['hmin']
1098 else: hmin = 70
1106 else: hmin = 70
1099 if kwargs.has_key('hmax'):
1107 if kwargs.has_key('hmax'):
1100 hmax = kwargs['hmax']
1108 hmax = kwargs['hmax']
1101 else: hmax = 110
1109 else: hmax = 110
1102
1110
1103 if kwargs.has_key('BinKm'):
1111 if kwargs.has_key('BinKm'):
1104 binkm = kwargs['BinKm']
1112 binkm = kwargs['BinKm']
1105 else:
1113 else:
1106 binkm = 2
1114 binkm = 2
1107
1115
1108 dataOut.outputInterval = nHours*3600
1116 dataOut.outputInterval = nHours*3600
1109
1117
1110 if self.__isConfig == False:
1118 if self.__isConfig == False:
1111 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1119 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1112 #Get Initial LTC time
1120 #Get Initial LTC time
1113 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1121 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1114 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1122 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1115
1123
1116 self.__isConfig = True
1124 self.__isConfig = True
1117
1125
1118 if self.__buffer is None:
1126 if self.__buffer is None:
1119 self.__buffer = dataOut.data_param
1127 self.__buffer = dataOut.data_param
1120 self.__firstdata = copy.copy(dataOut)
1128 self.__firstdata = copy.copy(dataOut)
1121
1129
1122 else:
1130 else:
1123 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1131 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1124
1132
1125 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1133 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1126
1134
1127 if self.__dataReady:
1135 if self.__dataReady:
1128 dataOut.utctimeInit = self.__initime
1136 dataOut.utctimeInit = self.__initime
1129
1137
1130 self.__initime += dataOut.outputInterval #to erase time offset
1138 self.__initime += dataOut.outputInterval #to erase time offset
1131
1139
1132 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax, binkm)
1140 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax, binkm)
1133 dataOut.flagNoData = False
1141 dataOut.flagNoData = False
1134 self.__buffer = None
1142 self.__buffer = None
1135
1143
1136 elif technique == 'Meteors1':
1144 elif technique == 'Meteors1':
1137 dataOut.flagNoData = True
1145 dataOut.flagNoData = True
1138 self.__dataReady = False
1146 self.__dataReady = False
1139
1147
1140 if kwargs.has_key('nMins'):
1148 if kwargs.has_key('nMins'):
1141 nMins = kwargs['nMins']
1149 nMins = kwargs['nMins']
1142 else: nMins = 20
1150 else: nMins = 20
1143 if kwargs.has_key('rx_location'):
1151 if kwargs.has_key('rx_location'):
1144 rx_location = kwargs['rx_location']
1152 rx_location = kwargs['rx_location']
1145 else: rx_location = [(0,1),(1,1),(1,0)]
1153 else: rx_location = [(0,1),(1,1),(1,0)]
1146 if kwargs.has_key('azimuth'):
1154 if kwargs.has_key('azimuth'):
1147 azimuth = kwargs['azimuth']
1155 azimuth = kwargs['azimuth']
1148 else: azimuth = 51
1156 else: azimuth = 51
1149 if kwargs.has_key('dfactor'):
1157 if kwargs.has_key('dfactor'):
1150 dfactor = kwargs['dfactor']
1158 dfactor = kwargs['dfactor']
1151 if kwargs.has_key('mode'):
1159 if kwargs.has_key('mode'):
1152 mode = kwargs['mode']
1160 mode = kwargs['mode']
1153 else: mode = 'SA'
1161 else: mode = 'SA'
1154
1162
1155 #Borrar luego esto
1163 #Borrar luego esto
1156 if dataOut.groupList is None:
1164 if dataOut.groupList is None:
1157 dataOut.groupList = [(0,1),(0,2),(1,2)]
1165 dataOut.groupList = [(0,1),(0,2),(1,2)]
1158 groupList = dataOut.groupList
1166 groupList = dataOut.groupList
1159 C = 3e8
1167 C = 3e8
1160 freq = 50e6
1168 freq = 50e6
1161 lamb = C/freq
1169 lamb = C/freq
1162 k = 2*numpy.pi/lamb
1170 k = 2*numpy.pi/lamb
1163
1171
1164 timeList = dataOut.abscissaList
1172 timeList = dataOut.abscissaList
1165 heightList = dataOut.heightList
1173 heightList = dataOut.heightList
1166
1174
1167 if self.__isConfig == False:
1175 if self.__isConfig == False:
1168 dataOut.outputInterval = nMins*60
1176 dataOut.outputInterval = nMins*60
1169 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1177 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1170 #Get Initial LTC time
1178 #Get Initial LTC time
1171 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1179 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1172 minuteAux = initime.minute
1180 minuteAux = initime.minute
1173 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
1181 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
1174 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1182 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1175
1183
1176 self.__isConfig = True
1184 self.__isConfig = True
1177
1185
1178 if self.__buffer is None:
1186 if self.__buffer is None:
1179 self.__buffer = dataOut.data_param
1187 self.__buffer = dataOut.data_param
1180 self.__firstdata = copy.copy(dataOut)
1188 self.__firstdata = copy.copy(dataOut)
1181
1189
1182 else:
1190 else:
1183 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1191 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1184
1192
1185 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1193 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1186
1194
1187 if self.__dataReady:
1195 if self.__dataReady:
1188 dataOut.utctimeInit = self.__initime
1196 dataOut.utctimeInit = self.__initime
1189 self.__initime += dataOut.outputInterval #to erase time offset
1197 self.__initime += dataOut.outputInterval #to erase time offset
1190
1198
1191 metArray = self.__buffer
1199 metArray = self.__buffer
1192 if mode == 'SA':
1200 if mode == 'SA':
1193 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
1201 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
1194 elif mode == 'DBS':
1202 elif mode == 'DBS':
1195 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList)
1203 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList)
1196 dataOut.data_output = dataOut.data_output.T
1204 dataOut.data_output = dataOut.data_output.T
1197 dataOut.flagNoData = False
1205 dataOut.flagNoData = False
1198 self.__buffer = None
1206 self.__buffer = None
1199
1207
1200 return
1208 return
1201
1209
1202 class EWDriftsEstimation(Operation):
1210 class EWDriftsEstimation(Operation):
1203
1211
1204
1212
1205 def __correctValues(self, heiRang, phi, velRadial, SNR):
1213 def __correctValues(self, heiRang, phi, velRadial, SNR):
1206 listPhi = phi.tolist()
1214 listPhi = phi.tolist()
1207 maxid = listPhi.index(max(listPhi))
1215 maxid = listPhi.index(max(listPhi))
1208 minid = listPhi.index(min(listPhi))
1216 minid = listPhi.index(min(listPhi))
1209
1217
1210 rango = range(len(phi))
1218 rango = range(len(phi))
1211 # rango = numpy.delete(rango,maxid)
1219 # rango = numpy.delete(rango,maxid)
1212
1220
1213 heiRang1 = heiRang*math.cos(phi[maxid])
1221 heiRang1 = heiRang*math.cos(phi[maxid])
1214 heiRangAux = heiRang*math.cos(phi[minid])
1222 heiRangAux = heiRang*math.cos(phi[minid])
1215 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1223 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1216 heiRang1 = numpy.delete(heiRang1,indOut)
1224 heiRang1 = numpy.delete(heiRang1,indOut)
1217
1225
1218 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1226 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1219 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1227 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1220
1228
1221 for i in rango:
1229 for i in rango:
1222 x = heiRang*math.cos(phi[i])
1230 x = heiRang*math.cos(phi[i])
1223 y1 = velRadial[i,:]
1231 y1 = velRadial[i,:]
1224 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1232 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1225
1233
1226 x1 = heiRang1
1234 x1 = heiRang1
1227 y11 = f1(x1)
1235 y11 = f1(x1)
1228
1236
1229 y2 = SNR[i,:]
1237 y2 = SNR[i,:]
1230 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1238 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1231 y21 = f2(x1)
1239 y21 = f2(x1)
1232
1240
1233 velRadial1[i,:] = y11
1241 velRadial1[i,:] = y11
1234 SNR1[i,:] = y21
1242 SNR1[i,:] = y21
1235
1243
1236 return heiRang1, velRadial1, SNR1
1244 return heiRang1, velRadial1, SNR1
1237
1245
1238 def run(self, dataOut, zenith, zenithCorrection):
1246 def run(self, dataOut, zenith, zenithCorrection):
1239 heiRang = dataOut.heightList
1247 heiRang = dataOut.heightList
1240 velRadial = dataOut.data_param[:,3,:]
1248 velRadial = dataOut.data_param[:,3,:]
1241 SNR = dataOut.data_SNR
1249 SNR = dataOut.data_SNR
1242
1250
1243 zenith = numpy.array(zenith)
1251 zenith = numpy.array(zenith)
1244 zenith -= zenithCorrection
1252 zenith -= zenithCorrection
1245 zenith *= numpy.pi/180
1253 zenith *= numpy.pi/180
1246
1254
1247 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
1255 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
1248
1256
1249 alp = zenith[0]
1257 alp = zenith[0]
1250 bet = zenith[1]
1258 bet = zenith[1]
1251
1259
1252 w_w = velRadial1[0,:]
1260 w_w = velRadial1[0,:]
1253 w_e = velRadial1[1,:]
1261 w_e = velRadial1[1,:]
1254
1262
1255 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
1263 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
1256 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
1264 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
1257
1265
1258 winds = numpy.vstack((u,w))
1266 winds = numpy.vstack((u,w))
1259
1267
1260 dataOut.heightList = heiRang1
1268 dataOut.heightList = heiRang1
1261 dataOut.data_output = winds
1269 dataOut.data_output = winds
1262 dataOut.data_SNR = SNR1
1270 dataOut.data_SNR = SNR1
1263
1271
1264 dataOut.utctimeInit = dataOut.utctime
1272 dataOut.utctimeInit = dataOut.utctime
1265 dataOut.outputInterval = dataOut.timeInterval
1273 dataOut.outputInterval = dataOut.timeInterval
1266 return
1274 return
1267
1275
1268 #--------------- Non Specular Meteor ----------------
1276 #--------------- Non Specular Meteor ----------------
1269
1277
1270 class NonSpecularMeteorDetection(Operation):
1278 class NonSpecularMeteorDetection(Operation):
1271
1279
1272 def run(self, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
1280 def run(self, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
1273 data_acf = self.dataOut.data_pre[0]
1281 data_acf = self.dataOut.data_pre[0]
1274 data_ccf = self.dataOut.data_pre[1]
1282 data_ccf = self.dataOut.data_pre[1]
1275
1283
1276 lamb = self.dataOut.C/self.dataOut.frequency
1284 lamb = self.dataOut.C/self.dataOut.frequency
1277 tSamp = self.dataOut.ippSeconds*self.dataOut.nCohInt
1285 tSamp = self.dataOut.ippSeconds*self.dataOut.nCohInt
1278 paramInterval = self.dataOut.paramInterval
1286 paramInterval = self.dataOut.paramInterval
1279
1287
1280 nChannels = data_acf.shape[0]
1288 nChannels = data_acf.shape[0]
1281 nLags = data_acf.shape[1]
1289 nLags = data_acf.shape[1]
1282 nProfiles = data_acf.shape[2]
1290 nProfiles = data_acf.shape[2]
1283 nHeights = self.dataOut.nHeights
1291 nHeights = self.dataOut.nHeights
1284 nCohInt = self.dataOut.nCohInt
1292 nCohInt = self.dataOut.nCohInt
1285 sec = numpy.round(nProfiles/self.dataOut.paramInterval)
1293 sec = numpy.round(nProfiles/self.dataOut.paramInterval)
1286 heightList = self.dataOut.heightList
1294 heightList = self.dataOut.heightList
1287 ippSeconds = self.dataOut.ippSeconds*self.dataOut.nCohInt*self.dataOut.nAvg
1295 ippSeconds = self.dataOut.ippSeconds*self.dataOut.nCohInt*self.dataOut.nAvg
1288 utctime = self.dataOut.utctime
1296 utctime = self.dataOut.utctime
1289
1297
1290 self.dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
1298 self.dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
1291
1299
1292 #------------------------ SNR --------------------------------------
1300 #------------------------ SNR --------------------------------------
1293 power = data_acf[:,0,:,:].real
1301 power = data_acf[:,0,:,:].real
1294 noise = numpy.zeros(nChannels)
1302 noise = numpy.zeros(nChannels)
1295 SNR = numpy.zeros(power.shape)
1303 SNR = numpy.zeros(power.shape)
1296 for i in range(nChannels):
1304 for i in range(nChannels):
1297 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
1305 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
1298 SNR[i] = (power[i]-noise[i])/noise[i]
1306 SNR[i] = (power[i]-noise[i])/noise[i]
1299 SNRm = numpy.nanmean(SNR, axis = 0)
1307 SNRm = numpy.nanmean(SNR, axis = 0)
1300 SNRdB = 10*numpy.log10(SNR)
1308 SNRdB = 10*numpy.log10(SNR)
1301
1309
1302 if mode == 'SA':
1310 if mode == 'SA':
1303 nPairs = data_ccf.shape[0]
1311 nPairs = data_ccf.shape[0]
1304 #---------------------- Coherence and Phase --------------------------
1312 #---------------------- Coherence and Phase --------------------------
1305 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
1313 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
1306 # phase1 = numpy.copy(phase)
1314 # phase1 = numpy.copy(phase)
1307 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
1315 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
1308
1316
1309 for p in range(nPairs):
1317 for p in range(nPairs):
1310 ch0 = self.dataOut.groupList[p][0]
1318 ch0 = self.dataOut.groupList[p][0]
1311 ch1 = self.dataOut.groupList[p][1]
1319 ch1 = self.dataOut.groupList[p][1]
1312 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
1320 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
1313 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
1321 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
1314 # phase1[p,:,:] = numpy.angle(ccf) #median filter
1322 # phase1[p,:,:] = numpy.angle(ccf) #median filter
1315 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
1323 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
1316 # coh1[p,:,:] = numpy.abs(ccf) #median filter
1324 # coh1[p,:,:] = numpy.abs(ccf) #median filter
1317 coh = numpy.nanmax(coh1, axis = 0)
1325 coh = numpy.nanmax(coh1, axis = 0)
1318 # struc = numpy.ones((5,1))
1326 # struc = numpy.ones((5,1))
1319 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
1327 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
1320 #---------------------- Radial Velocity ----------------------------
1328 #---------------------- Radial Velocity ----------------------------
1321 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
1329 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
1322 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
1330 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
1323
1331
1324 if allData:
1332 if allData:
1325 boolMetFin = ~numpy.isnan(SNRm)
1333 boolMetFin = ~numpy.isnan(SNRm)
1326 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1334 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1327 else:
1335 else:
1328 #------------------------ Meteor mask ---------------------------------
1336 #------------------------ Meteor mask ---------------------------------
1329 # #SNR mask
1337 # #SNR mask
1330 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
1338 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
1331 #
1339 #
1332 # #Erase small objects
1340 # #Erase small objects
1333 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
1341 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
1334 #
1342 #
1335 # auxEEJ = numpy.sum(boolMet1,axis=0)
1343 # auxEEJ = numpy.sum(boolMet1,axis=0)
1336 # indOver = auxEEJ>nProfiles*0.8 #Use this later
1344 # indOver = auxEEJ>nProfiles*0.8 #Use this later
1337 # indEEJ = numpy.where(indOver)[0]
1345 # indEEJ = numpy.where(indOver)[0]
1338 # indNEEJ = numpy.where(~indOver)[0]
1346 # indNEEJ = numpy.where(~indOver)[0]
1339 #
1347 #
1340 # boolMetFin = boolMet1
1348 # boolMetFin = boolMet1
1341 #
1349 #
1342 # if indEEJ.size > 0:
1350 # if indEEJ.size > 0:
1343 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
1351 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
1344 #
1352 #
1345 # boolMet2 = coh > cohThresh
1353 # boolMet2 = coh > cohThresh
1346 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
1354 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
1347 #
1355 #
1348 # #Final Meteor mask
1356 # #Final Meteor mask
1349 # boolMetFin = boolMet1|boolMet2
1357 # boolMetFin = boolMet1|boolMet2
1350
1358
1351 #Coherence mask
1359 #Coherence mask
1352 boolMet1 = coh > 0.75
1360 boolMet1 = coh > 0.75
1353 struc = numpy.ones((30,1))
1361 struc = numpy.ones((30,1))
1354 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
1362 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
1355
1363
1356 #Derivative mask
1364 #Derivative mask
1357 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1365 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1358 boolMet2 = derPhase < 0.2
1366 boolMet2 = derPhase < 0.2
1359 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
1367 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
1360 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
1368 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
1361 boolMet2 = ndimage.median_filter(boolMet2,size=5)
1369 boolMet2 = ndimage.median_filter(boolMet2,size=5)
1362 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
1370 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
1363 # #Final mask
1371 # #Final mask
1364 # boolMetFin = boolMet2
1372 # boolMetFin = boolMet2
1365 boolMetFin = boolMet1&boolMet2
1373 boolMetFin = boolMet1&boolMet2
1366 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
1374 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
1367 #Creating data_param
1375 #Creating data_param
1368 coordMet = numpy.where(boolMetFin)
1376 coordMet = numpy.where(boolMetFin)
1369
1377
1370 tmet = coordMet[0]
1378 tmet = coordMet[0]
1371 hmet = coordMet[1]
1379 hmet = coordMet[1]
1372
1380
1373 data_param = numpy.zeros((tmet.size, 6 + nPairs))
1381 data_param = numpy.zeros((tmet.size, 6 + nPairs))
1374 data_param[:,0] = utctime
1382 data_param[:,0] = utctime
1375 data_param[:,1] = tmet
1383 data_param[:,1] = tmet
1376 data_param[:,2] = hmet
1384 data_param[:,2] = hmet
1377 data_param[:,3] = SNRm[tmet,hmet]
1385 data_param[:,3] = SNRm[tmet,hmet]
1378 data_param[:,4] = velRad[tmet,hmet]
1386 data_param[:,4] = velRad[tmet,hmet]
1379 data_param[:,5] = coh[tmet,hmet]
1387 data_param[:,5] = coh[tmet,hmet]
1380 data_param[:,6:] = phase[:,tmet,hmet].T
1388 data_param[:,6:] = phase[:,tmet,hmet].T
1381
1389
1382 elif mode == 'DBS':
1390 elif mode == 'DBS':
1383 self.dataOut.groupList = numpy.arange(nChannels)
1391 self.dataOut.groupList = numpy.arange(nChannels)
1384
1392
1385 #Radial Velocities
1393 #Radial Velocities
1386 # phase = numpy.angle(data_acf[:,1,:,:])
1394 # phase = numpy.angle(data_acf[:,1,:,:])
1387 phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
1395 phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
1388 velRad = phase*lamb/(4*numpy.pi*tSamp)
1396 velRad = phase*lamb/(4*numpy.pi*tSamp)
1389
1397
1390 #Spectral width
1398 #Spectral width
1391 acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
1399 acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
1392 acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
1400 acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
1393
1401
1394 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
1402 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
1395 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
1403 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
1396 if allData:
1404 if allData:
1397 boolMetFin = ~numpy.isnan(SNRdB)
1405 boolMetFin = ~numpy.isnan(SNRdB)
1398 else:
1406 else:
1399 #SNR
1407 #SNR
1400 boolMet1 = (SNRdB>SNRthresh) #SNR mask
1408 boolMet1 = (SNRdB>SNRthresh) #SNR mask
1401 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
1409 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
1402
1410
1403 #Radial velocity
1411 #Radial velocity
1404 boolMet2 = numpy.abs(velRad) < 30
1412 boolMet2 = numpy.abs(velRad) < 30
1405 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
1413 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
1406
1414
1407 #Spectral Width
1415 #Spectral Width
1408 boolMet3 = spcWidth < 30
1416 boolMet3 = spcWidth < 30
1409 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
1417 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
1410 # boolMetFin = self.__erase_small(boolMet1, 10,5)
1418 # boolMetFin = self.__erase_small(boolMet1, 10,5)
1411 boolMetFin = boolMet1&boolMet2&boolMet3
1419 boolMetFin = boolMet1&boolMet2&boolMet3
1412
1420
1413 #Creating data_param
1421 #Creating data_param
1414 coordMet = numpy.where(boolMetFin)
1422 coordMet = numpy.where(boolMetFin)
1415
1423
1416 cmet = coordMet[0]
1424 cmet = coordMet[0]
1417 tmet = coordMet[1]
1425 tmet = coordMet[1]
1418 hmet = coordMet[2]
1426 hmet = coordMet[2]
1419
1427
1420 data_param = numpy.zeros((tmet.size, 7))
1428 data_param = numpy.zeros((tmet.size, 7))
1421 data_param[:,0] = utctime
1429 data_param[:,0] = utctime
1422 data_param[:,1] = cmet
1430 data_param[:,1] = cmet
1423 data_param[:,2] = tmet
1431 data_param[:,2] = tmet
1424 data_param[:,3] = hmet
1432 data_param[:,3] = hmet
1425 data_param[:,4] = SNR[cmet,tmet,hmet].T
1433 data_param[:,4] = SNR[cmet,tmet,hmet].T
1426 data_param[:,5] = velRad[cmet,tmet,hmet].T
1434 data_param[:,5] = velRad[cmet,tmet,hmet].T
1427 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
1435 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
1428
1436
1429 # self.dataOut.data_param = data_int
1437 # self.dataOut.data_param = data_int
1430 if len(data_param) == 0:
1438 if len(data_param) == 0:
1431 self.dataOut.flagNoData = True
1439 self.dataOut.flagNoData = True
1432 else:
1440 else:
1433 self.dataOut.data_param = data_param
1441 self.dataOut.data_param = data_param
1434
1442
1435 def __erase_small(self, binArray, threshX, threshY):
1443 def __erase_small(self, binArray, threshX, threshY):
1436 labarray, numfeat = ndimage.measurements.label(binArray)
1444 labarray, numfeat = ndimage.measurements.label(binArray)
1437 binArray1 = numpy.copy(binArray)
1445 binArray1 = numpy.copy(binArray)
1438
1446
1439 for i in range(1,numfeat + 1):
1447 for i in range(1,numfeat + 1):
1440 auxBin = (labarray==i)
1448 auxBin = (labarray==i)
1441 auxSize = auxBin.sum()
1449 auxSize = auxBin.sum()
1442
1450
1443 x,y = numpy.where(auxBin)
1451 x,y = numpy.where(auxBin)
1444 widthX = x.max() - x.min()
1452 widthX = x.max() - x.min()
1445 widthY = y.max() - y.min()
1453 widthY = y.max() - y.min()
1446
1454
1447 #width X: 3 seg -> 12.5*3
1455 #width X: 3 seg -> 12.5*3
1448 #width Y:
1456 #width Y:
1449
1457
1450 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
1458 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
1451 binArray1[auxBin] = False
1459 binArray1[auxBin] = False
1452
1460
1453 return binArray1
1461 return binArray1
1454
1462
1455 #--------------- Specular Meteor ----------------
1463 #--------------- Specular Meteor ----------------
1456
1464
1457 class SMDetection(Operation):
1465 class SMDetection(Operation):
1458 '''
1466 '''
1459 Function DetectMeteors()
1467 Function DetectMeteors()
1460 Project developed with paper:
1468 Project developed with paper:
1461 HOLDSWORTH ET AL. 2004
1469 HOLDSWORTH ET AL. 2004
1462
1470
1463 Input:
1471 Input:
1464 self.dataOut.data_pre
1472 self.dataOut.data_pre
1465
1473
1466 centerReceiverIndex: From the channels, which is the center receiver
1474 centerReceiverIndex: From the channels, which is the center receiver
1467
1475
1468 hei_ref: Height reference for the Beacon signal extraction
1476 hei_ref: Height reference for the Beacon signal extraction
1469 tauindex:
1477 tauindex:
1470 predefinedPhaseShifts: Predefined phase offset for the voltge signals
1478 predefinedPhaseShifts: Predefined phase offset for the voltge signals
1471
1479
1472 cohDetection: Whether to user Coherent detection or not
1480 cohDetection: Whether to user Coherent detection or not
1473 cohDet_timeStep: Coherent Detection calculation time step
1481 cohDet_timeStep: Coherent Detection calculation time step
1474 cohDet_thresh: Coherent Detection phase threshold to correct phases
1482 cohDet_thresh: Coherent Detection phase threshold to correct phases
1475
1483
1476 noise_timeStep: Noise calculation time step
1484 noise_timeStep: Noise calculation time step
1477 noise_multiple: Noise multiple to define signal threshold
1485 noise_multiple: Noise multiple to define signal threshold
1478
1486
1479 multDet_timeLimit: Multiple Detection Removal time limit in seconds
1487 multDet_timeLimit: Multiple Detection Removal time limit in seconds
1480 multDet_rangeLimit: Multiple Detection Removal range limit in km
1488 multDet_rangeLimit: Multiple Detection Removal range limit in km
1481
1489
1482 phaseThresh: Maximum phase difference between receiver to be consider a meteor
1490 phaseThresh: Maximum phase difference between receiver to be consider a meteor
1483 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
1491 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
1484
1492
1485 hmin: Minimum Height of the meteor to use it in the further wind estimations
1493 hmin: Minimum Height of the meteor to use it in the further wind estimations
1486 hmax: Maximum Height of the meteor to use it in the further wind estimations
1494 hmax: Maximum Height of the meteor to use it in the further wind estimations
1487 azimuth: Azimuth angle correction
1495 azimuth: Azimuth angle correction
1488
1496
1489 Affected:
1497 Affected:
1490 self.dataOut.data_param
1498 self.dataOut.data_param
1491
1499
1492 Rejection Criteria (Errors):
1500 Rejection Criteria (Errors):
1493 0: No error; analysis OK
1501 0: No error; analysis OK
1494 1: SNR < SNR threshold
1502 1: SNR < SNR threshold
1495 2: angle of arrival (AOA) ambiguously determined
1503 2: angle of arrival (AOA) ambiguously determined
1496 3: AOA estimate not feasible
1504 3: AOA estimate not feasible
1497 4: Large difference in AOAs obtained from different antenna baselines
1505 4: Large difference in AOAs obtained from different antenna baselines
1498 5: echo at start or end of time series
1506 5: echo at start or end of time series
1499 6: echo less than 5 examples long; too short for analysis
1507 6: echo less than 5 examples long; too short for analysis
1500 7: echo rise exceeds 0.3s
1508 7: echo rise exceeds 0.3s
1501 8: echo decay time less than twice rise time
1509 8: echo decay time less than twice rise time
1502 9: large power level before echo
1510 9: large power level before echo
1503 10: large power level after echo
1511 10: large power level after echo
1504 11: poor fit to amplitude for estimation of decay time
1512 11: poor fit to amplitude for estimation of decay time
1505 12: poor fit to CCF phase variation for estimation of radial drift velocity
1513 12: poor fit to CCF phase variation for estimation of radial drift velocity
1506 13: height unresolvable echo: not valid height within 70 to 110 km
1514 13: height unresolvable echo: not valid height within 70 to 110 km
1507 14: height ambiguous echo: more then one possible height within 70 to 110 km
1515 14: height ambiguous echo: more then one possible height within 70 to 110 km
1508 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
1516 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
1509 16: oscilatory echo, indicating event most likely not an underdense echo
1517 16: oscilatory echo, indicating event most likely not an underdense echo
1510
1518
1511 17: phase difference in meteor Reestimation
1519 17: phase difference in meteor Reestimation
1512
1520
1513 Data Storage:
1521 Data Storage:
1514 Meteors for Wind Estimation (8):
1522 Meteors for Wind Estimation (8):
1515 Utc Time | Range Height
1523 Utc Time | Range Height
1516 Azimuth Zenith errorCosDir
1524 Azimuth Zenith errorCosDir
1517 VelRad errorVelRad
1525 VelRad errorVelRad
1518 Phase0 Phase1 Phase2 Phase3
1526 Phase0 Phase1 Phase2 Phase3
1519 TypeError
1527 TypeError
1520
1528
1521 '''
1529 '''
1522
1530
1523 def run(self, dataOut, hei_ref = None, tauindex = 0,
1531 def run(self, dataOut, hei_ref = None, tauindex = 0,
1524 phaseOffsets = None,
1532 phaseOffsets = None,
1525 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
1533 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
1526 noise_timeStep = 4, noise_multiple = 4,
1534 noise_timeStep = 4, noise_multiple = 4,
1527 multDet_timeLimit = 1, multDet_rangeLimit = 3,
1535 multDet_timeLimit = 1, multDet_rangeLimit = 3,
1528 phaseThresh = 20, SNRThresh = 5,
1536 phaseThresh = 20, SNRThresh = 5,
1529 hmin = 50, hmax=150, azimuth = 0,
1537 hmin = 50, hmax=150, azimuth = 0,
1530 channelPositions = None) :
1538 channelPositions = None) :
1531
1539
1532
1540
1533 #Getting Pairslist
1541 #Getting Pairslist
1534 if channelPositions is None:
1542 if channelPositions is None:
1535 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
1543 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
1536 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
1544 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
1537 meteorOps = SMOperations()
1545 meteorOps = SMOperations()
1538 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
1546 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
1539 heiRang = dataOut.getHeiRange()
1547 heiRang = dataOut.getHeiRange()
1540 #Get Beacon signal - No Beacon signal anymore
1548 #Get Beacon signal - No Beacon signal anymore
1541 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
1549 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
1542 #
1550 #
1543 # if hei_ref != None:
1551 # if hei_ref != None:
1544 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
1552 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
1545 #
1553 #
1546
1554
1547
1555
1548 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
1556 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
1549 # see if the user put in pre defined phase shifts
1557 # see if the user put in pre defined phase shifts
1550 voltsPShift = dataOut.data_pre.copy()
1558 voltsPShift = dataOut.data_pre.copy()
1551
1559
1552 # if predefinedPhaseShifts != None:
1560 # if predefinedPhaseShifts != None:
1553 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
1561 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
1554 #
1562 #
1555 # # elif beaconPhaseShifts:
1563 # # elif beaconPhaseShifts:
1556 # # #get hardware phase shifts using beacon signal
1564 # # #get hardware phase shifts using beacon signal
1557 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
1565 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
1558 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
1566 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
1559 #
1567 #
1560 # else:
1568 # else:
1561 # hardwarePhaseShifts = numpy.zeros(5)
1569 # hardwarePhaseShifts = numpy.zeros(5)
1562 #
1570 #
1563 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
1571 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
1564 # for i in range(self.dataOut.data_pre.shape[0]):
1572 # for i in range(self.dataOut.data_pre.shape[0]):
1565 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
1573 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
1566
1574
1567 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
1575 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
1568
1576
1569 #Remove DC
1577 #Remove DC
1570 voltsDC = numpy.mean(voltsPShift,1)
1578 voltsDC = numpy.mean(voltsPShift,1)
1571 voltsDC = numpy.mean(voltsDC,1)
1579 voltsDC = numpy.mean(voltsDC,1)
1572 for i in range(voltsDC.shape[0]):
1580 for i in range(voltsDC.shape[0]):
1573 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
1581 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
1574
1582
1575 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
1583 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
1576 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
1584 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
1577
1585
1578 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
1586 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
1579 #Coherent Detection
1587 #Coherent Detection
1580 if cohDetection:
1588 if cohDetection:
1581 #use coherent detection to get the net power
1589 #use coherent detection to get the net power
1582 cohDet_thresh = cohDet_thresh*numpy.pi/180
1590 cohDet_thresh = cohDet_thresh*numpy.pi/180
1583 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
1591 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
1584
1592
1585 #Non-coherent detection!
1593 #Non-coherent detection!
1586 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
1594 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
1587 #********** END OF COH/NON-COH POWER CALCULATION**********************
1595 #********** END OF COH/NON-COH POWER CALCULATION**********************
1588
1596
1589 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
1597 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
1590 #Get noise
1598 #Get noise
1591 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
1599 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
1592 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
1600 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
1593 #Get signal threshold
1601 #Get signal threshold
1594 signalThresh = noise_multiple*noise
1602 signalThresh = noise_multiple*noise
1595 #Meteor echoes detection
1603 #Meteor echoes detection
1596 listMeteors = self.__findMeteors(powerNet, signalThresh)
1604 listMeteors = self.__findMeteors(powerNet, signalThresh)
1597 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
1605 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
1598
1606
1599 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
1607 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
1600 #Parameters
1608 #Parameters
1601 heiRange = dataOut.getHeiRange()
1609 heiRange = dataOut.getHeiRange()
1602 rangeInterval = heiRange[1] - heiRange[0]
1610 rangeInterval = heiRange[1] - heiRange[0]
1603 rangeLimit = multDet_rangeLimit/rangeInterval
1611 rangeLimit = multDet_rangeLimit/rangeInterval
1604 timeLimit = multDet_timeLimit/dataOut.timeInterval
1612 timeLimit = multDet_timeLimit/dataOut.timeInterval
1605 #Multiple detection removals
1613 #Multiple detection removals
1606 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
1614 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
1607 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
1615 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
1608
1616
1609 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
1617 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
1610 #Parameters
1618 #Parameters
1611 phaseThresh = phaseThresh*numpy.pi/180
1619 phaseThresh = phaseThresh*numpy.pi/180
1612 thresh = [phaseThresh, noise_multiple, SNRThresh]
1620 thresh = [phaseThresh, noise_multiple, SNRThresh]
1613 #Meteor reestimation (Errors N 1, 6, 12, 17)
1621 #Meteor reestimation (Errors N 1, 6, 12, 17)
1614 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
1622 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
1615 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
1623 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
1616 #Estimation of decay times (Errors N 7, 8, 11)
1624 #Estimation of decay times (Errors N 7, 8, 11)
1617 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
1625 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
1618 #******************* END OF METEOR REESTIMATION *******************
1626 #******************* END OF METEOR REESTIMATION *******************
1619
1627
1620 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
1628 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
1621 #Calculating Radial Velocity (Error N 15)
1629 #Calculating Radial Velocity (Error N 15)
1622 radialStdThresh = 10
1630 radialStdThresh = 10
1623 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
1631 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
1624
1632
1625 if len(listMeteors4) > 0:
1633 if len(listMeteors4) > 0:
1626 #Setting New Array
1634 #Setting New Array
1627 date = dataOut.utctime
1635 date = dataOut.utctime
1628 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
1636 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
1629
1637
1630 #Correcting phase offset
1638 #Correcting phase offset
1631 if phaseOffsets != None:
1639 if phaseOffsets != None:
1632 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
1640 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
1633 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
1641 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
1634
1642
1635 #Second Pairslist
1643 #Second Pairslist
1636 pairsList = []
1644 pairsList = []
1637 pairx = (0,1)
1645 pairx = (0,1)
1638 pairy = (2,3)
1646 pairy = (2,3)
1639 pairsList.append(pairx)
1647 pairsList.append(pairx)
1640 pairsList.append(pairy)
1648 pairsList.append(pairy)
1641
1649
1642 jph = numpy.array([0,0,0,0])
1650 jph = numpy.array([0,0,0,0])
1643 h = (hmin,hmax)
1651 h = (hmin,hmax)
1644 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
1652 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
1645
1653
1646 # #Calculate AOA (Error N 3, 4)
1654 # #Calculate AOA (Error N 3, 4)
1647 # #JONES ET AL. 1998
1655 # #JONES ET AL. 1998
1648 # error = arrayParameters[:,-1]
1656 # error = arrayParameters[:,-1]
1649 # AOAthresh = numpy.pi/8
1657 # AOAthresh = numpy.pi/8
1650 # phases = -arrayParameters[:,9:13]
1658 # phases = -arrayParameters[:,9:13]
1651 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
1659 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
1652 #
1660 #
1653 # #Calculate Heights (Error N 13 and 14)
1661 # #Calculate Heights (Error N 13 and 14)
1654 # error = arrayParameters[:,-1]
1662 # error = arrayParameters[:,-1]
1655 # Ranges = arrayParameters[:,2]
1663 # Ranges = arrayParameters[:,2]
1656 # zenith = arrayParameters[:,5]
1664 # zenith = arrayParameters[:,5]
1657 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
1665 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
1658 # error = arrayParameters[:,-1]
1666 # error = arrayParameters[:,-1]
1659 #********************* END OF PARAMETERS CALCULATION **************************
1667 #********************* END OF PARAMETERS CALCULATION **************************
1660
1668
1661 #***************************+ PASS DATA TO NEXT STEP **********************
1669 #***************************+ PASS DATA TO NEXT STEP **********************
1662 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
1670 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
1663 dataOut.data_param = arrayParameters
1671 dataOut.data_param = arrayParameters
1664
1672
1665 if arrayParameters is None:
1673 if arrayParameters is None:
1666 dataOut.flagNoData = True
1674 dataOut.flagNoData = True
1667 else:
1675 else:
1668 dataOut.flagNoData = True
1676 dataOut.flagNoData = True
1669
1677
1670 return
1678 return
1671
1679
1672 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
1680 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
1673
1681
1674 minIndex = min(newheis[0])
1682 minIndex = min(newheis[0])
1675 maxIndex = max(newheis[0])
1683 maxIndex = max(newheis[0])
1676
1684
1677 voltage = voltage0[:,:,minIndex:maxIndex+1]
1685 voltage = voltage0[:,:,minIndex:maxIndex+1]
1678 nLength = voltage.shape[1]/n
1686 nLength = voltage.shape[1]/n
1679 nMin = 0
1687 nMin = 0
1680 nMax = 0
1688 nMax = 0
1681 phaseOffset = numpy.zeros((len(pairslist),n))
1689 phaseOffset = numpy.zeros((len(pairslist),n))
1682
1690
1683 for i in range(n):
1691 for i in range(n):
1684 nMax += nLength
1692 nMax += nLength
1685 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
1693 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
1686 phaseCCF = numpy.mean(phaseCCF, axis = 2)
1694 phaseCCF = numpy.mean(phaseCCF, axis = 2)
1687 phaseOffset[:,i] = phaseCCF.transpose()
1695 phaseOffset[:,i] = phaseCCF.transpose()
1688 nMin = nMax
1696 nMin = nMax
1689 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
1697 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
1690
1698
1691 #Remove Outliers
1699 #Remove Outliers
1692 factor = 2
1700 factor = 2
1693 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
1701 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
1694 dw = numpy.std(wt,axis = 1)
1702 dw = numpy.std(wt,axis = 1)
1695 dw = dw.reshape((dw.size,1))
1703 dw = dw.reshape((dw.size,1))
1696 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
1704 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
1697 phaseOffset[ind] = numpy.nan
1705 phaseOffset[ind] = numpy.nan
1698 phaseOffset = stats.nanmean(phaseOffset, axis=1)
1706 phaseOffset = stats.nanmean(phaseOffset, axis=1)
1699
1707
1700 return phaseOffset
1708 return phaseOffset
1701
1709
1702 def __shiftPhase(self, data, phaseShift):
1710 def __shiftPhase(self, data, phaseShift):
1703 #this will shift the phase of a complex number
1711 #this will shift the phase of a complex number
1704 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
1712 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
1705 return dataShifted
1713 return dataShifted
1706
1714
1707 def __estimatePhaseDifference(self, array, pairslist):
1715 def __estimatePhaseDifference(self, array, pairslist):
1708 nChannel = array.shape[0]
1716 nChannel = array.shape[0]
1709 nHeights = array.shape[2]
1717 nHeights = array.shape[2]
1710 numPairs = len(pairslist)
1718 numPairs = len(pairslist)
1711 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
1719 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
1712 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
1720 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
1713
1721
1714 #Correct phases
1722 #Correct phases
1715 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
1723 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
1716 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
1724 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
1717
1725
1718 if indDer[0].shape[0] > 0:
1726 if indDer[0].shape[0] > 0:
1719 for i in range(indDer[0].shape[0]):
1727 for i in range(indDer[0].shape[0]):
1720 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
1728 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
1721 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
1729 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
1722
1730
1723 # for j in range(numSides):
1731 # for j in range(numSides):
1724 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
1732 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
1725 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
1733 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
1726 #
1734 #
1727 #Linear
1735 #Linear
1728 phaseInt = numpy.zeros((numPairs,1))
1736 phaseInt = numpy.zeros((numPairs,1))
1729 angAllCCF = phaseCCF[:,[0,1,3,4],0]
1737 angAllCCF = phaseCCF[:,[0,1,3,4],0]
1730 for j in range(numPairs):
1738 for j in range(numPairs):
1731 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
1739 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
1732 phaseInt[j] = fit[1]
1740 phaseInt[j] = fit[1]
1733 #Phase Differences
1741 #Phase Differences
1734 phaseDiff = phaseInt - phaseCCF[:,2,:]
1742 phaseDiff = phaseInt - phaseCCF[:,2,:]
1735 phaseArrival = phaseInt.reshape(phaseInt.size)
1743 phaseArrival = phaseInt.reshape(phaseInt.size)
1736
1744
1737 #Dealias
1745 #Dealias
1738 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
1746 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
1739 # indAlias = numpy.where(phaseArrival > numpy.pi)
1747 # indAlias = numpy.where(phaseArrival > numpy.pi)
1740 # phaseArrival[indAlias] -= 2*numpy.pi
1748 # phaseArrival[indAlias] -= 2*numpy.pi
1741 # indAlias = numpy.where(phaseArrival < -numpy.pi)
1749 # indAlias = numpy.where(phaseArrival < -numpy.pi)
1742 # phaseArrival[indAlias] += 2*numpy.pi
1750 # phaseArrival[indAlias] += 2*numpy.pi
1743
1751
1744 return phaseDiff, phaseArrival
1752 return phaseDiff, phaseArrival
1745
1753
1746 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
1754 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
1747 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
1755 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
1748 #find the phase shifts of each channel over 1 second intervals
1756 #find the phase shifts of each channel over 1 second intervals
1749 #only look at ranges below the beacon signal
1757 #only look at ranges below the beacon signal
1750 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1758 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1751 numBlocks = int(volts.shape[1]/numProfPerBlock)
1759 numBlocks = int(volts.shape[1]/numProfPerBlock)
1752 numHeights = volts.shape[2]
1760 numHeights = volts.shape[2]
1753 nChannel = volts.shape[0]
1761 nChannel = volts.shape[0]
1754 voltsCohDet = volts.copy()
1762 voltsCohDet = volts.copy()
1755
1763
1756 pairsarray = numpy.array(pairslist)
1764 pairsarray = numpy.array(pairslist)
1757 indSides = pairsarray[:,1]
1765 indSides = pairsarray[:,1]
1758 # indSides = numpy.array(range(nChannel))
1766 # indSides = numpy.array(range(nChannel))
1759 # indSides = numpy.delete(indSides, indCenter)
1767 # indSides = numpy.delete(indSides, indCenter)
1760 #
1768 #
1761 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
1769 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
1762 listBlocks = numpy.array_split(volts, numBlocks, 1)
1770 listBlocks = numpy.array_split(volts, numBlocks, 1)
1763
1771
1764 startInd = 0
1772 startInd = 0
1765 endInd = 0
1773 endInd = 0
1766
1774
1767 for i in range(numBlocks):
1775 for i in range(numBlocks):
1768 startInd = endInd
1776 startInd = endInd
1769 endInd = endInd + listBlocks[i].shape[1]
1777 endInd = endInd + listBlocks[i].shape[1]
1770
1778
1771 arrayBlock = listBlocks[i]
1779 arrayBlock = listBlocks[i]
1772 # arrayBlockCenter = listCenter[i]
1780 # arrayBlockCenter = listCenter[i]
1773
1781
1774 #Estimate the Phase Difference
1782 #Estimate the Phase Difference
1775 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
1783 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
1776 #Phase Difference RMS
1784 #Phase Difference RMS
1777 arrayPhaseRMS = numpy.abs(phaseDiff)
1785 arrayPhaseRMS = numpy.abs(phaseDiff)
1778 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
1786 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
1779 indPhase = numpy.where(phaseRMSaux==4)
1787 indPhase = numpy.where(phaseRMSaux==4)
1780 #Shifting
1788 #Shifting
1781 if indPhase[0].shape[0] > 0:
1789 if indPhase[0].shape[0] > 0:
1782 for j in range(indSides.size):
1790 for j in range(indSides.size):
1783 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
1791 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
1784 voltsCohDet[:,startInd:endInd,:] = arrayBlock
1792 voltsCohDet[:,startInd:endInd,:] = arrayBlock
1785
1793
1786 return voltsCohDet
1794 return voltsCohDet
1787
1795
1788 def __calculateCCF(self, volts, pairslist ,laglist):
1796 def __calculateCCF(self, volts, pairslist ,laglist):
1789
1797
1790 nHeights = volts.shape[2]
1798 nHeights = volts.shape[2]
1791 nPoints = volts.shape[1]
1799 nPoints = volts.shape[1]
1792 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
1800 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
1793
1801
1794 for i in range(len(pairslist)):
1802 for i in range(len(pairslist)):
1795 volts1 = volts[pairslist[i][0]]
1803 volts1 = volts[pairslist[i][0]]
1796 volts2 = volts[pairslist[i][1]]
1804 volts2 = volts[pairslist[i][1]]
1797
1805
1798 for t in range(len(laglist)):
1806 for t in range(len(laglist)):
1799 idxT = laglist[t]
1807 idxT = laglist[t]
1800 if idxT >= 0:
1808 if idxT >= 0:
1801 vStacked = numpy.vstack((volts2[idxT:,:],
1809 vStacked = numpy.vstack((volts2[idxT:,:],
1802 numpy.zeros((idxT, nHeights),dtype='complex')))
1810 numpy.zeros((idxT, nHeights),dtype='complex')))
1803 else:
1811 else:
1804 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
1812 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
1805 volts2[:(nPoints + idxT),:]))
1813 volts2[:(nPoints + idxT),:]))
1806 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
1814 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
1807
1815
1808 vStacked = None
1816 vStacked = None
1809 return voltsCCF
1817 return voltsCCF
1810
1818
1811 def __getNoise(self, power, timeSegment, timeInterval):
1819 def __getNoise(self, power, timeSegment, timeInterval):
1812 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1820 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1813 numBlocks = int(power.shape[0]/numProfPerBlock)
1821 numBlocks = int(power.shape[0]/numProfPerBlock)
1814 numHeights = power.shape[1]
1822 numHeights = power.shape[1]
1815
1823
1816 listPower = numpy.array_split(power, numBlocks, 0)
1824 listPower = numpy.array_split(power, numBlocks, 0)
1817 noise = numpy.zeros((power.shape[0], power.shape[1]))
1825 noise = numpy.zeros((power.shape[0], power.shape[1]))
1818 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
1826 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
1819
1827
1820 startInd = 0
1828 startInd = 0
1821 endInd = 0
1829 endInd = 0
1822
1830
1823 for i in range(numBlocks): #split por canal
1831 for i in range(numBlocks): #split por canal
1824 startInd = endInd
1832 startInd = endInd
1825 endInd = endInd + listPower[i].shape[0]
1833 endInd = endInd + listPower[i].shape[0]
1826
1834
1827 arrayBlock = listPower[i]
1835 arrayBlock = listPower[i]
1828 noiseAux = numpy.mean(arrayBlock, 0)
1836 noiseAux = numpy.mean(arrayBlock, 0)
1829 # noiseAux = numpy.median(noiseAux)
1837 # noiseAux = numpy.median(noiseAux)
1830 # noiseAux = numpy.mean(arrayBlock)
1838 # noiseAux = numpy.mean(arrayBlock)
1831 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
1839 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
1832
1840
1833 noiseAux1 = numpy.mean(arrayBlock)
1841 noiseAux1 = numpy.mean(arrayBlock)
1834 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
1842 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
1835
1843
1836 return noise, noise1
1844 return noise, noise1
1837
1845
1838 def __findMeteors(self, power, thresh):
1846 def __findMeteors(self, power, thresh):
1839 nProf = power.shape[0]
1847 nProf = power.shape[0]
1840 nHeights = power.shape[1]
1848 nHeights = power.shape[1]
1841 listMeteors = []
1849 listMeteors = []
1842
1850
1843 for i in range(nHeights):
1851 for i in range(nHeights):
1844 powerAux = power[:,i]
1852 powerAux = power[:,i]
1845 threshAux = thresh[:,i]
1853 threshAux = thresh[:,i]
1846
1854
1847 indUPthresh = numpy.where(powerAux > threshAux)[0]
1855 indUPthresh = numpy.where(powerAux > threshAux)[0]
1848 indDNthresh = numpy.where(powerAux <= threshAux)[0]
1856 indDNthresh = numpy.where(powerAux <= threshAux)[0]
1849
1857
1850 j = 0
1858 j = 0
1851
1859
1852 while (j < indUPthresh.size - 2):
1860 while (j < indUPthresh.size - 2):
1853 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
1861 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
1854 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
1862 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
1855 indDNthresh = indDNthresh[indDNAux]
1863 indDNthresh = indDNthresh[indDNAux]
1856
1864
1857 if (indDNthresh.size > 0):
1865 if (indDNthresh.size > 0):
1858 indEnd = indDNthresh[0] - 1
1866 indEnd = indDNthresh[0] - 1
1859 indInit = indUPthresh[j] if isinstance(indUPthresh[j], (int, float)) else indUPthresh[j][0] ##CHECK!!!!
1867 indInit = indUPthresh[j] if isinstance(indUPthresh[j], (int, float)) else indUPthresh[j][0] ##CHECK!!!!
1860
1868
1861 meteor = powerAux[indInit:indEnd + 1]
1869 meteor = powerAux[indInit:indEnd + 1]
1862 indPeak = meteor.argmax() + indInit
1870 indPeak = meteor.argmax() + indInit
1863 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
1871 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
1864
1872
1865 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
1873 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
1866 j = numpy.where(indUPthresh == indEnd)[0] + 1
1874 j = numpy.where(indUPthresh == indEnd)[0] + 1
1867 else: j+=1
1875 else: j+=1
1868 else: j+=1
1876 else: j+=1
1869
1877
1870 return listMeteors
1878 return listMeteors
1871
1879
1872 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
1880 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
1873
1881
1874 arrayMeteors = numpy.asarray(listMeteors)
1882 arrayMeteors = numpy.asarray(listMeteors)
1875 listMeteors1 = []
1883 listMeteors1 = []
1876
1884
1877 while arrayMeteors.shape[0] > 0:
1885 while arrayMeteors.shape[0] > 0:
1878 FLAs = arrayMeteors[:,4]
1886 FLAs = arrayMeteors[:,4]
1879 maxFLA = FLAs.argmax()
1887 maxFLA = FLAs.argmax()
1880 listMeteors1.append(arrayMeteors[maxFLA,:])
1888 listMeteors1.append(arrayMeteors[maxFLA,:])
1881
1889
1882 MeteorInitTime = arrayMeteors[maxFLA,1]
1890 MeteorInitTime = arrayMeteors[maxFLA,1]
1883 MeteorEndTime = arrayMeteors[maxFLA,3]
1891 MeteorEndTime = arrayMeteors[maxFLA,3]
1884 MeteorHeight = arrayMeteors[maxFLA,0]
1892 MeteorHeight = arrayMeteors[maxFLA,0]
1885
1893
1886 #Check neighborhood
1894 #Check neighborhood
1887 maxHeightIndex = MeteorHeight + rangeLimit
1895 maxHeightIndex = MeteorHeight + rangeLimit
1888 minHeightIndex = MeteorHeight - rangeLimit
1896 minHeightIndex = MeteorHeight - rangeLimit
1889 minTimeIndex = MeteorInitTime - timeLimit
1897 minTimeIndex = MeteorInitTime - timeLimit
1890 maxTimeIndex = MeteorEndTime + timeLimit
1898 maxTimeIndex = MeteorEndTime + timeLimit
1891
1899
1892 #Check Heights
1900 #Check Heights
1893 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
1901 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
1894 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
1902 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
1895 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
1903 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
1896
1904
1897 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
1905 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
1898
1906
1899 return listMeteors1
1907 return listMeteors1
1900
1908
1901 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
1909 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
1902 numHeights = volts.shape[2]
1910 numHeights = volts.shape[2]
1903 nChannel = volts.shape[0]
1911 nChannel = volts.shape[0]
1904
1912
1905 thresholdPhase = thresh[0]
1913 thresholdPhase = thresh[0]
1906 thresholdNoise = thresh[1]
1914 thresholdNoise = thresh[1]
1907 thresholdDB = float(thresh[2])
1915 thresholdDB = float(thresh[2])
1908
1916
1909 thresholdDB1 = 10**(thresholdDB/10)
1917 thresholdDB1 = 10**(thresholdDB/10)
1910 pairsarray = numpy.array(pairslist)
1918 pairsarray = numpy.array(pairslist)
1911 indSides = pairsarray[:,1]
1919 indSides = pairsarray[:,1]
1912
1920
1913 pairslist1 = list(pairslist)
1921 pairslist1 = list(pairslist)
1914 pairslist1.append((0,4))
1922 pairslist1.append((0,4))
1915 pairslist1.append((1,3))
1923 pairslist1.append((1,3))
1916
1924
1917 listMeteors1 = []
1925 listMeteors1 = []
1918 listPowerSeries = []
1926 listPowerSeries = []
1919 listVoltageSeries = []
1927 listVoltageSeries = []
1920 #volts has the war data
1928 #volts has the war data
1921
1929
1922 if frequency == 30.175e6:
1930 if frequency == 30.175e6:
1923 timeLag = 45*10**-3
1931 timeLag = 45*10**-3
1924 else:
1932 else:
1925 timeLag = 15*10**-3
1933 timeLag = 15*10**-3
1926 lag = int(numpy.ceil(timeLag/timeInterval))
1934 lag = int(numpy.ceil(timeLag/timeInterval))
1927
1935
1928 for i in range(len(listMeteors)):
1936 for i in range(len(listMeteors)):
1929
1937
1930 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
1938 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
1931 meteorAux = numpy.zeros(16)
1939 meteorAux = numpy.zeros(16)
1932
1940
1933 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
1941 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
1934 mHeight = int(listMeteors[i][0])
1942 mHeight = int(listMeteors[i][0])
1935 mStart = int(listMeteors[i][1])
1943 mStart = int(listMeteors[i][1])
1936 mPeak = int(listMeteors[i][2])
1944 mPeak = int(listMeteors[i][2])
1937 mEnd = int(listMeteors[i][3])
1945 mEnd = int(listMeteors[i][3])
1938
1946
1939 #get the volt data between the start and end times of the meteor
1947 #get the volt data between the start and end times of the meteor
1940 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
1948 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
1941 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
1949 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
1942
1950
1943 #3.6. Phase Difference estimation
1951 #3.6. Phase Difference estimation
1944 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
1952 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
1945
1953
1946 #3.7. Phase difference removal & meteor start, peak and end times reestimated
1954 #3.7. Phase difference removal & meteor start, peak and end times reestimated
1947 #meteorVolts0.- all Channels, all Profiles
1955 #meteorVolts0.- all Channels, all Profiles
1948 meteorVolts0 = volts[:,:,mHeight]
1956 meteorVolts0 = volts[:,:,mHeight]
1949 meteorThresh = noise[:,mHeight]*thresholdNoise
1957 meteorThresh = noise[:,mHeight]*thresholdNoise
1950 meteorNoise = noise[:,mHeight]
1958 meteorNoise = noise[:,mHeight]
1951 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
1959 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
1952 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
1960 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
1953
1961
1954 #Times reestimation
1962 #Times reestimation
1955 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
1963 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
1956 if mStart1.size > 0:
1964 if mStart1.size > 0:
1957 mStart1 = mStart1[-1] + 1
1965 mStart1 = mStart1[-1] + 1
1958
1966
1959 else:
1967 else:
1960 mStart1 = mPeak
1968 mStart1 = mPeak
1961
1969
1962 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
1970 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
1963 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
1971 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
1964 if mEndDecayTime1.size == 0:
1972 if mEndDecayTime1.size == 0:
1965 mEndDecayTime1 = powerNet0.size
1973 mEndDecayTime1 = powerNet0.size
1966 else:
1974 else:
1967 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
1975 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
1968 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
1976 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
1969
1977
1970 #meteorVolts1.- all Channels, from start to end
1978 #meteorVolts1.- all Channels, from start to end
1971 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
1979 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
1972 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
1980 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
1973 if meteorVolts2.shape[1] == 0:
1981 if meteorVolts2.shape[1] == 0:
1974 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
1982 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
1975 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
1983 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
1976 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
1984 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
1977 ##################### END PARAMETERS REESTIMATION #########################
1985 ##################### END PARAMETERS REESTIMATION #########################
1978
1986
1979 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
1987 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
1980 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
1988 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
1981 if meteorVolts2.shape[1] > 0:
1989 if meteorVolts2.shape[1] > 0:
1982 #Phase Difference re-estimation
1990 #Phase Difference re-estimation
1983 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
1991 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
1984 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
1992 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
1985 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
1993 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
1986 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
1994 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
1987 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
1995 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
1988
1996
1989 #Phase Difference RMS
1997 #Phase Difference RMS
1990 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
1998 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
1991 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
1999 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
1992 #Data from Meteor
2000 #Data from Meteor
1993 mPeak1 = powerNet1.argmax() + mStart1
2001 mPeak1 = powerNet1.argmax() + mStart1
1994 mPeakPower1 = powerNet1.max()
2002 mPeakPower1 = powerNet1.max()
1995 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
2003 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
1996 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
2004 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
1997 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
2005 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
1998 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
2006 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
1999 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
2007 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
2000 #Vectorize
2008 #Vectorize
2001 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
2009 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
2002 meteorAux[7:11] = phaseDiffint[0:4]
2010 meteorAux[7:11] = phaseDiffint[0:4]
2003
2011
2004 #Rejection Criterions
2012 #Rejection Criterions
2005 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
2013 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
2006 meteorAux[-1] = 17
2014 meteorAux[-1] = 17
2007 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
2015 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
2008 meteorAux[-1] = 1
2016 meteorAux[-1] = 1
2009
2017
2010
2018
2011 else:
2019 else:
2012 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
2020 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
2013 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
2021 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
2014 PowerSeries = 0
2022 PowerSeries = 0
2015
2023
2016 listMeteors1.append(meteorAux)
2024 listMeteors1.append(meteorAux)
2017 listPowerSeries.append(PowerSeries)
2025 listPowerSeries.append(PowerSeries)
2018 listVoltageSeries.append(meteorVolts1)
2026 listVoltageSeries.append(meteorVolts1)
2019
2027
2020 return listMeteors1, listPowerSeries, listVoltageSeries
2028 return listMeteors1, listPowerSeries, listVoltageSeries
2021
2029
2022 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
2030 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
2023
2031
2024 threshError = 10
2032 threshError = 10
2025 #Depending if it is 30 or 50 MHz
2033 #Depending if it is 30 or 50 MHz
2026 if frequency == 30.175e6:
2034 if frequency == 30.175e6:
2027 timeLag = 45*10**-3
2035 timeLag = 45*10**-3
2028 else:
2036 else:
2029 timeLag = 15*10**-3
2037 timeLag = 15*10**-3
2030 lag = int(numpy.ceil(timeLag/timeInterval))
2038 lag = int(numpy.ceil(timeLag/timeInterval))
2031
2039
2032 listMeteors1 = []
2040 listMeteors1 = []
2033
2041
2034 for i in range(len(listMeteors)):
2042 for i in range(len(listMeteors)):
2035 meteorPower = listPower[i]
2043 meteorPower = listPower[i]
2036 meteorAux = listMeteors[i]
2044 meteorAux = listMeteors[i]
2037
2045
2038 if meteorAux[-1] == 0:
2046 if meteorAux[-1] == 0:
2039
2047
2040 try:
2048 try:
2041 indmax = meteorPower.argmax()
2049 indmax = meteorPower.argmax()
2042 indlag = indmax + lag
2050 indlag = indmax + lag
2043
2051
2044 y = meteorPower[indlag:]
2052 y = meteorPower[indlag:]
2045 x = numpy.arange(0, y.size)*timeLag
2053 x = numpy.arange(0, y.size)*timeLag
2046
2054
2047 #first guess
2055 #first guess
2048 a = y[0]
2056 a = y[0]
2049 tau = timeLag
2057 tau = timeLag
2050 #exponential fit
2058 #exponential fit
2051 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
2059 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
2052 y1 = self.__exponential_function(x, *popt)
2060 y1 = self.__exponential_function(x, *popt)
2053 #error estimation
2061 #error estimation
2054 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
2062 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
2055
2063
2056 decayTime = popt[1]
2064 decayTime = popt[1]
2057 riseTime = indmax*timeInterval
2065 riseTime = indmax*timeInterval
2058 meteorAux[11:13] = [decayTime, error]
2066 meteorAux[11:13] = [decayTime, error]
2059
2067
2060 #Table items 7, 8 and 11
2068 #Table items 7, 8 and 11
2061 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
2069 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
2062 meteorAux[-1] = 7
2070 meteorAux[-1] = 7
2063 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
2071 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
2064 meteorAux[-1] = 8
2072 meteorAux[-1] = 8
2065 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
2073 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
2066 meteorAux[-1] = 11
2074 meteorAux[-1] = 11
2067
2075
2068
2076
2069 except:
2077 except:
2070 meteorAux[-1] = 11
2078 meteorAux[-1] = 11
2071
2079
2072
2080
2073 listMeteors1.append(meteorAux)
2081 listMeteors1.append(meteorAux)
2074
2082
2075 return listMeteors1
2083 return listMeteors1
2076
2084
2077 #Exponential Function
2085 #Exponential Function
2078
2086
2079 def __exponential_function(self, x, a, tau):
2087 def __exponential_function(self, x, a, tau):
2080 y = a*numpy.exp(-x/tau)
2088 y = a*numpy.exp(-x/tau)
2081 return y
2089 return y
2082
2090
2083 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
2091 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
2084
2092
2085 pairslist1 = list(pairslist)
2093 pairslist1 = list(pairslist)
2086 pairslist1.append((0,4))
2094 pairslist1.append((0,4))
2087 pairslist1.append((1,3))
2095 pairslist1.append((1,3))
2088 numPairs = len(pairslist1)
2096 numPairs = len(pairslist1)
2089 #Time Lag
2097 #Time Lag
2090 timeLag = 45*10**-3
2098 timeLag = 45*10**-3
2091 c = 3e8
2099 c = 3e8
2092 lag = numpy.ceil(timeLag/timeInterval)
2100 lag = numpy.ceil(timeLag/timeInterval)
2093 freq = 30.175e6
2101 freq = 30.175e6
2094
2102
2095 listMeteors1 = []
2103 listMeteors1 = []
2096
2104
2097 for i in range(len(listMeteors)):
2105 for i in range(len(listMeteors)):
2098 meteorAux = listMeteors[i]
2106 meteorAux = listMeteors[i]
2099 if meteorAux[-1] == 0:
2107 if meteorAux[-1] == 0:
2100 mStart = listMeteors[i][1]
2108 mStart = listMeteors[i][1]
2101 mPeak = listMeteors[i][2]
2109 mPeak = listMeteors[i][2]
2102 mLag = mPeak - mStart + lag
2110 mLag = mPeak - mStart + lag
2103
2111
2104 #get the volt data between the start and end times of the meteor
2112 #get the volt data between the start and end times of the meteor
2105 meteorVolts = listVolts[i]
2113 meteorVolts = listVolts[i]
2106 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
2114 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
2107
2115
2108 #Get CCF
2116 #Get CCF
2109 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
2117 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
2110
2118
2111 #Method 2
2119 #Method 2
2112 slopes = numpy.zeros(numPairs)
2120 slopes = numpy.zeros(numPairs)
2113 time = numpy.array([-2,-1,1,2])*timeInterval
2121 time = numpy.array([-2,-1,1,2])*timeInterval
2114 angAllCCF = numpy.angle(allCCFs[:,[0,4,2,3],0])
2122 angAllCCF = numpy.angle(allCCFs[:,[0,4,2,3],0])
2115
2123
2116 #Correct phases
2124 #Correct phases
2117 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
2125 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
2118 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2126 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2119
2127
2120 if indDer[0].shape[0] > 0:
2128 if indDer[0].shape[0] > 0:
2121 for i in range(indDer[0].shape[0]):
2129 for i in range(indDer[0].shape[0]):
2122 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
2130 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
2123 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
2131 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
2124
2132
2125 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
2133 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
2126 for j in range(numPairs):
2134 for j in range(numPairs):
2127 fit = stats.linregress(time, angAllCCF[j,:])
2135 fit = stats.linregress(time, angAllCCF[j,:])
2128 slopes[j] = fit[0]
2136 slopes[j] = fit[0]
2129
2137
2130 #Remove Outlier
2138 #Remove Outlier
2131 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2139 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2132 # slopes = numpy.delete(slopes,indOut)
2140 # slopes = numpy.delete(slopes,indOut)
2133 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2141 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2134 # slopes = numpy.delete(slopes,indOut)
2142 # slopes = numpy.delete(slopes,indOut)
2135
2143
2136 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
2144 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
2137 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
2145 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
2138 meteorAux[-2] = radialError
2146 meteorAux[-2] = radialError
2139 meteorAux[-3] = radialVelocity
2147 meteorAux[-3] = radialVelocity
2140
2148
2141 #Setting Error
2149 #Setting Error
2142 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
2150 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
2143 if numpy.abs(radialVelocity) > 200:
2151 if numpy.abs(radialVelocity) > 200:
2144 meteorAux[-1] = 15
2152 meteorAux[-1] = 15
2145 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
2153 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
2146 elif radialError > radialStdThresh:
2154 elif radialError > radialStdThresh:
2147 meteorAux[-1] = 12
2155 meteorAux[-1] = 12
2148
2156
2149 listMeteors1.append(meteorAux)
2157 listMeteors1.append(meteorAux)
2150 return listMeteors1
2158 return listMeteors1
2151
2159
2152 def __setNewArrays(self, listMeteors, date, heiRang):
2160 def __setNewArrays(self, listMeteors, date, heiRang):
2153
2161
2154 #New arrays
2162 #New arrays
2155 arrayMeteors = numpy.array(listMeteors)
2163 arrayMeteors = numpy.array(listMeteors)
2156 arrayParameters = numpy.zeros((len(listMeteors), 13))
2164 arrayParameters = numpy.zeros((len(listMeteors), 13))
2157
2165
2158 #Date inclusion
2166 #Date inclusion
2159 # date = re.findall(r'\((.*?)\)', date)
2167 # date = re.findall(r'\((.*?)\)', date)
2160 # date = date[0].split(',')
2168 # date = date[0].split(',')
2161 # date = map(int, date)
2169 # date = map(int, date)
2162 #
2170 #
2163 # if len(date)<6:
2171 # if len(date)<6:
2164 # date.append(0)
2172 # date.append(0)
2165 #
2173 #
2166 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
2174 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
2167 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
2175 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
2168 arrayDate = numpy.tile(date, (len(listMeteors)))
2176 arrayDate = numpy.tile(date, (len(listMeteors)))
2169
2177
2170 #Meteor array
2178 #Meteor array
2171 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
2179 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
2172 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
2180 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
2173
2181
2174 #Parameters Array
2182 #Parameters Array
2175 arrayParameters[:,0] = arrayDate #Date
2183 arrayParameters[:,0] = arrayDate #Date
2176 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
2184 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
2177 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
2185 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
2178 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
2186 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
2179 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
2187 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
2180
2188
2181
2189
2182 return arrayParameters
2190 return arrayParameters
2183
2191
2184 class CorrectSMPhases(Operation):
2192 class CorrectSMPhases(Operation):
2185
2193
2186 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
2194 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
2187
2195
2188 arrayParameters = dataOut.data_param
2196 arrayParameters = dataOut.data_param
2189 pairsList = []
2197 pairsList = []
2190 pairx = (0,1)
2198 pairx = (0,1)
2191 pairy = (2,3)
2199 pairy = (2,3)
2192 pairsList.append(pairx)
2200 pairsList.append(pairx)
2193 pairsList.append(pairy)
2201 pairsList.append(pairy)
2194 jph = numpy.zeros(4)
2202 jph = numpy.zeros(4)
2195
2203
2196 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2204 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2197 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2205 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2198 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
2206 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
2199
2207
2200 meteorOps = SMOperations()
2208 meteorOps = SMOperations()
2201 if channelPositions is None:
2209 if channelPositions is None:
2202 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2210 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2203 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2211 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2204
2212
2205 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2213 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2206 h = (hmin,hmax)
2214 h = (hmin,hmax)
2207
2215
2208 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2216 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2209
2217
2210 dataOut.data_param = arrayParameters
2218 dataOut.data_param = arrayParameters
2211 return
2219 return
2212
2220
2213 class SMPhaseCalibration(Operation):
2221 class SMPhaseCalibration(Operation):
2214
2222
2215 __buffer = None
2223 __buffer = None
2216
2224
2217 __initime = None
2225 __initime = None
2218
2226
2219 __dataReady = False
2227 __dataReady = False
2220
2228
2221 __isConfig = False
2229 __isConfig = False
2222
2230
2223 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
2231 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
2224
2232
2225 dataTime = currentTime + paramInterval
2233 dataTime = currentTime + paramInterval
2226 deltaTime = dataTime - initTime
2234 deltaTime = dataTime - initTime
2227
2235
2228 if deltaTime >= outputInterval or deltaTime < 0:
2236 if deltaTime >= outputInterval or deltaTime < 0:
2229 return True
2237 return True
2230
2238
2231 return False
2239 return False
2232
2240
2233 def __getGammas(self, pairs, d, phases):
2241 def __getGammas(self, pairs, d, phases):
2234 gammas = numpy.zeros(2)
2242 gammas = numpy.zeros(2)
2235
2243
2236 for i in range(len(pairs)):
2244 for i in range(len(pairs)):
2237
2245
2238 pairi = pairs[i]
2246 pairi = pairs[i]
2239
2247
2240 phip3 = phases[:,pairi[1]]
2248 phip3 = phases[:,pairi[1]]
2241 d3 = d[pairi[1]]
2249 d3 = d[pairi[1]]
2242 phip2 = phases[:,pairi[0]]
2250 phip2 = phases[:,pairi[0]]
2243 d2 = d[pairi[0]]
2251 d2 = d[pairi[0]]
2244 #Calculating gamma
2252 #Calculating gamma
2245 # jdcos = alp1/(k*d1)
2253 # jdcos = alp1/(k*d1)
2246 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
2254 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
2247 jgamma = -phip2*d3/d2 - phip3
2255 jgamma = -phip2*d3/d2 - phip3
2248 jgamma = numpy.angle(numpy.exp(1j*jgamma))
2256 jgamma = numpy.angle(numpy.exp(1j*jgamma))
2249 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
2257 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
2250 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
2258 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
2251
2259
2252 #Revised distribution
2260 #Revised distribution
2253 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
2261 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
2254
2262
2255 #Histogram
2263 #Histogram
2256 nBins = 64.0
2264 nBins = 64.0
2257 rmin = -0.5*numpy.pi
2265 rmin = -0.5*numpy.pi
2258 rmax = 0.5*numpy.pi
2266 rmax = 0.5*numpy.pi
2259 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
2267 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
2260
2268
2261 meteorsY = phaseHisto[0]
2269 meteorsY = phaseHisto[0]
2262 phasesX = phaseHisto[1][:-1]
2270 phasesX = phaseHisto[1][:-1]
2263 width = phasesX[1] - phasesX[0]
2271 width = phasesX[1] - phasesX[0]
2264 phasesX += width/2
2272 phasesX += width/2
2265
2273
2266 #Gaussian aproximation
2274 #Gaussian aproximation
2267 bpeak = meteorsY.argmax()
2275 bpeak = meteorsY.argmax()
2268 peak = meteorsY.max()
2276 peak = meteorsY.max()
2269 jmin = bpeak - 5
2277 jmin = bpeak - 5
2270 jmax = bpeak + 5 + 1
2278 jmax = bpeak + 5 + 1
2271
2279
2272 if jmin<0:
2280 if jmin<0:
2273 jmin = 0
2281 jmin = 0
2274 jmax = 6
2282 jmax = 6
2275 elif jmax > meteorsY.size:
2283 elif jmax > meteorsY.size:
2276 jmin = meteorsY.size - 6
2284 jmin = meteorsY.size - 6
2277 jmax = meteorsY.size
2285 jmax = meteorsY.size
2278
2286
2279 x0 = numpy.array([peak,bpeak,50])
2287 x0 = numpy.array([peak,bpeak,50])
2280 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
2288 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
2281
2289
2282 #Gammas
2290 #Gammas
2283 gammas[i] = coeff[0][1]
2291 gammas[i] = coeff[0][1]
2284
2292
2285 return gammas
2293 return gammas
2286
2294
2287 def __residualFunction(self, coeffs, y, t):
2295 def __residualFunction(self, coeffs, y, t):
2288
2296
2289 return y - self.__gauss_function(t, coeffs)
2297 return y - self.__gauss_function(t, coeffs)
2290
2298
2291 def __gauss_function(self, t, coeffs):
2299 def __gauss_function(self, t, coeffs):
2292
2300
2293 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
2301 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
2294
2302
2295 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
2303 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
2296 meteorOps = SMOperations()
2304 meteorOps = SMOperations()
2297 nchan = 4
2305 nchan = 4
2298 pairx = pairsList[0]
2306 pairx = pairsList[0]
2299 pairy = pairsList[1]
2307 pairy = pairsList[1]
2300 center_xangle = 0
2308 center_xangle = 0
2301 center_yangle = 0
2309 center_yangle = 0
2302 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
2310 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
2303 ntimes = len(range_angle)
2311 ntimes = len(range_angle)
2304
2312
2305 nstepsx = 20.0
2313 nstepsx = 20.0
2306 nstepsy = 20.0
2314 nstepsy = 20.0
2307
2315
2308 for iz in range(ntimes):
2316 for iz in range(ntimes):
2309 min_xangle = -range_angle[iz]/2 + center_xangle
2317 min_xangle = -range_angle[iz]/2 + center_xangle
2310 max_xangle = range_angle[iz]/2 + center_xangle
2318 max_xangle = range_angle[iz]/2 + center_xangle
2311 min_yangle = -range_angle[iz]/2 + center_yangle
2319 min_yangle = -range_angle[iz]/2 + center_yangle
2312 max_yangle = range_angle[iz]/2 + center_yangle
2320 max_yangle = range_angle[iz]/2 + center_yangle
2313
2321
2314 inc_x = (max_xangle-min_xangle)/nstepsx
2322 inc_x = (max_xangle-min_xangle)/nstepsx
2315 inc_y = (max_yangle-min_yangle)/nstepsy
2323 inc_y = (max_yangle-min_yangle)/nstepsy
2316
2324
2317 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
2325 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
2318 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
2326 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
2319 penalty = numpy.zeros((nstepsx,nstepsy))
2327 penalty = numpy.zeros((nstepsx,nstepsy))
2320 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
2328 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
2321 jph = numpy.zeros(nchan)
2329 jph = numpy.zeros(nchan)
2322
2330
2323 # Iterations looking for the offset
2331 # Iterations looking for the offset
2324 for iy in range(int(nstepsy)):
2332 for iy in range(int(nstepsy)):
2325 for ix in range(int(nstepsx)):
2333 for ix in range(int(nstepsx)):
2326 jph[pairy[1]] = alpha_y[iy]
2334 jph[pairy[1]] = alpha_y[iy]
2327 jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
2335 jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
2328
2336
2329 jph[pairx[1]] = alpha_x[ix]
2337 jph[pairx[1]] = alpha_x[ix]
2330 jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
2338 jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
2331
2339
2332 jph_array[:,ix,iy] = jph
2340 jph_array[:,ix,iy] = jph
2333
2341
2334 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
2342 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
2335 error = meteorsArray1[:,-1]
2343 error = meteorsArray1[:,-1]
2336 ind1 = numpy.where(error==0)[0]
2344 ind1 = numpy.where(error==0)[0]
2337 penalty[ix,iy] = ind1.size
2345 penalty[ix,iy] = ind1.size
2338
2346
2339 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
2347 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
2340 phOffset = jph_array[:,i,j]
2348 phOffset = jph_array[:,i,j]
2341
2349
2342 center_xangle = phOffset[pairx[1]]
2350 center_xangle = phOffset[pairx[1]]
2343 center_yangle = phOffset[pairy[1]]
2351 center_yangle = phOffset[pairy[1]]
2344
2352
2345 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
2353 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
2346 phOffset = phOffset*180/numpy.pi
2354 phOffset = phOffset*180/numpy.pi
2347 return phOffset
2355 return phOffset
2348
2356
2349
2357
2350 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
2358 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
2351
2359
2352 dataOut.flagNoData = True
2360 dataOut.flagNoData = True
2353 self.__dataReady = False
2361 self.__dataReady = False
2354 dataOut.outputInterval = nHours*3600
2362 dataOut.outputInterval = nHours*3600
2355
2363
2356 if self.__isConfig == False:
2364 if self.__isConfig == False:
2357 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2365 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2358 #Get Initial LTC time
2366 #Get Initial LTC time
2359 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2367 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2360 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2368 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2361
2369
2362 self.__isConfig = True
2370 self.__isConfig = True
2363
2371
2364 if self.__buffer is None:
2372 if self.__buffer is None:
2365 self.__buffer = dataOut.data_param.copy()
2373 self.__buffer = dataOut.data_param.copy()
2366
2374
2367 else:
2375 else:
2368 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2376 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2369
2377
2370 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2378 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2371
2379
2372 if self.__dataReady:
2380 if self.__dataReady:
2373 dataOut.utctimeInit = self.__initime
2381 dataOut.utctimeInit = self.__initime
2374 self.__initime += dataOut.outputInterval #to erase time offset
2382 self.__initime += dataOut.outputInterval #to erase time offset
2375
2383
2376 freq = dataOut.frequency
2384 freq = dataOut.frequency
2377 c = dataOut.C #m/s
2385 c = dataOut.C #m/s
2378 lamb = c/freq
2386 lamb = c/freq
2379 k = 2*numpy.pi/lamb
2387 k = 2*numpy.pi/lamb
2380 azimuth = 0
2388 azimuth = 0
2381 h = (hmin, hmax)
2389 h = (hmin, hmax)
2382 pairs = ((0,1),(2,3))
2390 pairs = ((0,1),(2,3))
2383
2391
2384 if channelPositions is None:
2392 if channelPositions is None:
2385 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2393 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2386 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2394 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2387 meteorOps = SMOperations()
2395 meteorOps = SMOperations()
2388 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2396 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2389
2397
2390 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
2398 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
2391
2399
2392 meteorsArray = self.__buffer
2400 meteorsArray = self.__buffer
2393 error = meteorsArray[:,-1]
2401 error = meteorsArray[:,-1]
2394 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
2402 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
2395 ind1 = numpy.where(boolError)[0]
2403 ind1 = numpy.where(boolError)[0]
2396 meteorsArray = meteorsArray[ind1,:]
2404 meteorsArray = meteorsArray[ind1,:]
2397 meteorsArray[:,-1] = 0
2405 meteorsArray[:,-1] = 0
2398 phases = meteorsArray[:,8:12]
2406 phases = meteorsArray[:,8:12]
2399
2407
2400 #Calculate Gammas
2408 #Calculate Gammas
2401 gammas = self.__getGammas(pairs, distances, phases)
2409 gammas = self.__getGammas(pairs, distances, phases)
2402 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
2410 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
2403 #Calculate Phases
2411 #Calculate Phases
2404 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
2412 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
2405 phasesOff = phasesOff.reshape((1,phasesOff.size))
2413 phasesOff = phasesOff.reshape((1,phasesOff.size))
2406 dataOut.data_output = -phasesOff
2414 dataOut.data_output = -phasesOff
2407 dataOut.flagNoData = False
2415 dataOut.flagNoData = False
2408 dataOut.channelList = pairslist0
2416 dataOut.channelList = pairslist0
2409 self.__buffer = None
2417 self.__buffer = None
2410
2418
2411
2419
2412 return
2420 return
2413
2421
2414 class SMOperations():
2422 class SMOperations():
2415
2423
2416 def __init__(self):
2424 def __init__(self):
2417
2425
2418 return
2426 return
2419
2427
2420 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
2428 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
2421
2429
2422 arrayParameters = arrayParameters0.copy()
2430 arrayParameters = arrayParameters0.copy()
2423 hmin = h[0]
2431 hmin = h[0]
2424 hmax = h[1]
2432 hmax = h[1]
2425
2433
2426 #Calculate AOA (Error N 3, 4)
2434 #Calculate AOA (Error N 3, 4)
2427 #JONES ET AL. 1998
2435 #JONES ET AL. 1998
2428 AOAthresh = numpy.pi/8
2436 AOAthresh = numpy.pi/8
2429 error = arrayParameters[:,-1]
2437 error = arrayParameters[:,-1]
2430 phases = -arrayParameters[:,8:12] + jph
2438 phases = -arrayParameters[:,8:12] + jph
2431 # phases = numpy.unwrap(phases)
2439 # phases = numpy.unwrap(phases)
2432 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
2440 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
2433
2441
2434 #Calculate Heights (Error N 13 and 14)
2442 #Calculate Heights (Error N 13 and 14)
2435 error = arrayParameters[:,-1]
2443 error = arrayParameters[:,-1]
2436 Ranges = arrayParameters[:,1]
2444 Ranges = arrayParameters[:,1]
2437 zenith = arrayParameters[:,4]
2445 zenith = arrayParameters[:,4]
2438 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
2446 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
2439
2447
2440 #----------------------- Get Final data ------------------------------------
2448 #----------------------- Get Final data ------------------------------------
2441 # error = arrayParameters[:,-1]
2449 # error = arrayParameters[:,-1]
2442 # ind1 = numpy.where(error==0)[0]
2450 # ind1 = numpy.where(error==0)[0]
2443 # arrayParameters = arrayParameters[ind1,:]
2451 # arrayParameters = arrayParameters[ind1,:]
2444
2452
2445 return arrayParameters
2453 return arrayParameters
2446
2454
2447 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
2455 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
2448
2456
2449 arrayAOA = numpy.zeros((phases.shape[0],3))
2457 arrayAOA = numpy.zeros((phases.shape[0],3))
2450 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
2458 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
2451
2459
2452 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2460 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2453 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2461 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2454 arrayAOA[:,2] = cosDirError
2462 arrayAOA[:,2] = cosDirError
2455
2463
2456 azimuthAngle = arrayAOA[:,0]
2464 azimuthAngle = arrayAOA[:,0]
2457 zenithAngle = arrayAOA[:,1]
2465 zenithAngle = arrayAOA[:,1]
2458
2466
2459 #Setting Error
2467 #Setting Error
2460 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
2468 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
2461 error[indError] = 0
2469 error[indError] = 0
2462 #Number 3: AOA not fesible
2470 #Number 3: AOA not fesible
2463 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2471 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2464 error[indInvalid] = 3
2472 error[indInvalid] = 3
2465 #Number 4: Large difference in AOAs obtained from different antenna baselines
2473 #Number 4: Large difference in AOAs obtained from different antenna baselines
2466 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2474 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2467 error[indInvalid] = 4
2475 error[indInvalid] = 4
2468 return arrayAOA, error
2476 return arrayAOA, error
2469
2477
2470 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
2478 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
2471
2479
2472 #Initializing some variables
2480 #Initializing some variables
2473 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2481 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2474 ang_aux = ang_aux.reshape(1,ang_aux.size)
2482 ang_aux = ang_aux.reshape(1,ang_aux.size)
2475
2483
2476 cosdir = numpy.zeros((arrayPhase.shape[0],2))
2484 cosdir = numpy.zeros((arrayPhase.shape[0],2))
2477 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2485 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2478
2486
2479
2487
2480 for i in range(2):
2488 for i in range(2):
2481 ph0 = arrayPhase[:,pairsList[i][0]]
2489 ph0 = arrayPhase[:,pairsList[i][0]]
2482 ph1 = arrayPhase[:,pairsList[i][1]]
2490 ph1 = arrayPhase[:,pairsList[i][1]]
2483 d0 = distances[pairsList[i][0]]
2491 d0 = distances[pairsList[i][0]]
2484 d1 = distances[pairsList[i][1]]
2492 d1 = distances[pairsList[i][1]]
2485
2493
2486 ph0_aux = ph0 + ph1
2494 ph0_aux = ph0 + ph1
2487 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
2495 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
2488 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
2496 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
2489 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
2497 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
2490 #First Estimation
2498 #First Estimation
2491 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
2499 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
2492
2500
2493 #Most-Accurate Second Estimation
2501 #Most-Accurate Second Estimation
2494 phi1_aux = ph0 - ph1
2502 phi1_aux = ph0 - ph1
2495 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2503 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2496 #Direction Cosine 1
2504 #Direction Cosine 1
2497 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
2505 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
2498
2506
2499 #Searching the correct Direction Cosine
2507 #Searching the correct Direction Cosine
2500 cosdir0_aux = cosdir0[:,i]
2508 cosdir0_aux = cosdir0[:,i]
2501 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2509 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2502 #Minimum Distance
2510 #Minimum Distance
2503 cosDiff = (cosdir1 - cosdir0_aux)**2
2511 cosDiff = (cosdir1 - cosdir0_aux)**2
2504 indcos = cosDiff.argmin(axis = 1)
2512 indcos = cosDiff.argmin(axis = 1)
2505 #Saving Value obtained
2513 #Saving Value obtained
2506 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2514 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2507
2515
2508 return cosdir0, cosdir
2516 return cosdir0, cosdir
2509
2517
2510 def __calculateAOA(self, cosdir, azimuth):
2518 def __calculateAOA(self, cosdir, azimuth):
2511 cosdirX = cosdir[:,0]
2519 cosdirX = cosdir[:,0]
2512 cosdirY = cosdir[:,1]
2520 cosdirY = cosdir[:,1]
2513
2521
2514 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2522 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2515 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
2523 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
2516 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2524 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2517
2525
2518 return angles
2526 return angles
2519
2527
2520 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2528 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2521
2529
2522 Ramb = 375 #Ramb = c/(2*PRF)
2530 Ramb = 375 #Ramb = c/(2*PRF)
2523 Re = 6371 #Earth Radius
2531 Re = 6371 #Earth Radius
2524 heights = numpy.zeros(Ranges.shape)
2532 heights = numpy.zeros(Ranges.shape)
2525
2533
2526 R_aux = numpy.array([0,1,2])*Ramb
2534 R_aux = numpy.array([0,1,2])*Ramb
2527 R_aux = R_aux.reshape(1,R_aux.size)
2535 R_aux = R_aux.reshape(1,R_aux.size)
2528
2536
2529 Ranges = Ranges.reshape(Ranges.size,1)
2537 Ranges = Ranges.reshape(Ranges.size,1)
2530
2538
2531 Ri = Ranges + R_aux
2539 Ri = Ranges + R_aux
2532 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2540 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2533
2541
2534 #Check if there is a height between 70 and 110 km
2542 #Check if there is a height between 70 and 110 km
2535 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2543 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2536 ind_h = numpy.where(h_bool == 1)[0]
2544 ind_h = numpy.where(h_bool == 1)[0]
2537
2545
2538 hCorr = hi[ind_h, :]
2546 hCorr = hi[ind_h, :]
2539 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2547 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2540
2548
2541 hCorr = hi[ind_hCorr]
2549 hCorr = hi[ind_hCorr]
2542 heights[ind_h] = hCorr
2550 heights[ind_h] = hCorr
2543
2551
2544 #Setting Error
2552 #Setting Error
2545 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2553 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2546 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2554 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2547 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
2555 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
2548 error[indError] = 0
2556 error[indError] = 0
2549 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2557 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2550 error[indInvalid2] = 14
2558 error[indInvalid2] = 14
2551 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2559 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2552 error[indInvalid1] = 13
2560 error[indInvalid1] = 13
2553
2561
2554 return heights, error
2562 return heights, error
2555
2563
2556 def getPhasePairs(self, channelPositions):
2564 def getPhasePairs(self, channelPositions):
2557 chanPos = numpy.array(channelPositions)
2565 chanPos = numpy.array(channelPositions)
2558 listOper = list(itertools.combinations(range(5),2))
2566 listOper = list(itertools.combinations(range(5),2))
2559
2567
2560 distances = numpy.zeros(4)
2568 distances = numpy.zeros(4)
2561 axisX = []
2569 axisX = []
2562 axisY = []
2570 axisY = []
2563 distX = numpy.zeros(3)
2571 distX = numpy.zeros(3)
2564 distY = numpy.zeros(3)
2572 distY = numpy.zeros(3)
2565 ix = 0
2573 ix = 0
2566 iy = 0
2574 iy = 0
2567
2575
2568 pairX = numpy.zeros((2,2))
2576 pairX = numpy.zeros((2,2))
2569 pairY = numpy.zeros((2,2))
2577 pairY = numpy.zeros((2,2))
2570
2578
2571 for i in range(len(listOper)):
2579 for i in range(len(listOper)):
2572 pairi = listOper[i]
2580 pairi = listOper[i]
2573
2581
2574 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
2582 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
2575
2583
2576 if posDif[0] == 0:
2584 if posDif[0] == 0:
2577 axisY.append(pairi)
2585 axisY.append(pairi)
2578 distY[iy] = posDif[1]
2586 distY[iy] = posDif[1]
2579 iy += 1
2587 iy += 1
2580 elif posDif[1] == 0:
2588 elif posDif[1] == 0:
2581 axisX.append(pairi)
2589 axisX.append(pairi)
2582 distX[ix] = posDif[0]
2590 distX[ix] = posDif[0]
2583 ix += 1
2591 ix += 1
2584
2592
2585 for i in range(2):
2593 for i in range(2):
2586 if i==0:
2594 if i==0:
2587 dist0 = distX
2595 dist0 = distX
2588 axis0 = axisX
2596 axis0 = axisX
2589 else:
2597 else:
2590 dist0 = distY
2598 dist0 = distY
2591 axis0 = axisY
2599 axis0 = axisY
2592
2600
2593 side = numpy.argsort(dist0)[:-1]
2601 side = numpy.argsort(dist0)[:-1]
2594 axis0 = numpy.array(axis0)[side,:]
2602 axis0 = numpy.array(axis0)[side,:]
2595 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
2603 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
2596 axis1 = numpy.unique(numpy.reshape(axis0,4))
2604 axis1 = numpy.unique(numpy.reshape(axis0,4))
2597 side = axis1[axis1 != chanC]
2605 side = axis1[axis1 != chanC]
2598 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
2606 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
2599 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
2607 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
2600 if diff1<0:
2608 if diff1<0:
2601 chan2 = side[0]
2609 chan2 = side[0]
2602 d2 = numpy.abs(diff1)
2610 d2 = numpy.abs(diff1)
2603 chan1 = side[1]
2611 chan1 = side[1]
2604 d1 = numpy.abs(diff2)
2612 d1 = numpy.abs(diff2)
2605 else:
2613 else:
2606 chan2 = side[1]
2614 chan2 = side[1]
2607 d2 = numpy.abs(diff2)
2615 d2 = numpy.abs(diff2)
2608 chan1 = side[0]
2616 chan1 = side[0]
2609 d1 = numpy.abs(diff1)
2617 d1 = numpy.abs(diff1)
2610
2618
2611 if i==0:
2619 if i==0:
2612 chanCX = chanC
2620 chanCX = chanC
2613 chan1X = chan1
2621 chan1X = chan1
2614 chan2X = chan2
2622 chan2X = chan2
2615 distances[0:2] = numpy.array([d1,d2])
2623 distances[0:2] = numpy.array([d1,d2])
2616 else:
2624 else:
2617 chanCY = chanC
2625 chanCY = chanC
2618 chan1Y = chan1
2626 chan1Y = chan1
2619 chan2Y = chan2
2627 chan2Y = chan2
2620 distances[2:4] = numpy.array([d1,d2])
2628 distances[2:4] = numpy.array([d1,d2])
2621 # axisXsides = numpy.reshape(axisX[ix,:],4)
2629 # axisXsides = numpy.reshape(axisX[ix,:],4)
2622 #
2630 #
2623 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
2631 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
2624 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
2632 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
2625 #
2633 #
2626 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
2634 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
2627 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
2635 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
2628 # channel25X = int(pairX[0,ind25X])
2636 # channel25X = int(pairX[0,ind25X])
2629 # channel20X = int(pairX[1,ind20X])
2637 # channel20X = int(pairX[1,ind20X])
2630 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
2638 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
2631 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
2639 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
2632 # channel25Y = int(pairY[0,ind25Y])
2640 # channel25Y = int(pairY[0,ind25Y])
2633 # channel20Y = int(pairY[1,ind20Y])
2641 # channel20Y = int(pairY[1,ind20Y])
2634
2642
2635 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
2643 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
2636 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
2644 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
2637
2645
2638 return pairslist, distances
2646 return pairslist, distances
2639 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
2647 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
2640 #
2648 #
2641 # arrayAOA = numpy.zeros((phases.shape[0],3))
2649 # arrayAOA = numpy.zeros((phases.shape[0],3))
2642 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
2650 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
2643 #
2651 #
2644 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2652 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2645 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2653 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2646 # arrayAOA[:,2] = cosDirError
2654 # arrayAOA[:,2] = cosDirError
2647 #
2655 #
2648 # azimuthAngle = arrayAOA[:,0]
2656 # azimuthAngle = arrayAOA[:,0]
2649 # zenithAngle = arrayAOA[:,1]
2657 # zenithAngle = arrayAOA[:,1]
2650 #
2658 #
2651 # #Setting Error
2659 # #Setting Error
2652 # #Number 3: AOA not fesible
2660 # #Number 3: AOA not fesible
2653 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2661 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2654 # error[indInvalid] = 3
2662 # error[indInvalid] = 3
2655 # #Number 4: Large difference in AOAs obtained from different antenna baselines
2663 # #Number 4: Large difference in AOAs obtained from different antenna baselines
2656 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2664 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2657 # error[indInvalid] = 4
2665 # error[indInvalid] = 4
2658 # return arrayAOA, error
2666 # return arrayAOA, error
2659 #
2667 #
2660 # def __getDirectionCosines(self, arrayPhase, pairsList):
2668 # def __getDirectionCosines(self, arrayPhase, pairsList):
2661 #
2669 #
2662 # #Initializing some variables
2670 # #Initializing some variables
2663 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2671 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2664 # ang_aux = ang_aux.reshape(1,ang_aux.size)
2672 # ang_aux = ang_aux.reshape(1,ang_aux.size)
2665 #
2673 #
2666 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
2674 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
2667 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2675 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2668 #
2676 #
2669 #
2677 #
2670 # for i in range(2):
2678 # for i in range(2):
2671 # #First Estimation
2679 # #First Estimation
2672 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
2680 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
2673 # #Dealias
2681 # #Dealias
2674 # indcsi = numpy.where(phi0_aux > numpy.pi)
2682 # indcsi = numpy.where(phi0_aux > numpy.pi)
2675 # phi0_aux[indcsi] -= 2*numpy.pi
2683 # phi0_aux[indcsi] -= 2*numpy.pi
2676 # indcsi = numpy.where(phi0_aux < -numpy.pi)
2684 # indcsi = numpy.where(phi0_aux < -numpy.pi)
2677 # phi0_aux[indcsi] += 2*numpy.pi
2685 # phi0_aux[indcsi] += 2*numpy.pi
2678 # #Direction Cosine 0
2686 # #Direction Cosine 0
2679 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
2687 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
2680 #
2688 #
2681 # #Most-Accurate Second Estimation
2689 # #Most-Accurate Second Estimation
2682 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
2690 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
2683 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2691 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2684 # #Direction Cosine 1
2692 # #Direction Cosine 1
2685 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
2693 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
2686 #
2694 #
2687 # #Searching the correct Direction Cosine
2695 # #Searching the correct Direction Cosine
2688 # cosdir0_aux = cosdir0[:,i]
2696 # cosdir0_aux = cosdir0[:,i]
2689 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2697 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2690 # #Minimum Distance
2698 # #Minimum Distance
2691 # cosDiff = (cosdir1 - cosdir0_aux)**2
2699 # cosDiff = (cosdir1 - cosdir0_aux)**2
2692 # indcos = cosDiff.argmin(axis = 1)
2700 # indcos = cosDiff.argmin(axis = 1)
2693 # #Saving Value obtained
2701 # #Saving Value obtained
2694 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2702 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2695 #
2703 #
2696 # return cosdir0, cosdir
2704 # return cosdir0, cosdir
2697 #
2705 #
2698 # def __calculateAOA(self, cosdir, azimuth):
2706 # def __calculateAOA(self, cosdir, azimuth):
2699 # cosdirX = cosdir[:,0]
2707 # cosdirX = cosdir[:,0]
2700 # cosdirY = cosdir[:,1]
2708 # cosdirY = cosdir[:,1]
2701 #
2709 #
2702 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2710 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2703 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
2711 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
2704 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2712 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2705 #
2713 #
2706 # return angles
2714 # return angles
2707 #
2715 #
2708 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2716 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2709 #
2717 #
2710 # Ramb = 375 #Ramb = c/(2*PRF)
2718 # Ramb = 375 #Ramb = c/(2*PRF)
2711 # Re = 6371 #Earth Radius
2719 # Re = 6371 #Earth Radius
2712 # heights = numpy.zeros(Ranges.shape)
2720 # heights = numpy.zeros(Ranges.shape)
2713 #
2721 #
2714 # R_aux = numpy.array([0,1,2])*Ramb
2722 # R_aux = numpy.array([0,1,2])*Ramb
2715 # R_aux = R_aux.reshape(1,R_aux.size)
2723 # R_aux = R_aux.reshape(1,R_aux.size)
2716 #
2724 #
2717 # Ranges = Ranges.reshape(Ranges.size,1)
2725 # Ranges = Ranges.reshape(Ranges.size,1)
2718 #
2726 #
2719 # Ri = Ranges + R_aux
2727 # Ri = Ranges + R_aux
2720 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2728 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2721 #
2729 #
2722 # #Check if there is a height between 70 and 110 km
2730 # #Check if there is a height between 70 and 110 km
2723 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2731 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2724 # ind_h = numpy.where(h_bool == 1)[0]
2732 # ind_h = numpy.where(h_bool == 1)[0]
2725 #
2733 #
2726 # hCorr = hi[ind_h, :]
2734 # hCorr = hi[ind_h, :]
2727 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2735 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2728 #
2736 #
2729 # hCorr = hi[ind_hCorr]
2737 # hCorr = hi[ind_hCorr]
2730 # heights[ind_h] = hCorr
2738 # heights[ind_h] = hCorr
2731 #
2739 #
2732 # #Setting Error
2740 # #Setting Error
2733 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2741 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2734 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2742 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2735 #
2743 #
2736 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2744 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2737 # error[indInvalid2] = 14
2745 # error[indInvalid2] = 14
2738 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2746 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2739 # error[indInvalid1] = 13
2747 # error[indInvalid1] = 13
2740 #
2748 #
2741 # return heights, error
2749 # return heights, error
@@ -1,425 +1,437
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 cPickle as pickle
10 import cPickle as pickle
11 import datetime
11 import datetime
12 from zmq.utils.monitor import recv_monitor_message
12 from zmq.utils.monitor import recv_monitor_message
13 from functools import wraps
13 from functools import wraps
14 from threading import Thread
14 from threading import Thread
15 from multiprocessing import Process
15 from multiprocessing import Process
16
16
17 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
18
18
19 MAXNUMX = 100
19 MAXNUMX = 100
20 MAXNUMY = 100
20 MAXNUMY = 100
21
21
22 class PrettyFloat(float):
22 class PrettyFloat(float):
23 def __repr__(self):
23 def __repr__(self):
24 return '%.2f' % self
24 return '%.2f' % self
25
25
26 def roundFloats(obj):
26 def roundFloats(obj):
27 if isinstance(obj, list):
27 if isinstance(obj, list):
28 return map(roundFloats, obj)
28 return map(roundFloats, obj)
29 elif isinstance(obj, float):
29 elif isinstance(obj, float):
30 return round(obj, 2)
30 return round(obj, 2)
31
31
32 def decimate(z):
32 def decimate(z):
33 # dx = int(len(self.x)/self.__MAXNUMX) + 1
33 # dx = int(len(self.x)/self.__MAXNUMX) + 1
34
34
35 dy = int(len(z[0])/MAXNUMY) + 1
35 dy = int(len(z[0])/MAXNUMY) + 1
36
36
37 return z[::, ::dy]
37 return z[::, ::dy]
38
38
39 class throttle(object):
39 class throttle(object):
40 """Decorator that prevents a function from being called more than once every
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
75
76 class PublishData(Operation):
76 class PublishData(Operation):
77 """Clase publish."""
77 """Clase publish."""
78
78
79 def __init__(self, **kwargs):
79 def __init__(self, **kwargs):
80 """Inicio."""
80 """Inicio."""
81 Operation.__init__(self, **kwargs)
81 Operation.__init__(self, **kwargs)
82 self.isConfig = False
82 self.isConfig = False
83 self.client = None
83 self.client = None
84 self.zeromq = None
84 self.zeromq = None
85 self.mqtt = None
85 self.mqtt = None
86
86
87 def on_disconnect(self, client, userdata, rc):
87 def on_disconnect(self, client, userdata, rc):
88 if rc != 0:
88 if rc != 0:
89 print("Unexpected disconnection.")
89 print("Unexpected disconnection.")
90 self.connect()
90 self.connect()
91
91
92 def connect(self):
92 def connect(self):
93 print 'trying to connect'
93 print 'trying to connect'
94 try:
94 try:
95 self.client.connect(
95 self.client.connect(
96 host=self.host,
96 host=self.host,
97 port=self.port,
97 port=self.port,
98 keepalive=60*10,
98 keepalive=60*10,
99 bind_address='')
99 bind_address='')
100 self.client.loop_start()
100 self.client.loop_start()
101 # self.client.publish(
101 # self.client.publish(
102 # self.topic + 'SETUP',
102 # self.topic + 'SETUP',
103 # json.dumps(setup),
103 # json.dumps(setup),
104 # retain=True
104 # retain=True
105 # )
105 # )
106 except:
106 except:
107 print "MQTT Conection error."
107 print "MQTT Conection error."
108 self.client = False
108 self.client = False
109
109
110 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, **kwargs):
110 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, **kwargs):
111 self.counter = 0
111 self.counter = 0
112 self.topic = kwargs.get('topic', 'schain')
112 self.topic = kwargs.get('topic', 'schain')
113 self.delay = kwargs.get('delay', 0)
113 self.delay = kwargs.get('delay', 0)
114 self.plottype = kwargs.get('plottype', 'spectra')
114 self.plottype = kwargs.get('plottype', 'spectra')
115 self.host = kwargs.get('host', "10.10.10.82")
115 self.host = kwargs.get('host', "10.10.10.82")
116 self.port = kwargs.get('port', 3000)
116 self.port = kwargs.get('port', 3000)
117 self.clientId = clientId
117 self.clientId = clientId
118 self.cnt = 0
118 self.cnt = 0
119 self.zeromq = zeromq
119 self.zeromq = zeromq
120 self.mqtt = kwargs.get('plottype', 0)
120 self.mqtt = kwargs.get('plottype', 0)
121 self.client = None
121 self.client = None
122 setup = []
122 setup = []
123 if mqtt is 1:
123 if mqtt is 1:
124 self.client = mqtt.Client(
124 self.client = mqtt.Client(
125 client_id=self.clientId + self.topic + 'SCHAIN',
125 client_id=self.clientId + self.topic + 'SCHAIN',
126 clean_session=True)
126 clean_session=True)
127 self.client.on_disconnect = self.on_disconnect
127 self.client.on_disconnect = self.on_disconnect
128 self.connect()
128 self.connect()
129 for plot in self.plottype:
129 for plot in self.plottype:
130 setup.append({
130 setup.append({
131 'plot': plot,
131 'plot': plot,
132 'topic': self.topic + plot,
132 'topic': self.topic + plot,
133 'title': getattr(self, plot + '_' + 'title', False),
133 'title': getattr(self, plot + '_' + 'title', False),
134 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
134 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
135 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
135 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
136 'xrange': getattr(self, plot + '_' + 'xrange', False),
136 'xrange': getattr(self, plot + '_' + 'xrange', False),
137 'yrange': getattr(self, plot + '_' + 'yrange', False),
137 'yrange': getattr(self, plot + '_' + 'yrange', False),
138 'zrange': getattr(self, plot + '_' + 'zrange', False),
138 'zrange': getattr(self, plot + '_' + 'zrange', False),
139 })
139 })
140 if zeromq is 1:
140 if zeromq is 1:
141 context = zmq.Context()
141 context = zmq.Context()
142 self.zmq_socket = context.socket(zmq.PUSH)
142 self.zmq_socket = context.socket(zmq.PUSH)
143 server = kwargs.get('server', 'zmq.pipe')
143 server = kwargs.get('server', 'zmq.pipe')
144
144
145 if 'tcp://' in server:
145 if 'tcp://' in server:
146 address = server
146 address = server
147 else:
147 else:
148 address = 'ipc:///tmp/%s' % server
148 address = 'ipc:///tmp/%s' % server
149
149
150 self.zmq_socket.connect(address)
150 self.zmq_socket.connect(address)
151 time.sleep(1)
151 time.sleep(1)
152
152
153 def publish_data(self):
153 def publish_data(self):
154 self.dataOut.finished = False
154 self.dataOut.finished = False
155 if self.mqtt is 1:
155 if self.mqtt is 1:
156 yData = self.dataOut.heightList[:2].tolist()
156 yData = self.dataOut.heightList[:2].tolist()
157 if self.plottype == 'spectra':
157 if self.plottype == 'spectra':
158 data = getattr(self.dataOut, 'data_spc')
158 data = getattr(self.dataOut, 'data_spc')
159 z = data/self.dataOut.normFactor
159 z = data/self.dataOut.normFactor
160 zdB = 10*numpy.log10(z)
160 zdB = 10*numpy.log10(z)
161 xlen, ylen = zdB[0].shape
161 xlen, ylen = zdB[0].shape
162 dx = int(xlen/MAXNUMX) + 1
162 dx = int(xlen/MAXNUMX) + 1
163 dy = int(ylen/MAXNUMY) + 1
163 dy = int(ylen/MAXNUMY) + 1
164 Z = [0 for i in self.dataOut.channelList]
164 Z = [0 for i in self.dataOut.channelList]
165 for i in self.dataOut.channelList:
165 for i in self.dataOut.channelList:
166 Z[i] = zdB[i][::dx, ::dy].tolist()
166 Z[i] = zdB[i][::dx, ::dy].tolist()
167 payload = {
167 payload = {
168 'timestamp': self.dataOut.utctime,
168 'timestamp': self.dataOut.utctime,
169 'data': roundFloats(Z),
169 'data': roundFloats(Z),
170 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
170 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
171 'interval': self.dataOut.getTimeInterval(),
171 'interval': self.dataOut.getTimeInterval(),
172 'type': self.plottype,
172 'type': self.plottype,
173 'yData': yData
173 'yData': yData
174 }
174 }
175 # print payload
175 # print payload
176
176
177 elif self.plottype in ('rti', 'power'):
177 elif self.plottype in ('rti', 'power'):
178 data = getattr(self.dataOut, 'data_spc')
178 data = getattr(self.dataOut, 'data_spc')
179 z = data/self.dataOut.normFactor
179 z = data/self.dataOut.normFactor
180 avg = numpy.average(z, axis=1)
180 avg = numpy.average(z, axis=1)
181 avgdB = 10*numpy.log10(avg)
181 avgdB = 10*numpy.log10(avg)
182 xlen, ylen = z[0].shape
182 xlen, ylen = z[0].shape
183 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
183 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
184 AVG = [0 for i in self.dataOut.channelList]
184 AVG = [0 for i in self.dataOut.channelList]
185 for i in self.dataOut.channelList:
185 for i in self.dataOut.channelList:
186 AVG[i] = avgdB[i][::dy].tolist()
186 AVG[i] = avgdB[i][::dy].tolist()
187 payload = {
187 payload = {
188 'timestamp': self.dataOut.utctime,
188 'timestamp': self.dataOut.utctime,
189 'data': roundFloats(AVG),
189 'data': roundFloats(AVG),
190 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
190 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
191 'interval': self.dataOut.getTimeInterval(),
191 'interval': self.dataOut.getTimeInterval(),
192 'type': self.plottype,
192 'type': self.plottype,
193 'yData': yData
193 'yData': yData
194 }
194 }
195 elif self.plottype == 'noise':
195 elif self.plottype == 'noise':
196 noise = self.dataOut.getNoise()/self.dataOut.normFactor
196 noise = self.dataOut.getNoise()/self.dataOut.normFactor
197 noisedB = 10*numpy.log10(noise)
197 noisedB = 10*numpy.log10(noise)
198 payload = {
198 payload = {
199 'timestamp': self.dataOut.utctime,
199 'timestamp': self.dataOut.utctime,
200 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
200 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
201 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
201 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
202 'interval': self.dataOut.getTimeInterval(),
202 'interval': self.dataOut.getTimeInterval(),
203 'type': self.plottype,
203 'type': self.plottype,
204 'yData': yData
204 'yData': yData
205 }
205 }
206 elif self.plottype == 'snr':
206 elif self.plottype == 'snr':
207 data = getattr(self.dataOut, 'data_SNR')
207 data = getattr(self.dataOut, 'data_SNR')
208 avgdB = 10*numpy.log10(data)
208 avgdB = 10*numpy.log10(data)
209
209
210 ylen = data[0].size
210 ylen = data[0].size
211 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
211 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
212 AVG = [0 for i in self.dataOut.channelList]
212 AVG = [0 for i in self.dataOut.channelList]
213 for i in self.dataOut.channelList:
213 for i in self.dataOut.channelList:
214 AVG[i] = avgdB[i][::dy].tolist()
214 AVG[i] = avgdB[i][::dy].tolist()
215 payload = {
215 payload = {
216 'timestamp': self.dataOut.utctime,
216 'timestamp': self.dataOut.utctime,
217 'data': roundFloats(AVG),
217 'data': roundFloats(AVG),
218 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
218 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
219 'type': self.plottype,
219 'type': self.plottype,
220 'yData': yData
220 'yData': yData
221 }
221 }
222 else:
222 else:
223 print "Tipo de grafico invalido"
223 print "Tipo de grafico invalido"
224 payload = {
224 payload = {
225 'data': 'None',
225 'data': 'None',
226 'timestamp': 'None',
226 'timestamp': 'None',
227 'type': None
227 'type': None
228 }
228 }
229 # print 'Publishing data to {}'.format(self.host)
229 # print 'Publishing data to {}'.format(self.host)
230 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
230 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
231
231
232 if self.zeromq is 1:
232 if self.zeromq is 1:
233 print '[Sending] {} - {}'.format(self.dataOut.type, self.dataOut.datatime)
233 print '[Sending] {} - {}'.format(self.dataOut.type, self.dataOut.datatime)
234 self.zmq_socket.send_pyobj(self.dataOut)
234 self.zmq_socket.send_pyobj(self.dataOut)
235
235
236 def run(self, dataOut, **kwargs):
236 def run(self, dataOut, **kwargs):
237 self.dataOut = dataOut
237 self.dataOut = dataOut
238 if not self.isConfig:
238 if not self.isConfig:
239 self.setup(**kwargs)
239 self.setup(**kwargs)
240 self.isConfig = True
240 self.isConfig = True
241
241
242 self.publish_data()
242 self.publish_data()
243 time.sleep(self.delay)
243 time.sleep(self.delay)
244
244
245 def close(self):
245 def close(self):
246 if self.zeromq is 1:
246 if self.zeromq is 1:
247 self.dataOut.finished = True
247 self.dataOut.finished = True
248 self.zmq_socket.send_pyobj(self.dataOut)
248 self.zmq_socket.send_pyobj(self.dataOut)
249
249
250 if self.client:
250 if self.client:
251 self.client.loop_stop()
251 self.client.loop_stop()
252 self.client.disconnect()
252 self.client.disconnect()
253
253
254
254
255 class ReceiverData(ProcessingUnit, Process):
255 class ReceiverData(ProcessingUnit, Process):
256
256
257 throttle_value = 5
257 throttle_value = 5
258
258
259 def __init__(self, **kwargs):
259 def __init__(self, **kwargs):
260
260
261 ProcessingUnit.__init__(self, **kwargs)
261 ProcessingUnit.__init__(self, **kwargs)
262 Process.__init__(self)
262 Process.__init__(self)
263 self.mp = False
263 self.mp = False
264 self.isConfig = False
264 self.isConfig = False
265 self.isWebConfig = False
265 self.isWebConfig = False
266 self.plottypes =[]
266 self.plottypes =[]
267 self.connections = 0
267 self.connections = 0
268 server = kwargs.get('server', 'zmq.pipe')
268 server = kwargs.get('server', 'zmq.pipe')
269 plot_server = kwargs.get('plot_server', 'zmq.web')
269 plot_server = kwargs.get('plot_server', 'zmq.web')
270 if 'tcp://' in server:
270 if 'tcp://' in server:
271 address = server
271 address = server
272 else:
272 else:
273 address = 'ipc:///tmp/%s' % server
273 address = 'ipc:///tmp/%s' % server
274
274
275 if 'tcp://' in plot_server:
275 if 'tcp://' in plot_server:
276 plot_address = plot_server
276 plot_address = plot_server
277 else:
277 else:
278 plot_address = 'ipc:///tmp/%s' % plot_server
278 plot_address = 'ipc:///tmp/%s' % plot_server
279
279
280 self.address = address
280 self.address = address
281 self.plot_address = plot_address
281 self.plot_address = plot_address
282 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
282 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
283 self.realtime = kwargs.get('realtime', False)
283 self.realtime = kwargs.get('realtime', False)
284 self.throttle_value = kwargs.get('throttle', 10)
284 self.throttle_value = kwargs.get('throttle', 5)
285 self.sendData = self.initThrottle(self.throttle_value)
285 self.sendData = self.initThrottle(self.throttle_value)
286 self.setup()
286 self.setup()
287
287
288 def setup(self):
288 def setup(self):
289
289
290 self.data = {}
290 self.data = {}
291 self.data['times'] = []
291 self.data['times'] = []
292 for plottype in self.plottypes:
292 for plottype in self.plottypes:
293 self.data[plottype] = {}
293 self.data[plottype] = {}
294 self.data['noise'] = {}
294 self.data['noise'] = {}
295 self.data['throttle'] = self.throttle_value
295 self.data['throttle'] = self.throttle_value
296 self.data['ENDED'] = False
296 self.data['ENDED'] = False
297 self.isConfig = True
297 self.isConfig = True
298 self.data_web = {}
298 self.data_web = {}
299
299
300 def event_monitor(self, monitor):
300 def event_monitor(self, monitor):
301
301
302 events = {}
302 events = {}
303
303
304 for name in dir(zmq):
304 for name in dir(zmq):
305 if name.startswith('EVENT_'):
305 if name.startswith('EVENT_'):
306 value = getattr(zmq, name)
306 value = getattr(zmq, name)
307 events[value] = name
307 events[value] = name
308
308
309 while monitor.poll():
309 while monitor.poll():
310 evt = recv_monitor_message(monitor)
310 evt = recv_monitor_message(monitor)
311 if evt['event'] == 32:
311 if evt['event'] == 32:
312 self.connections += 1
312 self.connections += 1
313 if evt['event'] == 512:
313 if evt['event'] == 512:
314 pass
314 pass
315 if self.connections == 0 and self.started is True:
315 if self.connections == 0 and self.started is True:
316 self.ended = True
316 self.ended = True
317 # send('ENDED')
317 # send('ENDED')
318 evt.update({'description': events[evt['event']]})
318 evt.update({'description': events[evt['event']]})
319
319
320 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
320 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
321 break
321 break
322 monitor.close()
322 monitor.close()
323 print("event monitor thread done!")
323 print("event monitor thread done!")
324
324
325 def initThrottle(self, throttle_value):
325 def initThrottle(self, throttle_value):
326
326
327 @throttle(seconds=throttle_value)
327 @throttle(seconds=throttle_value)
328 def sendDataThrottled(fn_sender, data):
328 def sendDataThrottled(fn_sender, data):
329 fn_sender(data)
329 fn_sender(data)
330
330
331 return sendDataThrottled
331 return sendDataThrottled
332
332
333 def send(self, data):
333 def send(self, data):
334 # print '[sending] data=%s size=%s' % (data.keys(), len(data['times']))
334 # print '[sending] data=%s size=%s' % (data.keys(), len(data['times']))
335 self.sender.send_pyobj(data)
335 self.sender.send_pyobj(data)
336
336
337 def update(self):
337 def update(self):
338 t = self.dataOut.utctime
338 t = self.dataOut.utctime
339 self.data['times'].append(t)
339 self.data['times'].append(t)
340 self.data['dataOut'] = self.dataOut
340 self.data['dataOut'] = self.dataOut
341 for plottype in self.plottypes:
341 for plottype in self.plottypes:
342 if plottype == 'spc':
342 if plottype == 'spc':
343 z = self.dataOut.data_spc/self.dataOut.normFactor
343 z = self.dataOut.data_spc/self.dataOut.normFactor
344 self.data[plottype] = 10*numpy.log10(z)
344 self.data[plottype] = 10*numpy.log10(z)
345 self.data['noise'][t] = 10*numpy.log10(self.dataOut.getNoise()/self.dataOut.normFactor)
345 self.data['noise'][t] = 10*numpy.log10(self.dataOut.getNoise()/self.dataOut.normFactor)
346 if plottype == 'cspc':
347 jcoherence = self.dataOut.data_cspc/numpy.sqrt(self.dataOut.data_spc*self.dataOut.data_spc)
348 self.data['cspc_coh'] = numpy.abs(jcoherence)
349 self.data['cspc_phase'] = numpy.arctan2(jcoherence.imag, jcoherence.real)*180/numpy.pi
346 if plottype == 'rti':
350 if plottype == 'rti':
347 self.data[plottype][t] = self.dataOut.getPower()
351 self.data[plottype][t] = self.dataOut.getPower()
348 if plottype == 'snr':
352 if plottype == 'snr':
349 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_SNR)
353 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_SNR)
350 if plottype == 'dop':
354 if plottype == 'dop':
351 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_DOP)
355 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_DOP)
356 if plottype == 'mean':
357 self.data[plottype][t] = self.dataOut.data_MEAN
358 if plottype == 'std':
359 self.data[plottype][t] = self.dataOut.data_STD
352 if plottype == 'coh':
360 if plottype == 'coh':
353 self.data[plottype][t] = self.dataOut.getCoherence()
361 self.data[plottype][t] = self.dataOut.getCoherence()
354 if plottype == 'phase':
362 if plottype == 'phase':
355 self.data[plottype][t] = self.dataOut.getCoherence(phase=True)
363 self.data[plottype][t] = self.dataOut.getCoherence(phase=True)
356 if self.realtime:
364 if self.realtime:
357 self.data_web[plottype] = roundFloats(decimate(self.data[plottype][t]).tolist())
365 self.data_web['timestamp'] = t
358 self.data_web['timestamp'] = t
359 if plottype == 'spc':
366 if plottype == 'spc':
360 self.data_web[plottype] = roundFloats(decimate(self.data[plottype]).tolist())
367 self.data_web[plottype] = roundFloats(decimate(self.data[plottype]).tolist())
368 elif plottype == 'cspc':
369 self.data_web['cspc_coh'] = roundFloats(decimate(self.data['cspc_coh']).tolist())
370 self.data_web['cspc_phase'] = roundFloats(decimate(self.data['cspc_phase']).tolist())
371 elif plottype == 'noise':
372 self.data_web['noise'] = roundFloats(self.data['noise'][t].tolist())
361 else:
373 else:
362 self.data_web[plottype] = roundFloats(decimate(self.data[plottype][t]).tolist())
374 self.data_web[plottype] = roundFloats(decimate(self.data[plottype][t]).tolist())
363 self.data_web['interval'] = self.dataOut.getTimeInterval()
375 self.data_web['interval'] = self.dataOut.getTimeInterval()
364 self.data_web['type'] = plottype
376 self.data_web['type'] = plottype
365
377
366 def run(self):
378 def run(self):
367
379
368 print '[Starting] {} from {}'.format(self.name, self.address)
380 print '[Starting] {} from {}'.format(self.name, self.address)
369
381
370 self.context = zmq.Context()
382 self.context = zmq.Context()
371 self.receiver = self.context.socket(zmq.PULL)
383 self.receiver = self.context.socket(zmq.PULL)
372 self.receiver.bind(self.address)
384 self.receiver.bind(self.address)
373 monitor = self.receiver.get_monitor_socket()
385 monitor = self.receiver.get_monitor_socket()
374 self.sender = self.context.socket(zmq.PUB)
386 self.sender = self.context.socket(zmq.PUB)
375 if self.realtime:
387 if self.realtime:
376 self.sender_web = self.context.socket(zmq.PUB)
388 self.sender_web = self.context.socket(zmq.PUB)
377 self.sender_web.connect(self.plot_address)
389 self.sender_web.connect(self.plot_address)
378 time.sleep(1)
390 time.sleep(1)
379 self.sender.bind("ipc:///tmp/zmq.plots")
391 self.sender.bind("ipc:///tmp/zmq.plots")
380
392
381 t = Thread(target=self.event_monitor, args=(monitor,))
393 t = Thread(target=self.event_monitor, args=(monitor,))
382 t.start()
394 t.start()
383
395
384 while True:
396 while True:
385 self.dataOut = self.receiver.recv_pyobj()
397 self.dataOut = self.receiver.recv_pyobj()
386 # print '[Receiving] {} - {}'.format(self.dataOut.type,
398 # print '[Receiving] {} - {}'.format(self.dataOut.type,
387 # self.dataOut.datatime.ctime())
399 # self.dataOut.datatime.ctime())
388
400
389 self.update()
401 self.update()
390
402
391 if self.dataOut.finished is True:
403 if self.dataOut.finished is True:
392 self.send(self.data)
404 self.send(self.data)
393 self.connections -= 1
405 self.connections -= 1
394 if self.connections == 0 and self.started:
406 if self.connections == 0 and self.started:
395 self.ended = True
407 self.ended = True
396 self.data['ENDED'] = True
408 self.data['ENDED'] = True
397 self.send(self.data)
409 self.send(self.data)
398 self.setup()
410 self.setup()
399 else:
411 else:
400 if self.realtime:
412 if self.realtime:
401 self.send(self.data)
413 self.send(self.data)
402 self.sender_web.send_string(json.dumps(self.data_web))
414 self.sender_web.send_string(json.dumps(self.data_web))
403 else:
415 else:
404 self.sendData(self.send, self.data)
416 self.sendData(self.send, self.data)
405 self.started = True
417 self.started = True
406
418
407 return
419 return
408
420
409 def sendToWeb(self):
421 def sendToWeb(self):
410
422
411 if not self.isWebConfig:
423 if not self.isWebConfig:
412 context = zmq.Context()
424 context = zmq.Context()
413 sender_web_config = context.socket(zmq.PUB)
425 sender_web_config = context.socket(zmq.PUB)
414 if 'tcp://' in self.plot_address:
426 if 'tcp://' in self.plot_address:
415 dum, address, port = self.plot_address.split(':')
427 dum, address, port = self.plot_address.split(':')
416 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
428 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
417 else:
429 else:
418 conf_address = self.plot_address + '.config'
430 conf_address = self.plot_address + '.config'
419 sender_web_config.bind(conf_address)
431 sender_web_config.bind(conf_address)
420 time.sleep(1)
432 time.sleep(1)
421 for kwargs in self.operationKwargs.values():
433 for kwargs in self.operationKwargs.values():
422 if 'plot' in kwargs:
434 if 'plot' in kwargs:
423 print '[Sending] Config data to web for {}'.format(kwargs['code'].upper())
435 print '[Sending] Config data to web for {}'.format(kwargs['code'].upper())
424 sender_web_config.send_string(json.dumps(kwargs))
436 sender_web_config.send_string(json.dumps(kwargs))
425 self.isWebConfig = True
437 self.isWebConfig = True
General Comments 0
You need to be logged in to leave comments. Login now