##// END OF EJS Templates
GetMoments bug fixed
Julio Valdez -
r549:7ef3a32aff91
parent child
Show More
@@ -1,1770 +1,1780
1 import numpy
1 import numpy
2 import math
2 import math
3 from scipy import optimize
3 from scipy import optimize
4 from scipy import interpolate
4 from scipy import interpolate
5 from scipy import signal
5 from scipy import signal
6 from scipy import stats
6 from scipy import stats
7 import re
7 import re
8 import datetime
8 import datetime
9 import copy
9 import copy
10 import sys
10 import sys
11 import importlib
11 import importlib
12 import itertools
12 import itertools
13
13
14 from jroproc_base import ProcessingUnit, Operation
14 from jroproc_base import ProcessingUnit, Operation
15 from model.data.jrodata import Parameters
15 from model.data.jrodata import Parameters
16
16
17
17
18 class ParametersProc(ProcessingUnit):
18 class ParametersProc(ProcessingUnit):
19
19
20 nSeconds = None
20 nSeconds = None
21
21
22 def __init__(self):
22 def __init__(self):
23 ProcessingUnit.__init__(self)
23 ProcessingUnit.__init__(self)
24
24
25 # self.objectDict = {}
25 # self.objectDict = {}
26 self.buffer = None
26 self.buffer = None
27 self.firstdatatime = None
27 self.firstdatatime = None
28 self.profIndex = 0
28 self.profIndex = 0
29 self.dataOut = Parameters()
29 self.dataOut = Parameters()
30
30
31 def __updateObjFromInput(self):
31 def __updateObjFromInput(self):
32
32
33 self.dataOut.inputUnit = self.dataIn.type
33 self.dataOut.inputUnit = self.dataIn.type
34
34
35 self.dataOut.timeZone = self.dataIn.timeZone
35 self.dataOut.timeZone = self.dataIn.timeZone
36 self.dataOut.dstFlag = self.dataIn.dstFlag
36 self.dataOut.dstFlag = self.dataIn.dstFlag
37 self.dataOut.errorCount = self.dataIn.errorCount
37 self.dataOut.errorCount = self.dataIn.errorCount
38 self.dataOut.useLocalTime = self.dataIn.useLocalTime
38 self.dataOut.useLocalTime = self.dataIn.useLocalTime
39
39
40 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
40 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
41 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
41 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
42 self.dataOut.channelList = self.dataIn.channelList
42 self.dataOut.channelList = self.dataIn.channelList
43 self.dataOut.heightList = self.dataIn.heightList
43 self.dataOut.heightList = self.dataIn.heightList
44 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
44 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
45 # self.dataOut.nHeights = self.dataIn.nHeights
45 # self.dataOut.nHeights = self.dataIn.nHeights
46 # self.dataOut.nChannels = self.dataIn.nChannels
46 # self.dataOut.nChannels = self.dataIn.nChannels
47 self.dataOut.nBaud = self.dataIn.nBaud
47 self.dataOut.nBaud = self.dataIn.nBaud
48 self.dataOut.nCode = self.dataIn.nCode
48 self.dataOut.nCode = self.dataIn.nCode
49 self.dataOut.code = self.dataIn.code
49 self.dataOut.code = self.dataIn.code
50 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
50 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
51 self.dataOut.flagTimeBlock = self.dataIn.flagTimeBlock
51 self.dataOut.flagTimeBlock = self.dataIn.flagTimeBlock
52 self.dataOut.utctime = self.firstdatatime
52 self.dataOut.utctime = self.firstdatatime
53 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
53 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
54 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
54 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
55 # self.dataOut.nCohInt = self.dataIn.nCohInt
55 # self.dataOut.nCohInt = self.dataIn.nCohInt
56 # self.dataOut.nIncohInt = 1
56 # self.dataOut.nIncohInt = 1
57 self.dataOut.ippSeconds = self.dataIn.ippSeconds
57 self.dataOut.ippSeconds = self.dataIn.ippSeconds
58 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
58 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
59 self.dataOut.timeInterval = self.dataIn.timeInterval
59 self.dataOut.timeInterval = self.dataIn.timeInterval
60 self.dataOut.heightList = self.dataIn.getHeiRange()
60 self.dataOut.heightList = self.dataIn.getHeiRange()
61 self.dataOut.frequency = self.dataIn.frequency
61 self.dataOut.frequency = self.dataIn.frequency
62
62
63 def run(self, nSeconds = None, nProfiles = None):
63 def run(self, nSeconds = None, nProfiles = None):
64
64
65
65
66
66
67 if self.firstdatatime == None:
67 if self.firstdatatime == None:
68 self.firstdatatime = self.dataIn.utctime
68 self.firstdatatime = self.dataIn.utctime
69
69
70 #---------------------- Voltage Data ---------------------------
70 #---------------------- Voltage Data ---------------------------
71
71
72 if self.dataIn.type == "Voltage":
72 if self.dataIn.type == "Voltage":
73 self.dataOut.flagNoData = True
73 self.dataOut.flagNoData = True
74 if nSeconds != None:
74 if nSeconds != None:
75 self.nSeconds = nSeconds
75 self.nSeconds = nSeconds
76 self.nProfiles= int(numpy.floor(nSeconds/(self.dataIn.ippSeconds*self.dataIn.nCohInt)))
76 self.nProfiles= int(numpy.floor(nSeconds/(self.dataIn.ippSeconds*self.dataIn.nCohInt)))
77
77
78 if self.buffer == None:
78 if self.buffer == None:
79 self.buffer = numpy.zeros((self.dataIn.nChannels,
79 self.buffer = numpy.zeros((self.dataIn.nChannels,
80 self.nProfiles,
80 self.nProfiles,
81 self.dataIn.nHeights),
81 self.dataIn.nHeights),
82 dtype='complex')
82 dtype='complex')
83
83
84 self.buffer[:,self.profIndex,:] = self.dataIn.data.copy()
84 self.buffer[:,self.profIndex,:] = self.dataIn.data.copy()
85 self.profIndex += 1
85 self.profIndex += 1
86
86
87 if self.profIndex == self.nProfiles:
87 if self.profIndex == self.nProfiles:
88
88
89 self.__updateObjFromInput()
89 self.__updateObjFromInput()
90 self.dataOut.data_pre = self.buffer.copy()
90 self.dataOut.data_pre = self.buffer.copy()
91 self.dataOut.paramInterval = nSeconds
91 self.dataOut.paramInterval = nSeconds
92 self.dataOut.flagNoData = False
92 self.dataOut.flagNoData = False
93
93
94 self.buffer = None
94 self.buffer = None
95 self.firstdatatime = None
95 self.firstdatatime = None
96 self.profIndex = 0
96 self.profIndex = 0
97 return
97 return
98
98
99 #---------------------- Spectra Data ---------------------------
99 #---------------------- Spectra Data ---------------------------
100
100
101 if self.dataIn.type == "Spectra":
101 if self.dataIn.type == "Spectra":
102 self.dataOut.data_pre = self.dataIn.data_spc.copy()
102 self.dataOut.data_pre = self.dataIn.data_spc.copy()
103 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
103 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
104 self.dataOut.noise = self.dataIn.getNoise()
104 self.dataOut.noise = self.dataIn.getNoise()
105 self.dataOut.normFactor = self.dataIn.normFactor
105 self.dataOut.normFactor = self.dataIn.normFactor
106 self.dataOut.groupList = self.dataIn.pairsList
106 self.dataOut.flagNoData = False
107 self.dataOut.flagNoData = False
107
108
108 #---------------------- Correlation Data ---------------------------
109 #---------------------- Correlation Data ---------------------------
109
110
110 if self.dataIn.type == "Correlation":
111 if self.dataIn.type == "Correlation":
111 lagRRange = self.dataIn.lagR
112 lagRRange = self.dataIn.lagR
112 indR = numpy.where(lagRRange == 0)[0][0]
113 indR = numpy.where(lagRRange == 0)[0][0]
113
114
114 self.dataOut.data_pre = self.dataIn.data_corr.copy()[:,:,indR,:]
115 self.dataOut.data_pre = self.dataIn.data_corr.copy()[:,:,indR,:]
115 self.dataOut.abscissaList = self.dataIn.getLagTRange(1)
116 self.dataOut.abscissaList = self.dataIn.getLagTRange(1)
116 self.dataOut.noise = self.dataIn.noise
117 self.dataOut.noise = self.dataIn.noise
117 self.dataOut.normFactor = self.dataIn.normFactor
118 self.dataOut.normFactor = self.dataIn.normFactor
118 self.dataOut.data_SNR = self.dataIn.SNR
119 self.dataOut.data_SNR = self.dataIn.SNR
119 self.dataOut.groupList = self.dataIn.pairsList
120 self.dataOut.groupList = self.dataIn.pairsList
120 self.dataOut.flagNoData = False
121 self.dataOut.flagNoData = False
121
122
122 #---------------------- Correlation Data ---------------------------
123 #---------------------- Correlation Data ---------------------------
123
124
124 if self.dataIn.type == "Parameters":
125 if self.dataIn.type == "Parameters":
125 self.dataOut.copy(self.dataIn)
126 self.dataOut.copy(self.dataIn)
126 self.dataOut.flagNoData = False
127 self.dataOut.flagNoData = False
127
128
128 return True
129 return True
129
130
130 self.__updateObjFromInput()
131 self.__updateObjFromInput()
131 self.firstdatatime = None
132 self.firstdatatime = None
132 self.dataOut.utctimeInit = self.dataIn.utctime
133 self.dataOut.utctimeInit = self.dataIn.utctime
133 self.dataOut.outputInterval = self.dataIn.timeInterval
134 self.dataOut.outputInterval = self.dataIn.timeInterval
134
135
135 #------------------- Get Moments ----------------------------------
136 #------------------- Get Moments ----------------------------------
136 def GetMoments(self, channelList = None):
137 def GetMoments(self, channelList = None):
137 '''
138 '''
138 Function GetMoments()
139 Function GetMoments()
139
140
140 Input:
141 Input:
141 channelList : simple channel list to select e.g. [2,3,7]
142 channelList : simple channel list to select e.g. [2,3,7]
142 self.dataOut.data_pre
143 self.dataOut.data_pre
143 self.dataOut.abscissaList
144 self.dataOut.abscissaList
144 self.dataOut.noise
145 self.dataOut.noise
145
146
146 Affected:
147 Affected:
147 self.dataOut.data_param
148 self.dataOut.data_param
148 self.dataOut.data_SNR
149 self.dataOut.data_SNR
149
150
150 '''
151 '''
151 data = self.dataOut.data_pre
152 data = self.dataOut.data_pre
152 absc = self.dataOut.abscissaList[:-1]
153 absc = self.dataOut.abscissaList[:-1]
153 noise = self.dataOut.noise
154 noise = self.dataOut.noise
154
155
155 data_param = numpy.zeros((data.shape[0], 4, data.shape[2]))
156 data_param = numpy.zeros((data.shape[0], 4, data.shape[2]))
156
157
157 if channelList== None:
158 if channelList== None:
158 channelList = self.dataIn.channelList
159 channelList = self.dataIn.channelList
159 self.dataOut.channelList = channelList
160 self.dataOut.channelList = channelList
160
161
161 for ind in channelList:
162 for ind in channelList:
162 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:], absc, noise[ind])
163 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:], absc, noise[ind])
163
164
164 self.dataOut.data_param = data_param[:,1:,:]
165 self.dataOut.data_param = data_param[:,1:,:]
165 self.dataOut.data_SNR = data_param[:,0]
166 self.dataOut.data_SNR = data_param[:,0]
166 return
167 return
167
168
168 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):
169 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):
169
170
170 if (nicoh == None): nicoh = 1
171 if (nicoh == None): nicoh = 1
171 if (graph == None): graph = 0
172 if (graph == None): graph = 0
172 if (smooth == None): smooth = 0
173 if (smooth == None): smooth = 0
173 elif (self.smooth < 3): smooth = 0
174 elif (self.smooth < 3): smooth = 0
174
175
175 if (type1 == None): type1 = 0
176 if (type1 == None): type1 = 0
176 if (fwindow == None): fwindow = numpy.zeros(oldfreq.size) + 1
177 if (fwindow == None): fwindow = numpy.zeros(oldfreq.size) + 1
177 if (snrth == None): snrth = -3
178 if (snrth == None): snrth = -3
178 if (dc == None): dc = 0
179 if (dc == None): dc = 0
179 if (aliasing == None): aliasing = 0
180 if (aliasing == None): aliasing = 0
180 if (oldfd == None): oldfd = 0
181 if (oldfd == None): oldfd = 0
181 if (wwauto == None): wwauto = 0
182 if (wwauto == None): wwauto = 0
182
183
183 if (n0 < 1.e-20): n0 = 1.e-20
184 if (n0 < 1.e-20): n0 = 1.e-20
184
185
185 freq = oldfreq
186 freq = oldfreq
186 vec_power = numpy.zeros(oldspec.shape[1])
187 vec_power = numpy.zeros(oldspec.shape[1])
187 vec_fd = numpy.zeros(oldspec.shape[1])
188 vec_fd = numpy.zeros(oldspec.shape[1])
188 vec_w = numpy.zeros(oldspec.shape[1])
189 vec_w = numpy.zeros(oldspec.shape[1])
189 vec_snr = numpy.zeros(oldspec.shape[1])
190 vec_snr = numpy.zeros(oldspec.shape[1])
190
191
191 for ind in range(oldspec.shape[1]):
192 for ind in range(oldspec.shape[1]):
192
193
193 spec = oldspec[:,ind]
194 spec = oldspec[:,ind]
194 aux = spec*fwindow
195 aux = spec*fwindow
195 max_spec = aux.max()
196 max_spec = aux.max()
196 m = list(aux).index(max_spec)
197 m = list(aux).index(max_spec)
197
198
198 #Smooth
199 #Smooth
199 if (smooth == 0): spec2 = spec
200 if (smooth == 0): spec2 = spec
200 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
201 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
201
202
202 # Calculo de Momentos
203 # Calculo de Momentos
203 bb = spec2[range(m,spec2.size)]
204 bb = spec2[range(m,spec2.size)]
204 bb = (bb<n0).nonzero()
205 bb = (bb<n0).nonzero()
205 bb = bb[0]
206 bb = bb[0]
206
207
207 ss = spec2[range(0,m + 1)]
208 ss = spec2[range(0,m + 1)]
208 ss = (ss<n0).nonzero()
209 ss = (ss<n0).nonzero()
209 ss = ss[0]
210 ss = ss[0]
210
211
211 if (bb.size == 0):
212 if (bb.size == 0):
212 bb0 = spec.size - 1 - m
213 bb0 = spec.size - 1 - m
213 else:
214 else:
214 bb0 = bb[0] - 1
215 bb0 = bb[0] - 1
215 if (bb0 < 0):
216 if (bb0 < 0):
216 bb0 = 0
217 bb0 = 0
217
218
218 if (ss.size == 0): ss1 = 1
219 if (ss.size == 0): ss1 = 1
219 else: ss1 = max(ss) + 1
220 else: ss1 = max(ss) + 1
220
221
221 if (ss1 > m): ss1 = m
222 if (ss1 > m): ss1 = m
222
223
223 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
224 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
224 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
225 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
225 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
226 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
226 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
227 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
227 snr = (spec2.mean()-n0)/n0
228 snr = (spec2.mean()-n0)/n0
228
229
229 if (snr < 1.e-20) :
230 if (snr < 1.e-20) :
230 snr = 1.e-20
231 snr = 1.e-20
231
232
232 vec_power[ind] = power
233 vec_power[ind] = power
233 vec_fd[ind] = fd
234 vec_fd[ind] = fd
234 vec_w[ind] = w
235 vec_w[ind] = w
235 vec_snr[ind] = snr
236 vec_snr[ind] = snr
236
237
237 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
238 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
238 return moments
239 return moments
239
240
241 #------------------ Get SA Parameters --------------------------
242 def GetSAParameters(self):
243 data = self.dataOut.data_pre
244 crossdata = self.dataIn.data_cspc
245 a = 1
246
247
248
240 #------------------- Get Lags ----------------------------------
249 #------------------- Get Lags ----------------------------------
241
250
242 def GetLags(self):
251 def GetLags(self):
243 '''
252 '''
244 Function GetMoments()
253 Function GetMoments()
245
254
246 Input:
255 Input:
247 self.dataOut.data_pre
256 self.dataOut.data_pre
248 self.dataOut.abscissaList
257 self.dataOut.abscissaList
249 self.dataOut.noise
258 self.dataOut.noise
250 self.dataOut.normFactor
259 self.dataOut.normFactor
251 self.dataOut.data_SNR
260 self.dataOut.data_SNR
252 self.dataOut.groupList
261 self.dataOut.groupList
253 self.dataOut.nChannels
262 self.dataOut.nChannels
254
263
255 Affected:
264 Affected:
256 self.dataOut.data_param
265 self.dataOut.data_param
257
266
258 '''
267 '''
268
259 data = self.dataOut.data_pre
269 data = self.dataOut.data_pre
260 normFactor = self.dataOut.normFactor
270 normFactor = self.dataOut.normFactor
261 nHeights = self.dataOut.nHeights
271 nHeights = self.dataOut.nHeights
262 absc = self.dataOut.abscissaList[:-1]
272 absc = self.dataOut.abscissaList[:-1]
263 noise = self.dataOut.noise
273 noise = self.dataOut.noise
264 SNR = self.dataOut.data_SNR
274 SNR = self.dataOut.data_SNR
265 pairsList = self.dataOut.groupList
275 pairsList = self.dataOut.groupList
266 nChannels = self.dataOut.nChannels
276 nChannels = self.dataOut.nChannels
267 pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
277 pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
268 self.dataOut.data_param = numpy.zeros((len(pairsCrossCorr)*2 + 1, nHeights))
278 self.dataOut.data_param = numpy.zeros((len(pairsCrossCorr)*2 + 1, nHeights))
269
279
270 dataNorm = numpy.abs(data)
280 dataNorm = numpy.abs(data)
271 for l in range(len(pairsList)):
281 for l in range(len(pairsList)):
272 dataNorm[l,:,:] = dataNorm[l,:,:]/normFactor[l,:]
282 dataNorm[l,:,:] = dataNorm[l,:,:]/normFactor[l,:]
273
283
274 self.dataOut.data_param[:-1,:] = self.__calculateTaus(dataNorm, pairsCrossCorr, pairsAutoCorr, absc)
284 self.dataOut.data_param[:-1,:] = self.__calculateTaus(dataNorm, pairsCrossCorr, pairsAutoCorr, absc)
275 self.dataOut.data_param[-1,:] = self.__calculateLag1Phase(data, pairsAutoCorr, absc)
285 self.dataOut.data_param[-1,:] = self.__calculateLag1Phase(data, pairsAutoCorr, absc)
276 return
286 return
277
287
278 def __getPairsAutoCorr(self, pairsList, nChannels):
288 def __getPairsAutoCorr(self, pairsList, nChannels):
279
289
280 pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
290 pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
281
291
282 for l in range(len(pairsList)):
292 for l in range(len(pairsList)):
283 firstChannel = pairsList[l][0]
293 firstChannel = pairsList[l][0]
284 secondChannel = pairsList[l][1]
294 secondChannel = pairsList[l][1]
285
295
286 #Obteniendo pares de Autocorrelacion
296 #Obteniendo pares de Autocorrelacion
287 if firstChannel == secondChannel:
297 if firstChannel == secondChannel:
288 pairsAutoCorr[firstChannel] = int(l)
298 pairsAutoCorr[firstChannel] = int(l)
289
299
290 pairsAutoCorr = pairsAutoCorr.astype(int)
300 pairsAutoCorr = pairsAutoCorr.astype(int)
291
301
292 pairsCrossCorr = range(len(pairsList))
302 pairsCrossCorr = range(len(pairsList))
293 pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
303 pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
294
304
295 return pairsAutoCorr, pairsCrossCorr
305 return pairsAutoCorr, pairsCrossCorr
296
306
297 def __calculateTaus(self, data, pairsCrossCorr, pairsAutoCorr, lagTRange):
307 def __calculateTaus(self, data, pairsCrossCorr, pairsAutoCorr, lagTRange):
298
308
299 Pt0 = data.shape[1]/2
309 Pt0 = data.shape[1]/2
300 #Funcion de Autocorrelacion
310 #Funcion de Autocorrelacion
301 dataAutoCorr = stats.nanmean(data[pairsAutoCorr,:,:], axis = 0)
311 dataAutoCorr = stats.nanmean(data[pairsAutoCorr,:,:], axis = 0)
302
312
303 #Obtencion Indice de TauCross
313 #Obtencion Indice de TauCross
304 indCross = data[pairsCrossCorr,:,:].argmax(axis = 1)
314 indCross = data[pairsCrossCorr,:,:].argmax(axis = 1)
305 #Obtencion Indice de TauAuto
315 #Obtencion Indice de TauAuto
306 indAuto = numpy.zeros(indCross.shape,dtype = 'int')
316 indAuto = numpy.zeros(indCross.shape,dtype = 'int')
307 CCValue = data[pairsCrossCorr,Pt0,:]
317 CCValue = data[pairsCrossCorr,Pt0,:]
308 for i in range(pairsCrossCorr.size):
318 for i in range(pairsCrossCorr.size):
309 indAuto[i,:] = numpy.abs(dataAutoCorr - CCValue[i,:]).argmin(axis = 0)
319 indAuto[i,:] = numpy.abs(dataAutoCorr - CCValue[i,:]).argmin(axis = 0)
310
320
311 #Obtencion de TauCross y TauAuto
321 #Obtencion de TauCross y TauAuto
312 tauCross = lagTRange[indCross]
322 tauCross = lagTRange[indCross]
313 tauAuto = lagTRange[indAuto]
323 tauAuto = lagTRange[indAuto]
314
324
315 Nan1, Nan2 = numpy.where(tauCross == lagTRange[0])
325 Nan1, Nan2 = numpy.where(tauCross == lagTRange[0])
316
326
317 tauCross[Nan1,Nan2] = numpy.nan
327 tauCross[Nan1,Nan2] = numpy.nan
318 tauAuto[Nan1,Nan2] = numpy.nan
328 tauAuto[Nan1,Nan2] = numpy.nan
319 tau = numpy.vstack((tauCross,tauAuto))
329 tau = numpy.vstack((tauCross,tauAuto))
320
330
321 return tau
331 return tau
322
332
323 def __calculateLag1Phase(self, data, pairs, lagTRange):
333 def __calculateLag1Phase(self, data, pairs, lagTRange):
324 data1 = stats.nanmean(data[pairs,:,:], axis = 0)
334 data1 = stats.nanmean(data[pairs,:,:], axis = 0)
325 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
335 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
326
336
327 phase = numpy.angle(data1[lag1,:])
337 phase = numpy.angle(data1[lag1,:])
328
338
329 return phase
339 return phase
330 #------------------- Detect Meteors ------------------------------
340 #------------------- Detect Meteors ------------------------------
331
341
332 def DetectMeteors(self, hei_ref = None, tauindex = 0,
342 def DetectMeteors(self, hei_ref = None, tauindex = 0,
333 predefinedPhaseShifts = None, centerReceiverIndex = 2,
343 predefinedPhaseShifts = None, centerReceiverIndex = 2,
334 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
344 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
335 noise_timeStep = 4, noise_multiple = 4,
345 noise_timeStep = 4, noise_multiple = 4,
336 multDet_timeLimit = 1, multDet_rangeLimit = 3,
346 multDet_timeLimit = 1, multDet_rangeLimit = 3,
337 phaseThresh = 20, SNRThresh = 8,
347 phaseThresh = 20, SNRThresh = 8,
338 hmin = 70, hmax=110, azimuth = 0) :
348 hmin = 70, hmax=110, azimuth = 0) :
339
349
340 '''
350 '''
341 Function DetectMeteors()
351 Function DetectMeteors()
342 Project developed with paper:
352 Project developed with paper:
343 HOLDSWORTH ET AL. 2004
353 HOLDSWORTH ET AL. 2004
344
354
345 Input:
355 Input:
346 self.dataOut.data_pre
356 self.dataOut.data_pre
347
357
348 centerReceiverIndex: From the channels, which is the center receiver
358 centerReceiverIndex: From the channels, which is the center receiver
349
359
350 hei_ref: Height reference for the Beacon signal extraction
360 hei_ref: Height reference for the Beacon signal extraction
351 tauindex:
361 tauindex:
352 predefinedPhaseShifts: Predefined phase offset for the voltge signals
362 predefinedPhaseShifts: Predefined phase offset for the voltge signals
353
363
354 cohDetection: Whether to user Coherent detection or not
364 cohDetection: Whether to user Coherent detection or not
355 cohDet_timeStep: Coherent Detection calculation time step
365 cohDet_timeStep: Coherent Detection calculation time step
356 cohDet_thresh: Coherent Detection phase threshold to correct phases
366 cohDet_thresh: Coherent Detection phase threshold to correct phases
357
367
358 noise_timeStep: Noise calculation time step
368 noise_timeStep: Noise calculation time step
359 noise_multiple: Noise multiple to define signal threshold
369 noise_multiple: Noise multiple to define signal threshold
360
370
361 multDet_timeLimit: Multiple Detection Removal time limit in seconds
371 multDet_timeLimit: Multiple Detection Removal time limit in seconds
362 multDet_rangeLimit: Multiple Detection Removal range limit in km
372 multDet_rangeLimit: Multiple Detection Removal range limit in km
363
373
364 phaseThresh: Maximum phase difference between receiver to be consider a meteor
374 phaseThresh: Maximum phase difference between receiver to be consider a meteor
365 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
375 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
366
376
367 hmin: Minimum Height of the meteor to use it in the further wind estimations
377 hmin: Minimum Height of the meteor to use it in the further wind estimations
368 hmax: Maximum Height of the meteor to use it in the further wind estimations
378 hmax: Maximum Height of the meteor to use it in the further wind estimations
369 azimuth: Azimuth angle correction
379 azimuth: Azimuth angle correction
370
380
371 Affected:
381 Affected:
372 self.dataOut.data_param
382 self.dataOut.data_param
373
383
374 Rejection Criteria (Errors):
384 Rejection Criteria (Errors):
375 0: No error; analysis OK
385 0: No error; analysis OK
376 1: SNR < SNR threshold
386 1: SNR < SNR threshold
377 2: angle of arrival (AOA) ambiguously determined
387 2: angle of arrival (AOA) ambiguously determined
378 3: AOA estimate not feasible
388 3: AOA estimate not feasible
379 4: Large difference in AOAs obtained from different antenna baselines
389 4: Large difference in AOAs obtained from different antenna baselines
380 5: echo at start or end of time series
390 5: echo at start or end of time series
381 6: echo less than 5 examples long; too short for analysis
391 6: echo less than 5 examples long; too short for analysis
382 7: echo rise exceeds 0.3s
392 7: echo rise exceeds 0.3s
383 8: echo decay time less than twice rise time
393 8: echo decay time less than twice rise time
384 9: large power level before echo
394 9: large power level before echo
385 10: large power level after echo
395 10: large power level after echo
386 11: poor fit to amplitude for estimation of decay time
396 11: poor fit to amplitude for estimation of decay time
387 12: poor fit to CCF phase variation for estimation of radial drift velocity
397 12: poor fit to CCF phase variation for estimation of radial drift velocity
388 13: height unresolvable echo: not valid height within 70 to 110 km
398 13: height unresolvable echo: not valid height within 70 to 110 km
389 14: height ambiguous echo: more then one possible height within 70 to 110 km
399 14: height ambiguous echo: more then one possible height within 70 to 110 km
390 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
400 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
391 16: oscilatory echo, indicating event most likely not an underdense echo
401 16: oscilatory echo, indicating event most likely not an underdense echo
392
402
393 17: phase difference in meteor Reestimation
403 17: phase difference in meteor Reestimation
394
404
395 Data Storage:
405 Data Storage:
396 Meteors for Wind Estimation (8):
406 Meteors for Wind Estimation (8):
397 Day Hour | Range Height
407 Day Hour | Range Height
398 Azimuth Zenith errorCosDir
408 Azimuth Zenith errorCosDir
399 VelRad errorVelRad
409 VelRad errorVelRad
400 TypeError
410 TypeError
401
411
402 '''
412 '''
403 #Get Beacon signal
413 #Get Beacon signal
404 newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
414 newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
405
415
406 if hei_ref != None:
416 if hei_ref != None:
407 newheis = numpy.where(self.dataOut.heightList>hei_ref)
417 newheis = numpy.where(self.dataOut.heightList>hei_ref)
408
418
409 heiRang = self.dataOut.getHeiRange()
419 heiRang = self.dataOut.getHeiRange()
410 #Pairs List
420 #Pairs List
411 pairslist = []
421 pairslist = []
412 nChannel = self.dataOut.nChannels
422 nChannel = self.dataOut.nChannels
413 for i in range(nChannel):
423 for i in range(nChannel):
414 if i != centerReceiverIndex:
424 if i != centerReceiverIndex:
415 pairslist.append((centerReceiverIndex,i))
425 pairslist.append((centerReceiverIndex,i))
416
426
417 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
427 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
418 # see if the user put in pre defined phase shifts
428 # see if the user put in pre defined phase shifts
419 voltsPShift = self.dataOut.data_pre.copy()
429 voltsPShift = self.dataOut.data_pre.copy()
420
430
421 if predefinedPhaseShifts != None:
431 if predefinedPhaseShifts != None:
422 hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
432 hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
423 else:
433 else:
424 #get hardware phase shifts using beacon signal
434 #get hardware phase shifts using beacon signal
425 hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
435 hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
426 hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
436 hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
427
437
428 voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
438 voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
429 for i in range(self.dataOut.data_pre.shape[0]):
439 for i in range(self.dataOut.data_pre.shape[0]):
430 voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
440 voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
431 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
441 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
432
442
433 #Remove DC
443 #Remove DC
434 voltsDC = numpy.mean(voltsPShift,1)
444 voltsDC = numpy.mean(voltsPShift,1)
435 voltsDC = numpy.mean(voltsDC,1)
445 voltsDC = numpy.mean(voltsDC,1)
436 for i in range(voltsDC.shape[0]):
446 for i in range(voltsDC.shape[0]):
437 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
447 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
438
448
439 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
449 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
440 voltsPShift = voltsPShift[:,:,:newheis[0][0]]
450 voltsPShift = voltsPShift[:,:,:newheis[0][0]]
441
451
442 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
452 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
443 #Coherent Detection
453 #Coherent Detection
444 if cohDetection:
454 if cohDetection:
445 #use coherent detection to get the net power
455 #use coherent detection to get the net power
446 cohDet_thresh = cohDet_thresh*numpy.pi/180
456 cohDet_thresh = cohDet_thresh*numpy.pi/180
447 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, self.dataOut.timeInterval, pairslist, cohDet_thresh)
457 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, self.dataOut.timeInterval, pairslist, cohDet_thresh)
448
458
449 #Non-coherent detection!
459 #Non-coherent detection!
450 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
460 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
451 #********** END OF COH/NON-COH POWER CALCULATION**********************
461 #********** END OF COH/NON-COH POWER CALCULATION**********************
452
462
453 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
463 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
454 #Get noise
464 #Get noise
455 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, self.dataOut.timeInterval)
465 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, self.dataOut.timeInterval)
456 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
466 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
457 #Get signal threshold
467 #Get signal threshold
458 signalThresh = noise_multiple*noise
468 signalThresh = noise_multiple*noise
459 #Meteor echoes detection
469 #Meteor echoes detection
460 listMeteors = self.__findMeteors(powerNet, signalThresh)
470 listMeteors = self.__findMeteors(powerNet, signalThresh)
461 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
471 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
462
472
463 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
473 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
464 #Parameters
474 #Parameters
465 heiRange = self.dataOut.getHeiRange()
475 heiRange = self.dataOut.getHeiRange()
466 rangeInterval = heiRange[1] - heiRange[0]
476 rangeInterval = heiRange[1] - heiRange[0]
467 rangeLimit = multDet_rangeLimit/rangeInterval
477 rangeLimit = multDet_rangeLimit/rangeInterval
468 timeLimit = multDet_timeLimit/self.dataOut.timeInterval
478 timeLimit = multDet_timeLimit/self.dataOut.timeInterval
469 #Multiple detection removals
479 #Multiple detection removals
470 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
480 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
471 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
481 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
472
482
473 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
483 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
474 #Parameters
484 #Parameters
475 phaseThresh = phaseThresh*numpy.pi/180
485 phaseThresh = phaseThresh*numpy.pi/180
476 thresh = [phaseThresh, noise_multiple, SNRThresh]
486 thresh = [phaseThresh, noise_multiple, SNRThresh]
477 #Meteor reestimation (Errors N 1, 6, 12, 17)
487 #Meteor reestimation (Errors N 1, 6, 12, 17)
478 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist, thresh, noise, self.dataOut.timeInterval, self.dataOut.frequency)
488 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist, thresh, noise, self.dataOut.timeInterval, self.dataOut.frequency)
479 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
489 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
480 #Estimation of decay times (Errors N 7, 8, 11)
490 #Estimation of decay times (Errors N 7, 8, 11)
481 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, self.dataOut.timeInterval, self.dataOut.frequency)
491 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, self.dataOut.timeInterval, self.dataOut.frequency)
482 #******************* END OF METEOR REESTIMATION *******************
492 #******************* END OF METEOR REESTIMATION *******************
483
493
484 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
494 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
485 #Calculating Radial Velocity (Error N 15)
495 #Calculating Radial Velocity (Error N 15)
486 radialStdThresh = 10
496 radialStdThresh = 10
487 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist, self.dataOut.timeInterval)
497 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist, self.dataOut.timeInterval)
488
498
489 if len(listMeteors4) > 0:
499 if len(listMeteors4) > 0:
490 #Setting New Array
500 #Setting New Array
491 date = repr(self.dataOut.datatime)
501 date = repr(self.dataOut.datatime)
492 arrayMeteors4, arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
502 arrayMeteors4, arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
493
503
494 #Calculate AOA (Error N 3, 4)
504 #Calculate AOA (Error N 3, 4)
495 #JONES ET AL. 1998
505 #JONES ET AL. 1998
496 AOAthresh = numpy.pi/8
506 AOAthresh = numpy.pi/8
497 error = arrayParameters[:,-1]
507 error = arrayParameters[:,-1]
498 phases = -arrayMeteors4[:,9:13]
508 phases = -arrayMeteors4[:,9:13]
499 pairsList = []
509 pairsList = []
500 pairsList.append((0,3))
510 pairsList.append((0,3))
501 pairsList.append((1,2))
511 pairsList.append((1,2))
502 arrayParameters[:,4:7], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, error, AOAthresh, azimuth)
512 arrayParameters[:,4:7], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, error, AOAthresh, azimuth)
503
513
504 #Calculate Heights (Error N 13 and 14)
514 #Calculate Heights (Error N 13 and 14)
505 error = arrayParameters[:,-1]
515 error = arrayParameters[:,-1]
506 Ranges = arrayParameters[:,2]
516 Ranges = arrayParameters[:,2]
507 zenith = arrayParameters[:,5]
517 zenith = arrayParameters[:,5]
508 arrayParameters[:,3], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
518 arrayParameters[:,3], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
509 #********************* END OF PARAMETERS CALCULATION **************************
519 #********************* END OF PARAMETERS CALCULATION **************************
510
520
511 #***************************+ SAVE DATA IN HDF5 FORMAT **********************
521 #***************************+ SAVE DATA IN HDF5 FORMAT **********************
512 self.dataOut.data_param = arrayParameters
522 self.dataOut.data_param = arrayParameters
513
523
514 return
524 return
515
525
516 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
526 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
517
527
518 minIndex = min(newheis[0])
528 minIndex = min(newheis[0])
519 maxIndex = max(newheis[0])
529 maxIndex = max(newheis[0])
520
530
521 voltage = voltage0[:,:,minIndex:maxIndex+1]
531 voltage = voltage0[:,:,minIndex:maxIndex+1]
522 nLength = voltage.shape[1]/n
532 nLength = voltage.shape[1]/n
523 nMin = 0
533 nMin = 0
524 nMax = 0
534 nMax = 0
525 phaseOffset = numpy.zeros((len(pairslist),n))
535 phaseOffset = numpy.zeros((len(pairslist),n))
526
536
527 for i in range(n):
537 for i in range(n):
528 nMax += nLength
538 nMax += nLength
529 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
539 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
530 phaseCCF = numpy.mean(phaseCCF, axis = 2)
540 phaseCCF = numpy.mean(phaseCCF, axis = 2)
531 phaseOffset[:,i] = phaseCCF.transpose()
541 phaseOffset[:,i] = phaseCCF.transpose()
532 nMin = nMax
542 nMin = nMax
533 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
543 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
534
544
535 #Remove Outliers
545 #Remove Outliers
536 factor = 2
546 factor = 2
537 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
547 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
538 dw = numpy.std(wt,axis = 1)
548 dw = numpy.std(wt,axis = 1)
539 dw = dw.reshape((dw.size,1))
549 dw = dw.reshape((dw.size,1))
540 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
550 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
541 phaseOffset[ind] = numpy.nan
551 phaseOffset[ind] = numpy.nan
542 phaseOffset = stats.nanmean(phaseOffset, axis=1)
552 phaseOffset = stats.nanmean(phaseOffset, axis=1)
543
553
544 return phaseOffset
554 return phaseOffset
545
555
546 def __shiftPhase(self, data, phaseShift):
556 def __shiftPhase(self, data, phaseShift):
547 #this will shift the phase of a complex number
557 #this will shift the phase of a complex number
548 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
558 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
549 return dataShifted
559 return dataShifted
550
560
551 def __estimatePhaseDifference(self, array, pairslist):
561 def __estimatePhaseDifference(self, array, pairslist):
552 nChannel = array.shape[0]
562 nChannel = array.shape[0]
553 nHeights = array.shape[2]
563 nHeights = array.shape[2]
554 numPairs = len(pairslist)
564 numPairs = len(pairslist)
555 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
565 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
556 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
566 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
557
567
558 #Correct phases
568 #Correct phases
559 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
569 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
560 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
570 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
561
571
562 if indDer[0].shape[0] > 0:
572 if indDer[0].shape[0] > 0:
563 for i in range(indDer[0].shape[0]):
573 for i in range(indDer[0].shape[0]):
564 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
574 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
565 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
575 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
566
576
567 # for j in range(numSides):
577 # for j in range(numSides):
568 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
578 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
569 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
579 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
570 #
580 #
571 #Linear
581 #Linear
572 phaseInt = numpy.zeros((numPairs,1))
582 phaseInt = numpy.zeros((numPairs,1))
573 angAllCCF = phaseCCF[:,[0,1,3,4],0]
583 angAllCCF = phaseCCF[:,[0,1,3,4],0]
574 for j in range(numPairs):
584 for j in range(numPairs):
575 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
585 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
576 phaseInt[j] = fit[1]
586 phaseInt[j] = fit[1]
577 #Phase Differences
587 #Phase Differences
578 phaseDiff = phaseInt - phaseCCF[:,2,:]
588 phaseDiff = phaseInt - phaseCCF[:,2,:]
579 phaseArrival = phaseInt.reshape(phaseInt.size)
589 phaseArrival = phaseInt.reshape(phaseInt.size)
580
590
581 #Dealias
591 #Dealias
582 indAlias = numpy.where(phaseArrival > numpy.pi)
592 indAlias = numpy.where(phaseArrival > numpy.pi)
583 phaseArrival[indAlias] -= 2*numpy.pi
593 phaseArrival[indAlias] -= 2*numpy.pi
584 indAlias = numpy.where(phaseArrival < -numpy.pi)
594 indAlias = numpy.where(phaseArrival < -numpy.pi)
585 phaseArrival[indAlias] += 2*numpy.pi
595 phaseArrival[indAlias] += 2*numpy.pi
586
596
587 return phaseDiff, phaseArrival
597 return phaseDiff, phaseArrival
588
598
589 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
599 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
590 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
600 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
591 #find the phase shifts of each channel over 1 second intervals
601 #find the phase shifts of each channel over 1 second intervals
592 #only look at ranges below the beacon signal
602 #only look at ranges below the beacon signal
593 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
603 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
594 numBlocks = int(volts.shape[1]/numProfPerBlock)
604 numBlocks = int(volts.shape[1]/numProfPerBlock)
595 numHeights = volts.shape[2]
605 numHeights = volts.shape[2]
596 nChannel = volts.shape[0]
606 nChannel = volts.shape[0]
597 voltsCohDet = volts.copy()
607 voltsCohDet = volts.copy()
598
608
599 pairsarray = numpy.array(pairslist)
609 pairsarray = numpy.array(pairslist)
600 indSides = pairsarray[:,1]
610 indSides = pairsarray[:,1]
601 # indSides = numpy.array(range(nChannel))
611 # indSides = numpy.array(range(nChannel))
602 # indSides = numpy.delete(indSides, indCenter)
612 # indSides = numpy.delete(indSides, indCenter)
603 #
613 #
604 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
614 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
605 listBlocks = numpy.array_split(volts, numBlocks, 1)
615 listBlocks = numpy.array_split(volts, numBlocks, 1)
606
616
607 startInd = 0
617 startInd = 0
608 endInd = 0
618 endInd = 0
609
619
610 for i in range(numBlocks):
620 for i in range(numBlocks):
611 startInd = endInd
621 startInd = endInd
612 endInd = endInd + listBlocks[i].shape[1]
622 endInd = endInd + listBlocks[i].shape[1]
613
623
614 arrayBlock = listBlocks[i]
624 arrayBlock = listBlocks[i]
615 # arrayBlockCenter = listCenter[i]
625 # arrayBlockCenter = listCenter[i]
616
626
617 #Estimate the Phase Difference
627 #Estimate the Phase Difference
618 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
628 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
619 #Phase Difference RMS
629 #Phase Difference RMS
620 arrayPhaseRMS = numpy.abs(phaseDiff)
630 arrayPhaseRMS = numpy.abs(phaseDiff)
621 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
631 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
622 indPhase = numpy.where(phaseRMSaux==4)
632 indPhase = numpy.where(phaseRMSaux==4)
623 #Shifting
633 #Shifting
624 if indPhase[0].shape[0] > 0:
634 if indPhase[0].shape[0] > 0:
625 for j in range(indSides.size):
635 for j in range(indSides.size):
626 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
636 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
627 voltsCohDet[:,startInd:endInd,:] = arrayBlock
637 voltsCohDet[:,startInd:endInd,:] = arrayBlock
628
638
629 return voltsCohDet
639 return voltsCohDet
630
640
631 def __calculateCCF(self, volts, pairslist ,laglist):
641 def __calculateCCF(self, volts, pairslist ,laglist):
632
642
633 nHeights = volts.shape[2]
643 nHeights = volts.shape[2]
634 nPoints = volts.shape[1]
644 nPoints = volts.shape[1]
635 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
645 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
636
646
637 for i in range(len(pairslist)):
647 for i in range(len(pairslist)):
638 volts1 = volts[pairslist[i][0]]
648 volts1 = volts[pairslist[i][0]]
639 volts2 = volts[pairslist[i][1]]
649 volts2 = volts[pairslist[i][1]]
640
650
641 for t in range(len(laglist)):
651 for t in range(len(laglist)):
642 idxT = laglist[t]
652 idxT = laglist[t]
643 if idxT >= 0:
653 if idxT >= 0:
644 vStacked = numpy.vstack((volts2[idxT:,:],
654 vStacked = numpy.vstack((volts2[idxT:,:],
645 numpy.zeros((idxT, nHeights),dtype='complex')))
655 numpy.zeros((idxT, nHeights),dtype='complex')))
646 else:
656 else:
647 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
657 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
648 volts2[:(nPoints + idxT),:]))
658 volts2[:(nPoints + idxT),:]))
649 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
659 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
650
660
651 vStacked = None
661 vStacked = None
652 return voltsCCF
662 return voltsCCF
653
663
654 def __getNoise(self, power, timeSegment, timeInterval):
664 def __getNoise(self, power, timeSegment, timeInterval):
655 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
665 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
656 numBlocks = int(power.shape[0]/numProfPerBlock)
666 numBlocks = int(power.shape[0]/numProfPerBlock)
657 numHeights = power.shape[1]
667 numHeights = power.shape[1]
658
668
659 listPower = numpy.array_split(power, numBlocks, 0)
669 listPower = numpy.array_split(power, numBlocks, 0)
660 noise = numpy.zeros((power.shape[0], power.shape[1]))
670 noise = numpy.zeros((power.shape[0], power.shape[1]))
661 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
671 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
662
672
663 startInd = 0
673 startInd = 0
664 endInd = 0
674 endInd = 0
665
675
666 for i in range(numBlocks): #split por canal
676 for i in range(numBlocks): #split por canal
667 startInd = endInd
677 startInd = endInd
668 endInd = endInd + listPower[i].shape[0]
678 endInd = endInd + listPower[i].shape[0]
669
679
670 arrayBlock = listPower[i]
680 arrayBlock = listPower[i]
671 noiseAux = numpy.mean(arrayBlock, 0)
681 noiseAux = numpy.mean(arrayBlock, 0)
672 # noiseAux = numpy.median(noiseAux)
682 # noiseAux = numpy.median(noiseAux)
673 # noiseAux = numpy.mean(arrayBlock)
683 # noiseAux = numpy.mean(arrayBlock)
674 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
684 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
675
685
676 noiseAux1 = numpy.mean(arrayBlock)
686 noiseAux1 = numpy.mean(arrayBlock)
677 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
687 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
678
688
679 return noise, noise1
689 return noise, noise1
680
690
681 def __findMeteors(self, power, thresh):
691 def __findMeteors(self, power, thresh):
682 nProf = power.shape[0]
692 nProf = power.shape[0]
683 nHeights = power.shape[1]
693 nHeights = power.shape[1]
684 listMeteors = []
694 listMeteors = []
685
695
686 for i in range(nHeights):
696 for i in range(nHeights):
687 powerAux = power[:,i]
697 powerAux = power[:,i]
688 threshAux = thresh[:,i]
698 threshAux = thresh[:,i]
689
699
690 indUPthresh = numpy.where(powerAux > threshAux)[0]
700 indUPthresh = numpy.where(powerAux > threshAux)[0]
691 indDNthresh = numpy.where(powerAux <= threshAux)[0]
701 indDNthresh = numpy.where(powerAux <= threshAux)[0]
692
702
693 j = 0
703 j = 0
694
704
695 while (j < indUPthresh.size - 2):
705 while (j < indUPthresh.size - 2):
696 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
706 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
697 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
707 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
698 indDNthresh = indDNthresh[indDNAux]
708 indDNthresh = indDNthresh[indDNAux]
699
709
700 if (indDNthresh.size > 0):
710 if (indDNthresh.size > 0):
701 indEnd = indDNthresh[0] - 1
711 indEnd = indDNthresh[0] - 1
702 indInit = indUPthresh[j]
712 indInit = indUPthresh[j]
703
713
704 meteor = powerAux[indInit:indEnd + 1]
714 meteor = powerAux[indInit:indEnd + 1]
705 indPeak = meteor.argmax() + indInit
715 indPeak = meteor.argmax() + indInit
706 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
716 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
707
717
708 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
718 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
709 j = numpy.where(indUPthresh == indEnd)[0] + 1
719 j = numpy.where(indUPthresh == indEnd)[0] + 1
710 else: j+=1
720 else: j+=1
711 else: j+=1
721 else: j+=1
712
722
713 return listMeteors
723 return listMeteors
714
724
715 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
725 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
716
726
717 arrayMeteors = numpy.asarray(listMeteors)
727 arrayMeteors = numpy.asarray(listMeteors)
718 listMeteors1 = []
728 listMeteors1 = []
719
729
720 while arrayMeteors.shape[0] > 0:
730 while arrayMeteors.shape[0] > 0:
721 FLAs = arrayMeteors[:,4]
731 FLAs = arrayMeteors[:,4]
722 maxFLA = FLAs.argmax()
732 maxFLA = FLAs.argmax()
723 listMeteors1.append(arrayMeteors[maxFLA,:])
733 listMeteors1.append(arrayMeteors[maxFLA,:])
724
734
725 MeteorInitTime = arrayMeteors[maxFLA,1]
735 MeteorInitTime = arrayMeteors[maxFLA,1]
726 MeteorEndTime = arrayMeteors[maxFLA,3]
736 MeteorEndTime = arrayMeteors[maxFLA,3]
727 MeteorHeight = arrayMeteors[maxFLA,0]
737 MeteorHeight = arrayMeteors[maxFLA,0]
728
738
729 #Check neighborhood
739 #Check neighborhood
730 maxHeightIndex = MeteorHeight + rangeLimit
740 maxHeightIndex = MeteorHeight + rangeLimit
731 minHeightIndex = MeteorHeight - rangeLimit
741 minHeightIndex = MeteorHeight - rangeLimit
732 minTimeIndex = MeteorInitTime - timeLimit
742 minTimeIndex = MeteorInitTime - timeLimit
733 maxTimeIndex = MeteorEndTime + timeLimit
743 maxTimeIndex = MeteorEndTime + timeLimit
734
744
735 #Check Heights
745 #Check Heights
736 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
746 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
737 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
747 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
738 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
748 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
739
749
740 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
750 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
741
751
742 return listMeteors1
752 return listMeteors1
743
753
744 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
754 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
745 numHeights = volts.shape[2]
755 numHeights = volts.shape[2]
746 nChannel = volts.shape[0]
756 nChannel = volts.shape[0]
747
757
748 thresholdPhase = thresh[0]
758 thresholdPhase = thresh[0]
749 thresholdNoise = thresh[1]
759 thresholdNoise = thresh[1]
750 thresholdDB = float(thresh[2])
760 thresholdDB = float(thresh[2])
751
761
752 thresholdDB1 = 10**(thresholdDB/10)
762 thresholdDB1 = 10**(thresholdDB/10)
753 pairsarray = numpy.array(pairslist)
763 pairsarray = numpy.array(pairslist)
754 indSides = pairsarray[:,1]
764 indSides = pairsarray[:,1]
755
765
756 pairslist1 = list(pairslist)
766 pairslist1 = list(pairslist)
757 pairslist1.append((0,1))
767 pairslist1.append((0,1))
758 pairslist1.append((3,4))
768 pairslist1.append((3,4))
759
769
760 listMeteors1 = []
770 listMeteors1 = []
761 listPowerSeries = []
771 listPowerSeries = []
762 listVoltageSeries = []
772 listVoltageSeries = []
763 #volts has the war data
773 #volts has the war data
764
774
765 if frequency == 30e6:
775 if frequency == 30e6:
766 timeLag = 45*10**-3
776 timeLag = 45*10**-3
767 else:
777 else:
768 timeLag = 15*10**-3
778 timeLag = 15*10**-3
769 lag = numpy.ceil(timeLag/timeInterval)
779 lag = numpy.ceil(timeLag/timeInterval)
770
780
771 for i in range(len(listMeteors)):
781 for i in range(len(listMeteors)):
772
782
773 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
783 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
774 meteorAux = numpy.zeros(16)
784 meteorAux = numpy.zeros(16)
775
785
776 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
786 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
777 mHeight = listMeteors[i][0]
787 mHeight = listMeteors[i][0]
778 mStart = listMeteors[i][1]
788 mStart = listMeteors[i][1]
779 mPeak = listMeteors[i][2]
789 mPeak = listMeteors[i][2]
780 mEnd = listMeteors[i][3]
790 mEnd = listMeteors[i][3]
781
791
782 #get the volt data between the start and end times of the meteor
792 #get the volt data between the start and end times of the meteor
783 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
793 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
784 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
794 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
785
795
786 #3.6. Phase Difference estimation
796 #3.6. Phase Difference estimation
787 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
797 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
788
798
789 #3.7. Phase difference removal & meteor start, peak and end times reestimated
799 #3.7. Phase difference removal & meteor start, peak and end times reestimated
790 #meteorVolts0.- all Channels, all Profiles
800 #meteorVolts0.- all Channels, all Profiles
791 meteorVolts0 = volts[:,:,mHeight]
801 meteorVolts0 = volts[:,:,mHeight]
792 meteorThresh = noise[:,mHeight]*thresholdNoise
802 meteorThresh = noise[:,mHeight]*thresholdNoise
793 meteorNoise = noise[:,mHeight]
803 meteorNoise = noise[:,mHeight]
794 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
804 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
795 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
805 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
796
806
797 #Times reestimation
807 #Times reestimation
798 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
808 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
799 if mStart1.size > 0:
809 if mStart1.size > 0:
800 mStart1 = mStart1[-1] + 1
810 mStart1 = mStart1[-1] + 1
801
811
802 else:
812 else:
803 mStart1 = mPeak
813 mStart1 = mPeak
804
814
805 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
815 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
806 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
816 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
807 if mEndDecayTime1.size == 0:
817 if mEndDecayTime1.size == 0:
808 mEndDecayTime1 = powerNet0.size
818 mEndDecayTime1 = powerNet0.size
809 else:
819 else:
810 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
820 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
811 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
821 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
812
822
813 #meteorVolts1.- all Channels, from start to end
823 #meteorVolts1.- all Channels, from start to end
814 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
824 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
815 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
825 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
816 if meteorVolts2.shape[1] == 0:
826 if meteorVolts2.shape[1] == 0:
817 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
827 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
818 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
828 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
819 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
829 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
820 ##################### END PARAMETERS REESTIMATION #########################
830 ##################### END PARAMETERS REESTIMATION #########################
821
831
822 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
832 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
823 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
833 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
824 if meteorVolts2.shape[1] > 0:
834 if meteorVolts2.shape[1] > 0:
825 #Phase Difference re-estimation
835 #Phase Difference re-estimation
826 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
836 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
827 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
837 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
828 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
838 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
829 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
839 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
830 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
840 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
831
841
832 #Phase Difference RMS
842 #Phase Difference RMS
833 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
843 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
834 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
844 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
835 #Data from Meteor
845 #Data from Meteor
836 mPeak1 = powerNet1.argmax() + mStart1
846 mPeak1 = powerNet1.argmax() + mStart1
837 mPeakPower1 = powerNet1.max()
847 mPeakPower1 = powerNet1.max()
838 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
848 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
839 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
849 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
840 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
850 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
841 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
851 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
842 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
852 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
843 #Vectorize
853 #Vectorize
844 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
854 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
845 meteorAux[7:11] = phaseDiffint[0:4]
855 meteorAux[7:11] = phaseDiffint[0:4]
846
856
847 #Rejection Criterions
857 #Rejection Criterions
848 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
858 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
849 meteorAux[-1] = 17
859 meteorAux[-1] = 17
850 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
860 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
851 meteorAux[-1] = 1
861 meteorAux[-1] = 1
852
862
853
863
854 else:
864 else:
855 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
865 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
856 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
866 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
857 PowerSeries = 0
867 PowerSeries = 0
858
868
859 listMeteors1.append(meteorAux)
869 listMeteors1.append(meteorAux)
860 listPowerSeries.append(PowerSeries)
870 listPowerSeries.append(PowerSeries)
861 listVoltageSeries.append(meteorVolts1)
871 listVoltageSeries.append(meteorVolts1)
862
872
863 return listMeteors1, listPowerSeries, listVoltageSeries
873 return listMeteors1, listPowerSeries, listVoltageSeries
864
874
865 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
875 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
866
876
867 threshError = 10
877 threshError = 10
868 #Depending if it is 30 or 50 MHz
878 #Depending if it is 30 or 50 MHz
869 if frequency == 30e6:
879 if frequency == 30e6:
870 timeLag = 45*10**-3
880 timeLag = 45*10**-3
871 else:
881 else:
872 timeLag = 15*10**-3
882 timeLag = 15*10**-3
873 lag = numpy.ceil(timeLag/timeInterval)
883 lag = numpy.ceil(timeLag/timeInterval)
874
884
875 listMeteors1 = []
885 listMeteors1 = []
876
886
877 for i in range(len(listMeteors)):
887 for i in range(len(listMeteors)):
878 meteorPower = listPower[i]
888 meteorPower = listPower[i]
879 meteorAux = listMeteors[i]
889 meteorAux = listMeteors[i]
880
890
881 if meteorAux[-1] == 0:
891 if meteorAux[-1] == 0:
882
892
883 try:
893 try:
884 indmax = meteorPower.argmax()
894 indmax = meteorPower.argmax()
885 indlag = indmax + lag
895 indlag = indmax + lag
886
896
887 y = meteorPower[indlag:]
897 y = meteorPower[indlag:]
888 x = numpy.arange(0, y.size)*timeLag
898 x = numpy.arange(0, y.size)*timeLag
889
899
890 #first guess
900 #first guess
891 a = y[0]
901 a = y[0]
892 tau = timeLag
902 tau = timeLag
893 #exponential fit
903 #exponential fit
894 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
904 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
895 y1 = self.__exponential_function(x, *popt)
905 y1 = self.__exponential_function(x, *popt)
896 #error estimation
906 #error estimation
897 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
907 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
898
908
899 decayTime = popt[1]
909 decayTime = popt[1]
900 riseTime = indmax*timeInterval
910 riseTime = indmax*timeInterval
901 meteorAux[11:13] = [decayTime, error]
911 meteorAux[11:13] = [decayTime, error]
902
912
903 #Table items 7, 8 and 11
913 #Table items 7, 8 and 11
904 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
914 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
905 meteorAux[-1] = 7
915 meteorAux[-1] = 7
906 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
916 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
907 meteorAux[-1] = 8
917 meteorAux[-1] = 8
908 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
918 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
909 meteorAux[-1] = 11
919 meteorAux[-1] = 11
910
920
911
921
912 except:
922 except:
913 meteorAux[-1] = 11
923 meteorAux[-1] = 11
914
924
915
925
916 listMeteors1.append(meteorAux)
926 listMeteors1.append(meteorAux)
917
927
918 return listMeteors1
928 return listMeteors1
919
929
920 #Exponential Function
930 #Exponential Function
921
931
922 def __exponential_function(self, x, a, tau):
932 def __exponential_function(self, x, a, tau):
923 y = a*numpy.exp(-x/tau)
933 y = a*numpy.exp(-x/tau)
924 return y
934 return y
925
935
926 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
936 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
927
937
928 pairslist1 = list(pairslist)
938 pairslist1 = list(pairslist)
929 pairslist1.append((0,1))
939 pairslist1.append((0,1))
930 pairslist1.append((3,4))
940 pairslist1.append((3,4))
931 numPairs = len(pairslist1)
941 numPairs = len(pairslist1)
932 #Time Lag
942 #Time Lag
933 timeLag = 45*10**-3
943 timeLag = 45*10**-3
934 c = 3e8
944 c = 3e8
935 lag = numpy.ceil(timeLag/timeInterval)
945 lag = numpy.ceil(timeLag/timeInterval)
936 freq = 30e6
946 freq = 30e6
937
947
938 listMeteors1 = []
948 listMeteors1 = []
939
949
940 for i in range(len(listMeteors)):
950 for i in range(len(listMeteors)):
941 meteor = listMeteors[i]
951 meteor = listMeteors[i]
942 meteorAux = numpy.hstack((meteor[:-1], 0, 0, meteor[-1]))
952 meteorAux = numpy.hstack((meteor[:-1], 0, 0, meteor[-1]))
943 if meteor[-1] == 0:
953 if meteor[-1] == 0:
944 mStart = listMeteors[i][1]
954 mStart = listMeteors[i][1]
945 mPeak = listMeteors[i][2]
955 mPeak = listMeteors[i][2]
946 mLag = mPeak - mStart + lag
956 mLag = mPeak - mStart + lag
947
957
948 #get the volt data between the start and end times of the meteor
958 #get the volt data between the start and end times of the meteor
949 meteorVolts = listVolts[i]
959 meteorVolts = listVolts[i]
950 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
960 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
951
961
952 #Get CCF
962 #Get CCF
953 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
963 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
954
964
955 #Method 2
965 #Method 2
956 slopes = numpy.zeros(numPairs)
966 slopes = numpy.zeros(numPairs)
957 time = numpy.array([-2,-1,1,2])*timeInterval
967 time = numpy.array([-2,-1,1,2])*timeInterval
958 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
968 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
959
969
960 #Correct phases
970 #Correct phases
961 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
971 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
962 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
972 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
963
973
964 if indDer[0].shape[0] > 0:
974 if indDer[0].shape[0] > 0:
965 for i in range(indDer[0].shape[0]):
975 for i in range(indDer[0].shape[0]):
966 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
976 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
967 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
977 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
968
978
969 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
979 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
970 for j in range(numPairs):
980 for j in range(numPairs):
971 fit = stats.linregress(time, angAllCCF[j,:])
981 fit = stats.linregress(time, angAllCCF[j,:])
972 slopes[j] = fit[0]
982 slopes[j] = fit[0]
973
983
974 #Remove Outlier
984 #Remove Outlier
975 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
985 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
976 # slopes = numpy.delete(slopes,indOut)
986 # slopes = numpy.delete(slopes,indOut)
977 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
987 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
978 # slopes = numpy.delete(slopes,indOut)
988 # slopes = numpy.delete(slopes,indOut)
979
989
980 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
990 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
981 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
991 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
982 meteorAux[-2] = radialError
992 meteorAux[-2] = radialError
983 meteorAux[-3] = radialVelocity
993 meteorAux[-3] = radialVelocity
984
994
985 #Setting Error
995 #Setting Error
986 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
996 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
987 if numpy.abs(radialVelocity) > 200:
997 if numpy.abs(radialVelocity) > 200:
988 meteorAux[-1] = 15
998 meteorAux[-1] = 15
989 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
999 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
990 elif radialError > radialStdThresh:
1000 elif radialError > radialStdThresh:
991 meteorAux[-1] = 12
1001 meteorAux[-1] = 12
992
1002
993 listMeteors1.append(meteorAux)
1003 listMeteors1.append(meteorAux)
994 return listMeteors1
1004 return listMeteors1
995
1005
996 def __setNewArrays(self, listMeteors, date, heiRang):
1006 def __setNewArrays(self, listMeteors, date, heiRang):
997
1007
998 #New arrays
1008 #New arrays
999 arrayMeteors = numpy.array(listMeteors)
1009 arrayMeteors = numpy.array(listMeteors)
1000 arrayParameters = numpy.zeros((len(listMeteors),10))
1010 arrayParameters = numpy.zeros((len(listMeteors),10))
1001
1011
1002 #Date inclusion
1012 #Date inclusion
1003 date = re.findall(r'\((.*?)\)', date)
1013 date = re.findall(r'\((.*?)\)', date)
1004 date = date[0].split(',')
1014 date = date[0].split(',')
1005 date = map(int, date)
1015 date = map(int, date)
1006 date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
1016 date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
1007 arrayDate = numpy.tile(date, (len(listMeteors), 1))
1017 arrayDate = numpy.tile(date, (len(listMeteors), 1))
1008
1018
1009 #Meteor array
1019 #Meteor array
1010 arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
1020 arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
1011 arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
1021 arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
1012
1022
1013 #Parameters Array
1023 #Parameters Array
1014 arrayParameters[:,0:3] = arrayMeteors[:,0:3]
1024 arrayParameters[:,0:3] = arrayMeteors[:,0:3]
1015 arrayParameters[:,-3:] = arrayMeteors[:,-3:]
1025 arrayParameters[:,-3:] = arrayMeteors[:,-3:]
1016
1026
1017 return arrayMeteors, arrayParameters
1027 return arrayMeteors, arrayParameters
1018
1028
1019 def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
1029 def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
1020
1030
1021 arrayAOA = numpy.zeros((phases.shape[0],3))
1031 arrayAOA = numpy.zeros((phases.shape[0],3))
1022 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
1032 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
1023
1033
1024 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
1034 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
1025 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
1035 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
1026 arrayAOA[:,2] = cosDirError
1036 arrayAOA[:,2] = cosDirError
1027
1037
1028 azimuthAngle = arrayAOA[:,0]
1038 azimuthAngle = arrayAOA[:,0]
1029 zenithAngle = arrayAOA[:,1]
1039 zenithAngle = arrayAOA[:,1]
1030
1040
1031 #Setting Error
1041 #Setting Error
1032 #Number 3: AOA not fesible
1042 #Number 3: AOA not fesible
1033 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
1043 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
1034 error[indInvalid] = 3
1044 error[indInvalid] = 3
1035 #Number 4: Large difference in AOAs obtained from different antenna baselines
1045 #Number 4: Large difference in AOAs obtained from different antenna baselines
1036 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
1046 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
1037 error[indInvalid] = 4
1047 error[indInvalid] = 4
1038 return arrayAOA, error
1048 return arrayAOA, error
1039
1049
1040 def __getDirectionCosines(self, arrayPhase, pairsList):
1050 def __getDirectionCosines(self, arrayPhase, pairsList):
1041
1051
1042 #Initializing some variables
1052 #Initializing some variables
1043 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
1053 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
1044 ang_aux = ang_aux.reshape(1,ang_aux.size)
1054 ang_aux = ang_aux.reshape(1,ang_aux.size)
1045
1055
1046 cosdir = numpy.zeros((arrayPhase.shape[0],2))
1056 cosdir = numpy.zeros((arrayPhase.shape[0],2))
1047 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
1057 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
1048
1058
1049
1059
1050 for i in range(2):
1060 for i in range(2):
1051 #First Estimation
1061 #First Estimation
1052 phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
1062 phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
1053 #Dealias
1063 #Dealias
1054 indcsi = numpy.where(phi0_aux > numpy.pi)
1064 indcsi = numpy.where(phi0_aux > numpy.pi)
1055 phi0_aux[indcsi] -= 2*numpy.pi
1065 phi0_aux[indcsi] -= 2*numpy.pi
1056 indcsi = numpy.where(phi0_aux < -numpy.pi)
1066 indcsi = numpy.where(phi0_aux < -numpy.pi)
1057 phi0_aux[indcsi] += 2*numpy.pi
1067 phi0_aux[indcsi] += 2*numpy.pi
1058 #Direction Cosine 0
1068 #Direction Cosine 0
1059 cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
1069 cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
1060
1070
1061 #Most-Accurate Second Estimation
1071 #Most-Accurate Second Estimation
1062 phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
1072 phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
1063 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
1073 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
1064 #Direction Cosine 1
1074 #Direction Cosine 1
1065 cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
1075 cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
1066
1076
1067 #Searching the correct Direction Cosine
1077 #Searching the correct Direction Cosine
1068 cosdir0_aux = cosdir0[:,i]
1078 cosdir0_aux = cosdir0[:,i]
1069 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
1079 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
1070 #Minimum Distance
1080 #Minimum Distance
1071 cosDiff = (cosdir1 - cosdir0_aux)**2
1081 cosDiff = (cosdir1 - cosdir0_aux)**2
1072 indcos = cosDiff.argmin(axis = 1)
1082 indcos = cosDiff.argmin(axis = 1)
1073 #Saving Value obtained
1083 #Saving Value obtained
1074 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
1084 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
1075
1085
1076 return cosdir0, cosdir
1086 return cosdir0, cosdir
1077
1087
1078 def __calculateAOA(self, cosdir, azimuth):
1088 def __calculateAOA(self, cosdir, azimuth):
1079 cosdirX = cosdir[:,0]
1089 cosdirX = cosdir[:,0]
1080 cosdirY = cosdir[:,1]
1090 cosdirY = cosdir[:,1]
1081
1091
1082 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
1092 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
1083 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
1093 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
1084 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
1094 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
1085
1095
1086 return angles
1096 return angles
1087
1097
1088 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
1098 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
1089
1099
1090 Ramb = 375 #Ramb = c/(2*PRF)
1100 Ramb = 375 #Ramb = c/(2*PRF)
1091 Re = 6371 #Earth Radius
1101 Re = 6371 #Earth Radius
1092 heights = numpy.zeros(Ranges.shape)
1102 heights = numpy.zeros(Ranges.shape)
1093
1103
1094 R_aux = numpy.array([0,1,2])*Ramb
1104 R_aux = numpy.array([0,1,2])*Ramb
1095 R_aux = R_aux.reshape(1,R_aux.size)
1105 R_aux = R_aux.reshape(1,R_aux.size)
1096
1106
1097 Ranges = Ranges.reshape(Ranges.size,1)
1107 Ranges = Ranges.reshape(Ranges.size,1)
1098
1108
1099 Ri = Ranges + R_aux
1109 Ri = Ranges + R_aux
1100 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
1110 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
1101
1111
1102 #Check if there is a height between 70 and 110 km
1112 #Check if there is a height between 70 and 110 km
1103 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
1113 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
1104 ind_h = numpy.where(h_bool == 1)[0]
1114 ind_h = numpy.where(h_bool == 1)[0]
1105
1115
1106 hCorr = hi[ind_h, :]
1116 hCorr = hi[ind_h, :]
1107 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
1117 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
1108
1118
1109 hCorr = hi[ind_hCorr]
1119 hCorr = hi[ind_hCorr]
1110 heights[ind_h] = hCorr
1120 heights[ind_h] = hCorr
1111
1121
1112 #Setting Error
1122 #Setting Error
1113 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
1123 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
1114 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
1124 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
1115
1125
1116 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
1126 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
1117 error[indInvalid2] = 14
1127 error[indInvalid2] = 14
1118 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
1128 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
1119 error[indInvalid1] = 13
1129 error[indInvalid1] = 13
1120
1130
1121 return heights, error
1131 return heights, error
1122
1132
1123 def SpectralFitting(self, getSNR = True, path=None, file=None, groupList=None):
1133 def SpectralFitting(self, getSNR = True, path=None, file=None, groupList=None):
1124
1134
1125 '''
1135 '''
1126 Function GetMoments()
1136 Function GetMoments()
1127
1137
1128 Input:
1138 Input:
1129 Output:
1139 Output:
1130 Variables modified:
1140 Variables modified:
1131 '''
1141 '''
1132 if path != None:
1142 if path != None:
1133 sys.path.append(path)
1143 sys.path.append(path)
1134 self.dataOut.library = importlib.import_module(file)
1144 self.dataOut.library = importlib.import_module(file)
1135
1145
1136 #To be inserted as a parameter
1146 #To be inserted as a parameter
1137 groupArray = numpy.array(groupList)
1147 groupArray = numpy.array(groupList)
1138 # groupArray = numpy.array([[0,1],[2,3]])
1148 # groupArray = numpy.array([[0,1],[2,3]])
1139 self.dataOut.groupList = groupArray
1149 self.dataOut.groupList = groupArray
1140
1150
1141 nGroups = groupArray.shape[0]
1151 nGroups = groupArray.shape[0]
1142 nChannels = self.dataIn.nChannels
1152 nChannels = self.dataIn.nChannels
1143 nHeights=self.dataIn.heightList.size
1153 nHeights=self.dataIn.heightList.size
1144
1154
1145 #Parameters Array
1155 #Parameters Array
1146 self.dataOut.data_param = None
1156 self.dataOut.data_param = None
1147
1157
1148 #Set constants
1158 #Set constants
1149 constants = self.dataOut.library.setConstants(self.dataIn)
1159 constants = self.dataOut.library.setConstants(self.dataIn)
1150 self.dataOut.constants = constants
1160 self.dataOut.constants = constants
1151 M = self.dataIn.normFactor
1161 M = self.dataIn.normFactor
1152 N = self.dataIn.nFFTPoints
1162 N = self.dataIn.nFFTPoints
1153 ippSeconds = self.dataIn.ippSeconds
1163 ippSeconds = self.dataIn.ippSeconds
1154 K = self.dataIn.nIncohInt
1164 K = self.dataIn.nIncohInt
1155 pairsArray = numpy.array(self.dataIn.pairsList)
1165 pairsArray = numpy.array(self.dataIn.pairsList)
1156
1166
1157 #List of possible combinations
1167 #List of possible combinations
1158 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1168 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1159 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1169 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1160
1170
1161 if getSNR:
1171 if getSNR:
1162 listChannels = groupArray.reshape((groupArray.size))
1172 listChannels = groupArray.reshape((groupArray.size))
1163 listChannels.sort()
1173 listChannels.sort()
1164 noise = self.dataIn.getNoise()
1174 noise = self.dataIn.getNoise()
1165 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1175 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1166
1176
1167 for i in range(nGroups):
1177 for i in range(nGroups):
1168 coord = groupArray[i,:]
1178 coord = groupArray[i,:]
1169
1179
1170 #Input data array
1180 #Input data array
1171 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1181 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1172 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1182 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1173
1183
1174 #Cross Spectra data array for Covariance Matrixes
1184 #Cross Spectra data array for Covariance Matrixes
1175 ind = 0
1185 ind = 0
1176 for pairs in listComb:
1186 for pairs in listComb:
1177 pairsSel = numpy.array([coord[x],coord[y]])
1187 pairsSel = numpy.array([coord[x],coord[y]])
1178 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1188 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1179 ind += 1
1189 ind += 1
1180 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1190 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1181 dataCross = dataCross**2/K
1191 dataCross = dataCross**2/K
1182
1192
1183 for h in range(nHeights):
1193 for h in range(nHeights):
1184 # print self.dataOut.heightList[h]
1194 # print self.dataOut.heightList[h]
1185
1195
1186 #Input
1196 #Input
1187 d = data[:,h]
1197 d = data[:,h]
1188
1198
1189 #Covariance Matrix
1199 #Covariance Matrix
1190 D = numpy.diag(d**2/K)
1200 D = numpy.diag(d**2/K)
1191 ind = 0
1201 ind = 0
1192 for pairs in listComb:
1202 for pairs in listComb:
1193 #Coordinates in Covariance Matrix
1203 #Coordinates in Covariance Matrix
1194 x = pairs[0]
1204 x = pairs[0]
1195 y = pairs[1]
1205 y = pairs[1]
1196 #Channel Index
1206 #Channel Index
1197 S12 = dataCross[ind,:,h]
1207 S12 = dataCross[ind,:,h]
1198 D12 = numpy.diag(S12)
1208 D12 = numpy.diag(S12)
1199 #Completing Covariance Matrix with Cross Spectras
1209 #Completing Covariance Matrix with Cross Spectras
1200 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1210 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1201 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1211 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1202 ind += 1
1212 ind += 1
1203 Dinv=numpy.linalg.inv(D)
1213 Dinv=numpy.linalg.inv(D)
1204 L=numpy.linalg.cholesky(Dinv)
1214 L=numpy.linalg.cholesky(Dinv)
1205 LT=L.T
1215 LT=L.T
1206
1216
1207 dp = numpy.dot(LT,d)
1217 dp = numpy.dot(LT,d)
1208
1218
1209 #Initial values
1219 #Initial values
1210 data_spc = self.dataIn.data_spc[coord,:,h]
1220 data_spc = self.dataIn.data_spc[coord,:,h]
1211
1221
1212 if (h>0)and(error1[3]<5):
1222 if (h>0)and(error1[3]<5):
1213 p0 = self.dataOut.data_param[i,:,h-1]
1223 p0 = self.dataOut.data_param[i,:,h-1]
1214 else:
1224 else:
1215 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1225 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1216
1226
1217 try:
1227 try:
1218 #Least Squares
1228 #Least Squares
1219 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1229 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1220 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1230 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1221 #Chi square error
1231 #Chi square error
1222 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1232 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1223 #Error with Jacobian
1233 #Error with Jacobian
1224 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1234 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1225 except:
1235 except:
1226 minp = p0*numpy.nan
1236 minp = p0*numpy.nan
1227 error0 = numpy.nan
1237 error0 = numpy.nan
1228 error1 = p0*numpy.nan
1238 error1 = p0*numpy.nan
1229
1239
1230 #Save
1240 #Save
1231 if self.dataOut.data_param == None:
1241 if self.dataOut.data_param == None:
1232 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1242 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1233 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1243 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1234
1244
1235 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1245 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1236 self.dataOut.data_param[i,:,h] = minp
1246 self.dataOut.data_param[i,:,h] = minp
1237 return
1247 return
1238
1248
1239
1249
1240 def __residFunction(self, p, dp, LT, constants):
1250 def __residFunction(self, p, dp, LT, constants):
1241
1251
1242 fm = self.dataOut.library.modelFunction(p, constants)
1252 fm = self.dataOut.library.modelFunction(p, constants)
1243 fmp=numpy.dot(LT,fm)
1253 fmp=numpy.dot(LT,fm)
1244
1254
1245 return dp-fmp
1255 return dp-fmp
1246
1256
1247 def __getSNR(self, z, noise):
1257 def __getSNR(self, z, noise):
1248
1258
1249 avg = numpy.average(z, axis=1)
1259 avg = numpy.average(z, axis=1)
1250 SNR = (avg.T-noise)/noise
1260 SNR = (avg.T-noise)/noise
1251 SNR = SNR.T
1261 SNR = SNR.T
1252 return SNR
1262 return SNR
1253
1263
1254 def __chisq(p,chindex,hindex):
1264 def __chisq(p,chindex,hindex):
1255 #similar to Resid but calculates CHI**2
1265 #similar to Resid but calculates CHI**2
1256 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1266 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1257 dp=numpy.dot(LT,d)
1267 dp=numpy.dot(LT,d)
1258 fmp=numpy.dot(LT,fm)
1268 fmp=numpy.dot(LT,fm)
1259 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1269 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1260 return chisq
1270 return chisq
1261
1271
1262
1272
1263
1273
1264 class WindProfiler(Operation):
1274 class WindProfiler(Operation):
1265
1275
1266 __isConfig = False
1276 __isConfig = False
1267
1277
1268 __initime = None
1278 __initime = None
1269 __lastdatatime = None
1279 __lastdatatime = None
1270 __integrationtime = None
1280 __integrationtime = None
1271
1281
1272 __buffer = None
1282 __buffer = None
1273
1283
1274 __dataReady = False
1284 __dataReady = False
1275
1285
1276 __firstdata = None
1286 __firstdata = None
1277
1287
1278 n = None
1288 n = None
1279
1289
1280 def __init__(self):
1290 def __init__(self):
1281 Operation.__init__(self)
1291 Operation.__init__(self)
1282
1292
1283 def __calculateCosDir(self, elev, azim):
1293 def __calculateCosDir(self, elev, azim):
1284 zen = (90 - elev)*numpy.pi/180
1294 zen = (90 - elev)*numpy.pi/180
1285 azim = azim*numpy.pi/180
1295 azim = azim*numpy.pi/180
1286 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1296 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1287 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1297 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1288
1298
1289 signX = numpy.sign(numpy.cos(azim))
1299 signX = numpy.sign(numpy.cos(azim))
1290 signY = numpy.sign(numpy.sin(azim))
1300 signY = numpy.sign(numpy.sin(azim))
1291
1301
1292 cosDirX = numpy.copysign(cosDirX, signX)
1302 cosDirX = numpy.copysign(cosDirX, signX)
1293 cosDirY = numpy.copysign(cosDirY, signY)
1303 cosDirY = numpy.copysign(cosDirY, signY)
1294 return cosDirX, cosDirY
1304 return cosDirX, cosDirY
1295
1305
1296 def __calculateAngles(self, theta_x, theta_y, azimuth):
1306 def __calculateAngles(self, theta_x, theta_y, azimuth):
1297
1307
1298 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1308 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1299 zenith_arr = numpy.arccos(dir_cosw)
1309 zenith_arr = numpy.arccos(dir_cosw)
1300 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1310 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1301
1311
1302 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1312 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1303 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1313 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1304
1314
1305 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1315 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1306
1316
1307 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1317 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1308
1318
1309 #
1319 #
1310 if horOnly:
1320 if horOnly:
1311 A = numpy.c_[dir_cosu,dir_cosv]
1321 A = numpy.c_[dir_cosu,dir_cosv]
1312 else:
1322 else:
1313 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1323 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1314 A = numpy.asmatrix(A)
1324 A = numpy.asmatrix(A)
1315 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1325 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1316
1326
1317 return A1
1327 return A1
1318
1328
1319 def __correctValues(self, heiRang, phi, velRadial, SNR):
1329 def __correctValues(self, heiRang, phi, velRadial, SNR):
1320 listPhi = phi.tolist()
1330 listPhi = phi.tolist()
1321 maxid = listPhi.index(max(listPhi))
1331 maxid = listPhi.index(max(listPhi))
1322 minid = listPhi.index(min(listPhi))
1332 minid = listPhi.index(min(listPhi))
1323
1333
1324 rango = range(len(phi))
1334 rango = range(len(phi))
1325 # rango = numpy.delete(rango,maxid)
1335 # rango = numpy.delete(rango,maxid)
1326
1336
1327 heiRang1 = heiRang*math.cos(phi[maxid])
1337 heiRang1 = heiRang*math.cos(phi[maxid])
1328 heiRangAux = heiRang*math.cos(phi[minid])
1338 heiRangAux = heiRang*math.cos(phi[minid])
1329 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1339 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1330 heiRang1 = numpy.delete(heiRang1,indOut)
1340 heiRang1 = numpy.delete(heiRang1,indOut)
1331
1341
1332 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1342 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1333 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1343 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1334
1344
1335 for i in rango:
1345 for i in rango:
1336 x = heiRang*math.cos(phi[i])
1346 x = heiRang*math.cos(phi[i])
1337 y1 = velRadial[i,:]
1347 y1 = velRadial[i,:]
1338 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1348 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1339
1349
1340 x1 = heiRang1
1350 x1 = heiRang1
1341 y11 = f1(x1)
1351 y11 = f1(x1)
1342
1352
1343 y2 = SNR[i,:]
1353 y2 = SNR[i,:]
1344 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1354 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1345 y21 = f2(x1)
1355 y21 = f2(x1)
1346
1356
1347 velRadial1[i,:] = y11
1357 velRadial1[i,:] = y11
1348 SNR1[i,:] = y21
1358 SNR1[i,:] = y21
1349
1359
1350 return heiRang1, velRadial1, SNR1
1360 return heiRang1, velRadial1, SNR1
1351
1361
1352 def __calculateVelUVW(self, A, velRadial):
1362 def __calculateVelUVW(self, A, velRadial):
1353
1363
1354 #Operacion Matricial
1364 #Operacion Matricial
1355 # velUVW = numpy.zeros((velRadial.shape[1],3))
1365 # velUVW = numpy.zeros((velRadial.shape[1],3))
1356 # for ind in range(velRadial.shape[1]):
1366 # for ind in range(velRadial.shape[1]):
1357 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1367 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1358 # velUVW = velUVW.transpose()
1368 # velUVW = velUVW.transpose()
1359 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1369 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1360 velUVW[:,:] = numpy.dot(A,velRadial)
1370 velUVW[:,:] = numpy.dot(A,velRadial)
1361
1371
1362
1372
1363 return velUVW
1373 return velUVW
1364
1374
1365 def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1375 def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1366 """
1376 """
1367 Function that implements Doppler Beam Swinging (DBS) technique.
1377 Function that implements Doppler Beam Swinging (DBS) technique.
1368
1378
1369 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1379 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1370 Direction correction (if necessary), Ranges and SNR
1380 Direction correction (if necessary), Ranges and SNR
1371
1381
1372 Output: Winds estimation (Zonal, Meridional and Vertical)
1382 Output: Winds estimation (Zonal, Meridional and Vertical)
1373
1383
1374 Parameters affected: Winds, height range, SNR
1384 Parameters affected: Winds, height range, SNR
1375 """
1385 """
1376 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(dirCosx, disrCosy, azimuth)
1386 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(dirCosx, disrCosy, azimuth)
1377 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correct*velRadial0, SNR0)
1387 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correct*velRadial0, SNR0)
1378 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1388 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1379
1389
1380 #Calculo de Componentes de la velocidad con DBS
1390 #Calculo de Componentes de la velocidad con DBS
1381 winds = self.__calculateVelUVW(A,velRadial1)
1391 winds = self.__calculateVelUVW(A,velRadial1)
1382
1392
1383 return winds, heiRang1, SNR1
1393 return winds, heiRang1, SNR1
1384
1394
1385 def __calculateDistance(self, posx, posy, pairsCrossCorr, pairsList, pairs, azimuth = None):
1395 def __calculateDistance(self, posx, posy, pairsCrossCorr, pairsList, pairs, azimuth = None):
1386
1396
1387 posx = numpy.asarray(posx)
1397 posx = numpy.asarray(posx)
1388 posy = numpy.asarray(posy)
1398 posy = numpy.asarray(posy)
1389
1399
1390 #Rotacion Inversa para alinear con el azimuth
1400 #Rotacion Inversa para alinear con el azimuth
1391 if azimuth!= None:
1401 if azimuth!= None:
1392 azimuth = azimuth*math.pi/180
1402 azimuth = azimuth*math.pi/180
1393 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1403 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1394 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1404 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1395 else:
1405 else:
1396 posx1 = posx
1406 posx1 = posx
1397 posy1 = posy
1407 posy1 = posy
1398
1408
1399 #Calculo de Distancias
1409 #Calculo de Distancias
1400 distx = numpy.zeros(pairsCrossCorr.size)
1410 distx = numpy.zeros(pairsCrossCorr.size)
1401 disty = numpy.zeros(pairsCrossCorr.size)
1411 disty = numpy.zeros(pairsCrossCorr.size)
1402 dist = numpy.zeros(pairsCrossCorr.size)
1412 dist = numpy.zeros(pairsCrossCorr.size)
1403 ang = numpy.zeros(pairsCrossCorr.size)
1413 ang = numpy.zeros(pairsCrossCorr.size)
1404
1414
1405 for i in range(pairsCrossCorr.size):
1415 for i in range(pairsCrossCorr.size):
1406 distx[i] = posx1[pairsList[pairsCrossCorr[i]][1]] - posx1[pairsList[pairsCrossCorr[i]][0]]
1416 distx[i] = posx1[pairsList[pairsCrossCorr[i]][1]] - posx1[pairsList[pairsCrossCorr[i]][0]]
1407 disty[i] = posy1[pairsList[pairsCrossCorr[i]][1]] - posy1[pairsList[pairsCrossCorr[i]][0]]
1417 disty[i] = posy1[pairsList[pairsCrossCorr[i]][1]] - posy1[pairsList[pairsCrossCorr[i]][0]]
1408 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1418 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1409 ang[i] = numpy.arctan2(disty[i],distx[i])
1419 ang[i] = numpy.arctan2(disty[i],distx[i])
1410 #Calculo de Matrices
1420 #Calculo de Matrices
1411 nPairs = len(pairs)
1421 nPairs = len(pairs)
1412 ang1 = numpy.zeros((nPairs, 2, 1))
1422 ang1 = numpy.zeros((nPairs, 2, 1))
1413 dist1 = numpy.zeros((nPairs, 2, 1))
1423 dist1 = numpy.zeros((nPairs, 2, 1))
1414
1424
1415 for j in range(nPairs):
1425 for j in range(nPairs):
1416 dist1[j,0,0] = dist[pairs[j][0]]
1426 dist1[j,0,0] = dist[pairs[j][0]]
1417 dist1[j,1,0] = dist[pairs[j][1]]
1427 dist1[j,1,0] = dist[pairs[j][1]]
1418 ang1[j,0,0] = ang[pairs[j][0]]
1428 ang1[j,0,0] = ang[pairs[j][0]]
1419 ang1[j,1,0] = ang[pairs[j][1]]
1429 ang1[j,1,0] = ang[pairs[j][1]]
1420
1430
1421 return distx,disty, dist1,ang1
1431 return distx,disty, dist1,ang1
1422
1432
1423 def __calculateVelVer(self, phase, lagTRange, _lambda):
1433 def __calculateVelVer(self, phase, lagTRange, _lambda):
1424
1434
1425 Ts = lagTRange[1] - lagTRange[0]
1435 Ts = lagTRange[1] - lagTRange[0]
1426 velW = -_lambda*phase/(4*math.pi*Ts)
1436 velW = -_lambda*phase/(4*math.pi*Ts)
1427
1437
1428 return velW
1438 return velW
1429
1439
1430 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1440 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1431 nPairs = tau1.shape[0]
1441 nPairs = tau1.shape[0]
1432 vel = numpy.zeros((nPairs,3,tau1.shape[2]))
1442 vel = numpy.zeros((nPairs,3,tau1.shape[2]))
1433
1443
1434 angCos = numpy.cos(ang)
1444 angCos = numpy.cos(ang)
1435 angSin = numpy.sin(ang)
1445 angSin = numpy.sin(ang)
1436
1446
1437 vel0 = dist*tau1/(2*tau2**2)
1447 vel0 = dist*tau1/(2*tau2**2)
1438 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1448 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1439 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1449 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1440
1450
1441 ind = numpy.where(numpy.isinf(vel))
1451 ind = numpy.where(numpy.isinf(vel))
1442 vel[ind] = numpy.nan
1452 vel[ind] = numpy.nan
1443
1453
1444 return vel
1454 return vel
1445
1455
1446 def __getPairsAutoCorr(self, pairsList, nChannels):
1456 def __getPairsAutoCorr(self, pairsList, nChannels):
1447
1457
1448 pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1458 pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1449
1459
1450 for l in range(len(pairsList)):
1460 for l in range(len(pairsList)):
1451 firstChannel = pairsList[l][0]
1461 firstChannel = pairsList[l][0]
1452 secondChannel = pairsList[l][1]
1462 secondChannel = pairsList[l][1]
1453
1463
1454 #Obteniendo pares de Autocorrelacion
1464 #Obteniendo pares de Autocorrelacion
1455 if firstChannel == secondChannel:
1465 if firstChannel == secondChannel:
1456 pairsAutoCorr[firstChannel] = int(l)
1466 pairsAutoCorr[firstChannel] = int(l)
1457
1467
1458 pairsAutoCorr = pairsAutoCorr.astype(int)
1468 pairsAutoCorr = pairsAutoCorr.astype(int)
1459
1469
1460 pairsCrossCorr = range(len(pairsList))
1470 pairsCrossCorr = range(len(pairsList))
1461 pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1471 pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1462
1472
1463 return pairsAutoCorr, pairsCrossCorr
1473 return pairsAutoCorr, pairsCrossCorr
1464
1474
1465 def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1475 def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1466 """
1476 """
1467 Function that implements Spaced Antenna (SA) technique.
1477 Function that implements Spaced Antenna (SA) technique.
1468
1478
1469 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1479 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1470 Direction correction (if necessary), Ranges and SNR
1480 Direction correction (if necessary), Ranges and SNR
1471
1481
1472 Output: Winds estimation (Zonal, Meridional and Vertical)
1482 Output: Winds estimation (Zonal, Meridional and Vertical)
1473
1483
1474 Parameters affected: Winds
1484 Parameters affected: Winds
1475 """
1485 """
1476 #Cross Correlation pairs obtained
1486 #Cross Correlation pairs obtained
1477 pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1487 pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1478 pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1488 pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1479 pairsSelArray = numpy.array(pairsSelected)
1489 pairsSelArray = numpy.array(pairsSelected)
1480 pairs = []
1490 pairs = []
1481
1491
1482 #Wind estimation pairs obtained
1492 #Wind estimation pairs obtained
1483 for i in range(pairsSelArray.shape[0]/2):
1493 for i in range(pairsSelArray.shape[0]/2):
1484 ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1494 ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1485 ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1495 ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1486 pairs.append((ind1,ind2))
1496 pairs.append((ind1,ind2))
1487
1497
1488 indtau = tau.shape[0]/2
1498 indtau = tau.shape[0]/2
1489 tau1 = tau[:indtau,:]
1499 tau1 = tau[:indtau,:]
1490 tau2 = tau[indtau:-1,:]
1500 tau2 = tau[indtau:-1,:]
1491 tau1 = tau1[pairs,:]
1501 tau1 = tau1[pairs,:]
1492 tau2 = tau2[pairs,:]
1502 tau2 = tau2[pairs,:]
1493 phase1 = tau[-1,:]
1503 phase1 = tau[-1,:]
1494
1504
1495 #---------------------------------------------------------------------
1505 #---------------------------------------------------------------------
1496 #Metodo Directo
1506 #Metodo Directo
1497 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairsCrossCorr, pairsList, pairs,azimuth)
1507 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairsCrossCorr, pairsList, pairs,azimuth)
1498 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1508 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1499 winds = stats.nanmean(winds, axis=0)
1509 winds = stats.nanmean(winds, axis=0)
1500 #---------------------------------------------------------------------
1510 #---------------------------------------------------------------------
1501 #Metodo General
1511 #Metodo General
1502 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1512 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1503 # #Calculo Coeficientes de Funcion de Correlacion
1513 # #Calculo Coeficientes de Funcion de Correlacion
1504 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1514 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1505 # #Calculo de Velocidades
1515 # #Calculo de Velocidades
1506 # winds = self.calculateVelUV(F,G,A,B,H)
1516 # winds = self.calculateVelUV(F,G,A,B,H)
1507
1517
1508 #---------------------------------------------------------------------
1518 #---------------------------------------------------------------------
1509 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1519 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1510 winds = correctFactor*winds
1520 winds = correctFactor*winds
1511 return winds
1521 return winds
1512
1522
1513 def __checkTime(self, currentTime, paramInterval, outputInterval):
1523 def __checkTime(self, currentTime, paramInterval, outputInterval):
1514
1524
1515 dataTime = currentTime + paramInterval
1525 dataTime = currentTime + paramInterval
1516 deltaTime = dataTime - self.__initime
1526 deltaTime = dataTime - self.__initime
1517
1527
1518 if deltaTime >= outputInterval or deltaTime < 0:
1528 if deltaTime >= outputInterval or deltaTime < 0:
1519 self.__dataReady = True
1529 self.__dataReady = True
1520 return
1530 return
1521
1531
1522 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1532 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1523 '''
1533 '''
1524 Function that implements winds estimation technique with detected meteors.
1534 Function that implements winds estimation technique with detected meteors.
1525
1535
1526 Input: Detected meteors, Minimum meteor quantity to wind estimation
1536 Input: Detected meteors, Minimum meteor quantity to wind estimation
1527
1537
1528 Output: Winds estimation (Zonal and Meridional)
1538 Output: Winds estimation (Zonal and Meridional)
1529
1539
1530 Parameters affected: Winds
1540 Parameters affected: Winds
1531 '''
1541 '''
1532 #Settings
1542 #Settings
1533 nInt = (heightMax - heightMin)/2
1543 nInt = (heightMax - heightMin)/2
1534 winds = numpy.zeros((2,nInt))*numpy.nan
1544 winds = numpy.zeros((2,nInt))*numpy.nan
1535
1545
1536 #Filter errors
1546 #Filter errors
1537 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1547 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1538 finalMeteor = arrayMeteor[error,:]
1548 finalMeteor = arrayMeteor[error,:]
1539
1549
1540 #Meteor Histogram
1550 #Meteor Histogram
1541 finalHeights = finalMeteor[:,3]
1551 finalHeights = finalMeteor[:,3]
1542 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1552 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1543 nMeteorsPerI = hist[0]
1553 nMeteorsPerI = hist[0]
1544 heightPerI = hist[1]
1554 heightPerI = hist[1]
1545
1555
1546 #Sort of meteors
1556 #Sort of meteors
1547 indSort = finalHeights.argsort()
1557 indSort = finalHeights.argsort()
1548 finalMeteor2 = finalMeteor[indSort,:]
1558 finalMeteor2 = finalMeteor[indSort,:]
1549
1559
1550 # Calculating winds
1560 # Calculating winds
1551 ind1 = 0
1561 ind1 = 0
1552 ind2 = 0
1562 ind2 = 0
1553
1563
1554 for i in range(nInt):
1564 for i in range(nInt):
1555 nMet = nMeteorsPerI[i]
1565 nMet = nMeteorsPerI[i]
1556 ind1 = ind2
1566 ind1 = ind2
1557 ind2 = ind1 + nMet
1567 ind2 = ind1 + nMet
1558
1568
1559 meteorAux = finalMeteor2[ind1:ind2,:]
1569 meteorAux = finalMeteor2[ind1:ind2,:]
1560
1570
1561 if meteorAux.shape[0] >= meteorThresh:
1571 if meteorAux.shape[0] >= meteorThresh:
1562 vel = meteorAux[:, 7]
1572 vel = meteorAux[:, 7]
1563 zen = meteorAux[:, 5]*numpy.pi/180
1573 zen = meteorAux[:, 5]*numpy.pi/180
1564 azim = meteorAux[:, 4]*numpy.pi/180
1574 azim = meteorAux[:, 4]*numpy.pi/180
1565
1575
1566 n = numpy.cos(zen)
1576 n = numpy.cos(zen)
1567 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1577 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1568 # l = m*numpy.tan(azim)
1578 # l = m*numpy.tan(azim)
1569 l = numpy.sin(zen)*numpy.sin(azim)
1579 l = numpy.sin(zen)*numpy.sin(azim)
1570 m = numpy.sin(zen)*numpy.cos(azim)
1580 m = numpy.sin(zen)*numpy.cos(azim)
1571
1581
1572 A = numpy.vstack((l, m)).transpose()
1582 A = numpy.vstack((l, m)).transpose()
1573 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1583 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1574 windsAux = numpy.dot(A1, vel)
1584 windsAux = numpy.dot(A1, vel)
1575
1585
1576 winds[0,i] = windsAux[0]
1586 winds[0,i] = windsAux[0]
1577 winds[1,i] = windsAux[1]
1587 winds[1,i] = windsAux[1]
1578
1588
1579 return winds, heightPerI[:-1]
1589 return winds, heightPerI[:-1]
1580
1590
1581 def run(self, dataOut, technique, **kwargs):
1591 def run(self, dataOut, technique, **kwargs):
1582
1592
1583 param = dataOut.data_param
1593 param = dataOut.data_param
1584 if dataOut.abscissaList != None:
1594 if dataOut.abscissaList != None:
1585 absc = dataOut.abscissaList[:-1]
1595 absc = dataOut.abscissaList[:-1]
1586 noise = dataOut.noise
1596 noise = dataOut.noise
1587 heightList = dataOut.getHeiRange()
1597 heightList = dataOut.getHeiRange()
1588 SNR = dataOut.data_SNR
1598 SNR = dataOut.data_SNR
1589
1599
1590 if technique == 'DBS':
1600 if technique == 'DBS':
1591
1601
1592 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
1602 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
1593 theta_x = numpy.array(kwargs['dirCosx'])
1603 theta_x = numpy.array(kwargs['dirCosx'])
1594 theta_y = numpy.array(kwargs['dirCosy'])
1604 theta_y = numpy.array(kwargs['dirCosy'])
1595 else:
1605 else:
1596 elev = numpy.array(kwargs['elevation'])
1606 elev = numpy.array(kwargs['elevation'])
1597 azim = numpy.array(kwargs['azimuth'])
1607 azim = numpy.array(kwargs['azimuth'])
1598 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1608 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1599 azimuth = kwargs['correctAzimuth']
1609 azimuth = kwargs['correctAzimuth']
1600 if kwargs.has_key('horizontalOnly'):
1610 if kwargs.has_key('horizontalOnly'):
1601 horizontalOnly = kwargs['horizontalOnly']
1611 horizontalOnly = kwargs['horizontalOnly']
1602 else: horizontalOnly = False
1612 else: horizontalOnly = False
1603 if kwargs.has_key('correctFactor'):
1613 if kwargs.has_key('correctFactor'):
1604 correctFactor = kwargs['correctFactor']
1614 correctFactor = kwargs['correctFactor']
1605 else: correctFactor = 1
1615 else: correctFactor = 1
1606 if kwargs.has_key('channelList'):
1616 if kwargs.has_key('channelList'):
1607 channelList = kwargs['channelList']
1617 channelList = kwargs['channelList']
1608 if len(channelList) == 2:
1618 if len(channelList) == 2:
1609 horizontalOnly = True
1619 horizontalOnly = True
1610 arrayChannel = numpy.array(channelList)
1620 arrayChannel = numpy.array(channelList)
1611 param = param[arrayChannel,:,:]
1621 param = param[arrayChannel,:,:]
1612 theta_x = theta_x[arrayChannel]
1622 theta_x = theta_x[arrayChannel]
1613 theta_y = theta_y[arrayChannel]
1623 theta_y = theta_y[arrayChannel]
1614
1624
1615 velRadial0 = param[:,1,:] #Radial velocity
1625 velRadial0 = param[:,1,:] #Radial velocity
1616 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(velRadial0, theta_x, theta_y, azimuth, correctFactor, horizontalOnly, heightList, SNR) #DBS Function
1626 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(velRadial0, theta_x, theta_y, azimuth, correctFactor, horizontalOnly, heightList, SNR) #DBS Function
1617 dataOut.utctimeInit = dataOut.utctime
1627 dataOut.utctimeInit = dataOut.utctime
1618 dataOut.outputInterval = dataOut.timeInterval
1628 dataOut.outputInterval = dataOut.timeInterval
1619
1629
1620 elif technique == 'SA':
1630 elif technique == 'SA':
1621
1631
1622 #Parameters
1632 #Parameters
1623 position_x = kwargs['positionX']
1633 position_x = kwargs['positionX']
1624 position_y = kwargs['positionY']
1634 position_y = kwargs['positionY']
1625 azimuth = kwargs['azimuth']
1635 azimuth = kwargs['azimuth']
1626
1636
1627 if kwargs.has_key('crosspairsList'):
1637 if kwargs.has_key('crosspairsList'):
1628 pairs = kwargs['crosspairsList']
1638 pairs = kwargs['crosspairsList']
1629 else:
1639 else:
1630 pairs = None
1640 pairs = None
1631
1641
1632 if kwargs.has_key('correctFactor'):
1642 if kwargs.has_key('correctFactor'):
1633 correctFactor = kwargs['correctFactor']
1643 correctFactor = kwargs['correctFactor']
1634 else:
1644 else:
1635 correctFactor = 1
1645 correctFactor = 1
1636
1646
1637 tau = dataOut.data_param
1647 tau = dataOut.data_param
1638 _lambda = dataOut.C/dataOut.frequency
1648 _lambda = dataOut.C/dataOut.frequency
1639 pairsList = dataOut.groupList
1649 pairsList = dataOut.groupList
1640 nChannels = dataOut.nChannels
1650 nChannels = dataOut.nChannels
1641
1651
1642 dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1652 dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1643 dataOut.utctimeInit = dataOut.utctime
1653 dataOut.utctimeInit = dataOut.utctime
1644 dataOut.outputInterval = dataOut.timeInterval
1654 dataOut.outputInterval = dataOut.timeInterval
1645
1655
1646 elif technique == 'Meteors':
1656 elif technique == 'Meteors':
1647 dataOut.flagNoData = True
1657 dataOut.flagNoData = True
1648 self.__dataReady = False
1658 self.__dataReady = False
1649
1659
1650 if kwargs.has_key('nHours'):
1660 if kwargs.has_key('nHours'):
1651 nHours = kwargs['nHours']
1661 nHours = kwargs['nHours']
1652 else:
1662 else:
1653 nHours = 1
1663 nHours = 1
1654
1664
1655 if kwargs.has_key('meteorsPerBin'):
1665 if kwargs.has_key('meteorsPerBin'):
1656 meteorThresh = kwargs['meteorsPerBin']
1666 meteorThresh = kwargs['meteorsPerBin']
1657 else:
1667 else:
1658 meteorThresh = 6
1668 meteorThresh = 6
1659
1669
1660 if kwargs.has_key('hmin'):
1670 if kwargs.has_key('hmin'):
1661 hmin = kwargs['hmin']
1671 hmin = kwargs['hmin']
1662 else: hmin = 70
1672 else: hmin = 70
1663 if kwargs.has_key('hmax'):
1673 if kwargs.has_key('hmax'):
1664 hmax = kwargs['hmax']
1674 hmax = kwargs['hmax']
1665 else: hmax = 110
1675 else: hmax = 110
1666
1676
1667 dataOut.outputInterval = nHours*3600
1677 dataOut.outputInterval = nHours*3600
1668
1678
1669 if self.__isConfig == False:
1679 if self.__isConfig == False:
1670 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1680 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1671 #Get Initial LTC time
1681 #Get Initial LTC time
1672 self.__initime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
1682 self.__initime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
1673 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1683 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1674
1684
1675 self.__isConfig = True
1685 self.__isConfig = True
1676
1686
1677 if self.__buffer == None:
1687 if self.__buffer == None:
1678 self.__buffer = dataOut.data_param
1688 self.__buffer = dataOut.data_param
1679 self.__firstdata = copy.copy(dataOut)
1689 self.__firstdata = copy.copy(dataOut)
1680
1690
1681 else:
1691 else:
1682 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1692 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1683
1693
1684 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1694 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1685
1695
1686 if self.__dataReady:
1696 if self.__dataReady:
1687 dataOut.utctimeInit = self.__initime
1697 dataOut.utctimeInit = self.__initime
1688
1698
1689 self.__initime += dataOut.outputInterval #to erase time offset
1699 self.__initime += dataOut.outputInterval #to erase time offset
1690
1700
1691 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
1701 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
1692 dataOut.flagNoData = False
1702 dataOut.flagNoData = False
1693 self.__buffer = None
1703 self.__buffer = None
1694
1704
1695 return
1705 return
1696
1706
1697 class EWDriftsEstimation(Operation):
1707 class EWDriftsEstimation(Operation):
1698
1708
1699
1709
1700 def __init__(self):
1710 def __init__(self):
1701 Operation.__init__(self)
1711 Operation.__init__(self)
1702
1712
1703 def __correctValues(self, heiRang, phi, velRadial, SNR):
1713 def __correctValues(self, heiRang, phi, velRadial, SNR):
1704 listPhi = phi.tolist()
1714 listPhi = phi.tolist()
1705 maxid = listPhi.index(max(listPhi))
1715 maxid = listPhi.index(max(listPhi))
1706 minid = listPhi.index(min(listPhi))
1716 minid = listPhi.index(min(listPhi))
1707
1717
1708 rango = range(len(phi))
1718 rango = range(len(phi))
1709 # rango = numpy.delete(rango,maxid)
1719 # rango = numpy.delete(rango,maxid)
1710
1720
1711 heiRang1 = heiRang*math.cos(phi[maxid])
1721 heiRang1 = heiRang*math.cos(phi[maxid])
1712 heiRangAux = heiRang*math.cos(phi[minid])
1722 heiRangAux = heiRang*math.cos(phi[minid])
1713 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1723 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1714 heiRang1 = numpy.delete(heiRang1,indOut)
1724 heiRang1 = numpy.delete(heiRang1,indOut)
1715
1725
1716 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1726 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1717 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1727 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1718
1728
1719 for i in rango:
1729 for i in rango:
1720 x = heiRang*math.cos(phi[i])
1730 x = heiRang*math.cos(phi[i])
1721 y1 = velRadial[i,:]
1731 y1 = velRadial[i,:]
1722 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1732 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1723
1733
1724 x1 = heiRang1
1734 x1 = heiRang1
1725 y11 = f1(x1)
1735 y11 = f1(x1)
1726
1736
1727 y2 = SNR[i,:]
1737 y2 = SNR[i,:]
1728 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1738 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1729 y21 = f2(x1)
1739 y21 = f2(x1)
1730
1740
1731 velRadial1[i,:] = y11
1741 velRadial1[i,:] = y11
1732 SNR1[i,:] = y21
1742 SNR1[i,:] = y21
1733
1743
1734 return heiRang1, velRadial1, SNR1
1744 return heiRang1, velRadial1, SNR1
1735
1745
1736 def run(self, dataOut, zenith, zenithCorrection):
1746 def run(self, dataOut, zenith, zenithCorrection):
1737 heiRang = dataOut.heightList
1747 heiRang = dataOut.heightList
1738 velRadial = dataOut.data_param[:,3,:]
1748 velRadial = dataOut.data_param[:,3,:]
1739 SNR = dataOut.data_SNR
1749 SNR = dataOut.data_SNR
1740
1750
1741 zenith = numpy.array(zenith)
1751 zenith = numpy.array(zenith)
1742 zenith -= zenithCorrection
1752 zenith -= zenithCorrection
1743 zenith *= numpy.pi/180
1753 zenith *= numpy.pi/180
1744
1754
1745 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
1755 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
1746
1756
1747 alp = zenith[0]
1757 alp = zenith[0]
1748 bet = zenith[1]
1758 bet = zenith[1]
1749
1759
1750 w_w = velRadial1[0,:]
1760 w_w = velRadial1[0,:]
1751 w_e = velRadial1[1,:]
1761 w_e = velRadial1[1,:]
1752
1762
1753 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
1763 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
1754 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
1764 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
1755
1765
1756 winds = numpy.vstack((u,w))
1766 winds = numpy.vstack((u,w))
1757
1767
1758 dataOut.heightList = heiRang1
1768 dataOut.heightList = heiRang1
1759 dataOut.data_output = winds
1769 dataOut.data_output = winds
1760 dataOut.data_SNR = SNR1
1770 dataOut.data_SNR = SNR1
1761
1771
1762 dataOut.utctimeInit = dataOut.utctime
1772 dataOut.utctimeInit = dataOut.utctime
1763 dataOut.outputInterval = dataOut.timeInterval
1773 dataOut.outputInterval = dataOut.timeInterval
1764 return
1774 return
1765
1775
1766
1776
1767
1777
1768
1778
1769
1779
1770 No newline at end of file
1780
General Comments 0
You need to be logged in to leave comments. Login now