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