##// END OF EJS Templates
last update
avaldezp -
r1412:7050d08f9cdf
parent child
Show More
@@ -1,4306 +1,4306
1 import numpy,os,h5py
1 import numpy,os,h5py
2 import math
2 import math
3 from scipy import optimize, interpolate, signal, stats, ndimage
3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 import scipy
5 import re
5 import re
6 import datetime
6 import datetime
7 import copy
7 import copy
8 import sys
8 import sys
9 import importlib
9 import importlib
10 import itertools
10 import itertools
11 from multiprocessing import Pool, TimeoutError
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
12 from multiprocessing.pool import ThreadPool
13 import time
13 import time
14
14
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 from scipy import asarray as ar,exp
18 from scipy import asarray as ar,exp
19 from scipy.optimize import curve_fit
19 from scipy.optimize import curve_fit
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import warnings
21 import warnings
22 from numpy import NaN
22 from numpy import NaN
23 from scipy.optimize.optimize import OptimizeWarning
23 from scipy.optimize.optimize import OptimizeWarning
24 warnings.filterwarnings('ignore')
24 warnings.filterwarnings('ignore')
25
25
26 from time import sleep
26 from time import sleep
27
27
28 import matplotlib.pyplot as plt
28 import matplotlib.pyplot as plt
29
29
30 SPEED_OF_LIGHT = 299792458
30 SPEED_OF_LIGHT = 299792458
31
31
32 '''solving pickling issue'''
32 '''solving pickling issue'''
33
33
34 def _pickle_method(method):
34 def _pickle_method(method):
35 func_name = method.__func__.__name__
35 func_name = method.__func__.__name__
36 obj = method.__self__
36 obj = method.__self__
37 cls = method.__self__.__class__
37 cls = method.__self__.__class__
38 return _unpickle_method, (func_name, obj, cls)
38 return _unpickle_method, (func_name, obj, cls)
39
39
40 def _unpickle_method(func_name, obj, cls):
40 def _unpickle_method(func_name, obj, cls):
41 for cls in cls.mro():
41 for cls in cls.mro():
42 try:
42 try:
43 func = cls.__dict__[func_name]
43 func = cls.__dict__[func_name]
44 except KeyError:
44 except KeyError:
45 pass
45 pass
46 else:
46 else:
47 break
47 break
48 return func.__get__(obj, cls)
48 return func.__get__(obj, cls)
49
49
50 def isNumber(str):
50 def isNumber(str):
51 try:
51 try:
52 float(str)
52 float(str)
53 return True
53 return True
54 except:
54 except:
55 return False
55 return False
56
56
57 class ParametersProc(ProcessingUnit):
57 class ParametersProc(ProcessingUnit):
58
58
59 METHODS = {}
59 METHODS = {}
60 nSeconds = None
60 nSeconds = None
61
61
62 def __init__(self):
62 def __init__(self):
63 ProcessingUnit.__init__(self)
63 ProcessingUnit.__init__(self)
64
64
65 # self.objectDict = {}
65 # self.objectDict = {}
66 self.buffer = None
66 self.buffer = None
67 self.firstdatatime = None
67 self.firstdatatime = None
68 self.profIndex = 0
68 self.profIndex = 0
69 self.dataOut = Parameters()
69 self.dataOut = Parameters()
70 self.setupReq = False #Agregar a todas las unidades de proc
70 self.setupReq = False #Agregar a todas las unidades de proc
71
71
72 def __updateObjFromInput(self):
72 def __updateObjFromInput(self):
73
73
74 self.dataOut.inputUnit = self.dataIn.type
74 self.dataOut.inputUnit = self.dataIn.type
75
75
76 self.dataOut.timeZone = self.dataIn.timeZone
76 self.dataOut.timeZone = self.dataIn.timeZone
77 self.dataOut.dstFlag = self.dataIn.dstFlag
77 self.dataOut.dstFlag = self.dataIn.dstFlag
78 self.dataOut.errorCount = self.dataIn.errorCount
78 self.dataOut.errorCount = self.dataIn.errorCount
79 self.dataOut.useLocalTime = self.dataIn.useLocalTime
79 self.dataOut.useLocalTime = self.dataIn.useLocalTime
80
80
81 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
81 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
82 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
82 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
83 self.dataOut.channelList = self.dataIn.channelList
83 self.dataOut.channelList = self.dataIn.channelList
84 self.dataOut.heightList = self.dataIn.heightList
84 self.dataOut.heightList = self.dataIn.heightList
85 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
85 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
86 # self.dataOut.nHeights = self.dataIn.nHeights
86 # self.dataOut.nHeights = self.dataIn.nHeights
87 # self.dataOut.nChannels = self.dataIn.nChannels
87 # self.dataOut.nChannels = self.dataIn.nChannels
88 # self.dataOut.nBaud = self.dataIn.nBaud
88 # self.dataOut.nBaud = self.dataIn.nBaud
89 # self.dataOut.nCode = self.dataIn.nCode
89 # self.dataOut.nCode = self.dataIn.nCode
90 # self.dataOut.code = self.dataIn.code
90 # self.dataOut.code = self.dataIn.code
91 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
91 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
92 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
92 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
93 # self.dataOut.utctime = self.firstdatatime
93 # self.dataOut.utctime = self.firstdatatime
94 self.dataOut.utctime = self.dataIn.utctime
94 self.dataOut.utctime = self.dataIn.utctime
95 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
95 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
96 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
96 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
97 self.dataOut.nCohInt = self.dataIn.nCohInt
97 self.dataOut.nCohInt = self.dataIn.nCohInt
98 # self.dataOut.nIncohInt = 1
98 # self.dataOut.nIncohInt = 1
99 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
99 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
100 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
100 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
101 self.dataOut.timeInterval1 = self.dataIn.timeInterval
101 self.dataOut.timeInterval1 = self.dataIn.timeInterval
102 self.dataOut.heightList = self.dataIn.heightList
102 self.dataOut.heightList = self.dataIn.heightList
103 self.dataOut.frequency = self.dataIn.frequency
103 self.dataOut.frequency = self.dataIn.frequency
104 # self.dataOut.noise = self.dataIn.noise
104 # self.dataOut.noise = self.dataIn.noise
105
105
106 def run(self):
106 def run(self):
107
107
108
108
109 #print("HOLA MUNDO SOY YO")
109 #print("HOLA MUNDO SOY YO")
110 #---------------------- Voltage Data ---------------------------
110 #---------------------- Voltage Data ---------------------------
111
111
112 if self.dataIn.type == "Voltage":
112 if self.dataIn.type == "Voltage":
113
113
114 self.__updateObjFromInput()
114 self.__updateObjFromInput()
115 self.dataOut.data_pre = self.dataIn.data.copy()
115 self.dataOut.data_pre = self.dataIn.data.copy()
116 self.dataOut.flagNoData = False
116 self.dataOut.flagNoData = False
117 self.dataOut.utctimeInit = self.dataIn.utctime
117 self.dataOut.utctimeInit = self.dataIn.utctime
118 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
118 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
119
119
120 if hasattr(self.dataIn, 'flagDataAsBlock'):
120 if hasattr(self.dataIn, 'flagDataAsBlock'):
121 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
121 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
122
122
123 if hasattr(self.dataIn, 'profileIndex'):
123 if hasattr(self.dataIn, 'profileIndex'):
124 self.dataOut.profileIndex = self.dataIn.profileIndex
124 self.dataOut.profileIndex = self.dataIn.profileIndex
125
125
126 if hasattr(self.dataIn, 'dataPP_POW'):
126 if hasattr(self.dataIn, 'dataPP_POW'):
127 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
127 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
128
128
129 if hasattr(self.dataIn, 'dataPP_POWER'):
129 if hasattr(self.dataIn, 'dataPP_POWER'):
130 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
130 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
131
131
132 if hasattr(self.dataIn, 'dataPP_DOP'):
132 if hasattr(self.dataIn, 'dataPP_DOP'):
133 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
133 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
134
134
135 if hasattr(self.dataIn, 'dataPP_SNR'):
135 if hasattr(self.dataIn, 'dataPP_SNR'):
136 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
136 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
137
137
138 if hasattr(self.dataIn, 'dataPP_WIDTH'):
138 if hasattr(self.dataIn, 'dataPP_WIDTH'):
139 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
139 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
140 return
140 return
141
141
142 #---------------------- Spectra Data ---------------------------
142 #---------------------- Spectra Data ---------------------------
143
143
144 if self.dataIn.type == "Spectra":
144 if self.dataIn.type == "Spectra":
145 #print("que paso en spectra")
145 #print("que paso en spectra")
146 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
146 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
147 self.dataOut.data_spc = self.dataIn.data_spc
147 self.dataOut.data_spc = self.dataIn.data_spc
148 self.dataOut.data_cspc = self.dataIn.data_cspc
148 self.dataOut.data_cspc = self.dataIn.data_cspc
149 self.dataOut.nProfiles = self.dataIn.nProfiles
149 self.dataOut.nProfiles = self.dataIn.nProfiles
150 self.dataOut.nIncohInt = self.dataIn.nIncohInt
150 self.dataOut.nIncohInt = self.dataIn.nIncohInt
151 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
151 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
152 self.dataOut.ippFactor = self.dataIn.ippFactor
152 self.dataOut.ippFactor = self.dataIn.ippFactor
153 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
153 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
154 self.dataOut.spc_noise = self.dataIn.getNoise()
154 self.dataOut.spc_noise = self.dataIn.getNoise()
155 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
155 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
156 # self.dataOut.normFactor = self.dataIn.normFactor
156 # self.dataOut.normFactor = self.dataIn.normFactor
157 self.dataOut.pairsList = self.dataIn.pairsList
157 self.dataOut.pairsList = self.dataIn.pairsList
158 self.dataOut.groupList = self.dataIn.pairsList
158 self.dataOut.groupList = self.dataIn.pairsList
159 self.dataOut.flagNoData = False
159 self.dataOut.flagNoData = False
160
160
161 if hasattr(self.dataIn, 'flagDataAsBlock'):
161 if hasattr(self.dataIn, 'flagDataAsBlock'):
162 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
162 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
163
163
164 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
164 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
165 self.dataOut.ChanDist = self.dataIn.ChanDist
165 self.dataOut.ChanDist = self.dataIn.ChanDist
166 else: self.dataOut.ChanDist = None
166 else: self.dataOut.ChanDist = None
167
167
168 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
168 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
169 # self.dataOut.VelRange = self.dataIn.VelRange
169 # self.dataOut.VelRange = self.dataIn.VelRange
170 #else: self.dataOut.VelRange = None
170 #else: self.dataOut.VelRange = None
171
171
172 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
172 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
173 self.dataOut.RadarConst = self.dataIn.RadarConst
173 self.dataOut.RadarConst = self.dataIn.RadarConst
174
174
175 if hasattr(self.dataIn, 'NPW'): #NPW
175 if hasattr(self.dataIn, 'NPW'): #NPW
176 self.dataOut.NPW = self.dataIn.NPW
176 self.dataOut.NPW = self.dataIn.NPW
177
177
178 if hasattr(self.dataIn, 'COFA'): #COFA
178 if hasattr(self.dataIn, 'COFA'): #COFA
179 self.dataOut.COFA = self.dataIn.COFA
179 self.dataOut.COFA = self.dataIn.COFA
180
180
181
181
182
182
183 #---------------------- Correlation Data ---------------------------
183 #---------------------- Correlation Data ---------------------------
184
184
185 if self.dataIn.type == "Correlation":
185 if self.dataIn.type == "Correlation":
186 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
186 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
187
187
188 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
188 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
189 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
189 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
190 self.dataOut.groupList = (acf_pairs, ccf_pairs)
190 self.dataOut.groupList = (acf_pairs, ccf_pairs)
191
191
192 self.dataOut.abscissaList = self.dataIn.lagRange
192 self.dataOut.abscissaList = self.dataIn.lagRange
193 self.dataOut.noise = self.dataIn.noise
193 self.dataOut.noise = self.dataIn.noise
194 self.dataOut.data_snr = self.dataIn.SNR
194 self.dataOut.data_snr = self.dataIn.SNR
195 self.dataOut.flagNoData = False
195 self.dataOut.flagNoData = False
196 self.dataOut.nAvg = self.dataIn.nAvg
196 self.dataOut.nAvg = self.dataIn.nAvg
197
197
198 #---------------------- Parameters Data ---------------------------
198 #---------------------- Parameters Data ---------------------------
199
199
200 if self.dataIn.type == "Parameters":
200 if self.dataIn.type == "Parameters":
201 self.dataOut.copy(self.dataIn)
201 self.dataOut.copy(self.dataIn)
202 self.dataOut.flagNoData = False
202 self.dataOut.flagNoData = False
203 #print("yo si entre")
203 #print("yo si entre")
204
204
205 return True
205 return True
206
206
207 self.__updateObjFromInput()
207 self.__updateObjFromInput()
208 #print("yo si entre2")
208 #print("yo si entre2")
209
209
210 self.dataOut.utctimeInit = self.dataIn.utctime
210 self.dataOut.utctimeInit = self.dataIn.utctime
211 self.dataOut.paramInterval = self.dataIn.timeInterval
211 self.dataOut.paramInterval = self.dataIn.timeInterval
212 #print("soy spectra ",self.dataOut.utctimeInit)
212 #print("soy spectra ",self.dataOut.utctimeInit)
213 return
213 return
214
214
215
215
216 def target(tups):
216 def target(tups):
217
217
218 obj, args = tups
218 obj, args = tups
219
219
220 return obj.FitGau(args)
220 return obj.FitGau(args)
221
221
222 class RemoveWideGC(Operation):
222 class RemoveWideGC(Operation):
223 ''' This class remove the wide clutter and replace it with a simple interpolation points
223 ''' This class remove the wide clutter and replace it with a simple interpolation points
224 This mainly applies to CLAIRE radar
224 This mainly applies to CLAIRE radar
225
225
226 ClutterWidth : Width to look for the clutter peak
226 ClutterWidth : Width to look for the clutter peak
227
227
228 Input:
228 Input:
229
229
230 self.dataOut.data_pre : SPC and CSPC
230 self.dataOut.data_pre : SPC and CSPC
231 self.dataOut.spc_range : To select wind and rainfall velocities
231 self.dataOut.spc_range : To select wind and rainfall velocities
232
232
233 Affected:
233 Affected:
234
234
235 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
235 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
236
236
237 Written by D. ScipiΓ³n 25.02.2021
237 Written by D. ScipiΓ³n 25.02.2021
238 '''
238 '''
239 def __init__(self):
239 def __init__(self):
240 Operation.__init__(self)
240 Operation.__init__(self)
241 self.i = 0
241 self.i = 0
242 self.ich = 0
242 self.ich = 0
243 self.ir = 0
243 self.ir = 0
244
244
245 def run(self, dataOut, ClutterWidth=2.5):
245 def run(self, dataOut, ClutterWidth=2.5):
246 # print ('Entering RemoveWideGC ... ')
246 # print ('Entering RemoveWideGC ... ')
247
247
248 self.spc = dataOut.data_pre[0].copy()
248 self.spc = dataOut.data_pre[0].copy()
249 self.spc_out = dataOut.data_pre[0].copy()
249 self.spc_out = dataOut.data_pre[0].copy()
250 self.Num_Chn = self.spc.shape[0]
250 self.Num_Chn = self.spc.shape[0]
251 self.Num_Hei = self.spc.shape[2]
251 self.Num_Hei = self.spc.shape[2]
252 VelRange = dataOut.spc_range[2][:-1]
252 VelRange = dataOut.spc_range[2][:-1]
253 dv = VelRange[1]-VelRange[0]
253 dv = VelRange[1]-VelRange[0]
254
254
255 # Find the velocities that corresponds to zero
255 # Find the velocities that corresponds to zero
256 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
256 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
257
257
258 # Removing novalid data from the spectra
258 # Removing novalid data from the spectra
259 for ich in range(self.Num_Chn) :
259 for ich in range(self.Num_Chn) :
260 for ir in range(self.Num_Hei) :
260 for ir in range(self.Num_Hei) :
261 # Estimate the noise at each range
261 # Estimate the noise at each range
262 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
262 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
263
263
264 # Removing the noise floor at each range
264 # Removing the noise floor at each range
265 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
265 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
266 self.spc[ich,novalid,ir] = HSn
266 self.spc[ich,novalid,ir] = HSn
267
267
268 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
268 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
269 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
269 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
270 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
270 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
271 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
271 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
272 continue
272 continue
273 junk3 = numpy.squeeze(numpy.diff(j1index))
273 junk3 = numpy.squeeze(numpy.diff(j1index))
274 junk4 = numpy.squeeze(numpy.diff(j2index))
274 junk4 = numpy.squeeze(numpy.diff(j2index))
275
275
276 valleyindex = j2index[numpy.where(junk4>1)]
276 valleyindex = j2index[numpy.where(junk4>1)]
277 peakindex = j1index[numpy.where(junk3>1)]
277 peakindex = j1index[numpy.where(junk3>1)]
278
278
279 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
279 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
280 if numpy.size(isvalid) == 0 :
280 if numpy.size(isvalid) == 0 :
281 continue
281 continue
282 if numpy.size(isvalid) >1 :
282 if numpy.size(isvalid) >1 :
283 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
283 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
284 isvalid = isvalid[vindex]
284 isvalid = isvalid[vindex]
285
285
286 # clutter peak
286 # clutter peak
287 gcpeak = peakindex[isvalid]
287 gcpeak = peakindex[isvalid]
288 vl = numpy.where(valleyindex < gcpeak)
288 vl = numpy.where(valleyindex < gcpeak)
289 if numpy.size(vl) == 0:
289 if numpy.size(vl) == 0:
290 continue
290 continue
291 gcvl = valleyindex[vl[0][-1]]
291 gcvl = valleyindex[vl[0][-1]]
292 vr = numpy.where(valleyindex > gcpeak)
292 vr = numpy.where(valleyindex > gcpeak)
293 if numpy.size(vr) == 0:
293 if numpy.size(vr) == 0:
294 continue
294 continue
295 gcvr = valleyindex[vr[0][0]]
295 gcvr = valleyindex[vr[0][0]]
296
296
297 # Removing the clutter
297 # Removing the clutter
298 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
298 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
299 gcindex = gc_values[gcvl+1:gcvr-1]
299 gcindex = gc_values[gcvl+1:gcvr-1]
300 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
300 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
301
301
302 dataOut.data_pre[0] = self.spc_out
302 dataOut.data_pre[0] = self.spc_out
303 #print ('Leaving RemoveWideGC ... ')
303 #print ('Leaving RemoveWideGC ... ')
304 return dataOut
304 return dataOut
305
305
306 class SpectralFilters(Operation):
306 class SpectralFilters(Operation):
307 ''' This class allows to replace the novalid values with noise for each channel
307 ''' This class allows to replace the novalid values with noise for each channel
308 This applies to CLAIRE RADAR
308 This applies to CLAIRE RADAR
309
309
310 PositiveLimit : RightLimit of novalid data
310 PositiveLimit : RightLimit of novalid data
311 NegativeLimit : LeftLimit of novalid data
311 NegativeLimit : LeftLimit of novalid data
312
312
313 Input:
313 Input:
314
314
315 self.dataOut.data_pre : SPC and CSPC
315 self.dataOut.data_pre : SPC and CSPC
316 self.dataOut.spc_range : To select wind and rainfall velocities
316 self.dataOut.spc_range : To select wind and rainfall velocities
317
317
318 Affected:
318 Affected:
319
319
320 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
320 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
321
321
322 Written by D. ScipiΓ³n 29.01.2021
322 Written by D. ScipiΓ³n 29.01.2021
323 '''
323 '''
324 def __init__(self):
324 def __init__(self):
325 Operation.__init__(self)
325 Operation.__init__(self)
326 self.i = 0
326 self.i = 0
327
327
328 def run(self, dataOut, ):
328 def run(self, dataOut, ):
329
329
330 self.spc = dataOut.data_pre[0].copy()
330 self.spc = dataOut.data_pre[0].copy()
331 self.Num_Chn = self.spc.shape[0]
331 self.Num_Chn = self.spc.shape[0]
332 VelRange = dataOut.spc_range[2]
332 VelRange = dataOut.spc_range[2]
333
333
334 # novalid corresponds to data within the Negative and PositiveLimit
334 # novalid corresponds to data within the Negative and PositiveLimit
335
335
336
336
337 # Removing novalid data from the spectra
337 # Removing novalid data from the spectra
338 for i in range(self.Num_Chn):
338 for i in range(self.Num_Chn):
339 self.spc[i,novalid,:] = dataOut.noise[i]
339 self.spc[i,novalid,:] = dataOut.noise[i]
340 dataOut.data_pre[0] = self.spc
340 dataOut.data_pre[0] = self.spc
341 return dataOut
341 return dataOut
342
342
343 class GaussianFit(Operation):
343 class GaussianFit(Operation):
344
344
345 '''
345 '''
346 Function that fit of one and two generalized gaussians (gg) based
346 Function that fit of one and two generalized gaussians (gg) based
347 on the PSD shape across an "power band" identified from a cumsum of
347 on the PSD shape across an "power band" identified from a cumsum of
348 the measured spectrum - noise.
348 the measured spectrum - noise.
349
349
350 Input:
350 Input:
351 self.dataOut.data_pre : SelfSpectra
351 self.dataOut.data_pre : SelfSpectra
352
352
353 Output:
353 Output:
354 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
354 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
355
355
356 '''
356 '''
357 def __init__(self):
357 def __init__(self):
358 Operation.__init__(self)
358 Operation.__init__(self)
359 self.i=0
359 self.i=0
360
360
361
361
362 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
362 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
363 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
363 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
364 """This routine will find a couple of generalized Gaussians to a power spectrum
364 """This routine will find a couple of generalized Gaussians to a power spectrum
365 methods: generalized, squared
365 methods: generalized, squared
366 input: spc
366 input: spc
367 output:
367 output:
368 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
368 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
369 """
369 """
370 print ('Entering ',method,' double Gaussian fit')
370 print ('Entering ',method,' double Gaussian fit')
371 self.spc = dataOut.data_pre[0].copy()
371 self.spc = dataOut.data_pre[0].copy()
372 self.Num_Hei = self.spc.shape[2]
372 self.Num_Hei = self.spc.shape[2]
373 self.Num_Bin = self.spc.shape[1]
373 self.Num_Bin = self.spc.shape[1]
374 self.Num_Chn = self.spc.shape[0]
374 self.Num_Chn = self.spc.shape[0]
375
375
376 start_time = time.time()
376 start_time = time.time()
377
377
378 pool = Pool(processes=self.Num_Chn)
378 pool = Pool(processes=self.Num_Chn)
379 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
379 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
380 objs = [self for __ in range(self.Num_Chn)]
380 objs = [self for __ in range(self.Num_Chn)]
381 attrs = list(zip(objs, args))
381 attrs = list(zip(objs, args))
382 DGauFitParam = pool.map(target, attrs)
382 DGauFitParam = pool.map(target, attrs)
383 # Parameters:
383 # Parameters:
384 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
384 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
385 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
385 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
386
386
387 # Double Gaussian Curves
387 # Double Gaussian Curves
388 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
388 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
389 gau0[:] = numpy.NaN
389 gau0[:] = numpy.NaN
390 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
390 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
391 gau1[:] = numpy.NaN
391 gau1[:] = numpy.NaN
392 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
392 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
393 for iCh in range(self.Num_Chn):
393 for iCh in range(self.Num_Chn):
394 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
394 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
395 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
395 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
396 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
396 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
397 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
397 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
398 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
398 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
399 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
399 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
400 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
400 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
401 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
401 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
402 if method == 'genealized':
402 if method == 'genealized':
403 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
403 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
404 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
404 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
405 elif method == 'squared':
405 elif method == 'squared':
406 p0 = 2.
406 p0 = 2.
407 p1 = 2.
407 p1 = 2.
408 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
408 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
409 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
409 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
410 dataOut.GaussFit0 = gau0
410 dataOut.GaussFit0 = gau0
411 dataOut.GaussFit1 = gau1
411 dataOut.GaussFit1 = gau1
412
412
413 print('Leaving ',method ,' double Gaussian fit')
413 print('Leaving ',method ,' double Gaussian fit')
414 return dataOut
414 return dataOut
415
415
416 def FitGau(self, X):
416 def FitGau(self, X):
417 # print('Entering FitGau')
417 # print('Entering FitGau')
418 # Assigning the variables
418 # Assigning the variables
419 Vrange, ch, wnoise, num_intg, SNRlimit = X
419 Vrange, ch, wnoise, num_intg, SNRlimit = X
420 # Noise Limits
420 # Noise Limits
421 noisebl = wnoise * 0.9
421 noisebl = wnoise * 0.9
422 noisebh = wnoise * 1.1
422 noisebh = wnoise * 1.1
423 # Radar Velocity
423 # Radar Velocity
424 Va = max(Vrange)
424 Va = max(Vrange)
425 deltav = Vrange[1] - Vrange[0]
425 deltav = Vrange[1] - Vrange[0]
426 x = numpy.arange(self.Num_Bin)
426 x = numpy.arange(self.Num_Bin)
427
427
428 # print ('stop 0')
428 # print ('stop 0')
429
429
430 # 5 parameters, 2 Gaussians
430 # 5 parameters, 2 Gaussians
431 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
431 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
432 DGauFitParam[:] = numpy.NaN
432 DGauFitParam[:] = numpy.NaN
433
433
434 # SPCparam = []
434 # SPCparam = []
435 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
435 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
436 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
436 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
437 # SPC_ch1[:] = 0 #numpy.NaN
437 # SPC_ch1[:] = 0 #numpy.NaN
438 # SPC_ch2[:] = 0 #numpy.NaN
438 # SPC_ch2[:] = 0 #numpy.NaN
439 # print ('stop 1')
439 # print ('stop 1')
440 for ht in range(self.Num_Hei):
440 for ht in range(self.Num_Hei):
441 # print (ht)
441 # print (ht)
442 # print ('stop 2')
442 # print ('stop 2')
443 # Spectra at each range
443 # Spectra at each range
444 spc = numpy.asarray(self.spc)[ch,:,ht]
444 spc = numpy.asarray(self.spc)[ch,:,ht]
445 snr = ( spc.mean() - wnoise ) / wnoise
445 snr = ( spc.mean() - wnoise ) / wnoise
446 snrdB = 10.*numpy.log10(snr)
446 snrdB = 10.*numpy.log10(snr)
447
447
448 #print ('stop 3')
448 #print ('stop 3')
449 if snrdB < SNRlimit :
449 if snrdB < SNRlimit :
450 # snr = numpy.NaN
450 # snr = numpy.NaN
451 # SPC_ch1[:,ht] = 0#numpy.NaN
451 # SPC_ch1[:,ht] = 0#numpy.NaN
452 # SPC_ch1[:,ht] = 0#numpy.NaN
452 # SPC_ch1[:,ht] = 0#numpy.NaN
453 # SPCparam = (SPC_ch1,SPC_ch2)
453 # SPCparam = (SPC_ch1,SPC_ch2)
454 # print ('SNR less than SNRth')
454 # print ('SNR less than SNRth')
455 continue
455 continue
456 # wnoise = hildebrand_sekhon(spc,num_intg)
456 # wnoise = hildebrand_sekhon(spc,num_intg)
457 # print ('stop 2.01')
457 # print ('stop 2.01')
458 #############################################
458 #############################################
459 # normalizing spc and noise
459 # normalizing spc and noise
460 # This part differs from gg1
460 # This part differs from gg1
461 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
461 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
462 #spc = spc / spc_norm_max
462 #spc = spc / spc_norm_max
463 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
463 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
464 #############################################
464 #############################################
465
465
466 # print ('stop 2.1')
466 # print ('stop 2.1')
467 fatspectra=1.0
467 fatspectra=1.0
468 # noise per channel.... we might want to use the noise at each range
468 # noise per channel.... we might want to use the noise at each range
469
469
470 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
470 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
471 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
471 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
472 #if wnoise>1.1*pnoise: # to be tested later
472 #if wnoise>1.1*pnoise: # to be tested later
473 # wnoise=pnoise
473 # wnoise=pnoise
474 # noisebl = wnoise*0.9
474 # noisebl = wnoise*0.9
475 # noisebh = wnoise*1.1
475 # noisebh = wnoise*1.1
476 spc = spc - wnoise # signal
476 spc = spc - wnoise # signal
477
477
478 # print ('stop 2.2')
478 # print ('stop 2.2')
479 minx = numpy.argmin(spc)
479 minx = numpy.argmin(spc)
480 #spcs=spc.copy()
480 #spcs=spc.copy()
481 spcs = numpy.roll(spc,-minx)
481 spcs = numpy.roll(spc,-minx)
482 cum = numpy.cumsum(spcs)
482 cum = numpy.cumsum(spcs)
483 # tot_noise = wnoise * self.Num_Bin #64;
483 # tot_noise = wnoise * self.Num_Bin #64;
484
484
485 # print ('stop 2.3')
485 # print ('stop 2.3')
486 # snr = sum(spcs) / tot_noise
486 # snr = sum(spcs) / tot_noise
487 # snrdB = 10.*numpy.log10(snr)
487 # snrdB = 10.*numpy.log10(snr)
488 #print ('stop 3')
488 #print ('stop 3')
489 # if snrdB < SNRlimit :
489 # if snrdB < SNRlimit :
490 # snr = numpy.NaN
490 # snr = numpy.NaN
491 # SPC_ch1[:,ht] = 0#numpy.NaN
491 # SPC_ch1[:,ht] = 0#numpy.NaN
492 # SPC_ch1[:,ht] = 0#numpy.NaN
492 # SPC_ch1[:,ht] = 0#numpy.NaN
493 # SPCparam = (SPC_ch1,SPC_ch2)
493 # SPCparam = (SPC_ch1,SPC_ch2)
494 # print ('SNR less than SNRth')
494 # print ('SNR less than SNRth')
495 # continue
495 # continue
496
496
497
497
498 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
498 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
499 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
499 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
500 # print ('stop 4')
500 # print ('stop 4')
501 cummax = max(cum)
501 cummax = max(cum)
502 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
502 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
503 cumlo = cummax * epsi
503 cumlo = cummax * epsi
504 cumhi = cummax * (1-epsi)
504 cumhi = cummax * (1-epsi)
505 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
505 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
506
506
507 # print ('stop 5')
507 # print ('stop 5')
508 if len(powerindex) < 1:# case for powerindex 0
508 if len(powerindex) < 1:# case for powerindex 0
509 # print ('powerindex < 1')
509 # print ('powerindex < 1')
510 continue
510 continue
511 powerlo = powerindex[0]
511 powerlo = powerindex[0]
512 powerhi = powerindex[-1]
512 powerhi = powerindex[-1]
513 powerwidth = powerhi-powerlo
513 powerwidth = powerhi-powerlo
514 if powerwidth <= 1:
514 if powerwidth <= 1:
515 # print('powerwidth <= 1')
515 # print('powerwidth <= 1')
516 continue
516 continue
517
517
518 # print ('stop 6')
518 # print ('stop 6')
519 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
519 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
520 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
520 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
521 midpeak = (firstpeak + secondpeak)/2.
521 midpeak = (firstpeak + secondpeak)/2.
522 firstamp = spcs[int(firstpeak)]
522 firstamp = spcs[int(firstpeak)]
523 secondamp = spcs[int(secondpeak)]
523 secondamp = spcs[int(secondpeak)]
524 midamp = spcs[int(midpeak)]
524 midamp = spcs[int(midpeak)]
525
525
526 y_data = spc + wnoise
526 y_data = spc + wnoise
527
527
528 ''' single Gaussian '''
528 ''' single Gaussian '''
529 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
529 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
530 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
530 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
531 power0 = 2.
531 power0 = 2.
532 amplitude0 = midamp
532 amplitude0 = midamp
533 state0 = [shift0,width0,amplitude0,power0,wnoise]
533 state0 = [shift0,width0,amplitude0,power0,wnoise]
534 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
534 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
535 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
535 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
536 # print ('stop 7.1')
536 # print ('stop 7.1')
537 # print (bnds)
537 # print (bnds)
538
538
539 chiSq1=lsq1[1]
539 chiSq1=lsq1[1]
540
540
541 # print ('stop 8')
541 # print ('stop 8')
542 if fatspectra<1.0 and powerwidth<4:
542 if fatspectra<1.0 and powerwidth<4:
543 choice=0
543 choice=0
544 Amplitude0=lsq1[0][2]
544 Amplitude0=lsq1[0][2]
545 shift0=lsq1[0][0]
545 shift0=lsq1[0][0]
546 width0=lsq1[0][1]
546 width0=lsq1[0][1]
547 p0=lsq1[0][3]
547 p0=lsq1[0][3]
548 Amplitude1=0.
548 Amplitude1=0.
549 shift1=0.
549 shift1=0.
550 width1=0.
550 width1=0.
551 p1=0.
551 p1=0.
552 noise=lsq1[0][4]
552 noise=lsq1[0][4]
553 #return (numpy.array([shift0,width0,Amplitude0,p0]),
553 #return (numpy.array([shift0,width0,Amplitude0,p0]),
554 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
554 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
555
555
556 # print ('stop 9')
556 # print ('stop 9')
557 ''' two Gaussians '''
557 ''' two Gaussians '''
558 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
558 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
559 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
559 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
560 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
560 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
561 width0 = powerwidth/6.
561 width0 = powerwidth/6.
562 width1 = width0
562 width1 = width0
563 power0 = 2.
563 power0 = 2.
564 power1 = power0
564 power1 = power0
565 amplitude0 = firstamp
565 amplitude0 = firstamp
566 amplitude1 = secondamp
566 amplitude1 = secondamp
567 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
567 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
568 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
568 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
569 bnds=((0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
569 bnds=((0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
570 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
570 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
571
571
572 # print ('stop 10')
572 # print ('stop 10')
573 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
573 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
574
574
575 # print ('stop 11')
575 # print ('stop 11')
576 chiSq2 = lsq2[1]
576 chiSq2 = lsq2[1]
577
577
578 # print ('stop 12')
578 # print ('stop 12')
579
579
580 oneG = (chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
580 oneG = (chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
581
581
582 # print ('stop 13')
582 # print ('stop 13')
583 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
583 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
584 if oneG:
584 if oneG:
585 choice = 0
585 choice = 0
586 else:
586 else:
587 w1 = lsq2[0][1]; w2 = lsq2[0][5]
587 w1 = lsq2[0][1]; w2 = lsq2[0][5]
588 a1 = lsq2[0][2]; a2 = lsq2[0][6]
588 a1 = lsq2[0][2]; a2 = lsq2[0][6]
589 p1 = lsq2[0][3]; p2 = lsq2[0][7]
589 p1 = lsq2[0][3]; p2 = lsq2[0][7]
590 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
590 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
591 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
591 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
592 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
592 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
593
593
594 if gp1>gp2:
594 if gp1>gp2:
595 if a1>0.7*a2:
595 if a1>0.7*a2:
596 choice = 1
596 choice = 1
597 else:
597 else:
598 choice = 2
598 choice = 2
599 elif gp2>gp1:
599 elif gp2>gp1:
600 if a2>0.7*a1:
600 if a2>0.7*a1:
601 choice = 2
601 choice = 2
602 else:
602 else:
603 choice = 1
603 choice = 1
604 else:
604 else:
605 choice = numpy.argmax([a1,a2])+1
605 choice = numpy.argmax([a1,a2])+1
606 #else:
606 #else:
607 #choice=argmin([std2a,std2b])+1
607 #choice=argmin([std2a,std2b])+1
608
608
609 else: # with low SNR go to the most energetic peak
609 else: # with low SNR go to the most energetic peak
610 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
610 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
611
611
612 # print ('stop 14')
612 # print ('stop 14')
613 shift0 = lsq2[0][0]
613 shift0 = lsq2[0][0]
614 vel0 = Vrange[0] + shift0 * deltav
614 vel0 = Vrange[0] + shift0 * deltav
615 shift1 = lsq2[0][4]
615 shift1 = lsq2[0][4]
616 # vel1=Vrange[0] + shift1 * deltav
616 # vel1=Vrange[0] + shift1 * deltav
617
617
618 # max_vel = 1.0
618 # max_vel = 1.0
619 # Va = max(Vrange)
619 # Va = max(Vrange)
620 # deltav = Vrange[1]-Vrange[0]
620 # deltav = Vrange[1]-Vrange[0]
621 # print ('stop 15')
621 # print ('stop 15')
622 #first peak will be 0, second peak will be 1
622 #first peak will be 0, second peak will be 1
623 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
623 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
624 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
624 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
625 shift0 = lsq2[0][0]
625 shift0 = lsq2[0][0]
626 width0 = lsq2[0][1]
626 width0 = lsq2[0][1]
627 Amplitude0 = lsq2[0][2]
627 Amplitude0 = lsq2[0][2]
628 p0 = lsq2[0][3]
628 p0 = lsq2[0][3]
629
629
630 shift1 = lsq2[0][4]
630 shift1 = lsq2[0][4]
631 width1 = lsq2[0][5]
631 width1 = lsq2[0][5]
632 Amplitude1 = lsq2[0][6]
632 Amplitude1 = lsq2[0][6]
633 p1 = lsq2[0][7]
633 p1 = lsq2[0][7]
634 noise = lsq2[0][8]
634 noise = lsq2[0][8]
635 else:
635 else:
636 shift1 = lsq2[0][0]
636 shift1 = lsq2[0][0]
637 width1 = lsq2[0][1]
637 width1 = lsq2[0][1]
638 Amplitude1 = lsq2[0][2]
638 Amplitude1 = lsq2[0][2]
639 p1 = lsq2[0][3]
639 p1 = lsq2[0][3]
640
640
641 shift0 = lsq2[0][4]
641 shift0 = lsq2[0][4]
642 width0 = lsq2[0][5]
642 width0 = lsq2[0][5]
643 Amplitude0 = lsq2[0][6]
643 Amplitude0 = lsq2[0][6]
644 p0 = lsq2[0][7]
644 p0 = lsq2[0][7]
645 noise = lsq2[0][8]
645 noise = lsq2[0][8]
646
646
647 if Amplitude0<0.05: # in case the peak is noise
647 if Amplitude0<0.05: # in case the peak is noise
648 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
648 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
649 if Amplitude1<0.05:
649 if Amplitude1<0.05:
650 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
650 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
651
651
652 # print ('stop 16 ')
652 # print ('stop 16 ')
653 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
653 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
654 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
654 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
655 # SPCparam = (SPC_ch1,SPC_ch2)
655 # SPCparam = (SPC_ch1,SPC_ch2)
656
656
657 DGauFitParam[0,ht,0] = noise
657 DGauFitParam[0,ht,0] = noise
658 DGauFitParam[0,ht,1] = noise
658 DGauFitParam[0,ht,1] = noise
659 DGauFitParam[1,ht,0] = Amplitude0
659 DGauFitParam[1,ht,0] = Amplitude0
660 DGauFitParam[1,ht,1] = Amplitude1
660 DGauFitParam[1,ht,1] = Amplitude1
661 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
661 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
662 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
662 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
663 DGauFitParam[3,ht,0] = width0 * deltav
663 DGauFitParam[3,ht,0] = width0 * deltav
664 DGauFitParam[3,ht,1] = width1 * deltav
664 DGauFitParam[3,ht,1] = width1 * deltav
665 DGauFitParam[4,ht,0] = p0
665 DGauFitParam[4,ht,0] = p0
666 DGauFitParam[4,ht,1] = p1
666 DGauFitParam[4,ht,1] = p1
667
667
668 # print (DGauFitParam.shape)
668 # print (DGauFitParam.shape)
669 # print ('Leaving FitGau')
669 # print ('Leaving FitGau')
670 return DGauFitParam
670 return DGauFitParam
671 # return SPCparam
671 # return SPCparam
672 # return GauSPC
672 # return GauSPC
673
673
674 def y_model1(self,x,state):
674 def y_model1(self,x,state):
675 shift0, width0, amplitude0, power0, noise = state
675 shift0, width0, amplitude0, power0, noise = state
676 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
676 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
677 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
677 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
678 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
678 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
679 return model0 + model0u + model0d + noise
679 return model0 + model0u + model0d + noise
680
680
681 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
681 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
682 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
682 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
683 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
683 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
684 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
684 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
685 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
685 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
686
686
687 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
687 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
688 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
688 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
689 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
689 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
690 return model0 + model0u + model0d + model1 + model1u + model1d + noise
690 return model0 + model0u + model0d + model1 + model1u + model1d + noise
691
691
692 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
692 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
693
693
694 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
694 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
695
695
696 def misfit2(self,state,y_data,x,num_intg):
696 def misfit2(self,state,y_data,x,num_intg):
697 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
697 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
698
698
699
699
700
700
701 class PrecipitationProc(Operation):
701 class PrecipitationProc(Operation):
702
702
703 '''
703 '''
704 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
704 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
705
705
706 Input:
706 Input:
707 self.dataOut.data_pre : SelfSpectra
707 self.dataOut.data_pre : SelfSpectra
708
708
709 Output:
709 Output:
710
710
711 self.dataOut.data_output : Reflectivity factor, rainfall Rate
711 self.dataOut.data_output : Reflectivity factor, rainfall Rate
712
712
713
713
714 Parameters affected:
714 Parameters affected:
715 '''
715 '''
716
716
717 def __init__(self):
717 def __init__(self):
718 Operation.__init__(self)
718 Operation.__init__(self)
719 self.i=0
719 self.i=0
720
720
721 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
721 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
722 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
722 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
723
723
724 # print ('Entering PrecepitationProc ... ')
724 # print ('Entering PrecepitationProc ... ')
725
725
726 if radar == "MIRA35C" :
726 if radar == "MIRA35C" :
727
727
728 self.spc = dataOut.data_pre[0].copy()
728 self.spc = dataOut.data_pre[0].copy()
729 self.Num_Hei = self.spc.shape[2]
729 self.Num_Hei = self.spc.shape[2]
730 self.Num_Bin = self.spc.shape[1]
730 self.Num_Bin = self.spc.shape[1]
731 self.Num_Chn = self.spc.shape[0]
731 self.Num_Chn = self.spc.shape[0]
732 Ze = self.dBZeMODE2(dataOut)
732 Ze = self.dBZeMODE2(dataOut)
733
733
734 else:
734 else:
735
735
736 self.spc = dataOut.data_pre[0].copy()
736 self.spc = dataOut.data_pre[0].copy()
737
737
738 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
738 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
739 self.spc[:,:,0:7]= numpy.NaN
739 self.spc[:,:,0:7]= numpy.NaN
740
740
741 self.Num_Hei = self.spc.shape[2]
741 self.Num_Hei = self.spc.shape[2]
742 self.Num_Bin = self.spc.shape[1]
742 self.Num_Bin = self.spc.shape[1]
743 self.Num_Chn = self.spc.shape[0]
743 self.Num_Chn = self.spc.shape[0]
744
744
745 VelRange = dataOut.spc_range[2]
745 VelRange = dataOut.spc_range[2]
746
746
747 ''' Se obtiene la constante del RADAR '''
747 ''' Se obtiene la constante del RADAR '''
748
748
749 self.Pt = Pt
749 self.Pt = Pt
750 self.Gt = Gt
750 self.Gt = Gt
751 self.Gr = Gr
751 self.Gr = Gr
752 self.Lambda = Lambda
752 self.Lambda = Lambda
753 self.aL = aL
753 self.aL = aL
754 self.tauW = tauW
754 self.tauW = tauW
755 self.ThetaT = ThetaT
755 self.ThetaT = ThetaT
756 self.ThetaR = ThetaR
756 self.ThetaR = ThetaR
757 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
757 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
758 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
758 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
759 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
759 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
760
760
761 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
761 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
762 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
762 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
763 RadarConstant = 10e-26 * Numerator / Denominator #
763 RadarConstant = 10e-26 * Numerator / Denominator #
764 ExpConstant = 10**(40/10) #Constante Experimental
764 ExpConstant = 10**(40/10) #Constante Experimental
765
765
766 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
766 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
767 for i in range(self.Num_Chn):
767 for i in range(self.Num_Chn):
768 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
768 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
769 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
769 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
770
770
771 SPCmean = numpy.mean(SignalPower, 0)
771 SPCmean = numpy.mean(SignalPower, 0)
772 Pr = SPCmean[:,:]/dataOut.normFactor
772 Pr = SPCmean[:,:]/dataOut.normFactor
773
773
774 # Declaring auxiliary variables
774 # Declaring auxiliary variables
775 Range = dataOut.heightList*1000. #Range in m
775 Range = dataOut.heightList*1000. #Range in m
776 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
776 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
777 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
777 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
778 zMtrx = rMtrx+Altitude
778 zMtrx = rMtrx+Altitude
779 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
779 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
780 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
780 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
781
781
782 # height dependence to air density Foote and Du Toit (1969)
782 # height dependence to air density Foote and Du Toit (1969)
783 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
783 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
784 VMtrx = VelMtrx / delv_z #Normalized velocity
784 VMtrx = VelMtrx / delv_z #Normalized velocity
785 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
785 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
786 # Diameter is related to the fall speed of falling drops
786 # Diameter is related to the fall speed of falling drops
787 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
787 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
788 # Only valid for D>= 0.16 mm
788 # Only valid for D>= 0.16 mm
789 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
789 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
790
790
791 #Calculate Radar Reflectivity ETAn
791 #Calculate Radar Reflectivity ETAn
792 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
792 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
793 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
793 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
794 # Radar Cross Section
794 # Radar Cross Section
795 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
795 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
796 # Drop Size Distribution
796 # Drop Size Distribution
797 DSD = ETAn / sigmaD
797 DSD = ETAn / sigmaD
798 # Equivalente Reflectivy
798 # Equivalente Reflectivy
799 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
799 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
800 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
800 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
801 # RainFall Rate
801 # RainFall Rate
802 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
802 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
803
803
804 # Censoring the data
804 # Censoring the data
805 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
805 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
806 SNRth = 10**(SNRdBlimit/10) #-30dB
806 SNRth = 10**(SNRdBlimit/10) #-30dB
807 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
807 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
808 W = numpy.nanmean(dataOut.data_dop,0)
808 W = numpy.nanmean(dataOut.data_dop,0)
809 W[novalid] = numpy.NaN
809 W[novalid] = numpy.NaN
810 Ze_org[novalid] = numpy.NaN
810 Ze_org[novalid] = numpy.NaN
811 RR[novalid] = numpy.NaN
811 RR[novalid] = numpy.NaN
812
812
813 dataOut.data_output = RR[8]
813 dataOut.data_output = RR[8]
814 dataOut.data_param = numpy.ones([3,self.Num_Hei])
814 dataOut.data_param = numpy.ones([3,self.Num_Hei])
815 dataOut.channelList = [0,1,2]
815 dataOut.channelList = [0,1,2]
816
816
817 dataOut.data_param[0]=10*numpy.log10(Ze_org)
817 dataOut.data_param[0]=10*numpy.log10(Ze_org)
818 dataOut.data_param[1]=-W
818 dataOut.data_param[1]=-W
819 dataOut.data_param[2]=RR
819 dataOut.data_param[2]=RR
820
820
821 # print ('Leaving PrecepitationProc ... ')
821 # print ('Leaving PrecepitationProc ... ')
822 return dataOut
822 return dataOut
823
823
824 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
824 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
825
825
826 NPW = dataOut.NPW
826 NPW = dataOut.NPW
827 COFA = dataOut.COFA
827 COFA = dataOut.COFA
828
828
829 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
829 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
830 RadarConst = dataOut.RadarConst
830 RadarConst = dataOut.RadarConst
831 #frequency = 34.85*10**9
831 #frequency = 34.85*10**9
832
832
833 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
833 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
834 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
834 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
835
835
836 ETA = numpy.sum(SNR,1)
836 ETA = numpy.sum(SNR,1)
837
837
838 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
838 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
839
839
840 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
840 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
841
841
842 for r in range(self.Num_Hei):
842 for r in range(self.Num_Hei):
843
843
844 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
844 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
845 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
845 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
846
846
847 return Ze
847 return Ze
848
848
849 # def GetRadarConstant(self):
849 # def GetRadarConstant(self):
850 #
850 #
851 # """
851 # """
852 # Constants:
852 # Constants:
853 #
853 #
854 # Pt: Transmission Power dB 5kW 5000
854 # Pt: Transmission Power dB 5kW 5000
855 # Gt: Transmission Gain dB 24.7 dB 295.1209
855 # Gt: Transmission Gain dB 24.7 dB 295.1209
856 # Gr: Reception Gain dB 18.5 dB 70.7945
856 # Gr: Reception Gain dB 18.5 dB 70.7945
857 # Lambda: Wavelenght m 0.6741 m 0.6741
857 # Lambda: Wavelenght m 0.6741 m 0.6741
858 # aL: Attenuation loses dB 4dB 2.5118
858 # aL: Attenuation loses dB 4dB 2.5118
859 # tauW: Width of transmission pulse s 4us 4e-6
859 # tauW: Width of transmission pulse s 4us 4e-6
860 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
860 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
861 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
861 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
862 #
862 #
863 # """
863 # """
864 #
864 #
865 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
865 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
866 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
866 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
867 # RadarConstant = Numerator / Denominator
867 # RadarConstant = Numerator / Denominator
868 #
868 #
869 # return RadarConstant
869 # return RadarConstant
870
870
871
871
872
872
873 class FullSpectralAnalysis(Operation):
873 class FullSpectralAnalysis(Operation):
874
874
875 """
875 """
876 Function that implements Full Spectral Analysis technique.
876 Function that implements Full Spectral Analysis technique.
877
877
878 Input:
878 Input:
879 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
879 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
880 self.dataOut.groupList : Pairlist of channels
880 self.dataOut.groupList : Pairlist of channels
881 self.dataOut.ChanDist : Physical distance between receivers
881 self.dataOut.ChanDist : Physical distance between receivers
882
882
883
883
884 Output:
884 Output:
885
885
886 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
886 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
887
887
888
888
889 Parameters affected: Winds, height range, SNR
889 Parameters affected: Winds, height range, SNR
890
890
891 """
891 """
892 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
892 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
893 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
893 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
894
894
895 spc = dataOut.data_pre[0].copy()
895 spc = dataOut.data_pre[0].copy()
896 cspc = dataOut.data_pre[1]
896 cspc = dataOut.data_pre[1]
897 nHeights = spc.shape[2]
897 nHeights = spc.shape[2]
898
898
899 # first_height = 0.75 #km (ref: data header 20170822)
899 # first_height = 0.75 #km (ref: data header 20170822)
900 # resolution_height = 0.075 #km
900 # resolution_height = 0.075 #km
901 '''
901 '''
902 finding height range. check this when radar parameters are changed!
902 finding height range. check this when radar parameters are changed!
903 '''
903 '''
904 if maxheight is not None:
904 if maxheight is not None:
905 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
905 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
906 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
906 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
907 else:
907 else:
908 range_max = nHeights
908 range_max = nHeights
909 if minheight is not None:
909 if minheight is not None:
910 # range_min = int((minheight - first_height) / resolution_height) # theoretical
910 # range_min = int((minheight - first_height) / resolution_height) # theoretical
911 range_min = int(13.26 * minheight - 5) # empirical, works better
911 range_min = int(13.26 * minheight - 5) # empirical, works better
912 if range_min < 0:
912 if range_min < 0:
913 range_min = 0
913 range_min = 0
914 else:
914 else:
915 range_min = 0
915 range_min = 0
916
916
917 pairsList = dataOut.groupList
917 pairsList = dataOut.groupList
918 if dataOut.ChanDist is not None :
918 if dataOut.ChanDist is not None :
919 ChanDist = dataOut.ChanDist
919 ChanDist = dataOut.ChanDist
920 else:
920 else:
921 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
921 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
922
922
923 # 4 variables: zonal, meridional, vertical, and average SNR
923 # 4 variables: zonal, meridional, vertical, and average SNR
924 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
924 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
925 velocityX = numpy.zeros([nHeights]) * numpy.NaN
925 velocityX = numpy.zeros([nHeights]) * numpy.NaN
926 velocityY = numpy.zeros([nHeights]) * numpy.NaN
926 velocityY = numpy.zeros([nHeights]) * numpy.NaN
927 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
927 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
928
928
929 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
929 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
930
930
931 '''***********************************************WIND ESTIMATION**************************************'''
931 '''***********************************************WIND ESTIMATION**************************************'''
932 for Height in range(nHeights):
932 for Height in range(nHeights):
933
933
934 if Height >= range_min and Height < range_max:
934 if Height >= range_min and Height < range_max:
935 # error_code will be useful in future analysis
935 # error_code will be useful in future analysis
936 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
936 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
937 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
937 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
938
938
939 if abs(Vzon) < 100. and abs(Vmer) < 100.:
939 if abs(Vzon) < 100. and abs(Vmer) < 100.:
940 velocityX[Height] = Vzon
940 velocityX[Height] = Vzon
941 velocityY[Height] = -Vmer
941 velocityY[Height] = -Vmer
942 velocityZ[Height] = Vver
942 velocityZ[Height] = Vver
943
943
944 # Censoring data with SNR threshold
944 # Censoring data with SNR threshold
945 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
945 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
946
946
947 data_param[0] = velocityX
947 data_param[0] = velocityX
948 data_param[1] = velocityY
948 data_param[1] = velocityY
949 data_param[2] = velocityZ
949 data_param[2] = velocityZ
950 data_param[3] = dbSNR
950 data_param[3] = dbSNR
951 dataOut.data_param = data_param
951 dataOut.data_param = data_param
952 return dataOut
952 return dataOut
953
953
954 def moving_average(self,x, N=2):
954 def moving_average(self,x, N=2):
955 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
955 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
956 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
956 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
957
957
958 def gaus(self,xSamples,Amp,Mu,Sigma):
958 def gaus(self,xSamples,Amp,Mu,Sigma):
959 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
959 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
960
960
961 def Moments(self, ySamples, xSamples):
961 def Moments(self, ySamples, xSamples):
962 Power = numpy.nanmean(ySamples) # Power, 0th Moment
962 Power = numpy.nanmean(ySamples) # Power, 0th Moment
963 yNorm = ySamples / numpy.nansum(ySamples)
963 yNorm = ySamples / numpy.nansum(ySamples)
964 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
964 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
965 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
965 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
966 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
966 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
967 return numpy.array([Power,RadVel,StdDev])
967 return numpy.array([Power,RadVel,StdDev])
968
968
969 def StopWindEstimation(self, error_code):
969 def StopWindEstimation(self, error_code):
970 Vzon = numpy.NaN
970 Vzon = numpy.NaN
971 Vmer = numpy.NaN
971 Vmer = numpy.NaN
972 Vver = numpy.NaN
972 Vver = numpy.NaN
973 return Vzon, Vmer, Vver, error_code
973 return Vzon, Vmer, Vver, error_code
974
974
975 def AntiAliasing(self, interval, maxstep):
975 def AntiAliasing(self, interval, maxstep):
976 """
976 """
977 function to prevent errors from aliased values when computing phaseslope
977 function to prevent errors from aliased values when computing phaseslope
978 """
978 """
979 antialiased = numpy.zeros(len(interval))
979 antialiased = numpy.zeros(len(interval))
980 copyinterval = interval.copy()
980 copyinterval = interval.copy()
981
981
982 antialiased[0] = copyinterval[0]
982 antialiased[0] = copyinterval[0]
983
983
984 for i in range(1,len(antialiased)):
984 for i in range(1,len(antialiased)):
985 step = interval[i] - interval[i-1]
985 step = interval[i] - interval[i-1]
986 if step > maxstep:
986 if step > maxstep:
987 copyinterval -= 2*numpy.pi
987 copyinterval -= 2*numpy.pi
988 antialiased[i] = copyinterval[i]
988 antialiased[i] = copyinterval[i]
989 elif step < maxstep*(-1):
989 elif step < maxstep*(-1):
990 copyinterval += 2*numpy.pi
990 copyinterval += 2*numpy.pi
991 antialiased[i] = copyinterval[i]
991 antialiased[i] = copyinterval[i]
992 else:
992 else:
993 antialiased[i] = copyinterval[i].copy()
993 antialiased[i] = copyinterval[i].copy()
994
994
995 return antialiased
995 return antialiased
996
996
997 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
997 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
998 """
998 """
999 Function that Calculates Zonal, Meridional and Vertical wind velocities.
999 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1000 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1000 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1001
1001
1002 Input:
1002 Input:
1003 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1003 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1004 pairsList : Pairlist of channels
1004 pairsList : Pairlist of channels
1005 ChanDist : array of xi_ij and eta_ij
1005 ChanDist : array of xi_ij and eta_ij
1006 Height : height at which data is processed
1006 Height : height at which data is processed
1007 noise : noise in [channels] format for specific height
1007 noise : noise in [channels] format for specific height
1008 Abbsisarange : range of the frequencies or velocities
1008 Abbsisarange : range of the frequencies or velocities
1009 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1009 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1010
1010
1011 Output:
1011 Output:
1012 Vzon, Vmer, Vver : wind velocities
1012 Vzon, Vmer, Vver : wind velocities
1013 error_code : int that states where code is terminated
1013 error_code : int that states where code is terminated
1014
1014
1015 0 : no error detected
1015 0 : no error detected
1016 1 : Gaussian of mean spc exceeds widthlimit
1016 1 : Gaussian of mean spc exceeds widthlimit
1017 2 : no Gaussian of mean spc found
1017 2 : no Gaussian of mean spc found
1018 3 : SNR to low or velocity to high -> prec. e.g.
1018 3 : SNR to low or velocity to high -> prec. e.g.
1019 4 : at least one Gaussian of cspc exceeds widthlimit
1019 4 : at least one Gaussian of cspc exceeds widthlimit
1020 5 : zero out of three cspc Gaussian fits converged
1020 5 : zero out of three cspc Gaussian fits converged
1021 6 : phase slope fit could not be found
1021 6 : phase slope fit could not be found
1022 7 : arrays used to fit phase have different length
1022 7 : arrays used to fit phase have different length
1023 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1023 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1024
1024
1025 """
1025 """
1026
1026
1027 error_code = 0
1027 error_code = 0
1028
1028
1029 nChan = spc.shape[0]
1029 nChan = spc.shape[0]
1030 nProf = spc.shape[1]
1030 nProf = spc.shape[1]
1031 nPair = cspc.shape[0]
1031 nPair = cspc.shape[0]
1032
1032
1033 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1033 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1034 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1034 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1035 phase = numpy.zeros([nPair, nProf]) # phase between channels
1035 phase = numpy.zeros([nPair, nProf]) # phase between channels
1036 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1036 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1037 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1037 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1038 xFrec = AbbsisaRange[0][:-1] # frequency range
1038 xFrec = AbbsisaRange[0][:-1] # frequency range
1039 xVel = AbbsisaRange[2][:-1] # velocity range
1039 xVel = AbbsisaRange[2][:-1] # velocity range
1040 xSamples = xFrec # the frequency range is taken
1040 xSamples = xFrec # the frequency range is taken
1041 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1041 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1042
1042
1043 # only consider velocities with in NegativeLimit and PositiveLimit
1043 # only consider velocities with in NegativeLimit and PositiveLimit
1044 if (NegativeLimit is None):
1044 if (NegativeLimit is None):
1045 NegativeLimit = numpy.min(xVel)
1045 NegativeLimit = numpy.min(xVel)
1046 if (PositiveLimit is None):
1046 if (PositiveLimit is None):
1047 PositiveLimit = numpy.max(xVel)
1047 PositiveLimit = numpy.max(xVel)
1048 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1048 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1049 xSamples_zoom = xSamples[xvalid]
1049 xSamples_zoom = xSamples[xvalid]
1050
1050
1051 '''Getting Eij and Nij'''
1051 '''Getting Eij and Nij'''
1052 Xi01, Xi02, Xi12 = ChanDist[:,0]
1052 Xi01, Xi02, Xi12 = ChanDist[:,0]
1053 Eta01, Eta02, Eta12 = ChanDist[:,1]
1053 Eta01, Eta02, Eta12 = ChanDist[:,1]
1054
1054
1055 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1055 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1056 widthlimit = 10
1056 widthlimit = 10
1057 '''************************* SPC is normalized ********************************'''
1057 '''************************* SPC is normalized ********************************'''
1058 spc_norm = spc.copy()
1058 spc_norm = spc.copy()
1059 # For each channel
1059 # For each channel
1060 for i in range(nChan):
1060 for i in range(nChan):
1061 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1061 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1062 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1062 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1063
1063
1064 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1064 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1065
1065
1066 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1066 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1067 you only fit the curve and don't need the absolute value of height for calculation,
1067 you only fit the curve and don't need the absolute value of height for calculation,
1068 only for estimation of width. for normalization of cross spectra, you need initial,
1068 only for estimation of width. for normalization of cross spectra, you need initial,
1069 unnormalized self-spectra With noise.
1069 unnormalized self-spectra With noise.
1070
1070
1071 Technically, you don't even need to normalize the self-spectra, as you only need the
1071 Technically, you don't even need to normalize the self-spectra, as you only need the
1072 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1072 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1073 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1073 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1074 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1074 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1075 """
1075 """
1076 # initial conditions
1076 # initial conditions
1077 popt = [1e-10,0,1e-10]
1077 popt = [1e-10,0,1e-10]
1078 # Spectra average
1078 # Spectra average
1079 SPCMean = numpy.average(SPC_Samples,0)
1079 SPCMean = numpy.average(SPC_Samples,0)
1080 # Moments in frequency
1080 # Moments in frequency
1081 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1081 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1082
1082
1083 # Gauss Fit SPC in frequency domain
1083 # Gauss Fit SPC in frequency domain
1084 if dbSNR > SNRlimit: # only if SNR > SNRth
1084 if dbSNR > SNRlimit: # only if SNR > SNRth
1085 try:
1085 try:
1086 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1086 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1087 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1087 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1088 return self.StopWindEstimation(error_code = 1)
1088 return self.StopWindEstimation(error_code = 1)
1089 FitGauss = self.gaus(xSamples_zoom,*popt)
1089 FitGauss = self.gaus(xSamples_zoom,*popt)
1090 except :#RuntimeError:
1090 except :#RuntimeError:
1091 return self.StopWindEstimation(error_code = 2)
1091 return self.StopWindEstimation(error_code = 2)
1092 else:
1092 else:
1093 return self.StopWindEstimation(error_code = 3)
1093 return self.StopWindEstimation(error_code = 3)
1094
1094
1095 '''***************************** CSPC Normalization *************************
1095 '''***************************** CSPC Normalization *************************
1096 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1096 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1097 influence the norm which is not desired. First, a range is identified where the
1097 influence the norm which is not desired. First, a range is identified where the
1098 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1098 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1099 around it gets cut off and values replaced by mean determined by the boundary
1099 around it gets cut off and values replaced by mean determined by the boundary
1100 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1100 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1101
1101
1102 The sums are then added and multiplied by range/datapoints, because you need
1102 The sums are then added and multiplied by range/datapoints, because you need
1103 an integral and not a sum for normalization.
1103 an integral and not a sum for normalization.
1104
1104
1105 A norm is found according to Briggs 92.
1105 A norm is found according to Briggs 92.
1106 '''
1106 '''
1107 # for each pair
1107 # for each pair
1108 for i in range(nPair):
1108 for i in range(nPair):
1109 cspc_norm = cspc[i,:].copy()
1109 cspc_norm = cspc[i,:].copy()
1110 chan_index0 = pairsList[i][0]
1110 chan_index0 = pairsList[i][0]
1111 chan_index1 = pairsList[i][1]
1111 chan_index1 = pairsList[i][1]
1112 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1112 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1113 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1113 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1114
1114
1115 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1115 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1116 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1116 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1117 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1117 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1118
1118
1119 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1119 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1120 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1120 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1121
1121
1122 '''*******************************FIT GAUSS CSPC************************************'''
1122 '''*******************************FIT GAUSS CSPC************************************'''
1123 try:
1123 try:
1124 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1124 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1125 if popt01[2] > widthlimit: # CONDITION
1125 if popt01[2] > widthlimit: # CONDITION
1126 return self.StopWindEstimation(error_code = 4)
1126 return self.StopWindEstimation(error_code = 4)
1127 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1127 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1128 if popt02[2] > widthlimit: # CONDITION
1128 if popt02[2] > widthlimit: # CONDITION
1129 return self.StopWindEstimation(error_code = 4)
1129 return self.StopWindEstimation(error_code = 4)
1130 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1130 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1131 if popt12[2] > widthlimit: # CONDITION
1131 if popt12[2] > widthlimit: # CONDITION
1132 return self.StopWindEstimation(error_code = 4)
1132 return self.StopWindEstimation(error_code = 4)
1133
1133
1134 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1134 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1135 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1135 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1136 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1136 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1137 except:
1137 except:
1138 return self.StopWindEstimation(error_code = 5)
1138 return self.StopWindEstimation(error_code = 5)
1139
1139
1140
1140
1141 '''************* Getting Fij ***************'''
1141 '''************* Getting Fij ***************'''
1142 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1142 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1143 GaussCenter = popt[1]
1143 GaussCenter = popt[1]
1144 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1144 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1145 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1145 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1146
1146
1147 # Point where e^-1 is located in the gaussian
1147 # Point where e^-1 is located in the gaussian
1148 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1148 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1149 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1149 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1150 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1150 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1151 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1151 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1152
1152
1153 '''********** Taking frequency ranges from mean SPCs **********'''
1153 '''********** Taking frequency ranges from mean SPCs **********'''
1154 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1154 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1155 Range = numpy.empty(2)
1155 Range = numpy.empty(2)
1156 Range[0] = GaussCenter - GauWidth
1156 Range[0] = GaussCenter - GauWidth
1157 Range[1] = GaussCenter + GauWidth
1157 Range[1] = GaussCenter + GauWidth
1158 # Point in x-axis where the bandwidth is located (min:max)
1158 # Point in x-axis where the bandwidth is located (min:max)
1159 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1159 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1160 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1160 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1161 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1161 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1162 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1162 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1163 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1163 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1164 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1164 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1165
1165
1166 '''************************** Getting Phase Slope ***************************'''
1166 '''************************** Getting Phase Slope ***************************'''
1167 for i in range(nPair):
1167 for i in range(nPair):
1168 if len(FrecRange) > 5:
1168 if len(FrecRange) > 5:
1169 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1169 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1170 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1170 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1171 if len(FrecRange) == len(PhaseRange):
1171 if len(FrecRange) == len(PhaseRange):
1172 try:
1172 try:
1173 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1173 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1174 PhaseSlope[i] = slope
1174 PhaseSlope[i] = slope
1175 PhaseInter[i] = intercept
1175 PhaseInter[i] = intercept
1176 except:
1176 except:
1177 return self.StopWindEstimation(error_code = 6)
1177 return self.StopWindEstimation(error_code = 6)
1178 else:
1178 else:
1179 return self.StopWindEstimation(error_code = 7)
1179 return self.StopWindEstimation(error_code = 7)
1180 else:
1180 else:
1181 return self.StopWindEstimation(error_code = 8)
1181 return self.StopWindEstimation(error_code = 8)
1182
1182
1183 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1183 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1184
1184
1185 '''Getting constant C'''
1185 '''Getting constant C'''
1186 cC=(Fij*numpy.pi)**2
1186 cC=(Fij*numpy.pi)**2
1187
1187
1188 '''****** Getting constants F and G ******'''
1188 '''****** Getting constants F and G ******'''
1189 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1189 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1190 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1190 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1191 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1191 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1192 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1192 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1193 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1193 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1194 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1194 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1195 MijResults = numpy.array([MijResult1, MijResult2])
1195 MijResults = numpy.array([MijResult1, MijResult2])
1196 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1196 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1197
1197
1198 '''****** Getting constants A, B and H ******'''
1198 '''****** Getting constants A, B and H ******'''
1199 W01 = numpy.nanmax( FitGauss01 )
1199 W01 = numpy.nanmax( FitGauss01 )
1200 W02 = numpy.nanmax( FitGauss02 )
1200 W02 = numpy.nanmax( FitGauss02 )
1201 W12 = numpy.nanmax( FitGauss12 )
1201 W12 = numpy.nanmax( FitGauss12 )
1202
1202
1203 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1203 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1204 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1204 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1205 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1205 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1206 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1206 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1207
1207
1208 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1208 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1209 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1209 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1210
1210
1211 VxVy = numpy.array([[cA,cH],[cH,cB]])
1211 VxVy = numpy.array([[cA,cH],[cH,cB]])
1212 VxVyResults = numpy.array([-cF,-cG])
1212 VxVyResults = numpy.array([-cF,-cG])
1213 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1213 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1214 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1214 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1215 error_code = 0
1215 error_code = 0
1216
1216
1217 return Vzon, Vmer, Vver, error_code
1217 return Vzon, Vmer, Vver, error_code
1218
1218
1219 class SpectralMoments(Operation):
1219 class SpectralMoments(Operation):
1220
1220
1221 '''
1221 '''
1222 Function SpectralMoments()
1222 Function SpectralMoments()
1223
1223
1224 Calculates moments (power, mean, standard deviation) and SNR of the signal
1224 Calculates moments (power, mean, standard deviation) and SNR of the signal
1225
1225
1226 Type of dataIn: Spectra
1226 Type of dataIn: Spectra
1227
1227
1228 Configuration Parameters:
1228 Configuration Parameters:
1229
1229
1230 dirCosx : Cosine director in X axis
1230 dirCosx : Cosine director in X axis
1231 dirCosy : Cosine director in Y axis
1231 dirCosy : Cosine director in Y axis
1232
1232
1233 elevation :
1233 elevation :
1234 azimuth :
1234 azimuth :
1235
1235
1236 Input:
1236 Input:
1237 channelList : simple channel list to select e.g. [2,3,7]
1237 channelList : simple channel list to select e.g. [2,3,7]
1238 self.dataOut.data_pre : Spectral data
1238 self.dataOut.data_pre : Spectral data
1239 self.dataOut.abscissaList : List of frequencies
1239 self.dataOut.abscissaList : List of frequencies
1240 self.dataOut.noise : Noise level per channel
1240 self.dataOut.noise : Noise level per channel
1241
1241
1242 Affected:
1242 Affected:
1243 self.dataOut.moments : Parameters per channel
1243 self.dataOut.moments : Parameters per channel
1244 self.dataOut.data_snr : SNR per channel
1244 self.dataOut.data_snr : SNR per channel
1245
1245
1246 '''
1246 '''
1247
1247
1248 def run(self, dataOut):
1248 def run(self, dataOut):
1249
1249
1250 data = dataOut.data_pre[0]
1250 data = dataOut.data_pre[0]
1251 absc = dataOut.abscissaList[:-1]
1251 absc = dataOut.abscissaList[:-1]
1252 noise = dataOut.noise
1252 noise = dataOut.noise
1253 nChannel = data.shape[0]
1253 nChannel = data.shape[0]
1254 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1254 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1255
1255
1256 for ind in range(nChannel):
1256 for ind in range(nChannel):
1257 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1257 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1258
1258
1259 dataOut.moments = data_param[:,1:,:]
1259 dataOut.moments = data_param[:,1:,:]
1260 dataOut.data_snr = data_param[:,0]
1260 dataOut.data_snr = data_param[:,0]
1261 dataOut.data_pow = data_param[:,1]
1261 dataOut.data_pow = data_param[:,1]
1262 dataOut.data_dop = data_param[:,2]
1262 dataOut.data_dop = data_param[:,2]
1263 dataOut.data_width = data_param[:,3]
1263 dataOut.data_width = data_param[:,3]
1264 return dataOut
1264 return dataOut
1265
1265
1266 def __calculateMoments(self, oldspec, oldfreq, n0,
1266 def __calculateMoments(self, oldspec, oldfreq, n0,
1267 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1267 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1268
1268
1269 if (nicoh is None): nicoh = 1
1269 if (nicoh is None): nicoh = 1
1270 if (graph is None): graph = 0
1270 if (graph is None): graph = 0
1271 if (smooth is None): smooth = 0
1271 if (smooth is None): smooth = 0
1272 elif (self.smooth < 3): smooth = 0
1272 elif (self.smooth < 3): smooth = 0
1273
1273
1274 if (type1 is None): type1 = 0
1274 if (type1 is None): type1 = 0
1275 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1275 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1276 if (snrth is None): snrth = -3
1276 if (snrth is None): snrth = -3
1277 if (dc is None): dc = 0
1277 if (dc is None): dc = 0
1278 if (aliasing is None): aliasing = 0
1278 if (aliasing is None): aliasing = 0
1279 if (oldfd is None): oldfd = 0
1279 if (oldfd is None): oldfd = 0
1280 if (wwauto is None): wwauto = 0
1280 if (wwauto is None): wwauto = 0
1281
1281
1282 if (n0 < 1.e-20): n0 = 1.e-20
1282 if (n0 < 1.e-20): n0 = 1.e-20
1283
1283
1284 freq = oldfreq
1284 freq = oldfreq
1285 vec_power = numpy.zeros(oldspec.shape[1])
1285 vec_power = numpy.zeros(oldspec.shape[1])
1286 vec_fd = numpy.zeros(oldspec.shape[1])
1286 vec_fd = numpy.zeros(oldspec.shape[1])
1287 vec_w = numpy.zeros(oldspec.shape[1])
1287 vec_w = numpy.zeros(oldspec.shape[1])
1288 vec_snr = numpy.zeros(oldspec.shape[1])
1288 vec_snr = numpy.zeros(oldspec.shape[1])
1289
1289
1290 # oldspec = numpy.ma.masked_invalid(oldspec)
1290 # oldspec = numpy.ma.masked_invalid(oldspec)
1291 for ind in range(oldspec.shape[1]):
1291 for ind in range(oldspec.shape[1]):
1292
1292
1293 spec = oldspec[:,ind]
1293 spec = oldspec[:,ind]
1294 aux = spec*fwindow
1294 aux = spec*fwindow
1295 max_spec = aux.max()
1295 max_spec = aux.max()
1296 m = aux.tolist().index(max_spec)
1296 m = aux.tolist().index(max_spec)
1297
1297
1298 # Smooth
1298 # Smooth
1299 if (smooth == 0):
1299 if (smooth == 0):
1300 spec2 = spec
1300 spec2 = spec
1301 else:
1301 else:
1302 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1302 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1303
1303
1304 # Moments Estimation
1304 # Moments Estimation
1305 bb = spec2[numpy.arange(m,spec2.size)]
1305 bb = spec2[numpy.arange(m,spec2.size)]
1306 bb = (bb<n0).nonzero()
1306 bb = (bb<n0).nonzero()
1307 bb = bb[0]
1307 bb = bb[0]
1308
1308
1309 ss = spec2[numpy.arange(0,m + 1)]
1309 ss = spec2[numpy.arange(0,m + 1)]
1310 ss = (ss<n0).nonzero()
1310 ss = (ss<n0).nonzero()
1311 ss = ss[0]
1311 ss = ss[0]
1312
1312
1313 if (bb.size == 0):
1313 if (bb.size == 0):
1314 bb0 = spec.size - 1 - m
1314 bb0 = spec.size - 1 - m
1315 else:
1315 else:
1316 bb0 = bb[0] - 1
1316 bb0 = bb[0] - 1
1317 if (bb0 < 0):
1317 if (bb0 < 0):
1318 bb0 = 0
1318 bb0 = 0
1319
1319
1320 if (ss.size == 0):
1320 if (ss.size == 0):
1321 ss1 = 1
1321 ss1 = 1
1322 else:
1322 else:
1323 ss1 = max(ss) + 1
1323 ss1 = max(ss) + 1
1324
1324
1325 if (ss1 > m):
1325 if (ss1 > m):
1326 ss1 = m
1326 ss1 = m
1327
1327
1328 #valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1328 #valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1329 valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1329 valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1330 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1330 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1331 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1331 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1332 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1332 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1333 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1333 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1334 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1334 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1335 snr = (spec2.mean()-n0)/n0
1335 snr = (spec2.mean()-n0)/n0
1336 if (snr < 1.e-20) :
1336 if (snr < 1.e-20) :
1337 snr = 1.e-20
1337 snr = 1.e-20
1338
1338
1339 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1339 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1340 vec_power[ind] = total_power
1340 vec_power[ind] = total_power
1341 vec_fd[ind] = fd
1341 vec_fd[ind] = fd
1342 vec_w[ind] = w
1342 vec_w[ind] = w
1343 vec_snr[ind] = snr
1343 vec_snr[ind] = snr
1344
1344
1345 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1345 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1346
1346
1347 #------------------ Get SA Parameters --------------------------
1347 #------------------ Get SA Parameters --------------------------
1348
1348
1349 def GetSAParameters(self):
1349 def GetSAParameters(self):
1350 #SA en frecuencia
1350 #SA en frecuencia
1351 pairslist = self.dataOut.groupList
1351 pairslist = self.dataOut.groupList
1352 num_pairs = len(pairslist)
1352 num_pairs = len(pairslist)
1353
1353
1354 vel = self.dataOut.abscissaList
1354 vel = self.dataOut.abscissaList
1355 spectra = self.dataOut.data_pre
1355 spectra = self.dataOut.data_pre
1356 cspectra = self.dataIn.data_cspc
1356 cspectra = self.dataIn.data_cspc
1357 delta_v = vel[1] - vel[0]
1357 delta_v = vel[1] - vel[0]
1358
1358
1359 #Calculating the power spectrum
1359 #Calculating the power spectrum
1360 spc_pow = numpy.sum(spectra, 3)*delta_v
1360 spc_pow = numpy.sum(spectra, 3)*delta_v
1361 #Normalizing Spectra
1361 #Normalizing Spectra
1362 norm_spectra = spectra/spc_pow
1362 norm_spectra = spectra/spc_pow
1363 #Calculating the norm_spectra at peak
1363 #Calculating the norm_spectra at peak
1364 max_spectra = numpy.max(norm_spectra, 3)
1364 max_spectra = numpy.max(norm_spectra, 3)
1365
1365
1366 #Normalizing Cross Spectra
1366 #Normalizing Cross Spectra
1367 norm_cspectra = numpy.zeros(cspectra.shape)
1367 norm_cspectra = numpy.zeros(cspectra.shape)
1368
1368
1369 for i in range(num_chan):
1369 for i in range(num_chan):
1370 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1370 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1371
1371
1372 max_cspectra = numpy.max(norm_cspectra,2)
1372 max_cspectra = numpy.max(norm_cspectra,2)
1373 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1373 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1374
1374
1375 for i in range(num_pairs):
1375 for i in range(num_pairs):
1376 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1376 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1377 #------------------- Get Lags ----------------------------------
1377 #------------------- Get Lags ----------------------------------
1378
1378
1379 class SALags(Operation):
1379 class SALags(Operation):
1380 '''
1380 '''
1381 Function GetMoments()
1381 Function GetMoments()
1382
1382
1383 Input:
1383 Input:
1384 self.dataOut.data_pre
1384 self.dataOut.data_pre
1385 self.dataOut.abscissaList
1385 self.dataOut.abscissaList
1386 self.dataOut.noise
1386 self.dataOut.noise
1387 self.dataOut.normFactor
1387 self.dataOut.normFactor
1388 self.dataOut.data_snr
1388 self.dataOut.data_snr
1389 self.dataOut.groupList
1389 self.dataOut.groupList
1390 self.dataOut.nChannels
1390 self.dataOut.nChannels
1391
1391
1392 Affected:
1392 Affected:
1393 self.dataOut.data_param
1393 self.dataOut.data_param
1394
1394
1395 '''
1395 '''
1396 def run(self, dataOut):
1396 def run(self, dataOut):
1397 data_acf = dataOut.data_pre[0]
1397 data_acf = dataOut.data_pre[0]
1398 data_ccf = dataOut.data_pre[1]
1398 data_ccf = dataOut.data_pre[1]
1399 normFactor_acf = dataOut.normFactor[0]
1399 normFactor_acf = dataOut.normFactor[0]
1400 normFactor_ccf = dataOut.normFactor[1]
1400 normFactor_ccf = dataOut.normFactor[1]
1401 pairs_acf = dataOut.groupList[0]
1401 pairs_acf = dataOut.groupList[0]
1402 pairs_ccf = dataOut.groupList[1]
1402 pairs_ccf = dataOut.groupList[1]
1403
1403
1404 nHeights = dataOut.nHeights
1404 nHeights = dataOut.nHeights
1405 absc = dataOut.abscissaList
1405 absc = dataOut.abscissaList
1406 noise = dataOut.noise
1406 noise = dataOut.noise
1407 SNR = dataOut.data_snr
1407 SNR = dataOut.data_snr
1408 nChannels = dataOut.nChannels
1408 nChannels = dataOut.nChannels
1409 # pairsList = dataOut.groupList
1409 # pairsList = dataOut.groupList
1410 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1410 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1411
1411
1412 for l in range(len(pairs_acf)):
1412 for l in range(len(pairs_acf)):
1413 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1413 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1414
1414
1415 for l in range(len(pairs_ccf)):
1415 for l in range(len(pairs_ccf)):
1416 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1416 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1417
1417
1418 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1418 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1419 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1419 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1420 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1420 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1421 return
1421 return
1422
1422
1423 # def __getPairsAutoCorr(self, pairsList, nChannels):
1423 # def __getPairsAutoCorr(self, pairsList, nChannels):
1424 #
1424 #
1425 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1425 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1426 #
1426 #
1427 # for l in range(len(pairsList)):
1427 # for l in range(len(pairsList)):
1428 # firstChannel = pairsList[l][0]
1428 # firstChannel = pairsList[l][0]
1429 # secondChannel = pairsList[l][1]
1429 # secondChannel = pairsList[l][1]
1430 #
1430 #
1431 # #Obteniendo pares de Autocorrelacion
1431 # #Obteniendo pares de Autocorrelacion
1432 # if firstChannel == secondChannel:
1432 # if firstChannel == secondChannel:
1433 # pairsAutoCorr[firstChannel] = int(l)
1433 # pairsAutoCorr[firstChannel] = int(l)
1434 #
1434 #
1435 # pairsAutoCorr = pairsAutoCorr.astype(int)
1435 # pairsAutoCorr = pairsAutoCorr.astype(int)
1436 #
1436 #
1437 # pairsCrossCorr = range(len(pairsList))
1437 # pairsCrossCorr = range(len(pairsList))
1438 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1438 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1439 #
1439 #
1440 # return pairsAutoCorr, pairsCrossCorr
1440 # return pairsAutoCorr, pairsCrossCorr
1441
1441
1442 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1442 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1443
1443
1444 lag0 = data_acf.shape[1]/2
1444 lag0 = data_acf.shape[1]/2
1445 #Funcion de Autocorrelacion
1445 #Funcion de Autocorrelacion
1446 mean_acf = stats.nanmean(data_acf, axis = 0)
1446 mean_acf = stats.nanmean(data_acf, axis = 0)
1447
1447
1448 #Obtencion Indice de TauCross
1448 #Obtencion Indice de TauCross
1449 ind_ccf = data_ccf.argmax(axis = 1)
1449 ind_ccf = data_ccf.argmax(axis = 1)
1450 #Obtencion Indice de TauAuto
1450 #Obtencion Indice de TauAuto
1451 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1451 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1452 ccf_lag0 = data_ccf[:,lag0,:]
1452 ccf_lag0 = data_ccf[:,lag0,:]
1453
1453
1454 for i in range(ccf_lag0.shape[0]):
1454 for i in range(ccf_lag0.shape[0]):
1455 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1455 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1456
1456
1457 #Obtencion de TauCross y TauAuto
1457 #Obtencion de TauCross y TauAuto
1458 tau_ccf = lagRange[ind_ccf]
1458 tau_ccf = lagRange[ind_ccf]
1459 tau_acf = lagRange[ind_acf]
1459 tau_acf = lagRange[ind_acf]
1460
1460
1461 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1461 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1462
1462
1463 tau_ccf[Nan1,Nan2] = numpy.nan
1463 tau_ccf[Nan1,Nan2] = numpy.nan
1464 tau_acf[Nan1,Nan2] = numpy.nan
1464 tau_acf[Nan1,Nan2] = numpy.nan
1465 tau = numpy.vstack((tau_ccf,tau_acf))
1465 tau = numpy.vstack((tau_ccf,tau_acf))
1466
1466
1467 return tau
1467 return tau
1468
1468
1469 def __calculateLag1Phase(self, data, lagTRange):
1469 def __calculateLag1Phase(self, data, lagTRange):
1470 data1 = stats.nanmean(data, axis = 0)
1470 data1 = stats.nanmean(data, axis = 0)
1471 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1471 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1472
1472
1473 phase = numpy.angle(data1[lag1,:])
1473 phase = numpy.angle(data1[lag1,:])
1474
1474
1475 return phase
1475 return phase
1476
1476
1477 class SpectralFitting(Operation):
1477 class SpectralFitting(Operation):
1478 '''
1478 '''
1479 Function GetMoments()
1479 Function GetMoments()
1480
1480
1481 Input:
1481 Input:
1482 Output:
1482 Output:
1483 Variables modified:
1483 Variables modified:
1484 '''
1484 '''
1485
1485
1486 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1486 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1487
1487
1488
1488
1489 if path != None:
1489 if path != None:
1490 sys.path.append(path)
1490 sys.path.append(path)
1491 self.dataOut.library = importlib.import_module(file)
1491 self.dataOut.library = importlib.import_module(file)
1492
1492
1493 #To be inserted as a parameter
1493 #To be inserted as a parameter
1494 groupArray = numpy.array(groupList)
1494 groupArray = numpy.array(groupList)
1495 # groupArray = numpy.array([[0,1],[2,3]])
1495 # groupArray = numpy.array([[0,1],[2,3]])
1496 self.dataOut.groupList = groupArray
1496 self.dataOut.groupList = groupArray
1497
1497
1498 nGroups = groupArray.shape[0]
1498 nGroups = groupArray.shape[0]
1499 nChannels = self.dataIn.nChannels
1499 nChannels = self.dataIn.nChannels
1500 nHeights=self.dataIn.heightList.size
1500 nHeights=self.dataIn.heightList.size
1501
1501
1502 #Parameters Array
1502 #Parameters Array
1503 self.dataOut.data_param = None
1503 self.dataOut.data_param = None
1504
1504
1505 #Set constants
1505 #Set constants
1506 constants = self.dataOut.library.setConstants(self.dataIn)
1506 constants = self.dataOut.library.setConstants(self.dataIn)
1507 self.dataOut.constants = constants
1507 self.dataOut.constants = constants
1508 M = self.dataIn.normFactor
1508 M = self.dataIn.normFactor
1509 N = self.dataIn.nFFTPoints
1509 N = self.dataIn.nFFTPoints
1510 ippSeconds = self.dataIn.ippSeconds
1510 ippSeconds = self.dataIn.ippSeconds
1511 K = self.dataIn.nIncohInt
1511 K = self.dataIn.nIncohInt
1512 pairsArray = numpy.array(self.dataIn.pairsList)
1512 pairsArray = numpy.array(self.dataIn.pairsList)
1513
1513
1514 #List of possible combinations
1514 #List of possible combinations
1515 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1515 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1516 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1516 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1517
1517
1518 if getSNR:
1518 if getSNR:
1519 listChannels = groupArray.reshape((groupArray.size))
1519 listChannels = groupArray.reshape((groupArray.size))
1520 listChannels.sort()
1520 listChannels.sort()
1521 noise = self.dataIn.getNoise()
1521 noise = self.dataIn.getNoise()
1522 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1522 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1523
1523
1524 for i in range(nGroups):
1524 for i in range(nGroups):
1525 coord = groupArray[i,:]
1525 coord = groupArray[i,:]
1526
1526
1527 #Input data array
1527 #Input data array
1528 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1528 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1529 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1529 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1530
1530
1531 #Cross Spectra data array for Covariance Matrixes
1531 #Cross Spectra data array for Covariance Matrixes
1532 ind = 0
1532 ind = 0
1533 for pairs in listComb:
1533 for pairs in listComb:
1534 pairsSel = numpy.array([coord[x],coord[y]])
1534 pairsSel = numpy.array([coord[x],coord[y]])
1535 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1535 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1536 ind += 1
1536 ind += 1
1537 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1537 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1538 dataCross = dataCross**2/K
1538 dataCross = dataCross**2/K
1539
1539
1540 for h in range(nHeights):
1540 for h in range(nHeights):
1541
1541
1542 #Input
1542 #Input
1543 d = data[:,h]
1543 d = data[:,h]
1544
1544
1545 #Covariance Matrix
1545 #Covariance Matrix
1546 D = numpy.diag(d**2/K)
1546 D = numpy.diag(d**2/K)
1547 ind = 0
1547 ind = 0
1548 for pairs in listComb:
1548 for pairs in listComb:
1549 #Coordinates in Covariance Matrix
1549 #Coordinates in Covariance Matrix
1550 x = pairs[0]
1550 x = pairs[0]
1551 y = pairs[1]
1551 y = pairs[1]
1552 #Channel Index
1552 #Channel Index
1553 S12 = dataCross[ind,:,h]
1553 S12 = dataCross[ind,:,h]
1554 D12 = numpy.diag(S12)
1554 D12 = numpy.diag(S12)
1555 #Completing Covariance Matrix with Cross Spectras
1555 #Completing Covariance Matrix with Cross Spectras
1556 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1556 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1557 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1557 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1558 ind += 1
1558 ind += 1
1559 Dinv=numpy.linalg.inv(D)
1559 Dinv=numpy.linalg.inv(D)
1560 L=numpy.linalg.cholesky(Dinv)
1560 L=numpy.linalg.cholesky(Dinv)
1561 LT=L.T
1561 LT=L.T
1562
1562
1563 dp = numpy.dot(LT,d)
1563 dp = numpy.dot(LT,d)
1564
1564
1565 #Initial values
1565 #Initial values
1566 data_spc = self.dataIn.data_spc[coord,:,h]
1566 data_spc = self.dataIn.data_spc[coord,:,h]
1567
1567
1568 if (h>0)and(error1[3]<5):
1568 if (h>0)and(error1[3]<5):
1569 p0 = self.dataOut.data_param[i,:,h-1]
1569 p0 = self.dataOut.data_param[i,:,h-1]
1570 else:
1570 else:
1571 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1571 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1572
1572
1573 try:
1573 try:
1574 #Least Squares
1574 #Least Squares
1575 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1575 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1576 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1576 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1577 #Chi square error
1577 #Chi square error
1578 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1578 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1579 #Error with Jacobian
1579 #Error with Jacobian
1580 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1580 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1581 except:
1581 except:
1582 minp = p0*numpy.nan
1582 minp = p0*numpy.nan
1583 error0 = numpy.nan
1583 error0 = numpy.nan
1584 error1 = p0*numpy.nan
1584 error1 = p0*numpy.nan
1585
1585
1586 #Save
1586 #Save
1587 if self.dataOut.data_param is None:
1587 if self.dataOut.data_param is None:
1588 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1588 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1589 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1589 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1590
1590
1591 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1591 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1592 self.dataOut.data_param[i,:,h] = minp
1592 self.dataOut.data_param[i,:,h] = minp
1593 return
1593 return
1594
1594
1595 def __residFunction(self, p, dp, LT, constants):
1595 def __residFunction(self, p, dp, LT, constants):
1596
1596
1597 fm = self.dataOut.library.modelFunction(p, constants)
1597 fm = self.dataOut.library.modelFunction(p, constants)
1598 fmp=numpy.dot(LT,fm)
1598 fmp=numpy.dot(LT,fm)
1599
1599
1600 return dp-fmp
1600 return dp-fmp
1601
1601
1602 def __getSNR(self, z, noise):
1602 def __getSNR(self, z, noise):
1603
1603
1604 avg = numpy.average(z, axis=1)
1604 avg = numpy.average(z, axis=1)
1605 SNR = (avg.T-noise)/noise
1605 SNR = (avg.T-noise)/noise
1606 SNR = SNR.T
1606 SNR = SNR.T
1607 return SNR
1607 return SNR
1608
1608
1609 def __chisq(p,chindex,hindex):
1609 def __chisq(p,chindex,hindex):
1610 #similar to Resid but calculates CHI**2
1610 #similar to Resid but calculates CHI**2
1611 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1611 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1612 dp=numpy.dot(LT,d)
1612 dp=numpy.dot(LT,d)
1613 fmp=numpy.dot(LT,fm)
1613 fmp=numpy.dot(LT,fm)
1614 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1614 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1615 return chisq
1615 return chisq
1616
1616
1617 class WindProfiler(Operation):
1617 class WindProfiler(Operation):
1618
1618
1619 __isConfig = False
1619 __isConfig = False
1620
1620
1621 __initime = None
1621 __initime = None
1622 __lastdatatime = None
1622 __lastdatatime = None
1623 __integrationtime = None
1623 __integrationtime = None
1624
1624
1625 __buffer = None
1625 __buffer = None
1626
1626
1627 __dataReady = False
1627 __dataReady = False
1628
1628
1629 __firstdata = None
1629 __firstdata = None
1630
1630
1631 n = None
1631 n = None
1632
1632
1633 def __init__(self):
1633 def __init__(self):
1634 Operation.__init__(self)
1634 Operation.__init__(self)
1635
1635
1636 def __calculateCosDir(self, elev, azim):
1636 def __calculateCosDir(self, elev, azim):
1637 zen = (90 - elev)*numpy.pi/180
1637 zen = (90 - elev)*numpy.pi/180
1638 azim = azim*numpy.pi/180
1638 azim = azim*numpy.pi/180
1639 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1639 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1640 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1640 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1641
1641
1642 signX = numpy.sign(numpy.cos(azim))
1642 signX = numpy.sign(numpy.cos(azim))
1643 signY = numpy.sign(numpy.sin(azim))
1643 signY = numpy.sign(numpy.sin(azim))
1644
1644
1645 cosDirX = numpy.copysign(cosDirX, signX)
1645 cosDirX = numpy.copysign(cosDirX, signX)
1646 cosDirY = numpy.copysign(cosDirY, signY)
1646 cosDirY = numpy.copysign(cosDirY, signY)
1647 return cosDirX, cosDirY
1647 return cosDirX, cosDirY
1648
1648
1649 def __calculateAngles(self, theta_x, theta_y, azimuth):
1649 def __calculateAngles(self, theta_x, theta_y, azimuth):
1650
1650
1651 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1651 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1652 zenith_arr = numpy.arccos(dir_cosw)
1652 zenith_arr = numpy.arccos(dir_cosw)
1653 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1653 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1654
1654
1655 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1655 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1656 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1656 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1657
1657
1658 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1658 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1659
1659
1660 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1660 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1661
1661
1662 #
1662 #
1663 if horOnly:
1663 if horOnly:
1664 A = numpy.c_[dir_cosu,dir_cosv]
1664 A = numpy.c_[dir_cosu,dir_cosv]
1665 else:
1665 else:
1666 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1666 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1667 A = numpy.asmatrix(A)
1667 A = numpy.asmatrix(A)
1668 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1668 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1669
1669
1670 return A1
1670 return A1
1671
1671
1672 def __correctValues(self, heiRang, phi, velRadial, SNR):
1672 def __correctValues(self, heiRang, phi, velRadial, SNR):
1673 listPhi = phi.tolist()
1673 listPhi = phi.tolist()
1674 maxid = listPhi.index(max(listPhi))
1674 maxid = listPhi.index(max(listPhi))
1675 minid = listPhi.index(min(listPhi))
1675 minid = listPhi.index(min(listPhi))
1676
1676
1677 rango = list(range(len(phi)))
1677 rango = list(range(len(phi)))
1678 # rango = numpy.delete(rango,maxid)
1678 # rango = numpy.delete(rango,maxid)
1679
1679
1680 heiRang1 = heiRang*math.cos(phi[maxid])
1680 heiRang1 = heiRang*math.cos(phi[maxid])
1681 heiRangAux = heiRang*math.cos(phi[minid])
1681 heiRangAux = heiRang*math.cos(phi[minid])
1682 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1682 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1683 heiRang1 = numpy.delete(heiRang1,indOut)
1683 heiRang1 = numpy.delete(heiRang1,indOut)
1684
1684
1685 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1685 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1686 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1686 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1687
1687
1688 for i in rango:
1688 for i in rango:
1689 x = heiRang*math.cos(phi[i])
1689 x = heiRang*math.cos(phi[i])
1690 y1 = velRadial[i,:]
1690 y1 = velRadial[i,:]
1691 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1691 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1692
1692
1693 x1 = heiRang1
1693 x1 = heiRang1
1694 y11 = f1(x1)
1694 y11 = f1(x1)
1695
1695
1696 y2 = SNR[i,:]
1696 y2 = SNR[i,:]
1697 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1697 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1698 y21 = f2(x1)
1698 y21 = f2(x1)
1699
1699
1700 velRadial1[i,:] = y11
1700 velRadial1[i,:] = y11
1701 SNR1[i,:] = y21
1701 SNR1[i,:] = y21
1702
1702
1703 return heiRang1, velRadial1, SNR1
1703 return heiRang1, velRadial1, SNR1
1704
1704
1705 def __calculateVelUVW(self, A, velRadial):
1705 def __calculateVelUVW(self, A, velRadial):
1706
1706
1707 #Operacion Matricial
1707 #Operacion Matricial
1708 # velUVW = numpy.zeros((velRadial.shape[1],3))
1708 # velUVW = numpy.zeros((velRadial.shape[1],3))
1709 # for ind in range(velRadial.shape[1]):
1709 # for ind in range(velRadial.shape[1]):
1710 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1710 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1711 # velUVW = velUVW.transpose()
1711 # velUVW = velUVW.transpose()
1712 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1712 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1713 velUVW[:,:] = numpy.dot(A,velRadial)
1713 velUVW[:,:] = numpy.dot(A,velRadial)
1714
1714
1715
1715
1716 return velUVW
1716 return velUVW
1717
1717
1718 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1718 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1719
1719
1720 def techniqueDBS(self, kwargs):
1720 def techniqueDBS(self, kwargs):
1721 """
1721 """
1722 Function that implements Doppler Beam Swinging (DBS) technique.
1722 Function that implements Doppler Beam Swinging (DBS) technique.
1723
1723
1724 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1724 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1725 Direction correction (if necessary), Ranges and SNR
1725 Direction correction (if necessary), Ranges and SNR
1726
1726
1727 Output: Winds estimation (Zonal, Meridional and Vertical)
1727 Output: Winds estimation (Zonal, Meridional and Vertical)
1728
1728
1729 Parameters affected: Winds, height range, SNR
1729 Parameters affected: Winds, height range, SNR
1730 """
1730 """
1731 velRadial0 = kwargs['velRadial']
1731 velRadial0 = kwargs['velRadial']
1732 heiRang = kwargs['heightList']
1732 heiRang = kwargs['heightList']
1733 SNR0 = kwargs['SNR']
1733 SNR0 = kwargs['SNR']
1734
1734
1735 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1735 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1736 theta_x = numpy.array(kwargs['dirCosx'])
1736 theta_x = numpy.array(kwargs['dirCosx'])
1737 theta_y = numpy.array(kwargs['dirCosy'])
1737 theta_y = numpy.array(kwargs['dirCosy'])
1738 else:
1738 else:
1739 elev = numpy.array(kwargs['elevation'])
1739 elev = numpy.array(kwargs['elevation'])
1740 azim = numpy.array(kwargs['azimuth'])
1740 azim = numpy.array(kwargs['azimuth'])
1741 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1741 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1742 azimuth = kwargs['correctAzimuth']
1742 azimuth = kwargs['correctAzimuth']
1743 if 'horizontalOnly' in kwargs:
1743 if 'horizontalOnly' in kwargs:
1744 horizontalOnly = kwargs['horizontalOnly']
1744 horizontalOnly = kwargs['horizontalOnly']
1745 else: horizontalOnly = False
1745 else: horizontalOnly = False
1746 if 'correctFactor' in kwargs:
1746 if 'correctFactor' in kwargs:
1747 correctFactor = kwargs['correctFactor']
1747 correctFactor = kwargs['correctFactor']
1748 else: correctFactor = 1
1748 else: correctFactor = 1
1749 if 'channelList' in kwargs:
1749 if 'channelList' in kwargs:
1750 channelList = kwargs['channelList']
1750 channelList = kwargs['channelList']
1751 if len(channelList) == 2:
1751 if len(channelList) == 2:
1752 horizontalOnly = True
1752 horizontalOnly = True
1753 arrayChannel = numpy.array(channelList)
1753 arrayChannel = numpy.array(channelList)
1754 param = param[arrayChannel,:,:]
1754 param = param[arrayChannel,:,:]
1755 theta_x = theta_x[arrayChannel]
1755 theta_x = theta_x[arrayChannel]
1756 theta_y = theta_y[arrayChannel]
1756 theta_y = theta_y[arrayChannel]
1757
1757
1758 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1758 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1759 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1759 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1760 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1760 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1761
1761
1762 #Calculo de Componentes de la velocidad con DBS
1762 #Calculo de Componentes de la velocidad con DBS
1763 winds = self.__calculateVelUVW(A,velRadial1)
1763 winds = self.__calculateVelUVW(A,velRadial1)
1764
1764
1765 return winds, heiRang1, SNR1
1765 return winds, heiRang1, SNR1
1766
1766
1767 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1767 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1768
1768
1769 nPairs = len(pairs_ccf)
1769 nPairs = len(pairs_ccf)
1770 posx = numpy.asarray(posx)
1770 posx = numpy.asarray(posx)
1771 posy = numpy.asarray(posy)
1771 posy = numpy.asarray(posy)
1772
1772
1773 #Rotacion Inversa para alinear con el azimuth
1773 #Rotacion Inversa para alinear con el azimuth
1774 if azimuth!= None:
1774 if azimuth!= None:
1775 azimuth = azimuth*math.pi/180
1775 azimuth = azimuth*math.pi/180
1776 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1776 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1777 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1777 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1778 else:
1778 else:
1779 posx1 = posx
1779 posx1 = posx
1780 posy1 = posy
1780 posy1 = posy
1781
1781
1782 #Calculo de Distancias
1782 #Calculo de Distancias
1783 distx = numpy.zeros(nPairs)
1783 distx = numpy.zeros(nPairs)
1784 disty = numpy.zeros(nPairs)
1784 disty = numpy.zeros(nPairs)
1785 dist = numpy.zeros(nPairs)
1785 dist = numpy.zeros(nPairs)
1786 ang = numpy.zeros(nPairs)
1786 ang = numpy.zeros(nPairs)
1787
1787
1788 for i in range(nPairs):
1788 for i in range(nPairs):
1789 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1789 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1790 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1790 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1791 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1791 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1792 ang[i] = numpy.arctan2(disty[i],distx[i])
1792 ang[i] = numpy.arctan2(disty[i],distx[i])
1793
1793
1794 return distx, disty, dist, ang
1794 return distx, disty, dist, ang
1795 #Calculo de Matrices
1795 #Calculo de Matrices
1796 # nPairs = len(pairs)
1796 # nPairs = len(pairs)
1797 # ang1 = numpy.zeros((nPairs, 2, 1))
1797 # ang1 = numpy.zeros((nPairs, 2, 1))
1798 # dist1 = numpy.zeros((nPairs, 2, 1))
1798 # dist1 = numpy.zeros((nPairs, 2, 1))
1799 #
1799 #
1800 # for j in range(nPairs):
1800 # for j in range(nPairs):
1801 # dist1[j,0,0] = dist[pairs[j][0]]
1801 # dist1[j,0,0] = dist[pairs[j][0]]
1802 # dist1[j,1,0] = dist[pairs[j][1]]
1802 # dist1[j,1,0] = dist[pairs[j][1]]
1803 # ang1[j,0,0] = ang[pairs[j][0]]
1803 # ang1[j,0,0] = ang[pairs[j][0]]
1804 # ang1[j,1,0] = ang[pairs[j][1]]
1804 # ang1[j,1,0] = ang[pairs[j][1]]
1805 #
1805 #
1806 # return distx,disty, dist1,ang1
1806 # return distx,disty, dist1,ang1
1807
1807
1808
1808
1809 def __calculateVelVer(self, phase, lagTRange, _lambda):
1809 def __calculateVelVer(self, phase, lagTRange, _lambda):
1810
1810
1811 Ts = lagTRange[1] - lagTRange[0]
1811 Ts = lagTRange[1] - lagTRange[0]
1812 velW = -_lambda*phase/(4*math.pi*Ts)
1812 velW = -_lambda*phase/(4*math.pi*Ts)
1813
1813
1814 return velW
1814 return velW
1815
1815
1816 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1816 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1817 nPairs = tau1.shape[0]
1817 nPairs = tau1.shape[0]
1818 nHeights = tau1.shape[1]
1818 nHeights = tau1.shape[1]
1819 vel = numpy.zeros((nPairs,3,nHeights))
1819 vel = numpy.zeros((nPairs,3,nHeights))
1820 dist1 = numpy.reshape(dist, (dist.size,1))
1820 dist1 = numpy.reshape(dist, (dist.size,1))
1821
1821
1822 angCos = numpy.cos(ang)
1822 angCos = numpy.cos(ang)
1823 angSin = numpy.sin(ang)
1823 angSin = numpy.sin(ang)
1824
1824
1825 vel0 = dist1*tau1/(2*tau2**2)
1825 vel0 = dist1*tau1/(2*tau2**2)
1826 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1826 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1827 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1827 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1828
1828
1829 ind = numpy.where(numpy.isinf(vel))
1829 ind = numpy.where(numpy.isinf(vel))
1830 vel[ind] = numpy.nan
1830 vel[ind] = numpy.nan
1831
1831
1832 return vel
1832 return vel
1833
1833
1834 # def __getPairsAutoCorr(self, pairsList, nChannels):
1834 # def __getPairsAutoCorr(self, pairsList, nChannels):
1835 #
1835 #
1836 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1836 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1837 #
1837 #
1838 # for l in range(len(pairsList)):
1838 # for l in range(len(pairsList)):
1839 # firstChannel = pairsList[l][0]
1839 # firstChannel = pairsList[l][0]
1840 # secondChannel = pairsList[l][1]
1840 # secondChannel = pairsList[l][1]
1841 #
1841 #
1842 # #Obteniendo pares de Autocorrelacion
1842 # #Obteniendo pares de Autocorrelacion
1843 # if firstChannel == secondChannel:
1843 # if firstChannel == secondChannel:
1844 # pairsAutoCorr[firstChannel] = int(l)
1844 # pairsAutoCorr[firstChannel] = int(l)
1845 #
1845 #
1846 # pairsAutoCorr = pairsAutoCorr.astype(int)
1846 # pairsAutoCorr = pairsAutoCorr.astype(int)
1847 #
1847 #
1848 # pairsCrossCorr = range(len(pairsList))
1848 # pairsCrossCorr = range(len(pairsList))
1849 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1849 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1850 #
1850 #
1851 # return pairsAutoCorr, pairsCrossCorr
1851 # return pairsAutoCorr, pairsCrossCorr
1852
1852
1853 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1853 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1854 def techniqueSA(self, kwargs):
1854 def techniqueSA(self, kwargs):
1855
1855
1856 """
1856 """
1857 Function that implements Spaced Antenna (SA) technique.
1857 Function that implements Spaced Antenna (SA) technique.
1858
1858
1859 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1859 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1860 Direction correction (if necessary), Ranges and SNR
1860 Direction correction (if necessary), Ranges and SNR
1861
1861
1862 Output: Winds estimation (Zonal, Meridional and Vertical)
1862 Output: Winds estimation (Zonal, Meridional and Vertical)
1863
1863
1864 Parameters affected: Winds
1864 Parameters affected: Winds
1865 """
1865 """
1866 position_x = kwargs['positionX']
1866 position_x = kwargs['positionX']
1867 position_y = kwargs['positionY']
1867 position_y = kwargs['positionY']
1868 azimuth = kwargs['azimuth']
1868 azimuth = kwargs['azimuth']
1869
1869
1870 if 'correctFactor' in kwargs:
1870 if 'correctFactor' in kwargs:
1871 correctFactor = kwargs['correctFactor']
1871 correctFactor = kwargs['correctFactor']
1872 else:
1872 else:
1873 correctFactor = 1
1873 correctFactor = 1
1874
1874
1875 groupList = kwargs['groupList']
1875 groupList = kwargs['groupList']
1876 pairs_ccf = groupList[1]
1876 pairs_ccf = groupList[1]
1877 tau = kwargs['tau']
1877 tau = kwargs['tau']
1878 _lambda = kwargs['_lambda']
1878 _lambda = kwargs['_lambda']
1879
1879
1880 #Cross Correlation pairs obtained
1880 #Cross Correlation pairs obtained
1881 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1881 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1882 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1882 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1883 # pairsSelArray = numpy.array(pairsSelected)
1883 # pairsSelArray = numpy.array(pairsSelected)
1884 # pairs = []
1884 # pairs = []
1885 #
1885 #
1886 # #Wind estimation pairs obtained
1886 # #Wind estimation pairs obtained
1887 # for i in range(pairsSelArray.shape[0]/2):
1887 # for i in range(pairsSelArray.shape[0]/2):
1888 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1888 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1889 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1889 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1890 # pairs.append((ind1,ind2))
1890 # pairs.append((ind1,ind2))
1891
1891
1892 indtau = tau.shape[0]/2
1892 indtau = tau.shape[0]/2
1893 tau1 = tau[:indtau,:]
1893 tau1 = tau[:indtau,:]
1894 tau2 = tau[indtau:-1,:]
1894 tau2 = tau[indtau:-1,:]
1895 # tau1 = tau1[pairs,:]
1895 # tau1 = tau1[pairs,:]
1896 # tau2 = tau2[pairs,:]
1896 # tau2 = tau2[pairs,:]
1897 phase1 = tau[-1,:]
1897 phase1 = tau[-1,:]
1898
1898
1899 #---------------------------------------------------------------------
1899 #---------------------------------------------------------------------
1900 #Metodo Directo
1900 #Metodo Directo
1901 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1901 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1902 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1902 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1903 winds = stats.nanmean(winds, axis=0)
1903 winds = stats.nanmean(winds, axis=0)
1904 #---------------------------------------------------------------------
1904 #---------------------------------------------------------------------
1905 #Metodo General
1905 #Metodo General
1906 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1906 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1907 # #Calculo Coeficientes de Funcion de Correlacion
1907 # #Calculo Coeficientes de Funcion de Correlacion
1908 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1908 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1909 # #Calculo de Velocidades
1909 # #Calculo de Velocidades
1910 # winds = self.calculateVelUV(F,G,A,B,H)
1910 # winds = self.calculateVelUV(F,G,A,B,H)
1911
1911
1912 #---------------------------------------------------------------------
1912 #---------------------------------------------------------------------
1913 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1913 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1914 winds = correctFactor*winds
1914 winds = correctFactor*winds
1915 return winds
1915 return winds
1916
1916
1917 def __checkTime(self, currentTime, paramInterval, outputInterval):
1917 def __checkTime(self, currentTime, paramInterval, outputInterval):
1918
1918
1919 dataTime = currentTime + paramInterval
1919 dataTime = currentTime + paramInterval
1920 deltaTime = dataTime - self.__initime
1920 deltaTime = dataTime - self.__initime
1921
1921
1922 if deltaTime >= outputInterval or deltaTime < 0:
1922 if deltaTime >= outputInterval or deltaTime < 0:
1923 self.__dataReady = True
1923 self.__dataReady = True
1924 return
1924 return
1925
1925
1926 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1926 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1927 '''
1927 '''
1928 Function that implements winds estimation technique with detected meteors.
1928 Function that implements winds estimation technique with detected meteors.
1929
1929
1930 Input: Detected meteors, Minimum meteor quantity to wind estimation
1930 Input: Detected meteors, Minimum meteor quantity to wind estimation
1931
1931
1932 Output: Winds estimation (Zonal and Meridional)
1932 Output: Winds estimation (Zonal and Meridional)
1933
1933
1934 Parameters affected: Winds
1934 Parameters affected: Winds
1935 '''
1935 '''
1936 #Settings
1936 #Settings
1937 nInt = (heightMax - heightMin)/2
1937 nInt = (heightMax - heightMin)/2
1938 nInt = int(nInt)
1938 nInt = int(nInt)
1939 winds = numpy.zeros((2,nInt))*numpy.nan
1939 winds = numpy.zeros((2,nInt))*numpy.nan
1940
1940
1941 #Filter errors
1941 #Filter errors
1942 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1942 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1943 finalMeteor = arrayMeteor[error,:]
1943 finalMeteor = arrayMeteor[error,:]
1944
1944
1945 #Meteor Histogram
1945 #Meteor Histogram
1946 finalHeights = finalMeteor[:,2]
1946 finalHeights = finalMeteor[:,2]
1947 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1947 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1948 nMeteorsPerI = hist[0]
1948 nMeteorsPerI = hist[0]
1949 heightPerI = hist[1]
1949 heightPerI = hist[1]
1950
1950
1951 #Sort of meteors
1951 #Sort of meteors
1952 indSort = finalHeights.argsort()
1952 indSort = finalHeights.argsort()
1953 finalMeteor2 = finalMeteor[indSort,:]
1953 finalMeteor2 = finalMeteor[indSort,:]
1954
1954
1955 # Calculating winds
1955 # Calculating winds
1956 ind1 = 0
1956 ind1 = 0
1957 ind2 = 0
1957 ind2 = 0
1958
1958
1959 for i in range(nInt):
1959 for i in range(nInt):
1960 nMet = nMeteorsPerI[i]
1960 nMet = nMeteorsPerI[i]
1961 ind1 = ind2
1961 ind1 = ind2
1962 ind2 = ind1 + nMet
1962 ind2 = ind1 + nMet
1963
1963
1964 meteorAux = finalMeteor2[ind1:ind2,:]
1964 meteorAux = finalMeteor2[ind1:ind2,:]
1965
1965
1966 if meteorAux.shape[0] >= meteorThresh:
1966 if meteorAux.shape[0] >= meteorThresh:
1967 vel = meteorAux[:, 6]
1967 vel = meteorAux[:, 6]
1968 zen = meteorAux[:, 4]*numpy.pi/180
1968 zen = meteorAux[:, 4]*numpy.pi/180
1969 azim = meteorAux[:, 3]*numpy.pi/180
1969 azim = meteorAux[:, 3]*numpy.pi/180
1970
1970
1971 n = numpy.cos(zen)
1971 n = numpy.cos(zen)
1972 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1972 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1973 # l = m*numpy.tan(azim)
1973 # l = m*numpy.tan(azim)
1974 l = numpy.sin(zen)*numpy.sin(azim)
1974 l = numpy.sin(zen)*numpy.sin(azim)
1975 m = numpy.sin(zen)*numpy.cos(azim)
1975 m = numpy.sin(zen)*numpy.cos(azim)
1976
1976
1977 A = numpy.vstack((l, m)).transpose()
1977 A = numpy.vstack((l, m)).transpose()
1978 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1978 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1979 windsAux = numpy.dot(A1, vel)
1979 windsAux = numpy.dot(A1, vel)
1980
1980
1981 winds[0,i] = windsAux[0]
1981 winds[0,i] = windsAux[0]
1982 winds[1,i] = windsAux[1]
1982 winds[1,i] = windsAux[1]
1983
1983
1984 return winds, heightPerI[:-1]
1984 return winds, heightPerI[:-1]
1985
1985
1986 def techniqueNSM_SA(self, **kwargs):
1986 def techniqueNSM_SA(self, **kwargs):
1987 metArray = kwargs['metArray']
1987 metArray = kwargs['metArray']
1988 heightList = kwargs['heightList']
1988 heightList = kwargs['heightList']
1989 timeList = kwargs['timeList']
1989 timeList = kwargs['timeList']
1990
1990
1991 rx_location = kwargs['rx_location']
1991 rx_location = kwargs['rx_location']
1992 groupList = kwargs['groupList']
1992 groupList = kwargs['groupList']
1993 azimuth = kwargs['azimuth']
1993 azimuth = kwargs['azimuth']
1994 dfactor = kwargs['dfactor']
1994 dfactor = kwargs['dfactor']
1995 k = kwargs['k']
1995 k = kwargs['k']
1996
1996
1997 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1997 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1998 d = dist*dfactor
1998 d = dist*dfactor
1999 #Phase calculation
1999 #Phase calculation
2000 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2000 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2001
2001
2002 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2002 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2003
2003
2004 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2004 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2005 azimuth1 = azimuth1*numpy.pi/180
2005 azimuth1 = azimuth1*numpy.pi/180
2006
2006
2007 for i in range(heightList.size):
2007 for i in range(heightList.size):
2008 h = heightList[i]
2008 h = heightList[i]
2009 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2009 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2010 metHeight = metArray1[indH,:]
2010 metHeight = metArray1[indH,:]
2011 if metHeight.shape[0] >= 2:
2011 if metHeight.shape[0] >= 2:
2012 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2012 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2013 iazim = metHeight[:,1].astype(int)
2013 iazim = metHeight[:,1].astype(int)
2014 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2014 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2015 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2015 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2016 A = numpy.asmatrix(A)
2016 A = numpy.asmatrix(A)
2017 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2017 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2018 velHor = numpy.dot(A1,velAux)
2018 velHor = numpy.dot(A1,velAux)
2019
2019
2020 velEst[i,:] = numpy.squeeze(velHor)
2020 velEst[i,:] = numpy.squeeze(velHor)
2021 return velEst
2021 return velEst
2022
2022
2023 def __getPhaseSlope(self, metArray, heightList, timeList):
2023 def __getPhaseSlope(self, metArray, heightList, timeList):
2024 meteorList = []
2024 meteorList = []
2025 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2025 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2026 #Putting back together the meteor matrix
2026 #Putting back together the meteor matrix
2027 utctime = metArray[:,0]
2027 utctime = metArray[:,0]
2028 uniqueTime = numpy.unique(utctime)
2028 uniqueTime = numpy.unique(utctime)
2029
2029
2030 phaseDerThresh = 0.5
2030 phaseDerThresh = 0.5
2031 ippSeconds = timeList[1] - timeList[0]
2031 ippSeconds = timeList[1] - timeList[0]
2032 sec = numpy.where(timeList>1)[0][0]
2032 sec = numpy.where(timeList>1)[0][0]
2033 nPairs = metArray.shape[1] - 6
2033 nPairs = metArray.shape[1] - 6
2034 nHeights = len(heightList)
2034 nHeights = len(heightList)
2035
2035
2036 for t in uniqueTime:
2036 for t in uniqueTime:
2037 metArray1 = metArray[utctime==t,:]
2037 metArray1 = metArray[utctime==t,:]
2038 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2038 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2039 tmet = metArray1[:,1].astype(int)
2039 tmet = metArray1[:,1].astype(int)
2040 hmet = metArray1[:,2].astype(int)
2040 hmet = metArray1[:,2].astype(int)
2041
2041
2042 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2042 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2043 metPhase[:,:] = numpy.nan
2043 metPhase[:,:] = numpy.nan
2044 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2044 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2045
2045
2046 #Delete short trails
2046 #Delete short trails
2047 metBool = ~numpy.isnan(metPhase[0,:,:])
2047 metBool = ~numpy.isnan(metPhase[0,:,:])
2048 heightVect = numpy.sum(metBool, axis = 1)
2048 heightVect = numpy.sum(metBool, axis = 1)
2049 metBool[heightVect<sec,:] = False
2049 metBool[heightVect<sec,:] = False
2050 metPhase[:,heightVect<sec,:] = numpy.nan
2050 metPhase[:,heightVect<sec,:] = numpy.nan
2051
2051
2052 #Derivative
2052 #Derivative
2053 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2053 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2054 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2054 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2055 metPhase[phDerAux] = numpy.nan
2055 metPhase[phDerAux] = numpy.nan
2056
2056
2057 #--------------------------METEOR DETECTION -----------------------------------------
2057 #--------------------------METEOR DETECTION -----------------------------------------
2058 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2058 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2059
2059
2060 for p in numpy.arange(nPairs):
2060 for p in numpy.arange(nPairs):
2061 phase = metPhase[p,:,:]
2061 phase = metPhase[p,:,:]
2062 phDer = metDer[p,:,:]
2062 phDer = metDer[p,:,:]
2063
2063
2064 for h in indMet:
2064 for h in indMet:
2065 height = heightList[h]
2065 height = heightList[h]
2066 phase1 = phase[h,:] #82
2066 phase1 = phase[h,:] #82
2067 phDer1 = phDer[h,:]
2067 phDer1 = phDer[h,:]
2068
2068
2069 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2069 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2070
2070
2071 indValid = numpy.where(~numpy.isnan(phase1))[0]
2071 indValid = numpy.where(~numpy.isnan(phase1))[0]
2072 initMet = indValid[0]
2072 initMet = indValid[0]
2073 endMet = 0
2073 endMet = 0
2074
2074
2075 for i in range(len(indValid)-1):
2075 for i in range(len(indValid)-1):
2076
2076
2077 #Time difference
2077 #Time difference
2078 inow = indValid[i]
2078 inow = indValid[i]
2079 inext = indValid[i+1]
2079 inext = indValid[i+1]
2080 idiff = inext - inow
2080 idiff = inext - inow
2081 #Phase difference
2081 #Phase difference
2082 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2082 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2083
2083
2084 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2084 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2085 sizeTrail = inow - initMet + 1
2085 sizeTrail = inow - initMet + 1
2086 if sizeTrail>3*sec: #Too short meteors
2086 if sizeTrail>3*sec: #Too short meteors
2087 x = numpy.arange(initMet,inow+1)*ippSeconds
2087 x = numpy.arange(initMet,inow+1)*ippSeconds
2088 y = phase1[initMet:inow+1]
2088 y = phase1[initMet:inow+1]
2089 ynnan = ~numpy.isnan(y)
2089 ynnan = ~numpy.isnan(y)
2090 x = x[ynnan]
2090 x = x[ynnan]
2091 y = y[ynnan]
2091 y = y[ynnan]
2092 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2092 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2093 ylin = x*slope + intercept
2093 ylin = x*slope + intercept
2094 rsq = r_value**2
2094 rsq = r_value**2
2095 if rsq > 0.5:
2095 if rsq > 0.5:
2096 vel = slope#*height*1000/(k*d)
2096 vel = slope#*height*1000/(k*d)
2097 estAux = numpy.array([utctime,p,height, vel, rsq])
2097 estAux = numpy.array([utctime,p,height, vel, rsq])
2098 meteorList.append(estAux)
2098 meteorList.append(estAux)
2099 initMet = inext
2099 initMet = inext
2100 metArray2 = numpy.array(meteorList)
2100 metArray2 = numpy.array(meteorList)
2101
2101
2102 return metArray2
2102 return metArray2
2103
2103
2104 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2104 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2105
2105
2106 azimuth1 = numpy.zeros(len(pairslist))
2106 azimuth1 = numpy.zeros(len(pairslist))
2107 dist = numpy.zeros(len(pairslist))
2107 dist = numpy.zeros(len(pairslist))
2108
2108
2109 for i in range(len(rx_location)):
2109 for i in range(len(rx_location)):
2110 ch0 = pairslist[i][0]
2110 ch0 = pairslist[i][0]
2111 ch1 = pairslist[i][1]
2111 ch1 = pairslist[i][1]
2112
2112
2113 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2113 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2114 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2114 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2115 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2115 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2116 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2116 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2117
2117
2118 azimuth1 -= azimuth0
2118 azimuth1 -= azimuth0
2119 return azimuth1, dist
2119 return azimuth1, dist
2120
2120
2121 def techniqueNSM_DBS(self, **kwargs):
2121 def techniqueNSM_DBS(self, **kwargs):
2122 metArray = kwargs['metArray']
2122 metArray = kwargs['metArray']
2123 heightList = kwargs['heightList']
2123 heightList = kwargs['heightList']
2124 timeList = kwargs['timeList']
2124 timeList = kwargs['timeList']
2125 azimuth = kwargs['azimuth']
2125 azimuth = kwargs['azimuth']
2126 theta_x = numpy.array(kwargs['theta_x'])
2126 theta_x = numpy.array(kwargs['theta_x'])
2127 theta_y = numpy.array(kwargs['theta_y'])
2127 theta_y = numpy.array(kwargs['theta_y'])
2128
2128
2129 utctime = metArray[:,0]
2129 utctime = metArray[:,0]
2130 cmet = metArray[:,1].astype(int)
2130 cmet = metArray[:,1].astype(int)
2131 hmet = metArray[:,3].astype(int)
2131 hmet = metArray[:,3].astype(int)
2132 SNRmet = metArray[:,4]
2132 SNRmet = metArray[:,4]
2133 vmet = metArray[:,5]
2133 vmet = metArray[:,5]
2134 spcmet = metArray[:,6]
2134 spcmet = metArray[:,6]
2135
2135
2136 nChan = numpy.max(cmet) + 1
2136 nChan = numpy.max(cmet) + 1
2137 nHeights = len(heightList)
2137 nHeights = len(heightList)
2138
2138
2139 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2139 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2140 hmet = heightList[hmet]
2140 hmet = heightList[hmet]
2141 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2141 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2142
2142
2143 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2143 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2144
2144
2145 for i in range(nHeights - 1):
2145 for i in range(nHeights - 1):
2146 hmin = heightList[i]
2146 hmin = heightList[i]
2147 hmax = heightList[i + 1]
2147 hmax = heightList[i + 1]
2148
2148
2149 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2149 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2150 indthisH = numpy.where(thisH)
2150 indthisH = numpy.where(thisH)
2151
2151
2152 if numpy.size(indthisH) > 3:
2152 if numpy.size(indthisH) > 3:
2153
2153
2154 vel_aux = vmet[thisH]
2154 vel_aux = vmet[thisH]
2155 chan_aux = cmet[thisH]
2155 chan_aux = cmet[thisH]
2156 cosu_aux = dir_cosu[chan_aux]
2156 cosu_aux = dir_cosu[chan_aux]
2157 cosv_aux = dir_cosv[chan_aux]
2157 cosv_aux = dir_cosv[chan_aux]
2158 cosw_aux = dir_cosw[chan_aux]
2158 cosw_aux = dir_cosw[chan_aux]
2159
2159
2160 nch = numpy.size(numpy.unique(chan_aux))
2160 nch = numpy.size(numpy.unique(chan_aux))
2161 if nch > 1:
2161 if nch > 1:
2162 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2162 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2163 velEst[i,:] = numpy.dot(A,vel_aux)
2163 velEst[i,:] = numpy.dot(A,vel_aux)
2164
2164
2165 return velEst
2165 return velEst
2166
2166
2167 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2167 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2168
2168
2169 param = dataOut.data_param
2169 param = dataOut.data_param
2170 if dataOut.abscissaList != None:
2170 if dataOut.abscissaList != None:
2171 absc = dataOut.abscissaList[:-1]
2171 absc = dataOut.abscissaList[:-1]
2172 # noise = dataOut.noise
2172 # noise = dataOut.noise
2173 heightList = dataOut.heightList
2173 heightList = dataOut.heightList
2174 SNR = dataOut.data_snr
2174 SNR = dataOut.data_snr
2175
2175
2176 if technique == 'DBS':
2176 if technique == 'DBS':
2177
2177
2178 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2178 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2179 kwargs['heightList'] = heightList
2179 kwargs['heightList'] = heightList
2180 kwargs['SNR'] = SNR
2180 kwargs['SNR'] = SNR
2181
2181
2182 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2182 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2183 dataOut.utctimeInit = dataOut.utctime
2183 dataOut.utctimeInit = dataOut.utctime
2184 dataOut.outputInterval = dataOut.paramInterval
2184 dataOut.outputInterval = dataOut.paramInterval
2185
2185
2186 elif technique == 'SA':
2186 elif technique == 'SA':
2187
2187
2188 #Parameters
2188 #Parameters
2189 # position_x = kwargs['positionX']
2189 # position_x = kwargs['positionX']
2190 # position_y = kwargs['positionY']
2190 # position_y = kwargs['positionY']
2191 # azimuth = kwargs['azimuth']
2191 # azimuth = kwargs['azimuth']
2192 #
2192 #
2193 # if kwargs.has_key('crosspairsList'):
2193 # if kwargs.has_key('crosspairsList'):
2194 # pairs = kwargs['crosspairsList']
2194 # pairs = kwargs['crosspairsList']
2195 # else:
2195 # else:
2196 # pairs = None
2196 # pairs = None
2197 #
2197 #
2198 # if kwargs.has_key('correctFactor'):
2198 # if kwargs.has_key('correctFactor'):
2199 # correctFactor = kwargs['correctFactor']
2199 # correctFactor = kwargs['correctFactor']
2200 # else:
2200 # else:
2201 # correctFactor = 1
2201 # correctFactor = 1
2202
2202
2203 # tau = dataOut.data_param
2203 # tau = dataOut.data_param
2204 # _lambda = dataOut.C/dataOut.frequency
2204 # _lambda = dataOut.C/dataOut.frequency
2205 # pairsList = dataOut.groupList
2205 # pairsList = dataOut.groupList
2206 # nChannels = dataOut.nChannels
2206 # nChannels = dataOut.nChannels
2207
2207
2208 kwargs['groupList'] = dataOut.groupList
2208 kwargs['groupList'] = dataOut.groupList
2209 kwargs['tau'] = dataOut.data_param
2209 kwargs['tau'] = dataOut.data_param
2210 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2210 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2211 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2211 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2212 dataOut.data_output = self.techniqueSA(kwargs)
2212 dataOut.data_output = self.techniqueSA(kwargs)
2213 dataOut.utctimeInit = dataOut.utctime
2213 dataOut.utctimeInit = dataOut.utctime
2214 dataOut.outputInterval = dataOut.timeInterval
2214 dataOut.outputInterval = dataOut.timeInterval
2215
2215
2216 elif technique == 'Meteors':
2216 elif technique == 'Meteors':
2217 dataOut.flagNoData = True
2217 dataOut.flagNoData = True
2218 self.__dataReady = False
2218 self.__dataReady = False
2219
2219
2220 if 'nHours' in kwargs:
2220 if 'nHours' in kwargs:
2221 nHours = kwargs['nHours']
2221 nHours = kwargs['nHours']
2222 else:
2222 else:
2223 nHours = 1
2223 nHours = 1
2224
2224
2225 if 'meteorsPerBin' in kwargs:
2225 if 'meteorsPerBin' in kwargs:
2226 meteorThresh = kwargs['meteorsPerBin']
2226 meteorThresh = kwargs['meteorsPerBin']
2227 else:
2227 else:
2228 meteorThresh = 6
2228 meteorThresh = 6
2229
2229
2230 if 'hmin' in kwargs:
2230 if 'hmin' in kwargs:
2231 hmin = kwargs['hmin']
2231 hmin = kwargs['hmin']
2232 else: hmin = 70
2232 else: hmin = 70
2233 if 'hmax' in kwargs:
2233 if 'hmax' in kwargs:
2234 hmax = kwargs['hmax']
2234 hmax = kwargs['hmax']
2235 else: hmax = 110
2235 else: hmax = 110
2236
2236
2237 dataOut.outputInterval = nHours*3600
2237 dataOut.outputInterval = nHours*3600
2238
2238
2239 if self.__isConfig == False:
2239 if self.__isConfig == False:
2240 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2240 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2241 #Get Initial LTC time
2241 #Get Initial LTC time
2242 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2242 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2243 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2243 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2244
2244
2245 self.__isConfig = True
2245 self.__isConfig = True
2246
2246
2247 if self.__buffer is None:
2247 if self.__buffer is None:
2248 self.__buffer = dataOut.data_param
2248 self.__buffer = dataOut.data_param
2249 self.__firstdata = copy.copy(dataOut)
2249 self.__firstdata = copy.copy(dataOut)
2250
2250
2251 else:
2251 else:
2252 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2252 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2253
2253
2254 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2254 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2255
2255
2256 if self.__dataReady:
2256 if self.__dataReady:
2257 dataOut.utctimeInit = self.__initime
2257 dataOut.utctimeInit = self.__initime
2258
2258
2259 self.__initime += dataOut.outputInterval #to erase time offset
2259 self.__initime += dataOut.outputInterval #to erase time offset
2260
2260
2261 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2261 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2262 dataOut.flagNoData = False
2262 dataOut.flagNoData = False
2263 self.__buffer = None
2263 self.__buffer = None
2264
2264
2265 elif technique == 'Meteors1':
2265 elif technique == 'Meteors1':
2266 dataOut.flagNoData = True
2266 dataOut.flagNoData = True
2267 self.__dataReady = False
2267 self.__dataReady = False
2268
2268
2269 if 'nMins' in kwargs:
2269 if 'nMins' in kwargs:
2270 nMins = kwargs['nMins']
2270 nMins = kwargs['nMins']
2271 else: nMins = 20
2271 else: nMins = 20
2272 if 'rx_location' in kwargs:
2272 if 'rx_location' in kwargs:
2273 rx_location = kwargs['rx_location']
2273 rx_location = kwargs['rx_location']
2274 else: rx_location = [(0,1),(1,1),(1,0)]
2274 else: rx_location = [(0,1),(1,1),(1,0)]
2275 if 'azimuth' in kwargs:
2275 if 'azimuth' in kwargs:
2276 azimuth = kwargs['azimuth']
2276 azimuth = kwargs['azimuth']
2277 else: azimuth = 51.06
2277 else: azimuth = 51.06
2278 if 'dfactor' in kwargs:
2278 if 'dfactor' in kwargs:
2279 dfactor = kwargs['dfactor']
2279 dfactor = kwargs['dfactor']
2280 if 'mode' in kwargs:
2280 if 'mode' in kwargs:
2281 mode = kwargs['mode']
2281 mode = kwargs['mode']
2282 if 'theta_x' in kwargs:
2282 if 'theta_x' in kwargs:
2283 theta_x = kwargs['theta_x']
2283 theta_x = kwargs['theta_x']
2284 if 'theta_y' in kwargs:
2284 if 'theta_y' in kwargs:
2285 theta_y = kwargs['theta_y']
2285 theta_y = kwargs['theta_y']
2286 else: mode = 'SA'
2286 else: mode = 'SA'
2287
2287
2288 #Borrar luego esto
2288 #Borrar luego esto
2289 if dataOut.groupList is None:
2289 if dataOut.groupList is None:
2290 dataOut.groupList = [(0,1),(0,2),(1,2)]
2290 dataOut.groupList = [(0,1),(0,2),(1,2)]
2291 groupList = dataOut.groupList
2291 groupList = dataOut.groupList
2292 C = 3e8
2292 C = 3e8
2293 freq = 50e6
2293 freq = 50e6
2294 lamb = C/freq
2294 lamb = C/freq
2295 k = 2*numpy.pi/lamb
2295 k = 2*numpy.pi/lamb
2296
2296
2297 timeList = dataOut.abscissaList
2297 timeList = dataOut.abscissaList
2298 heightList = dataOut.heightList
2298 heightList = dataOut.heightList
2299
2299
2300 if self.__isConfig == False:
2300 if self.__isConfig == False:
2301 dataOut.outputInterval = nMins*60
2301 dataOut.outputInterval = nMins*60
2302 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2302 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2303 #Get Initial LTC time
2303 #Get Initial LTC time
2304 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2304 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2305 minuteAux = initime.minute
2305 minuteAux = initime.minute
2306 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2306 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2307 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2307 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2308
2308
2309 self.__isConfig = True
2309 self.__isConfig = True
2310
2310
2311 if self.__buffer is None:
2311 if self.__buffer is None:
2312 self.__buffer = dataOut.data_param
2312 self.__buffer = dataOut.data_param
2313 self.__firstdata = copy.copy(dataOut)
2313 self.__firstdata = copy.copy(dataOut)
2314
2314
2315 else:
2315 else:
2316 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2316 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2317
2317
2318 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2318 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2319
2319
2320 if self.__dataReady:
2320 if self.__dataReady:
2321 dataOut.utctimeInit = self.__initime
2321 dataOut.utctimeInit = self.__initime
2322 self.__initime += dataOut.outputInterval #to erase time offset
2322 self.__initime += dataOut.outputInterval #to erase time offset
2323
2323
2324 metArray = self.__buffer
2324 metArray = self.__buffer
2325 if mode == 'SA':
2325 if mode == 'SA':
2326 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2326 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2327 elif mode == 'DBS':
2327 elif mode == 'DBS':
2328 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2328 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2329 dataOut.data_output = dataOut.data_output.T
2329 dataOut.data_output = dataOut.data_output.T
2330 dataOut.flagNoData = False
2330 dataOut.flagNoData = False
2331 self.__buffer = None
2331 self.__buffer = None
2332
2332
2333 return
2333 return
2334
2334
2335 class EWDriftsEstimation(Operation):
2335 class EWDriftsEstimation(Operation):
2336
2336
2337 def __init__(self):
2337 def __init__(self):
2338 Operation.__init__(self)
2338 Operation.__init__(self)
2339
2339
2340 def __correctValues(self, heiRang, phi, velRadial, SNR):
2340 def __correctValues(self, heiRang, phi, velRadial, SNR):
2341 listPhi = phi.tolist()
2341 listPhi = phi.tolist()
2342 maxid = listPhi.index(max(listPhi))
2342 maxid = listPhi.index(max(listPhi))
2343 minid = listPhi.index(min(listPhi))
2343 minid = listPhi.index(min(listPhi))
2344
2344
2345 rango = list(range(len(phi)))
2345 rango = list(range(len(phi)))
2346 # rango = numpy.delete(rango,maxid)
2346 # rango = numpy.delete(rango,maxid)
2347
2347
2348 heiRang1 = heiRang*math.cos(phi[maxid])
2348 heiRang1 = heiRang*math.cos(phi[maxid])
2349 heiRangAux = heiRang*math.cos(phi[minid])
2349 heiRangAux = heiRang*math.cos(phi[minid])
2350 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2350 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2351 heiRang1 = numpy.delete(heiRang1,indOut)
2351 heiRang1 = numpy.delete(heiRang1,indOut)
2352
2352
2353 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2353 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2354 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2354 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2355
2355
2356 for i in rango:
2356 for i in rango:
2357 x = heiRang*math.cos(phi[i])
2357 x = heiRang*math.cos(phi[i])
2358 y1 = velRadial[i,:]
2358 y1 = velRadial[i,:]
2359 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2359 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2360
2360
2361 x1 = heiRang1
2361 x1 = heiRang1
2362 y11 = f1(x1)
2362 y11 = f1(x1)
2363
2363
2364 y2 = SNR[i,:]
2364 y2 = SNR[i,:]
2365 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2365 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2366 y21 = f2(x1)
2366 y21 = f2(x1)
2367
2367
2368 velRadial1[i,:] = y11
2368 velRadial1[i,:] = y11
2369 SNR1[i,:] = y21
2369 SNR1[i,:] = y21
2370
2370
2371 return heiRang1, velRadial1, SNR1
2371 return heiRang1, velRadial1, SNR1
2372
2372
2373 def run(self, dataOut, zenith, zenithCorrection):
2373 def run(self, dataOut, zenith, zenithCorrection):
2374 heiRang = dataOut.heightList
2374 heiRang = dataOut.heightList
2375 velRadial = dataOut.data_param[:,3,:]
2375 velRadial = dataOut.data_param[:,3,:]
2376 SNR = dataOut.data_snr
2376 SNR = dataOut.data_snr
2377
2377
2378 zenith = numpy.array(zenith)
2378 zenith = numpy.array(zenith)
2379 zenith -= zenithCorrection
2379 zenith -= zenithCorrection
2380 zenith *= numpy.pi/180
2380 zenith *= numpy.pi/180
2381
2381
2382 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2382 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2383
2383
2384 alp = zenith[0]
2384 alp = zenith[0]
2385 bet = zenith[1]
2385 bet = zenith[1]
2386
2386
2387 w_w = velRadial1[0,:]
2387 w_w = velRadial1[0,:]
2388 w_e = velRadial1[1,:]
2388 w_e = velRadial1[1,:]
2389
2389
2390 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2390 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2391 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2391 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2392
2392
2393 winds = numpy.vstack((u,w))
2393 winds = numpy.vstack((u,w))
2394
2394
2395 dataOut.heightList = heiRang1
2395 dataOut.heightList = heiRang1
2396 dataOut.data_output = winds
2396 dataOut.data_output = winds
2397 dataOut.data_snr = SNR1
2397 dataOut.data_snr = SNR1
2398
2398
2399 dataOut.utctimeInit = dataOut.utctime
2399 dataOut.utctimeInit = dataOut.utctime
2400 dataOut.outputInterval = dataOut.timeInterval
2400 dataOut.outputInterval = dataOut.timeInterval
2401 return
2401 return
2402
2402
2403 #--------------- Non Specular Meteor ----------------
2403 #--------------- Non Specular Meteor ----------------
2404
2404
2405 class NonSpecularMeteorDetection(Operation):
2405 class NonSpecularMeteorDetection(Operation):
2406
2406
2407 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2407 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2408 data_acf = dataOut.data_pre[0]
2408 data_acf = dataOut.data_pre[0]
2409 data_ccf = dataOut.data_pre[1]
2409 data_ccf = dataOut.data_pre[1]
2410 pairsList = dataOut.groupList[1]
2410 pairsList = dataOut.groupList[1]
2411
2411
2412 lamb = dataOut.C/dataOut.frequency
2412 lamb = dataOut.C/dataOut.frequency
2413 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2413 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2414 paramInterval = dataOut.paramInterval
2414 paramInterval = dataOut.paramInterval
2415
2415
2416 nChannels = data_acf.shape[0]
2416 nChannels = data_acf.shape[0]
2417 nLags = data_acf.shape[1]
2417 nLags = data_acf.shape[1]
2418 nProfiles = data_acf.shape[2]
2418 nProfiles = data_acf.shape[2]
2419 nHeights = dataOut.nHeights
2419 nHeights = dataOut.nHeights
2420 nCohInt = dataOut.nCohInt
2420 nCohInt = dataOut.nCohInt
2421 sec = numpy.round(nProfiles/dataOut.paramInterval)
2421 sec = numpy.round(nProfiles/dataOut.paramInterval)
2422 heightList = dataOut.heightList
2422 heightList = dataOut.heightList
2423 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2423 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2424 utctime = dataOut.utctime
2424 utctime = dataOut.utctime
2425
2425
2426 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2426 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2427
2427
2428 #------------------------ SNR --------------------------------------
2428 #------------------------ SNR --------------------------------------
2429 power = data_acf[:,0,:,:].real
2429 power = data_acf[:,0,:,:].real
2430 noise = numpy.zeros(nChannels)
2430 noise = numpy.zeros(nChannels)
2431 SNR = numpy.zeros(power.shape)
2431 SNR = numpy.zeros(power.shape)
2432 for i in range(nChannels):
2432 for i in range(nChannels):
2433 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2433 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2434 SNR[i] = (power[i]-noise[i])/noise[i]
2434 SNR[i] = (power[i]-noise[i])/noise[i]
2435 SNRm = numpy.nanmean(SNR, axis = 0)
2435 SNRm = numpy.nanmean(SNR, axis = 0)
2436 SNRdB = 10*numpy.log10(SNR)
2436 SNRdB = 10*numpy.log10(SNR)
2437
2437
2438 if mode == 'SA':
2438 if mode == 'SA':
2439 dataOut.groupList = dataOut.groupList[1]
2439 dataOut.groupList = dataOut.groupList[1]
2440 nPairs = data_ccf.shape[0]
2440 nPairs = data_ccf.shape[0]
2441 #---------------------- Coherence and Phase --------------------------
2441 #---------------------- Coherence and Phase --------------------------
2442 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2442 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2443 # phase1 = numpy.copy(phase)
2443 # phase1 = numpy.copy(phase)
2444 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2444 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2445
2445
2446 for p in range(nPairs):
2446 for p in range(nPairs):
2447 ch0 = pairsList[p][0]
2447 ch0 = pairsList[p][0]
2448 ch1 = pairsList[p][1]
2448 ch1 = pairsList[p][1]
2449 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2449 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2450 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2450 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2451 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2451 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2452 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2452 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2453 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2453 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2454 coh = numpy.nanmax(coh1, axis = 0)
2454 coh = numpy.nanmax(coh1, axis = 0)
2455 # struc = numpy.ones((5,1))
2455 # struc = numpy.ones((5,1))
2456 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2456 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2457 #---------------------- Radial Velocity ----------------------------
2457 #---------------------- Radial Velocity ----------------------------
2458 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2458 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2459 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2459 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2460
2460
2461 if allData:
2461 if allData:
2462 boolMetFin = ~numpy.isnan(SNRm)
2462 boolMetFin = ~numpy.isnan(SNRm)
2463 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2463 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2464 else:
2464 else:
2465 #------------------------ Meteor mask ---------------------------------
2465 #------------------------ Meteor mask ---------------------------------
2466 # #SNR mask
2466 # #SNR mask
2467 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2467 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2468 #
2468 #
2469 # #Erase small objects
2469 # #Erase small objects
2470 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2470 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2471 #
2471 #
2472 # auxEEJ = numpy.sum(boolMet1,axis=0)
2472 # auxEEJ = numpy.sum(boolMet1,axis=0)
2473 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2473 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2474 # indEEJ = numpy.where(indOver)[0]
2474 # indEEJ = numpy.where(indOver)[0]
2475 # indNEEJ = numpy.where(~indOver)[0]
2475 # indNEEJ = numpy.where(~indOver)[0]
2476 #
2476 #
2477 # boolMetFin = boolMet1
2477 # boolMetFin = boolMet1
2478 #
2478 #
2479 # if indEEJ.size > 0:
2479 # if indEEJ.size > 0:
2480 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2480 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2481 #
2481 #
2482 # boolMet2 = coh > cohThresh
2482 # boolMet2 = coh > cohThresh
2483 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2483 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2484 #
2484 #
2485 # #Final Meteor mask
2485 # #Final Meteor mask
2486 # boolMetFin = boolMet1|boolMet2
2486 # boolMetFin = boolMet1|boolMet2
2487
2487
2488 #Coherence mask
2488 #Coherence mask
2489 boolMet1 = coh > 0.75
2489 boolMet1 = coh > 0.75
2490 struc = numpy.ones((30,1))
2490 struc = numpy.ones((30,1))
2491 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2491 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2492
2492
2493 #Derivative mask
2493 #Derivative mask
2494 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2494 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2495 boolMet2 = derPhase < 0.2
2495 boolMet2 = derPhase < 0.2
2496 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2496 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2497 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2497 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2498 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2498 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2499 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2499 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2500 # #Final mask
2500 # #Final mask
2501 # boolMetFin = boolMet2
2501 # boolMetFin = boolMet2
2502 boolMetFin = boolMet1&boolMet2
2502 boolMetFin = boolMet1&boolMet2
2503 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2503 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2504 #Creating data_param
2504 #Creating data_param
2505 coordMet = numpy.where(boolMetFin)
2505 coordMet = numpy.where(boolMetFin)
2506
2506
2507 tmet = coordMet[0]
2507 tmet = coordMet[0]
2508 hmet = coordMet[1]
2508 hmet = coordMet[1]
2509
2509
2510 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2510 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2511 data_param[:,0] = utctime
2511 data_param[:,0] = utctime
2512 data_param[:,1] = tmet
2512 data_param[:,1] = tmet
2513 data_param[:,2] = hmet
2513 data_param[:,2] = hmet
2514 data_param[:,3] = SNRm[tmet,hmet]
2514 data_param[:,3] = SNRm[tmet,hmet]
2515 data_param[:,4] = velRad[tmet,hmet]
2515 data_param[:,4] = velRad[tmet,hmet]
2516 data_param[:,5] = coh[tmet,hmet]
2516 data_param[:,5] = coh[tmet,hmet]
2517 data_param[:,6:] = phase[:,tmet,hmet].T
2517 data_param[:,6:] = phase[:,tmet,hmet].T
2518
2518
2519 elif mode == 'DBS':
2519 elif mode == 'DBS':
2520 dataOut.groupList = numpy.arange(nChannels)
2520 dataOut.groupList = numpy.arange(nChannels)
2521
2521
2522 #Radial Velocities
2522 #Radial Velocities
2523 phase = numpy.angle(data_acf[:,1,:,:])
2523 phase = numpy.angle(data_acf[:,1,:,:])
2524 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2524 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2525 velRad = phase*lamb/(4*numpy.pi*tSamp)
2525 velRad = phase*lamb/(4*numpy.pi*tSamp)
2526
2526
2527 #Spectral width
2527 #Spectral width
2528 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2528 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2529 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2529 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2530 acf1 = data_acf[:,1,:,:]
2530 acf1 = data_acf[:,1,:,:]
2531 acf2 = data_acf[:,2,:,:]
2531 acf2 = data_acf[:,2,:,:]
2532
2532
2533 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2533 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2534 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2534 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2535 if allData:
2535 if allData:
2536 boolMetFin = ~numpy.isnan(SNRdB)
2536 boolMetFin = ~numpy.isnan(SNRdB)
2537 else:
2537 else:
2538 #SNR
2538 #SNR
2539 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2539 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2540 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2540 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2541
2541
2542 #Radial velocity
2542 #Radial velocity
2543 boolMet2 = numpy.abs(velRad) < 20
2543 boolMet2 = numpy.abs(velRad) < 20
2544 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2544 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2545
2545
2546 #Spectral Width
2546 #Spectral Width
2547 boolMet3 = spcWidth < 30
2547 boolMet3 = spcWidth < 30
2548 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2548 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2549 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2549 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2550 boolMetFin = boolMet1&boolMet2&boolMet3
2550 boolMetFin = boolMet1&boolMet2&boolMet3
2551
2551
2552 #Creating data_param
2552 #Creating data_param
2553 coordMet = numpy.where(boolMetFin)
2553 coordMet = numpy.where(boolMetFin)
2554
2554
2555 cmet = coordMet[0]
2555 cmet = coordMet[0]
2556 tmet = coordMet[1]
2556 tmet = coordMet[1]
2557 hmet = coordMet[2]
2557 hmet = coordMet[2]
2558
2558
2559 data_param = numpy.zeros((tmet.size, 7))
2559 data_param = numpy.zeros((tmet.size, 7))
2560 data_param[:,0] = utctime
2560 data_param[:,0] = utctime
2561 data_param[:,1] = cmet
2561 data_param[:,1] = cmet
2562 data_param[:,2] = tmet
2562 data_param[:,2] = tmet
2563 data_param[:,3] = hmet
2563 data_param[:,3] = hmet
2564 data_param[:,4] = SNR[cmet,tmet,hmet].T
2564 data_param[:,4] = SNR[cmet,tmet,hmet].T
2565 data_param[:,5] = velRad[cmet,tmet,hmet].T
2565 data_param[:,5] = velRad[cmet,tmet,hmet].T
2566 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2566 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2567
2567
2568 # self.dataOut.data_param = data_int
2568 # self.dataOut.data_param = data_int
2569 if len(data_param) == 0:
2569 if len(data_param) == 0:
2570 dataOut.flagNoData = True
2570 dataOut.flagNoData = True
2571 else:
2571 else:
2572 dataOut.data_param = data_param
2572 dataOut.data_param = data_param
2573
2573
2574 def __erase_small(self, binArray, threshX, threshY):
2574 def __erase_small(self, binArray, threshX, threshY):
2575 labarray, numfeat = ndimage.measurements.label(binArray)
2575 labarray, numfeat = ndimage.measurements.label(binArray)
2576 binArray1 = numpy.copy(binArray)
2576 binArray1 = numpy.copy(binArray)
2577
2577
2578 for i in range(1,numfeat + 1):
2578 for i in range(1,numfeat + 1):
2579 auxBin = (labarray==i)
2579 auxBin = (labarray==i)
2580 auxSize = auxBin.sum()
2580 auxSize = auxBin.sum()
2581
2581
2582 x,y = numpy.where(auxBin)
2582 x,y = numpy.where(auxBin)
2583 widthX = x.max() - x.min()
2583 widthX = x.max() - x.min()
2584 widthY = y.max() - y.min()
2584 widthY = y.max() - y.min()
2585
2585
2586 #width X: 3 seg -> 12.5*3
2586 #width X: 3 seg -> 12.5*3
2587 #width Y:
2587 #width Y:
2588
2588
2589 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2589 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2590 binArray1[auxBin] = False
2590 binArray1[auxBin] = False
2591
2591
2592 return binArray1
2592 return binArray1
2593
2593
2594 #--------------- Specular Meteor ----------------
2594 #--------------- Specular Meteor ----------------
2595
2595
2596 class SMDetection(Operation):
2596 class SMDetection(Operation):
2597 '''
2597 '''
2598 Function DetectMeteors()
2598 Function DetectMeteors()
2599 Project developed with paper:
2599 Project developed with paper:
2600 HOLDSWORTH ET AL. 2004
2600 HOLDSWORTH ET AL. 2004
2601
2601
2602 Input:
2602 Input:
2603 self.dataOut.data_pre
2603 self.dataOut.data_pre
2604
2604
2605 centerReceiverIndex: From the channels, which is the center receiver
2605 centerReceiverIndex: From the channels, which is the center receiver
2606
2606
2607 hei_ref: Height reference for the Beacon signal extraction
2607 hei_ref: Height reference for the Beacon signal extraction
2608 tauindex:
2608 tauindex:
2609 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2609 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2610
2610
2611 cohDetection: Whether to user Coherent detection or not
2611 cohDetection: Whether to user Coherent detection or not
2612 cohDet_timeStep: Coherent Detection calculation time step
2612 cohDet_timeStep: Coherent Detection calculation time step
2613 cohDet_thresh: Coherent Detection phase threshold to correct phases
2613 cohDet_thresh: Coherent Detection phase threshold to correct phases
2614
2614
2615 noise_timeStep: Noise calculation time step
2615 noise_timeStep: Noise calculation time step
2616 noise_multiple: Noise multiple to define signal threshold
2616 noise_multiple: Noise multiple to define signal threshold
2617
2617
2618 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2618 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2619 multDet_rangeLimit: Multiple Detection Removal range limit in km
2619 multDet_rangeLimit: Multiple Detection Removal range limit in km
2620
2620
2621 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2621 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2622 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2622 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2623
2623
2624 hmin: Minimum Height of the meteor to use it in the further wind estimations
2624 hmin: Minimum Height of the meteor to use it in the further wind estimations
2625 hmax: Maximum Height of the meteor to use it in the further wind estimations
2625 hmax: Maximum Height of the meteor to use it in the further wind estimations
2626 azimuth: Azimuth angle correction
2626 azimuth: Azimuth angle correction
2627
2627
2628 Affected:
2628 Affected:
2629 self.dataOut.data_param
2629 self.dataOut.data_param
2630
2630
2631 Rejection Criteria (Errors):
2631 Rejection Criteria (Errors):
2632 0: No error; analysis OK
2632 0: No error; analysis OK
2633 1: SNR < SNR threshold
2633 1: SNR < SNR threshold
2634 2: angle of arrival (AOA) ambiguously determined
2634 2: angle of arrival (AOA) ambiguously determined
2635 3: AOA estimate not feasible
2635 3: AOA estimate not feasible
2636 4: Large difference in AOAs obtained from different antenna baselines
2636 4: Large difference in AOAs obtained from different antenna baselines
2637 5: echo at start or end of time series
2637 5: echo at start or end of time series
2638 6: echo less than 5 examples long; too short for analysis
2638 6: echo less than 5 examples long; too short for analysis
2639 7: echo rise exceeds 0.3s
2639 7: echo rise exceeds 0.3s
2640 8: echo decay time less than twice rise time
2640 8: echo decay time less than twice rise time
2641 9: large power level before echo
2641 9: large power level before echo
2642 10: large power level after echo
2642 10: large power level after echo
2643 11: poor fit to amplitude for estimation of decay time
2643 11: poor fit to amplitude for estimation of decay time
2644 12: poor fit to CCF phase variation for estimation of radial drift velocity
2644 12: poor fit to CCF phase variation for estimation of radial drift velocity
2645 13: height unresolvable echo: not valid height within 70 to 110 km
2645 13: height unresolvable echo: not valid height within 70 to 110 km
2646 14: height ambiguous echo: more then one possible height within 70 to 110 km
2646 14: height ambiguous echo: more then one possible height within 70 to 110 km
2647 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2647 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2648 16: oscilatory echo, indicating event most likely not an underdense echo
2648 16: oscilatory echo, indicating event most likely not an underdense echo
2649
2649
2650 17: phase difference in meteor Reestimation
2650 17: phase difference in meteor Reestimation
2651
2651
2652 Data Storage:
2652 Data Storage:
2653 Meteors for Wind Estimation (8):
2653 Meteors for Wind Estimation (8):
2654 Utc Time | Range Height
2654 Utc Time | Range Height
2655 Azimuth Zenith errorCosDir
2655 Azimuth Zenith errorCosDir
2656 VelRad errorVelRad
2656 VelRad errorVelRad
2657 Phase0 Phase1 Phase2 Phase3
2657 Phase0 Phase1 Phase2 Phase3
2658 TypeError
2658 TypeError
2659
2659
2660 '''
2660 '''
2661
2661
2662 def run(self, dataOut, hei_ref = None, tauindex = 0,
2662 def run(self, dataOut, hei_ref = None, tauindex = 0,
2663 phaseOffsets = None,
2663 phaseOffsets = None,
2664 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2664 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2665 noise_timeStep = 4, noise_multiple = 4,
2665 noise_timeStep = 4, noise_multiple = 4,
2666 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2666 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2667 phaseThresh = 20, SNRThresh = 5,
2667 phaseThresh = 20, SNRThresh = 5,
2668 hmin = 50, hmax=150, azimuth = 0,
2668 hmin = 50, hmax=150, azimuth = 0,
2669 channelPositions = None) :
2669 channelPositions = None) :
2670
2670
2671
2671
2672 #Getting Pairslist
2672 #Getting Pairslist
2673 if channelPositions is None:
2673 if channelPositions is None:
2674 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2674 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2675 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2675 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2676 meteorOps = SMOperations()
2676 meteorOps = SMOperations()
2677 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2677 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2678 heiRang = dataOut.heightList
2678 heiRang = dataOut.heightList
2679 #Get Beacon signal - No Beacon signal anymore
2679 #Get Beacon signal - No Beacon signal anymore
2680 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2680 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2681 #
2681 #
2682 # if hei_ref != None:
2682 # if hei_ref != None:
2683 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2683 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2684 #
2684 #
2685
2685
2686
2686
2687 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2687 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2688 # see if the user put in pre defined phase shifts
2688 # see if the user put in pre defined phase shifts
2689 voltsPShift = dataOut.data_pre.copy()
2689 voltsPShift = dataOut.data_pre.copy()
2690
2690
2691 # if predefinedPhaseShifts != None:
2691 # if predefinedPhaseShifts != None:
2692 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2692 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2693 #
2693 #
2694 # # elif beaconPhaseShifts:
2694 # # elif beaconPhaseShifts:
2695 # # #get hardware phase shifts using beacon signal
2695 # # #get hardware phase shifts using beacon signal
2696 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2696 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2697 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2697 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2698 #
2698 #
2699 # else:
2699 # else:
2700 # hardwarePhaseShifts = numpy.zeros(5)
2700 # hardwarePhaseShifts = numpy.zeros(5)
2701 #
2701 #
2702 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2702 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2703 # for i in range(self.dataOut.data_pre.shape[0]):
2703 # for i in range(self.dataOut.data_pre.shape[0]):
2704 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2704 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2705
2705
2706 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2706 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2707
2707
2708 #Remove DC
2708 #Remove DC
2709 voltsDC = numpy.mean(voltsPShift,1)
2709 voltsDC = numpy.mean(voltsPShift,1)
2710 voltsDC = numpy.mean(voltsDC,1)
2710 voltsDC = numpy.mean(voltsDC,1)
2711 for i in range(voltsDC.shape[0]):
2711 for i in range(voltsDC.shape[0]):
2712 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2712 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2713
2713
2714 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2714 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2715 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2715 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2716
2716
2717 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2717 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2718 #Coherent Detection
2718 #Coherent Detection
2719 if cohDetection:
2719 if cohDetection:
2720 #use coherent detection to get the net power
2720 #use coherent detection to get the net power
2721 cohDet_thresh = cohDet_thresh*numpy.pi/180
2721 cohDet_thresh = cohDet_thresh*numpy.pi/180
2722 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2722 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2723
2723
2724 #Non-coherent detection!
2724 #Non-coherent detection!
2725 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2725 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2726 #********** END OF COH/NON-COH POWER CALCULATION**********************
2726 #********** END OF COH/NON-COH POWER CALCULATION**********************
2727
2727
2728 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2728 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2729 #Get noise
2729 #Get noise
2730 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2730 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2731 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2731 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2732 #Get signal threshold
2732 #Get signal threshold
2733 signalThresh = noise_multiple*noise
2733 signalThresh = noise_multiple*noise
2734 #Meteor echoes detection
2734 #Meteor echoes detection
2735 listMeteors = self.__findMeteors(powerNet, signalThresh)
2735 listMeteors = self.__findMeteors(powerNet, signalThresh)
2736 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2736 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2737
2737
2738 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2738 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2739 #Parameters
2739 #Parameters
2740 heiRange = dataOut.heightList
2740 heiRange = dataOut.heightList
2741 rangeInterval = heiRange[1] - heiRange[0]
2741 rangeInterval = heiRange[1] - heiRange[0]
2742 rangeLimit = multDet_rangeLimit/rangeInterval
2742 rangeLimit = multDet_rangeLimit/rangeInterval
2743 timeLimit = multDet_timeLimit/dataOut.timeInterval
2743 timeLimit = multDet_timeLimit/dataOut.timeInterval
2744 #Multiple detection removals
2744 #Multiple detection removals
2745 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2745 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2746 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2746 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2747
2747
2748 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2748 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2749 #Parameters
2749 #Parameters
2750 phaseThresh = phaseThresh*numpy.pi/180
2750 phaseThresh = phaseThresh*numpy.pi/180
2751 thresh = [phaseThresh, noise_multiple, SNRThresh]
2751 thresh = [phaseThresh, noise_multiple, SNRThresh]
2752 #Meteor reestimation (Errors N 1, 6, 12, 17)
2752 #Meteor reestimation (Errors N 1, 6, 12, 17)
2753 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2753 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2754 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2754 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2755 #Estimation of decay times (Errors N 7, 8, 11)
2755 #Estimation of decay times (Errors N 7, 8, 11)
2756 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2756 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2757 #******************* END OF METEOR REESTIMATION *******************
2757 #******************* END OF METEOR REESTIMATION *******************
2758
2758
2759 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2759 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2760 #Calculating Radial Velocity (Error N 15)
2760 #Calculating Radial Velocity (Error N 15)
2761 radialStdThresh = 10
2761 radialStdThresh = 10
2762 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2762 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2763
2763
2764 if len(listMeteors4) > 0:
2764 if len(listMeteors4) > 0:
2765 #Setting New Array
2765 #Setting New Array
2766 date = dataOut.utctime
2766 date = dataOut.utctime
2767 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2767 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2768
2768
2769 #Correcting phase offset
2769 #Correcting phase offset
2770 if phaseOffsets != None:
2770 if phaseOffsets != None:
2771 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2771 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2772 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2772 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2773
2773
2774 #Second Pairslist
2774 #Second Pairslist
2775 pairsList = []
2775 pairsList = []
2776 pairx = (0,1)
2776 pairx = (0,1)
2777 pairy = (2,3)
2777 pairy = (2,3)
2778 pairsList.append(pairx)
2778 pairsList.append(pairx)
2779 pairsList.append(pairy)
2779 pairsList.append(pairy)
2780
2780
2781 jph = numpy.array([0,0,0,0])
2781 jph = numpy.array([0,0,0,0])
2782 h = (hmin,hmax)
2782 h = (hmin,hmax)
2783 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2783 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2784
2784
2785 # #Calculate AOA (Error N 3, 4)
2785 # #Calculate AOA (Error N 3, 4)
2786 # #JONES ET AL. 1998
2786 # #JONES ET AL. 1998
2787 # error = arrayParameters[:,-1]
2787 # error = arrayParameters[:,-1]
2788 # AOAthresh = numpy.pi/8
2788 # AOAthresh = numpy.pi/8
2789 # phases = -arrayParameters[:,9:13]
2789 # phases = -arrayParameters[:,9:13]
2790 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2790 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2791 #
2791 #
2792 # #Calculate Heights (Error N 13 and 14)
2792 # #Calculate Heights (Error N 13 and 14)
2793 # error = arrayParameters[:,-1]
2793 # error = arrayParameters[:,-1]
2794 # Ranges = arrayParameters[:,2]
2794 # Ranges = arrayParameters[:,2]
2795 # zenith = arrayParameters[:,5]
2795 # zenith = arrayParameters[:,5]
2796 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2796 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2797 # error = arrayParameters[:,-1]
2797 # error = arrayParameters[:,-1]
2798 #********************* END OF PARAMETERS CALCULATION **************************
2798 #********************* END OF PARAMETERS CALCULATION **************************
2799
2799
2800 #***************************+ PASS DATA TO NEXT STEP **********************
2800 #***************************+ PASS DATA TO NEXT STEP **********************
2801 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2801 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2802 dataOut.data_param = arrayParameters
2802 dataOut.data_param = arrayParameters
2803
2803
2804 if arrayParameters is None:
2804 if arrayParameters is None:
2805 dataOut.flagNoData = True
2805 dataOut.flagNoData = True
2806 else:
2806 else:
2807 dataOut.flagNoData = True
2807 dataOut.flagNoData = True
2808
2808
2809 return
2809 return
2810
2810
2811 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2811 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2812
2812
2813 minIndex = min(newheis[0])
2813 minIndex = min(newheis[0])
2814 maxIndex = max(newheis[0])
2814 maxIndex = max(newheis[0])
2815
2815
2816 voltage = voltage0[:,:,minIndex:maxIndex+1]
2816 voltage = voltage0[:,:,minIndex:maxIndex+1]
2817 nLength = voltage.shape[1]/n
2817 nLength = voltage.shape[1]/n
2818 nMin = 0
2818 nMin = 0
2819 nMax = 0
2819 nMax = 0
2820 phaseOffset = numpy.zeros((len(pairslist),n))
2820 phaseOffset = numpy.zeros((len(pairslist),n))
2821
2821
2822 for i in range(n):
2822 for i in range(n):
2823 nMax += nLength
2823 nMax += nLength
2824 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2824 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2825 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2825 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2826 phaseOffset[:,i] = phaseCCF.transpose()
2826 phaseOffset[:,i] = phaseCCF.transpose()
2827 nMin = nMax
2827 nMin = nMax
2828 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2828 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2829
2829
2830 #Remove Outliers
2830 #Remove Outliers
2831 factor = 2
2831 factor = 2
2832 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2832 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2833 dw = numpy.std(wt,axis = 1)
2833 dw = numpy.std(wt,axis = 1)
2834 dw = dw.reshape((dw.size,1))
2834 dw = dw.reshape((dw.size,1))
2835 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2835 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2836 phaseOffset[ind] = numpy.nan
2836 phaseOffset[ind] = numpy.nan
2837 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2837 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2838
2838
2839 return phaseOffset
2839 return phaseOffset
2840
2840
2841 def __shiftPhase(self, data, phaseShift):
2841 def __shiftPhase(self, data, phaseShift):
2842 #this will shift the phase of a complex number
2842 #this will shift the phase of a complex number
2843 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2843 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2844 return dataShifted
2844 return dataShifted
2845
2845
2846 def __estimatePhaseDifference(self, array, pairslist):
2846 def __estimatePhaseDifference(self, array, pairslist):
2847 nChannel = array.shape[0]
2847 nChannel = array.shape[0]
2848 nHeights = array.shape[2]
2848 nHeights = array.shape[2]
2849 numPairs = len(pairslist)
2849 numPairs = len(pairslist)
2850 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2850 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2851 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2851 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2852
2852
2853 #Correct phases
2853 #Correct phases
2854 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2854 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2855 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2855 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2856
2856
2857 if indDer[0].shape[0] > 0:
2857 if indDer[0].shape[0] > 0:
2858 for i in range(indDer[0].shape[0]):
2858 for i in range(indDer[0].shape[0]):
2859 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2859 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2860 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2860 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2861
2861
2862 # for j in range(numSides):
2862 # for j in range(numSides):
2863 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2863 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2864 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2864 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2865 #
2865 #
2866 #Linear
2866 #Linear
2867 phaseInt = numpy.zeros((numPairs,1))
2867 phaseInt = numpy.zeros((numPairs,1))
2868 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2868 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2869 for j in range(numPairs):
2869 for j in range(numPairs):
2870 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2870 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2871 phaseInt[j] = fit[1]
2871 phaseInt[j] = fit[1]
2872 #Phase Differences
2872 #Phase Differences
2873 phaseDiff = phaseInt - phaseCCF[:,2,:]
2873 phaseDiff = phaseInt - phaseCCF[:,2,:]
2874 phaseArrival = phaseInt.reshape(phaseInt.size)
2874 phaseArrival = phaseInt.reshape(phaseInt.size)
2875
2875
2876 #Dealias
2876 #Dealias
2877 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2877 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2878 # indAlias = numpy.where(phaseArrival > numpy.pi)
2878 # indAlias = numpy.where(phaseArrival > numpy.pi)
2879 # phaseArrival[indAlias] -= 2*numpy.pi
2879 # phaseArrival[indAlias] -= 2*numpy.pi
2880 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2880 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2881 # phaseArrival[indAlias] += 2*numpy.pi
2881 # phaseArrival[indAlias] += 2*numpy.pi
2882
2882
2883 return phaseDiff, phaseArrival
2883 return phaseDiff, phaseArrival
2884
2884
2885 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2885 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2886 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2886 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2887 #find the phase shifts of each channel over 1 second intervals
2887 #find the phase shifts of each channel over 1 second intervals
2888 #only look at ranges below the beacon signal
2888 #only look at ranges below the beacon signal
2889 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2889 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2890 numBlocks = int(volts.shape[1]/numProfPerBlock)
2890 numBlocks = int(volts.shape[1]/numProfPerBlock)
2891 numHeights = volts.shape[2]
2891 numHeights = volts.shape[2]
2892 nChannel = volts.shape[0]
2892 nChannel = volts.shape[0]
2893 voltsCohDet = volts.copy()
2893 voltsCohDet = volts.copy()
2894
2894
2895 pairsarray = numpy.array(pairslist)
2895 pairsarray = numpy.array(pairslist)
2896 indSides = pairsarray[:,1]
2896 indSides = pairsarray[:,1]
2897 # indSides = numpy.array(range(nChannel))
2897 # indSides = numpy.array(range(nChannel))
2898 # indSides = numpy.delete(indSides, indCenter)
2898 # indSides = numpy.delete(indSides, indCenter)
2899 #
2899 #
2900 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2900 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2901 listBlocks = numpy.array_split(volts, numBlocks, 1)
2901 listBlocks = numpy.array_split(volts, numBlocks, 1)
2902
2902
2903 startInd = 0
2903 startInd = 0
2904 endInd = 0
2904 endInd = 0
2905
2905
2906 for i in range(numBlocks):
2906 for i in range(numBlocks):
2907 startInd = endInd
2907 startInd = endInd
2908 endInd = endInd + listBlocks[i].shape[1]
2908 endInd = endInd + listBlocks[i].shape[1]
2909
2909
2910 arrayBlock = listBlocks[i]
2910 arrayBlock = listBlocks[i]
2911 # arrayBlockCenter = listCenter[i]
2911 # arrayBlockCenter = listCenter[i]
2912
2912
2913 #Estimate the Phase Difference
2913 #Estimate the Phase Difference
2914 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2914 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2915 #Phase Difference RMS
2915 #Phase Difference RMS
2916 arrayPhaseRMS = numpy.abs(phaseDiff)
2916 arrayPhaseRMS = numpy.abs(phaseDiff)
2917 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2917 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2918 indPhase = numpy.where(phaseRMSaux==4)
2918 indPhase = numpy.where(phaseRMSaux==4)
2919 #Shifting
2919 #Shifting
2920 if indPhase[0].shape[0] > 0:
2920 if indPhase[0].shape[0] > 0:
2921 for j in range(indSides.size):
2921 for j in range(indSides.size):
2922 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2922 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2923 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2923 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2924
2924
2925 return voltsCohDet
2925 return voltsCohDet
2926
2926
2927 def __calculateCCF(self, volts, pairslist ,laglist):
2927 def __calculateCCF(self, volts, pairslist ,laglist):
2928
2928
2929 nHeights = volts.shape[2]
2929 nHeights = volts.shape[2]
2930 nPoints = volts.shape[1]
2930 nPoints = volts.shape[1]
2931 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2931 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2932
2932
2933 for i in range(len(pairslist)):
2933 for i in range(len(pairslist)):
2934 volts1 = volts[pairslist[i][0]]
2934 volts1 = volts[pairslist[i][0]]
2935 volts2 = volts[pairslist[i][1]]
2935 volts2 = volts[pairslist[i][1]]
2936
2936
2937 for t in range(len(laglist)):
2937 for t in range(len(laglist)):
2938 idxT = laglist[t]
2938 idxT = laglist[t]
2939 if idxT >= 0:
2939 if idxT >= 0:
2940 vStacked = numpy.vstack((volts2[idxT:,:],
2940 vStacked = numpy.vstack((volts2[idxT:,:],
2941 numpy.zeros((idxT, nHeights),dtype='complex')))
2941 numpy.zeros((idxT, nHeights),dtype='complex')))
2942 else:
2942 else:
2943 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2943 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2944 volts2[:(nPoints + idxT),:]))
2944 volts2[:(nPoints + idxT),:]))
2945 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2945 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2946
2946
2947 vStacked = None
2947 vStacked = None
2948 return voltsCCF
2948 return voltsCCF
2949
2949
2950 def __getNoise(self, power, timeSegment, timeInterval):
2950 def __getNoise(self, power, timeSegment, timeInterval):
2951 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2951 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2952 numBlocks = int(power.shape[0]/numProfPerBlock)
2952 numBlocks = int(power.shape[0]/numProfPerBlock)
2953 numHeights = power.shape[1]
2953 numHeights = power.shape[1]
2954
2954
2955 listPower = numpy.array_split(power, numBlocks, 0)
2955 listPower = numpy.array_split(power, numBlocks, 0)
2956 noise = numpy.zeros((power.shape[0], power.shape[1]))
2956 noise = numpy.zeros((power.shape[0], power.shape[1]))
2957 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2957 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2958
2958
2959 startInd = 0
2959 startInd = 0
2960 endInd = 0
2960 endInd = 0
2961
2961
2962 for i in range(numBlocks): #split por canal
2962 for i in range(numBlocks): #split por canal
2963 startInd = endInd
2963 startInd = endInd
2964 endInd = endInd + listPower[i].shape[0]
2964 endInd = endInd + listPower[i].shape[0]
2965
2965
2966 arrayBlock = listPower[i]
2966 arrayBlock = listPower[i]
2967 noiseAux = numpy.mean(arrayBlock, 0)
2967 noiseAux = numpy.mean(arrayBlock, 0)
2968 # noiseAux = numpy.median(noiseAux)
2968 # noiseAux = numpy.median(noiseAux)
2969 # noiseAux = numpy.mean(arrayBlock)
2969 # noiseAux = numpy.mean(arrayBlock)
2970 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2970 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2971
2971
2972 noiseAux1 = numpy.mean(arrayBlock)
2972 noiseAux1 = numpy.mean(arrayBlock)
2973 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2973 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2974
2974
2975 return noise, noise1
2975 return noise, noise1
2976
2976
2977 def __findMeteors(self, power, thresh):
2977 def __findMeteors(self, power, thresh):
2978 nProf = power.shape[0]
2978 nProf = power.shape[0]
2979 nHeights = power.shape[1]
2979 nHeights = power.shape[1]
2980 listMeteors = []
2980 listMeteors = []
2981
2981
2982 for i in range(nHeights):
2982 for i in range(nHeights):
2983 powerAux = power[:,i]
2983 powerAux = power[:,i]
2984 threshAux = thresh[:,i]
2984 threshAux = thresh[:,i]
2985
2985
2986 indUPthresh = numpy.where(powerAux > threshAux)[0]
2986 indUPthresh = numpy.where(powerAux > threshAux)[0]
2987 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2987 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2988
2988
2989 j = 0
2989 j = 0
2990
2990
2991 while (j < indUPthresh.size - 2):
2991 while (j < indUPthresh.size - 2):
2992 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2992 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2993 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2993 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2994 indDNthresh = indDNthresh[indDNAux]
2994 indDNthresh = indDNthresh[indDNAux]
2995
2995
2996 if (indDNthresh.size > 0):
2996 if (indDNthresh.size > 0):
2997 indEnd = indDNthresh[0] - 1
2997 indEnd = indDNthresh[0] - 1
2998 indInit = indUPthresh[j]
2998 indInit = indUPthresh[j]
2999
2999
3000 meteor = powerAux[indInit:indEnd + 1]
3000 meteor = powerAux[indInit:indEnd + 1]
3001 indPeak = meteor.argmax() + indInit
3001 indPeak = meteor.argmax() + indInit
3002 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3002 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3003
3003
3004 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3004 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3005 j = numpy.where(indUPthresh == indEnd)[0] + 1
3005 j = numpy.where(indUPthresh == indEnd)[0] + 1
3006 else: j+=1
3006 else: j+=1
3007 else: j+=1
3007 else: j+=1
3008
3008
3009 return listMeteors
3009 return listMeteors
3010
3010
3011 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3011 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3012
3012
3013 arrayMeteors = numpy.asarray(listMeteors)
3013 arrayMeteors = numpy.asarray(listMeteors)
3014 listMeteors1 = []
3014 listMeteors1 = []
3015
3015
3016 while arrayMeteors.shape[0] > 0:
3016 while arrayMeteors.shape[0] > 0:
3017 FLAs = arrayMeteors[:,4]
3017 FLAs = arrayMeteors[:,4]
3018 maxFLA = FLAs.argmax()
3018 maxFLA = FLAs.argmax()
3019 listMeteors1.append(arrayMeteors[maxFLA,:])
3019 listMeteors1.append(arrayMeteors[maxFLA,:])
3020
3020
3021 MeteorInitTime = arrayMeteors[maxFLA,1]
3021 MeteorInitTime = arrayMeteors[maxFLA,1]
3022 MeteorEndTime = arrayMeteors[maxFLA,3]
3022 MeteorEndTime = arrayMeteors[maxFLA,3]
3023 MeteorHeight = arrayMeteors[maxFLA,0]
3023 MeteorHeight = arrayMeteors[maxFLA,0]
3024
3024
3025 #Check neighborhood
3025 #Check neighborhood
3026 maxHeightIndex = MeteorHeight + rangeLimit
3026 maxHeightIndex = MeteorHeight + rangeLimit
3027 minHeightIndex = MeteorHeight - rangeLimit
3027 minHeightIndex = MeteorHeight - rangeLimit
3028 minTimeIndex = MeteorInitTime - timeLimit
3028 minTimeIndex = MeteorInitTime - timeLimit
3029 maxTimeIndex = MeteorEndTime + timeLimit
3029 maxTimeIndex = MeteorEndTime + timeLimit
3030
3030
3031 #Check Heights
3031 #Check Heights
3032 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3032 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3033 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3033 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3034 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3034 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3035
3035
3036 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3036 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3037
3037
3038 return listMeteors1
3038 return listMeteors1
3039
3039
3040 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3040 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3041 numHeights = volts.shape[2]
3041 numHeights = volts.shape[2]
3042 nChannel = volts.shape[0]
3042 nChannel = volts.shape[0]
3043
3043
3044 thresholdPhase = thresh[0]
3044 thresholdPhase = thresh[0]
3045 thresholdNoise = thresh[1]
3045 thresholdNoise = thresh[1]
3046 thresholdDB = float(thresh[2])
3046 thresholdDB = float(thresh[2])
3047
3047
3048 thresholdDB1 = 10**(thresholdDB/10)
3048 thresholdDB1 = 10**(thresholdDB/10)
3049 pairsarray = numpy.array(pairslist)
3049 pairsarray = numpy.array(pairslist)
3050 indSides = pairsarray[:,1]
3050 indSides = pairsarray[:,1]
3051
3051
3052 pairslist1 = list(pairslist)
3052 pairslist1 = list(pairslist)
3053 pairslist1.append((0,1))
3053 pairslist1.append((0,1))
3054 pairslist1.append((3,4))
3054 pairslist1.append((3,4))
3055
3055
3056 listMeteors1 = []
3056 listMeteors1 = []
3057 listPowerSeries = []
3057 listPowerSeries = []
3058 listVoltageSeries = []
3058 listVoltageSeries = []
3059 #volts has the war data
3059 #volts has the war data
3060
3060
3061 if frequency == 30e6:
3061 if frequency == 30e6:
3062 timeLag = 45*10**-3
3062 timeLag = 45*10**-3
3063 else:
3063 else:
3064 timeLag = 15*10**-3
3064 timeLag = 15*10**-3
3065 lag = numpy.ceil(timeLag/timeInterval)
3065 lag = numpy.ceil(timeLag/timeInterval)
3066
3066
3067 for i in range(len(listMeteors)):
3067 for i in range(len(listMeteors)):
3068
3068
3069 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3069 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3070 meteorAux = numpy.zeros(16)
3070 meteorAux = numpy.zeros(16)
3071
3071
3072 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3072 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3073 mHeight = listMeteors[i][0]
3073 mHeight = listMeteors[i][0]
3074 mStart = listMeteors[i][1]
3074 mStart = listMeteors[i][1]
3075 mPeak = listMeteors[i][2]
3075 mPeak = listMeteors[i][2]
3076 mEnd = listMeteors[i][3]
3076 mEnd = listMeteors[i][3]
3077
3077
3078 #get the volt data between the start and end times of the meteor
3078 #get the volt data between the start and end times of the meteor
3079 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3079 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3080 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3080 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3081
3081
3082 #3.6. Phase Difference estimation
3082 #3.6. Phase Difference estimation
3083 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3083 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3084
3084
3085 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3085 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3086 #meteorVolts0.- all Channels, all Profiles
3086 #meteorVolts0.- all Channels, all Profiles
3087 meteorVolts0 = volts[:,:,mHeight]
3087 meteorVolts0 = volts[:,:,mHeight]
3088 meteorThresh = noise[:,mHeight]*thresholdNoise
3088 meteorThresh = noise[:,mHeight]*thresholdNoise
3089 meteorNoise = noise[:,mHeight]
3089 meteorNoise = noise[:,mHeight]
3090 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3090 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3091 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3091 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3092
3092
3093 #Times reestimation
3093 #Times reestimation
3094 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3094 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3095 if mStart1.size > 0:
3095 if mStart1.size > 0:
3096 mStart1 = mStart1[-1] + 1
3096 mStart1 = mStart1[-1] + 1
3097
3097
3098 else:
3098 else:
3099 mStart1 = mPeak
3099 mStart1 = mPeak
3100
3100
3101 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3101 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3102 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3102 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3103 if mEndDecayTime1.size == 0:
3103 if mEndDecayTime1.size == 0:
3104 mEndDecayTime1 = powerNet0.size
3104 mEndDecayTime1 = powerNet0.size
3105 else:
3105 else:
3106 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3106 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3107 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3107 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3108
3108
3109 #meteorVolts1.- all Channels, from start to end
3109 #meteorVolts1.- all Channels, from start to end
3110 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3110 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3111 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3111 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3112 if meteorVolts2.shape[1] == 0:
3112 if meteorVolts2.shape[1] == 0:
3113 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3113 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3114 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3114 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3115 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3115 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3116 ##################### END PARAMETERS REESTIMATION #########################
3116 ##################### END PARAMETERS REESTIMATION #########################
3117
3117
3118 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3118 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3119 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3119 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3120 if meteorVolts2.shape[1] > 0:
3120 if meteorVolts2.shape[1] > 0:
3121 #Phase Difference re-estimation
3121 #Phase Difference re-estimation
3122 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3122 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3123 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3123 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3124 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3124 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3125 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3125 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3126 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3126 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3127
3127
3128 #Phase Difference RMS
3128 #Phase Difference RMS
3129 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3129 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3130 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3130 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3131 #Data from Meteor
3131 #Data from Meteor
3132 mPeak1 = powerNet1.argmax() + mStart1
3132 mPeak1 = powerNet1.argmax() + mStart1
3133 mPeakPower1 = powerNet1.max()
3133 mPeakPower1 = powerNet1.max()
3134 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3134 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3135 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3135 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3136 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3136 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3137 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3137 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3138 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3138 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3139 #Vectorize
3139 #Vectorize
3140 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3140 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3141 meteorAux[7:11] = phaseDiffint[0:4]
3141 meteorAux[7:11] = phaseDiffint[0:4]
3142
3142
3143 #Rejection Criterions
3143 #Rejection Criterions
3144 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3144 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3145 meteorAux[-1] = 17
3145 meteorAux[-1] = 17
3146 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3146 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3147 meteorAux[-1] = 1
3147 meteorAux[-1] = 1
3148
3148
3149
3149
3150 else:
3150 else:
3151 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3151 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3152 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3152 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3153 PowerSeries = 0
3153 PowerSeries = 0
3154
3154
3155 listMeteors1.append(meteorAux)
3155 listMeteors1.append(meteorAux)
3156 listPowerSeries.append(PowerSeries)
3156 listPowerSeries.append(PowerSeries)
3157 listVoltageSeries.append(meteorVolts1)
3157 listVoltageSeries.append(meteorVolts1)
3158
3158
3159 return listMeteors1, listPowerSeries, listVoltageSeries
3159 return listMeteors1, listPowerSeries, listVoltageSeries
3160
3160
3161 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3161 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3162
3162
3163 threshError = 10
3163 threshError = 10
3164 #Depending if it is 30 or 50 MHz
3164 #Depending if it is 30 or 50 MHz
3165 if frequency == 30e6:
3165 if frequency == 30e6:
3166 timeLag = 45*10**-3
3166 timeLag = 45*10**-3
3167 else:
3167 else:
3168 timeLag = 15*10**-3
3168 timeLag = 15*10**-3
3169 lag = numpy.ceil(timeLag/timeInterval)
3169 lag = numpy.ceil(timeLag/timeInterval)
3170
3170
3171 listMeteors1 = []
3171 listMeteors1 = []
3172
3172
3173 for i in range(len(listMeteors)):
3173 for i in range(len(listMeteors)):
3174 meteorPower = listPower[i]
3174 meteorPower = listPower[i]
3175 meteorAux = listMeteors[i]
3175 meteorAux = listMeteors[i]
3176
3176
3177 if meteorAux[-1] == 0:
3177 if meteorAux[-1] == 0:
3178
3178
3179 try:
3179 try:
3180 indmax = meteorPower.argmax()
3180 indmax = meteorPower.argmax()
3181 indlag = indmax + lag
3181 indlag = indmax + lag
3182
3182
3183 y = meteorPower[indlag:]
3183 y = meteorPower[indlag:]
3184 x = numpy.arange(0, y.size)*timeLag
3184 x = numpy.arange(0, y.size)*timeLag
3185
3185
3186 #first guess
3186 #first guess
3187 a = y[0]
3187 a = y[0]
3188 tau = timeLag
3188 tau = timeLag
3189 #exponential fit
3189 #exponential fit
3190 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3190 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3191 y1 = self.__exponential_function(x, *popt)
3191 y1 = self.__exponential_function(x, *popt)
3192 #error estimation
3192 #error estimation
3193 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3193 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3194
3194
3195 decayTime = popt[1]
3195 decayTime = popt[1]
3196 riseTime = indmax*timeInterval
3196 riseTime = indmax*timeInterval
3197 meteorAux[11:13] = [decayTime, error]
3197 meteorAux[11:13] = [decayTime, error]
3198
3198
3199 #Table items 7, 8 and 11
3199 #Table items 7, 8 and 11
3200 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3200 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3201 meteorAux[-1] = 7
3201 meteorAux[-1] = 7
3202 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3202 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3203 meteorAux[-1] = 8
3203 meteorAux[-1] = 8
3204 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3204 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3205 meteorAux[-1] = 11
3205 meteorAux[-1] = 11
3206
3206
3207
3207
3208 except:
3208 except:
3209 meteorAux[-1] = 11
3209 meteorAux[-1] = 11
3210
3210
3211
3211
3212 listMeteors1.append(meteorAux)
3212 listMeteors1.append(meteorAux)
3213
3213
3214 return listMeteors1
3214 return listMeteors1
3215
3215
3216 #Exponential Function
3216 #Exponential Function
3217
3217
3218 def __exponential_function(self, x, a, tau):
3218 def __exponential_function(self, x, a, tau):
3219 y = a*numpy.exp(-x/tau)
3219 y = a*numpy.exp(-x/tau)
3220 return y
3220 return y
3221
3221
3222 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3222 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3223
3223
3224 pairslist1 = list(pairslist)
3224 pairslist1 = list(pairslist)
3225 pairslist1.append((0,1))
3225 pairslist1.append((0,1))
3226 pairslist1.append((3,4))
3226 pairslist1.append((3,4))
3227 numPairs = len(pairslist1)
3227 numPairs = len(pairslist1)
3228 #Time Lag
3228 #Time Lag
3229 timeLag = 45*10**-3
3229 timeLag = 45*10**-3
3230 c = 3e8
3230 c = 3e8
3231 lag = numpy.ceil(timeLag/timeInterval)
3231 lag = numpy.ceil(timeLag/timeInterval)
3232 freq = 30e6
3232 freq = 30e6
3233
3233
3234 listMeteors1 = []
3234 listMeteors1 = []
3235
3235
3236 for i in range(len(listMeteors)):
3236 for i in range(len(listMeteors)):
3237 meteorAux = listMeteors[i]
3237 meteorAux = listMeteors[i]
3238 if meteorAux[-1] == 0:
3238 if meteorAux[-1] == 0:
3239 mStart = listMeteors[i][1]
3239 mStart = listMeteors[i][1]
3240 mPeak = listMeteors[i][2]
3240 mPeak = listMeteors[i][2]
3241 mLag = mPeak - mStart + lag
3241 mLag = mPeak - mStart + lag
3242
3242
3243 #get the volt data between the start and end times of the meteor
3243 #get the volt data between the start and end times of the meteor
3244 meteorVolts = listVolts[i]
3244 meteorVolts = listVolts[i]
3245 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3245 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3246
3246
3247 #Get CCF
3247 #Get CCF
3248 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3248 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3249
3249
3250 #Method 2
3250 #Method 2
3251 slopes = numpy.zeros(numPairs)
3251 slopes = numpy.zeros(numPairs)
3252 time = numpy.array([-2,-1,1,2])*timeInterval
3252 time = numpy.array([-2,-1,1,2])*timeInterval
3253 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3253 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3254
3254
3255 #Correct phases
3255 #Correct phases
3256 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3256 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3257 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3257 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3258
3258
3259 if indDer[0].shape[0] > 0:
3259 if indDer[0].shape[0] > 0:
3260 for i in range(indDer[0].shape[0]):
3260 for i in range(indDer[0].shape[0]):
3261 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3261 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3262 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3262 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3263
3263
3264 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3264 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3265 for j in range(numPairs):
3265 for j in range(numPairs):
3266 fit = stats.linregress(time, angAllCCF[j,:])
3266 fit = stats.linregress(time, angAllCCF[j,:])
3267 slopes[j] = fit[0]
3267 slopes[j] = fit[0]
3268
3268
3269 #Remove Outlier
3269 #Remove Outlier
3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3271 # slopes = numpy.delete(slopes,indOut)
3271 # slopes = numpy.delete(slopes,indOut)
3272 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3272 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3273 # slopes = numpy.delete(slopes,indOut)
3273 # slopes = numpy.delete(slopes,indOut)
3274
3274
3275 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3275 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3276 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3276 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3277 meteorAux[-2] = radialError
3277 meteorAux[-2] = radialError
3278 meteorAux[-3] = radialVelocity
3278 meteorAux[-3] = radialVelocity
3279
3279
3280 #Setting Error
3280 #Setting Error
3281 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3281 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3282 if numpy.abs(radialVelocity) > 200:
3282 if numpy.abs(radialVelocity) > 200:
3283 meteorAux[-1] = 15
3283 meteorAux[-1] = 15
3284 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3284 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3285 elif radialError > radialStdThresh:
3285 elif radialError > radialStdThresh:
3286 meteorAux[-1] = 12
3286 meteorAux[-1] = 12
3287
3287
3288 listMeteors1.append(meteorAux)
3288 listMeteors1.append(meteorAux)
3289 return listMeteors1
3289 return listMeteors1
3290
3290
3291 def __setNewArrays(self, listMeteors, date, heiRang):
3291 def __setNewArrays(self, listMeteors, date, heiRang):
3292
3292
3293 #New arrays
3293 #New arrays
3294 arrayMeteors = numpy.array(listMeteors)
3294 arrayMeteors = numpy.array(listMeteors)
3295 arrayParameters = numpy.zeros((len(listMeteors), 13))
3295 arrayParameters = numpy.zeros((len(listMeteors), 13))
3296
3296
3297 #Date inclusion
3297 #Date inclusion
3298 # date = re.findall(r'\((.*?)\)', date)
3298 # date = re.findall(r'\((.*?)\)', date)
3299 # date = date[0].split(',')
3299 # date = date[0].split(',')
3300 # date = map(int, date)
3300 # date = map(int, date)
3301 #
3301 #
3302 # if len(date)<6:
3302 # if len(date)<6:
3303 # date.append(0)
3303 # date.append(0)
3304 #
3304 #
3305 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3305 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3306 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3306 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3307 arrayDate = numpy.tile(date, (len(listMeteors)))
3307 arrayDate = numpy.tile(date, (len(listMeteors)))
3308
3308
3309 #Meteor array
3309 #Meteor array
3310 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3310 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3311 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3311 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3312
3312
3313 #Parameters Array
3313 #Parameters Array
3314 arrayParameters[:,0] = arrayDate #Date
3314 arrayParameters[:,0] = arrayDate #Date
3315 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3315 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3316 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3316 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3317 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3317 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3318 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3318 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3319
3319
3320
3320
3321 return arrayParameters
3321 return arrayParameters
3322
3322
3323 class CorrectSMPhases(Operation):
3323 class CorrectSMPhases(Operation):
3324
3324
3325 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3325 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3326
3326
3327 arrayParameters = dataOut.data_param
3327 arrayParameters = dataOut.data_param
3328 pairsList = []
3328 pairsList = []
3329 pairx = (0,1)
3329 pairx = (0,1)
3330 pairy = (2,3)
3330 pairy = (2,3)
3331 pairsList.append(pairx)
3331 pairsList.append(pairx)
3332 pairsList.append(pairy)
3332 pairsList.append(pairy)
3333 jph = numpy.zeros(4)
3333 jph = numpy.zeros(4)
3334
3334
3335 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3335 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3336 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3336 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3337 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3337 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3338
3338
3339 meteorOps = SMOperations()
3339 meteorOps = SMOperations()
3340 if channelPositions is None:
3340 if channelPositions is None:
3341 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3341 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3342 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3342 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3343
3343
3344 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3344 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3345 h = (hmin,hmax)
3345 h = (hmin,hmax)
3346
3346
3347 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3347 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3348
3348
3349 dataOut.data_param = arrayParameters
3349 dataOut.data_param = arrayParameters
3350 return
3350 return
3351
3351
3352 class SMPhaseCalibration(Operation):
3352 class SMPhaseCalibration(Operation):
3353
3353
3354 __buffer = None
3354 __buffer = None
3355
3355
3356 __initime = None
3356 __initime = None
3357
3357
3358 __dataReady = False
3358 __dataReady = False
3359
3359
3360 __isConfig = False
3360 __isConfig = False
3361
3361
3362 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3362 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3363
3363
3364 dataTime = currentTime + paramInterval
3364 dataTime = currentTime + paramInterval
3365 deltaTime = dataTime - initTime
3365 deltaTime = dataTime - initTime
3366
3366
3367 if deltaTime >= outputInterval or deltaTime < 0:
3367 if deltaTime >= outputInterval or deltaTime < 0:
3368 return True
3368 return True
3369
3369
3370 return False
3370 return False
3371
3371
3372 def __getGammas(self, pairs, d, phases):
3372 def __getGammas(self, pairs, d, phases):
3373 gammas = numpy.zeros(2)
3373 gammas = numpy.zeros(2)
3374
3374
3375 for i in range(len(pairs)):
3375 for i in range(len(pairs)):
3376
3376
3377 pairi = pairs[i]
3377 pairi = pairs[i]
3378
3378
3379 phip3 = phases[:,pairi[0]]
3379 phip3 = phases[:,pairi[0]]
3380 d3 = d[pairi[0]]
3380 d3 = d[pairi[0]]
3381 phip2 = phases[:,pairi[1]]
3381 phip2 = phases[:,pairi[1]]
3382 d2 = d[pairi[1]]
3382 d2 = d[pairi[1]]
3383 #Calculating gamma
3383 #Calculating gamma
3384 # jdcos = alp1/(k*d1)
3384 # jdcos = alp1/(k*d1)
3385 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3385 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3386 jgamma = -phip2*d3/d2 - phip3
3386 jgamma = -phip2*d3/d2 - phip3
3387 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3387 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3388 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3388 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3389 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3389 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3390
3390
3391 #Revised distribution
3391 #Revised distribution
3392 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3392 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3393
3393
3394 #Histogram
3394 #Histogram
3395 nBins = 64
3395 nBins = 64
3396 rmin = -0.5*numpy.pi
3396 rmin = -0.5*numpy.pi
3397 rmax = 0.5*numpy.pi
3397 rmax = 0.5*numpy.pi
3398 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3398 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3399
3399
3400 meteorsY = phaseHisto[0]
3400 meteorsY = phaseHisto[0]
3401 phasesX = phaseHisto[1][:-1]
3401 phasesX = phaseHisto[1][:-1]
3402 width = phasesX[1] - phasesX[0]
3402 width = phasesX[1] - phasesX[0]
3403 phasesX += width/2
3403 phasesX += width/2
3404
3404
3405 #Gaussian aproximation
3405 #Gaussian aproximation
3406 bpeak = meteorsY.argmax()
3406 bpeak = meteorsY.argmax()
3407 peak = meteorsY.max()
3407 peak = meteorsY.max()
3408 jmin = bpeak - 5
3408 jmin = bpeak - 5
3409 jmax = bpeak + 5 + 1
3409 jmax = bpeak + 5 + 1
3410
3410
3411 if jmin<0:
3411 if jmin<0:
3412 jmin = 0
3412 jmin = 0
3413 jmax = 6
3413 jmax = 6
3414 elif jmax > meteorsY.size:
3414 elif jmax > meteorsY.size:
3415 jmin = meteorsY.size - 6
3415 jmin = meteorsY.size - 6
3416 jmax = meteorsY.size
3416 jmax = meteorsY.size
3417
3417
3418 x0 = numpy.array([peak,bpeak,50])
3418 x0 = numpy.array([peak,bpeak,50])
3419 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3419 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3420
3420
3421 #Gammas
3421 #Gammas
3422 gammas[i] = coeff[0][1]
3422 gammas[i] = coeff[0][1]
3423
3423
3424 return gammas
3424 return gammas
3425
3425
3426 def __residualFunction(self, coeffs, y, t):
3426 def __residualFunction(self, coeffs, y, t):
3427
3427
3428 return y - self.__gauss_function(t, coeffs)
3428 return y - self.__gauss_function(t, coeffs)
3429
3429
3430 def __gauss_function(self, t, coeffs):
3430 def __gauss_function(self, t, coeffs):
3431
3431
3432 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3432 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3433
3433
3434 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3434 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3435 meteorOps = SMOperations()
3435 meteorOps = SMOperations()
3436 nchan = 4
3436 nchan = 4
3437 pairx = pairsList[0] #x es 0
3437 pairx = pairsList[0] #x es 0
3438 pairy = pairsList[1] #y es 1
3438 pairy = pairsList[1] #y es 1
3439 center_xangle = 0
3439 center_xangle = 0
3440 center_yangle = 0
3440 center_yangle = 0
3441 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3441 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3442 ntimes = len(range_angle)
3442 ntimes = len(range_angle)
3443
3443
3444 nstepsx = 20
3444 nstepsx = 20
3445 nstepsy = 20
3445 nstepsy = 20
3446
3446
3447 for iz in range(ntimes):
3447 for iz in range(ntimes):
3448 min_xangle = -range_angle[iz]/2 + center_xangle
3448 min_xangle = -range_angle[iz]/2 + center_xangle
3449 max_xangle = range_angle[iz]/2 + center_xangle
3449 max_xangle = range_angle[iz]/2 + center_xangle
3450 min_yangle = -range_angle[iz]/2 + center_yangle
3450 min_yangle = -range_angle[iz]/2 + center_yangle
3451 max_yangle = range_angle[iz]/2 + center_yangle
3451 max_yangle = range_angle[iz]/2 + center_yangle
3452
3452
3453 inc_x = (max_xangle-min_xangle)/nstepsx
3453 inc_x = (max_xangle-min_xangle)/nstepsx
3454 inc_y = (max_yangle-min_yangle)/nstepsy
3454 inc_y = (max_yangle-min_yangle)/nstepsy
3455
3455
3456 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3456 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3457 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3457 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3458 penalty = numpy.zeros((nstepsx,nstepsy))
3458 penalty = numpy.zeros((nstepsx,nstepsy))
3459 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3459 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3460 jph = numpy.zeros(nchan)
3460 jph = numpy.zeros(nchan)
3461
3461
3462 # Iterations looking for the offset
3462 # Iterations looking for the offset
3463 for iy in range(int(nstepsy)):
3463 for iy in range(int(nstepsy)):
3464 for ix in range(int(nstepsx)):
3464 for ix in range(int(nstepsx)):
3465 d3 = d[pairsList[1][0]]
3465 d3 = d[pairsList[1][0]]
3466 d2 = d[pairsList[1][1]]
3466 d2 = d[pairsList[1][1]]
3467 d5 = d[pairsList[0][0]]
3467 d5 = d[pairsList[0][0]]
3468 d4 = d[pairsList[0][1]]
3468 d4 = d[pairsList[0][1]]
3469
3469
3470 alp2 = alpha_y[iy] #gamma 1
3470 alp2 = alpha_y[iy] #gamma 1
3471 alp4 = alpha_x[ix] #gamma 0
3471 alp4 = alpha_x[ix] #gamma 0
3472
3472
3473 alp3 = -alp2*d3/d2 - gammas[1]
3473 alp3 = -alp2*d3/d2 - gammas[1]
3474 alp5 = -alp4*d5/d4 - gammas[0]
3474 alp5 = -alp4*d5/d4 - gammas[0]
3475 # jph[pairy[1]] = alpha_y[iy]
3475 # jph[pairy[1]] = alpha_y[iy]
3476 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3476 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3477
3477
3478 # jph[pairx[1]] = alpha_x[ix]
3478 # jph[pairx[1]] = alpha_x[ix]
3479 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3479 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3480 jph[pairsList[0][1]] = alp4
3480 jph[pairsList[0][1]] = alp4
3481 jph[pairsList[0][0]] = alp5
3481 jph[pairsList[0][0]] = alp5
3482 jph[pairsList[1][0]] = alp3
3482 jph[pairsList[1][0]] = alp3
3483 jph[pairsList[1][1]] = alp2
3483 jph[pairsList[1][1]] = alp2
3484 jph_array[:,ix,iy] = jph
3484 jph_array[:,ix,iy] = jph
3485 # d = [2.0,2.5,2.5,2.0]
3485 # d = [2.0,2.5,2.5,2.0]
3486 #falta chequear si va a leer bien los meteoros
3486 #falta chequear si va a leer bien los meteoros
3487 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3487 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3488 error = meteorsArray1[:,-1]
3488 error = meteorsArray1[:,-1]
3489 ind1 = numpy.where(error==0)[0]
3489 ind1 = numpy.where(error==0)[0]
3490 penalty[ix,iy] = ind1.size
3490 penalty[ix,iy] = ind1.size
3491
3491
3492 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3492 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3493 phOffset = jph_array[:,i,j]
3493 phOffset = jph_array[:,i,j]
3494
3494
3495 center_xangle = phOffset[pairx[1]]
3495 center_xangle = phOffset[pairx[1]]
3496 center_yangle = phOffset[pairy[1]]
3496 center_yangle = phOffset[pairy[1]]
3497
3497
3498 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3498 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3499 phOffset = phOffset*180/numpy.pi
3499 phOffset = phOffset*180/numpy.pi
3500 return phOffset
3500 return phOffset
3501
3501
3502
3502
3503 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3503 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3504
3504
3505 dataOut.flagNoData = True
3505 dataOut.flagNoData = True
3506 self.__dataReady = False
3506 self.__dataReady = False
3507 dataOut.outputInterval = nHours*3600
3507 dataOut.outputInterval = nHours*3600
3508
3508
3509 if self.__isConfig == False:
3509 if self.__isConfig == False:
3510 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3510 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3511 #Get Initial LTC time
3511 #Get Initial LTC time
3512 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3512 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3513 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3513 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3514
3514
3515 self.__isConfig = True
3515 self.__isConfig = True
3516
3516
3517 if self.__buffer is None:
3517 if self.__buffer is None:
3518 self.__buffer = dataOut.data_param.copy()
3518 self.__buffer = dataOut.data_param.copy()
3519
3519
3520 else:
3520 else:
3521 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3521 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3522
3522
3523 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3523 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3524
3524
3525 if self.__dataReady:
3525 if self.__dataReady:
3526 dataOut.utctimeInit = self.__initime
3526 dataOut.utctimeInit = self.__initime
3527 self.__initime += dataOut.outputInterval #to erase time offset
3527 self.__initime += dataOut.outputInterval #to erase time offset
3528
3528
3529 freq = dataOut.frequency
3529 freq = dataOut.frequency
3530 c = dataOut.C #m/s
3530 c = dataOut.C #m/s
3531 lamb = c/freq
3531 lamb = c/freq
3532 k = 2*numpy.pi/lamb
3532 k = 2*numpy.pi/lamb
3533 azimuth = 0
3533 azimuth = 0
3534 h = (hmin, hmax)
3534 h = (hmin, hmax)
3535 # pairs = ((0,1),(2,3)) #Estrella
3535 # pairs = ((0,1),(2,3)) #Estrella
3536 # pairs = ((1,0),(2,3)) #T
3536 # pairs = ((1,0),(2,3)) #T
3537
3537
3538 if channelPositions is None:
3538 if channelPositions is None:
3539 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3539 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3540 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3540 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3541 meteorOps = SMOperations()
3541 meteorOps = SMOperations()
3542 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3542 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3543
3543
3544 #Checking correct order of pairs
3544 #Checking correct order of pairs
3545 pairs = []
3545 pairs = []
3546 if distances[1] > distances[0]:
3546 if distances[1] > distances[0]:
3547 pairs.append((1,0))
3547 pairs.append((1,0))
3548 else:
3548 else:
3549 pairs.append((0,1))
3549 pairs.append((0,1))
3550
3550
3551 if distances[3] > distances[2]:
3551 if distances[3] > distances[2]:
3552 pairs.append((3,2))
3552 pairs.append((3,2))
3553 else:
3553 else:
3554 pairs.append((2,3))
3554 pairs.append((2,3))
3555 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3555 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3556
3556
3557 meteorsArray = self.__buffer
3557 meteorsArray = self.__buffer
3558 error = meteorsArray[:,-1]
3558 error = meteorsArray[:,-1]
3559 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3559 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3560 ind1 = numpy.where(boolError)[0]
3560 ind1 = numpy.where(boolError)[0]
3561 meteorsArray = meteorsArray[ind1,:]
3561 meteorsArray = meteorsArray[ind1,:]
3562 meteorsArray[:,-1] = 0
3562 meteorsArray[:,-1] = 0
3563 phases = meteorsArray[:,8:12]
3563 phases = meteorsArray[:,8:12]
3564
3564
3565 #Calculate Gammas
3565 #Calculate Gammas
3566 gammas = self.__getGammas(pairs, distances, phases)
3566 gammas = self.__getGammas(pairs, distances, phases)
3567 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3567 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3568 #Calculate Phases
3568 #Calculate Phases
3569 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3569 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3570 phasesOff = phasesOff.reshape((1,phasesOff.size))
3570 phasesOff = phasesOff.reshape((1,phasesOff.size))
3571 dataOut.data_output = -phasesOff
3571 dataOut.data_output = -phasesOff
3572 dataOut.flagNoData = False
3572 dataOut.flagNoData = False
3573 self.__buffer = None
3573 self.__buffer = None
3574
3574
3575
3575
3576 return
3576 return
3577
3577
3578 class SMOperations():
3578 class SMOperations():
3579
3579
3580 def __init__(self):
3580 def __init__(self):
3581
3581
3582 return
3582 return
3583
3583
3584 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3584 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3585
3585
3586 arrayParameters = arrayParameters0.copy()
3586 arrayParameters = arrayParameters0.copy()
3587 hmin = h[0]
3587 hmin = h[0]
3588 hmax = h[1]
3588 hmax = h[1]
3589
3589
3590 #Calculate AOA (Error N 3, 4)
3590 #Calculate AOA (Error N 3, 4)
3591 #JONES ET AL. 1998
3591 #JONES ET AL. 1998
3592 AOAthresh = numpy.pi/8
3592 AOAthresh = numpy.pi/8
3593 error = arrayParameters[:,-1]
3593 error = arrayParameters[:,-1]
3594 phases = -arrayParameters[:,8:12] + jph
3594 phases = -arrayParameters[:,8:12] + jph
3595 # phases = numpy.unwrap(phases)
3595 # phases = numpy.unwrap(phases)
3596 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3596 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3597
3597
3598 #Calculate Heights (Error N 13 and 14)
3598 #Calculate Heights (Error N 13 and 14)
3599 error = arrayParameters[:,-1]
3599 error = arrayParameters[:,-1]
3600 Ranges = arrayParameters[:,1]
3600 Ranges = arrayParameters[:,1]
3601 zenith = arrayParameters[:,4]
3601 zenith = arrayParameters[:,4]
3602 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3602 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3603
3603
3604 #----------------------- Get Final data ------------------------------------
3604 #----------------------- Get Final data ------------------------------------
3605 # error = arrayParameters[:,-1]
3605 # error = arrayParameters[:,-1]
3606 # ind1 = numpy.where(error==0)[0]
3606 # ind1 = numpy.where(error==0)[0]
3607 # arrayParameters = arrayParameters[ind1,:]
3607 # arrayParameters = arrayParameters[ind1,:]
3608
3608
3609 return arrayParameters
3609 return arrayParameters
3610
3610
3611 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3611 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3612
3612
3613 arrayAOA = numpy.zeros((phases.shape[0],3))
3613 arrayAOA = numpy.zeros((phases.shape[0],3))
3614 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3614 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3615
3615
3616 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3616 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3617 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3617 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3618 arrayAOA[:,2] = cosDirError
3618 arrayAOA[:,2] = cosDirError
3619
3619
3620 azimuthAngle = arrayAOA[:,0]
3620 azimuthAngle = arrayAOA[:,0]
3621 zenithAngle = arrayAOA[:,1]
3621 zenithAngle = arrayAOA[:,1]
3622
3622
3623 #Setting Error
3623 #Setting Error
3624 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3624 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3625 error[indError] = 0
3625 error[indError] = 0
3626 #Number 3: AOA not fesible
3626 #Number 3: AOA not fesible
3627 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3627 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3628 error[indInvalid] = 3
3628 error[indInvalid] = 3
3629 #Number 4: Large difference in AOAs obtained from different antenna baselines
3629 #Number 4: Large difference in AOAs obtained from different antenna baselines
3630 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3630 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3631 error[indInvalid] = 4
3631 error[indInvalid] = 4
3632 return arrayAOA, error
3632 return arrayAOA, error
3633
3633
3634 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3634 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3635
3635
3636 #Initializing some variables
3636 #Initializing some variables
3637 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3637 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3638 ang_aux = ang_aux.reshape(1,ang_aux.size)
3638 ang_aux = ang_aux.reshape(1,ang_aux.size)
3639
3639
3640 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3640 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3641 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3641 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3642
3642
3643
3643
3644 for i in range(2):
3644 for i in range(2):
3645 ph0 = arrayPhase[:,pairsList[i][0]]
3645 ph0 = arrayPhase[:,pairsList[i][0]]
3646 ph1 = arrayPhase[:,pairsList[i][1]]
3646 ph1 = arrayPhase[:,pairsList[i][1]]
3647 d0 = distances[pairsList[i][0]]
3647 d0 = distances[pairsList[i][0]]
3648 d1 = distances[pairsList[i][1]]
3648 d1 = distances[pairsList[i][1]]
3649
3649
3650 ph0_aux = ph0 + ph1
3650 ph0_aux = ph0 + ph1
3651 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3651 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3652 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3652 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3653 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3653 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3654 #First Estimation
3654 #First Estimation
3655 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3655 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3656
3656
3657 #Most-Accurate Second Estimation
3657 #Most-Accurate Second Estimation
3658 phi1_aux = ph0 - ph1
3658 phi1_aux = ph0 - ph1
3659 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3659 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3660 #Direction Cosine 1
3660 #Direction Cosine 1
3661 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3661 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3662
3662
3663 #Searching the correct Direction Cosine
3663 #Searching the correct Direction Cosine
3664 cosdir0_aux = cosdir0[:,i]
3664 cosdir0_aux = cosdir0[:,i]
3665 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3665 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3666 #Minimum Distance
3666 #Minimum Distance
3667 cosDiff = (cosdir1 - cosdir0_aux)**2
3667 cosDiff = (cosdir1 - cosdir0_aux)**2
3668 indcos = cosDiff.argmin(axis = 1)
3668 indcos = cosDiff.argmin(axis = 1)
3669 #Saving Value obtained
3669 #Saving Value obtained
3670 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3670 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3671
3671
3672 return cosdir0, cosdir
3672 return cosdir0, cosdir
3673
3673
3674 def __calculateAOA(self, cosdir, azimuth):
3674 def __calculateAOA(self, cosdir, azimuth):
3675 cosdirX = cosdir[:,0]
3675 cosdirX = cosdir[:,0]
3676 cosdirY = cosdir[:,1]
3676 cosdirY = cosdir[:,1]
3677
3677
3678 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3678 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3679 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3679 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3680 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3680 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3681
3681
3682 return angles
3682 return angles
3683
3683
3684 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3684 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3685
3685
3686 Ramb = 375 #Ramb = c/(2*PRF)
3686 Ramb = 375 #Ramb = c/(2*PRF)
3687 Re = 6371 #Earth Radius
3687 Re = 6371 #Earth Radius
3688 heights = numpy.zeros(Ranges.shape)
3688 heights = numpy.zeros(Ranges.shape)
3689
3689
3690 R_aux = numpy.array([0,1,2])*Ramb
3690 R_aux = numpy.array([0,1,2])*Ramb
3691 R_aux = R_aux.reshape(1,R_aux.size)
3691 R_aux = R_aux.reshape(1,R_aux.size)
3692
3692
3693 Ranges = Ranges.reshape(Ranges.size,1)
3693 Ranges = Ranges.reshape(Ranges.size,1)
3694
3694
3695 Ri = Ranges + R_aux
3695 Ri = Ranges + R_aux
3696 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3696 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3697
3697
3698 #Check if there is a height between 70 and 110 km
3698 #Check if there is a height between 70 and 110 km
3699 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3699 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3700 ind_h = numpy.where(h_bool == 1)[0]
3700 ind_h = numpy.where(h_bool == 1)[0]
3701
3701
3702 hCorr = hi[ind_h, :]
3702 hCorr = hi[ind_h, :]
3703 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3703 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3704
3704
3705 hCorr = hi[ind_hCorr][:len(ind_h)]
3705 hCorr = hi[ind_hCorr][:len(ind_h)]
3706 heights[ind_h] = hCorr
3706 heights[ind_h] = hCorr
3707
3707
3708 #Setting Error
3708 #Setting Error
3709 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3709 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3710 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3710 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3711 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3711 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3712 error[indError] = 0
3712 error[indError] = 0
3713 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3713 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3714 error[indInvalid2] = 14
3714 error[indInvalid2] = 14
3715 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3715 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3716 error[indInvalid1] = 13
3716 error[indInvalid1] = 13
3717
3717
3718 return heights, error
3718 return heights, error
3719
3719
3720 def getPhasePairs(self, channelPositions):
3720 def getPhasePairs(self, channelPositions):
3721 chanPos = numpy.array(channelPositions)
3721 chanPos = numpy.array(channelPositions)
3722 listOper = list(itertools.combinations(list(range(5)),2))
3722 listOper = list(itertools.combinations(list(range(5)),2))
3723
3723
3724 distances = numpy.zeros(4)
3724 distances = numpy.zeros(4)
3725 axisX = []
3725 axisX = []
3726 axisY = []
3726 axisY = []
3727 distX = numpy.zeros(3)
3727 distX = numpy.zeros(3)
3728 distY = numpy.zeros(3)
3728 distY = numpy.zeros(3)
3729 ix = 0
3729 ix = 0
3730 iy = 0
3730 iy = 0
3731
3731
3732 pairX = numpy.zeros((2,2))
3732 pairX = numpy.zeros((2,2))
3733 pairY = numpy.zeros((2,2))
3733 pairY = numpy.zeros((2,2))
3734
3734
3735 for i in range(len(listOper)):
3735 for i in range(len(listOper)):
3736 pairi = listOper[i]
3736 pairi = listOper[i]
3737
3737
3738 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3738 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3739
3739
3740 if posDif[0] == 0:
3740 if posDif[0] == 0:
3741 axisY.append(pairi)
3741 axisY.append(pairi)
3742 distY[iy] = posDif[1]
3742 distY[iy] = posDif[1]
3743 iy += 1
3743 iy += 1
3744 elif posDif[1] == 0:
3744 elif posDif[1] == 0:
3745 axisX.append(pairi)
3745 axisX.append(pairi)
3746 distX[ix] = posDif[0]
3746 distX[ix] = posDif[0]
3747 ix += 1
3747 ix += 1
3748
3748
3749 for i in range(2):
3749 for i in range(2):
3750 if i==0:
3750 if i==0:
3751 dist0 = distX
3751 dist0 = distX
3752 axis0 = axisX
3752 axis0 = axisX
3753 else:
3753 else:
3754 dist0 = distY
3754 dist0 = distY
3755 axis0 = axisY
3755 axis0 = axisY
3756
3756
3757 side = numpy.argsort(dist0)[:-1]
3757 side = numpy.argsort(dist0)[:-1]
3758 axis0 = numpy.array(axis0)[side,:]
3758 axis0 = numpy.array(axis0)[side,:]
3759 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3759 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3760 axis1 = numpy.unique(numpy.reshape(axis0,4))
3760 axis1 = numpy.unique(numpy.reshape(axis0,4))
3761 side = axis1[axis1 != chanC]
3761 side = axis1[axis1 != chanC]
3762 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3762 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3763 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3763 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3764 if diff1<0:
3764 if diff1<0:
3765 chan2 = side[0]
3765 chan2 = side[0]
3766 d2 = numpy.abs(diff1)
3766 d2 = numpy.abs(diff1)
3767 chan1 = side[1]
3767 chan1 = side[1]
3768 d1 = numpy.abs(diff2)
3768 d1 = numpy.abs(diff2)
3769 else:
3769 else:
3770 chan2 = side[1]
3770 chan2 = side[1]
3771 d2 = numpy.abs(diff2)
3771 d2 = numpy.abs(diff2)
3772 chan1 = side[0]
3772 chan1 = side[0]
3773 d1 = numpy.abs(diff1)
3773 d1 = numpy.abs(diff1)
3774
3774
3775 if i==0:
3775 if i==0:
3776 chanCX = chanC
3776 chanCX = chanC
3777 chan1X = chan1
3777 chan1X = chan1
3778 chan2X = chan2
3778 chan2X = chan2
3779 distances[0:2] = numpy.array([d1,d2])
3779 distances[0:2] = numpy.array([d1,d2])
3780 else:
3780 else:
3781 chanCY = chanC
3781 chanCY = chanC
3782 chan1Y = chan1
3782 chan1Y = chan1
3783 chan2Y = chan2
3783 chan2Y = chan2
3784 distances[2:4] = numpy.array([d1,d2])
3784 distances[2:4] = numpy.array([d1,d2])
3785 # axisXsides = numpy.reshape(axisX[ix,:],4)
3785 # axisXsides = numpy.reshape(axisX[ix,:],4)
3786 #
3786 #
3787 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3787 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3788 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3788 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3789 #
3789 #
3790 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3790 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3791 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3791 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3792 # channel25X = int(pairX[0,ind25X])
3792 # channel25X = int(pairX[0,ind25X])
3793 # channel20X = int(pairX[1,ind20X])
3793 # channel20X = int(pairX[1,ind20X])
3794 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3794 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3795 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3795 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3796 # channel25Y = int(pairY[0,ind25Y])
3796 # channel25Y = int(pairY[0,ind25Y])
3797 # channel20Y = int(pairY[1,ind20Y])
3797 # channel20Y = int(pairY[1,ind20Y])
3798
3798
3799 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3799 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3800 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3800 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3801
3801
3802 return pairslist, distances
3802 return pairslist, distances
3803 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3803 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3804 #
3804 #
3805 # arrayAOA = numpy.zeros((phases.shape[0],3))
3805 # arrayAOA = numpy.zeros((phases.shape[0],3))
3806 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3806 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3807 #
3807 #
3808 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3808 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3809 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3809 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3810 # arrayAOA[:,2] = cosDirError
3810 # arrayAOA[:,2] = cosDirError
3811 #
3811 #
3812 # azimuthAngle = arrayAOA[:,0]
3812 # azimuthAngle = arrayAOA[:,0]
3813 # zenithAngle = arrayAOA[:,1]
3813 # zenithAngle = arrayAOA[:,1]
3814 #
3814 #
3815 # #Setting Error
3815 # #Setting Error
3816 # #Number 3: AOA not fesible
3816 # #Number 3: AOA not fesible
3817 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3817 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3818 # error[indInvalid] = 3
3818 # error[indInvalid] = 3
3819 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3819 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3820 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3820 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3821 # error[indInvalid] = 4
3821 # error[indInvalid] = 4
3822 # return arrayAOA, error
3822 # return arrayAOA, error
3823 #
3823 #
3824 # def __getDirectionCosines(self, arrayPhase, pairsList):
3824 # def __getDirectionCosines(self, arrayPhase, pairsList):
3825 #
3825 #
3826 # #Initializing some variables
3826 # #Initializing some variables
3827 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3827 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3828 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3828 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3829 #
3829 #
3830 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3830 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3831 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3831 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3832 #
3832 #
3833 #
3833 #
3834 # for i in range(2):
3834 # for i in range(2):
3835 # #First Estimation
3835 # #First Estimation
3836 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3836 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3837 # #Dealias
3837 # #Dealias
3838 # indcsi = numpy.where(phi0_aux > numpy.pi)
3838 # indcsi = numpy.where(phi0_aux > numpy.pi)
3839 # phi0_aux[indcsi] -= 2*numpy.pi
3839 # phi0_aux[indcsi] -= 2*numpy.pi
3840 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3840 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3841 # phi0_aux[indcsi] += 2*numpy.pi
3841 # phi0_aux[indcsi] += 2*numpy.pi
3842 # #Direction Cosine 0
3842 # #Direction Cosine 0
3843 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3843 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3844 #
3844 #
3845 # #Most-Accurate Second Estimation
3845 # #Most-Accurate Second Estimation
3846 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3846 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3847 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3847 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3848 # #Direction Cosine 1
3848 # #Direction Cosine 1
3849 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3849 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3850 #
3850 #
3851 # #Searching the correct Direction Cosine
3851 # #Searching the correct Direction Cosine
3852 # cosdir0_aux = cosdir0[:,i]
3852 # cosdir0_aux = cosdir0[:,i]
3853 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3853 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3854 # #Minimum Distance
3854 # #Minimum Distance
3855 # cosDiff = (cosdir1 - cosdir0_aux)**2
3855 # cosDiff = (cosdir1 - cosdir0_aux)**2
3856 # indcos = cosDiff.argmin(axis = 1)
3856 # indcos = cosDiff.argmin(axis = 1)
3857 # #Saving Value obtained
3857 # #Saving Value obtained
3858 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3858 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3859 #
3859 #
3860 # return cosdir0, cosdir
3860 # return cosdir0, cosdir
3861 #
3861 #
3862 # def __calculateAOA(self, cosdir, azimuth):
3862 # def __calculateAOA(self, cosdir, azimuth):
3863 # cosdirX = cosdir[:,0]
3863 # cosdirX = cosdir[:,0]
3864 # cosdirY = cosdir[:,1]
3864 # cosdirY = cosdir[:,1]
3865 #
3865 #
3866 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3866 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3867 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3867 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3868 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3868 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3869 #
3869 #
3870 # return angles
3870 # return angles
3871 #
3871 #
3872 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3872 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3873 #
3873 #
3874 # Ramb = 375 #Ramb = c/(2*PRF)
3874 # Ramb = 375 #Ramb = c/(2*PRF)
3875 # Re = 6371 #Earth Radius
3875 # Re = 6371 #Earth Radius
3876 # heights = numpy.zeros(Ranges.shape)
3876 # heights = numpy.zeros(Ranges.shape)
3877 #
3877 #
3878 # R_aux = numpy.array([0,1,2])*Ramb
3878 # R_aux = numpy.array([0,1,2])*Ramb
3879 # R_aux = R_aux.reshape(1,R_aux.size)
3879 # R_aux = R_aux.reshape(1,R_aux.size)
3880 #
3880 #
3881 # Ranges = Ranges.reshape(Ranges.size,1)
3881 # Ranges = Ranges.reshape(Ranges.size,1)
3882 #
3882 #
3883 # Ri = Ranges + R_aux
3883 # Ri = Ranges + R_aux
3884 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3884 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3885 #
3885 #
3886 # #Check if there is a height between 70 and 110 km
3886 # #Check if there is a height between 70 and 110 km
3887 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3887 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3888 # ind_h = numpy.where(h_bool == 1)[0]
3888 # ind_h = numpy.where(h_bool == 1)[0]
3889 #
3889 #
3890 # hCorr = hi[ind_h, :]
3890 # hCorr = hi[ind_h, :]
3891 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3891 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3892 #
3892 #
3893 # hCorr = hi[ind_hCorr]
3893 # hCorr = hi[ind_hCorr]
3894 # heights[ind_h] = hCorr
3894 # heights[ind_h] = hCorr
3895 #
3895 #
3896 # #Setting Error
3896 # #Setting Error
3897 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3897 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3898 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3898 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3899 #
3899 #
3900 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3900 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3901 # error[indInvalid2] = 14
3901 # error[indInvalid2] = 14
3902 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3902 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3903 # error[indInvalid1] = 13
3903 # error[indInvalid1] = 13
3904 #
3904 #
3905 # return heights, error
3905 # return heights, error
3906
3906
3907
3907
3908 class WeatherRadar(Operation):
3908 class WeatherRadar(Operation):
3909 '''
3909 '''
3910 Function tat implements Weather Radar operations-
3910 Function tat implements Weather Radar operations-
3911 Input:
3911 Input:
3912 Output:
3912 Output:
3913 Parameters affected:
3913 Parameters affected:
3914 '''
3914 '''
3915 isConfig = False
3915 isConfig = False
3916
3916
3917 def __init__(self):
3917 def __init__(self):
3918 Operation.__init__(self)
3918 Operation.__init__(self)
3919
3919
3920 def setup(self,dataOut,Pt=0,Gt=0,Gr=0,lambda_=0, aL=0,
3920 def setup(self,dataOut,Pt=0,Gt=0,Gr=0,lambda_=0, aL=0,
3921 tauW= 0,thetaT=0,thetaR=0,Km =0):
3921 tauW= 0,thetaT=0,thetaR=0,Km =0):
3922 self.nCh = dataOut.nChannels
3922 self.nCh = dataOut.nChannels
3923 self.nHeis = dataOut.nHeights
3923 self.nHeis = dataOut.nHeights
3924 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3924 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3925 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3925 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3926 self.Range = self.Range.reshape(1,self.nHeis)
3926 self.Range = self.Range.reshape(1,self.nHeis)
3927 self.Range = numpy.tile(self.Range,[self.nCh,1])
3927 self.Range = numpy.tile(self.Range,[self.nCh,1])
3928 '''-----------1 Constante del Radar----------'''
3928 '''-----------1 Constante del Radar----------'''
3929 self.Pt = Pt
3929 self.Pt = Pt
3930 self.Gt = Gt
3930 self.Gt = Gt
3931 self.Gr = Gr
3931 self.Gr = Gr
3932 self.lambda_ = lambda_
3932 self.lambda_ = lambda_
3933 self.aL = aL
3933 self.aL = aL
3934 self.tauW = tauW
3934 self.tauW = tauW
3935 self.thetaT = thetaT
3935 self.thetaT = thetaT
3936 self.thetaR = thetaR
3936 self.thetaR = thetaR
3937 self.Km = Km
3937 self.Km = Km
3938 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3938 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3939 Denominator = (Pt * Gt * Gr * lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3939 Denominator = (Pt * Gt * Gr * lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3940 self.RadarConstant = Numerator/Denominator
3940 self.RadarConstant = Numerator/Denominator
3941 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3941 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3942 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3942 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3943 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3943 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3944
3944
3945 def setMoments(self,dataOut,i):
3945 def setMoments(self,dataOut,i):
3946
3946
3947 type = dataOut.inputUnit
3947 type = dataOut.inputUnit
3948 nCh = dataOut.nChannels
3948 nCh = dataOut.nChannels
3949 nHeis = dataOut.nHeights
3949 nHeis = dataOut.nHeights
3950 data_param = numpy.zeros((nCh,4,nHeis))
3950 data_param = numpy.zeros((nCh,4,nHeis))
3951 if type == "Voltage":
3951 if type == "Voltage":
3952 factor = dataOut.normFactor
3952 factor = dataOut.normFactor
3953 data_param[:,0,:] = dataOut.dataPP_POW/(factor)
3953 data_param[:,0,:] = dataOut.dataPP_POW/(factor)
3954 data_param[:,1,:] = dataOut.dataPP_DOP
3954 data_param[:,1,:] = dataOut.dataPP_DOP
3955 data_param[:,2,:] = dataOut.dataPP_WIDTH
3955 data_param[:,2,:] = dataOut.dataPP_WIDTH
3956 data_param[:,3,:] = dataOut.dataPP_SNR
3956 data_param[:,3,:] = dataOut.dataPP_SNR
3957 if type == "Spectra":
3957 if type == "Spectra":
3958 data_param[:,0,:] = dataOut.data_POW
3958 data_param[:,0,:] = dataOut.data_POW
3959 data_param[:,1,:] = dataOut.data_DOP
3959 data_param[:,1,:] = dataOut.data_DOP
3960 data_param[:,2,:] = dataOut.data_WIDTH
3960 data_param[:,2,:] = dataOut.data_WIDTH
3961 data_param[:,3,:] = dataOut.data_SNR
3961 data_param[:,3,:] = dataOut.data_SNR
3962
3962
3963 return data_param[:,i,:]
3963 return data_param[:,i,:]
3964
3964
3965
3965
3966 def run(self,dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3966 def run(self,dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3967 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93):
3967 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93):
3968
3968
3969 if not self.isConfig:
3969 if not self.isConfig:
3970 self.setup(dataOut= dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3970 self.setup(dataOut= dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3971 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93)
3971 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93)
3972 self.isConfig = True
3972 self.isConfig = True
3973 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3973 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3974 Pr = self.setMoments(dataOut,0)
3974 Pr = self.setMoments(dataOut,0)
3975
3975
3976 for R in range(self.nHeis):
3976 for R in range(self.nHeis):
3977 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
3977 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
3978
3978
3979 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
3979 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
3980
3980
3981 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3981 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3982 Zeh = self.Z_radar
3982 Zeh = self.Z_radar
3983 dBZeh = 10*numpy.log10(Zeh)
3983 dBZeh = 10*numpy.log10(Zeh)
3984 dataOut.factor_Zeh= dBZeh
3984 dataOut.factor_Zeh= dBZeh
3985 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3985 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3986 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3986 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3987
3987
3988 return dataOut
3988 return dataOut
3989
3989
3990 class PedestalInformation(Operation):
3990 class PedestalInformation(Operation):
3991 path_ped = None
3991 path_ped = None
3992 path_adq = None
3992 path_adq = None
3993 t_Interval_p = None
3993 t_Interval_p = None
3994 n_Muestras_p = None
3994 n_Muestras_p = None
3995 isConfig = False
3995 isConfig = False
3996 blocksPerfile= None
3996 blocksPerfile= None
3997 f_a_p = None
3997 f_a_p = None
3998 online = None
3998 online = None
3999 angulo_adq = None
3999 angulo_adq = None
4000 nro_file = None
4000 nro_file = None
4001 nro_key_p = None
4001 nro_key_p = None
4002 tmp = None
4002 tmp = None
4003
4003
4004
4004
4005 def __init__(self):
4005 def __init__(self):
4006 Operation.__init__(self)
4006 Operation.__init__(self)
4007
4007
4008
4008
4009 def getAnguloProfile(self,utc_adq,list_pedestal):
4009 def getAnguloProfile(self,utc_adq,list_pedestal):
4010 utc_adq = utc_adq
4010 utc_adq = utc_adq
4011 list_pedestal = list_pedestal
4011 list_pedestal = list_pedestal
4012 utc_ped_list = []
4012 utc_ped_list = []
4013
4014 for i in range(len(list_pedestal)):
4013 for i in range(len(list_pedestal)):
4015 #print(i)# OJO IDENTIFICADOR DE SINCRONISMO
4014 #print(i)# OJO IDENTIFICADOR DE SINCRONISMO
4016 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=list_pedestal[i]))
4015 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=list_pedestal[i]))
4017
4016
4018 nro_file,utc_ped,utc_ped_1 =self.getNROFile(utc_adq,utc_ped_list)
4017 nro_file,utc_ped,utc_ped_1 =self.getNROFile(utc_adq,utc_ped_list)
4019
4018
4020 if nro_file < 0:
4019 if nro_file < 0:
4021 return numpy.NaN
4020 return numpy.NaN,numpy.NaN
4022 else:
4021 else:
4023 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1 # ojito al -1 estimado alex
4022 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1 # ojito al -1 estimado alex
4024 ff_pedestal = list_pedestal[nro_file]
4023 ff_pedestal = list_pedestal[nro_file]
4025 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4024 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4026 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4025 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4027 angulo_ele = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="ele_pos")
4026 angulo_ele = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="ele_pos")
4028
4027
4029 if 99>=nro_key_p>0:
4028 if 99>=nro_key_p>0:
4030 ##print("angulo_array :",angulo[nro_key_p])
4029 ##print("angulo_array :",angulo[nro_key_p])
4031 return angulo[nro_key_p],angulo_ele[nro_key_p]
4030 return angulo[nro_key_p],angulo_ele[nro_key_p]
4032 else:
4031 else:
4033 #print("-----------------------------------------------------------------")
4032 #print("-----------------------------------------------------------------")
4034 return numpy.NaN,numpy.NaN
4033 return numpy.NaN,numpy.NaN
4035
4034
4036
4035
4037 def getfirstFilefromPath(self,path,meta,ext):
4036 def getfirstFilefromPath(self,path,meta,ext):
4038 validFilelist = []
4037 validFilelist = []
4039 #print("SEARH",path)
4038 #print("SEARH",path)
4040 try:
4039 try:
4041 fileList = os.listdir(path)
4040 fileList = os.listdir(path)
4042 except:
4041 except:
4043 print("check path - fileList")
4042 print("check path - fileList")
4044 if len(fileList)<1:
4043 if len(fileList)<1:
4045 return None
4044 return None
4046 # meta 1234 567 8-18 BCDE
4045 # meta 1234 567 8-18 BCDE
4047 # H,D,PE YYYY DDD EPOC .ext
4046 # H,D,PE YYYY DDD EPOC .ext
4048
4047
4049 for thisFile in fileList:
4048 for thisFile in fileList:
4050 #print("HI",thisFile)
4049 #print("HI",thisFile)
4051 if meta =="PE":
4050 if meta =="PE":
4052 try:
4051 try:
4053 number= int(thisFile[len(meta)+7:len(meta)+17])
4052 number= int(thisFile[len(meta)+7:len(meta)+17])
4054 except:
4053 except:
4055 print("There is a file or folder with different format")
4054 print("There is a file or folder with different format")
4056 if meta == "D":
4055 if meta == "D":
4057 try:
4056 try:
4058 number= int(thisFile[8:11])
4057 number= int(thisFile[8:11])
4059 except:
4058 except:
4060 print("There is a file or folder with different format")
4059 print("There is a file or folder with different format")
4061
4060
4062 if not isNumber(str=number):
4061 if not isNumber(str=number):
4063 continue
4062 continue
4064 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4063 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4065 continue
4064 continue
4066 validFilelist.sort()
4065 validFilelist.sort()
4067 validFilelist.append(thisFile)
4066 validFilelist.append(thisFile)
4068 if len(validFilelist)>0:
4067 if len(validFilelist)>0:
4069 validFilelist = sorted(validFilelist,key=str.lower)
4068 validFilelist = sorted(validFilelist,key=str.lower)
4070 return validFilelist
4069 return validFilelist
4071 return None
4070 return None
4072
4071
4073 def gettimeutcfromDirFilename(self,path,file):
4072 def gettimeutcfromDirFilename(self,path,file):
4074 dir_file= path+"/"+file
4073 dir_file= path+"/"+file
4075 fp = h5py.File(dir_file,'r')
4074 fp = h5py.File(dir_file,'r')
4076 #epoc = fp['Metadata'].get('utctimeInit')[()]
4075 #epoc = fp['Metadata'].get('utctimeInit')[()]
4077 epoc = fp['Data'].get('utc')[()]
4076 epoc = fp['Data'].get('utc')[()]
4078 fp.close()
4077 fp.close()
4079 return epoc
4078 return epoc
4080
4079
4081 def gettimeutcadqfromDirFilename(self,path,file):
4080 def gettimeutcadqfromDirFilename(self,path,file):
4082 pass
4081 pass
4083
4082
4084 def getDatavaluefromDirFilename(self,path,file,value):
4083 def getDatavaluefromDirFilename(self,path,file,value):
4085 dir_file= path+"/"+file
4084 dir_file= path+"/"+file
4086 fp = h5py.File(dir_file,'r')
4085 fp = h5py.File(dir_file,'r')
4087 array = fp['Data'].get(value)[()]
4086 array = fp['Data'].get(value)[()]
4088 fp.close()
4087 fp.close()
4089 return array
4088 return array
4090
4089
4091
4090
4092 def getNROFile(self,utc_adq,utc_ped_list):
4091 def getNROFile(self,utc_adq,utc_ped_list):
4093 c=0
4092 c=0
4094 #print(utc_adq)
4093 #print(utc_adq)
4095 #print(len(utc_ped_list))
4094 #print(len(utc_ped_list))
4095 #print(utc_ped_list)
4096 for i in range(len(utc_ped_list)):
4096 for i in range(len(utc_ped_list)):
4097 if utc_adq>utc_ped_list[i]:
4097 if utc_adq>utc_ped_list[i]:
4098 #print("mayor")
4098 #print("mayor")
4099 #print("utc_ped_list",utc_ped_list[i])
4099 #print("utc_ped_list",utc_ped_list[i])
4100 c +=1
4100 c +=1
4101
4101
4102 return c-1,utc_ped_list[c-1],utc_ped_list[c]
4102 return c-1,utc_ped_list[c-1],utc_ped_list[c]
4103
4103
4104 def verificarNROFILE(self,dataOut,utc_ped,f_a_p,n_Muestras_p):
4104 def verificarNROFILE(self,dataOut,utc_ped,f_a_p,n_Muestras_p):
4105 pass
4105 pass
4106
4106
4107 def setup_offline(self,dataOut,list_pedestal):
4107 def setup_offline(self,dataOut,list_pedestal):
4108 pass
4108 pass
4109
4109
4110 def setup_online(self,dataOut):
4110 def setup_online(self,dataOut):
4111 pass
4111 pass
4112
4112
4113 #def setup(self,dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4113 #def setup(self,dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4114 def setup(self,dataOut,path_ped,t_Interval_p):
4114 def setup(self,dataOut,path_ped,t_Interval_p):
4115 self.__dataReady = False
4115 self.__dataReady = False
4116 self.path_ped = path_ped
4116 self.path_ped = path_ped
4117 self.t_Interval_p = t_Interval_p
4117 self.t_Interval_p = t_Interval_p
4118 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4118 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4119
4119
4120 def setNextFileP(self,dataOut):
4120 def setNextFileP(self,dataOut):
4121 pass
4121 pass
4122
4122
4123 def checkPedFile(self,path,nro_file):
4123 def checkPedFile(self,path,nro_file):
4124 pass
4124 pass
4125
4125
4126 def setNextFileoffline(self,dataOut):
4126 def setNextFileoffline(self,dataOut):
4127 pass
4127 pass
4128
4128
4129 def setNextFileonline(self):
4129 def setNextFileonline(self):
4130 pass
4130 pass
4131
4131
4132 def run(self, dataOut,path_ped,t_Interval_p):
4132 def run(self, dataOut,path_ped,t_Interval_p):
4133 if not self.isConfig:
4133 if not self.isConfig:
4134 self.setup(dataOut, path_ped,t_Interval_p)
4134 self.setup(dataOut, path_ped,t_Interval_p)
4135 self.__dataReady = True
4135 self.__dataReady = True
4136 self.isConfig = True
4136 self.isConfig = True
4137 #print("config TRUE")
4137 #print("config TRUE")
4138 utc_adq = dataOut.utctime
4138 utc_adq = dataOut.utctime
4139 ####print("utc_adq---------------",utc_adq)
4139 ####print("utc_adq---------------",utc_adq)
4140 list_pedestal = self.list_pedestal
4140 list_pedestal = self.list_pedestal
4141 angulo,angulo_ele = self.getAnguloProfile(utc_adq=utc_adq,list_pedestal=list_pedestal)
4141 angulo,angulo_ele = self.getAnguloProfile(utc_adq=utc_adq,list_pedestal=list_pedestal)
4142 ####print("angulo**********",angulo)
4142 ####print("angulo**********",angulo)
4143 dataOut.flagNoData = False
4143 dataOut.flagNoData = False
4144 if numpy.isnan(angulo) or numpy.isnan(angulo_ele) :
4144 if numpy.isnan(angulo) or numpy.isnan(angulo_ele) :
4145 dataOut.flagNoData = True
4145 dataOut.flagNoData = True
4146 return dataOut
4146 return dataOut
4147 dataOut.azimuth = angulo
4147 dataOut.azimuth = angulo
4148 dataOut.elevation = angulo_ele
4148 dataOut.elevation = angulo_ele
4149 return dataOut
4149 return dataOut
4150
4150
4151 class Block360(Operation):
4151 class Block360(Operation):
4152 '''
4152 '''
4153 '''
4153 '''
4154 isConfig = False
4154 isConfig = False
4155 __profIndex = 0
4155 __profIndex = 0
4156 __initime = None
4156 __initime = None
4157 __lastdatatime = None
4157 __lastdatatime = None
4158 __buffer = None
4158 __buffer = None
4159 __dataReady = False
4159 __dataReady = False
4160 n = None
4160 n = None
4161 __nch = 0
4161 __nch = 0
4162 __nHeis = 0
4162 __nHeis = 0
4163 index = 0
4163 index = 0
4164 mode = 0
4164 mode = 0
4165
4165
4166 def __init__(self,**kwargs):
4166 def __init__(self,**kwargs):
4167 Operation.__init__(self,**kwargs)
4167 Operation.__init__(self,**kwargs)
4168
4168
4169 def setup(self, dataOut, n = None, mode = None):
4169 def setup(self, dataOut, n = None, mode = None):
4170 '''
4170 '''
4171 n= Numero de PRF's de entrada
4171 n= Numero de PRF's de entrada
4172 '''
4172 '''
4173 self.__initime = None
4173 self.__initime = None
4174 self.__lastdatatime = 0
4174 self.__lastdatatime = 0
4175 self.__dataReady = False
4175 self.__dataReady = False
4176 self.__buffer = 0
4176 self.__buffer = 0
4177 self.__buffer_1D = 0
4177 self.__buffer_1D = 0
4178 self.__profIndex = 0
4178 self.__profIndex = 0
4179 self.index = 0
4179 self.index = 0
4180 self.__nch = dataOut.nChannels
4180 self.__nch = dataOut.nChannels
4181 self.__nHeis = dataOut.nHeights
4181 self.__nHeis = dataOut.nHeights
4182 ##print("ELVALOR DE n es:", n)
4182 ##print("ELVALOR DE n es:", n)
4183 if n == None:
4183 if n == None:
4184 raise ValueError("n should be specified.")
4184 raise ValueError("n should be specified.")
4185
4185
4186 if mode == None:
4186 if mode == None:
4187 raise ValueError("mode should be specified.")
4187 raise ValueError("mode should be specified.")
4188
4188
4189 if n != None:
4189 if n != None:
4190 if n<1:
4190 if n<1:
4191 print("n should be greater than 2")
4191 print("n should be greater than 2")
4192 raise ValueError("n should be greater than 2")
4192 raise ValueError("n should be greater than 2")
4193
4193
4194 self.n = n
4194 self.n = n
4195 self.mode = mode
4195 self.mode = mode
4196 print("self.mode",self.mode)
4196 #print("self.mode",self.mode)
4197 #print("nHeights")
4197 #print("nHeights")
4198 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4198 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4199 self.__buffer2 = numpy.zeros(n)
4199 self.__buffer2 = numpy.zeros(n)
4200 self.__buffer3 = numpy.zeros(n)
4200 self.__buffer3 = numpy.zeros(n)
4201
4201
4202
4202
4203 def putData(self,data,mode):
4203 def putData(self,data,mode):
4204 '''
4204 '''
4205 Add a profile to he __buffer and increase in one the __profiel Index
4205 Add a profile to he __buffer and increase in one the __profiel Index
4206 '''
4206 '''
4207 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4207 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4208 #print("line 4049",data.azimuth.shape,data.azimuth)
4208 #print("line 4049",data.azimuth.shape,data.azimuth)
4209 if self.mode==0:
4209 if self.mode==0:
4210 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4210 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4211 if self.mode==1:
4211 if self.mode==1:
4212 self.__buffer[:,self.__profIndex,:]= data.data_pow
4212 self.__buffer[:,self.__profIndex,:]= data.data_pow
4213 #print("me casi",self.index,data.azimuth[self.index])
4213 #print("me casi",self.index,data.azimuth[self.index])
4214 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4214 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4215 #print("magic",data.profileIndex)
4215 #print("magic",data.profileIndex)
4216 #print(data.azimuth[self.index])
4216 #print(data.azimuth[self.index])
4217 #print("index",self.index)
4217 #print("index",self.index)
4218
4218
4219 #####self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4219 #####self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4220 self.__buffer2[self.__profIndex] = data.azimuth
4220 self.__buffer2[self.__profIndex] = data.azimuth
4221 self.__buffer3[self.__profIndex] = data.elevation
4221 self.__buffer3[self.__profIndex] = data.elevation
4222 #print("q pasa")
4222 #print("q pasa")
4223 #####self.index+=1
4223 #####self.index+=1
4224 #print("index",self.index,data.azimuth[:10])
4224 #print("index",self.index,data.azimuth[:10])
4225 self.__profIndex += 1
4225 self.__profIndex += 1
4226 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4226 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4227
4227
4228 def pushData(self,data):
4228 def pushData(self,data):
4229 '''
4229 '''
4230 Return the PULSEPAIR and the profiles used in the operation
4230 Return the PULSEPAIR and the profiles used in the operation
4231 Affected : self.__profileIndex
4231 Affected : self.__profileIndex
4232 '''
4232 '''
4233 #print("pushData")
4233 #print("pushData")
4234
4234
4235 data_360 = self.__buffer
4235 data_360 = self.__buffer
4236 data_p = self.__buffer2
4236 data_p = self.__buffer2
4237 data_e = self.__buffer3
4237 data_e = self.__buffer3
4238 n = self.__profIndex
4238 n = self.__profIndex
4239
4239
4240 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4240 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4241 self.__buffer2 = numpy.zeros(self.n)
4241 self.__buffer2 = numpy.zeros(self.n)
4242 self.__buffer3 = numpy.zeros(self.n)
4242 self.__buffer3 = numpy.zeros(self.n)
4243 self.__profIndex = 0
4243 self.__profIndex = 0
4244 #print("pushData")
4244 #print("pushData")
4245 return data_360,n,data_p,data_e
4245 return data_360,n,data_p,data_e
4246
4246
4247
4247
4248 def byProfiles(self,dataOut):
4248 def byProfiles(self,dataOut):
4249
4249
4250 self.__dataReady = False
4250 self.__dataReady = False
4251 data_360 = None
4251 data_360 = None
4252 data_p = None
4252 data_p = None
4253 data_e = None
4253 data_e = None
4254 #print("dataOu",dataOut.dataPP_POW)
4254 #print("dataOu",dataOut.dataPP_POW)
4255 self.putData(data=dataOut,mode = self.mode)
4255 self.putData(data=dataOut,mode = self.mode)
4256 ##### print("profIndex",self.__profIndex)
4256 ##### print("profIndex",self.__profIndex)
4257 if self.__profIndex == self.n:
4257 if self.__profIndex == self.n:
4258 data_360,n,data_p,data_e = self.pushData(data=dataOut)
4258 data_360,n,data_p,data_e = self.pushData(data=dataOut)
4259 self.__dataReady = True
4259 self.__dataReady = True
4260
4260
4261 return data_360,data_p,data_e
4261 return data_360,data_p,data_e
4262
4262
4263
4263
4264 def blockOp(self, dataOut, datatime= None):
4264 def blockOp(self, dataOut, datatime= None):
4265 if self.__initime == None:
4265 if self.__initime == None:
4266 self.__initime = datatime
4266 self.__initime = datatime
4267 data_360,data_p,data_e = self.byProfiles(dataOut)
4267 data_360,data_p,data_e = self.byProfiles(dataOut)
4268 self.__lastdatatime = datatime
4268 self.__lastdatatime = datatime
4269
4269
4270 if data_360 is None:
4270 if data_360 is None:
4271 return None, None,None,None
4271 return None, None,None,None
4272
4272
4273
4273
4274 avgdatatime = self.__initime
4274 avgdatatime = self.__initime
4275 if self.n==1:
4275 if self.n==1:
4276 avgdatatime = datatime
4276 avgdatatime = datatime
4277 deltatime = datatime - self.__lastdatatime
4277 deltatime = datatime - self.__lastdatatime
4278 self.__initime = datatime
4278 self.__initime = datatime
4279 #print(data_360.shape,avgdatatime,data_p.shape)
4279 #print(data_360.shape,avgdatatime,data_p.shape)
4280 return data_360,avgdatatime,data_p,data_e
4280 return data_360,avgdatatime,data_p,data_e
4281
4281
4282 def run(self, dataOut,n = None,mode=None,**kwargs):
4282 def run(self, dataOut,n = None,mode=None,**kwargs):
4283 #print("BLOCK 360 HERE WE GO MOMENTOS")
4283 #print("BLOCK 360 HERE WE GO MOMENTOS")
4284 if not self.isConfig:
4284 if not self.isConfig:
4285 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4285 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4286 ####self.index = 0
4286 ####self.index = 0
4287 #print("comova",self.isConfig)
4287 #print("comova",self.isConfig)
4288 self.isConfig = True
4288 self.isConfig = True
4289 ####if self.index==dataOut.azimuth.shape[0]:
4289 ####if self.index==dataOut.azimuth.shape[0]:
4290 #### self.index=0
4290 #### self.index=0
4291 data_360, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4291 data_360, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4292 dataOut.flagNoData = True
4292 dataOut.flagNoData = True
4293
4293
4294 if self.__dataReady:
4294 if self.__dataReady:
4295 dataOut.data_360 = data_360 # S
4295 dataOut.data_360 = data_360 # S
4296 ##print("---------------------------------------------------------------------------------")
4296 ##print("---------------------------------------------------------------------------------")
4297 #####print("---------------------------DATAREADY---------------------------------------------")
4297 #####print("---------------------------DATAREADY---------------------------------------------")
4298 ##print("---------------------------------------------------------------------------------")
4298 ##print("---------------------------------------------------------------------------------")
4299 ##print("data_360",dataOut.data_360.shape)
4299 ##print("data_360",dataOut.data_360.shape)
4300 dataOut.data_azi = data_p
4300 dataOut.data_azi = data_p
4301 dataOut.data_ele = data_e
4301 dataOut.data_ele = data_e
4302 #####print("azi: ",dataOut.data_azi)
4302 #####print("azi: ",dataOut.data_azi)
4303 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4303 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4304 dataOut.utctime = avgdatatime
4304 dataOut.utctime = avgdatatime
4305 dataOut.flagNoData = False
4305 dataOut.flagNoData = False
4306 return dataOut
4306 return dataOut
@@ -1,122 +1,122
1 # Ing. AVP
1 # Ing. AVP
2 # 04/01/2022
2 # 04/01/2022
3 # ARCHIVO DE LECTURA
3 # ARCHIVO DE LECTURA
4 #---- DATA RHI --- 23 DE NOVIEMBRE DEL 2021 --- 23/11/2021---
4 #---- DATA RHI --- 23 DE NOVIEMBRE DEL 2021 --- 23/11/2021---
5 #---- PEDESTAL ----------------------------------------------
5 #---- PEDESTAL ----------------------------------------------
6 #------- HORA 143826 /DATA_RM/TEST_PEDESTAL/P20211123-143826 14:38-15:10
6 #------- HORA 143826 /DATA_RM/TEST_PEDESTAL/P20211123-143826 14:38-15:10
7 #---- RADAR ----------------------------------------------
7 #---- RADAR ----------------------------------------------
8 #------- 14:26-15:00
8 #------- 14:26-15:00
9 #------- /DATA_RM/DRONE/2MHZ_5V_ELEVACION/
9 #------- /DATA_RM/DRONE/2MHZ_5V_ELEVACION/
10 #------- /DATA_RM/DRONE/2MHZ_5V_ELEVACION/ch0/2021-11-23T19-00-00
10 #------- /DATA_RM/DRONE/2MHZ_5V_ELEVACION/ch0/2021-11-23T19-00-00
11
11
12 import os, sys
12 import os, sys
13 import datetime
13 import datetime
14 import time
14 import time
15 import numpy
15 import numpy
16 from ext_met import getfirstFilefromPath,getDatavaluefromDirFilename
16 from ext_met import getfirstFilefromPath,getDatavaluefromDirFilename
17 from schainpy.controller import Project
17 from schainpy.controller import Project
18 #-----------------------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------------------
19 print("[SETUP]-RADAR METEOROLOGICO-")
19 print("[SETUP]-RADAR METEOROLOGICO-")
20 path_ped = "/DATA_RM/TEST_PEDESTAL/P20211123-143826"
20 path_ped = "/DATA_RM/TEST_PEDESTAL/P20211123-143826"
21 print("PATH PEDESTAL :",path_ped)
21 print("PATH PEDESTAL :",path_ped)
22 path_adq = "/DATA_RM/DRONE/2MHZ_5V_ELEVACION/"
22 path_adq = "/DATA_RM/DRONE/2MHZ_5V_ELEVACION/"
23 print("PATH DATA :",path_adq)
23 print("PATH DATA :",path_adq)
24 figpath_pp_rti = "/home/soporte/Pictures/TEST_PP_RHI"
24 figpath_pp_rti = "/home/soporte/Pictures/TEST_PP_RHI"
25 print("PATH PP RTI :",figpath_pp_rti)
25 print("PATH PP RTI :",figpath_pp_rti)
26 figpath_pp_rhi = "/home/soporte/Pictures/TEST_PP_RHI"
26 figpath_pp_rhi = "/home/soporte/Pictures/TEST_PP_RHI"
27 print("PATH PP RHI :",figpath_pp_rhi)
27 print("PATH PP RHI :",figpath_pp_rhi)
28 path_pp_save_int = "/DATA_RM/TEST_SAVE_PP_INT_RHI"
28 path_pp_save_int = "/DATA_RM/TEST_SAVE_PP_INT_RHI"
29 print("PATH SAVE PP INT :",path_pp_save_int)
29 print("PATH SAVE PP INT :",path_pp_save_int)
30 print(" ")
30 print(" ")
31 #-------------------------------------------------------------------------------------------
31 #-------------------------------------------------------------------------------------------
32 print("SELECCIONAR MODO: PPI (0) O RHI (1)")
32 print("SELECCIONAR MODO: PPI (0) O RHI (1)")
33 mode_wr = 1
33 mode_wr = 1
34 if mode_wr==0:
34 if mode_wr==0:
35 print("[ ON ] MODE PPI")
35 print("[ ON ] MODE PPI")
36 list_ped = getfirstFilefromPath(path=path_ped,meta="PE",ext=".hdf5")
36 list_ped = getfirstFilefromPath(path=path_ped,meta="PE",ext=".hdf5")
37 ff_pedestal = list_ped[2]
37 ff_pedestal = list_ped[2]
38 azi_vel = getDatavaluefromDirFilename(path=path_ped,file=ff_pedestal,value="azi_vel")
38 azi_vel = getDatavaluefromDirFilename(path=path_ped,file=ff_pedestal,value="azi_vel")
39 V = round(azi_vel[0])
39 V = round(azi_vel[0])
40 print("VELOCIDAD AZI :", int(numpy.mean(azi_vel)),"Β°/seg")
40 print("VELOCIDAD AZI :", int(numpy.mean(azi_vel)),"Β°/seg")
41 else:
41 else:
42 print("[ ON ] MODE RHI")
42 print("[ ON ] MODE RHI")
43 list_ped = getfirstFilefromPath(path=path_ped,meta="PE",ext=".hdf5")
43 list_ped = getfirstFilefromPath(path=path_ped,meta="PE",ext=".hdf5")
44 ff_pedestal = list_ped[2]
44 ff_pedestal = list_ped[2]
45 ele_vel = getDatavaluefromDirFilename(path=path_ped,file=ff_pedestal,value="ele_vel")
45 ele_vel = getDatavaluefromDirFilename(path=path_ped,file=ff_pedestal,value="ele_vel")
46 V = round(ele_vel[0])
46 V = round(ele_vel[0])
47 V = 10.0
47 V = 10.0
48 print("VELOCIDAD ELE :", int(numpy.mean(ele_vel)),"Β°/seg")
48 print("VELOCIDAD ELE :", int(numpy.mean(ele_vel)),"Β°/seg")
49 print(" ")
49 print(" ")
50 #---------------------------------------------------------------------------------------
50 #---------------------------------------------------------------------------------------
51 print("SELECCIONAR MODO: PULSE PAIR (0) O FREQUENCY (1)")
51 print("SELECCIONAR MODO: PULSE PAIR (0) O FREQUENCY (1)")
52 mode_proc = 0
52 mode_proc = 0
53 if mode_proc==0:
53 if mode_proc==0:
54 print("[ ON ] MODE PULSEPAIR")
54 print("[ ON ] MODE PULSEPAIR")
55 else:
55 else:
56 print("[ ON ] MODE FREQUENCY")
56 print("[ ON ] MODE FREQUENCY")
57 ipp = 60.0
57 ipp = 60.0
58 print("IPP(Km.) : %1.2f"%ipp)
58 print("IPP(Km.) : %1.2f"%ipp)
59 ipp_sec = (ipp*1.0e3/150.0)*1.0e-6
59 ipp_sec = (ipp*1.0e3/150.0)*1.0e-6
60 print("IPP(useg.) : %1.2f"%(ipp_sec*(1.0e6)))
60 print("IPP(useg.) : %1.2f"%(ipp_sec*(1.0e6)))
61 VEL=V
61 VEL=V
62 n= int(1/(VEL*ipp_sec))
62 n= int(1/(VEL*ipp_sec))
63 print("NΒ° Profiles : ", n)
63 print("NΒ° Profiles : ", n)
64 #--------------------------------------------
64 #--------------------------------------------
65 plot_rti = 0
65 plot_rti = 0
66 plot_rhi = 1
66 plot_rhi = 1
67 integration = 1
67 integration = 1
68 save = 0
68 save = 0
69 #---------------------------RANGO DE PLOTEO----------------------------------
69 #---------------------------RANGO DE PLOTEO----------------------------------
70 dBmin = '1'
70 dBmin = '1'
71 dBmax = '85'
71 dBmax = '85'
72 xmin = '17'
72 xmin = '17'
73 xmax = '17.25'
73 xmax = '17.25'
74 ymin = '0'
74 ymin = '0'
75 ymax = '600'
75 ymax = '600'
76 #----------------------------------------------------------------------------
76 #----------------------------------------------------------------------------
77 time.sleep(3)
77 time.sleep(3)
78 #---------------------SIGNAL CHAIN ------------------------------------
78 #---------------------SIGNAL CHAIN ------------------------------------
79 desc = "USRP_WEATHER_RADAR"
79 desc = "USRP_WEATHER_RADAR"
80 filename = "USRP_processing.xml"
80 filename = "USRP_processing.xml"
81 controllerObj = Project()
81 controllerObj = Project()
82 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
82 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
83 #---------------------UNIDAD DE LECTURA--------------------------------
83 #---------------------UNIDAD DE LECTURA--------------------------------
84 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
84 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
85 path=path_adq,
85 path=path_adq,
86 startDate="2021/11/10",#today,
86 startDate="2021/11/23",#today,
87 endDate="2021/12/30",#today,
87 endDate="2021/12/30",#today,
88 startTime='17:10:25',
88 startTime='14:38:23',
89 endTime='23:59:59',
89 endTime='23:59:59',
90 delay=0,
90 delay=0,
91 #set=0,
91 #set=0,
92 online=0,
92 online=0,
93 walk=1,
93 walk=1,
94 ippKm=ipp)
94 ippKm=ipp)
95
95
96 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc',inputId=readUnitConfObj.getId())
96 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc',inputId=readUnitConfObj.getId())
97
97
98 opObj11 = procUnitConfObjA.addOperation(name='selectHeights')
98 opObj11 = procUnitConfObjA.addOperation(name='selectHeights')
99 opObj11.addParameter(name='minIndex', value='1', format='int')
99 opObj11.addParameter(name='minIndex', value='1', format='int')
100 # opObj11.addParameter(name='maxIndex', value='10000', format='int')
100 # opObj11.addParameter(name='maxIndex', value='10000', format='int')
101 opObj11.addParameter(name='maxIndex', value='400', format='int')
101 opObj11.addParameter(name='maxIndex', value='400', format='int')
102
102
103 if mode_proc==0:
103 if mode_proc==0:
104 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
104 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
105 opObj11.addParameter(name='n', value=int(n), format='int')
105 opObj11.addParameter(name='n', value=int(n), format='int')
106 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
106 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
107
107
108 if integration==1:
108 if integration==1:
109 opObj11 = procUnitConfObjB.addOperation(name='PedestalInformation')
109 opObj11 = procUnitConfObjB.addOperation(name='PedestalInformation')
110 opObj11.addParameter(name='path_ped', value=path_ped)
110 opObj11.addParameter(name='path_ped', value=path_ped)
111 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
111 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
112
112
113 if plot_rhi==1:
113 if plot_rhi==1:
114 opObj11 = procUnitConfObjB.addOperation(name='Block360')
114 opObj11 = procUnitConfObjB.addOperation(name='Block360')
115 opObj11.addParameter(name='n', value='10', format='int')
115 opObj11.addParameter(name='n', value='10', format='int')
116 opObj11.addParameter(name='mode', value=mode_proc, format='int')
116 opObj11.addParameter(name='mode', value=mode_proc, format='int')
117 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
117 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
118 opObj11= procUnitConfObjB.addOperation(name='WeatherRHIPlot',optype='other')
118 opObj11= procUnitConfObjB.addOperation(name='WeatherRHIPlot',optype='other')
119 opObj11.addParameter(name='save', value=figpath_pp_rhi)
119 opObj11.addParameter(name='save', value=figpath_pp_rhi)
120 opObj11.addParameter(name='save_period', value=1)
120 opObj11.addParameter(name='save_period', value=1)
121
121
122 controllerObj.start()
122 controllerObj.start()
@@ -1,122 +1,123
1 # Ing-AlexanderValdez
1 # Ing-AlexanderValdez
2 # Monitoreo de Pedestal
2 # Monitoreo de Pedestal
3
3
4 ############## IMPORTA LIBRERIAS ###################
4 ############## IMPORTA LIBRERIAS ###################
5 import os,numpy,h5py
5 import os,numpy,h5py
6 import sys,time
6 import sys,time
7 import matplotlib.pyplot as plt
7 import matplotlib.pyplot as plt
8 ####################################################
8 ####################################################
9 #################################################################
9 #################################################################
10 # LA FECHA 21-10-20 CORRESPONDE A LAS PRUEBAS DEL DIA MIERCOLES
10 # LA FECHA 21-10-20 CORRESPONDE A LAS PRUEBAS DEL DIA MIERCOLES
11 # 1:15:51 pm hasta 3:49:32 pm
11 # 1:15:51 pm hasta 3:49:32 pm
12 #################################################################
12 #################################################################
13
13
14 #path_ped = '/DATA_RM/TEST_PEDESTAL/P20211012-082745'
14 #path_ped = '/DATA_RM/TEST_PEDESTAL/P20211012-082745'
15 path_ped = '/DATA_RM/TEST_PEDESTAL/P20211020-131248'
15 path_ped = '/DATA_RM/TEST_PEDESTAL/P20211020-131248'
16 path_ped = '/DATA_RM/TEST_PEDESTAL/P20211110-171003'
16 path_ped = '/DATA_RM/TEST_PEDESTAL/P20211110-171003'
17 path_ped = '/DATA_RM/TEST_PEDESTAL/P20211111-173856'
17 path_ped = '/DATA_RM/TEST_PEDESTAL/P20211111-173856'
18 path_ped = '/DATA_RM/TEST_PEDESTAL/P20211123-143826'
18 #path_ped = '/DATA_RM/TEST_PEDESTAL/P20211111-173409'
19 #path_ped = '/DATA_RM/TEST_PEDESTAL/P20211111-173409'
19 # Metodo para verificar numero
20 # Metodo para verificar numero
20 def isNumber(str):
21 def isNumber(str):
21 try:
22 try:
22 float(str)
23 float(str)
23 return True
24 return True
24 except:
25 except:
25 return False
26 return False
26 # Metodo para extraer el arreglo
27 # Metodo para extraer el arreglo
27 def getDatavaluefromDirFilename(path,file,value):
28 def getDatavaluefromDirFilename(path,file,value):
28 dir_file= path+"/"+file
29 dir_file= path+"/"+file
29 fp = h5py.File(dir_file,'r')
30 fp = h5py.File(dir_file,'r')
30 array = fp['Data'].get(value)[()]
31 array = fp['Data'].get(value)[()]
31 fp.close()
32 fp.close()
32 return array
33 return array
33
34
34 # LISTA COMPLETA DE ARCHIVOS HDF5 Pedestal
35 # LISTA COMPLETA DE ARCHIVOS HDF5 Pedestal
35 LIST= sorted(os.listdir(path_ped))
36 LIST= sorted(os.listdir(path_ped))
36 m=len(LIST)
37 m=len(LIST)
37 print("TOTAL DE ARCHIVOS DE PEDESTAL:",m)
38 print("TOTAL DE ARCHIVOS DE PEDESTAL:",m)
38 # Contadores temporales
39 # Contadores temporales
39 k= 0
40 k= 0
40 l= 0
41 l= 0
41 t= 0
42 t= 0
42 # Marca de tiempo temporal
43 # Marca de tiempo temporal
43 time_ = numpy.zeros([m])
44 time_ = numpy.zeros([m])
44 # creacion de
45 # creacion de
45 for i in range(m):
46 for i in range(m):
46 print("order:",i)
47 print("order:",i)
47 tmp_azi_pos = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="azi_pos")
48 tmp_azi_pos = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="azi_pos")
48 tmp_ele_pos = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="ele_pos")
49 tmp_ele_pos = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="ele_pos")
49 tmp_azi_vel = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="azi_vel")
50 tmp_azi_vel = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="azi_vel")
50 tmp_ele_vel = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="azi_vel")# nuevo :D
51 tmp_ele_vel = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="azi_vel")# nuevo :D
51
52
52 time_[i] = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="utc")
53 time_[i] = getDatavaluefromDirFilename(path=path_ped,file=LIST[i],value="utc")
53
54
54 k=k +tmp_azi_pos.shape[0]
55 k=k +tmp_azi_pos.shape[0]
55 l=l +tmp_ele_pos.shape[0]
56 l=l +tmp_ele_pos.shape[0]
56 t=t +tmp_azi_vel.shape[0]
57 t=t +tmp_azi_vel.shape[0]
57
58
58 print("TOTAL DE MUESTRAS, ARCHIVOS X100:",k)
59 print("TOTAL DE MUESTRAS, ARCHIVOS X100:",k)
59 time.sleep(5)
60 time.sleep(5)
60 ######CREACION DE ARREGLOS CANTIDAD DE VALORES POR MUESTRA#################
61 ######CREACION DE ARREGLOS CANTIDAD DE VALORES POR MUESTRA#################
61 azi_pos = numpy.zeros([k])
62 azi_pos = numpy.zeros([k])
62 ele_pos = numpy.zeros([l])
63 ele_pos = numpy.zeros([l])
63 time_azi_pos= numpy.zeros([k])
64 time_azi_pos= numpy.zeros([k])
64 # Contadores temporales
65 # Contadores temporales
65 p=0
66 p=0
66 r=0
67 r=0
67 z=0
68 z=0
68 # VARIABLES TMP para almacenar azimuth, elevacion y tiempo
69 # VARIABLES TMP para almacenar azimuth, elevacion y tiempo
69
70
70 #for filename in sorted(os.listdir(path_ped)):
71 #for filename in sorted(os.listdir(path_ped)):
71 # CONDICION POR LEER EN TIEMPO REAL NO OFFLINE
72 # CONDICION POR LEER EN TIEMPO REAL NO OFFLINE
72
73
73 for filename in LIST:
74 for filename in LIST:
74 tmp_azi_pos = getDatavaluefromDirFilename(path=path_ped,file=filename,value="azi_pos")
75 tmp_azi_pos = getDatavaluefromDirFilename(path=path_ped,file=filename,value="azi_pos")
75 tmp_ele_pos = getDatavaluefromDirFilename(path=path_ped,file=filename,value="ele_pos")
76 tmp_ele_pos = getDatavaluefromDirFilename(path=path_ped,file=filename,value="ele_pos")
76 # CONDICION POR LEER EN TIEMPO REAL NO OFFLINE
77 # CONDICION POR LEER EN TIEMPO REAL NO OFFLINE
77
78
78 if z==(m-1):
79 if z==(m-1):
79 tmp_azi_time=numpy.arange(time_[z],time_[z]+1,1/(tmp_azi_pos.shape[0]))
80 tmp_azi_time=numpy.arange(time_[z],time_[z]+1,1/(tmp_azi_pos.shape[0]))
80 else:
81 else:
81 tmp_azi_time=numpy.arange(time_[z],time_[z+1],(time_[z+1]-time_[z])/(tmp_azi_pos.shape[0]))
82 tmp_azi_time=numpy.arange(time_[z],time_[z+1],(time_[z+1]-time_[z])/(tmp_azi_pos.shape[0]))
82
83
83 print(filename,time_[z])
84 print(filename,time_[z])
84 print(z,tmp_azi_pos.shape[0])
85 print(z,tmp_azi_pos.shape[0])
85
86
86 i=0
87 i=0
87 for i in range(tmp_azi_pos.shape[0]):
88 for i in range(tmp_azi_pos.shape[0]):
88 index=p+i
89 index=p+i
89 azi_pos[index]=tmp_azi_pos[i]
90 azi_pos[index]=tmp_azi_pos[i]
90 time_azi_pos[index]=tmp_azi_time[i]
91 time_azi_pos[index]=tmp_azi_time[i]
91 p=p+tmp_azi_pos.shape[0]
92 p=p+tmp_azi_pos.shape[0]
92 i=0
93 i=0
93 for i in range(tmp_ele_pos.shape[0]):
94 for i in range(tmp_ele_pos.shape[0]):
94 index=r+i
95 index=r+i
95 ele_pos[index]=tmp_ele_pos[i]
96 ele_pos[index]=tmp_ele_pos[i]
96 r=r+tmp_ele_pos.shape[0]
97 r=r+tmp_ele_pos.shape[0]
97
98
98
99
99 z+=1
100 z+=1
100
101
101
102
102 ######## GRAFIQUEMOS Y VEAMOS LOS DATOS DEL Pedestal
103 ######## GRAFIQUEMOS Y VEAMOS LOS DATOS DEL Pedestal
103 fig, ax = plt.subplots(figsize=(16,8))
104 fig, ax = plt.subplots(figsize=(16,8))
104 print(time_azi_pos.shape)
105 print(time_azi_pos.shape)
105 print(azi_pos.shape)
106 print(azi_pos.shape)
106 t=numpy.arange(time_azi_pos.shape[0])*0.01/(60.0)
107 t=numpy.arange(time_azi_pos.shape[0])*0.01/(60.0)
107 plt.plot(t,azi_pos,label='AZIMUTH_POS',color='blue')
108 plt.plot(t,azi_pos,label='AZIMUTH_POS',color='blue')
108
109
109 # AQUI ESTOY ADICIONANDO LA POSICION EN elevaciont=numpy.arange(len(ele_pos))*0.01/60.0
110 # AQUI ESTOY ADICIONANDO LA POSICION EN elevaciont=numpy.arange(len(ele_pos))*0.01/60.0
110 t=numpy.arange(len(ele_pos))*0.01/60.0
111 t=numpy.arange(len(ele_pos))*0.01/60.0
111 plt.plot(t,ele_pos,label='ELEVATION_POS',color='red')#*10
112 plt.plot(t,ele_pos,label='ELEVATION_POS',color='red')#*10
112
113
113 #ax.set_xlim(0, 9)
114 ax.set_xlim(0, 4)
114 ax.set_ylim(-5, 20)
115 ax.set_ylim(-5, 50)
115 plt.ylabel("Azimuth Position")
116 plt.ylabel("Azimuth Position")
116 plt.xlabel("Muestra")
117 plt.xlabel("Muestra")
117 plt.title('Azimuth Position vs Muestra ', fontsize=20)
118 plt.title('Azimuth Position vs Muestra ', fontsize=20)
118 axes = plt.gca()
119 axes = plt.gca()
119 axes.yaxis.grid()
120 axes.yaxis.grid()
120 plt.xticks(fontsize=16)
121 plt.xticks(fontsize=16)
121 plt.yticks(fontsize=16)
122 plt.yticks(fontsize=16)
122 plt.show()
123 plt.show()
@@ -1,57 +1,58
1 import numpy as np
1 import numpy as np
2 import matplotlib.pyplot as plt
2 import matplotlib.pyplot as plt
3 import wradlib as wrl
3 import wradlib as wrl
4 import warnings
4 import warnings
5 # libreia nueva
5 # libreia nueva
6 #export WRADLIB_DATA="/home/soporte/Downloads/2014-06-09--185000.rhi.mvol"
6 from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
7 from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
7 warnings.filterwarnings('ignore')
8 warnings.filterwarnings('ignore')
8 # lectura de gaMIC hdf5 file
9 # lectura de gaMIC hdf5 file
9 filename = wrl.util.get_wradlib_data_file("/home/soporte/Downloads/2014-06-09--185000.rhi.mvol")
10 filename = wrl.util.get_wradlib_data_file("/home/soporte/Downloads/2014-06-09--185000.rhi.mvol")
10 data1, metadata = wrl.io.read_gamic_hdf5(filename)
11 data1, metadata = wrl.io.read_gamic_hdf5(filename)
11 print(data1)
12 print(data1)
12 data1 = data1['SCAN0']['ZH']['data']
13 data1 = data1['SCAN0']['ZH']['data']
13 print(data1)
14 print(data1)
14 print("SHAPE Data",np.array(data1).shape)
15 print("SHAPE Data",np.array(data1).shape)
15 r = metadata['SCAN0']['r']
16 r = metadata['SCAN0']['r']
16 print("r",r)
17 print("r",r)
17 print("longitud r",len(r))
18 print("longitud r",len(r))
18 th = metadata['SCAN0']['el']
19 th = metadata['SCAN0']['el']
19 print("th",th)
20 print("th",th)
20 print("longitud th",len(th))
21 print("longitud th",len(th))
21 az = metadata['SCAN0']['az']
22 az = metadata['SCAN0']['az']
22 print("az",az)
23 print("az",az)
23 site = (metadata['VOL']['Longitude'], metadata['VOL']['Latitude'],
24 site = (metadata['VOL']['Longitude'], metadata['VOL']['Latitude'],
24 metadata['VOL']['Height'])
25 metadata['VOL']['Height'])
25
26
26 print("Longitud,Latitud,Altura",site)
27 print("Longitud,Latitud,Altura",site)
27 ma1 = np.array(data1)
28 ma1 = np.array(data1)
28 '''
29 '''
29 mask_ind = np.where(data1 <= np.nanmin(data1))
30 mask_ind = np.where(data1 <= np.nanmin(data1))
30 data1[mask_ind] = np.nan
31 data1[mask_ind] = np.nan
31 ma1 = np.ma.array(data1, mask=np.isnan(data1))
32 ma1 = np.ma.array(data1, mask=np.isnan(data1))
32 '''
33 '''
33 #cgax, pm = wrl.vis.plot_rhi(ma1,r=r,th=th,rf=1e3)
34 #cgax, pm = wrl.vis.plot_rhi(ma1,r=r,th=th,rf=1e3)
34 fig = plt.figure(figsize=(10,8))
35 fig = plt.figure(figsize=(10,8))
35 cgax, pm = wrl.vis.plot_rhi(ma1,r=r,th=th,rf=1e3,fig=fig, ax=111,proj='cg')
36 cgax, pm = wrl.vis.plot_rhi(ma1,r=r,th=th,rf=1e3,fig=fig, ax=111,proj='cg')
36 caax = cgax.parasites[0]
37 caax = cgax.parasites[0]
37 paax = cgax.parasites[1]
38 paax = cgax.parasites[1]
38 cgax.set_ylim(0, 14)
39 cgax.set_ylim(0, 14)
39 #caax = cgax.parasites[0]
40 #caax = cgax.parasites[0]
40 #paax = cgax.parasites[1]
41 #paax = cgax.parasites[1]
41 #cgax, pm = wrl.vis.plot_rhi(ma1, r=r, th=th, rf=1e3, fig=fig, ax=111, proj='cg')
42 #cgax, pm = wrl.vis.plot_rhi(ma1, r=r, th=th, rf=1e3, fig=fig, ax=111, proj='cg')
42 txt = plt.title('Simple RHI',y=1.05)
43 txt = plt.title('Simple RHI',y=1.05)
43 #cbar = plt.gcf().colorbar(pm, pad=0.05, ax=paax)
44 #cbar = plt.gcf().colorbar(pm, pad=0.05, ax=paax)
44 cbar = plt.gcf().colorbar(pm, pad=0.05)
45 cbar = plt.gcf().colorbar(pm, pad=0.05)
45 cbar.set_label('reflectivity [dBZ]')
46 cbar.set_label('reflectivity [dBZ]')
46 caax.set_xlabel('x_range [km]')
47 caax.set_xlabel('x_range [km]')
47 caax.set_ylabel('y_range [km]')
48 caax.set_ylabel('y_range [km]')
48 plt.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',ha='right')
49 plt.text(1.0, 1.05, 'azimuth', transform=caax.transAxes, va='bottom',ha='right')
49 gh = cgax.get_grid_helper()
50 gh = cgax.get_grid_helper()
50
51
51 # set theta to some nice values
52 # set theta to some nice values
52 locs = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14.,
53 locs = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14.,
53 15., 16., 17., 18., 20., 22., 25., 30., 35., 40., 50., 60., 70., 80., 90.]
54 15., 16., 17., 18., 20., 22., 25., 30., 35., 40., 50., 60., 70., 80., 90.]
54 gh.grid_finder.grid_locator1 = FixedLocator(locs)
55 gh.grid_finder.grid_locator1 = FixedLocator(locs)
55 gh.grid_finder.tick_formatter1 = DictFormatter(dict([(i, r"${0:.0f}^\circ$".format(i)) for i in locs]))
56 gh.grid_finder.tick_formatter1 = DictFormatter(dict([(i, r"${0:.0f}^\circ$".format(i)) for i in locs]))
56
57
57 plt.show()
58 plt.show()
General Comments 0
You need to be logged in to leave comments. Login now