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