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