##// END OF EJS Templates
LAST UPDATE AFTER PERCY & ALEX REVISION
Alexander Valdez -
r1672:65c1739783d6
parent child
Show More
@@ -1,5245 +1,5341
1 import numpy
1 import numpy
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 from scipy.fftpack import fft
4 from scipy.fftpack import fft
5 import scipy
5 import scipy
6 import re
6 import re
7 import datetime
7 import datetime
8 import copy
8 import copy
9 import sys
9 import sys
10 import importlib
10 import importlib
11 import itertools
11 import itertools
12 from multiprocessing import Pool, TimeoutError
12 from multiprocessing import Pool, TimeoutError
13 from multiprocessing.pool import ThreadPool
13 from multiprocessing.pool import ThreadPool
14 import time
14 import time
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 schainpy.model.data.jrodata import Spectra
18 from schainpy.model.data.jrodata import Spectra
19 from scipy import asarray as ar,exp
19 from scipy import asarray as ar,exp
20 from scipy.optimize import fmin, curve_fit
20 from scipy.optimize import fmin, curve_fit
21 from schainpy.utils import log
21 from schainpy.utils import log
22 import warnings
22 import warnings
23 from numpy import NaN
23 from numpy import NaN
24 from scipy.optimize.optimize import OptimizeWarning
24 from scipy.optimize.optimize import OptimizeWarning
25 warnings.filterwarnings('ignore')
25 warnings.filterwarnings('ignore')
26
26
27
27
28 SPEED_OF_LIGHT = 299792458
28 SPEED_OF_LIGHT = 299792458
29
29
30 '''solving pickling issue'''
30 '''solving pickling issue'''
31
31
32 def _pickle_method(method):
32 def _pickle_method(method):
33 func_name = method.__func__.__name__
33 func_name = method.__func__.__name__
34 obj = method.__self__
34 obj = method.__self__
35 cls = method.__self__.__class__
35 cls = method.__self__.__class__
36 return _unpickle_method, (func_name, obj, cls)
36 return _unpickle_method, (func_name, obj, cls)
37
37
38 def _unpickle_method(func_name, obj, cls):
38 def _unpickle_method(func_name, obj, cls):
39 for cls in cls.mro():
39 for cls in cls.mro():
40 try:
40 try:
41 func = cls.__dict__[func_name]
41 func = cls.__dict__[func_name]
42 except KeyError:
42 except KeyError:
43 pass
43 pass
44 else:
44 else:
45 break
45 break
46 return func.__get__(obj, cls)
46 return func.__get__(obj, cls)
47
47
48
48
49 class ParametersProc(ProcessingUnit):
49 class ParametersProc(ProcessingUnit):
50
50
51 METHODS = {}
51 METHODS = {}
52 nSeconds = None
52 nSeconds = None
53
53
54 def __init__(self):
54 def __init__(self):
55 ProcessingUnit.__init__(self)
55 ProcessingUnit.__init__(self)
56
56
57 self.buffer = None
57 self.buffer = None
58 self.firstdatatime = None
58 self.firstdatatime = None
59 self.profIndex = 0
59 self.profIndex = 0
60 self.dataOut = Parameters()
60 self.dataOut = Parameters()
61 self.setupReq = False #Agregar a todas las unidades de proc
61 self.setupReq = False #Agregar a todas las unidades de proc
62
62
63 def __updateObjFromInput(self):
63 def __updateObjFromInput(self):
64
64
65 self.dataOut.inputUnit = self.dataIn.type
65 self.dataOut.inputUnit = self.dataIn.type
66
66
67 self.dataOut.timeZone = self.dataIn.timeZone
67 self.dataOut.timeZone = self.dataIn.timeZone
68 self.dataOut.dstFlag = self.dataIn.dstFlag
68 self.dataOut.dstFlag = self.dataIn.dstFlag
69 self.dataOut.errorCount = self.dataIn.errorCount
69 self.dataOut.errorCount = self.dataIn.errorCount
70 self.dataOut.useLocalTime = self.dataIn.useLocalTime
70 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71
71
72 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
72 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
73 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 self.dataOut.channelList = self.dataIn.channelList
74 self.dataOut.channelList = self.dataIn.channelList
75 self.dataOut.heightList = self.dataIn.heightList
75 self.dataOut.heightList = self.dataIn.heightList
76 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
76 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 # self.dataOut.nBaud = self.dataIn.nBaud
77 # self.dataOut.nBaud = self.dataIn.nBaud
78 # self.dataOut.nCode = self.dataIn.nCode
78 # self.dataOut.nCode = self.dataIn.nCode
79 # self.dataOut.code = self.dataIn.code
79 # self.dataOut.code = self.dataIn.code
80 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
80 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
81 self.dataOut.utctime = self.dataIn.utctime
81 self.dataOut.utctime = self.dataIn.utctime
82 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
82 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
83 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
83 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
84 self.dataOut.nCohInt = self.dataIn.nCohInt
84 self.dataOut.nCohInt = self.dataIn.nCohInt
85 self.dataOut.timeInterval1 = self.dataIn.timeInterval
85 self.dataOut.timeInterval1 = self.dataIn.timeInterval
86 self.dataOut.heightList = self.dataIn.heightList
86 self.dataOut.heightList = self.dataIn.heightList
87 self.dataOut.frequency = self.dataIn.frequency
87 self.dataOut.frequency = self.dataIn.frequency
88 self.dataOut.runNextUnit = self.dataIn.runNextUnit
88
89
90 def run(self, runNextUnit=0):
89
91
90 def run(self):
92 self.dataIn.runNextUnit = runNextUnit
91
92 #---------------------- Voltage Data ---------------------------
93 #---------------------- Voltage Data ---------------------------
93
94
94 if self.dataIn.type == "Voltage":
95 if self.dataIn.type == "Voltage":
95
96
96 self.__updateObjFromInput()
97 self.__updateObjFromInput()
97 self.dataOut.data_pre = self.dataIn.data.copy()
98 self.dataOut.data_pre = self.dataIn.data.copy()
98 self.dataOut.flagNoData = False
99 self.dataOut.flagNoData = False
99 self.dataOut.utctimeInit = self.dataIn.utctime
100 self.dataOut.utctimeInit = self.dataIn.utctime
100 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
101 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
101 if hasattr(self.dataIn, 'dataPP_POW'):
102 if hasattr(self.dataIn, 'dataPP_POW'):
102 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
103 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
103
104
104 if hasattr(self.dataIn, 'dataPP_POWER'):
105 if hasattr(self.dataIn, 'dataPP_POWER'):
105 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
106 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
106
107
107 if hasattr(self.dataIn, 'dataPP_DOP'):
108 if hasattr(self.dataIn, 'dataPP_DOP'):
108 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
109 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
109
110
110 if hasattr(self.dataIn, 'dataPP_SNR'):
111 if hasattr(self.dataIn, 'dataPP_SNR'):
111 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
112 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
112
113
113 if hasattr(self.dataIn, 'dataPP_WIDTH'):
114 if hasattr(self.dataIn, 'dataPP_WIDTH'):
114 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
115 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
115 return
116 return
116
117
117 #---------------------- Spectra Data ---------------------------
118 #---------------------- Spectra Data ---------------------------
118
119
119 if self.dataIn.type == "Spectra":
120 if self.dataIn.type == "Spectra":
120
121
121 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
122 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
122 self.dataOut.data_spc = self.dataIn.data_spc
123 self.dataOut.data_spc = self.dataIn.data_spc
123 self.dataOut.data_cspc = self.dataIn.data_cspc
124 self.dataOut.data_cspc = self.dataIn.data_cspc
124 self.dataOut.nProfiles = self.dataIn.nProfiles
125 self.dataOut.nProfiles = self.dataIn.nProfiles
125 self.dataOut.nIncohInt = self.dataIn.nIncohInt
126 self.dataOut.nIncohInt = self.dataIn.nIncohInt
126 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
127 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
127 self.dataOut.ippFactor = self.dataIn.ippFactor
128 self.dataOut.ippFactor = self.dataIn.ippFactor
128 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
129 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
129 self.dataOut.spc_noise = self.dataIn.getNoise()
130 self.dataOut.spc_noise = self.dataIn.getNoise()
130 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
131 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
131 # self.dataOut.normFactor = self.dataIn.normFactor
132 # self.dataOut.normFactor = self.dataIn.normFactor
132 self.dataOut.pairsList = self.dataIn.pairsList
133 self.dataOut.pairsList = self.dataIn.pairsList
133 self.dataOut.groupList = self.dataIn.pairsList
134 self.dataOut.groupList = self.dataIn.pairsList
134 self.dataOut.flagNoData = False
135 self.dataOut.flagNoData = False
135
136
136 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
137 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
137 self.dataOut.ChanDist = self.dataIn.ChanDist
138 self.dataOut.ChanDist = self.dataIn.ChanDist
138 else: self.dataOut.ChanDist = None
139 else: self.dataOut.ChanDist = None
139
140
140 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
141 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
141 # self.dataOut.VelRange = self.dataIn.VelRange
142 # self.dataOut.VelRange = self.dataIn.VelRange
142 #else: self.dataOut.VelRange = None
143 #else: self.dataOut.VelRange = None
143
144
144 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
145 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
145 self.dataOut.RadarConst = self.dataIn.RadarConst
146 self.dataOut.RadarConst = self.dataIn.RadarConst
146
147
147 if hasattr(self.dataIn, 'NPW'): #NPW
148 if hasattr(self.dataIn, 'NPW'): #NPW
148 self.dataOut.NPW = self.dataIn.NPW
149 self.dataOut.NPW = self.dataIn.NPW
149
150
150 if hasattr(self.dataIn, 'COFA'): #COFA
151 if hasattr(self.dataIn, 'COFA'): #COFA
151 self.dataOut.COFA = self.dataIn.COFA
152 self.dataOut.COFA = self.dataIn.COFA
152
153
153
154
154
155
155 #---------------------- Correlation Data ---------------------------
156 #---------------------- Correlation Data ---------------------------
156
157
157 if self.dataIn.type == "Correlation":
158 if self.dataIn.type == "Correlation":
158 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
159 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
159
160
160 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
161 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
161 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
162 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
162 self.dataOut.groupList = (acf_pairs, ccf_pairs)
163 self.dataOut.groupList = (acf_pairs, ccf_pairs)
163
164
164 self.dataOut.abscissaList = self.dataIn.lagRange
165 self.dataOut.abscissaList = self.dataIn.lagRange
165 self.dataOut.noise = self.dataIn.noise
166 self.dataOut.noise = self.dataIn.noise
166 self.dataOut.data_snr = self.dataIn.SNR
167 self.dataOut.data_snr = self.dataIn.SNR
167 self.dataOut.flagNoData = False
168 self.dataOut.flagNoData = False
168 self.dataOut.nAvg = self.dataIn.nAvg
169 self.dataOut.nAvg = self.dataIn.nAvg
169
170
170 #---------------------- Parameters Data ---------------------------
171 #---------------------- Parameters Data ---------------------------
171
172
172 if self.dataIn.type == "Parameters":
173 if self.dataIn.type == "Parameters":
173 self.dataOut.copy(self.dataIn)
174 self.dataOut.copy(self.dataIn)
174 self.dataOut.flagNoData = False
175 self.dataOut.flagNoData = False
175
176
176 return True
177 return True
177
178
178 self.__updateObjFromInput()
179 self.__updateObjFromInput()
179 self.dataOut.utctimeInit = self.dataIn.utctime
180 self.dataOut.utctimeInit = self.dataIn.utctime
180 self.dataOut.paramInterval = self.dataIn.timeInterval
181 self.dataOut.paramInterval = self.dataIn.timeInterval
181
182
182 return
183 return
183
184
184
185
185 def target(tups):
186 def target(tups):
186
187
187 obj, args = tups
188 obj, args = tups
188
189
189 return obj.FitGau(args)
190 return obj.FitGau(args)
190
191
191 class RemoveWideGC(Operation):
192 class RemoveWideGC(Operation):
192 ''' This class remove the wide clutter and replace it with a simple interpolation points
193 ''' This class remove the wide clutter and replace it with a simple interpolation points
193 This mainly applies to CLAIRE radar
194 This mainly applies to CLAIRE radar
194
195
195 ClutterWidth : Width to look for the clutter peak
196 ClutterWidth : Width to look for the clutter peak
196
197
197 Input:
198 Input:
198
199
199 self.dataOut.data_pre : SPC and CSPC
200 self.dataOut.data_pre : SPC and CSPC
200 self.dataOut.spc_range : To select wind and rainfall velocities
201 self.dataOut.spc_range : To select wind and rainfall velocities
201
202
202 Affected:
203 Affected:
203
204
204 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
205 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
205
206
206 Written by D. ScipiΓ³n 25.02.2021
207 Written by D. ScipiΓ³n 25.02.2021
207 '''
208 '''
208 def __init__(self):
209 def __init__(self):
209 Operation.__init__(self)
210 Operation.__init__(self)
210 self.i = 0
211 self.i = 0
211 self.ich = 0
212 self.ich = 0
212 self.ir = 0
213 self.ir = 0
213
214
214 def run(self, dataOut, ClutterWidth=2.5):
215 def run(self, dataOut, ClutterWidth=2.5):
215
216
216 self.spc = dataOut.data_pre[0].copy()
217 self.spc = dataOut.data_pre[0].copy()
217 self.spc_out = dataOut.data_pre[0].copy()
218 self.spc_out = dataOut.data_pre[0].copy()
218 self.Num_Chn = self.spc.shape[0]
219 self.Num_Chn = self.spc.shape[0]
219 self.Num_Hei = self.spc.shape[2]
220 self.Num_Hei = self.spc.shape[2]
220 VelRange = dataOut.spc_range[2][:-1]
221 VelRange = dataOut.spc_range[2][:-1]
221 dv = VelRange[1]-VelRange[0]
222 dv = VelRange[1]-VelRange[0]
222
223
223 # Find the velocities that corresponds to zero
224 # Find the velocities that corresponds to zero
224 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
225 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
225
226
226 # Removing novalid data from the spectra
227 # Removing novalid data from the spectra
227 for ich in range(self.Num_Chn) :
228 for ich in range(self.Num_Chn) :
228 for ir in range(self.Num_Hei) :
229 for ir in range(self.Num_Hei) :
229 # Estimate the noise at each range
230 # Estimate the noise at each range
230 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
231 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
231
232
232 # Removing the noise floor at each range
233 # Removing the noise floor at each range
233 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
234 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
234 self.spc[ich,novalid,ir] = HSn
235 self.spc[ich,novalid,ir] = HSn
235
236
236 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
237 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
237 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
238 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
238 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
239 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
239 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
240 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
240 continue
241 continue
241 junk3 = numpy.squeeze(numpy.diff(j1index))
242 junk3 = numpy.squeeze(numpy.diff(j1index))
242 junk4 = numpy.squeeze(numpy.diff(j2index))
243 junk4 = numpy.squeeze(numpy.diff(j2index))
243
244
244 valleyindex = j2index[numpy.where(junk4>1)]
245 valleyindex = j2index[numpy.where(junk4>1)]
245 peakindex = j1index[numpy.where(junk3>1)]
246 peakindex = j1index[numpy.where(junk3>1)]
246
247
247 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
248 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
248 if numpy.size(isvalid) == 0 :
249 if numpy.size(isvalid) == 0 :
249 continue
250 continue
250 if numpy.size(isvalid) >1 :
251 if numpy.size(isvalid) >1 :
251 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
252 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
252 isvalid = isvalid[vindex]
253 isvalid = isvalid[vindex]
253
254
254 # clutter peak
255 # clutter peak
255 gcpeak = peakindex[isvalid]
256 gcpeak = peakindex[isvalid]
256 vl = numpy.where(valleyindex < gcpeak)
257 vl = numpy.where(valleyindex < gcpeak)
257 if numpy.size(vl) == 0:
258 if numpy.size(vl) == 0:
258 continue
259 continue
259 gcvl = valleyindex[vl[0][-1]]
260 gcvl = valleyindex[vl[0][-1]]
260 vr = numpy.where(valleyindex > gcpeak)
261 vr = numpy.where(valleyindex > gcpeak)
261 if numpy.size(vr) == 0:
262 if numpy.size(vr) == 0:
262 continue
263 continue
263 gcvr = valleyindex[vr[0][0]]
264 gcvr = valleyindex[vr[0][0]]
264
265
265 # Removing the clutter
266 # Removing the clutter
266 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
267 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
267 gcindex = gc_values[gcvl+1:gcvr-1]
268 gcindex = gc_values[gcvl+1:gcvr-1]
268 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
269 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
269
270
270 dataOut.data_pre[0] = self.spc_out
271 dataOut.data_pre[0] = self.spc_out
271
272
272 return dataOut
273 return dataOut
273
274
274 class SpectralFilters(Operation):
275 class SpectralFilters(Operation):
275 ''' This class allows to replace the novalid values with noise for each channel
276 ''' This class allows to replace the novalid values with noise for each channel
276 This applies to CLAIRE RADAR
277 This applies to CLAIRE RADAR
277
278
278 PositiveLimit : RightLimit of novalid data
279 PositiveLimit : RightLimit of novalid data
279 NegativeLimit : LeftLimit of novalid data
280 NegativeLimit : LeftLimit of novalid data
280
281
281 Input:
282 Input:
282
283
283 self.dataOut.data_pre : SPC and CSPC
284 self.dataOut.data_pre : SPC and CSPC
284 self.dataOut.spc_range : To select wind and rainfall velocities
285 self.dataOut.spc_range : To select wind and rainfall velocities
285
286
286 Affected:
287 Affected:
287
288
288 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
289 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
289
290
290 Written by D. ScipiΓ³n 29.01.2021
291 Written by D. ScipiΓ³n 29.01.2021
291 '''
292 '''
292 def __init__(self):
293 def __init__(self):
293 Operation.__init__(self)
294 Operation.__init__(self)
294 self.i = 0
295 self.i = 0
295
296
296 def run(self, dataOut, ):
297 def run(self, dataOut, ):
297
298
298 self.spc = dataOut.data_pre[0].copy()
299 self.spc = dataOut.data_pre[0].copy()
299 self.Num_Chn = self.spc.shape[0]
300 self.Num_Chn = self.spc.shape[0]
300 VelRange = dataOut.spc_range[2]
301 VelRange = dataOut.spc_range[2]
301
302
302 # novalid corresponds to data within the Negative and PositiveLimit
303 # novalid corresponds to data within the Negative and PositiveLimit
303
304
304
305
305 # Removing novalid data from the spectra
306 # Removing novalid data from the spectra
306 for i in range(self.Num_Chn):
307 for i in range(self.Num_Chn):
307 self.spc[i,novalid,:] = dataOut.noise[i]
308 self.spc[i,novalid,:] = dataOut.noise[i]
308 dataOut.data_pre[0] = self.spc
309 dataOut.data_pre[0] = self.spc
309 return dataOut
310 return dataOut
310
311
311
312
312 class GaussianFit(Operation):
313 class GaussianFit(Operation):
313
314
314 '''
315 '''
315 Function that fit of one and two generalized gaussians (gg) based
316 Function that fit of one and two generalized gaussians (gg) based
316 on the PSD shape across an "power band" identified from a cumsum of
317 on the PSD shape across an "power band" identified from a cumsum of
317 the measured spectrum - noise.
318 the measured spectrum - noise.
318
319
319 Input:
320 Input:
320 self.dataOut.data_pre : SelfSpectra
321 self.dataOut.data_pre : SelfSpectra
321
322
322 Output:
323 Output:
323 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
324 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
324
325
325 '''
326 '''
326 def __init__(self):
327 def __init__(self):
327 Operation.__init__(self)
328 Operation.__init__(self)
328 self.i=0
329 self.i=0
329
330
330
331
331 # 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
332 # 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
332 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
333 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
333 """This routine will find a couple of generalized Gaussians to a power spectrum
334 """This routine will find a couple of generalized Gaussians to a power spectrum
334 methods: generalized, squared
335 methods: generalized, squared
335 input: spc
336 input: spc
336 output:
337 output:
337 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
338 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
338 """
339 """
339 print ('Entering ',method,' double Gaussian fit')
340 print ('Entering ',method,' double Gaussian fit')
340 self.spc = dataOut.data_pre[0].copy()
341 self.spc = dataOut.data_pre[0].copy()
341 self.Num_Hei = self.spc.shape[2]
342 self.Num_Hei = self.spc.shape[2]
342 self.Num_Bin = self.spc.shape[1]
343 self.Num_Bin = self.spc.shape[1]
343 self.Num_Chn = self.spc.shape[0]
344 self.Num_Chn = self.spc.shape[0]
344
345
345 start_time = time.time()
346 start_time = time.time()
346
347
347 pool = Pool(processes=self.Num_Chn)
348 pool = Pool(processes=self.Num_Chn)
348 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
349 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
349 objs = [self for __ in range(self.Num_Chn)]
350 objs = [self for __ in range(self.Num_Chn)]
350 attrs = list(zip(objs, args))
351 attrs = list(zip(objs, args))
351 DGauFitParam = pool.map(target, attrs)
352 DGauFitParam = pool.map(target, attrs)
352 # Parameters:
353 # Parameters:
353 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
354 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
354 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
355 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
355
356
356 # Double Gaussian Curves
357 # Double Gaussian Curves
357 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
358 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
358 gau0[:] = numpy.NaN
359 gau0[:] = numpy.NaN
359 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
360 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
360 gau1[:] = numpy.NaN
361 gau1[:] = numpy.NaN
361 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
362 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
362 for iCh in range(self.Num_Chn):
363 for iCh in range(self.Num_Chn):
363 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
364 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
364 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
365 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
365 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
366 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
366 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
367 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
367 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
368 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
368 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
369 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
369 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
370 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
370 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
371 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
371 if method == 'generalized':
372 if method == 'generalized':
372 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
373 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
373 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
374 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
374 elif method == 'squared':
375 elif method == 'squared':
375 p0 = 2.
376 p0 = 2.
376 p1 = 2.
377 p1 = 2.
377 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
378 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
378 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
379 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
379 dataOut.GaussFit0 = gau0
380 dataOut.GaussFit0 = gau0
380 dataOut.GaussFit1 = gau1
381 dataOut.GaussFit1 = gau1
381
382
382 print('Leaving ',method ,' double Gaussian fit')
383 print('Leaving ',method ,' double Gaussian fit')
383 return dataOut
384 return dataOut
384
385
385 def FitGau(self, X):
386 def FitGau(self, X):
386 # print('Entering FitGau')
387 # print('Entering FitGau')
387 # Assigning the variables
388 # Assigning the variables
388 Vrange, ch, wnoise, num_intg, SNRlimit = X
389 Vrange, ch, wnoise, num_intg, SNRlimit = X
389 # Noise Limits
390 # Noise Limits
390 noisebl = wnoise * 0.9
391 noisebl = wnoise * 0.9
391 noisebh = wnoise * 1.1
392 noisebh = wnoise * 1.1
392 # Radar Velocity
393 # Radar Velocity
393 Va = max(Vrange)
394 Va = max(Vrange)
394 deltav = Vrange[1] - Vrange[0]
395 deltav = Vrange[1] - Vrange[0]
395 x = numpy.arange(self.Num_Bin)
396 x = numpy.arange(self.Num_Bin)
396
397
397 # print ('stop 0')
398 # print ('stop 0')
398
399
399 # 5 parameters, 2 Gaussians
400 # 5 parameters, 2 Gaussians
400 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
401 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
401 DGauFitParam[:] = numpy.NaN
402 DGauFitParam[:] = numpy.NaN
402
403
403 # SPCparam = []
404 # SPCparam = []
404 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
405 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
405 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
406 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
406 # SPC_ch1[:] = 0 #numpy.NaN
407 # SPC_ch1[:] = 0 #numpy.NaN
407 # SPC_ch2[:] = 0 #numpy.NaN
408 # SPC_ch2[:] = 0 #numpy.NaN
408 # print ('stop 1')
409 # print ('stop 1')
409 for ht in range(self.Num_Hei):
410 for ht in range(self.Num_Hei):
410 # print (ht)
411 # print (ht)
411 # print ('stop 2')
412 # print ('stop 2')
412 # Spectra at each range
413 # Spectra at each range
413 spc = numpy.asarray(self.spc)[ch,:,ht]
414 spc = numpy.asarray(self.spc)[ch,:,ht]
414 snr = ( spc.mean() - wnoise ) / wnoise
415 snr = ( spc.mean() - wnoise ) / wnoise
415 snrdB = 10.*numpy.log10(snr)
416 snrdB = 10.*numpy.log10(snr)
416
417
417 #print ('stop 3')
418 #print ('stop 3')
418 if snrdB < SNRlimit :
419 if snrdB < SNRlimit :
419 # snr = numpy.NaN
420 # snr = numpy.NaN
420 # SPC_ch1[:,ht] = 0#numpy.NaN
421 # SPC_ch1[:,ht] = 0#numpy.NaN
421 # SPC_ch1[:,ht] = 0#numpy.NaN
422 # SPC_ch1[:,ht] = 0#numpy.NaN
422 # SPCparam = (SPC_ch1,SPC_ch2)
423 # SPCparam = (SPC_ch1,SPC_ch2)
423 # print ('SNR less than SNRth')
424 # print ('SNR less than SNRth')
424 continue
425 continue
425 # wnoise = hildebrand_sekhon(spc,num_intg)
426 # wnoise = hildebrand_sekhon(spc,num_intg)
426 # print ('stop 2.01')
427 # print ('stop 2.01')
427 #############################################
428 #############################################
428 # normalizing spc and noise
429 # normalizing spc and noise
429 # This part differs from gg1
430 # This part differs from gg1
430 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
431 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
431 #spc = spc / spc_norm_max
432 #spc = spc / spc_norm_max
432 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
433 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
433 #############################################
434 #############################################
434
435
435 # print ('stop 2.1')
436 # print ('stop 2.1')
436 fatspectra=1.0
437 fatspectra=1.0
437 # noise per channel.... we might want to use the noise at each range
438 # noise per channel.... we might want to use the noise at each range
438
439
439 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
440 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
440 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
441 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
441 #if wnoise>1.1*pnoise: # to be tested later
442 #if wnoise>1.1*pnoise: # to be tested later
442 # wnoise=pnoise
443 # wnoise=pnoise
443 # noisebl = wnoise*0.9
444 # noisebl = wnoise*0.9
444 # noisebh = wnoise*1.1
445 # noisebh = wnoise*1.1
445 spc = spc - wnoise # signal
446 spc = spc - wnoise # signal
446
447
447 # print ('stop 2.2')
448 # print ('stop 2.2')
448 minx = numpy.argmin(spc)
449 minx = numpy.argmin(spc)
449 #spcs=spc.copy()
450 #spcs=spc.copy()
450 spcs = numpy.roll(spc,-minx)
451 spcs = numpy.roll(spc,-minx)
451 cum = numpy.cumsum(spcs)
452 cum = numpy.cumsum(spcs)
452 # tot_noise = wnoise * self.Num_Bin #64;
453 # tot_noise = wnoise * self.Num_Bin #64;
453
454
454 # print ('stop 2.3')
455 # print ('stop 2.3')
455 # snr = sum(spcs) / tot_noise
456 # snr = sum(spcs) / tot_noise
456 # snrdB = 10.*numpy.log10(snr)
457 # snrdB = 10.*numpy.log10(snr)
457 #print ('stop 3')
458 #print ('stop 3')
458 # if snrdB < SNRlimit :
459 # if snrdB < SNRlimit :
459 # snr = numpy.NaN
460 # snr = numpy.NaN
460 # SPC_ch1[:,ht] = 0#numpy.NaN
461 # SPC_ch1[:,ht] = 0#numpy.NaN
461 # SPC_ch1[:,ht] = 0#numpy.NaN
462 # SPC_ch1[:,ht] = 0#numpy.NaN
462 # SPCparam = (SPC_ch1,SPC_ch2)
463 # SPCparam = (SPC_ch1,SPC_ch2)
463 # print ('SNR less than SNRth')
464 # print ('SNR less than SNRth')
464 # continue
465 # continue
465
466
466
467
467 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
468 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
468 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
469 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
469 # print ('stop 4')
470 # print ('stop 4')
470 cummax = max(cum)
471 cummax = max(cum)
471 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
472 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
472 cumlo = cummax * epsi
473 cumlo = cummax * epsi
473 cumhi = cummax * (1-epsi)
474 cumhi = cummax * (1-epsi)
474 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
475 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
475
476
476 # print ('stop 5')
477 # print ('stop 5')
477 if len(powerindex) < 1:# case for powerindex 0
478 if len(powerindex) < 1:# case for powerindex 0
478 # print ('powerindex < 1')
479 # print ('powerindex < 1')
479 continue
480 continue
480 powerlo = powerindex[0]
481 powerlo = powerindex[0]
481 powerhi = powerindex[-1]
482 powerhi = powerindex[-1]
482 powerwidth = powerhi-powerlo
483 powerwidth = powerhi-powerlo
483 if powerwidth <= 1:
484 if powerwidth <= 1:
484 # print('powerwidth <= 1')
485 # print('powerwidth <= 1')
485 continue
486 continue
486
487
487 # print ('stop 6')
488 # print ('stop 6')
488 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
489 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
489 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
490 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
490 midpeak = (firstpeak + secondpeak)/2.
491 midpeak = (firstpeak + secondpeak)/2.
491 firstamp = spcs[int(firstpeak)]
492 firstamp = spcs[int(firstpeak)]
492 secondamp = spcs[int(secondpeak)]
493 secondamp = spcs[int(secondpeak)]
493 midamp = spcs[int(midpeak)]
494 midamp = spcs[int(midpeak)]
494
495
495 y_data = spc + wnoise
496 y_data = spc + wnoise
496
497
497 ''' single Gaussian '''
498 ''' single Gaussian '''
498 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
499 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
499 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
500 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
500 power0 = 2.
501 power0 = 2.
501 amplitude0 = midamp
502 amplitude0 = midamp
502 state0 = [shift0,width0,amplitude0,power0,wnoise]
503 state0 = [shift0,width0,amplitude0,power0,wnoise]
503 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
504 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
504 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
505 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
505 # print ('stop 7.1')
506 # print ('stop 7.1')
506 # print (bnds)
507 # print (bnds)
507
508
508 chiSq1=lsq1[1]
509 chiSq1=lsq1[1]
509
510
510 # print ('stop 8')
511 # print ('stop 8')
511 if fatspectra<1.0 and powerwidth<4:
512 if fatspectra<1.0 and powerwidth<4:
512 choice=0
513 choice=0
513 Amplitude0=lsq1[0][2]
514 Amplitude0=lsq1[0][2]
514 shift0=lsq1[0][0]
515 shift0=lsq1[0][0]
515 width0=lsq1[0][1]
516 width0=lsq1[0][1]
516 p0=lsq1[0][3]
517 p0=lsq1[0][3]
517 Amplitude1=0.
518 Amplitude1=0.
518 shift1=0.
519 shift1=0.
519 width1=0.
520 width1=0.
520 p1=0.
521 p1=0.
521 noise=lsq1[0][4]
522 noise=lsq1[0][4]
522 #return (numpy.array([shift0,width0,Amplitude0,p0]),
523 #return (numpy.array([shift0,width0,Amplitude0,p0]),
523 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
524 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
524 # print ('stop 9')
525 # print ('stop 9')
525 ''' two Gaussians '''
526 ''' two Gaussians '''
526 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
527 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
527 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
528 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
528 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
529 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
529 width0 = powerwidth/6.
530 width0 = powerwidth/6.
530 width1 = width0
531 width1 = width0
531 power0 = 2.
532 power0 = 2.
532 power1 = power0
533 power1 = power0
533 amplitude0 = firstamp
534 amplitude0 = firstamp
534 amplitude1 = secondamp
535 amplitude1 = secondamp
535 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
536 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
536 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
537 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
537 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))
538 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))
538 #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))
539 #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))
539
540
540 # print ('stop 10')
541 # print ('stop 10')
541 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
542 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
542
543
543 # print ('stop 11')
544 # print ('stop 11')
544 chiSq2 = lsq2[1]
545 chiSq2 = lsq2[1]
545
546
546 # print ('stop 12')
547 # print ('stop 12')
547
548
548 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)
549 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)
549
550
550 # print ('stop 13')
551 # print ('stop 13')
551 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
552 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
552 if oneG:
553 if oneG:
553 choice = 0
554 choice = 0
554 else:
555 else:
555 w1 = lsq2[0][1]; w2 = lsq2[0][5]
556 w1 = lsq2[0][1]; w2 = lsq2[0][5]
556 a1 = lsq2[0][2]; a2 = lsq2[0][6]
557 a1 = lsq2[0][2]; a2 = lsq2[0][6]
557 p1 = lsq2[0][3]; p2 = lsq2[0][7]
558 p1 = lsq2[0][3]; p2 = lsq2[0][7]
558 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
559 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
559 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
560 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
560 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
561 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
561
562
562 if gp1>gp2:
563 if gp1>gp2:
563 if a1>0.7*a2:
564 if a1>0.7*a2:
564 choice = 1
565 choice = 1
565 else:
566 else:
566 choice = 2
567 choice = 2
567 elif gp2>gp1:
568 elif gp2>gp1:
568 if a2>0.7*a1:
569 if a2>0.7*a1:
569 choice = 2
570 choice = 2
570 else:
571 else:
571 choice = 1
572 choice = 1
572 else:
573 else:
573 choice = numpy.argmax([a1,a2])+1
574 choice = numpy.argmax([a1,a2])+1
574 #else:
575 #else:
575 #choice=argmin([std2a,std2b])+1
576 #choice=argmin([std2a,std2b])+1
576
577
577 else: # with low SNR go to the most energetic peak
578 else: # with low SNR go to the most energetic peak
578 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
579 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
579
580
580 # print ('stop 14')
581 # print ('stop 14')
581 shift0 = lsq2[0][0]
582 shift0 = lsq2[0][0]
582 vel0 = Vrange[0] + shift0 * deltav
583 vel0 = Vrange[0] + shift0 * deltav
583 shift1 = lsq2[0][4]
584 shift1 = lsq2[0][4]
584 # vel1=Vrange[0] + shift1 * deltav
585 # vel1=Vrange[0] + shift1 * deltav
585
586
586 # max_vel = 1.0
587 # max_vel = 1.0
587 # Va = max(Vrange)
588 # Va = max(Vrange)
588 # deltav = Vrange[1]-Vrange[0]
589 # deltav = Vrange[1]-Vrange[0]
589 # print ('stop 15')
590 # print ('stop 15')
590 #first peak will be 0, second peak will be 1
591 #first peak will be 0, second peak will be 1
591 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
592 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
592 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
593 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
593 shift0 = lsq2[0][0]
594 shift0 = lsq2[0][0]
594 width0 = lsq2[0][1]
595 width0 = lsq2[0][1]
595 Amplitude0 = lsq2[0][2]
596 Amplitude0 = lsq2[0][2]
596 p0 = lsq2[0][3]
597 p0 = lsq2[0][3]
597
598
598 shift1 = lsq2[0][4]
599 shift1 = lsq2[0][4]
599 width1 = lsq2[0][5]
600 width1 = lsq2[0][5]
600 Amplitude1 = lsq2[0][6]
601 Amplitude1 = lsq2[0][6]
601 p1 = lsq2[0][7]
602 p1 = lsq2[0][7]
602 noise = lsq2[0][8]
603 noise = lsq2[0][8]
603 else:
604 else:
604 shift1 = lsq2[0][0]
605 shift1 = lsq2[0][0]
605 width1 = lsq2[0][1]
606 width1 = lsq2[0][1]
606 Amplitude1 = lsq2[0][2]
607 Amplitude1 = lsq2[0][2]
607 p1 = lsq2[0][3]
608 p1 = lsq2[0][3]
608
609
609 shift0 = lsq2[0][4]
610 shift0 = lsq2[0][4]
610 width0 = lsq2[0][5]
611 width0 = lsq2[0][5]
611 Amplitude0 = lsq2[0][6]
612 Amplitude0 = lsq2[0][6]
612 p0 = lsq2[0][7]
613 p0 = lsq2[0][7]
613 noise = lsq2[0][8]
614 noise = lsq2[0][8]
614
615
615 if Amplitude0<0.05: # in case the peak is noise
616 if Amplitude0<0.05: # in case the peak is noise
616 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
617 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
617 if Amplitude1<0.05:
618 if Amplitude1<0.05:
618 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
619 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
619
620
620 # print ('stop 16 ')
621 # print ('stop 16 ')
621 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
622 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
622 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
623 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
623 # SPCparam = (SPC_ch1,SPC_ch2)
624 # SPCparam = (SPC_ch1,SPC_ch2)
624
625
625 DGauFitParam[0,ht,0] = noise
626 DGauFitParam[0,ht,0] = noise
626 DGauFitParam[0,ht,1] = noise
627 DGauFitParam[0,ht,1] = noise
627 DGauFitParam[1,ht,0] = Amplitude0
628 DGauFitParam[1,ht,0] = Amplitude0
628 DGauFitParam[1,ht,1] = Amplitude1
629 DGauFitParam[1,ht,1] = Amplitude1
629 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
630 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
630 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
631 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
631 DGauFitParam[3,ht,0] = width0 * deltav
632 DGauFitParam[3,ht,0] = width0 * deltav
632 DGauFitParam[3,ht,1] = width1 * deltav
633 DGauFitParam[3,ht,1] = width1 * deltav
633 DGauFitParam[4,ht,0] = p0
634 DGauFitParam[4,ht,0] = p0
634 DGauFitParam[4,ht,1] = p1
635 DGauFitParam[4,ht,1] = p1
635
636
636 return DGauFitParam
637 return DGauFitParam
637
638
638 def y_model1(self,x,state):
639 def y_model1(self,x,state):
639 shift0, width0, amplitude0, power0, noise = state
640 shift0, width0, amplitude0, power0, noise = state
640 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
641 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
641 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
642 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
642 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
643 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
643 return model0 + model0u + model0d + noise
644 return model0 + model0u + model0d + noise
644
645
645 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
646 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
646 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
647 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
647 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
648 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
648 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
649 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
649 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
650 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
650
651
651 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
652 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
652 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
653 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
653 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
654 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
654 return model0 + model0u + model0d + model1 + model1u + model1d + noise
655 return model0 + model0u + model0d + model1 + model1u + model1d + noise
655
656
656 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.
657 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.
657
658
658 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
659 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
659
660
660 def misfit2(self,state,y_data,x,num_intg):
661 def misfit2(self,state,y_data,x,num_intg):
661 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
662 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
662
663
663 class Oblique_Gauss_Fit(Operation):
664 class Oblique_Gauss_Fit(Operation):
664
665
665 def __init__(self):
666 def __init__(self):
666 Operation.__init__(self)
667 Operation.__init__(self)
667
668
668 def Gauss_fit(self,spc,x,nGauss):
669 def Gauss_fit(self,spc,x,nGauss):
669
670
670
671
671 def gaussian(x, a, b, c, d):
672 def gaussian(x, a, b, c, d):
672 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
673 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
673 return val
674 return val
674
675
675 if nGauss == 'first':
676 if nGauss == 'first':
676 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
677 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
677 spc_2_aux = numpy.flip(spc_1_aux)
678 spc_2_aux = numpy.flip(spc_1_aux)
678 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
679 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
679
680
680 len_dif = len(x)-len(spc_3_aux)
681 len_dif = len(x)-len(spc_3_aux)
681
682
682 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
683 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
683
684
684 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
685 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
685
686
686 y = spc_new
687 y = spc_new
687
688
688 elif nGauss == 'second':
689 elif nGauss == 'second':
689 y = spc
690 y = spc
690
691
691
692
692 # estimate starting values from the data
693 # estimate starting values from the data
693 a = y.max()
694 a = y.max()
694 b = x[numpy.argmax(y)]
695 b = x[numpy.argmax(y)]
695 if nGauss == 'first':
696 if nGauss == 'first':
696 c = 1.#b#b#numpy.std(spc)
697 c = 1.#b#b#numpy.std(spc)
697 elif nGauss == 'second':
698 elif nGauss == 'second':
698 c = b
699 c = b
699 else:
700 else:
700 print("ERROR")
701 print("ERROR")
701
702
702 d = numpy.mean(y[-100:])
703 d = numpy.mean(y[-100:])
703
704
704 # define a least squares function to optimize
705 # define a least squares function to optimize
705 def minfunc(params):
706 def minfunc(params):
706 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
707 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
707
708
708 # fit
709 # fit
709 popt = fmin(minfunc,[a,b,c,d],disp=False)
710 popt = fmin(minfunc,[a,b,c,d],disp=False)
710 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
711 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
711
712
712
713
713 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
714 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
714
715
715
716
716 def Gauss_fit_2(self,spc,x,nGauss):
717 def Gauss_fit_2(self,spc,x,nGauss):
717
718
718
719
719 def gaussian(x, a, b, c, d):
720 def gaussian(x, a, b, c, d):
720 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
721 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
721 return val
722 return val
722
723
723 if nGauss == 'first':
724 if nGauss == 'first':
724 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
725 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
725 spc_2_aux = numpy.flip(spc_1_aux)
726 spc_2_aux = numpy.flip(spc_1_aux)
726 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
727 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
727
728
728 len_dif = len(x)-len(spc_3_aux)
729 len_dif = len(x)-len(spc_3_aux)
729
730
730 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
731 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
731
732
732 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
733 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
733
734
734 y = spc_new
735 y = spc_new
735
736
736 elif nGauss == 'second':
737 elif nGauss == 'second':
737 y = spc
738 y = spc
738
739
739
740
740 # estimate starting values from the data
741 # estimate starting values from the data
741 a = y.max()
742 a = y.max()
742 b = x[numpy.argmax(y)]
743 b = x[numpy.argmax(y)]
743 if nGauss == 'first':
744 if nGauss == 'first':
744 c = 1.#b#b#numpy.std(spc)
745 c = 1.#b#b#numpy.std(spc)
745 elif nGauss == 'second':
746 elif nGauss == 'second':
746 c = b
747 c = b
747 else:
748 else:
748 print("ERROR")
749 print("ERROR")
749
750
750 d = numpy.mean(y[-100:])
751 d = numpy.mean(y[-100:])
751
752
752 # define a least squares function to optimize
753 # define a least squares function to optimize
753 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
754 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
754 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
755 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
755
756
756
757
757 #return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
758 #return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
758 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
759 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
759
760
760 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
761 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
761
762
762 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
763 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
763 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
764 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
764 return val
765 return val
765
766
766
767
767 y = spc
768 y = spc
768
769
769 # estimate starting values from the data
770 # estimate starting values from the data
770 a1 = A1
771 a1 = A1
771 b1 = B1
772 b1 = B1
772 c1 = C1#numpy.std(spc)
773 c1 = C1#numpy.std(spc)
773
774
774 a2 = A2#y.max()
775 a2 = A2#y.max()
775 b2 = B2#x[numpy.argmax(y)]
776 b2 = B2#x[numpy.argmax(y)]
776 c2 = C2#numpy.std(spc)
777 c2 = C2#numpy.std(spc)
777 d = D
778 d = D
778
779
779 # define a least squares function to optimize
780 # define a least squares function to optimize
780 def minfunc(params):
781 def minfunc(params):
781 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
782 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
782
783
783 # fit
784 # fit
784 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
785 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
785
786
786 return double_gaussian(x, popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
787 return double_gaussian(x, popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
787
788
788 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
789 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
789
790
790 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
791 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
791 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
792 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
792 return val
793 return val
793
794
794
795
795 y = spc
796 y = spc
796
797
797 # estimate starting values from the data
798 # estimate starting values from the data
798 a1 = A1
799 a1 = A1
799 b1 = B1
800 b1 = B1
800 c1 = C1#numpy.std(spc)
801 c1 = C1#numpy.std(spc)
801
802
802 a2 = A2#y.max()
803 a2 = A2#y.max()
803 b2 = B2#x[numpy.argmax(y)]
804 b2 = B2#x[numpy.argmax(y)]
804 c2 = C2#numpy.std(spc)
805 c2 = C2#numpy.std(spc)
805 d = D
806 d = D
806
807
807 # fit
808 # fit
808
809
809 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
810 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
810
811
811 error = numpy.sqrt(numpy.diag(pcov))
812 error = numpy.sqrt(numpy.diag(pcov))
812
813
813 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6], error[0], error[1], error[2], error[3], error[4], error[5], error[6]
814 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6], error[0], error[1], error[2], error[3], error[4], error[5], error[6]
814
815
815 def run(self, dataOut):
816 def run(self, dataOut):
816
817
817 pwcode = 1
818 pwcode = 1
818
819
819 if dataOut.flagDecodeData:
820 if dataOut.flagDecodeData:
820 pwcode = numpy.sum(dataOut.code[0]**2)
821 pwcode = numpy.sum(dataOut.code[0]**2)
821 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
822 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
822 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
823 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
823 factor = normFactor
824 factor = normFactor
824 z = dataOut.data_spc / factor
825 z = dataOut.data_spc / factor
825 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
826 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
826 dataOut.power = numpy.average(z, axis=1)
827 dataOut.power = numpy.average(z, axis=1)
827 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
828 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
828
829
829
830
830 x = dataOut.getVelRange(0)
831 x = dataOut.getVelRange(0)
831
832
832 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
833 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
833 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
834 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
834
835
835 dataOut.VelRange = x
836 dataOut.VelRange = x
836
837
837
838
838 l1=range(22,36)
839 l1=range(22,36)
839 l2=range(58,99)
840 l2=range(58,99)
840
841
841 for hei in itertools.chain(l1, l2):
842 for hei in itertools.chain(l1, l2):
842
843
843 try:
844 try:
844 spc = dataOut.data_spc[0,:,hei]
845 spc = dataOut.data_spc[0,:,hei]
845
846
846 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
847 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
847
848
848 spc_diff = spc - spc_fit
849 spc_diff = spc - spc_fit
849 spc_diff[spc_diff < 0] = 0
850 spc_diff[spc_diff < 0] = 0
850
851
851 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
852 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
852
853
853 D = (D1+D2)
854 D = (D1+D2)
854
855
855 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_param_errors[0,0,hei],dataOut.Oblique_param_errors[0,1,hei],dataOut.Oblique_param_errors[0,2,hei],dataOut.Oblique_param_errors[0,3,hei],dataOut.Oblique_param_errors[0,4,hei],dataOut.Oblique_param_errors[0,5,hei],dataOut.Oblique_param_errors[0,6,hei] = self.Double_Gauss_fit_2(spc,x,A1,B1,C1,A2,B2,C2,D)
856 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_param_errors[0,0,hei],dataOut.Oblique_param_errors[0,1,hei],dataOut.Oblique_param_errors[0,2,hei],dataOut.Oblique_param_errors[0,3,hei],dataOut.Oblique_param_errors[0,4,hei],dataOut.Oblique_param_errors[0,5,hei],dataOut.Oblique_param_errors[0,6,hei] = self.Double_Gauss_fit_2(spc,x,A1,B1,C1,A2,B2,C2,D)
856 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
857 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
857
858
858 except:
859 except:
859 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
860 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
860 pass
861 pass
861
862
862 return dataOut
863 return dataOut
863
864
864 class PrecipitationProc(Operation):
865 class PrecipitationProc(Operation):
865
866
866 '''
867 '''
867 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
868 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
868
869
869 Input:
870 Input:
870 self.dataOut.data_pre : SelfSpectra
871 self.dataOut.data_pre : SelfSpectra
871
872
872 Output:
873 Output:
873
874
874 self.dataOut.data_output : Reflectivity factor, rainfall Rate
875 self.dataOut.data_output : Reflectivity factor, rainfall Rate
875
876
876
877
877 Parameters affected:
878 Parameters affected:
878 '''
879 '''
879
880
880 def __init__(self):
881 def __init__(self):
881 Operation.__init__(self)
882 Operation.__init__(self)
882 self.i=0
883 self.i=0
883
884
884 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
885 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
885 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30,
886 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30,
886 channel=None):
887 channel=None):
887
888
888 # print ('Entering PrecepitationProc ... ')
889 # print ('Entering PrecepitationProc ... ')
889
890
890 if radar == "MIRA35C" :
891 if radar == "MIRA35C" :
891
892
892 self.spc = dataOut.data_pre[0].copy()
893 self.spc = dataOut.data_pre[0].copy()
893 self.Num_Hei = self.spc.shape[2]
894 self.Num_Hei = self.spc.shape[2]
894 self.Num_Bin = self.spc.shape[1]
895 self.Num_Bin = self.spc.shape[1]
895 self.Num_Chn = self.spc.shape[0]
896 self.Num_Chn = self.spc.shape[0]
896 Ze = self.dBZeMODE2(dataOut)
897 Ze = self.dBZeMODE2(dataOut)
897
898
898 else:
899 else:
899
900
900 self.spc = dataOut.data_pre[0].copy()
901 self.spc = dataOut.data_pre[0].copy()
901
902
902 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
903 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
903 self.spc[:,:,0:7]= numpy.NaN
904 self.spc[:,:,0:7]= numpy.NaN
904
905
905 self.Num_Hei = self.spc.shape[2]
906 self.Num_Hei = self.spc.shape[2]
906 self.Num_Bin = self.spc.shape[1]
907 self.Num_Bin = self.spc.shape[1]
907 self.Num_Chn = self.spc.shape[0]
908 self.Num_Chn = self.spc.shape[0]
908
909
909 VelRange = dataOut.spc_range[2]
910 VelRange = dataOut.spc_range[2]
910
911
911 ''' Se obtiene la constante del RADAR '''
912 ''' Se obtiene la constante del RADAR '''
912
913
913 self.Pt = Pt
914 self.Pt = Pt
914 self.Gt = Gt
915 self.Gt = Gt
915 self.Gr = Gr
916 self.Gr = Gr
916 self.Lambda = Lambda
917 self.Lambda = Lambda
917 self.aL = aL
918 self.aL = aL
918 self.tauW = tauW
919 self.tauW = tauW
919 self.ThetaT = ThetaT
920 self.ThetaT = ThetaT
920 self.ThetaR = ThetaR
921 self.ThetaR = ThetaR
921 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
922 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
922 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
923 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
923 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
924 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
924
925
925 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
926 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
926 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
927 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
927 RadarConstant = 10e-26 * Numerator / Denominator #
928 RadarConstant = 10e-26 * Numerator / Denominator #
928 ExpConstant = 10**(40/10) #Constante Experimental
929 ExpConstant = 10**(40/10) #Constante Experimental
929
930
930 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
931 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
931 for i in range(self.Num_Chn):
932 for i in range(self.Num_Chn):
932 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
933 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
933 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
934 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
934
935
935 if channel is None:
936 if channel is None:
936 SPCmean = numpy.mean(SignalPower, 0)
937 SPCmean = numpy.mean(SignalPower, 0)
937 else:
938 else:
938 SPCmean = SignalPower[channel]
939 SPCmean = SignalPower[channel]
939 Pr = SPCmean[:,:]/dataOut.normFactor
940 Pr = SPCmean[:,:]/dataOut.normFactor
940
941
941 # Declaring auxiliary variables
942 # Declaring auxiliary variables
942 Range = dataOut.heightList*1000. #Range in m
943 Range = dataOut.heightList*1000. #Range in m
943 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
944 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
944 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
945 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
945 zMtrx = rMtrx+Altitude
946 zMtrx = rMtrx+Altitude
946 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
947 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
947 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
948 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
948
949
949 # height dependence to air density Foote and Du Toit (1969)
950 # height dependence to air density Foote and Du Toit (1969)
950 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
951 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
951 VMtrx = VelMtrx / delv_z #Normalized velocity
952 VMtrx = VelMtrx / delv_z #Normalized velocity
952 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
953 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
953 # Diameter is related to the fall speed of falling drops
954 # Diameter is related to the fall speed of falling drops
954 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
955 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
955 # Only valid for D>= 0.16 mm
956 # Only valid for D>= 0.16 mm
956 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
957 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
957
958
958 #Calculate Radar Reflectivity ETAn
959 #Calculate Radar Reflectivity ETAn
959 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
960 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
960 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
961 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
961 # Radar Cross Section
962 # Radar Cross Section
962 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
963 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
963 # Drop Size Distribution
964 # Drop Size Distribution
964 DSD = ETAn / sigmaD
965 DSD = ETAn / sigmaD
965 # Equivalente Reflectivy
966 # Equivalente Reflectivy
966 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
967 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
967 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
968 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
968 # RainFall Rate
969 # RainFall Rate
969 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
970 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
970
971
971 # Censoring the data
972 # Censoring the data
972 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
973 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
973 SNRth = 10**(SNRdBlimit/10) #-30dB
974 SNRth = 10**(SNRdBlimit/10) #-30dB
974 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
975 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
975 W = numpy.nanmean(dataOut.data_dop,0)
976 W = numpy.nanmean(dataOut.data_dop,0)
976 W[novalid] = numpy.NaN
977 W[novalid] = numpy.NaN
977 Ze_org[novalid] = numpy.NaN
978 Ze_org[novalid] = numpy.NaN
978 RR[novalid] = numpy.NaN
979 RR[novalid] = numpy.NaN
979
980
980 dataOut.data_output = RR[8]
981 dataOut.data_output = RR[8]
981 dataOut.data_param = numpy.ones([3,self.Num_Hei])
982 dataOut.data_param = numpy.ones([3,self.Num_Hei])
982 dataOut.channelList = [0,1,2]
983 dataOut.channelList = [0,1,2]
983
984
984 dataOut.data_param[0]=10*numpy.log10(Ze_org)
985 dataOut.data_param[0]=10*numpy.log10(Ze_org)
985 dataOut.data_param[1]=-W
986 dataOut.data_param[1]=-W
986 dataOut.data_param[2]=RR
987 dataOut.data_param[2]=RR
987
988
988 # print ('Leaving PrecepitationProc ... ')
989 # print ('Leaving PrecepitationProc ... ')
989 return dataOut
990 return dataOut
990
991
991 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
992 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
992
993
993 NPW = dataOut.NPW
994 NPW = dataOut.NPW
994 COFA = dataOut.COFA
995 COFA = dataOut.COFA
995
996
996 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
997 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
997 RadarConst = dataOut.RadarConst
998 RadarConst = dataOut.RadarConst
998 #frequency = 34.85*10**9
999 #frequency = 34.85*10**9
999
1000
1000 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1001 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1001 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
1002 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
1002
1003
1003 ETA = numpy.sum(SNR,1)
1004 ETA = numpy.sum(SNR,1)
1004
1005
1005 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
1006 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
1006
1007
1007 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
1008 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
1008
1009
1009 for r in range(self.Num_Hei):
1010 for r in range(self.Num_Hei):
1010
1011
1011 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
1012 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
1012 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
1013 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
1013
1014
1014 return Ze
1015 return Ze
1015
1016
1016 # def GetRadarConstant(self):
1017 # def GetRadarConstant(self):
1017 #
1018 #
1018 # """
1019 # """
1019 # Constants:
1020 # Constants:
1020 #
1021 #
1021 # Pt: Transmission Power dB 5kW 5000
1022 # Pt: Transmission Power dB 5kW 5000
1022 # Gt: Transmission Gain dB 24.7 dB 295.1209
1023 # Gt: Transmission Gain dB 24.7 dB 295.1209
1023 # Gr: Reception Gain dB 18.5 dB 70.7945
1024 # Gr: Reception Gain dB 18.5 dB 70.7945
1024 # Lambda: Wavelenght m 0.6741 m 0.6741
1025 # Lambda: Wavelenght m 0.6741 m 0.6741
1025 # aL: Attenuation loses dB 4dB 2.5118
1026 # aL: Attenuation loses dB 4dB 2.5118
1026 # tauW: Width of transmission pulse s 4us 4e-6
1027 # tauW: Width of transmission pulse s 4us 4e-6
1027 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
1028 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
1028 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
1029 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
1029 #
1030 #
1030 # """
1031 # """
1031 #
1032 #
1032 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1033 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1033 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1034 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1034 # RadarConstant = Numerator / Denominator
1035 # RadarConstant = Numerator / Denominator
1035 #
1036 #
1036 # return RadarConstant
1037 # return RadarConstant
1037
1038
1038
1039
1039 class FullSpectralAnalysis(Operation):
1040 class FullSpectralAnalysis(Operation):
1040
1041
1041 """
1042 """
1042 Function that implements Full Spectral Analysis technique.
1043 Function that implements Full Spectral Analysis technique.
1043
1044
1044 Input:
1045 Input:
1045 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
1046 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
1046 self.dataOut.groupList : Pairlist of channels
1047 self.dataOut.groupList : Pairlist of channels
1047 self.dataOut.ChanDist : Physical distance between receivers
1048 self.dataOut.ChanDist : Physical distance between receivers
1048
1049
1049
1050
1050 Output:
1051 Output:
1051
1052
1052 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
1053 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
1053
1054
1054
1055
1055 Parameters affected: Winds, height range, SNR
1056 Parameters affected: Winds, height range, SNR
1056
1057
1057 """
1058 """
1058 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
1059 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
1059 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
1060 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
1060
1061
1061 spc = dataOut.data_pre[0].copy()
1062 spc = dataOut.data_pre[0].copy()
1062 cspc = dataOut.data_pre[1]
1063 cspc = dataOut.data_pre[1]
1063 nHeights = spc.shape[2]
1064 nHeights = spc.shape[2]
1064
1065
1065 # first_height = 0.75 #km (ref: data header 20170822)
1066 # first_height = 0.75 #km (ref: data header 20170822)
1066 # resolution_height = 0.075 #km
1067 # resolution_height = 0.075 #km
1067 '''
1068 '''
1068 finding height range. check this when radar parameters are changed!
1069 finding height range. check this when radar parameters are changed!
1069 '''
1070 '''
1070 if maxheight is not None:
1071 if maxheight is not None:
1071 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
1072 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
1072 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
1073 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
1073 else:
1074 else:
1074 range_max = nHeights
1075 range_max = nHeights
1075 if minheight is not None:
1076 if minheight is not None:
1076 # range_min = int((minheight - first_height) / resolution_height) # theoretical
1077 # range_min = int((minheight - first_height) / resolution_height) # theoretical
1077 range_min = int(13.26 * minheight - 5) # empirical, works better
1078 range_min = int(13.26 * minheight - 5) # empirical, works better
1078 if range_min < 0:
1079 if range_min < 0:
1079 range_min = 0
1080 range_min = 0
1080 else:
1081 else:
1081 range_min = 0
1082 range_min = 0
1082
1083
1083 pairsList = dataOut.groupList
1084 pairsList = dataOut.groupList
1084 if dataOut.ChanDist is not None :
1085 if dataOut.ChanDist is not None :
1085 ChanDist = dataOut.ChanDist
1086 ChanDist = dataOut.ChanDist
1086 else:
1087 else:
1087 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
1088 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
1088
1089
1089 # 4 variables: zonal, meridional, vertical, and average SNR
1090 # 4 variables: zonal, meridional, vertical, and average SNR
1090 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
1091 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
1091 velocityX = numpy.zeros([nHeights]) * numpy.NaN
1092 velocityX = numpy.zeros([nHeights]) * numpy.NaN
1092 velocityY = numpy.zeros([nHeights]) * numpy.NaN
1093 velocityY = numpy.zeros([nHeights]) * numpy.NaN
1093 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
1094 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
1094
1095
1095 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
1096 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
1096
1097
1097 '''***********************************************WIND ESTIMATION**************************************'''
1098 '''***********************************************WIND ESTIMATION**************************************'''
1098 for Height in range(nHeights):
1099 for Height in range(nHeights):
1099
1100
1100 if Height >= range_min and Height < range_max:
1101 if Height >= range_min and Height < range_max:
1101 # error_code will be useful in future analysis
1102 # error_code will be useful in future analysis
1102 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
1103 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
1103 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
1104 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
1104
1105
1105 if abs(Vzon) < 100. and abs(Vmer) < 100.:
1106 if abs(Vzon) < 100. and abs(Vmer) < 100.:
1106 velocityX[Height] = Vzon
1107 velocityX[Height] = Vzon
1107 velocityY[Height] = -Vmer
1108 velocityY[Height] = -Vmer
1108 velocityZ[Height] = Vver
1109 velocityZ[Height] = Vver
1109
1110
1110 # Censoring data with SNR threshold
1111 # Censoring data with SNR threshold
1111 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
1112 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
1112
1113
1113 data_param[0] = velocityX
1114 data_param[0] = velocityX
1114 data_param[1] = velocityY
1115 data_param[1] = velocityY
1115 data_param[2] = velocityZ
1116 data_param[2] = velocityZ
1116 data_param[3] = dbSNR
1117 data_param[3] = dbSNR
1117 dataOut.data_param = data_param
1118 dataOut.data_param = data_param
1118 return dataOut
1119 return dataOut
1119
1120
1120 def moving_average(self,x, N=2):
1121 def moving_average(self,x, N=2):
1121 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
1122 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
1122 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1123 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1123
1124
1124 def gaus(self,xSamples,Amp,Mu,Sigma):
1125 def gaus(self,xSamples,Amp,Mu,Sigma):
1125 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
1126 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
1126
1127
1127 def Moments(self, ySamples, xSamples):
1128 def Moments(self, ySamples, xSamples):
1128 Power = numpy.nanmean(ySamples) # Power, 0th Moment
1129 Power = numpy.nanmean(ySamples) # Power, 0th Moment
1129 yNorm = ySamples / numpy.nansum(ySamples)
1130 yNorm = ySamples / numpy.nansum(ySamples)
1130 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
1131 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
1131 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
1132 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
1132 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
1133 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
1133 return numpy.array([Power,RadVel,StdDev])
1134 return numpy.array([Power,RadVel,StdDev])
1134
1135
1135 def StopWindEstimation(self, error_code):
1136 def StopWindEstimation(self, error_code):
1136 Vzon = numpy.NaN
1137 Vzon = numpy.NaN
1137 Vmer = numpy.NaN
1138 Vmer = numpy.NaN
1138 Vver = numpy.NaN
1139 Vver = numpy.NaN
1139 return Vzon, Vmer, Vver, error_code
1140 return Vzon, Vmer, Vver, error_code
1140
1141
1141 def AntiAliasing(self, interval, maxstep):
1142 def AntiAliasing(self, interval, maxstep):
1142 """
1143 """
1143 function to prevent errors from aliased values when computing phaseslope
1144 function to prevent errors from aliased values when computing phaseslope
1144 """
1145 """
1145 antialiased = numpy.zeros(len(interval))
1146 antialiased = numpy.zeros(len(interval))
1146 copyinterval = interval.copy()
1147 copyinterval = interval.copy()
1147
1148
1148 antialiased[0] = copyinterval[0]
1149 antialiased[0] = copyinterval[0]
1149
1150
1150 for i in range(1,len(antialiased)):
1151 for i in range(1,len(antialiased)):
1151 step = interval[i] - interval[i-1]
1152 step = interval[i] - interval[i-1]
1152 if step > maxstep:
1153 if step > maxstep:
1153 copyinterval -= 2*numpy.pi
1154 copyinterval -= 2*numpy.pi
1154 antialiased[i] = copyinterval[i]
1155 antialiased[i] = copyinterval[i]
1155 elif step < maxstep*(-1):
1156 elif step < maxstep*(-1):
1156 copyinterval += 2*numpy.pi
1157 copyinterval += 2*numpy.pi
1157 antialiased[i] = copyinterval[i]
1158 antialiased[i] = copyinterval[i]
1158 else:
1159 else:
1159 antialiased[i] = copyinterval[i].copy()
1160 antialiased[i] = copyinterval[i].copy()
1160
1161
1161 return antialiased
1162 return antialiased
1162
1163
1163 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1164 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1164 """
1165 """
1165 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1166 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1166 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1167 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1167
1168
1168 Input:
1169 Input:
1169 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1170 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1170 pairsList : Pairlist of channels
1171 pairsList : Pairlist of channels
1171 ChanDist : array of xi_ij and eta_ij
1172 ChanDist : array of xi_ij and eta_ij
1172 Height : height at which data is processed
1173 Height : height at which data is processed
1173 noise : noise in [channels] format for specific height
1174 noise : noise in [channels] format for specific height
1174 Abbsisarange : range of the frequencies or velocities
1175 Abbsisarange : range of the frequencies or velocities
1175 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1176 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1176
1177
1177 Output:
1178 Output:
1178 Vzon, Vmer, Vver : wind velocities
1179 Vzon, Vmer, Vver : wind velocities
1179 error_code : int that states where code is terminated
1180 error_code : int that states where code is terminated
1180
1181
1181 0 : no error detected
1182 0 : no error detected
1182 1 : Gaussian of mean spc exceeds widthlimit
1183 1 : Gaussian of mean spc exceeds widthlimit
1183 2 : no Gaussian of mean spc found
1184 2 : no Gaussian of mean spc found
1184 3 : SNR to low or velocity to high -> prec. e.g.
1185 3 : SNR to low or velocity to high -> prec. e.g.
1185 4 : at least one Gaussian of cspc exceeds widthlimit
1186 4 : at least one Gaussian of cspc exceeds widthlimit
1186 5 : zero out of three cspc Gaussian fits converged
1187 5 : zero out of three cspc Gaussian fits converged
1187 6 : phase slope fit could not be found
1188 6 : phase slope fit could not be found
1188 7 : arrays used to fit phase have different length
1189 7 : arrays used to fit phase have different length
1189 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1190 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1190
1191
1191 """
1192 """
1192
1193
1193 error_code = 0
1194 error_code = 0
1194
1195
1195 nChan = spc.shape[0]
1196 nChan = spc.shape[0]
1196 nProf = spc.shape[1]
1197 nProf = spc.shape[1]
1197 nPair = cspc.shape[0]
1198 nPair = cspc.shape[0]
1198
1199
1199 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1200 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1200 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1201 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1201 phase = numpy.zeros([nPair, nProf]) # phase between channels
1202 phase = numpy.zeros([nPair, nProf]) # phase between channels
1202 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1203 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1203 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1204 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1204 xFrec = AbbsisaRange[0][:-1] # frequency range
1205 xFrec = AbbsisaRange[0][:-1] # frequency range
1205 xVel = AbbsisaRange[2][:-1] # velocity range
1206 xVel = AbbsisaRange[2][:-1] # velocity range
1206 xSamples = xFrec # the frequency range is taken
1207 xSamples = xFrec # the frequency range is taken
1207 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1208 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1208
1209
1209 # only consider velocities with in NegativeLimit and PositiveLimit
1210 # only consider velocities with in NegativeLimit and PositiveLimit
1210 if (NegativeLimit is None):
1211 if (NegativeLimit is None):
1211 NegativeLimit = numpy.min(xVel)
1212 NegativeLimit = numpy.min(xVel)
1212 if (PositiveLimit is None):
1213 if (PositiveLimit is None):
1213 PositiveLimit = numpy.max(xVel)
1214 PositiveLimit = numpy.max(xVel)
1214 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1215 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1215 xSamples_zoom = xSamples[xvalid]
1216 xSamples_zoom = xSamples[xvalid]
1216
1217
1217 '''Getting Eij and Nij'''
1218 '''Getting Eij and Nij'''
1218 Xi01, Xi02, Xi12 = ChanDist[:,0]
1219 Xi01, Xi02, Xi12 = ChanDist[:,0]
1219 Eta01, Eta02, Eta12 = ChanDist[:,1]
1220 Eta01, Eta02, Eta12 = ChanDist[:,1]
1220
1221
1221 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1222 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1222 widthlimit = 10
1223 widthlimit = 10
1223 '''************************* SPC is normalized ********************************'''
1224 '''************************* SPC is normalized ********************************'''
1224 spc_norm = spc.copy()
1225 spc_norm = spc.copy()
1225 # For each channel
1226 # For each channel
1226 for i in range(nChan):
1227 for i in range(nChan):
1227 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1228 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1228 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1229 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1229
1230
1230 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1231 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1231
1232
1232 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1233 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1233 you only fit the curve and don't need the absolute value of height for calculation,
1234 you only fit the curve and don't need the absolute value of height for calculation,
1234 only for estimation of width. for normalization of cross spectra, you need initial,
1235 only for estimation of width. for normalization of cross spectra, you need initial,
1235 unnormalized self-spectra With noise.
1236 unnormalized self-spectra With noise.
1236
1237
1237 Technically, you don't even need to normalize the self-spectra, as you only need the
1238 Technically, you don't even need to normalize the self-spectra, as you only need the
1238 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1239 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1239 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1240 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1240 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1241 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1241 """
1242 """
1242 # initial conditions
1243 # initial conditions
1243 popt = [1e-10,0,1e-10]
1244 popt = [1e-10,0,1e-10]
1244 # Spectra average
1245 # Spectra average
1245 SPCMean = numpy.average(SPC_Samples,0)
1246 SPCMean = numpy.average(SPC_Samples,0)
1246 # Moments in frequency
1247 # Moments in frequency
1247 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1248 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1248
1249
1249 # Gauss Fit SPC in frequency domain
1250 # Gauss Fit SPC in frequency domain
1250 if dbSNR > SNRlimit: # only if SNR > SNRth
1251 if dbSNR > SNRlimit: # only if SNR > SNRth
1251 try:
1252 try:
1252 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1253 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1253 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1254 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1254 return self.StopWindEstimation(error_code = 1)
1255 return self.StopWindEstimation(error_code = 1)
1255 FitGauss = self.gaus(xSamples_zoom,*popt)
1256 FitGauss = self.gaus(xSamples_zoom,*popt)
1256 except :#RuntimeError:
1257 except :#RuntimeError:
1257 return self.StopWindEstimation(error_code = 2)
1258 return self.StopWindEstimation(error_code = 2)
1258 else:
1259 else:
1259 return self.StopWindEstimation(error_code = 3)
1260 return self.StopWindEstimation(error_code = 3)
1260
1261
1261 '''***************************** CSPC Normalization *************************
1262 '''***************************** CSPC Normalization *************************
1262 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1263 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1263 influence the norm which is not desired. First, a range is identified where the
1264 influence the norm which is not desired. First, a range is identified where the
1264 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1265 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1265 around it gets cut off and values replaced by mean determined by the boundary
1266 around it gets cut off and values replaced by mean determined by the boundary
1266 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1267 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1267
1268
1268 The sums are then added and multiplied by range/datapoints, because you need
1269 The sums are then added and multiplied by range/datapoints, because you need
1269 an integral and not a sum for normalization.
1270 an integral and not a sum for normalization.
1270
1271
1271 A norm is found according to Briggs 92.
1272 A norm is found according to Briggs 92.
1272 '''
1273 '''
1273 # for each pair
1274 # for each pair
1274 for i in range(nPair):
1275 for i in range(nPair):
1275 cspc_norm = cspc[i,:].copy()
1276 cspc_norm = cspc[i,:].copy()
1276 chan_index0 = pairsList[i][0]
1277 chan_index0 = pairsList[i][0]
1277 chan_index1 = pairsList[i][1]
1278 chan_index1 = pairsList[i][1]
1278 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1279 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1279 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1280 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1280
1281
1281 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1282 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1282 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1283 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1283 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1284 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1284
1285
1285 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1286 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1286 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1287 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1287
1288
1288 '''*******************************FIT GAUSS CSPC************************************'''
1289 '''*******************************FIT GAUSS CSPC************************************'''
1289 try:
1290 try:
1290 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1291 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1291 if popt01[2] > widthlimit: # CONDITION
1292 if popt01[2] > widthlimit: # CONDITION
1292 return self.StopWindEstimation(error_code = 4)
1293 return self.StopWindEstimation(error_code = 4)
1293 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1294 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1294 if popt02[2] > widthlimit: # CONDITION
1295 if popt02[2] > widthlimit: # CONDITION
1295 return self.StopWindEstimation(error_code = 4)
1296 return self.StopWindEstimation(error_code = 4)
1296 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1297 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1297 if popt12[2] > widthlimit: # CONDITION
1298 if popt12[2] > widthlimit: # CONDITION
1298 return self.StopWindEstimation(error_code = 4)
1299 return self.StopWindEstimation(error_code = 4)
1299
1300
1300 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1301 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1301 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1302 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1302 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1303 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1303 except:
1304 except:
1304 return self.StopWindEstimation(error_code = 5)
1305 return self.StopWindEstimation(error_code = 5)
1305
1306
1306
1307
1307 '''************* Getting Fij ***************'''
1308 '''************* Getting Fij ***************'''
1308 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1309 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1309 GaussCenter = popt[1]
1310 GaussCenter = popt[1]
1310 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1311 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1311 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1312 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1312
1313
1313 # Point where e^-1 is located in the gaussian
1314 # Point where e^-1 is located in the gaussian
1314 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1315 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1315 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1316 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1316 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1317 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1317 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1318 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1318
1319
1319 '''********** Taking frequency ranges from mean SPCs **********'''
1320 '''********** Taking frequency ranges from mean SPCs **********'''
1320 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1321 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1321 Range = numpy.empty(2)
1322 Range = numpy.empty(2)
1322 Range[0] = GaussCenter - GauWidth
1323 Range[0] = GaussCenter - GauWidth
1323 Range[1] = GaussCenter + GauWidth
1324 Range[1] = GaussCenter + GauWidth
1324 # Point in x-axis where the bandwidth is located (min:max)
1325 # Point in x-axis where the bandwidth is located (min:max)
1325 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1326 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1326 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1327 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1327 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1328 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1328 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1329 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1329 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1330 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1330 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1331 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1331
1332
1332 '''************************** Getting Phase Slope ***************************'''
1333 '''************************** Getting Phase Slope ***************************'''
1333 for i in range(nPair):
1334 for i in range(nPair):
1334 if len(FrecRange) > 5:
1335 if len(FrecRange) > 5:
1335 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1336 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1336 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1337 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1337 if len(FrecRange) == len(PhaseRange):
1338 if len(FrecRange) == len(PhaseRange):
1338 try:
1339 try:
1339 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1340 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1340 PhaseSlope[i] = slope
1341 PhaseSlope[i] = slope
1341 PhaseInter[i] = intercept
1342 PhaseInter[i] = intercept
1342 except:
1343 except:
1343 return self.StopWindEstimation(error_code = 6)
1344 return self.StopWindEstimation(error_code = 6)
1344 else:
1345 else:
1345 return self.StopWindEstimation(error_code = 7)
1346 return self.StopWindEstimation(error_code = 7)
1346 else:
1347 else:
1347 return self.StopWindEstimation(error_code = 8)
1348 return self.StopWindEstimation(error_code = 8)
1348
1349
1349 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1350 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1350
1351
1351 '''Getting constant C'''
1352 '''Getting constant C'''
1352 cC=(Fij*numpy.pi)**2
1353 cC=(Fij*numpy.pi)**2
1353
1354
1354 '''****** Getting constants F and G ******'''
1355 '''****** Getting constants F and G ******'''
1355 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1356 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1356 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1357 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1357 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1358 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1358 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1359 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1359 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1360 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1360 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1361 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1361 MijResults = numpy.array([MijResult1, MijResult2])
1362 MijResults = numpy.array([MijResult1, MijResult2])
1362 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1363 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1363
1364
1364 '''****** Getting constants A, B and H ******'''
1365 '''****** Getting constants A, B and H ******'''
1365 W01 = numpy.nanmax( FitGauss01 )
1366 W01 = numpy.nanmax( FitGauss01 )
1366 W02 = numpy.nanmax( FitGauss02 )
1367 W02 = numpy.nanmax( FitGauss02 )
1367 W12 = numpy.nanmax( FitGauss12 )
1368 W12 = numpy.nanmax( FitGauss12 )
1368
1369
1369 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1370 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1370 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1371 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1371 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1372 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1372 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1373 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1373
1374
1374 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1375 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1375 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1376 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1376
1377
1377 VxVy = numpy.array([[cA,cH],[cH,cB]])
1378 VxVy = numpy.array([[cA,cH],[cH,cB]])
1378 VxVyResults = numpy.array([-cF,-cG])
1379 VxVyResults = numpy.array([-cF,-cG])
1379 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1380 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1380 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1381 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1381 error_code = 0
1382 error_code = 0
1382
1383
1383 return Vzon, Vmer, Vver, error_code
1384 return Vzon, Vmer, Vver, error_code
1384
1385
1385 class SpectralMoments(Operation):
1386 class SpectralMoments(Operation):
1386
1387
1387 '''
1388 '''
1388 Function SpectralMoments()
1389 Function SpectralMoments()
1389
1390
1390 Calculates moments (power, mean, standard deviation) and SNR of the signal
1391 Calculates moments (power, mean, standard deviation) and SNR of the signal
1391
1392
1392 Type of dataIn: Spectra
1393 Type of dataIn: Spectra
1393
1394
1394 Configuration Parameters:
1395 Configuration Parameters:
1395
1396
1396 dirCosx : Cosine director in X axis
1397 dirCosx : Cosine director in X axis
1397 dirCosy : Cosine director in Y axis
1398 dirCosy : Cosine director in Y axis
1398
1399
1399 elevation :
1400 elevation :
1400 azimuth :
1401 azimuth :
1401
1402
1402 Input:
1403 Input:
1403 channelList : simple channel list to select e.g. [2,3,7]
1404 channelList : simple channel list to select e.g. [2,3,7]
1404 self.dataOut.data_pre : Spectral data
1405 self.dataOut.data_pre : Spectral data
1405 self.dataOut.abscissaList : List of frequencies
1406 self.dataOut.abscissaList : List of frequencies
1406 self.dataOut.noise : Noise level per channel
1407 self.dataOut.noise : Noise level per channel
1407
1408
1408 Affected:
1409 Affected:
1409 self.dataOut.moments : Parameters per channel
1410 self.dataOut.moments : Parameters per channel
1410 self.dataOut.data_snr : SNR per channel
1411 self.dataOut.data_snr : SNR per channel
1411
1412
1412 '''
1413 '''
1413
1414
1414 def run(self, dataOut, proc_type=0):
1415 def run(self, dataOut, proc_type=0):
1415
1416
1416 absc = dataOut.abscissaList[:-1]
1417 absc = dataOut.abscissaList[:-1]
1417 nChannel = dataOut.data_pre[0].shape[0]
1418 nChannel = dataOut.data_pre[0].shape[0]
1418 nHei = dataOut.data_pre[0].shape[2]
1419 nHei = dataOut.data_pre[0].shape[2]
1419 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
1420 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
1420
1421
1421 if proc_type == 1:
1422 if proc_type == 1:
1422 fwindow = numpy.zeros(absc.size) + 1
1423 fwindow = numpy.zeros(absc.size) + 1
1423 b=64
1424 b=64
1424 #b=16
1425 #b=16
1425 fwindow[0:absc.size//2 - b] = 0
1426 fwindow[0:absc.size//2 - b] = 0
1426 fwindow[absc.size//2 + b:] = 0
1427 fwindow[absc.size//2 + b:] = 0
1427 type1 = 1 # moments calculation & gaussean fitting
1428 type1 = 1 # moments calculation & gaussean fitting
1428 nProfiles = dataOut.nProfiles
1429 nProfiles = dataOut.nProfiles
1429 nCohInt = dataOut.nCohInt
1430 nCohInt = dataOut.nCohInt
1430 nIncohInt = dataOut.nIncohInt
1431 nIncohInt = dataOut.nIncohInt
1431 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
1432 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
1432 N = numpy.array(M / nIncohInt,dtype='float32')
1433 N = numpy.array(M / nIncohInt,dtype='float32')
1433 data = dataOut.data_pre[0] * N
1434 data = dataOut.data_pre[0] * N
1434 #noise = dataOut.noise * N
1435 #noise = dataOut.noise * N
1435 noise = numpy.zeros(nChannel)
1436 noise = numpy.zeros(nChannel)
1436 for ind in range(nChannel):
1437 for ind in range(nChannel):
1437 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
1438 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
1438 smooth=3
1439 smooth=3
1439 else:
1440 else:
1440 data = dataOut.data_pre[0]
1441 data = dataOut.data_pre[0]
1441 noise = dataOut.noise
1442 noise = dataOut.noise
1442 fwindow = None
1443 fwindow = None
1443 type1 = 0
1444 type1 = 0
1444 nIncohInt = None
1445 nIncohInt = None
1445 smooth=None
1446 smooth=None
1446
1447
1447 for ind in range(nChannel):
1448 for ind in range(nChannel):
1448 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, id_ch=ind)
1449 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, id_ch=ind)
1449
1450
1450 if proc_type == 1:
1451 if proc_type == 1:
1451 dataOut.moments = data_param[:,1:,:]
1452 dataOut.moments = data_param[:,1:,:]
1452 dataOut.data_dop = data_param[:,2]
1453 dataOut.data_dop = data_param[:,2]
1453 dataOut.data_width = data_param[:,1]
1454 dataOut.data_width = data_param[:,1]
1454 dataOut.data_snr = data_param[:,0]
1455 dataOut.data_snr = data_param[:,0]
1455 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
1456 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
1456 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
1457 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
1457
1458 else:
1458 else:
1459 dataOut.moments = data_param[:,1:,:]
1459 dataOut.moments = data_param[:,1:,:]
1460 dataOut.data_snr = data_param[:,0]
1460 dataOut.data_snr = data_param[:,0]
1461 dataOut.data_pow = data_param[:,1]
1461 dataOut.data_pow = data_param[:,1]
1462 dataOut.data_dop = data_param[:,2]
1462 dataOut.data_dop = data_param[:,2]
1463 dataOut.data_width = data_param[:,3]
1463 dataOut.data_width = data_param[:,3]
1464 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
1464 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
1465
1465
1466 return dataOut
1466 return dataOut
1467
1467
1468 def __calculateMoments(self, oldspec, oldfreq, n0,
1468 def __calculateMoments(self, oldspec, oldfreq, n0,
1469 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,id_ch=0):
1469 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,id_ch=0):
1470
1470
1471 def __GAUSSWINFIT1(A, flagPDER=0):
1471 def __GAUSSWINFIT1(A, flagPDER=0):
1472 nonlocal truex, xvalid
1472 nonlocal truex, xvalid
1473 nparams = 4
1473 nparams = 4
1474 M=truex.size
1474 M=truex.size
1475 mm=numpy.arange(M,dtype='f4')
1475 mm=numpy.arange(M,dtype='f4')
1476 delta = numpy.zeros(M,dtype='f4')
1476 delta = numpy.zeros(M,dtype='f4')
1477 delta[0] = 1.0
1477 delta[0] = 1.0
1478 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
1478 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
1479 jj = -1j
1479 jj = -1j
1480 #if self.winauto is None: self.winauto = (1.0 - mm/M)
1480 #if self.winauto is None: self.winauto = (1.0 - mm/M)
1481 winauto = (1.0 - mm/M)
1481 winauto = (1.0 - mm/M)
1482 winauto = winauto/winauto.max() # Normalized to 1
1482 winauto = winauto/winauto.max() # Normalized to 1
1483 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
1483 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
1484 A[0] = numpy.abs(A[0])
1484 A[0] = numpy.abs(A[0])
1485 A[2] = numpy.abs(A[2])
1485 A[2] = numpy.abs(A[2])
1486 A[3] = numpy.abs(A[3])
1486 A[3] = numpy.abs(A[3])
1487 pi=numpy.array([numpy.pi],dtype='f4')[0]
1487 pi=numpy.array([numpy.pi],dtype='f4')[0]
1488 if A[2] != 0:
1488 if A[2] != 0:
1489 Z = numpy.exp(-2*numpy.power((pi*A[2]*mm*Ts),2,dtype='f4')+jj*2*pi*A[1]*mm*Ts, dtype='c8') # Get Z
1489 Z = numpy.exp(-2*numpy.power((pi*A[2]*mm*Ts),2,dtype='f4')+jj*2*pi*A[1]*mm*Ts, dtype='c8') # Get Z
1490 else:
1490 else:
1491 Z = mm*0.0
1491 Z = mm*0.0
1492 A[0] = 0.0
1492 A[0] = 0.0
1493 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
1493 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
1494 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
1494 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
1495 F = junkF[xvalid]
1495 F = junkF[xvalid]
1496 if flagPDER == 0: #NEED PARTIAL?
1496 if flagPDER == 0: #NEED PARTIAL?
1497 return F
1497 return F
1498 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
1498 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
1499 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
1499 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
1500 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
1500 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
1501 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
1501 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
1502 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
1502 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
1503 PDER = PDER[xvalid,:]
1503 PDER = PDER[xvalid,:]
1504 return F, PDER
1504 return F, PDER
1505
1505
1506 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
1506 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
1507 itmax=20, tol=None):
1507 itmax=20, tol=None):
1508 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
1508 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
1509 if tol == None:
1509 if tol == None:
1510 tol = numpy.array([1.e-3],dtype='f4')[0]
1510 tol = numpy.array([1.e-3],dtype='f4')[0]
1511 typ=a.dtype
1511 typ=a.dtype
1512 double = 1 if typ == numpy.float64 else 0
1512 double = 1 if typ == numpy.float64 else 0
1513 if typ != numpy.float32:
1513 if typ != numpy.float32:
1514 a=a.astype(numpy.float32) #Make params floating
1514 a=a.astype(numpy.float32) #Make params floating
1515 # if we will be estimating partial derivates then compute machine precision
1515 # if we will be estimating partial derivates then compute machine precision
1516 if FlagNoDerivative == 1:
1516 if FlagNoDerivative == 1:
1517 res=numpy.MachAr(float_conv=numpy.float32)
1517 res=numpy.MachAr(float_conv=numpy.float32)
1518 eps=numpy.sqrt(res.eps)
1518 eps=numpy.sqrt(res.eps)
1519
1519
1520 nterms = a.size # Number of parameters
1520 nterms = a.size # Number of parameters
1521 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
1521 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
1522 if nfree <= 0: print('Curvefit - not enough data points.')
1522 if nfree <= 0: print('Curvefit - not enough data points.')
1523 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
1523 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
1524 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
1524 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
1525 # Use diag method in python
1525 # Use diag method in python
1526 converge=1
1526 converge=1
1527
1527
1528 #Define the partial derivative array
1528 #Define the partial derivative array
1529 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
1529 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
1530
1530
1531 for Niter in range(itmax): #Iteration loop
1531 for Niter in range(itmax): #Iteration loop
1532
1532
1533 if FlagNoDerivative == 1:
1533 if FlagNoDerivative == 1:
1534 #Evaluate function and estimate partial derivatives
1534 #Evaluate function and estimate partial derivatives
1535 yfit = __GAUSSWINFIT1(a)
1535 yfit = __GAUSSWINFIT1(a)
1536 for term in range(nterms):
1536 for term in range(nterms):
1537 p=a.copy() # Copy current parameters
1537 p=a.copy() # Copy current parameters
1538 #Increment size for forward difference derivative
1538 #Increment size for forward difference derivative
1539 inc = eps * abs(p[term])
1539 inc = eps * abs(p[term])
1540 if inc == 0: inc = eps
1540 if inc == 0: inc = eps
1541 p[term] = p[term] + inc
1541 p[term] = p[term] + inc
1542 yfit1 = __GAUSSWINFIT1(p)
1542 yfit1 = __GAUSSWINFIT1(p)
1543 PDER[term,:] = (yfit1-yfit)/inc
1543 PDER[term,:] = (yfit1-yfit)/inc
1544 else:
1544 else:
1545 #The user's procedure will return partial derivatives
1545 #The user's procedure will return partial derivatives
1546 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
1546 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
1547
1547
1548 beta = numpy.dot(PDER,(y-yfit)*Weights)
1548 beta = numpy.dot(PDER,(y-yfit)*Weights)
1549 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
1549 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
1550 # save current values of return parameters
1550 # save current values of return parameters
1551 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
1551 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
1552 sigma = sigma1
1552 sigma = sigma1
1553
1553
1554 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
1554 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
1555 chisq = chisq1
1555 chisq = chisq1
1556 yfit1 = yfit
1556 yfit1 = yfit
1557 elev7=numpy.array([1.0e7],dtype='f4')[0]
1557 elev7=numpy.array([1.0e7],dtype='f4')[0]
1558 compara =numpy.sum(abs(y))/elev7/nfree
1558 compara =numpy.sum(abs(y))/elev7/nfree
1559 done_early = chisq1 < compara
1559 done_early = chisq1 < compara
1560
1560
1561 if done_early:
1561 if done_early:
1562 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1562 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1563 if done_early: Niter -= 1
1563 if done_early: Niter -= 1
1564 #save_tp(chisq,Niter,yfit)
1564 #save_tp(chisq,Niter,yfit)
1565 return yfit, a, converge, sigma, chisq # return result
1565 return yfit, a, converge, sigma, chisq # return result
1566 #c = numpy.dot(c, c) # this operator implemented at the next lines
1566 #c = numpy.dot(c, c) # this operator implemented at the next lines
1567 c_tmp = numpy.sqrt(numpy.diag(alpha))
1567 c_tmp = numpy.sqrt(numpy.diag(alpha))
1568 siz=len(c_tmp)
1568 siz=len(c_tmp)
1569 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
1569 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
1570 lambdaCount = 0
1570 lambdaCount = 0
1571 while True:
1571 while True:
1572 lambdaCount += 1
1572 lambdaCount += 1
1573 # Normalize alpha to have unit diagonal.
1573 # Normalize alpha to have unit diagonal.
1574 array = alpha / c
1574 array = alpha / c
1575 # Augment the diagonal.
1575 # Augment the diagonal.
1576 one=numpy.array([1.],dtype='f4')[0]
1576 one=numpy.array([1.],dtype='f4')[0]
1577 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
1577 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
1578 # Invert modified curvature matrix to find new parameters.
1578 # Invert modified curvature matrix to find new parameters.
1579 try:
1579 try:
1580 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
1580 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
1581 except Exception as e:
1581 except Exception as e:
1582 print(e)
1582 print(e)
1583 array[:]=numpy.NaN
1583 array[:]=numpy.NaN
1584
1584
1585 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
1585 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
1586 yfit = __GAUSSWINFIT1(b) # Evaluate function
1586 yfit = __GAUSSWINFIT1(b) # Evaluate function
1587 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
1587 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
1588 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
1588 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
1589 if (numpy.isfinite(chisq) == 0) or \
1589 if (numpy.isfinite(chisq) == 0) or \
1590 (lambdaCount > 30 and chisq >= chisq1):
1590 (lambdaCount > 30 and chisq >= chisq1):
1591 # Reject changes made this iteration, use old values.
1591 # Reject changes made this iteration, use old values.
1592 yfit = yfit1
1592 yfit = yfit1
1593 sigma = sigma1
1593 sigma = sigma1
1594 chisq = chisq1
1594 chisq = chisq1
1595 converge = 0
1595 converge = 0
1596 #print('Failed to converge.')
1596 #print('Failed to converge.')
1597 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1597 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1598 if done_early: Niter -= 1
1598 if done_early: Niter -= 1
1599 #save_tp(chisq,Niter,yfit)
1599 #save_tp(chisq,Niter,yfit)
1600 return yfit, a, converge, sigma, chisq, chi2 # return result
1600 return yfit, a, converge, sigma, chisq, chi2 # return result
1601 ten=numpy.array([10.0],dtype='f4')[0]
1601 ten=numpy.array([10.0],dtype='f4')[0]
1602 flambda *= ten # Assume fit got worse
1602 flambda *= ten # Assume fit got worse
1603 if chisq <= chisq1:
1603 if chisq <= chisq1:
1604 break
1604 break
1605 hundred=numpy.array([100.0],dtype='f4')[0]
1605 hundred=numpy.array([100.0],dtype='f4')[0]
1606 flambda /= hundred
1606 flambda /= hundred
1607
1607
1608 a=b # Save new parameter estimate.
1608 a=b # Save new parameter estimate.
1609 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
1609 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
1610 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1610 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1611 if done_early: Niter -= 1
1611 if done_early: Niter -= 1
1612 #save_tp(chisq,Niter,yfit)
1612 #save_tp(chisq,Niter,yfit)
1613 return yfit, a, converge, sigma, chisq, chi2 # return result
1613 return yfit, a, converge, sigma, chisq, chi2 # return result
1614 converge = 0
1614 converge = 0
1615 chi2 = chisq
1615 chi2 = chisq
1616 #print('Failed to converge.')
1616 #print('Failed to converge.')
1617 #save_tp(chisq,Niter,yfit)
1617 #save_tp(chisq,Niter,yfit)
1618 return yfit, a, converge, sigma, chisq, chi2
1618 return yfit, a, converge, sigma, chisq, chi2
1619
1619
1620 if (nicoh is None): nicoh = 1
1620 if (nicoh is None): nicoh = 1
1621 if (graph is None): graph = 0
1621 if (graph is None): graph = 0
1622 if (smooth is None): smooth = 0
1622 if (smooth is None): smooth = 0
1623 if (type1 is None): type1 = 0
1623 if (type1 is None): type1 = 0
1624 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1624 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1625 if (snrth is None): snrth = -20.0
1625 if (snrth is None): snrth = -20.0
1626 if (dc is None): dc = 0
1626 if (dc is None): dc = 0
1627 if (aliasing is None): aliasing = 0
1627 if (aliasing is None): aliasing = 0
1628 if (oldfd is None): oldfd = 0
1628 if (oldfd is None): oldfd = 0
1629 if (wwauto is None): wwauto = 0
1629 if (wwauto is None): wwauto = 0
1630
1630
1631 if (n0 < 1.e-20): n0 = 1.e-20
1631 if (n0 < 1.e-20): n0 = 1.e-20
1632
1632
1633 xvalid = numpy.where(fwindow == 1)[0]
1633 xvalid = numpy.where(fwindow == 1)[0]
1634 freq = oldfreq
1634 freq = oldfreq
1635 truex = oldfreq
1635 truex = oldfreq
1636 vec_power = numpy.zeros(oldspec.shape[1])
1636 vec_power = numpy.zeros(oldspec.shape[1])
1637 vec_fd = numpy.zeros(oldspec.shape[1])
1637 vec_fd = numpy.zeros(oldspec.shape[1])
1638 vec_w = numpy.zeros(oldspec.shape[1])
1638 vec_w = numpy.zeros(oldspec.shape[1])
1639 vec_snr = numpy.zeros(oldspec.shape[1])
1639 vec_snr = numpy.zeros(oldspec.shape[1])
1640 vec_n1 = numpy.empty(oldspec.shape[1])
1640 vec_n1 = numpy.empty(oldspec.shape[1])
1641 vec_fp = numpy.empty(oldspec.shape[1])
1641 vec_fp = numpy.empty(oldspec.shape[1])
1642 vec_sigma_fd = numpy.empty(oldspec.shape[1])
1642 vec_sigma_fd = numpy.empty(oldspec.shape[1])
1643
1643
1644 for ind in range(oldspec.shape[1]):
1644 for ind in range(oldspec.shape[1]):
1645
1645
1646 spec = oldspec[:,ind]
1646 spec = oldspec[:,ind]
1647 if (smooth == 0):
1647 if (smooth == 0):
1648 spec2 = spec
1648 spec2 = spec
1649 else:
1649 else:
1650 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1650 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1651
1651
1652 aux = spec2*fwindow
1652 aux = spec2*fwindow
1653 max_spec = aux.max()
1653 max_spec = aux.max()
1654 m = aux.tolist().index(max_spec)
1654 m = aux.tolist().index(max_spec)
1655
1655
1656 if m > 2 and m < oldfreq.size - 3:
1656 if m > 2 and m < oldfreq.size - 3:
1657 newindex = m + numpy.array([-2,-1,0,1,2])
1657 newindex = m + numpy.array([-2,-1,0,1,2])
1658 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
1658 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
1659 #peakspec = SPLINE(,)
1659 #peakspec = SPLINE(,)
1660 tck = interpolate.splrep(freq[newindex], spec2[newindex])
1660 tck = interpolate.splrep(freq[newindex], spec2[newindex])
1661 peakspec = interpolate.splev(newfreq, tck)
1661 peakspec = interpolate.splev(newfreq, tck)
1662 # max_spec = MAX(peakspec,)
1662 # max_spec = MAX(peakspec,)
1663 max_spec = numpy.max(peakspec)
1663 max_spec = numpy.max(peakspec)
1664 mnew = numpy.argmax(peakspec)
1664 mnew = numpy.argmax(peakspec)
1665 #fp = newfreq(mnew)
1665 #fp = newfreq(mnew)
1666 fp = newfreq[mnew]
1666 fp = newfreq[mnew]
1667 else:
1667 else:
1668 fp = freq[m]
1668 fp = freq[m]
1669
1669
1670 if type1==0:
1670 if type1==0:
1671
1671
1672 # Moments Estimation
1672 # Moments Estimation
1673 bb = spec2[numpy.arange(m,spec2.size)]
1673 bb = spec2[numpy.arange(m,spec2.size)]
1674 bb = (bb<n0).nonzero()
1674 bb = (bb<n0).nonzero()
1675 bb = bb[0]
1675 bb = bb[0]
1676
1676
1677 ss = spec2[numpy.arange(0,m + 1)]
1677 ss = spec2[numpy.arange(0,m + 1)]
1678 ss = (ss<n0).nonzero()
1678 ss = (ss<n0).nonzero()
1679 ss = ss[0]
1679 ss = ss[0]
1680
1680
1681 if (bb.size == 0):
1681 if (bb.size == 0):
1682 bb0 = spec.size - 1 - m
1682 bb0 = spec.size - 1 - m
1683 else:
1683 else:
1684 bb0 = bb[0] - 1
1684 bb0 = bb[0] - 1
1685 if (bb0 < 0):
1685 if (bb0 < 0):
1686 bb0 = 0
1686 bb0 = 0
1687
1687
1688 if (ss.size == 0):
1688 if (ss.size == 0):
1689 ss1 = 1
1689 ss1 = 1
1690 else:
1690 else:
1691 ss1 = max(ss) + 1
1691 ss1 = max(ss) + 1
1692
1692
1693 if (ss1 > m):
1693 if (ss1 > m):
1694 ss1 = m
1694 ss1 = m
1695
1695
1696 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1696 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1697
1697
1698 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1698 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1699 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1699 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1700 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1700 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1701 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1701 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1702 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1702 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1703 snr = (spec2.mean()-n0)/n0
1703 snr = (spec2.mean()-n0)/n0
1704 if (snr < 1.e-20): snr = 1.e-20
1704 if (snr < 1.e-20): snr = 1.e-20
1705
1705
1706 vec_power[ind] = total_power
1706 vec_power[ind] = total_power
1707 vec_fd[ind] = fd
1707 vec_fd[ind] = fd
1708 vec_w[ind] = w
1708 vec_w[ind] = w
1709 vec_snr[ind] = snr
1709 vec_snr[ind] = snr
1710 else:
1710 else:
1711 # Noise by heights
1711 # Noise by heights
1712 n1, stdv = self.__get_noise2(spec, nicoh)
1712 n1, stdv = self.__get_noise2(spec, nicoh)
1713 # Moments Estimation
1713 # Moments Estimation
1714 bb = spec2[numpy.arange(m,spec2.size)]
1714 bb = spec2[numpy.arange(m,spec2.size)]
1715 bb = (bb<n1).nonzero()
1715 bb = (bb<n1).nonzero()
1716 bb = bb[0]
1716 bb = bb[0]
1717
1717
1718 ss = spec2[numpy.arange(0,m + 1)]
1718 ss = spec2[numpy.arange(0,m + 1)]
1719 ss = (ss<n1).nonzero()
1719 ss = (ss<n1).nonzero()
1720 ss = ss[0]
1720 ss = ss[0]
1721
1721
1722 if (bb.size == 0):
1722 if (bb.size == 0):
1723 bb0 = spec.size - 1 - m
1723 bb0 = spec.size - 1 - m
1724 else:
1724 else:
1725 bb0 = bb[0] - 1
1725 bb0 = bb[0] - 1
1726 if (bb0 < 0):
1726 if (bb0 < 0):
1727 bb0 = 0
1727 bb0 = 0
1728
1728
1729 if (ss.size == 0):
1729 if (ss.size == 0):
1730 ss1 = 1
1730 ss1 = 1
1731 else:
1731 else:
1732 ss1 = max(ss) + 1
1732 ss1 = max(ss) + 1
1733
1733
1734 if (ss1 > m):
1734 if (ss1 > m):
1735 ss1 = m
1735 ss1 = m
1736
1736
1737 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1737 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1738 power = ((spec[valid] - n1)*fwindow[valid]).sum()
1738 power = ((spec[valid] - n1)*fwindow[valid]).sum()
1739 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
1739 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
1740 try:
1740 try:
1741 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1741 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1742 except:
1742 except:
1743 w = float("NaN")
1743 w = float("NaN")
1744 snr = power/(n0*fwindow.sum())
1744 snr = power/(n0*fwindow.sum())
1745 if snr < 1.e-20: snr = 1.e-20
1745 if snr < 1.e-20: snr = 1.e-20
1746
1746
1747 # Here start gaussean adjustment
1747 # Here start gaussean adjustment
1748
1748
1749 if snr > numpy.power(10,0.1*snrth):
1749 if snr > numpy.power(10,0.1*snrth):
1750
1750
1751 a = numpy.zeros(4,dtype='f4')
1751 a = numpy.zeros(4,dtype='f4')
1752 a[0] = snr * n0
1752 a[0] = snr * n0
1753 a[1] = fd
1753 a[1] = fd
1754 a[2] = w
1754 a[2] = w
1755 a[3] = n0
1755 a[3] = n0
1756
1756
1757 np = spec.size
1757 np = spec.size
1758 aold = a.copy()
1758 aold = a.copy()
1759 spec2 = spec.copy()
1759 spec2 = spec.copy()
1760 oldxvalid = xvalid.copy()
1760 oldxvalid = xvalid.copy()
1761
1761
1762 for i in range(2):
1762 for i in range(2):
1763
1763
1764 ww = 1.0/(numpy.power(spec2,2)/nicoh)
1764 ww = 1.0/(numpy.power(spec2,2)/nicoh)
1765 ww[np//2] = 0.0
1765 ww[np//2] = 0.0
1766
1766
1767 a = aold.copy()
1767 a = aold.copy()
1768 xvalid = oldxvalid.copy()
1768 xvalid = oldxvalid.copy()
1769 #self.show_var(xvalid)
1769 #self.show_var(xvalid)
1770
1770
1771 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
1771 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
1772 a = gaussfn[1]
1772 a = gaussfn[1]
1773 converge = gaussfn[2]
1773 converge = gaussfn[2]
1774
1774
1775 xvalid = numpy.arange(np)
1775 xvalid = numpy.arange(np)
1776 spec2 = __GAUSSWINFIT1(a)
1776 spec2 = __GAUSSWINFIT1(a)
1777
1777
1778 xvalid = oldxvalid.copy()
1778 xvalid = oldxvalid.copy()
1779 power = a[0] * np
1779 power = a[0] * np
1780 fd = a[1]
1780 fd = a[1]
1781 sigma_fd = gaussfn[3][1]
1781 sigma_fd = gaussfn[3][1]
1782 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
1782 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
1783 w = numpy.abs(a[2])
1783 w = numpy.abs(a[2])
1784 n1 = max(a[3], n0)
1784 n1 = max(a[3], n0)
1785
1785
1786 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
1786 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
1787 else:
1787 else:
1788 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
1788 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
1789
1789
1790 vec_fd[ind] = fd
1790 vec_fd[ind] = fd
1791 vec_w[ind] = w
1791 vec_w[ind] = w
1792 vec_snr[ind] = snr
1792 vec_snr[ind] = snr
1793 vec_n1[ind] = n1
1793 vec_n1[ind] = n1
1794 vec_fp[ind] = fp
1794 vec_fp[ind] = fp
1795 vec_sigma_fd[ind] = sigma_fd
1795 vec_sigma_fd[ind] = sigma_fd
1796 vec_power[ind] = power # to compare with type 0 proccessing
1796 vec_power[ind] = power # to compare with type 0 proccessing
1797
1797
1798 if type1==1:
1798 if type1==1:
1799 return numpy.vstack((vec_snr, vec_w, vec_fd, vec_n1, vec_fp, vec_sigma_fd, vec_power)) # snr and fd exchanged to compare doppler of both types
1799 return numpy.vstack((vec_snr, vec_w, vec_fd, vec_n1, vec_fp, vec_sigma_fd, vec_power)) # snr and fd exchanged to compare doppler of both types
1800 else:
1800 else:
1801 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1801 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1802
1802
1803 def __get_noise2(self,POWER, fft_avg, TALK=0):
1803 def __get_noise2(self,POWER, fft_avg, TALK=0):
1804 '''
1804 '''
1805 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
1805 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
1806 '''
1806 '''
1807 SPECT_PTS = len(POWER)
1807 SPECT_PTS = len(POWER)
1808 fft_avg = fft_avg*1.0
1808 fft_avg = fft_avg*1.0
1809 NOMIT = 0
1809 NOMIT = 0
1810 NN = SPECT_PTS - NOMIT
1810 NN = SPECT_PTS - NOMIT
1811 N = NN//2
1811 N = NN//2
1812 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
1812 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
1813 ARR = numpy.sort(ARR)
1813 ARR = numpy.sort(ARR)
1814 NUMS_MIN = (SPECT_PTS+7)//8
1814 NUMS_MIN = (SPECT_PTS+7)//8
1815 RTEST = (1.0+1.0/fft_avg)
1815 RTEST = (1.0+1.0/fft_avg)
1816 SUM = 0.0
1816 SUM = 0.0
1817 SUMSQ = 0.0
1817 SUMSQ = 0.0
1818 J = 0
1818 J = 0
1819 for I in range(NN):
1819 for I in range(NN):
1820 J = J + 1
1820 J = J + 1
1821 SUM = SUM + ARR[I]
1821 SUM = SUM + ARR[I]
1822 SUMSQ = SUMSQ + ARR[I]*ARR[I]
1822 SUMSQ = SUMSQ + ARR[I]*ARR[I]
1823 AVE = SUM*1.0/J
1823 AVE = SUM*1.0/J
1824 if J > NUMS_MIN:
1824 if J > NUMS_MIN:
1825 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
1825 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
1826 else:
1826 else:
1827 if J == NUMS_MIN: RNOISE = AVE
1827 if J == NUMS_MIN: RNOISE = AVE
1828 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
1828 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
1829 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1829 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1830 return RNOISE, stdv
1830 return RNOISE, stdv
1831
1831
1832 def __get_noise1(self, power, fft_avg, TALK=0):
1832 def __get_noise1(self, power, fft_avg, TALK=0):
1833 '''
1833 '''
1834 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
1834 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
1835 '''
1835 '''
1836 num_pts = numpy.size(power)
1836 num_pts = numpy.size(power)
1837 #print('num_pts',num_pts)
1837 #print('num_pts',num_pts)
1838 #print('power',power.shape)
1838 #print('power',power.shape)
1839 #print(power[256:267,0:2])
1839 #print(power[256:267,0:2])
1840 fft_avg = fft_avg*1.0
1840 fft_avg = fft_avg*1.0
1841
1841
1842 ind = numpy.argsort(power, axis=None, kind='stable')
1842 ind = numpy.argsort(power, axis=None, kind='stable')
1843 #ind = numpy.argsort(numpy.reshape(power,-1))
1843 #ind = numpy.argsort(numpy.reshape(power,-1))
1844 #print(ind.shape)
1844 #print(ind.shape)
1845 #print(ind[0:11])
1845 #print(ind[0:11])
1846 #print(numpy.reshape(power,-1)[ind[0:11]])
1846 #print(numpy.reshape(power,-1)[ind[0:11]])
1847 ARR = numpy.reshape(power,-1)[ind]
1847 ARR = numpy.reshape(power,-1)[ind]
1848 #print('ARR',len(ARR))
1848 #print('ARR',len(ARR))
1849 #print('ARR',ARR.shape)
1849 #print('ARR',ARR.shape)
1850 NUMS_MIN = num_pts//10
1850 NUMS_MIN = num_pts//10
1851 RTEST = (1.0+1.0/fft_avg)
1851 RTEST = (1.0+1.0/fft_avg)
1852 SUM = 0.0
1852 SUM = 0.0
1853 SUMSQ = 0.0
1853 SUMSQ = 0.0
1854 J = 0
1854 J = 0
1855 cont = 1
1855 cont = 1
1856 while cont == 1 and J < num_pts:
1856 while cont == 1 and J < num_pts:
1857
1857
1858 SUM = SUM + ARR[J]
1858 SUM = SUM + ARR[J]
1859 SUMSQ = SUMSQ + ARR[J]*ARR[J]
1859 SUMSQ = SUMSQ + ARR[J]*ARR[J]
1860 J = J + 1
1860 J = J + 1
1861
1861
1862 if J > NUMS_MIN:
1862 if J > NUMS_MIN:
1863 if (SUMSQ*J <= RTEST*SUM*SUM):
1863 if (SUMSQ*J <= RTEST*SUM*SUM):
1864 LNOISE = SUM*1.0/J
1864 LNOISE = SUM*1.0/J
1865 else:
1865 else:
1866 J = J - 1
1866 J = J - 1
1867 SUM = SUM - ARR[J]
1867 SUM = SUM - ARR[J]
1868 SUMSQ = SUMSQ - ARR[J]*ARR[J]
1868 SUMSQ = SUMSQ - ARR[J]*ARR[J]
1869 cont = 0
1869 cont = 0
1870 else:
1870 else:
1871 if J == NUMS_MIN: LNOISE = SUM*1.0/J
1871 if J == NUMS_MIN: LNOISE = SUM*1.0/J
1872 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
1872 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
1873 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1873 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1874 return LNOISE, stdv
1874 return LNOISE, stdv
1875
1875
1876 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
1876 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
1877
1877
1878 val_frq = numpy.arange(num_prof-2)+1
1878 val_frq = numpy.arange(num_prof-2)+1
1879 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
1879 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
1880 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
1880 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
1881 junkid = numpy.argsort(junkspc)
1881 junkid = numpy.argsort(junkspc)
1882 noisezone = val_frq[junkid[0:num_prof//2]]
1882 noisezone = val_frq[junkid[0:num_prof//2]]
1883 specnoise = spectra[noisezone,:]
1883 specnoise = spectra[noisezone,:]
1884 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
1884 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
1885
1885
1886 if talk:
1886 if talk:
1887 print('noise =', noise)
1887 print('noise =', noise)
1888 return noise
1888 return noise
1889 #------------------ Get SA Parameters --------------------------
1889 #------------------ Get SA Parameters --------------------------
1890
1890
1891 def GetSAParameters(self):
1891 def GetSAParameters(self):
1892 #SA en frecuencia
1892 #SA en frecuencia
1893 pairslist = self.dataOut.groupList
1893 pairslist = self.dataOut.groupList
1894 num_pairs = len(pairslist)
1894 num_pairs = len(pairslist)
1895
1895
1896 vel = self.dataOut.abscissaList
1896 vel = self.dataOut.abscissaList
1897 spectra = self.dataOut.data_pre
1897 spectra = self.dataOut.data_pre
1898 cspectra = self.dataIn.data_cspc
1898 cspectra = self.dataIn.data_cspc
1899 delta_v = vel[1] - vel[0]
1899 delta_v = vel[1] - vel[0]
1900
1900
1901 #Calculating the power spectrum
1901 #Calculating the power spectrum
1902 spc_pow = numpy.sum(spectra, 3)*delta_v
1902 spc_pow = numpy.sum(spectra, 3)*delta_v
1903 #Normalizing Spectra
1903 #Normalizing Spectra
1904 norm_spectra = spectra/spc_pow
1904 norm_spectra = spectra/spc_pow
1905 #Calculating the norm_spectra at peak
1905 #Calculating the norm_spectra at peak
1906 max_spectra = numpy.max(norm_spectra, 3)
1906 max_spectra = numpy.max(norm_spectra, 3)
1907
1907
1908 #Normalizing Cross Spectra
1908 #Normalizing Cross Spectra
1909 norm_cspectra = numpy.zeros(cspectra.shape)
1909 norm_cspectra = numpy.zeros(cspectra.shape)
1910
1910
1911 for i in range(num_chan):
1911 for i in range(num_chan):
1912 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1912 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1913
1913
1914 max_cspectra = numpy.max(norm_cspectra,2)
1914 max_cspectra = numpy.max(norm_cspectra,2)
1915 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1915 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1916
1916
1917 for i in range(num_pairs):
1917 for i in range(num_pairs):
1918 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1918 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1919 #------------------- Get Lags ----------------------------------
1919 #------------------- Get Lags ----------------------------------
1920
1920
1921 class JULIADriftsEstimation(Operation):
1921 class JULIADriftsEstimation(Operation):
1922
1922
1923 def __init__(self):
1923 def __init__(self):
1924 Operation.__init__(self)
1924 Operation.__init__(self)
1925
1925
1926 def newtotal(self, data):
1926 def newtotal(self, data):
1927 return numpy.nansum(data)
1927 return numpy.nansum(data)
1928
1928
1929 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
1929 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
1930
1930
1931 Sz0 = parm.shape # Sz0: h,p
1931 Sz0 = parm.shape # Sz0: h,p
1932 drift = parm[:,0]
1932 drift = parm[:,0]
1933 sw = 2*parm[:,1]
1933 sw = 2*parm[:,1]
1934 snr = 10*numpy.log10(parm[:,2])
1934 snr = 10*numpy.log10(parm[:,2])
1935 Sz = drift.shape # Sz: h
1935 Sz = drift.shape # Sz: h
1936 mask = numpy.ones((Sz[0]))
1936 mask = numpy.ones((Sz[0]))
1937 th=0
1937 th=0
1938 valid=numpy.where(numpy.isfinite(snr))
1938 valid=numpy.where(numpy.isfinite(snr))
1939 cvalid = len(valid[0])
1939 cvalid = len(valid[0])
1940 if cvalid >= 1:
1940 if cvalid >= 1:
1941 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
1941 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
1942 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
1942 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
1943 h = numpy.histogram(snr,bins=nbins)
1943 h = numpy.histogram(snr,bins=nbins)
1944 hist = h[0]
1944 hist = h[0]
1945 values = numpy.round_(h[1])
1945 values = numpy.round_(h[1])
1946 moda = values[numpy.where(hist == numpy.max(hist))]
1946 moda = values[numpy.where(hist == numpy.max(hist))]
1947 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
1947 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
1948
1948
1949 noise = snr[indNoise]
1949 noise = snr[indNoise]
1950 noise_mean = numpy.sum(noise)/len(noise)
1950 noise_mean = numpy.sum(noise)/len(noise)
1951 # CΓ‘lculo de media de snr
1951 # CΓ‘lculo de media de snr
1952 med = numpy.median(snr)
1952 med = numpy.median(snr)
1953 # Establece el umbral de snr
1953 # Establece el umbral de snr
1954 if noise_mean > med + 3:
1954 if noise_mean > med + 3:
1955 th = med
1955 th = med
1956 else:
1956 else:
1957 th = noise_mean + 3
1957 th = noise_mean + 3
1958 # Establece mΓ‘scara
1958 # Establece mΓ‘scara
1959 novalid = numpy.where(snr <= th)[0]
1959 novalid = numpy.where(snr <= th)[0]
1960 mask[novalid] = numpy.nan
1960 mask[novalid] = numpy.nan
1961 # Elimina datos que no sobrepasen el umbral: PARAMETRO
1961 # Elimina datos que no sobrepasen el umbral: PARAMETRO
1962 novalid = numpy.where(snr <= snrth)
1962 novalid = numpy.where(snr <= snrth)
1963 cnovalid = len(novalid[0])
1963 cnovalid = len(novalid[0])
1964 if cnovalid > 0:
1964 if cnovalid > 0:
1965 mask[novalid] = numpy.nan
1965 mask[novalid] = numpy.nan
1966 novalid = numpy.where(numpy.isnan(snr))
1966 novalid = numpy.where(numpy.isnan(snr))
1967 cnovalid = len(novalid[0])
1967 cnovalid = len(novalid[0])
1968 if cnovalid > 0:
1968 if cnovalid > 0:
1969 mask[novalid] = numpy.nan
1969 mask[novalid] = numpy.nan
1970 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
1970 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
1971 for h in range(Sz0[0]):
1971 for h in range(Sz0[0]):
1972 for p in range(Sz0[1]):
1972 for p in range(Sz0[1]):
1973 if numpy.isnan(mask[h]):
1973 if numpy.isnan(mask[h]):
1974 new_parm[h,p]=numpy.nan
1974 new_parm[h,p]=numpy.nan
1975 else:
1975 else:
1976 new_parm[h,p]=parm[h,p]
1976 new_parm[h,p]=parm[h,p]
1977
1977
1978 return new_parm, th
1978 return new_parm, th
1979
1979
1980 def run(self, dataOut, zenith, zenithCorrection,heights=None, statistics=0, otype=0):
1980 def run(self, dataOut, zenith, zenithCorrection,heights=None, statistics=0, otype=0):
1981
1981
1982 nCh=dataOut.spcpar.shape[0]
1982 nCh=dataOut.spcpar.shape[0]
1983 nHei=dataOut.spcpar.shape[1]
1983 nHei=dataOut.spcpar.shape[1]
1984 nParam=dataOut.spcpar.shape[2]
1984 nParam=dataOut.spcpar.shape[2]
1985 # Solo las alturas de interes
1985 # Solo las alturas de interes
1986 hei=dataOut.heightList
1986 hei=dataOut.heightList
1987 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
1987 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
1988 nhvalid=len(hvalid)
1988 nhvalid=len(hvalid)
1989 parm = numpy.zeros((nCh,nhvalid,nParam))
1989 parm = numpy.zeros((nCh,nhvalid,nParam))
1990 parm = dataOut.spcpar[:,hvalid,:]
1990 parm = dataOut.spcpar[:,hvalid,:]
1991 # Primer filtrado: Umbral de SNR
1991 # Primer filtrado: Umbral de SNR
1992 for i in range(nCh):
1992 for i in range(nCh):
1993 dataOut.spcpar[i,hvalid,:] = self.data_filter(parm[i,:,:])[0]
1993 dataOut.spcpar[i,hvalid,:] = self.data_filter(parm[i,:,:])[0]
1994 zenith = numpy.array(zenith)
1994 zenith = numpy.array(zenith)
1995 zenith -= zenithCorrection
1995 zenith -= zenithCorrection
1996 zenith *= numpy.pi/180
1996 zenith *= numpy.pi/180
1997 alpha = zenith[0]
1997 alpha = zenith[0]
1998 beta = zenith[1]
1998 beta = zenith[1]
1999
1999
2000 dopplerCH0 = dataOut.spcpar[0,:,0]
2000 dopplerCH0 = dataOut.spcpar[0,:,0]
2001 dopplerCH1 = dataOut.spcpar[1,:,0]
2001 dopplerCH1 = dataOut.spcpar[1,:,0]
2002 swCH0 = dataOut.spcpar[0,:,1]
2002 swCH0 = dataOut.spcpar[0,:,1]
2003 swCH1 = dataOut.spcpar[1,:,1]
2003 swCH1 = dataOut.spcpar[1,:,1]
2004 snrCH0 = 10*numpy.log10(dataOut.spcpar[0,:,2])
2004 snrCH0 = 10*numpy.log10(dataOut.spcpar[0,:,2])
2005 snrCH1 = 10*numpy.log10(dataOut.spcpar[1,:,2])
2005 snrCH1 = 10*numpy.log10(dataOut.spcpar[1,:,2])
2006 noiseCH0 = dataOut.spcpar[0,:,3]
2006 noiseCH0 = dataOut.spcpar[0,:,3]
2007 noiseCH1 = dataOut.spcpar[1,:,3]
2007 noiseCH1 = dataOut.spcpar[1,:,3]
2008 wErrCH0 = dataOut.spcpar[0,:,5]
2008 wErrCH0 = dataOut.spcpar[0,:,5]
2009 wErrCH1 = dataOut.spcpar[1,:,5]
2009 wErrCH1 = dataOut.spcpar[1,:,5]
2010
2010
2011 # Vertical and zonal calculation according to geometry
2011 # Vertical and zonal calculation according to geometry
2012 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
2012 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
2013 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
2013 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
2014 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
2014 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
2015 snr = (snrCH0 + snrCH1)/2
2015 snr = (snrCH0 + snrCH1)/2
2016 noise = (noiseCH0 + noiseCH1)/2
2016 noise = (noiseCH0 + noiseCH1)/2
2017 sw = (swCH0 + swCH1)/2
2017 sw = (swCH0 + swCH1)/2
2018 w_w_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.sin(beta)/numpy.abs(sinB_A),2) + numpy.power(wErrCH1 * numpy.sin(alpha)/numpy.abs(sinB_A),2))
2018 w_w_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.sin(beta)/numpy.abs(sinB_A),2) + numpy.power(wErrCH1 * numpy.sin(alpha)/numpy.abs(sinB_A),2))
2019 w_e_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.cos(beta)/numpy.abs(-1*sinB_A),2) + numpy.power(wErrCH1 * numpy.cos(alpha)/numpy.abs(-1*sinB_A),2))
2019 w_e_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.cos(beta)/numpy.abs(-1*sinB_A),2) + numpy.power(wErrCH1 * numpy.cos(alpha)/numpy.abs(-1*sinB_A),2))
2020
2020
2021 # for statistics150km
2021 # for statistics150km
2022 if statistics:
2022 if statistics:
2023 print('Implemented offline.')
2023 print('Implemented offline.')
2024 if otype == 0:
2024 if otype == 0:
2025 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
2025 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
2026 elif otype == 3:
2026 elif otype == 3:
2027 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
2027 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
2028 elif otype == 4:
2028 elif otype == 4:
2029 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
2029 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
2030
2030
2031 snr1 = numpy.vstack((snrCH0, snrCH1))
2031 snr1 = numpy.vstack((snrCH0, snrCH1))
2032 dataOut.data_output = winds
2032 dataOut.data_output = winds
2033 dataOut.data_snr = snr1
2033 dataOut.data_snr = snr1
2034
2034
2035 dataOut.utctimeInit = dataOut.utctime
2035 dataOut.utctimeInit = dataOut.utctime
2036 dataOut.outputInterval = dataOut.timeInterval
2036 dataOut.outputInterval = dataOut.timeInterval
2037
2037
2038 return dataOut
2038 return dataOut
2039
2039
2040 class SALags(Operation):
2040 class SALags(Operation):
2041 '''
2041 '''
2042 Function GetMoments()
2042 Function GetMoments()
2043
2043
2044 Input:
2044 Input:
2045 self.dataOut.data_pre
2045 self.dataOut.data_pre
2046 self.dataOut.abscissaList
2046 self.dataOut.abscissaList
2047 self.dataOut.noise
2047 self.dataOut.noise
2048 self.dataOut.normFactor
2048 self.dataOut.normFactor
2049 self.dataOut.data_snr
2049 self.dataOut.data_snr
2050 self.dataOut.groupList
2050 self.dataOut.groupList
2051 self.dataOut.nChannels
2051 self.dataOut.nChannels
2052
2052
2053 Affected:
2053 Affected:
2054 self.dataOut.data_param
2054 self.dataOut.data_param
2055
2055
2056 '''
2056 '''
2057 def run(self, dataOut):
2057 def run(self, dataOut):
2058 data_acf = dataOut.data_pre[0]
2058 data_acf = dataOut.data_pre[0]
2059 data_ccf = dataOut.data_pre[1]
2059 data_ccf = dataOut.data_pre[1]
2060 normFactor_acf = dataOut.normFactor[0]
2060 normFactor_acf = dataOut.normFactor[0]
2061 normFactor_ccf = dataOut.normFactor[1]
2061 normFactor_ccf = dataOut.normFactor[1]
2062 pairs_acf = dataOut.groupList[0]
2062 pairs_acf = dataOut.groupList[0]
2063 pairs_ccf = dataOut.groupList[1]
2063 pairs_ccf = dataOut.groupList[1]
2064
2064
2065 nHeights = dataOut.nHeights
2065 nHeights = dataOut.nHeights
2066 absc = dataOut.abscissaList
2066 absc = dataOut.abscissaList
2067 noise = dataOut.noise
2067 noise = dataOut.noise
2068 SNR = dataOut.data_snr
2068 SNR = dataOut.data_snr
2069 nChannels = dataOut.nChannels
2069 nChannels = dataOut.nChannels
2070 for l in range(len(pairs_acf)):
2070 for l in range(len(pairs_acf)):
2071 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
2071 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
2072
2072
2073 for l in range(len(pairs_ccf)):
2073 for l in range(len(pairs_ccf)):
2074 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
2074 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
2075
2075
2076 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
2076 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
2077 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
2077 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
2078 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
2078 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
2079 return
2079 return
2080
2080
2081 def __calculateTaus(self, data_acf, data_ccf, lagRange):
2081 def __calculateTaus(self, data_acf, data_ccf, lagRange):
2082
2082
2083 lag0 = data_acf.shape[1]/2
2083 lag0 = data_acf.shape[1]/2
2084 #Funcion de Autocorrelacion
2084 #Funcion de Autocorrelacion
2085 mean_acf = stats.nanmean(data_acf, axis = 0)
2085 mean_acf = stats.nanmean(data_acf, axis = 0)
2086
2086
2087 #Obtencion Indice de TauCross
2087 #Obtencion Indice de TauCross
2088 ind_ccf = data_ccf.argmax(axis = 1)
2088 ind_ccf = data_ccf.argmax(axis = 1)
2089 #Obtencion Indice de TauAuto
2089 #Obtencion Indice de TauAuto
2090 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
2090 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
2091 ccf_lag0 = data_ccf[:,lag0,:]
2091 ccf_lag0 = data_ccf[:,lag0,:]
2092
2092
2093 for i in range(ccf_lag0.shape[0]):
2093 for i in range(ccf_lag0.shape[0]):
2094 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
2094 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
2095
2095
2096 #Obtencion de TauCross y TauAuto
2096 #Obtencion de TauCross y TauAuto
2097 tau_ccf = lagRange[ind_ccf]
2097 tau_ccf = lagRange[ind_ccf]
2098 tau_acf = lagRange[ind_acf]
2098 tau_acf = lagRange[ind_acf]
2099
2099
2100 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
2100 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
2101
2101
2102 tau_ccf[Nan1,Nan2] = numpy.nan
2102 tau_ccf[Nan1,Nan2] = numpy.nan
2103 tau_acf[Nan1,Nan2] = numpy.nan
2103 tau_acf[Nan1,Nan2] = numpy.nan
2104 tau = numpy.vstack((tau_ccf,tau_acf))
2104 tau = numpy.vstack((tau_ccf,tau_acf))
2105
2105
2106 return tau
2106 return tau
2107
2107
2108 def __calculateLag1Phase(self, data, lagTRange):
2108 def __calculateLag1Phase(self, data, lagTRange):
2109 data1 = stats.nanmean(data, axis = 0)
2109 data1 = stats.nanmean(data, axis = 0)
2110 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
2110 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
2111
2111
2112 phase = numpy.angle(data1[lag1,:])
2112 phase = numpy.angle(data1[lag1,:])
2113
2113
2114 return phase
2114 return phase
2115
2115
2116 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
2116 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
2117 z = (x - a1) / a2
2117 z = (x - a1) / a2
2118 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
2118 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
2119 return y
2119 return y
2120
2120
2121
2121
2122 class SpectralFitting(Operation):
2122 class SpectralFitting(Operation):
2123 '''
2123 '''
2124 Function GetMoments()
2124 Function GetMoments()
2125
2125
2126 Input:
2126 Input:
2127 Output:
2127 Output:
2128 Variables modified:
2128 Variables modified:
2129 '''
2129 '''
2130 isConfig = False
2130 isConfig = False
2131 __dataReady = False
2131 __dataReady = False
2132 bloques = None
2132 bloques = None
2133 bloque0 = None
2133 bloque0 = None
2134 index = 0
2134 index = 0
2135 fint = 0
2135 fint = 0
2136 buffer = 0
2136 buffer = 0
2137 buffer2 = 0
2137 buffer2 = 0
2138 buffer3 = 0
2138 buffer3 = 0
2139
2139
2140 def __init__(self):
2140 def __init__(self):
2141 Operation.__init__(self)
2141 Operation.__init__(self)
2142 self.i=0
2142 self.i=0
2143 self.isConfig = False
2143 self.isConfig = False
2144
2144
2145
2145
2146 def setup(self,nChan,nProf,nHei,nBlocks):
2146 def setup(self,nChan,nProf,nHei,nBlocks):
2147 self.__dataReady = False
2147 self.__dataReady = False
2148 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
2148 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
2149 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
2149 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
2150
2150
2151 def __calculateMoments(self,oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
2151 def __calculateMoments(self,oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
2152
2152
2153 if (nicoh is None): nicoh = 1
2153 if (nicoh is None): nicoh = 1
2154 if (graph is None): graph = 0
2154 if (graph is None): graph = 0
2155 if (smooth is None): smooth = 0
2155 if (smooth is None): smooth = 0
2156 elif (self.smooth < 3): smooth = 0
2156 elif (self.smooth < 3): smooth = 0
2157
2157
2158 if (type1 is None): type1 = 0
2158 if (type1 is None): type1 = 0
2159 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2159 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2160 if (snrth is None): snrth = -3
2160 if (snrth is None): snrth = -3
2161 if (dc is None): dc = 0
2161 if (dc is None): dc = 0
2162 if (aliasing is None): aliasing = 0
2162 if (aliasing is None): aliasing = 0
2163 if (oldfd is None): oldfd = 0
2163 if (oldfd is None): oldfd = 0
2164 if (wwauto is None): wwauto = 0
2164 if (wwauto is None): wwauto = 0
2165
2165
2166 if (n0 < 1.e-20): n0 = 1.e-20
2166 if (n0 < 1.e-20): n0 = 1.e-20
2167
2167
2168 freq = oldfreq
2168 freq = oldfreq
2169 vec_power = numpy.zeros(oldspec.shape[1])
2169 vec_power = numpy.zeros(oldspec.shape[1])
2170 vec_fd = numpy.zeros(oldspec.shape[1])
2170 vec_fd = numpy.zeros(oldspec.shape[1])
2171 vec_w = numpy.zeros(oldspec.shape[1])
2171 vec_w = numpy.zeros(oldspec.shape[1])
2172 vec_snr = numpy.zeros(oldspec.shape[1])
2172 vec_snr = numpy.zeros(oldspec.shape[1])
2173
2173
2174 oldspec = numpy.ma.masked_invalid(oldspec)
2174 oldspec = numpy.ma.masked_invalid(oldspec)
2175
2175
2176 for ind in range(oldspec.shape[1]):
2176 for ind in range(oldspec.shape[1]):
2177
2177
2178 spec = oldspec[:,ind]
2178 spec = oldspec[:,ind]
2179 aux = spec*fwindow
2179 aux = spec*fwindow
2180 max_spec = aux.max()
2180 max_spec = aux.max()
2181 m = list(aux).index(max_spec)
2181 m = list(aux).index(max_spec)
2182
2182
2183 #Smooth
2183 #Smooth
2184 if (smooth == 0): spec2 = spec
2184 if (smooth == 0): spec2 = spec
2185 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2185 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2186
2186
2187 # Calculo de Momentos
2187 # Calculo de Momentos
2188 bb = spec2[list(range(m,spec2.size))]
2188 bb = spec2[list(range(m,spec2.size))]
2189 bb = (bb<n0).nonzero()
2189 bb = (bb<n0).nonzero()
2190 bb = bb[0]
2190 bb = bb[0]
2191
2191
2192 ss = spec2[list(range(0,m + 1))]
2192 ss = spec2[list(range(0,m + 1))]
2193 ss = (ss<n0).nonzero()
2193 ss = (ss<n0).nonzero()
2194 ss = ss[0]
2194 ss = ss[0]
2195
2195
2196 if (bb.size == 0):
2196 if (bb.size == 0):
2197 bb0 = spec.size - 1 - m
2197 bb0 = spec.size - 1 - m
2198 else:
2198 else:
2199 bb0 = bb[0] - 1
2199 bb0 = bb[0] - 1
2200 if (bb0 < 0):
2200 if (bb0 < 0):
2201 bb0 = 0
2201 bb0 = 0
2202
2202
2203 if (ss.size == 0): ss1 = 1
2203 if (ss.size == 0): ss1 = 1
2204 else: ss1 = max(ss) + 1
2204 else: ss1 = max(ss) + 1
2205
2205
2206 if (ss1 > m): ss1 = m
2206 if (ss1 > m): ss1 = m
2207
2207
2208 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
2208 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
2209 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
2209 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
2210 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
2210 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
2211 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2211 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2212 snr = (spec2.mean()-n0)/n0
2212 snr = (spec2.mean()-n0)/n0
2213
2213
2214 if (snr < 1.e-20) :
2214 if (snr < 1.e-20) :
2215 snr = 1.e-20
2215 snr = 1.e-20
2216
2216
2217 vec_power[ind] = power
2217 vec_power[ind] = power
2218 vec_fd[ind] = fd
2218 vec_fd[ind] = fd
2219 vec_w[ind] = w
2219 vec_w[ind] = w
2220 vec_snr[ind] = snr
2220 vec_snr[ind] = snr
2221
2221
2222 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2222 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2223 return moments
2223 return moments
2224
2224
2225 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
2225 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
2226
2226 nProf = dataOut.nProfiles
2227 nProf = dataOut.nProfiles
2227 heights = dataOut.heightList
2228 heights = dataOut.heightList
2228 nHei = len(heights)
2229 nHei = len(heights)
2229 channels = dataOut.channelList
2230 channels = dataOut.channelList
2230 nChan = len(channels)
2231 nChan = len(channels)
2231 crosspairs = dataOut.groupList
2232 crosspairs = dataOut.groupList
2232 nPairs = len(crosspairs)
2233 nPairs = len(crosspairs)
2233 #Separar espectros incoherentes de coherentes snr > 20 dB'
2234 #Separar espectros incoherentes de coherentes snr > 20 dB'
2234 snr_th = 10**(snrth/10.0)
2235 snr_th = 10**(snrth/10.0)
2235 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
2236 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
2236 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
2237 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
2237 my_incoh_aver = numpy.zeros([nChan, nHei])
2238 my_incoh_aver = numpy.zeros([nChan, nHei])
2238 my_coh_aver = numpy.zeros([nChan, nHei])
2239 my_coh_aver = numpy.zeros([nChan, nHei])
2239
2240
2240 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2241 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2241 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2242 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2242 coh_aver = numpy.zeros([nChan, nHei])
2243 coh_aver = numpy.zeros([nChan, nHei])
2243
2244
2244 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2245 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2245 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2246 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2246 incoh_aver = numpy.zeros([nChan, nHei])
2247 incoh_aver = numpy.zeros([nChan, nHei])
2247 power = numpy.sum(spectra, axis=1)
2248 power = numpy.sum(spectra, axis=1)
2248
2249
2249 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
2250 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
2250 if hei_th == None : hei_th = numpy.array([60,300,650])
2251 if hei_th == None : hei_th = numpy.array([60,300,650])
2251 for ic in range(2):
2252 for ic in range(nPairs):
2252 pair = crosspairs[ic]
2253 pair = crosspairs[ic]
2253 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
2254 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
2254 s_n0 = power[pair[0],:]/noise[pair[0]]
2255 s_n0 = power[pair[0],:]/noise[pair[0]]
2255 s_n1 = power[pair[1],:]/noise[pair[1]]
2256 s_n1 = power[pair[1],:]/noise[pair[1]]
2256
2257 valid1 =(s_n0>=snr_th).nonzero()
2257 valid1 =(s_n0>=snr_th).nonzero()
2258 valid2 = (s_n1>=snr_th).nonzero()
2258 valid2 = (s_n1>=snr_th).nonzero()
2259 #valid = valid2 + valid1 #numpy.concatenate((valid1,valid2), axis=None)
2260 valid1 = numpy.array(valid1[0])
2259 valid1 = numpy.array(valid1[0])
2261 valid2 = numpy.array(valid2[0])
2260 valid2 = numpy.array(valid2[0])
2262 valid = valid1
2261 valid = valid1
2263 for iv in range(len(valid2)):
2262 for iv in range(len(valid2)):
2264 #for ivv in range(len(valid1)) :
2265 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2263 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2266 if len(indv[0]) == 0 :
2264 if len(indv[0]) == 0 :
2267 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2265 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2268 if len(valid)>0:
2266 if len(valid)>0:
2269 my_coh_aver[pair[0],valid]=1
2267 my_coh_aver[pair[0],valid]=1
2270 my_coh_aver[pair[1],valid]=1
2268 my_coh_aver[pair[1],valid]=1
2271 # si la coherencia es mayor a la coherencia threshold los datos se toman
2269 # si la coherencia es mayor a la coherencia threshold los datos se toman
2272 #print my_coh_aver[0,:]
2273 coh = numpy.squeeze(numpy.nansum(cspectra[ic,:,:], axis=0)/numpy.sqrt(numpy.nansum(spectra[pair[0],:,:], axis=0)*numpy.nansum(spectra[pair[1],:,:], axis=0)))
2270 coh = numpy.squeeze(numpy.nansum(cspectra[ic,:,:], axis=0)/numpy.sqrt(numpy.nansum(spectra[pair[0],:,:], axis=0)*numpy.nansum(spectra[pair[1],:,:], axis=0)))
2274 #print('coh',numpy.absolute(coh))
2275 for ih in range(len(hei_th)):
2271 for ih in range(len(hei_th)):
2276 hvalid = (heights>hei_th[ih]).nonzero()
2272 hvalid = (heights>hei_th[ih]).nonzero()
2277 hvalid = hvalid[0]
2273 hvalid = hvalid[0]
2278 if len(hvalid)>0:
2274 if len(hvalid)>0:
2279 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
2275 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
2280 valid = valid[0]
2276 valid = valid[0]
2281 #print('hvalid:',hvalid)
2282 #print('valid', valid)
2283 if len(valid)>0:
2277 if len(valid)>0:
2284 my_coh_aver[pair[0],hvalid[valid]] =1
2278 my_coh_aver[pair[0],hvalid[valid]] =1
2285 my_coh_aver[pair[1],hvalid[valid]] =1
2279 my_coh_aver[pair[1],hvalid[valid]] =1
2286
2280
2287 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
2281 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
2288 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
2282 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
2289 incoh_echoes = incoh_echoes[0]
2283 incoh_echoes = incoh_echoes[0]
2290 if len(incoh_echoes) > 0:
2284 if len(incoh_echoes) > 0:
2291 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2285 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2292 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2286 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2293 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2287 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2294 my_incoh_aver[pair[0],incoh_echoes] = 1
2288 my_incoh_aver[pair[0],incoh_echoes] = 1
2295 my_incoh_aver[pair[1],incoh_echoes] = 1
2289 my_incoh_aver[pair[1],incoh_echoes] = 1
2296
2290
2297
2291
2298 for ic in range(2):
2292 for ic in range(nPairs):
2299 pair = crosspairs[ic]
2293 pair = crosspairs[ic]
2300
2294
2301 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
2295 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
2302 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
2296 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
2303 valid1 = numpy.array(valid1[0])
2297 valid1 = numpy.array(valid1[0])
2304 valid2 = numpy.array(valid2[0])
2298 valid2 = numpy.array(valid2[0])
2305 valid = valid1
2299 valid = valid1
2306 #print valid1 , valid2
2300
2307 for iv in range(len(valid2)):
2301 for iv in range(len(valid2)):
2308 #for ivv in range(len(valid1)) :
2302
2309 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2303 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2310 if len(indv[0]) == 0 :
2304 if len(indv[0]) == 0 :
2311 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2305 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2312 #print valid
2313 #valid = numpy.concatenate((valid1,valid2), axis=None)
2314 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
2306 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
2315 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
2307 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
2316 valid1 = numpy.array(valid1[0])
2308 valid1 = numpy.array(valid1[0])
2317 valid2 = numpy.array(valid2[0])
2309 valid2 = numpy.array(valid2[0])
2318 incoh_echoes = valid1
2310 incoh_echoes = valid1
2319 #print valid1, valid2
2320 #incoh_echoes= numpy.concatenate((valid1,valid2), axis=None)
2321 for iv in range(len(valid2)):
2311 for iv in range(len(valid2)):
2322 #for ivv in range(len(valid1)) :
2312
2323 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2313 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2324 if len(indv[0]) == 0 :
2314 if len(indv[0]) == 0 :
2325 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
2315 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
2326 #print incoh_echoes
2316
2327 if len(valid)>0:
2317 if len(valid)>0:
2328 #print pair
2329 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
2318 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
2330 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
2319 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
2331 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
2320 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
2332 coh_aver[pair[0],valid]=1
2321 coh_aver[pair[0],valid]=1
2333 coh_aver[pair[1],valid]=1
2322 coh_aver[pair[1],valid]=1
2334 if len(incoh_echoes)>0:
2323 if len(incoh_echoes)>0:
2335 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2324 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2336 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2325 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2337 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2326 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2338 incoh_aver[pair[0],incoh_echoes]=1
2327 incoh_aver[pair[0],incoh_echoes]=1
2339 incoh_aver[pair[1],incoh_echoes]=1
2328 incoh_aver[pair[1],incoh_echoes]=1
2340 return my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver
2329 return my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver
2341
2330
2331
2342 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
2332 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
2343
2333
2344 nProf = dataOut.nProfiles
2334 nProf = dataOut.nProfiles
2345 heights = dataOut.heightList
2335 heights = dataOut.heightList
2346 nHei = len(heights)
2336 nHei = len(heights)
2347 channels = dataOut.channelList
2337 channels = dataOut.channelList
2348 nChan = len(channels)
2338 nChan = len(channels)
2349 crosspairs = dataOut.groupList
2339 crosspairs = dataOut.groupList
2350 nPairs = len(crosspairs)
2340 nPairs = len(crosspairs)
2351
2341
2352 #data = dataOut.data_pre[0]
2353 absc = dataOut.abscissaList[:-1]
2342 absc = dataOut.abscissaList[:-1]
2354 #noise = dataOut.noise
2355 #nChannel = data.shape[0]
2356 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
2343 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
2357 clean_coh_spectra = spectra.copy()
2344 clean_coh_spectra = spectra.copy()
2358 clean_coh_cspectra = cspectra.copy()
2345 clean_coh_cspectra = cspectra.copy()
2359 clean_coh_aver = coh_aver.copy()
2346 clean_coh_aver = coh_aver.copy()
2360
2347
2361 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
2348 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
2362 coh_th = 0.75
2349 coh_th = 0.75
2363
2350
2364 rtime0 = [6,18] # periodo sin ESF
2351 rtime0 = [6,18] # periodo sin ESF
2365 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
2352 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
2366
2353
2367 time = index*5./60
2354 time = index*5./60 # en base a 5 min de proceso
2368 if clean_coh_echoes == 1 :
2355 if clean_coh_echoes == 1 :
2369 for ind in range(nChan):
2356 for ind in range(nChan):
2370 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
2357 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
2371 #print data_param[:,3]
2372 spwd = data_param[:,3]
2358 spwd = data_param[:,3]
2373 #print spwd.shape
2374 # SPECB_JULIA,header=anal_header,jspectra=spectra,vel=velocities,hei=heights, num_aver=1, mode_fit=0,smoothing=smoothing,jvelr=velr,jspwd=spwd,jsnr=snr,jnoise=noise,jstdvnoise=stdvnoise
2359 # SPECB_JULIA,header=anal_header,jspectra=spectra,vel=velocities,hei=heights, num_aver=1, mode_fit=0,smoothing=smoothing,jvelr=velr,jspwd=spwd,jsnr=snr,jnoise=noise,jstdvnoise=stdvnoise
2375 #spwd1=[ 1.65607, 1.43416, 0.500373, 0.208361, 0.000000, 26.7767, 22.5936, 26.7530, 20.6962, 29.1098, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 28.0300, 27.0511, 27.8810, 26.3126, 27.8445, 24.6181, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000]
2376 #spwd=numpy.array([spwd1,spwd1,spwd1,spwd1])
2377 #print spwd.shape, heights.shape,coh_aver.shape
2378 # para obtener spwd
2360 # para obtener spwd
2379 for ic in range(nPairs):
2361 for ic in range(nPairs):
2380 pair = crosspairs[ic]
2362 pair = crosspairs[ic]
2381 coh = numpy.squeeze(numpy.sum(cspectra[ic,:,:], axis=1)/numpy.sqrt(numpy.sum(spectra[pair[0],:,:], axis=1)*numpy.sum(spectra[pair[1],:,:], axis=1)))
2363 coh = numpy.squeeze(numpy.sum(cspectra[ic,:,:], axis=1)/numpy.sqrt(numpy.sum(spectra[pair[0],:,:], axis=1)*numpy.sum(spectra[pair[1],:,:], axis=1)))
2382 for ih in range(nHei) :
2364 for ih in range(nHei) :
2383 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
2365 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
2384 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
2366 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
2385 # Checking coherence
2367 # Checking coherence
2386 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
2368 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
2387 # Checking spectral widths
2369 # Checking spectral widths
2388 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
2370 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
2389 # satelite
2371 # satelite
2390 clean_coh_spectra[pair,ih,:] = 0.0
2372 clean_coh_spectra[pair,ih,:] = 0.0
2391 clean_coh_cspectra[ic,ih,:] = 0.0
2373 clean_coh_cspectra[ic,ih,:] = 0.0
2392 clean_coh_aver[pair,ih] = 0
2374 clean_coh_aver[pair,ih] = 0
2393 else :
2375 else :
2394 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
2376 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
2395 # Especial event like sun.
2377 # Especial event like sun.
2396 clean_coh_spectra[pair,ih,:] = 0.0
2378 clean_coh_spectra[pair,ih,:] = 0.0
2397 clean_coh_cspectra[ic,ih,:] = 0.0
2379 clean_coh_cspectra[ic,ih,:] = 0.0
2398 clean_coh_aver[pair,ih] = 0
2380 clean_coh_aver[pair,ih] = 0
2399
2381
2400 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
2382 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
2401
2383
2402 #def CleanRayleigh(self,dataOut,spectra,cspectra,out_spectra,out_cspectra,sat_spectra,sat_cspectra,crosspairs,heights, channels, nProf,nHei,nChan,nPairs,nIncohInt,nBlocks):
2403 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
2384 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
2404 #import matplotlib.pyplot as plt
2385
2405 #for k in range(149):
2386 rfunc = cspectra.copy()
2406
2407 # self.bloque0[:,:,:,k] = spectra[:,:,0:nHei]
2408 # self.bloques[:,:,:,k] = cspectra[:,:,0:nHei]
2409 #if self.i==nBlocks:
2410 # self.i==0
2411 rfunc = cspectra.copy() #self.bloques
2412 n_funct = len(rfunc[0,:,0,0])
2387 n_funct = len(rfunc[0,:,0,0])
2413 val_spc = spectra*0.0 #self.bloque0*0.0
2388 val_spc = spectra*0.0
2414 val_cspc = cspectra*0.0 #self.bloques*0.0
2389 val_cspc = cspectra*0.0
2415 in_sat_spectra = spectra.copy() #self.bloque0
2390 in_sat_spectra = spectra.copy()
2416 in_sat_cspectra = cspectra.copy() #self.bloques
2391 in_sat_cspectra = cspectra.copy()
2417
2392
2418 #print( rfunc.shape)
2419 min_hei = 200
2393 min_hei = 200
2420 nProf = dataOut.nProfiles
2394 nProf = dataOut.nProfiles
2421 heights = dataOut.heightList
2395 heights = dataOut.heightList
2422 nHei = len(heights)
2396 nHei = len(heights)
2423 channels = dataOut.channelList
2397 channels = dataOut.channelList
2424 nChan = len(channels)
2398 nChan = len(channels)
2425 crosspairs = dataOut.groupList
2399 crosspairs = dataOut.groupList
2426 nPairs = len(crosspairs)
2400 nPairs = len(crosspairs)
2427 hval=(heights >= min_hei).nonzero()
2401 hval=(heights >= min_hei).nonzero()
2428 ih=hval[0]
2402 ih=hval[0]
2429 #print numpy.absolute(rfunc[:,0,0,14])
2430 for ih in range(hval[0][0],nHei):
2403 for ih in range(hval[0][0],nHei):
2431 for ifreq in range(nProf):
2404 for ifreq in range(nProf):
2432 for ii in range(n_funct):
2405 for ii in range(n_funct):
2433
2406
2434 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
2407 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
2435 #print numpy.amin(func2clean)
2436 val = (numpy.isfinite(func2clean)==True).nonzero()
2408 val = (numpy.isfinite(func2clean)==True).nonzero()
2437 if len(val)>0:
2409 if len(val)>0:
2438 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
2410 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
2439 if min_val <= -40 : min_val = -40
2411 if min_val <= -40 : min_val = -40
2440 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
2412 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
2441 if max_val >= 200 : max_val = 200
2413 if max_val >= 200 : max_val = 200
2442 #print min_val, max_val
2443 step = 1
2414 step = 1
2444 #Getting bins and the histogram
2415 #Getting bins and the histogram
2445 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
2416 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
2446 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
2417 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
2447 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
2418 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
2448 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
2419 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
2449 parg = [numpy.amax(y_dist),mean,sigma]
2420 parg = [numpy.amax(y_dist),mean,sigma]
2450 try :
2421 try :
2451 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
2422 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
2452 mode = gauss_fit[1]
2423 mode = gauss_fit[1]
2453 stdv = gauss_fit[2]
2424 stdv = gauss_fit[2]
2454 except:
2425 except:
2455 mode = mean
2426 mode = mean
2456 stdv = sigma
2427 stdv = sigma
2457 # 7.84616 53.9307 3.61863
2458 #stdv = 3.61863 # 2.99089
2459 #mode = 53.9307 #7.79008
2460
2428
2461 #Removing echoes greater than mode + 3*stdv
2429 #Removing echoes greater than mode + 3*stdv
2462 factor_stdv = 2.5
2430 factor_stdv = 2.5
2463 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
2431 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
2464
2432
2465 if len(noval[0]) > 0:
2433 if len(noval[0]) > 0:
2466 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
2434 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
2467 cross_pairs = crosspairs[ii]
2435 cross_pairs = crosspairs[ii]
2468 #Getting coherent echoes which are removed.
2436 #Getting coherent echoes which are removed.
2469 if len(novall[0]) > 0:
2437 if len(novall[0]) > 0:
2470 #val_spc[(0,1),novall[a],ih] = 1
2471 #val_spc[,(2,3),novall[a],ih] = 1
2472 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
2438 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
2473 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
2439 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
2474 val_cspc[novall[0],ii,ifreq,ih] = 1
2440 val_cspc[novall[0],ii,ifreq,ih] = 1
2475 #print("OUT NOVALL 1")
2476 #Removing coherent from ISR data
2441 #Removing coherent from ISR data
2477 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
2442 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
2478 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
2443 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
2479 cspectra[noval,ii,ifreq,ih] = numpy.nan
2444 cspectra[noval,ii,ifreq,ih] = numpy.nan
2480 #no sale es para savedrifts >2
2481 ''' channels = channels
2482 cross_pairs = cross_pairs
2483 #print("OUT NOVALL 2")
2484
2445
2485 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
2486 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
2487 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
2488 #print('vcros =', vcross)
2489
2490 #Getting coherent echoes which are removed.
2491 if len(novall) > 0:
2492 #val_spc[novall,ii,ifreq,ih] = 1
2493 val_spc[ii,ifreq,ih,novall] = 1
2494 if len(vcross) > 0:
2495 val_cspc[vcross,ifreq,ih,novall] = 1
2496
2497 #Removing coherent from ISR data.
2498 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
2499 if len(vcross) > 0:
2500 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
2501 '''
2502 #Getting average of the spectra and cross-spectra from incoherent echoes.
2446 #Getting average of the spectra and cross-spectra from incoherent echoes.
2503 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
2447 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
2504 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
2448 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
2505 for ih in range(nHei):
2449 for ih in range(nHei):
2506 for ifreq in range(nProf):
2450 for ifreq in range(nProf):
2507 for ich in range(nChan):
2451 for ich in range(nChan):
2508 tmp = spectra[:,ich,ifreq,ih]
2452 tmp = spectra[:,ich,ifreq,ih]
2509 valid = (numpy.isfinite(tmp[:])==True).nonzero()
2453 valid = (numpy.isfinite(tmp[:])==True).nonzero()
2510 #print('TMP',tmp)
2511 if len(valid[0]) >0 :
2454 if len(valid[0]) >0 :
2512 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2455 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2513 #for icr in range(nPairs):
2514 for icr in range(nPairs):
2456 for icr in range(nPairs):
2515 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
2457 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
2516 valid = (numpy.isfinite(tmp)==True).nonzero()
2458 valid = (numpy.isfinite(tmp)==True).nonzero()
2517 if len(valid[0]) > 0:
2459 if len(valid[0]) > 0:
2518 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2460 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2519 # print('##########################################################')
2520 #Removing fake coherent echoes (at least 4 points around the point)
2461 #Removing fake coherent echoes (at least 4 points around the point)
2521
2522 val_spectra = numpy.sum(val_spc,0)
2462 val_spectra = numpy.sum(val_spc,0)
2523 val_cspectra = numpy.sum(val_cspc,0)
2463 val_cspectra = numpy.sum(val_cspc,0)
2524
2464
2525 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
2465 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
2526 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
2466 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
2527
2467
2528 for i in range(nChan):
2468 for i in range(nChan):
2529 for j in range(nProf):
2469 for j in range(nProf):
2530 for k in range(nHei):
2470 for k in range(nHei):
2531 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
2471 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
2532 val_spc[:,i,j,k] = 0.0
2472 val_spc[:,i,j,k] = 0.0
2533 for i in range(nPairs):
2473 for i in range(nPairs):
2534 for j in range(nProf):
2474 for j in range(nProf):
2535 for k in range(nHei):
2475 for k in range(nHei):
2536 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
2476 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
2537 val_cspc[:,i,j,k] = 0.0
2477 val_cspc[:,i,j,k] = 0.0
2538
2478
2539 tmp_sat_spectra = spectra.copy()
2479 tmp_sat_spectra = spectra.copy()
2540 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
2480 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
2541 tmp_sat_cspectra = cspectra.copy()
2481 tmp_sat_cspectra = cspectra.copy()
2542 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
2482 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
2543 val = (val_spc > 0).nonzero()
2483 val = (val_spc > 0).nonzero()
2544 if len(val[0]) > 0:
2484 if len(val[0]) > 0:
2545 tmp_sat_spectra[val] = in_sat_spectra[val]
2485 tmp_sat_spectra[val] = in_sat_spectra[val]
2546
2486
2547 val = (val_cspc > 0).nonzero()
2487 val = (val_cspc > 0).nonzero()
2548 if len(val[0]) > 0:
2488 if len(val[0]) > 0:
2549 tmp_sat_cspectra[val] = in_sat_cspectra[val]
2489 tmp_sat_cspectra[val] = in_sat_cspectra[val]
2550
2490
2551 #Getting average of the spectra and cross-spectra from incoherent echoes.
2491 #Getting average of the spectra and cross-spectra from incoherent echoes.
2552 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
2492 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
2553 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
2493 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
2554 for ih in range(nHei):
2494 for ih in range(nHei):
2555 for ifreq in range(nProf):
2495 for ifreq in range(nProf):
2556 for ich in range(nChan):
2496 for ich in range(nChan):
2557 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
2497 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
2558 valid = (numpy.isfinite(tmp)).nonzero()
2498 valid = (numpy.isfinite(tmp)).nonzero()
2559 if len(valid[0]) > 0:
2499 if len(valid[0]) > 0:
2560 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2500 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2561
2501
2562 for icr in range(nPairs):
2502 for icr in range(nPairs):
2563 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
2503 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
2564 valid = (numpy.isfinite(tmp)).nonzero()
2504 valid = (numpy.isfinite(tmp)).nonzero()
2565 if len(valid[0]) > 0:
2505 if len(valid[0]) > 0:
2566 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2506 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2567 #self.__dataReady= True
2568 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
2569 #if not self.__dataReady:
2570 #return None, None
2571 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
2507 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
2572 def REM_ISOLATED_POINTS(self,array,rth):
2508 def REM_ISOLATED_POINTS(self,array,rth):
2573 if rth == None : rth = 4
2509 if rth == None : rth = 4
2574
2575 num_prof = len(array[0,:,0])
2510 num_prof = len(array[0,:,0])
2576 num_hei = len(array[0,0,:])
2511 num_hei = len(array[0,0,:])
2577 n2d = len(array[:,0,0])
2512 n2d = len(array[:,0,0])
2578
2513
2579 for ii in range(n2d) :
2514 for ii in range(n2d) :
2580 #print ii,n2d
2581 tmp = array[ii,:,:]
2515 tmp = array[ii,:,:]
2582 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
2583 tmp = numpy.reshape(tmp,num_prof*num_hei)
2516 tmp = numpy.reshape(tmp,num_prof*num_hei)
2584 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
2517 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
2585 indxs2 = (tmp > 0).nonzero()
2518 indxs2 = (tmp > 0).nonzero()
2586
2587 indxs1 = (indxs1[0])
2519 indxs1 = (indxs1[0])
2588 indxs2 = indxs2[0]
2520 indxs2 = indxs2[0]
2589 #indxs1 = numpy.array(indxs1[0])
2590 #indxs2 = numpy.array(indxs2[0])
2591 indxs = None
2521 indxs = None
2592 #print indxs1 , indxs2
2593 for iv in range(len(indxs2)):
2522 for iv in range(len(indxs2)):
2594 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
2523 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
2595 #print len(indxs2), indv
2596 if len(indv[0]) > 0 :
2524 if len(indv[0]) > 0 :
2597 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
2525 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
2598 indxs = indxs[1:]
2526 indxs = indxs[1:]
2599 #print indxs, len(indxs)
2600 if len(indxs) < 4 :
2527 if len(indxs) < 4 :
2601 array[ii,:,:] = 0.
2528 array[ii,:,:] = 0.
2602 return
2529 return
2603
2530
2604 xpos = numpy.mod(indxs ,num_hei)
2531 xpos = numpy.mod(indxs ,num_hei)
2605 ypos = (indxs / num_hei)
2532 ypos = (indxs / num_hei)
2606 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
2533 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
2607 #print sx
2608 xpos = xpos[sx]
2534 xpos = xpos[sx]
2609 ypos = ypos[sx]
2535 ypos = ypos[sx]
2610 # *********************************** Cleaning isolated points **********************************
2536 # *********************************** Cleaning isolated points **********************************
2611 ic = 0
2537 ic = 0
2612 while True :
2538 while True :
2613 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
2539 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
2614 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
2615 #plt.plot(r)
2616 #plt.show()
2617 no_coh1 = (numpy.isfinite(r)==True).nonzero()
2540 no_coh1 = (numpy.isfinite(r)==True).nonzero()
2618 no_coh2 = (r <= rth).nonzero()
2541 no_coh2 = (r <= rth).nonzero()
2619 #print r, no_coh1, no_coh2
2620 no_coh1 = numpy.array(no_coh1[0])
2542 no_coh1 = numpy.array(no_coh1[0])
2621 no_coh2 = numpy.array(no_coh2[0])
2543 no_coh2 = numpy.array(no_coh2[0])
2622 no_coh = None
2544 no_coh = None
2623 #print valid1 , valid2
2624 for iv in range(len(no_coh2)):
2545 for iv in range(len(no_coh2)):
2625 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
2546 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
2626 if len(indv[0]) > 0 :
2547 if len(indv[0]) > 0 :
2627 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
2548 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
2628 no_coh = no_coh[1:]
2549 no_coh = no_coh[1:]
2629 #print len(no_coh), no_coh
2630 if len(no_coh) < 4 :
2550 if len(no_coh) < 4 :
2631 #print xpos[ic], ypos[ic], ic
2632 xpos[ic] = numpy.nan
2551 xpos[ic] = numpy.nan
2633 ypos[ic] = numpy.nan
2552 ypos[ic] = numpy.nan
2634
2553
2635 ic = ic + 1
2554 ic = ic + 1
2636 if (ic == len(indxs)) :
2555 if (ic == len(indxs)) :
2637 break
2556 break
2638 #print( xpos, ypos)
2639
2640 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
2557 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
2641 #print indxs[0]
2642 if len(indxs[0]) < 4 :
2558 if len(indxs[0]) < 4 :
2643 array[ii,:,:] = 0.
2559 array[ii,:,:] = 0.
2644 return
2560 return
2645
2561
2646 xpos = xpos[indxs[0]]
2562 xpos = xpos[indxs[0]]
2647 ypos = ypos[indxs[0]]
2563 ypos = ypos[indxs[0]]
2648 for i in range(0,len(ypos)):
2564 for i in range(0,len(ypos)):
2649 ypos[i]=int(ypos[i])
2565 ypos[i]=int(ypos[i])
2650 junk = tmp
2566 junk = tmp
2651 tmp = junk*0.0
2567 tmp = junk*0.0
2652
2568
2653 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
2569 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
2654 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
2570 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
2655
2656 #print array.shape
2657 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
2658 #print tmp.shape
2659
2660 return array
2571 return array
2572
2661 def moments(self,doppler,yarray,npoints):
2573 def moments(self,doppler,yarray,npoints):
2662 ytemp = yarray
2574 ytemp = yarray
2663 #val = WHERE(ytemp GT 0,cval)
2664 #if cval == 0 : val = range(npoints-1)
2665 val = (ytemp > 0).nonzero()
2575 val = (ytemp > 0).nonzero()
2666 val = val[0]
2576 val = val[0]
2667 #print('hvalid:',hvalid)
2668 #print('valid', valid)
2669 if len(val) == 0 : val = range(npoints-1)
2577 if len(val) == 0 : val = range(npoints-1)
2670
2578
2671 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
2579 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
2672 ytemp[len(ytemp):] = [ynew]
2580 ytemp[len(ytemp):] = [ynew]
2673
2581
2674 index = 0
2582 index = 0
2675 index = numpy.argmax(ytemp)
2583 index = numpy.argmax(ytemp)
2676 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
2584 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
2677 ytemp = ytemp[0:npoints-1]
2585 ytemp = ytemp[0:npoints-1]
2678
2586
2679 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
2587 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
2680 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
2588 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
2681 return [fmom,numpy.sqrt(smom)]
2589 return [fmom,numpy.sqrt(smom)]
2682
2590
2683
2591
2684
2592
2685
2593
2686
2594
2687
2595 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None, filec=None,coh_th=None, hei_th=None,taver=None,proc=None,nhei=None,nprofs=None,ipp=None,channelList=None):
2688
2596 if not numpy.any(proc):
2689
2690 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None, filec=None,coh_th=None, hei_th=None):
2691 nChannels = dataOut.nChannels
2597 nChannels = dataOut.nChannels
2692 nHeights= dataOut.heightList.size
2598 nHeights= dataOut.heightList.size
2693 nProf = dataOut.nProfiles
2599 nProf = dataOut.nProfiles
2600 if numpy.any(taver): taver=int(taver)
2601 else : taver = 5
2694 tini=time.localtime(dataOut.utctime)
2602 tini=time.localtime(dataOut.utctime)
2695 if (tini.tm_min % 5) == 0 and (tini.tm_sec < 5 and self.fint==0):
2603 if (tini.tm_min % taver) == 0 and (tini.tm_sec < 5 and self.fint==0):
2696 self.index = 0
2604 self.index = 0
2697 jspc = self.buffer
2605 jspc = self.buffer
2698 jcspc = self.buffer2
2606 jcspc = self.buffer2
2699 jnoise = self.buffer3
2607 jnoise = self.buffer3
2700 self.buffer = dataOut.data_spc
2608 self.buffer = dataOut.data_spc
2701 self.buffer2 = dataOut.data_cspc
2609 self.buffer2 = dataOut.data_cspc
2702 self.buffer3 = dataOut.noise
2610 self.buffer3 = dataOut.noise
2703 self.fint = 1
2611 self.fint = 1
2704 if numpy.any(jspc) :
2612 if numpy.any(jspc) :
2705 jspc= numpy.reshape(jspc,(int(len(jspc)/4),nChannels,nProf,nHeights))
2613 jspc= numpy.reshape(jspc,(int(len(jspc)/nChannels),nChannels,nProf,nHeights))
2706 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/2),2,nProf,nHeights))
2614 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/int(nChannels/2)),int(nChannels/2),nProf,nHeights))
2707 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/4),nChannels))
2615 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/nChannels),nChannels))
2708 else:
2616 else:
2709 dataOut.flagNoData = True
2617 dataOut.flagNoData = True
2710 return dataOut
2618 return dataOut
2711 else :
2619 else :
2712 if (tini.tm_min % 5) == 0 : self.fint = 1
2620 if (tini.tm_min % taver) == 0 : self.fint = 1
2713 else : self.fint = 0
2621 else : self.fint = 0
2714 self.index += 1
2622 self.index += 1
2715 if numpy.any(self.buffer):
2623 if numpy.any(self.buffer):
2716 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
2624 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
2717 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
2625 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
2718 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
2626 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
2719 else:
2627 else:
2720 self.buffer = dataOut.data_spc
2628 self.buffer = dataOut.data_spc
2721 self.buffer2 = dataOut.data_cspc
2629 self.buffer2 = dataOut.data_cspc
2722 self.buffer3 = dataOut.noise
2630 self.buffer3 = dataOut.noise
2723 dataOut.flagNoData = True
2631 dataOut.flagNoData = True
2724 return dataOut
2632 return dataOut
2725 if path != None:
2633 if path != None:
2726 sys.path.append(path)
2634 sys.path.append(path)
2727 self.library = importlib.import_module(file)
2635 self.library = importlib.import_module(file)
2636 if filec != None:
2637 self.weightf = importlib.import_module(filec)
2728
2638
2729 #To be inserted as a parameter
2639 #To be inserted as a parameter
2730 groupArray = numpy.array(groupList)
2640 groupArray = numpy.array(groupList)
2731 #groupArray = numpy.array([[0,1],[2,3]])
2641 #groupArray = numpy.array([[0,1],[2,3]])
2732 dataOut.groupList = groupArray
2642 dataOut.groupList = groupArray
2733
2734 nGroups = groupArray.shape[0]
2643 nGroups = groupArray.shape[0]
2735 nChannels = dataOut.nChannels
2644 nChannels = dataOut.nChannels
2736 nHeights = dataOut.heightList.size
2645 nHeights = dataOut.heightList.size
2737
2646
2738 #Parameters Array
2647 #Parameters Array
2739 dataOut.data_param = None
2648 dataOut.data_param = None
2740 dataOut.data_paramC = None
2649 dataOut.data_paramC = None
2650 dataOut.clean_num_aver = None
2651 dataOut.coh_num_aver = None
2652 dataOut.tmp_spectra_i = None
2653 dataOut.tmp_cspectra_i = None
2654 dataOut.tmp_spectra_c = None
2655 dataOut.tmp_cspectra_c = None
2656 dataOut.index = None
2741
2657
2742 #Set constants
2658 #Set constants
2743 constants = self.library.setConstants(dataOut)
2659 constants = self.library.setConstants(dataOut)
2744 dataOut.constants = constants
2660 dataOut.constants = constants
2745 M = dataOut.normFactor
2661 M = dataOut.normFactor
2746 N = dataOut.nFFTPoints
2662 N = dataOut.nFFTPoints
2747 ippSeconds = dataOut.ippSeconds
2663 ippSeconds = dataOut.ippSeconds
2748 K = dataOut.nIncohInt
2664 K = dataOut.nIncohInt
2749 pairsArray = numpy.array(dataOut.pairsList)
2665 pairsArray = numpy.array(dataOut.pairsList)
2750
2751 snrth= 20
2666 snrth= 20
2752 spectra = dataOut.data_spc
2667 spectra = dataOut.data_spc
2753 cspectra = dataOut.data_cspc
2668 cspectra = dataOut.data_cspc
2754 nProf = dataOut.nProfiles
2669 nProf = dataOut.nProfiles
2755 heights = dataOut.heightList
2670 heights = dataOut.heightList
2756 nHei = len(heights)
2671 nHei = len(heights)
2757 channels = dataOut.channelList
2672 channels = dataOut.channelList
2758 nChan = len(channels)
2673 nChan = len(channels)
2759 nIncohInt = dataOut.nIncohInt
2674 nIncohInt = dataOut.nIncohInt
2760 crosspairs = dataOut.groupList
2675 crosspairs = dataOut.groupList
2761 noise = dataOut.noise
2676 noise = dataOut.noise
2762 jnoise = jnoise/N
2677 jnoise = jnoise/N
2763 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
2678 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
2764 power = numpy.sum(spectra, axis=1)
2679 power = numpy.sum(spectra, axis=1)
2765 nPairs = len(crosspairs)
2680 nPairs = len(crosspairs)
2766 absc = dataOut.abscissaList[:-1]
2681 absc = dataOut.abscissaList[:-1]
2767
2682
2768 if not self.isConfig:
2683 if not self.isConfig:
2769 self.isConfig = True
2684 self.isConfig = True
2770
2685
2771 index = tini.tm_hour*12+tini.tm_min/5
2686 index = tini.tm_hour*12+tini.tm_min/taver
2687 dataOut.index= index
2772 jspc = jspc/N/N
2688 jspc = jspc/N/N
2773 jcspc = jcspc/N/N
2689 jcspc = jcspc/N/N
2774 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
2690 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
2775 jspectra = tmp_spectra*len(jspc[:,0,0,0])
2691 jspectra = tmp_spectra*len(jspc[:,0,0,0])
2776 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
2692 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
2777 my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver = self.__DiffCoherent(jspectra, jcspectra, dataOut, noise, snrth,coh_th, hei_th)
2693 my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver = self.__DiffCoherent(jspectra, jcspectra, dataOut, noise, snrth,coh_th, hei_th)
2778 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
2694 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
2779 dataOut.data_spc = incoh_spectra
2695 dataOut.data_spc = incoh_spectra
2780 dataOut.data_cspc = incoh_cspectra
2696 dataOut.data_cspc = incoh_cspectra
2781
2782 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
2697 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
2783 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
2698 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
2699 dataOut.clean_num_aver = clean_num_aver
2700 dataOut.coh_num_aver = coh_num_aver
2701 dataOut.tmp_spectra_i = incoh_spectra
2702 dataOut.tmp_cspectra_i = incoh_cspectra
2703 dataOut.tmp_spectra_c = clean_coh_spectra
2704 dataOut.tmp_cspectra_c = clean_coh_cspectra
2784 #List of possible combinations
2705 #List of possible combinations
2785 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
2706 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
2786 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
2707 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
2787
2788 if getSNR:
2708 if getSNR:
2789 listChannels = groupArray.reshape((groupArray.size))
2709 listChannels = groupArray.reshape((groupArray.size))
2790 listChannels.sort()
2710 listChannels.sort()
2791 dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
2711 dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
2712 else:
2713 clean_num_aver = dataOut.clean_num_aver
2714 coh_num_aver = dataOut.coh_num_aver
2715 dataOut.data_spc = dataOut.tmp_spectra_i
2716 dataOut.data_cspc = dataOut.tmp_cspectra_i
2717 clean_coh_spectra = dataOut.tmp_spectra_c
2718 clean_coh_cspectra = dataOut.tmp_cspectra_c
2719 jspectra = dataOut.data_spc+clean_coh_spectra
2720 nHeights = len(dataOut.heightList) # nhei
2721 nProf = int(dataOut.nProfiles)
2722 dataOut.nProfiles = nProf
2723 dataOut.data_param = None
2724 dataOut.data_paramC = None
2725 dataOut.code = numpy.array([[-1.,-1.,1.],[1.,1.,-1.]])
2726 #M=600
2727 #N=200
2728 dataOut.flagDecodeData=True
2729 M = int(dataOut.normFactor)
2730 N = int(dataOut.nFFTPoints)
2731 dataOut.nFFTPoints = N
2732 dataOut.nIncohInt= int(dataOut.nIncohInt)
2733 dataOut.nProfiles = int(dataOut.nProfiles)
2734 dataOut.nCohInt = int(dataOut.nCohInt)
2735 print('sale',dataOut.nProfiles,dataOut.nHeights)
2736 #dataOut.nFFTPoints=nprofs
2737 #dataOut.normFactor = nprofs
2738 dataOut.channelList = channelList
2739 #dataOut.ippFactor=1
2740 #ipp = ipp/150*1.e-3
2741 vmax = (300000000/49920000.0/2) / (dataOut.ippSeconds)
2742 #dataOut.ippSeconds=ipp
2743 absc = vmax*( numpy.arange(nProf,dtype='float')-nProf/2.)/nProf
2744 print('sale 2',dataOut.ippSeconds,M,N)
2745 print('Empieza procesamiento offline')
2746 if path != None:
2747 sys.path.append(path)
2748 self.library = importlib.import_module(file)
2749 constants = self.library.setConstants(dataOut)
2750 constants['M'] = M
2751 dataOut.constants = constants
2752
2753 groupArray = numpy.array(groupList)
2754 dataOut.groupList = groupArray
2755 nGroups = groupArray.shape[0]
2756 #List of possible combinations
2757 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
2758 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
2792 if dataOut.data_paramC is None:
2759 if dataOut.data_paramC is None:
2793 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
2760 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
2794 for i in range(nGroups):
2761 for i in range(nGroups):
2795 coord = groupArray[i,:]
2762 coord = groupArray[i,:]
2796 #Input data array
2763 #Input data array
2797 data = dataOut.data_spc[coord,:,:]/(M*N)
2764 data = dataOut.data_spc[coord,:,:]/(M*N)
2798 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
2765 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
2799
2766
2800 #Cross Spectra data array for Covariance Matrixes
2767 #Cross Spectra data array for Covariance Matrixes
2801 ind = 0
2768 ind = 0
2802 for pairs in listComb:
2769 for pairs in listComb:
2803 pairsSel = numpy.array([coord[x],coord[y]])
2770 pairsSel = numpy.array([coord[x],coord[y]])
2804 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
2771 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
2805 ind += 1
2772 ind += 1
2806 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
2773 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
2807 dataCross = dataCross**2
2774 dataCross = dataCross**2
2808 nhei = nHeights
2775 nhei = nHeights
2809 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
2776 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
2810 if i == 0 : my_noises = numpy.zeros(4,dtype=float) #FLTARR(4)
2777 if i == 0 : my_noises = numpy.zeros(4,dtype=float)
2811 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
2778 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
2812 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
2779 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
2813 n0 = n0i
2780 n0 = n0i
2814 n1= n1i
2781 n1= n1i
2815 my_noises[2*i+0] = n0
2782 my_noises[2*i+0] = n0
2816 my_noises[2*i+1] = n1
2783 my_noises[2*i+1] = n1
2817 snrth = -15.0 #-16 -10
2784 snrth = -15.0 # -4 -16 -25
2818 snrth = 10**(snrth/10.0)
2785 snrth = 10**(snrth/10.0)
2819 jvelr = numpy.zeros(nHeights, dtype = 'float')
2786 jvelr = numpy.zeros(nHeights, dtype = 'float')
2820 hvalid = [0]
2787 hvalid = [0]
2788 coh2 = abs(dataOut.data_cspc[i,1:nProf,:])**2/(dataOut.data_spc[0+i*2,1:nProf-0,:]*dataOut.data_spc[1+i*2,1:nProf-0,:])
2821 for h in range(nHeights):
2789 for h in range(nHeights):
2822 smooth = clean_num_aver[i+1,h]
2790 smooth = clean_num_aver[i+1,h]
2823 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
2791 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
2824 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
2792 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
2825 signal0 = signalpn0-n0
2793 signal0 = signalpn0-n0
2826 signal1 = signalpn1-n1
2794 signal1 = signalpn1-n1
2827 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2795 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2828 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2796 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2797 gamma = coh2[:,h]
2798 indxs = (numpy.isfinite(list(gamma))==True).nonzero()
2799 if len(indxs) >0:
2800 if numpy.nanmean(gamma) > 0.07:
2801 maxp0 = numpy.argmax(signal0*gamma)
2802 maxp1 = numpy.argmax(signal1*gamma)
2803 #print('usa gamma',numpy.nanmean(gamma))
2804 else:
2829 maxp0 = numpy.argmax(signal0)
2805 maxp0 = numpy.argmax(signal0)
2830 maxp1 = numpy.argmax(signal1)
2806 maxp1 = numpy.argmax(signal1)
2831 jvelr[h] = (absc[maxp0]+absc[maxp1])/2.
2807 jvelr[h] = (absc[maxp0]+absc[maxp1])/2.
2808 else: jvelr[h] = absc[0]
2832 if snr0 > 0.1 and snr1 > 0.1: hvalid = numpy.concatenate((hvalid,h), axis=None)
2809 if snr0 > 0.1 and snr1 > 0.1: hvalid = numpy.concatenate((hvalid,h), axis=None)
2833 #print(maxp0,absc[maxp0],snr0,jvelr[h])
2810 #print(maxp0,absc[maxp0],snr0,jvelr[h])
2834
2811
2835 if len(hvalid)> 1: fd0 = numpy.median(jvelr[hvalid[1:]])*-1
2812 if len(hvalid)> 1: fd0 = numpy.median(jvelr[hvalid[1:]])*-1
2836 else: fd0 = numpy.nan
2813 else: fd0 = numpy.nan
2837
2838 for h in range(nHeights):
2814 for h in range(nHeights):
2839 d = data[:,h]
2815 d = data[:,h]
2840 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
2816 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
2841 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
2817 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
2842 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
2818 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
2843 signal0 = signalpn0-n0
2819 signal0 = signalpn0-n0
2844 signal1 = signalpn1-n1
2820 signal1 = signalpn1-n1
2845 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2821 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2846 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2822 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2847 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
2823 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
2848 #Covariance Matrix
2824 #Covariance Matrix
2849 D = numpy.diag(d**2)
2825 D = numpy.diag(d**2)
2850 ind = 0
2826 ind = 0
2851 for pairs in listComb:
2827 for pairs in listComb:
2852 #Coordinates in Covariance Matrix
2828 #Coordinates in Covariance Matrix
2853 x = pairs[0]
2829 x = pairs[0]
2854 y = pairs[1]
2830 y = pairs[1]
2855 #Channel Index
2831 #Channel Index
2856 S12 = dataCross[ind,:,h]
2832 S12 = dataCross[ind,:,h]
2857 D12 = numpy.diag(S12)
2833 D12 = numpy.diag(S12)
2858 #Completing Covariance Matrix with Cross Spectras
2834 #Completing Covariance Matrix with Cross Spectras
2859 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
2835 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
2860 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
2836 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
2861 ind += 1
2837 ind += 1
2862 #diagD = numpy.zeros(256)
2838 diagD = numpy.zeros(256)
2863 #if h == 17 :
2839
2864 # for ii in range(256): diagD[ii] = D[ii,ii]
2865 #Dinv=numpy.linalg.inv(D)
2866 #L=numpy.linalg.cholesky(Dinv)
2867 try:
2840 try:
2868 Dinv=numpy.linalg.inv(D)
2841 Dinv=numpy.linalg.inv(D)
2869 L=numpy.linalg.cholesky(Dinv)
2842 L=numpy.linalg.cholesky(Dinv)
2870 except:
2843 except:
2871 Dinv = D*numpy.nan
2844 Dinv = D*numpy.nan
2872 L= D*numpy.nan
2845 L= D*numpy.nan
2873 LT=L.T
2846 LT=L.T
2874
2847
2875 dp = numpy.dot(LT,d)
2848 dp = numpy.dot(LT,d)
2876
2877 #Initial values
2849 #Initial values
2878 data_spc = dataOut.data_spc[coord,:,h]
2850 data_spc = dataOut.data_spc[coord,:,h]
2851 w = data_spc/data_spc
2852 if filec != None:
2853 w = self.weightf.weightfit(w,tini.tm_year,tini.tm_yday,index,h,i)
2879 if (h>6)and(error1[3]<25):
2854 if (h>6)and(error1[3]<25):
2880 p0 = dataOut.data_param[i,:,h-1]
2855 p0 = dataOut.data_param[i,:,h-1]
2881 else:
2856 else:
2882 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))# sin el i(data_spc, constants, i)
2857 p0 = numpy.array(self.library.initialValuesFunction(data_spc*w, constants))# sin el i(data_spc, constants, i)
2883 p0[3] = fd0
2858 p0[3] = fd0
2859 if filec != None:
2860 p0 = self.weightf.Vrfit(p0,tini.tm_year,tini.tm_yday,index,h,i)
2884 try:
2861 try:
2885 #Least Squares
2862 #Least Squares
2886 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
2863 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
2887 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
2864 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
2888 #Chi square error
2865 #Chi square error
2889 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
2866 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
2890 #Error with Jacobian
2867 #Error with Jacobian
2891 error1 = self.library.errorFunction(minp,constants,LT)
2868 error1 = self.library.errorFunction(minp,constants,LT)
2892
2869
2893 except:
2870 except:
2894 minp = p0*numpy.nan
2871 minp = p0*numpy.nan
2895 error0 = numpy.nan
2872 error0 = numpy.nan
2896 error1 = p0*numpy.nan
2873 error1 = p0*numpy.nan
2897 else :
2874 else :
2898 data_spc = dataOut.data_spc[coord,:,h]
2875 data_spc = dataOut.data_spc[coord,:,h]
2899 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
2876 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
2900 minp = p0*numpy.nan
2877 minp = p0*numpy.nan
2901 error0 = numpy.nan
2878 error0 = numpy.nan
2902 error1 = p0*numpy.nan
2879 error1 = p0*numpy.nan
2903 if dataOut.data_param is None:
2880 if dataOut.data_param is None:
2904 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
2881 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
2905 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
2882 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
2906
2883
2907 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
2884 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
2908 dataOut.data_param[i,:,h] = minp
2885 dataOut.data_param[i,:,h] = minp
2909 for ht in range(nHeights-1) :
2886 for ht in range(nHeights-1) :
2910 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
2887 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
2911 dataOut.data_paramC[4*i,ht,1] = smooth
2888 dataOut.data_paramC[4*i,ht,1] = smooth
2912 signalpn0 = (clean_coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
2889 signalpn0 = (clean_coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
2913 signalpn1 = (clean_coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
2890 signalpn1 = (clean_coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
2914 val0 = (signalpn0 > 0).nonzero()
2891 val0 = (signalpn0 > 0).nonzero()
2915 val0 = val0[0]
2892 val0 = val0[0]
2916 if len(val0) == 0 : val0_npoints = nProf
2893 if len(val0) == 0 : val0_npoints = nProf
2917 else : val0_npoints = len(val0)
2894 else : val0_npoints = len(val0)
2918
2895
2919 val1 = (signalpn1 > 0).nonzero()
2896 val1 = (signalpn1 > 0).nonzero()
2920 val1 = val1[0]
2897 val1 = val1[0]
2921 if len(val1) == 0 : val1_npoints = nProf
2898 if len(val1) == 0 : val1_npoints = nProf
2922 else : val1_npoints = len(val1)
2899 else : val1_npoints = len(val1)
2923
2900
2924 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
2901 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
2925 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
2902 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
2926
2903
2927 signal0 = (signalpn0-n0) # > 0
2904 signal0 = (signalpn0-n0)
2928 vali = (signal0 < 0).nonzero()
2905 vali = (signal0 < 0).nonzero()
2929 vali = vali[0]
2906 vali = vali[0]
2930 if len(vali) > 0 : signal0[vali] = 0
2907 if len(vali) > 0 : signal0[vali] = 0
2931 signal1 = (signalpn1-n1) #> 0
2908 signal1 = (signalpn1-n1)
2932 vali = (signal1 < 0).nonzero()
2909 vali = (signal1 < 0).nonzero()
2933 vali = vali[0]
2910 vali = vali[0]
2934 if len(vali) > 0 : signal1[vali] = 0
2911 if len(vali) > 0 : signal1[vali] = 0
2935 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2912 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2936 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2913 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2937 doppler = absc[1:]
2914 doppler = absc[1:]
2938 if snr0 >= snrth and snr1 >= snrth and smooth :
2915 if snr0 >= snrth and snr1 >= snrth and smooth :
2939 signalpn0_n0 = signalpn0
2916 signalpn0_n0 = signalpn0
2940 signalpn0_n0[val0] = signalpn0[val0] - n0
2917 signalpn0_n0[val0] = signalpn0[val0] - n0
2941 mom0 = self.moments(doppler,signalpn0-n0,nProf)
2918 mom0 = self.moments(doppler,signalpn0-n0,nProf)
2942 signalpn1_n1 = signalpn1
2919 signalpn1_n1 = signalpn1
2943 signalpn1_n1[val1] = signalpn1[val1] - n1
2920 signalpn1_n1[val1] = signalpn1[val1] - n1
2944 mom1 = self.moments(doppler,signalpn1_n1,nProf)
2921 mom1 = self.moments(doppler,signalpn1_n1,nProf)
2945 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
2922 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
2946 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
2923 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
2947
2924
2948 dataOut.data_spc = jspectra
2925 dataOut.data_spc = jspectra
2949 dataOut.spc_noise = my_noises*nProf*M
2926 dataOut.spc_noise = my_noises*nProf*M
2927 if numpy.any(proc): dataOut.spc_noise = my_noises*nProf*M
2950 if getSNR:
2928 if getSNR:
2951 listChannels = groupArray.reshape((groupArray.size))
2929 listChannels = groupArray.reshape((groupArray.size))
2952 listChannels.sort()
2930 listChannels.sort()
2953
2931
2954 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels])
2932 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels])
2955 return dataOut
2933 return dataOut
2956
2934
2957 def __residFunction(self, p, dp, LT, constants):
2935 def __residFunction(self, p, dp, LT, constants):
2958
2936
2959 fm = self.library.modelFunction(p, constants)
2937 fm = self.library.modelFunction(p, constants)
2960 fmp=numpy.dot(LT,fm)
2938 fmp=numpy.dot(LT,fm)
2961 return dp-fmp
2939 return dp-fmp
2962
2940
2963 def __getSNR(self, z, noise):
2941 def __getSNR(self, z, noise):
2964
2942
2965 avg = numpy.average(z, axis=1)
2943 avg = numpy.average(z, axis=1)
2966 SNR = (avg.T-noise)/noise
2944 SNR = (avg.T-noise)/noise
2967 SNR = SNR.T
2945 SNR = SNR.T
2968 return SNR
2946 return SNR
2969
2947
2970 def __chisq(self, p, chindex, hindex):
2948 def __chisq(self, p, chindex, hindex):
2971 #similar to Resid but calculates CHI**2
2949 #similar to Resid but calculates CHI**2
2972 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
2950 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
2973 dp=numpy.dot(LT,d)
2951 dp=numpy.dot(LT,d)
2974 fmp=numpy.dot(LT,fm)
2952 fmp=numpy.dot(LT,fm)
2975 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
2953 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
2976 return chisq
2954 return chisq
2977
2955
2978 class WindProfiler(Operation):
2956 class WindProfiler(Operation):
2979
2957
2980 __isConfig = False
2958 __isConfig = False
2981
2959
2982 __initime = None
2960 __initime = None
2983 __lastdatatime = None
2961 __lastdatatime = None
2984 __integrationtime = None
2962 __integrationtime = None
2985
2963
2986 __buffer = None
2964 __buffer = None
2987
2965
2988 __dataReady = False
2966 __dataReady = False
2989
2967
2990 __firstdata = None
2968 __firstdata = None
2991
2969
2992 n = None
2970 n = None
2993
2971
2994 def __init__(self):
2972 def __init__(self):
2995 Operation.__init__(self)
2973 Operation.__init__(self)
2996
2974
2997 def __calculateCosDir(self, elev, azim):
2975 def __calculateCosDir(self, elev, azim):
2998 zen = (90 - elev)*numpy.pi/180
2976 zen = (90 - elev)*numpy.pi/180
2999 azim = azim*numpy.pi/180
2977 azim = azim*numpy.pi/180
3000 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
2978 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
3001 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
2979 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
3002
2980
3003 signX = numpy.sign(numpy.cos(azim))
2981 signX = numpy.sign(numpy.cos(azim))
3004 signY = numpy.sign(numpy.sin(azim))
2982 signY = numpy.sign(numpy.sin(azim))
3005
2983
3006 cosDirX = numpy.copysign(cosDirX, signX)
2984 cosDirX = numpy.copysign(cosDirX, signX)
3007 cosDirY = numpy.copysign(cosDirY, signY)
2985 cosDirY = numpy.copysign(cosDirY, signY)
3008 return cosDirX, cosDirY
2986 return cosDirX, cosDirY
3009
2987
3010 def __calculateAngles(self, theta_x, theta_y, azimuth):
2988 def __calculateAngles(self, theta_x, theta_y, azimuth):
3011
2989
3012 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
2990 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
3013 zenith_arr = numpy.arccos(dir_cosw)
2991 zenith_arr = numpy.arccos(dir_cosw)
3014 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
2992 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
3015
2993
3016 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
2994 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
3017 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
2995 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
3018
2996
3019 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
2997 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
3020
2998
3021 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
2999 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
3022
3000
3023 if horOnly:
3001 if horOnly:
3024 A = numpy.c_[dir_cosu,dir_cosv]
3002 A = numpy.c_[dir_cosu,dir_cosv]
3025 else:
3003 else:
3026 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
3004 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
3027 A = numpy.asmatrix(A)
3005 A = numpy.asmatrix(A)
3028 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
3006 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
3029
3007
3030 return A1
3008 return A1
3031
3009
3032 def __correctValues(self, heiRang, phi, velRadial, SNR):
3010 def __correctValues(self, heiRang, phi, velRadial, SNR):
3033 listPhi = phi.tolist()
3011 listPhi = phi.tolist()
3034 maxid = listPhi.index(max(listPhi))
3012 maxid = listPhi.index(max(listPhi))
3035 minid = listPhi.index(min(listPhi))
3013 minid = listPhi.index(min(listPhi))
3036
3014
3037 rango = list(range(len(phi)))
3015 rango = list(range(len(phi)))
3038
3016
3039 heiRang1 = heiRang*math.cos(phi[maxid])
3017 heiRang1 = heiRang*math.cos(phi[maxid])
3040 heiRangAux = heiRang*math.cos(phi[minid])
3018 heiRangAux = heiRang*math.cos(phi[minid])
3041 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3019 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3042 heiRang1 = numpy.delete(heiRang1,indOut)
3020 heiRang1 = numpy.delete(heiRang1,indOut)
3043
3021
3044 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3022 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3045 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3023 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3046
3024
3047 for i in rango:
3025 for i in rango:
3048 x = heiRang*math.cos(phi[i])
3026 x = heiRang*math.cos(phi[i])
3049 y1 = velRadial[i,:]
3027 y1 = velRadial[i,:]
3050 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
3028 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
3051
3029
3052 x1 = heiRang1
3030 x1 = heiRang1
3053 y11 = f1(x1)
3031 y11 = f1(x1)
3054
3032
3055 y2 = SNR[i,:]
3033 y2 = SNR[i,:]
3056 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
3034 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
3057 y21 = f2(x1)
3035 y21 = f2(x1)
3058
3036
3059 velRadial1[i,:] = y11
3037 velRadial1[i,:] = y11
3060 SNR1[i,:] = y21
3038 SNR1[i,:] = y21
3061
3039
3062 return heiRang1, velRadial1, SNR1
3040 return heiRang1, velRadial1, SNR1
3063
3041
3064 def __calculateVelUVW(self, A, velRadial):
3042 def __calculateVelUVW(self, A, velRadial):
3065
3043
3066 #Operacion Matricial
3044 #Operacion Matricial
3067 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
3045 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
3068 velUVW[:,:] = numpy.dot(A,velRadial)
3046 velUVW[:,:] = numpy.dot(A,velRadial)
3069
3047
3070
3048
3071 return velUVW
3049 return velUVW
3072
3050
3073 def techniqueDBS(self, kwargs):
3051 def techniqueDBS(self, kwargs):
3074 """
3052 """
3075 Function that implements Doppler Beam Swinging (DBS) technique.
3053 Function that implements Doppler Beam Swinging (DBS) technique.
3076
3054
3077 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3055 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3078 Direction correction (if necessary), Ranges and SNR
3056 Direction correction (if necessary), Ranges and SNR
3079
3057
3080 Output: Winds estimation (Zonal, Meridional and Vertical)
3058 Output: Winds estimation (Zonal, Meridional and Vertical)
3081
3059
3082 Parameters affected: Winds, height range, SNR
3060 Parameters affected: Winds, height range, SNR
3083 """
3061 """
3084 velRadial0 = kwargs['velRadial']
3062 velRadial0 = kwargs['velRadial']
3085 heiRang = kwargs['heightList']
3063 heiRang = kwargs['heightList']
3086 SNR0 = kwargs['SNR']
3064 SNR0 = kwargs['SNR']
3087
3065
3088 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
3066 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
3089 theta_x = numpy.array(kwargs['dirCosx'])
3067 theta_x = numpy.array(kwargs['dirCosx'])
3090 theta_y = numpy.array(kwargs['dirCosy'])
3068 theta_y = numpy.array(kwargs['dirCosy'])
3091 else:
3069 else:
3092 elev = numpy.array(kwargs['elevation'])
3070 elev = numpy.array(kwargs['elevation'])
3093 azim = numpy.array(kwargs['azimuth'])
3071 azim = numpy.array(kwargs['azimuth'])
3094 theta_x, theta_y = self.__calculateCosDir(elev, azim)
3072 theta_x, theta_y = self.__calculateCosDir(elev, azim)
3095 azimuth = kwargs['correctAzimuth']
3073 azimuth = kwargs['correctAzimuth']
3096 if 'horizontalOnly' in kwargs:
3074 if 'horizontalOnly' in kwargs:
3097 horizontalOnly = kwargs['horizontalOnly']
3075 horizontalOnly = kwargs['horizontalOnly']
3098 else: horizontalOnly = False
3076 else: horizontalOnly = False
3099 if 'correctFactor' in kwargs:
3077 if 'correctFactor' in kwargs:
3100 correctFactor = kwargs['correctFactor']
3078 correctFactor = kwargs['correctFactor']
3101 else: correctFactor = 1
3079 else: correctFactor = 1
3102 if 'channelList' in kwargs:
3080 if 'channelList' in kwargs:
3103 channelList = kwargs['channelList']
3081 channelList = kwargs['channelList']
3104 if len(channelList) == 2:
3082 if len(channelList) == 2:
3105 horizontalOnly = True
3083 horizontalOnly = True
3106 arrayChannel = numpy.array(channelList)
3084 arrayChannel = numpy.array(channelList)
3107 param = param[arrayChannel,:,:]
3085 param = param[arrayChannel,:,:]
3108 theta_x = theta_x[arrayChannel]
3086 theta_x = theta_x[arrayChannel]
3109 theta_y = theta_y[arrayChannel]
3087 theta_y = theta_y[arrayChannel]
3110
3088
3111 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3089 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3112 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
3090 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
3113 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
3091 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
3114
3092
3115 #Calculo de Componentes de la velocidad con DBS
3093 #Calculo de Componentes de la velocidad con DBS
3116 winds = self.__calculateVelUVW(A,velRadial1)
3094 winds = self.__calculateVelUVW(A,velRadial1)
3117
3095
3118 return winds, heiRang1, SNR1
3096 return winds, heiRang1, SNR1
3119
3097
3120 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
3098 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
3121
3099
3122 nPairs = len(pairs_ccf)
3100 nPairs = len(pairs_ccf)
3123 posx = numpy.asarray(posx)
3101 posx = numpy.asarray(posx)
3124 posy = numpy.asarray(posy)
3102 posy = numpy.asarray(posy)
3125
3103
3126 #Rotacion Inversa para alinear con el azimuth
3104 #Rotacion Inversa para alinear con el azimuth
3127 if azimuth!= None:
3105 if azimuth!= None:
3128 azimuth = azimuth*math.pi/180
3106 azimuth = azimuth*math.pi/180
3129 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
3107 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
3130 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
3108 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
3131 else:
3109 else:
3132 posx1 = posx
3110 posx1 = posx
3133 posy1 = posy
3111 posy1 = posy
3134
3112
3135 #Calculo de Distancias
3113 #Calculo de Distancias
3136 distx = numpy.zeros(nPairs)
3114 distx = numpy.zeros(nPairs)
3137 disty = numpy.zeros(nPairs)
3115 disty = numpy.zeros(nPairs)
3138 dist = numpy.zeros(nPairs)
3116 dist = numpy.zeros(nPairs)
3139 ang = numpy.zeros(nPairs)
3117 ang = numpy.zeros(nPairs)
3140
3118
3141 for i in range(nPairs):
3119 for i in range(nPairs):
3142 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
3120 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
3143 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
3121 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
3144 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
3122 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
3145 ang[i] = numpy.arctan2(disty[i],distx[i])
3123 ang[i] = numpy.arctan2(disty[i],distx[i])
3146
3124
3147 return distx, disty, dist, ang
3125 return distx, disty, dist, ang
3148 #Calculo de Matrices
3126 #Calculo de Matrices
3149
3127
3150
3128
3151 def __calculateVelVer(self, phase, lagTRange, _lambda):
3129 def __calculateVelVer(self, phase, lagTRange, _lambda):
3152
3130
3153 Ts = lagTRange[1] - lagTRange[0]
3131 Ts = lagTRange[1] - lagTRange[0]
3154 velW = -_lambda*phase/(4*math.pi*Ts)
3132 velW = -_lambda*phase/(4*math.pi*Ts)
3155
3133
3156 return velW
3134 return velW
3157
3135
3158 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
3136 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
3159 nPairs = tau1.shape[0]
3137 nPairs = tau1.shape[0]
3160 nHeights = tau1.shape[1]
3138 nHeights = tau1.shape[1]
3161 vel = numpy.zeros((nPairs,3,nHeights))
3139 vel = numpy.zeros((nPairs,3,nHeights))
3162 dist1 = numpy.reshape(dist, (dist.size,1))
3140 dist1 = numpy.reshape(dist, (dist.size,1))
3163
3141
3164 angCos = numpy.cos(ang)
3142 angCos = numpy.cos(ang)
3165 angSin = numpy.sin(ang)
3143 angSin = numpy.sin(ang)
3166
3144
3167 vel0 = dist1*tau1/(2*tau2**2)
3145 vel0 = dist1*tau1/(2*tau2**2)
3168 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
3146 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
3169 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
3147 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
3170
3148
3171 ind = numpy.where(numpy.isinf(vel))
3149 ind = numpy.where(numpy.isinf(vel))
3172 vel[ind] = numpy.nan
3150 vel[ind] = numpy.nan
3173
3151
3174 return vel
3152 return vel
3175
3153
3176 def techniqueSA(self, kwargs):
3154 def techniqueSA(self, kwargs):
3177
3155
3178 """
3156 """
3179 Function that implements Spaced Antenna (SA) technique.
3157 Function that implements Spaced Antenna (SA) technique.
3180
3158
3181 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3159 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3182 Direction correction (if necessary), Ranges and SNR
3160 Direction correction (if necessary), Ranges and SNR
3183
3161
3184 Output: Winds estimation (Zonal, Meridional and Vertical)
3162 Output: Winds estimation (Zonal, Meridional and Vertical)
3185
3163
3186 Parameters affected: Winds
3164 Parameters affected: Winds
3187 """
3165 """
3188 position_x = kwargs['positionX']
3166 position_x = kwargs['positionX']
3189 position_y = kwargs['positionY']
3167 position_y = kwargs['positionY']
3190 azimuth = kwargs['azimuth']
3168 azimuth = kwargs['azimuth']
3191
3169
3192 if 'correctFactor' in kwargs:
3170 if 'correctFactor' in kwargs:
3193 correctFactor = kwargs['correctFactor']
3171 correctFactor = kwargs['correctFactor']
3194 else:
3172 else:
3195 correctFactor = 1
3173 correctFactor = 1
3196
3174
3197 groupList = kwargs['groupList']
3175 groupList = kwargs['groupList']
3198 pairs_ccf = groupList[1]
3176 pairs_ccf = groupList[1]
3199 tau = kwargs['tau']
3177 tau = kwargs['tau']
3200 _lambda = kwargs['_lambda']
3178 _lambda = kwargs['_lambda']
3201
3179
3202 #Cross Correlation pairs obtained
3180 #Cross Correlation pairs obtained
3203
3181
3204 indtau = tau.shape[0]/2
3182 indtau = tau.shape[0]/2
3205 tau1 = tau[:indtau,:]
3183 tau1 = tau[:indtau,:]
3206 tau2 = tau[indtau:-1,:]
3184 tau2 = tau[indtau:-1,:]
3207 phase1 = tau[-1,:]
3185 phase1 = tau[-1,:]
3208
3186
3209 #---------------------------------------------------------------------
3187 #---------------------------------------------------------------------
3210 #Metodo Directo
3188 #Metodo Directo
3211 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
3189 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
3212 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
3190 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
3213 winds = stats.nanmean(winds, axis=0)
3191 winds = stats.nanmean(winds, axis=0)
3214 #---------------------------------------------------------------------
3192 #---------------------------------------------------------------------
3215 #Metodo General
3193 #Metodo General
3216
3194
3217 #---------------------------------------------------------------------
3195 #---------------------------------------------------------------------
3218 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
3196 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
3219 winds = correctFactor*winds
3197 winds = correctFactor*winds
3220 return winds
3198 return winds
3221
3199
3222 def __checkTime(self, currentTime, paramInterval, outputInterval):
3200 def __checkTime(self, currentTime, paramInterval, outputInterval):
3223
3201
3224 dataTime = currentTime + paramInterval
3202 dataTime = currentTime + paramInterval
3225 deltaTime = dataTime - self.__initime
3203 deltaTime = dataTime - self.__initime
3226
3204
3227 if deltaTime >= outputInterval or deltaTime < 0:
3205 if deltaTime >= outputInterval or deltaTime < 0:
3228 self.__dataReady = True
3206 self.__dataReady = True
3229 return
3207 return
3230
3208
3231 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
3209 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
3232 '''
3210 '''
3233 Function that implements winds estimation technique with detected meteors.
3211 Function that implements winds estimation technique with detected meteors.
3234
3212
3235 Input: Detected meteors, Minimum meteor quantity to wind estimation
3213 Input: Detected meteors, Minimum meteor quantity to wind estimation
3236
3214
3237 Output: Winds estimation (Zonal and Meridional)
3215 Output: Winds estimation (Zonal and Meridional)
3238
3216
3239 Parameters affected: Winds
3217 Parameters affected: Winds
3240 '''
3218 '''
3241 #Settings
3219 #Settings
3242 nInt = (heightMax - heightMin)/2
3220 nInt = (heightMax - heightMin)/2
3243 nInt = int(nInt)
3221 nInt = int(nInt)
3244 winds = numpy.zeros((2,nInt))*numpy.nan
3222 winds = numpy.zeros((2,nInt))*numpy.nan
3245
3223
3246 #Filter errors
3224 #Filter errors
3247 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
3225 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
3248 finalMeteor = arrayMeteor[error,:]
3226 finalMeteor = arrayMeteor[error,:]
3249
3227
3250 #Meteor Histogram
3228 #Meteor Histogram
3251 finalHeights = finalMeteor[:,2]
3229 finalHeights = finalMeteor[:,2]
3252 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
3230 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
3253 nMeteorsPerI = hist[0]
3231 nMeteorsPerI = hist[0]
3254 heightPerI = hist[1]
3232 heightPerI = hist[1]
3255
3233
3256 #Sort of meteors
3234 #Sort of meteors
3257 indSort = finalHeights.argsort()
3235 indSort = finalHeights.argsort()
3258 finalMeteor2 = finalMeteor[indSort,:]
3236 finalMeteor2 = finalMeteor[indSort,:]
3259
3237
3260 # Calculating winds
3238 # Calculating winds
3261 ind1 = 0
3239 ind1 = 0
3262 ind2 = 0
3240 ind2 = 0
3263
3241
3264 for i in range(nInt):
3242 for i in range(nInt):
3265 nMet = nMeteorsPerI[i]
3243 nMet = nMeteorsPerI[i]
3266 ind1 = ind2
3244 ind1 = ind2
3267 ind2 = ind1 + nMet
3245 ind2 = ind1 + nMet
3268
3246
3269 meteorAux = finalMeteor2[ind1:ind2,:]
3247 meteorAux = finalMeteor2[ind1:ind2,:]
3270
3248
3271 if meteorAux.shape[0] >= meteorThresh:
3249 if meteorAux.shape[0] >= meteorThresh:
3272 vel = meteorAux[:, 6]
3250 vel = meteorAux[:, 6]
3273 zen = meteorAux[:, 4]*numpy.pi/180
3251 zen = meteorAux[:, 4]*numpy.pi/180
3274 azim = meteorAux[:, 3]*numpy.pi/180
3252 azim = meteorAux[:, 3]*numpy.pi/180
3275
3253
3276 n = numpy.cos(zen)
3254 n = numpy.cos(zen)
3277 l = numpy.sin(zen)*numpy.sin(azim)
3255 l = numpy.sin(zen)*numpy.sin(azim)
3278 m = numpy.sin(zen)*numpy.cos(azim)
3256 m = numpy.sin(zen)*numpy.cos(azim)
3279
3257
3280 A = numpy.vstack((l, m)).transpose()
3258 A = numpy.vstack((l, m)).transpose()
3281 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
3259 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
3282 windsAux = numpy.dot(A1, vel)
3260 windsAux = numpy.dot(A1, vel)
3283
3261
3284 winds[0,i] = windsAux[0]
3262 winds[0,i] = windsAux[0]
3285 winds[1,i] = windsAux[1]
3263 winds[1,i] = windsAux[1]
3286
3264
3287 return winds, heightPerI[:-1]
3265 return winds, heightPerI[:-1]
3288
3266
3289 def techniqueNSM_SA(self, **kwargs):
3267 def techniqueNSM_SA(self, **kwargs):
3290 metArray = kwargs['metArray']
3268 metArray = kwargs['metArray']
3291 heightList = kwargs['heightList']
3269 heightList = kwargs['heightList']
3292 timeList = kwargs['timeList']
3270 timeList = kwargs['timeList']
3293
3271
3294 rx_location = kwargs['rx_location']
3272 rx_location = kwargs['rx_location']
3295 groupList = kwargs['groupList']
3273 groupList = kwargs['groupList']
3296 azimuth = kwargs['azimuth']
3274 azimuth = kwargs['azimuth']
3297 dfactor = kwargs['dfactor']
3275 dfactor = kwargs['dfactor']
3298 k = kwargs['k']
3276 k = kwargs['k']
3299
3277
3300 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
3278 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
3301 d = dist*dfactor
3279 d = dist*dfactor
3302 #Phase calculation
3280 #Phase calculation
3303 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
3281 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
3304
3282
3305 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
3283 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
3306
3284
3307 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3285 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3308 azimuth1 = azimuth1*numpy.pi/180
3286 azimuth1 = azimuth1*numpy.pi/180
3309
3287
3310 for i in range(heightList.size):
3288 for i in range(heightList.size):
3311 h = heightList[i]
3289 h = heightList[i]
3312 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
3290 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
3313 metHeight = metArray1[indH,:]
3291 metHeight = metArray1[indH,:]
3314 if metHeight.shape[0] >= 2:
3292 if metHeight.shape[0] >= 2:
3315 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
3293 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
3316 iazim = metHeight[:,1].astype(int)
3294 iazim = metHeight[:,1].astype(int)
3317 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
3295 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
3318 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
3296 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
3319 A = numpy.asmatrix(A)
3297 A = numpy.asmatrix(A)
3320 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
3298 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
3321 velHor = numpy.dot(A1,velAux)
3299 velHor = numpy.dot(A1,velAux)
3322
3300
3323 velEst[i,:] = numpy.squeeze(velHor)
3301 velEst[i,:] = numpy.squeeze(velHor)
3324 return velEst
3302 return velEst
3325
3303
3326 def __getPhaseSlope(self, metArray, heightList, timeList):
3304 def __getPhaseSlope(self, metArray, heightList, timeList):
3327 meteorList = []
3305 meteorList = []
3328 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
3306 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
3329 #Putting back together the meteor matrix
3307 #Putting back together the meteor matrix
3330 utctime = metArray[:,0]
3308 utctime = metArray[:,0]
3331 uniqueTime = numpy.unique(utctime)
3309 uniqueTime = numpy.unique(utctime)
3332
3310
3333 phaseDerThresh = 0.5
3311 phaseDerThresh = 0.5
3334 ippSeconds = timeList[1] - timeList[0]
3312 ippSeconds = timeList[1] - timeList[0]
3335 sec = numpy.where(timeList>1)[0][0]
3313 sec = numpy.where(timeList>1)[0][0]
3336 nPairs = metArray.shape[1] - 6
3314 nPairs = metArray.shape[1] - 6
3337 nHeights = len(heightList)
3315 nHeights = len(heightList)
3338
3316
3339 for t in uniqueTime:
3317 for t in uniqueTime:
3340 metArray1 = metArray[utctime==t,:]
3318 metArray1 = metArray[utctime==t,:]
3341 tmet = metArray1[:,1].astype(int)
3319 tmet = metArray1[:,1].astype(int)
3342 hmet = metArray1[:,2].astype(int)
3320 hmet = metArray1[:,2].astype(int)
3343
3321
3344 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
3322 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
3345 metPhase[:,:] = numpy.nan
3323 metPhase[:,:] = numpy.nan
3346 metPhase[:,hmet,tmet] = metArray1[:,6:].T
3324 metPhase[:,hmet,tmet] = metArray1[:,6:].T
3347
3325
3348 #Delete short trails
3326 #Delete short trails
3349 metBool = ~numpy.isnan(metPhase[0,:,:])
3327 metBool = ~numpy.isnan(metPhase[0,:,:])
3350 heightVect = numpy.sum(metBool, axis = 1)
3328 heightVect = numpy.sum(metBool, axis = 1)
3351 metBool[heightVect<sec,:] = False
3329 metBool[heightVect<sec,:] = False
3352 metPhase[:,heightVect<sec,:] = numpy.nan
3330 metPhase[:,heightVect<sec,:] = numpy.nan
3353
3331
3354 #Derivative
3332 #Derivative
3355 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
3333 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
3356 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
3334 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
3357 metPhase[phDerAux] = numpy.nan
3335 metPhase[phDerAux] = numpy.nan
3358
3336
3359 #--------------------------METEOR DETECTION -----------------------------------------
3337 #--------------------------METEOR DETECTION -----------------------------------------
3360 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
3338 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
3361
3339
3362 for p in numpy.arange(nPairs):
3340 for p in numpy.arange(nPairs):
3363 phase = metPhase[p,:,:]
3341 phase = metPhase[p,:,:]
3364 phDer = metDer[p,:,:]
3342 phDer = metDer[p,:,:]
3365
3343
3366 for h in indMet:
3344 for h in indMet:
3367 height = heightList[h]
3345 height = heightList[h]
3368 phase1 = phase[h,:] #82
3346 phase1 = phase[h,:] #82
3369 phDer1 = phDer[h,:]
3347 phDer1 = phDer[h,:]
3370
3348
3371 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
3349 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
3372
3350
3373 indValid = numpy.where(~numpy.isnan(phase1))[0]
3351 indValid = numpy.where(~numpy.isnan(phase1))[0]
3374 initMet = indValid[0]
3352 initMet = indValid[0]
3375 endMet = 0
3353 endMet = 0
3376
3354
3377 for i in range(len(indValid)-1):
3355 for i in range(len(indValid)-1):
3378
3356
3379 #Time difference
3357 #Time difference
3380 inow = indValid[i]
3358 inow = indValid[i]
3381 inext = indValid[i+1]
3359 inext = indValid[i+1]
3382 idiff = inext - inow
3360 idiff = inext - inow
3383 #Phase difference
3361 #Phase difference
3384 phDiff = numpy.abs(phase1[inext] - phase1[inow])
3362 phDiff = numpy.abs(phase1[inext] - phase1[inow])
3385
3363
3386 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
3364 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
3387 sizeTrail = inow - initMet + 1
3365 sizeTrail = inow - initMet + 1
3388 if sizeTrail>3*sec: #Too short meteors
3366 if sizeTrail>3*sec: #Too short meteors
3389 x = numpy.arange(initMet,inow+1)*ippSeconds
3367 x = numpy.arange(initMet,inow+1)*ippSeconds
3390 y = phase1[initMet:inow+1]
3368 y = phase1[initMet:inow+1]
3391 ynnan = ~numpy.isnan(y)
3369 ynnan = ~numpy.isnan(y)
3392 x = x[ynnan]
3370 x = x[ynnan]
3393 y = y[ynnan]
3371 y = y[ynnan]
3394 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
3372 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
3395 ylin = x*slope + intercept
3373 ylin = x*slope + intercept
3396 rsq = r_value**2
3374 rsq = r_value**2
3397 if rsq > 0.5:
3375 if rsq > 0.5:
3398 vel = slope#*height*1000/(k*d)
3376 vel = slope#*height*1000/(k*d)
3399 estAux = numpy.array([utctime,p,height, vel, rsq])
3377 estAux = numpy.array([utctime,p,height, vel, rsq])
3400 meteorList.append(estAux)
3378 meteorList.append(estAux)
3401 initMet = inext
3379 initMet = inext
3402 metArray2 = numpy.array(meteorList)
3380 metArray2 = numpy.array(meteorList)
3403
3381
3404 return metArray2
3382 return metArray2
3405
3383
3406 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
3384 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
3407
3385
3408 azimuth1 = numpy.zeros(len(pairslist))
3386 azimuth1 = numpy.zeros(len(pairslist))
3409 dist = numpy.zeros(len(pairslist))
3387 dist = numpy.zeros(len(pairslist))
3410
3388
3411 for i in range(len(rx_location)):
3389 for i in range(len(rx_location)):
3412 ch0 = pairslist[i][0]
3390 ch0 = pairslist[i][0]
3413 ch1 = pairslist[i][1]
3391 ch1 = pairslist[i][1]
3414
3392
3415 diffX = rx_location[ch0][0] - rx_location[ch1][0]
3393 diffX = rx_location[ch0][0] - rx_location[ch1][0]
3416 diffY = rx_location[ch0][1] - rx_location[ch1][1]
3394 diffY = rx_location[ch0][1] - rx_location[ch1][1]
3417 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
3395 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
3418 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
3396 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
3419
3397
3420 azimuth1 -= azimuth0
3398 azimuth1 -= azimuth0
3421 return azimuth1, dist
3399 return azimuth1, dist
3422
3400
3423 def techniqueNSM_DBS(self, **kwargs):
3401 def techniqueNSM_DBS(self, **kwargs):
3424 metArray = kwargs['metArray']
3402 metArray = kwargs['metArray']
3425 heightList = kwargs['heightList']
3403 heightList = kwargs['heightList']
3426 timeList = kwargs['timeList']
3404 timeList = kwargs['timeList']
3427 azimuth = kwargs['azimuth']
3405 azimuth = kwargs['azimuth']
3428 theta_x = numpy.array(kwargs['theta_x'])
3406 theta_x = numpy.array(kwargs['theta_x'])
3429 theta_y = numpy.array(kwargs['theta_y'])
3407 theta_y = numpy.array(kwargs['theta_y'])
3430
3408
3431 utctime = metArray[:,0]
3409 utctime = metArray[:,0]
3432 cmet = metArray[:,1].astype(int)
3410 cmet = metArray[:,1].astype(int)
3433 hmet = metArray[:,3].astype(int)
3411 hmet = metArray[:,3].astype(int)
3434 SNRmet = metArray[:,4]
3412 SNRmet = metArray[:,4]
3435 vmet = metArray[:,5]
3413 vmet = metArray[:,5]
3436 spcmet = metArray[:,6]
3414 spcmet = metArray[:,6]
3437
3415
3438 nChan = numpy.max(cmet) + 1
3416 nChan = numpy.max(cmet) + 1
3439 nHeights = len(heightList)
3417 nHeights = len(heightList)
3440
3418
3441 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3419 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3442 hmet = heightList[hmet]
3420 hmet = heightList[hmet]
3443 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
3421 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
3444
3422
3445 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3423 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3446
3424
3447 for i in range(nHeights - 1):
3425 for i in range(nHeights - 1):
3448 hmin = heightList[i]
3426 hmin = heightList[i]
3449 hmax = heightList[i + 1]
3427 hmax = heightList[i + 1]
3450
3428
3451 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
3429 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
3452 indthisH = numpy.where(thisH)
3430 indthisH = numpy.where(thisH)
3453
3431
3454 if numpy.size(indthisH) > 3:
3432 if numpy.size(indthisH) > 3:
3455
3433
3456 vel_aux = vmet[thisH]
3434 vel_aux = vmet[thisH]
3457 chan_aux = cmet[thisH]
3435 chan_aux = cmet[thisH]
3458 cosu_aux = dir_cosu[chan_aux]
3436 cosu_aux = dir_cosu[chan_aux]
3459 cosv_aux = dir_cosv[chan_aux]
3437 cosv_aux = dir_cosv[chan_aux]
3460 cosw_aux = dir_cosw[chan_aux]
3438 cosw_aux = dir_cosw[chan_aux]
3461
3439
3462 nch = numpy.size(numpy.unique(chan_aux))
3440 nch = numpy.size(numpy.unique(chan_aux))
3463 if nch > 1:
3441 if nch > 1:
3464 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
3442 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
3465 velEst[i,:] = numpy.dot(A,vel_aux)
3443 velEst[i,:] = numpy.dot(A,vel_aux)
3466
3444
3467 return velEst
3445 return velEst
3468
3446
3469 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
3447 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
3470
3448
3471 param = dataOut.data_param
3449 param = dataOut.moments
3472 if dataOut.abscissaList != None:
3450 if numpy.any(dataOut.abscissaList):
3473 absc = dataOut.abscissaList[:-1]
3451 absc = dataOut.abscissaList[:-1]
3474 # noise = dataOut.noise
3452 # noise = dataOut.noise
3475 heightList = dataOut.heightList
3453 heightList = dataOut.heightList
3476 SNR = dataOut.data_snr
3454 SNR = dataOut.data_snr
3477
3455
3478 if technique == 'DBS':
3456 if technique == 'DBS':
3479
3457
3480 kwargs['velRadial'] = param[:,1,:] #Radial velocity
3458 kwargs['velRadial'] = param[:,1,:] #Radial velocity
3481 kwargs['heightList'] = heightList
3459 kwargs['heightList'] = heightList
3482 kwargs['SNR'] = SNR
3460 kwargs['SNR'] = SNR
3483
3461
3484 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
3462 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
3485 dataOut.utctimeInit = dataOut.utctime
3463 dataOut.utctimeInit = dataOut.utctime
3486 dataOut.outputInterval = dataOut.paramInterval
3464 dataOut.outputInterval = dataOut.paramInterval
3487
3465
3488 elif technique == 'SA':
3466 elif technique == 'SA':
3489
3467
3490 #Parameters
3468 #Parameters
3491 kwargs['groupList'] = dataOut.groupList
3469 kwargs['groupList'] = dataOut.groupList
3492 kwargs['tau'] = dataOut.data_param
3470 kwargs['tau'] = dataOut.data_param
3493 kwargs['_lambda'] = dataOut.C/dataOut.frequency
3471 kwargs['_lambda'] = dataOut.C/dataOut.frequency
3494 dataOut.data_output = self.techniqueSA(kwargs)
3472 dataOut.data_output = self.techniqueSA(kwargs)
3495 dataOut.utctimeInit = dataOut.utctime
3473 dataOut.utctimeInit = dataOut.utctime
3496 dataOut.outputInterval = dataOut.timeInterval
3474 dataOut.outputInterval = dataOut.timeInterval
3497
3475
3498 elif technique == 'Meteors':
3476 elif technique == 'Meteors':
3499 dataOut.flagNoData = True
3477 dataOut.flagNoData = True
3500 self.__dataReady = False
3478 self.__dataReady = False
3501
3479
3502 if 'nHours' in kwargs:
3480 if 'nHours' in kwargs:
3503 nHours = kwargs['nHours']
3481 nHours = kwargs['nHours']
3504 else:
3482 else:
3505 nHours = 1
3483 nHours = 1
3506
3484
3507 if 'meteorsPerBin' in kwargs:
3485 if 'meteorsPerBin' in kwargs:
3508 meteorThresh = kwargs['meteorsPerBin']
3486 meteorThresh = kwargs['meteorsPerBin']
3509 else:
3487 else:
3510 meteorThresh = 6
3488 meteorThresh = 6
3511
3489
3512 if 'hmin' in kwargs:
3490 if 'hmin' in kwargs:
3513 hmin = kwargs['hmin']
3491 hmin = kwargs['hmin']
3514 else: hmin = 70
3492 else: hmin = 70
3515 if 'hmax' in kwargs:
3493 if 'hmax' in kwargs:
3516 hmax = kwargs['hmax']
3494 hmax = kwargs['hmax']
3517 else: hmax = 110
3495 else: hmax = 110
3518
3496
3519 dataOut.outputInterval = nHours*3600
3497 dataOut.outputInterval = nHours*3600
3520
3498
3521 if self.__isConfig == False:
3499 if self.__isConfig == False:
3522 #Get Initial LTC time
3500 #Get Initial LTC time
3523 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3501 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3524 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3502 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3525
3503
3526 self.__isConfig = True
3504 self.__isConfig = True
3527
3505
3528 if self.__buffer is None:
3506 if self.__buffer is None:
3529 self.__buffer = dataOut.data_param
3507 self.__buffer = dataOut.data_param
3530 self.__firstdata = copy.copy(dataOut)
3508 self.__firstdata = copy.copy(dataOut)
3531
3509
3532 else:
3510 else:
3533 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3511 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3534
3512
3535 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3513 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3536
3514
3537 if self.__dataReady:
3515 if self.__dataReady:
3538 dataOut.utctimeInit = self.__initime
3516 dataOut.utctimeInit = self.__initime
3539
3517
3540 self.__initime += dataOut.outputInterval #to erase time offset
3518 self.__initime += dataOut.outputInterval #to erase time offset
3541
3519
3542 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
3520 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
3543 dataOut.flagNoData = False
3521 dataOut.flagNoData = False
3544 self.__buffer = None
3522 self.__buffer = None
3545
3523
3546 elif technique == 'Meteors1':
3524 elif technique == 'Meteors1':
3547 dataOut.flagNoData = True
3525 dataOut.flagNoData = True
3548 self.__dataReady = False
3526 self.__dataReady = False
3549
3527
3550 if 'nMins' in kwargs:
3528 if 'nMins' in kwargs:
3551 nMins = kwargs['nMins']
3529 nMins = kwargs['nMins']
3552 else: nMins = 20
3530 else: nMins = 20
3553 if 'rx_location' in kwargs:
3531 if 'rx_location' in kwargs:
3554 rx_location = kwargs['rx_location']
3532 rx_location = kwargs['rx_location']
3555 else: rx_location = [(0,1),(1,1),(1,0)]
3533 else: rx_location = [(0,1),(1,1),(1,0)]
3556 if 'azimuth' in kwargs:
3534 if 'azimuth' in kwargs:
3557 azimuth = kwargs['azimuth']
3535 azimuth = kwargs['azimuth']
3558 else: azimuth = 51.06
3536 else: azimuth = 51.06
3559 if 'dfactor' in kwargs:
3537 if 'dfactor' in kwargs:
3560 dfactor = kwargs['dfactor']
3538 dfactor = kwargs['dfactor']
3561 if 'mode' in kwargs:
3539 if 'mode' in kwargs:
3562 mode = kwargs['mode']
3540 mode = kwargs['mode']
3563 if 'theta_x' in kwargs:
3541 if 'theta_x' in kwargs:
3564 theta_x = kwargs['theta_x']
3542 theta_x = kwargs['theta_x']
3565 if 'theta_y' in kwargs:
3543 if 'theta_y' in kwargs:
3566 theta_y = kwargs['theta_y']
3544 theta_y = kwargs['theta_y']
3567 else: mode = 'SA'
3545 else: mode = 'SA'
3568
3546
3569 #Borrar luego esto
3547 #Borrar luego esto
3570 if dataOut.groupList is None:
3548 if dataOut.groupList is None:
3571 dataOut.groupList = [(0,1),(0,2),(1,2)]
3549 dataOut.groupList = [(0,1),(0,2),(1,2)]
3572 groupList = dataOut.groupList
3550 groupList = dataOut.groupList
3573 C = 3e8
3551 C = 3e8
3574 freq = 50e6
3552 freq = 50e6
3575 lamb = C/freq
3553 lamb = C/freq
3576 k = 2*numpy.pi/lamb
3554 k = 2*numpy.pi/lamb
3577
3555
3578 timeList = dataOut.abscissaList
3556 timeList = dataOut.abscissaList
3579 heightList = dataOut.heightList
3557 heightList = dataOut.heightList
3580
3558
3581 if self.__isConfig == False:
3559 if self.__isConfig == False:
3582 dataOut.outputInterval = nMins*60
3560 dataOut.outputInterval = nMins*60
3583 #Get Initial LTC time
3561 #Get Initial LTC time
3584 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3562 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3585 minuteAux = initime.minute
3563 minuteAux = initime.minute
3586 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
3564 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
3587 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3565 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3588
3566
3589 self.__isConfig = True
3567 self.__isConfig = True
3590
3568
3591 if self.__buffer is None:
3569 if self.__buffer is None:
3592 self.__buffer = dataOut.data_param
3570 self.__buffer = dataOut.data_param
3593 self.__firstdata = copy.copy(dataOut)
3571 self.__firstdata = copy.copy(dataOut)
3594
3572
3595 else:
3573 else:
3596 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3574 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3597
3575
3598 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3576 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3599
3577
3600 if self.__dataReady:
3578 if self.__dataReady:
3601 dataOut.utctimeInit = self.__initime
3579 dataOut.utctimeInit = self.__initime
3602 self.__initime += dataOut.outputInterval #to erase time offset
3580 self.__initime += dataOut.outputInterval #to erase time offset
3603
3581
3604 metArray = self.__buffer
3582 metArray = self.__buffer
3605 if mode == 'SA':
3583 if mode == 'SA':
3606 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
3584 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
3607 elif mode == 'DBS':
3585 elif mode == 'DBS':
3608 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
3586 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
3609 dataOut.data_output = dataOut.data_output.T
3587 dataOut.data_output = dataOut.data_output.T
3610 dataOut.flagNoData = False
3588 dataOut.flagNoData = False
3611 self.__buffer = None
3589 self.__buffer = None
3612
3590
3613 return
3591 return dataOut
3614
3592
3615 class EWDriftsEstimation(Operation):
3593 class EWDriftsEstimation(Operation):
3616
3594
3617 def __init__(self):
3595 def __init__(self):
3618 Operation.__init__(self)
3596 Operation.__init__(self)
3619
3597
3620 def __correctValues(self, heiRang, phi, velRadial, SNR):
3598 def __correctValues(self, heiRang, phi, velRadial, SNR):
3621 listPhi = phi.tolist()
3599 listPhi = phi.tolist()
3622 maxid = listPhi.index(max(listPhi))
3600 maxid = listPhi.index(max(listPhi))
3623 minid = listPhi.index(min(listPhi))
3601 minid = listPhi.index(min(listPhi))
3624
3602
3625 rango = list(range(len(phi)))
3603 rango = list(range(len(phi)))
3626 heiRang1 = heiRang*math.cos(phi[maxid])
3604 heiRang1 = heiRang*math.cos(phi[maxid])
3627 heiRangAux = heiRang*math.cos(phi[minid])
3605 heiRangAux = heiRang*math.cos(phi[minid])
3628 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3606 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3629 heiRang1 = numpy.delete(heiRang1,indOut)
3607 heiRang1 = numpy.delete(heiRang1,indOut)
3630
3608
3631 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3609 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3632 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3610 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3633
3611
3634 for i in rango:
3612 for i in rango:
3635 x = heiRang*math.cos(phi[i])
3613 x = heiRang*math.cos(phi[i])
3636 y1 = velRadial[i,:]
3614 y1 = velRadial[i,:]
3637 vali= (numpy.isfinite(y1)==True).nonzero()
3615 vali= (numpy.isfinite(y1)==True).nonzero()
3638 y1=y1[vali]
3616 y1=y1[vali]
3639 x = x[vali]
3617 x = x[vali]
3640 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
3618 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
3641
3642 #heiRang1 = x*math.cos(phi[maxid])
3643 x1 = heiRang1
3619 x1 = heiRang1
3644 y11 = f1(x1)
3620 y11 = f1(x1)
3645
3646 y2 = SNR[i,:]
3621 y2 = SNR[i,:]
3647 #print 'snr ', y2
3648 x = heiRang*math.cos(phi[i])
3622 x = heiRang*math.cos(phi[i])
3649 vali= (y2 != -1).nonzero()
3623 vali= (y2 != -1).nonzero()
3650 y2 = y2[vali]
3624 y2 = y2[vali]
3651 x = x[vali]
3625 x = x[vali]
3652 #print 'snr ',y2
3653 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
3626 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
3654 y21 = f2(x1)
3627 y21 = f2(x1)
3655
3628
3656 velRadial1[i,:] = y11
3629 velRadial1[i,:] = y11
3657 SNR1[i,:] = y21
3630 SNR1[i,:] = y21
3658
3631
3659 return heiRang1, velRadial1, SNR1
3632 return heiRang1, velRadial1, SNR1
3660
3633
3661 def run(self, dataOut, zenith, zenithCorrection,fileDrifts):
3634 def run(self, dataOut, zenith, zenithCorrection,fileDrifts):
3662
3635
3663 heiRang = dataOut.heightList
3636 heiRang = dataOut.heightList
3664 velRadial = dataOut.data_param[:,3,:]
3637 velRadial = dataOut.data_param[:,3,:]
3665 velRadialm = dataOut.data_param[:,2:4,:]*-1
3638 velRadialm = dataOut.data_param[:,2:4,:]*-1
3666
3667 rbufc=dataOut.data_paramC[:,:,0]
3639 rbufc=dataOut.data_paramC[:,:,0]
3668 ebufc=dataOut.data_paramC[:,:,1]
3640 ebufc=dataOut.data_paramC[:,:,1]
3669 SNR = dataOut.data_snr
3641 SNR = dataOut.data_snr
3670 velRerr = dataOut.data_error[:,4,:]
3642 velRerr = dataOut.data_error[:,4,:]
3671 #moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
3672 channels = dataOut.channelList
3643 channels = dataOut.channelList
3673 nChan = len(channels)
3644 nChan = len(channels)
3674 my_nbeams = nChan/2
3645 my_nbeams = nChan/2
3675 if my_nbeams == 2:
3646 if my_nbeams == 2:
3676 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
3647 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
3677 else :
3648 else :
3678 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]]))
3649 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]]))
3679 dataOut.moments=moments
3650 dataOut.moments=moments
3680 # Coherent
3651 # Coherent
3681 smooth_wC = ebufc[0,:]
3652 smooth_wC = ebufc[0,:]
3682 p_w0C = rbufc[0,:]
3653 p_w0C = rbufc[0,:]
3683 p_w1C = rbufc[1,:]
3654 p_w1C = rbufc[1,:]
3684 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
3655 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
3685 t_wC = rbufc[3,:]
3656 t_wC = rbufc[3,:]
3686 #my_nbeams = 2
3687 if my_nbeams == 1:
3657 if my_nbeams == 1:
3688 w = velRadial[0,:]
3658 w = velRadial[0,:]
3689 winds = velRadial.copy()
3659 winds = velRadial.copy()
3690 w_err = velRerr[0,:]
3660 w_err = velRerr[0,:]
3691 snr1 = 10*numpy.log10(SNR[0])
3661 snr1 = 10*numpy.log10(SNR[0])
3692 if my_nbeams == 2:
3662 if my_nbeams == 2:
3693 zenith = numpy.array(zenith)
3663 zenith = numpy.array(zenith)
3694 zenith -= zenithCorrection
3664 zenith -= zenithCorrection
3695 zenith *= numpy.pi/180
3665 zenith *= numpy.pi/180
3696 if zenithCorrection != 0 :
3666 if zenithCorrection != 0 :
3697 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
3667 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
3698 else :
3668 else :
3699 heiRang1 = heiRang
3669 heiRang1 = heiRang
3700 velRadial1 = velRadial
3670 velRadial1 = velRadial
3701 SNR1 = SNR
3671 SNR1 = SNR
3702
3672
3703 alp = zenith[0]
3673 alp = zenith[0]
3704 bet = zenith[1]
3674 bet = zenith[1]
3705
3675
3706 w_w = velRadial1[0,:]
3676 w_w = velRadial1[0,:]
3707 w_e = velRadial1[1,:]
3677 w_e = velRadial1[1,:]
3708 w_w_err = velRerr[0,:]
3678 w_w_err = velRerr[0,:]
3709 w_e_err = velRerr[1,:]
3679 w_e_err = velRerr[1,:]
3710
3680
3711 val = (numpy.isfinite(w_w)==False).nonzero()
3681 val = (numpy.isfinite(w_w)==False).nonzero()
3712 val = val[0]
3682 val = val[0]
3713 bad = val
3683 bad = val
3714 if len(bad) > 0 :
3684 if len(bad) > 0 :
3715 w_w[bad] = w_wC[bad]
3685 w_w[bad] = w_wC[bad]
3716 w_w_err[bad]= numpy.nan
3686 w_w_err[bad]= numpy.nan
3717 # if my_nbeams == 2:
3718 smooth_eC=ebufc[4,:]
3687 smooth_eC=ebufc[4,:]
3719 p_e0C = rbufc[4,:]
3688 p_e0C = rbufc[4,:]
3720 p_e1C = rbufc[5,:]
3689 p_e1C = rbufc[5,:]
3721 w_eC = rbufc[6,:]*-1
3690 w_eC = rbufc[6,:]*-1
3722 t_eC = rbufc[7,:]
3691 t_eC = rbufc[7,:]
3723 val = (numpy.isfinite(w_e)==False).nonzero()
3692 val = (numpy.isfinite(w_e)==False).nonzero()
3724 val = val[0]
3693 val = val[0]
3725 bad = val
3694 bad = val
3726 if len(bad) > 0 :
3695 if len(bad) > 0 :
3727 w_e[bad] = w_eC[bad]
3696 w_e[bad] = w_eC[bad]
3728 w_e_err[bad]= numpy.nan
3697 w_e_err[bad]= numpy.nan
3729
3698
3730 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
3699 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
3731 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
3700 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
3732
3701
3733 w_err = numpy.sqrt((w_w_err*numpy.sin(bet))**2.+(w_e_err*numpy.sin(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
3702 w_err = numpy.sqrt((w_w_err*numpy.sin(bet))**2.+(w_e_err*numpy.sin(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
3734 u_err = numpy.sqrt((w_w_err*numpy.cos(bet))**2.+(w_e_err*numpy.cos(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
3703 u_err = numpy.sqrt((w_w_err*numpy.cos(bet))**2.+(w_e_err*numpy.cos(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
3735
3704
3736 winds = numpy.vstack((w,u))
3705 winds = numpy.vstack((w,u))
3737
3706
3738 dataOut.heightList = heiRang1
3707 dataOut.heightList = heiRang1
3739 snr1 = 10*numpy.log10(SNR1[0])
3708 snr1 = 10*numpy.log10(SNR1[0])
3740 dataOut.data_output = winds
3709 dataOut.data_output = winds
3741 #snr1 = 10*numpy.log10(SNR1[0])
3710 #snr1 = 10*numpy.log10(SNR1[0])
3742 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
3711 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
3743 dataOut.utctimeInit = dataOut.utctime
3712 dataOut.utctimeInit = dataOut.utctime
3744 dataOut.outputInterval = dataOut.timeInterval
3713 dataOut.outputInterval = dataOut.timeInterval
3745
3714
3746 hei_aver0 = 218
3715 hei_aver0 = 218
3747 jrange = 450 #900 para HA drifts
3716 jrange = 450 #900 para HA drifts
3748 deltah = 15 # para EWDrifts 15.0 MP 15 #dataOut.spacing(0)
3717 deltah = 15.0 #dataOut.spacing(0) 25 HAD
3749 h0 = 0.0 #dataOut.first_height(0)
3718 h0 = 0.0 #dataOut.first_height(0)
3750 heights = dataOut.heightList
3719 heights = dataOut.heightList
3751 nhei = len(heights)
3720 nhei = len(heights)
3752
3721
3753 range1 = numpy.arange(nhei) * deltah + h0
3722 range1 = numpy.arange(nhei) * deltah + h0
3754
3755 #jhei = WHERE(range1 GE hei_aver0 , jcount)
3756 jhei = (range1 >= hei_aver0).nonzero()
3723 jhei = (range1 >= hei_aver0).nonzero()
3757 if len(jhei[0]) > 0 :
3724 if len(jhei[0]) > 0 :
3758 h0_index = jhei[0][0] # Initial height for getting averages 218km
3725 h0_index = jhei[0][0] # Initial height for getting averages 218km
3759
3726
3760 mynhei = 7
3727 mynhei = 7
3761 nhei_avg = int(jrange/deltah)
3728 nhei_avg = int(jrange/deltah)
3762 h_avgs = int(nhei_avg/mynhei)
3729 h_avgs = int(nhei_avg/mynhei)
3763 nhei_avg = h_avgs*(mynhei-1)+mynhei
3730 nhei_avg = h_avgs*(mynhei-1)+mynhei
3764
3731
3765 navgs = numpy.zeros(mynhei,dtype='float')
3732 navgs = numpy.zeros(mynhei,dtype='float')
3766 delta_h = numpy.zeros(mynhei,dtype='float')
3733 delta_h = numpy.zeros(mynhei,dtype='float')
3767 range_aver = numpy.zeros(mynhei,dtype='float')
3734 range_aver = numpy.zeros(mynhei,dtype='float')
3768 for ih in range( mynhei-1 ):
3735 for ih in range( mynhei-1 ):
3769 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
3736 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
3770 navgs[ih] = h_avgs
3737 navgs[ih] = h_avgs
3771 delta_h[ih] = deltah*h_avgs
3738 delta_h[ih] = deltah*h_avgs
3772
3739
3773 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
3740 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
3774 navgs[mynhei-1] = 6*h_avgs
3741 navgs[mynhei-1] = 6*h_avgs
3775 delta_h[mynhei-1] = deltah*6*h_avgs
3742 delta_h[mynhei-1] = deltah*6*h_avgs
3776
3743
3777 wA = w[h0_index:h0_index+nhei_avg-0]
3744 wA = w[h0_index:h0_index+nhei_avg-0]
3778 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
3745 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
3779
3780 for i in range(5) :
3746 for i in range(5) :
3781 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
3747 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
3782 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
3748 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
3783 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3749 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3784 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3750 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3785 wA[6*h_avgs+i] = avg
3751 wA[6*h_avgs+i] = avg
3786 wA_err[6*h_avgs+i] = sigma
3752 wA_err[6*h_avgs+i] = sigma
3787
3753
3788
3754
3789 vals = wA[0:6*h_avgs-0]
3755 vals = wA[0:6*h_avgs-0]
3790 errs=wA_err[0:6*h_avgs-0]
3756 errs=wA_err[0:6*h_avgs-0]
3791 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
3757 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
3792 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3758 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3793 wA[nhei_avg-1] = avg
3759 wA[nhei_avg-1] = avg
3794 wA_err[nhei_avg-1] = sigma
3760 wA_err[nhei_avg-1] = sigma
3795
3761
3796 wA = wA[6*h_avgs:nhei_avg-0]
3762 wA = wA[6*h_avgs:nhei_avg-0]
3797 wA_err=wA_err[6*h_avgs:nhei_avg-0]
3763 wA_err=wA_err[6*h_avgs:nhei_avg-0]
3798 if my_nbeams == 2 :
3764 if my_nbeams == 2 :
3799
3800 uA = u[h0_index:h0_index+nhei_avg]
3765 uA = u[h0_index:h0_index+nhei_avg]
3801 uA_err=u_err[h0_index:h0_index+nhei_avg]
3766 uA_err=u_err[h0_index:h0_index+nhei_avg]
3802
3767
3803 for i in range(5) :
3768 for i in range(5) :
3804 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
3769 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
3805 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
3770 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
3806 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3771 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3807 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3772 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3808 uA[6*h_avgs+i] = avg
3773 uA[6*h_avgs+i] = avg
3809 uA_err[6*h_avgs+i]=sigma
3774 uA_err[6*h_avgs+i]=sigma
3810
3775
3811 vals = uA[0:6*h_avgs-0]
3776 vals = uA[0:6*h_avgs-0]
3812 errs = uA_err[0:6*h_avgs-0]
3777 errs = uA_err[0:6*h_avgs-0]
3813 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3778 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3814 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3779 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3815 uA[nhei_avg-1] = avg
3780 uA[nhei_avg-1] = avg
3816 uA_err[nhei_avg-1] = sigma
3781 uA_err[nhei_avg-1] = sigma
3817 uA = uA[6*h_avgs:nhei_avg-0]
3782 uA = uA[6*h_avgs:nhei_avg-0]
3818 uA_err = uA_err[6*h_avgs:nhei_avg-0]
3783 uA_err = uA_err[6*h_avgs:nhei_avg-0]
3819 dataOut.drifts_avg = numpy.vstack((wA,uA))
3784 dataOut.drifts_avg = numpy.vstack((wA,uA))
3820 if my_nbeams == 1: dataOut.drifts_avg = wA
3785 if my_nbeams == 1: dataOut.drifts_avg = wA
3821 tini=time.localtime(dataOut.utctime)
3786 tini=time.localtime(dataOut.utctime)
3822 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
3787 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
3823 nfile = fileDrifts+'/jro'+datefile+'drifts.txt'
3788 nfile = fileDrifts+'/jro'+datefile+'drifts.txt'
3824
3825 f1 = open(nfile,'a')
3789 f1 = open(nfile,'a')
3826
3827 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
3790 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
3828 driftavgstr=str(dataOut.drifts_avg)
3791 driftavgstr=str(dataOut.drifts_avg)
3829
3830 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
3792 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
3831 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
3793 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
3832 f1.close()
3794 f1.close()
3833
3795
3834 return dataOut
3796 return dataOut
3835
3797
3836 #--------------- Non Specular Meteor ----------------
3798 #--------------- Non Specular Meteor ----------------
3837
3799
3838 class NonSpecularMeteorDetection(Operation):
3800 class NonSpecularMeteorDetection(Operation):
3839
3801
3840 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
3802 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
3841 data_acf = dataOut.data_pre[0]
3803 data_acf = dataOut.data_pre[0]
3842 data_ccf = dataOut.data_pre[1]
3804 data_ccf = dataOut.data_pre[1]
3843 pairsList = dataOut.groupList[1]
3805 pairsList = dataOut.groupList[1]
3844
3806
3845 lamb = dataOut.C/dataOut.frequency
3807 lamb = dataOut.C/dataOut.frequency
3846 tSamp = dataOut.ippSeconds*dataOut.nCohInt
3808 tSamp = dataOut.ippSeconds*dataOut.nCohInt
3847 paramInterval = dataOut.paramInterval
3809 paramInterval = dataOut.paramInterval
3848
3810
3849 nChannels = data_acf.shape[0]
3811 nChannels = data_acf.shape[0]
3850 nLags = data_acf.shape[1]
3812 nLags = data_acf.shape[1]
3851 nProfiles = data_acf.shape[2]
3813 nProfiles = data_acf.shape[2]
3852 nHeights = dataOut.nHeights
3814 nHeights = dataOut.nHeights
3853 nCohInt = dataOut.nCohInt
3815 nCohInt = dataOut.nCohInt
3854 sec = numpy.round(nProfiles/dataOut.paramInterval)
3816 sec = numpy.round(nProfiles/dataOut.paramInterval)
3855 heightList = dataOut.heightList
3817 heightList = dataOut.heightList
3856 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
3818 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
3857 utctime = dataOut.utctime
3819 utctime = dataOut.utctime
3858
3820
3859 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
3821 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
3860
3822
3861 #------------------------ SNR --------------------------------------
3823 #------------------------ SNR --------------------------------------
3862 power = data_acf[:,0,:,:].real
3824 power = data_acf[:,0,:,:].real
3863 noise = numpy.zeros(nChannels)
3825 noise = numpy.zeros(nChannels)
3864 SNR = numpy.zeros(power.shape)
3826 SNR = numpy.zeros(power.shape)
3865 for i in range(nChannels):
3827 for i in range(nChannels):
3866 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
3828 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
3867 SNR[i] = (power[i]-noise[i])/noise[i]
3829 SNR[i] = (power[i]-noise[i])/noise[i]
3868 SNRm = numpy.nanmean(SNR, axis = 0)
3830 SNRm = numpy.nanmean(SNR, axis = 0)
3869 SNRdB = 10*numpy.log10(SNR)
3831 SNRdB = 10*numpy.log10(SNR)
3870
3832
3871 if mode == 'SA':
3833 if mode == 'SA':
3872 dataOut.groupList = dataOut.groupList[1]
3834 dataOut.groupList = dataOut.groupList[1]
3873 nPairs = data_ccf.shape[0]
3835 nPairs = data_ccf.shape[0]
3874 #---------------------- Coherence and Phase --------------------------
3836 #---------------------- Coherence and Phase --------------------------
3875 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
3837 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
3876 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
3838 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
3877
3839
3878 for p in range(nPairs):
3840 for p in range(nPairs):
3879 ch0 = pairsList[p][0]
3841 ch0 = pairsList[p][0]
3880 ch1 = pairsList[p][1]
3842 ch1 = pairsList[p][1]
3881 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
3843 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
3882 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
3844 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
3883 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
3845 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
3884 coh = numpy.nanmax(coh1, axis = 0)
3846 coh = numpy.nanmax(coh1, axis = 0)
3885 #---------------------- Radial Velocity ----------------------------
3847 #---------------------- Radial Velocity ----------------------------
3886 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
3848 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
3887 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
3849 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
3888
3850
3889 if allData:
3851 if allData:
3890 boolMetFin = ~numpy.isnan(SNRm)
3852 boolMetFin = ~numpy.isnan(SNRm)
3891 else:
3853 else:
3892 #------------------------ Meteor mask ---------------------------------
3854 #------------------------ Meteor mask ---------------------------------
3893
3855
3894 #Coherence mask
3856 #Coherence mask
3895 boolMet1 = coh > 0.75
3857 boolMet1 = coh > 0.75
3896 struc = numpy.ones((30,1))
3858 struc = numpy.ones((30,1))
3897 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
3859 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
3898
3860
3899 #Derivative mask
3861 #Derivative mask
3900 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
3862 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
3901 boolMet2 = derPhase < 0.2
3863 boolMet2 = derPhase < 0.2
3902 boolMet2 = ndimage.median_filter(boolMet2,size=5)
3864 boolMet2 = ndimage.median_filter(boolMet2,size=5)
3903 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
3865 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
3904 boolMetFin = boolMet1&boolMet2
3866 boolMetFin = boolMet1&boolMet2
3905 #Creating data_param
3867 #Creating data_param
3906 coordMet = numpy.where(boolMetFin)
3868 coordMet = numpy.where(boolMetFin)
3907
3869
3908 tmet = coordMet[0]
3870 tmet = coordMet[0]
3909 hmet = coordMet[1]
3871 hmet = coordMet[1]
3910
3872
3911 data_param = numpy.zeros((tmet.size, 6 + nPairs))
3873 data_param = numpy.zeros((tmet.size, 6 + nPairs))
3912 data_param[:,0] = utctime
3874 data_param[:,0] = utctime
3913 data_param[:,1] = tmet
3875 data_param[:,1] = tmet
3914 data_param[:,2] = hmet
3876 data_param[:,2] = hmet
3915 data_param[:,3] = SNRm[tmet,hmet]
3877 data_param[:,3] = SNRm[tmet,hmet]
3916 data_param[:,4] = velRad[tmet,hmet]
3878 data_param[:,4] = velRad[tmet,hmet]
3917 data_param[:,5] = coh[tmet,hmet]
3879 data_param[:,5] = coh[tmet,hmet]
3918 data_param[:,6:] = phase[:,tmet,hmet].T
3880 data_param[:,6:] = phase[:,tmet,hmet].T
3919
3881
3920 elif mode == 'DBS':
3882 elif mode == 'DBS':
3921 dataOut.groupList = numpy.arange(nChannels)
3883 dataOut.groupList = numpy.arange(nChannels)
3922
3884
3923 #Radial Velocities
3885 #Radial Velocities
3924 phase = numpy.angle(data_acf[:,1,:,:])
3886 phase = numpy.angle(data_acf[:,1,:,:])
3925 velRad = phase*lamb/(4*numpy.pi*tSamp)
3887 velRad = phase*lamb/(4*numpy.pi*tSamp)
3926
3888
3927 #Spectral width
3889 #Spectral width
3928 acf1 = data_acf[:,1,:,:]
3890 acf1 = data_acf[:,1,:,:]
3929 acf2 = data_acf[:,2,:,:]
3891 acf2 = data_acf[:,2,:,:]
3930
3892
3931 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
3893 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
3932 if allData:
3894 if allData:
3933 boolMetFin = ~numpy.isnan(SNRdB)
3895 boolMetFin = ~numpy.isnan(SNRdB)
3934 else:
3896 else:
3935 #SNR
3897 #SNR
3936 boolMet1 = (SNRdB>SNRthresh) #SNR mask
3898 boolMet1 = (SNRdB>SNRthresh) #SNR mask
3937 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
3899 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
3938
3900
3939 #Radial velocity
3901 #Radial velocity
3940 boolMet2 = numpy.abs(velRad) < 20
3902 boolMet2 = numpy.abs(velRad) < 20
3941 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
3903 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
3942
3904
3943 #Spectral Width
3905 #Spectral Width
3944 boolMet3 = spcWidth < 30
3906 boolMet3 = spcWidth < 30
3945 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
3907 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
3946 boolMetFin = boolMet1&boolMet2&boolMet3
3908 boolMetFin = boolMet1&boolMet2&boolMet3
3947
3909
3948 #Creating data_param
3910 #Creating data_param
3949 coordMet = numpy.where(boolMetFin)
3911 coordMet = numpy.where(boolMetFin)
3950
3912
3951 cmet = coordMet[0]
3913 cmet = coordMet[0]
3952 tmet = coordMet[1]
3914 tmet = coordMet[1]
3953 hmet = coordMet[2]
3915 hmet = coordMet[2]
3954
3916
3955 data_param = numpy.zeros((tmet.size, 7))
3917 data_param = numpy.zeros((tmet.size, 7))
3956 data_param[:,0] = utctime
3918 data_param[:,0] = utctime
3957 data_param[:,1] = cmet
3919 data_param[:,1] = cmet
3958 data_param[:,2] = tmet
3920 data_param[:,2] = tmet
3959 data_param[:,3] = hmet
3921 data_param[:,3] = hmet
3960 data_param[:,4] = SNR[cmet,tmet,hmet].T
3922 data_param[:,4] = SNR[cmet,tmet,hmet].T
3961 data_param[:,5] = velRad[cmet,tmet,hmet].T
3923 data_param[:,5] = velRad[cmet,tmet,hmet].T
3962 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
3924 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
3963
3925
3964 if len(data_param) == 0:
3926 if len(data_param) == 0:
3965 dataOut.flagNoData = True
3927 dataOut.flagNoData = True
3966 else:
3928 else:
3967 dataOut.data_param = data_param
3929 dataOut.data_param = data_param
3968
3930
3969 def __erase_small(self, binArray, threshX, threshY):
3931 def __erase_small(self, binArray, threshX, threshY):
3970 labarray, numfeat = ndimage.measurements.label(binArray)
3932 labarray, numfeat = ndimage.measurements.label(binArray)
3971 binArray1 = numpy.copy(binArray)
3933 binArray1 = numpy.copy(binArray)
3972
3934
3973 for i in range(1,numfeat + 1):
3935 for i in range(1,numfeat + 1):
3974 auxBin = (labarray==i)
3936 auxBin = (labarray==i)
3975 auxSize = auxBin.sum()
3937 auxSize = auxBin.sum()
3976
3938
3977 x,y = numpy.where(auxBin)
3939 x,y = numpy.where(auxBin)
3978 widthX = x.max() - x.min()
3940 widthX = x.max() - x.min()
3979 widthY = y.max() - y.min()
3941 widthY = y.max() - y.min()
3980
3942
3981 #width X: 3 seg -> 12.5*3
3943 #width X: 3 seg -> 12.5*3
3982 #width Y:
3944 #width Y:
3983
3945
3984 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
3946 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
3985 binArray1[auxBin] = False
3947 binArray1[auxBin] = False
3986
3948
3987 return binArray1
3949 return binArray1
3988
3950
3989 #--------------- Specular Meteor ----------------
3951 #--------------- Specular Meteor ----------------
3990
3952
3991 class SMDetection(Operation):
3953 class SMDetection(Operation):
3992 '''
3954 '''
3993 Function DetectMeteors()
3955 Function DetectMeteors()
3994 Project developed with paper:
3956 Project developed with paper:
3995 HOLDSWORTH ET AL. 2004
3957 HOLDSWORTH ET AL. 2004
3996
3958
3997 Input:
3959 Input:
3998 self.dataOut.data_pre
3960 self.dataOut.data_pre
3999
3961
4000 centerReceiverIndex: From the channels, which is the center receiver
3962 centerReceiverIndex: From the channels, which is the center receiver
4001
3963
4002 hei_ref: Height reference for the Beacon signal extraction
3964 hei_ref: Height reference for the Beacon signal extraction
4003 tauindex:
3965 tauindex:
4004 predefinedPhaseShifts: Predefined phase offset for the voltge signals
3966 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4005
3967
4006 cohDetection: Whether to user Coherent detection or not
3968 cohDetection: Whether to user Coherent detection or not
4007 cohDet_timeStep: Coherent Detection calculation time step
3969 cohDet_timeStep: Coherent Detection calculation time step
4008 cohDet_thresh: Coherent Detection phase threshold to correct phases
3970 cohDet_thresh: Coherent Detection phase threshold to correct phases
4009
3971
4010 noise_timeStep: Noise calculation time step
3972 noise_timeStep: Noise calculation time step
4011 noise_multiple: Noise multiple to define signal threshold
3973 noise_multiple: Noise multiple to define signal threshold
4012
3974
4013 multDet_timeLimit: Multiple Detection Removal time limit in seconds
3975 multDet_timeLimit: Multiple Detection Removal time limit in seconds
4014 multDet_rangeLimit: Multiple Detection Removal range limit in km
3976 multDet_rangeLimit: Multiple Detection Removal range limit in km
4015
3977
4016 phaseThresh: Maximum phase difference between receiver to be consider a meteor
3978 phaseThresh: Maximum phase difference between receiver to be consider a meteor
4017 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
3979 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
4018
3980
4019 hmin: Minimum Height of the meteor to use it in the further wind estimations
3981 hmin: Minimum Height of the meteor to use it in the further wind estimations
4020 hmax: Maximum Height of the meteor to use it in the further wind estimations
3982 hmax: Maximum Height of the meteor to use it in the further wind estimations
4021 azimuth: Azimuth angle correction
3983 azimuth: Azimuth angle correction
4022
3984
4023 Affected:
3985 Affected:
4024 self.dataOut.data_param
3986 self.dataOut.data_param
4025
3987
4026 Rejection Criteria (Errors):
3988 Rejection Criteria (Errors):
4027 0: No error; analysis OK
3989 0: No error; analysis OK
4028 1: SNR < SNR threshold
3990 1: SNR < SNR threshold
4029 2: angle of arrival (AOA) ambiguously determined
3991 2: angle of arrival (AOA) ambiguously determined
4030 3: AOA estimate not feasible
3992 3: AOA estimate not feasible
4031 4: Large difference in AOAs obtained from different antenna baselines
3993 4: Large difference in AOAs obtained from different antenna baselines
4032 5: echo at start or end of time series
3994 5: echo at start or end of time series
4033 6: echo less than 5 examples long; too short for analysis
3995 6: echo less than 5 examples long; too short for analysis
4034 7: echo rise exceeds 0.3s
3996 7: echo rise exceeds 0.3s
4035 8: echo decay time less than twice rise time
3997 8: echo decay time less than twice rise time
4036 9: large power level before echo
3998 9: large power level before echo
4037 10: large power level after echo
3999 10: large power level after echo
4038 11: poor fit to amplitude for estimation of decay time
4000 11: poor fit to amplitude for estimation of decay time
4039 12: poor fit to CCF phase variation for estimation of radial drift velocity
4001 12: poor fit to CCF phase variation for estimation of radial drift velocity
4040 13: height unresolvable echo: not valid height within 70 to 110 km
4002 13: height unresolvable echo: not valid height within 70 to 110 km
4041 14: height ambiguous echo: more then one possible height within 70 to 110 km
4003 14: height ambiguous echo: more then one possible height within 70 to 110 km
4042 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
4004 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
4043 16: oscilatory echo, indicating event most likely not an underdense echo
4005 16: oscilatory echo, indicating event most likely not an underdense echo
4044
4006
4045 17: phase difference in meteor Reestimation
4007 17: phase difference in meteor Reestimation
4046
4008
4047 Data Storage:
4009 Data Storage:
4048 Meteors for Wind Estimation (8):
4010 Meteors for Wind Estimation (8):
4049 Utc Time | Range Height
4011 Utc Time | Range Height
4050 Azimuth Zenith errorCosDir
4012 Azimuth Zenith errorCosDir
4051 VelRad errorVelRad
4013 VelRad errorVelRad
4052 Phase0 Phase1 Phase2 Phase3
4014 Phase0 Phase1 Phase2 Phase3
4053 TypeError
4015 TypeError
4054
4016
4055 '''
4017 '''
4056
4018
4057 def run(self, dataOut, hei_ref = None, tauindex = 0,
4019 def run(self, dataOut, hei_ref = None, tauindex = 0,
4058 phaseOffsets = None,
4020 phaseOffsets = None,
4059 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
4021 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
4060 noise_timeStep = 4, noise_multiple = 4,
4022 noise_timeStep = 4, noise_multiple = 4,
4061 multDet_timeLimit = 1, multDet_rangeLimit = 3,
4023 multDet_timeLimit = 1, multDet_rangeLimit = 3,
4062 phaseThresh = 20, SNRThresh = 5,
4024 phaseThresh = 20, SNRThresh = 5,
4063 hmin = 50, hmax=150, azimuth = 0,
4025 hmin = 50, hmax=150, azimuth = 0,
4064 channelPositions = None) :
4026 channelPositions = None) :
4065
4027
4066
4028
4067 #Getting Pairslist
4029 #Getting Pairslist
4068 if channelPositions is None:
4030 if channelPositions is None:
4069 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4031 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4070 meteorOps = SMOperations()
4032 meteorOps = SMOperations()
4071 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4033 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4072 heiRang = dataOut.heightList
4034 heiRang = dataOut.heightList
4073 #Get Beacon signal - No Beacon signal anymore
4035 #Get Beacon signal - No Beacon signal anymore
4074 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
4036 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
4075 # see if the user put in pre defined phase shifts
4037 # see if the user put in pre defined phase shifts
4076 voltsPShift = dataOut.data_pre.copy()
4038 voltsPShift = dataOut.data_pre.copy()
4077
4039
4078 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
4040 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
4079
4041
4080 #Remove DC
4042 #Remove DC
4081 voltsDC = numpy.mean(voltsPShift,1)
4043 voltsDC = numpy.mean(voltsPShift,1)
4082 voltsDC = numpy.mean(voltsDC,1)
4044 voltsDC = numpy.mean(voltsDC,1)
4083 for i in range(voltsDC.shape[0]):
4045 for i in range(voltsDC.shape[0]):
4084 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
4046 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
4085
4047
4086 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
4048 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
4087
4049
4088 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
4050 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
4089 #Coherent Detection
4051 #Coherent Detection
4090 if cohDetection:
4052 if cohDetection:
4091 #use coherent detection to get the net power
4053 #use coherent detection to get the net power
4092 cohDet_thresh = cohDet_thresh*numpy.pi/180
4054 cohDet_thresh = cohDet_thresh*numpy.pi/180
4093 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
4055 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
4094
4056
4095 #Non-coherent detection!
4057 #Non-coherent detection!
4096 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
4058 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
4097 #********** END OF COH/NON-COH POWER CALCULATION**********************
4059 #********** END OF COH/NON-COH POWER CALCULATION**********************
4098
4060
4099 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
4061 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
4100 #Get noise
4062 #Get noise
4101 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
4063 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
4102 #Get signal threshold
4064 #Get signal threshold
4103 signalThresh = noise_multiple*noise
4065 signalThresh = noise_multiple*noise
4104 #Meteor echoes detection
4066 #Meteor echoes detection
4105 listMeteors = self.__findMeteors(powerNet, signalThresh)
4067 listMeteors = self.__findMeteors(powerNet, signalThresh)
4106 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
4068 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
4107
4069
4108 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
4070 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
4109 #Parameters
4071 #Parameters
4110 heiRange = dataOut.heightList
4072 heiRange = dataOut.heightList
4111 rangeInterval = heiRange[1] - heiRange[0]
4073 rangeInterval = heiRange[1] - heiRange[0]
4112 rangeLimit = multDet_rangeLimit/rangeInterval
4074 rangeLimit = multDet_rangeLimit/rangeInterval
4113 timeLimit = multDet_timeLimit/dataOut.timeInterval
4075 timeLimit = multDet_timeLimit/dataOut.timeInterval
4114 #Multiple detection removals
4076 #Multiple detection removals
4115 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
4077 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
4116 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
4078 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
4117
4079
4118 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
4080 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
4119 #Parameters
4081 #Parameters
4120 phaseThresh = phaseThresh*numpy.pi/180
4082 phaseThresh = phaseThresh*numpy.pi/180
4121 thresh = [phaseThresh, noise_multiple, SNRThresh]
4083 thresh = [phaseThresh, noise_multiple, SNRThresh]
4122 #Meteor reestimation (Errors N 1, 6, 12, 17)
4084 #Meteor reestimation (Errors N 1, 6, 12, 17)
4123 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
4085 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
4124 #Estimation of decay times (Errors N 7, 8, 11)
4086 #Estimation of decay times (Errors N 7, 8, 11)
4125 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
4087 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
4126 #******************* END OF METEOR REESTIMATION *******************
4088 #******************* END OF METEOR REESTIMATION *******************
4127
4089
4128 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
4090 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
4129 #Calculating Radial Velocity (Error N 15)
4091 #Calculating Radial Velocity (Error N 15)
4130 radialStdThresh = 10
4092 radialStdThresh = 10
4131 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
4093 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
4132
4094
4133 if len(listMeteors4) > 0:
4095 if len(listMeteors4) > 0:
4134 #Setting New Array
4096 #Setting New Array
4135 date = dataOut.utctime
4097 date = dataOut.utctime
4136 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
4098 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
4137
4099
4138 #Correcting phase offset
4100 #Correcting phase offset
4139 if phaseOffsets != None:
4101 if phaseOffsets != None:
4140 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4102 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4141 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4103 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4142
4104
4143 #Second Pairslist
4105 #Second Pairslist
4144 pairsList = []
4106 pairsList = []
4145 pairx = (0,1)
4107 pairx = (0,1)
4146 pairy = (2,3)
4108 pairy = (2,3)
4147 pairsList.append(pairx)
4109 pairsList.append(pairx)
4148 pairsList.append(pairy)
4110 pairsList.append(pairy)
4149
4111
4150 jph = numpy.array([0,0,0,0])
4112 jph = numpy.array([0,0,0,0])
4151 h = (hmin,hmax)
4113 h = (hmin,hmax)
4152 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4114 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4153 dataOut.data_param = arrayParameters
4115 dataOut.data_param = arrayParameters
4154
4116
4155 if arrayParameters is None:
4117 if arrayParameters is None:
4156 dataOut.flagNoData = True
4118 dataOut.flagNoData = True
4157 else:
4119 else:
4158 dataOut.flagNoData = True
4120 dataOut.flagNoData = True
4159
4121
4160 return
4122 return
4161
4123
4162 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
4124 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
4163
4125
4164 minIndex = min(newheis[0])
4126 minIndex = min(newheis[0])
4165 maxIndex = max(newheis[0])
4127 maxIndex = max(newheis[0])
4166
4128
4167 voltage = voltage0[:,:,minIndex:maxIndex+1]
4129 voltage = voltage0[:,:,minIndex:maxIndex+1]
4168 nLength = voltage.shape[1]/n
4130 nLength = voltage.shape[1]/n
4169 nMin = 0
4131 nMin = 0
4170 nMax = 0
4132 nMax = 0
4171 phaseOffset = numpy.zeros((len(pairslist),n))
4133 phaseOffset = numpy.zeros((len(pairslist),n))
4172
4134
4173 for i in range(n):
4135 for i in range(n):
4174 nMax += nLength
4136 nMax += nLength
4175 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
4137 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
4176 phaseCCF = numpy.mean(phaseCCF, axis = 2)
4138 phaseCCF = numpy.mean(phaseCCF, axis = 2)
4177 phaseOffset[:,i] = phaseCCF.transpose()
4139 phaseOffset[:,i] = phaseCCF.transpose()
4178 nMin = nMax
4140 nMin = nMax
4179
4141
4180 #Remove Outliers
4142 #Remove Outliers
4181 factor = 2
4143 factor = 2
4182 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
4144 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
4183 dw = numpy.std(wt,axis = 1)
4145 dw = numpy.std(wt,axis = 1)
4184 dw = dw.reshape((dw.size,1))
4146 dw = dw.reshape((dw.size,1))
4185 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
4147 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
4186 phaseOffset[ind] = numpy.nan
4148 phaseOffset[ind] = numpy.nan
4187 phaseOffset = stats.nanmean(phaseOffset, axis=1)
4149 phaseOffset = stats.nanmean(phaseOffset, axis=1)
4188
4150
4189 return phaseOffset
4151 return phaseOffset
4190
4152
4191 def __shiftPhase(self, data, phaseShift):
4153 def __shiftPhase(self, data, phaseShift):
4192 #this will shift the phase of a complex number
4154 #this will shift the phase of a complex number
4193 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
4155 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
4194 return dataShifted
4156 return dataShifted
4195
4157
4196 def __estimatePhaseDifference(self, array, pairslist):
4158 def __estimatePhaseDifference(self, array, pairslist):
4197 nChannel = array.shape[0]
4159 nChannel = array.shape[0]
4198 nHeights = array.shape[2]
4160 nHeights = array.shape[2]
4199 numPairs = len(pairslist)
4161 numPairs = len(pairslist)
4200 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
4162 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
4201
4163
4202 #Correct phases
4164 #Correct phases
4203 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
4165 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
4204 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4166 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4205
4167
4206 if indDer[0].shape[0] > 0:
4168 if indDer[0].shape[0] > 0:
4207 for i in range(indDer[0].shape[0]):
4169 for i in range(indDer[0].shape[0]):
4208 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
4170 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
4209 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
4171 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
4210
4172
4211 #Linear
4173 #Linear
4212 phaseInt = numpy.zeros((numPairs,1))
4174 phaseInt = numpy.zeros((numPairs,1))
4213 angAllCCF = phaseCCF[:,[0,1,3,4],0]
4175 angAllCCF = phaseCCF[:,[0,1,3,4],0]
4214 for j in range(numPairs):
4176 for j in range(numPairs):
4215 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
4177 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
4216 phaseInt[j] = fit[1]
4178 phaseInt[j] = fit[1]
4217 #Phase Differences
4179 #Phase Differences
4218 phaseDiff = phaseInt - phaseCCF[:,2,:]
4180 phaseDiff = phaseInt - phaseCCF[:,2,:]
4219 phaseArrival = phaseInt.reshape(phaseInt.size)
4181 phaseArrival = phaseInt.reshape(phaseInt.size)
4220
4182
4221 #Dealias
4183 #Dealias
4222 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
4184 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
4223
4185
4224 return phaseDiff, phaseArrival
4186 return phaseDiff, phaseArrival
4225
4187
4226 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
4188 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
4227 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
4189 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
4228 #find the phase shifts of each channel over 1 second intervals
4190 #find the phase shifts of each channel over 1 second intervals
4229 #only look at ranges below the beacon signal
4191 #only look at ranges below the beacon signal
4230 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4192 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4231 numBlocks = int(volts.shape[1]/numProfPerBlock)
4193 numBlocks = int(volts.shape[1]/numProfPerBlock)
4232 numHeights = volts.shape[2]
4194 numHeights = volts.shape[2]
4233 nChannel = volts.shape[0]
4195 nChannel = volts.shape[0]
4234 voltsCohDet = volts.copy()
4196 voltsCohDet = volts.copy()
4235
4197
4236 pairsarray = numpy.array(pairslist)
4198 pairsarray = numpy.array(pairslist)
4237 indSides = pairsarray[:,1]
4199 indSides = pairsarray[:,1]
4238 listBlocks = numpy.array_split(volts, numBlocks, 1)
4200 listBlocks = numpy.array_split(volts, numBlocks, 1)
4239
4201
4240 startInd = 0
4202 startInd = 0
4241 endInd = 0
4203 endInd = 0
4242
4204
4243 for i in range(numBlocks):
4205 for i in range(numBlocks):
4244 startInd = endInd
4206 startInd = endInd
4245 endInd = endInd + listBlocks[i].shape[1]
4207 endInd = endInd + listBlocks[i].shape[1]
4246
4208
4247 arrayBlock = listBlocks[i]
4209 arrayBlock = listBlocks[i]
4248
4210
4249 #Estimate the Phase Difference
4211 #Estimate the Phase Difference
4250 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
4212 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
4251 #Phase Difference RMS
4213 #Phase Difference RMS
4252 arrayPhaseRMS = numpy.abs(phaseDiff)
4214 arrayPhaseRMS = numpy.abs(phaseDiff)
4253 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
4215 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
4254 indPhase = numpy.where(phaseRMSaux==4)
4216 indPhase = numpy.where(phaseRMSaux==4)
4255 #Shifting
4217 #Shifting
4256 if indPhase[0].shape[0] > 0:
4218 if indPhase[0].shape[0] > 0:
4257 for j in range(indSides.size):
4219 for j in range(indSides.size):
4258 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
4220 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
4259 voltsCohDet[:,startInd:endInd,:] = arrayBlock
4221 voltsCohDet[:,startInd:endInd,:] = arrayBlock
4260
4222
4261 return voltsCohDet
4223 return voltsCohDet
4262
4224
4263 def __calculateCCF(self, volts, pairslist ,laglist):
4225 def __calculateCCF(self, volts, pairslist ,laglist):
4264
4226
4265 nHeights = volts.shape[2]
4227 nHeights = volts.shape[2]
4266 nPoints = volts.shape[1]
4228 nPoints = volts.shape[1]
4267 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
4229 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
4268
4230
4269 for i in range(len(pairslist)):
4231 for i in range(len(pairslist)):
4270 volts1 = volts[pairslist[i][0]]
4232 volts1 = volts[pairslist[i][0]]
4271 volts2 = volts[pairslist[i][1]]
4233 volts2 = volts[pairslist[i][1]]
4272
4234
4273 for t in range(len(laglist)):
4235 for t in range(len(laglist)):
4274 idxT = laglist[t]
4236 idxT = laglist[t]
4275 if idxT >= 0:
4237 if idxT >= 0:
4276 vStacked = numpy.vstack((volts2[idxT:,:],
4238 vStacked = numpy.vstack((volts2[idxT:,:],
4277 numpy.zeros((idxT, nHeights),dtype='complex')))
4239 numpy.zeros((idxT, nHeights),dtype='complex')))
4278 else:
4240 else:
4279 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
4241 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
4280 volts2[:(nPoints + idxT),:]))
4242 volts2[:(nPoints + idxT),:]))
4281 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
4243 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
4282
4244
4283 vStacked = None
4245 vStacked = None
4284 return voltsCCF
4246 return voltsCCF
4285
4247
4286 def __getNoise(self, power, timeSegment, timeInterval):
4248 def __getNoise(self, power, timeSegment, timeInterval):
4287 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4249 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4288 numBlocks = int(power.shape[0]/numProfPerBlock)
4250 numBlocks = int(power.shape[0]/numProfPerBlock)
4289 numHeights = power.shape[1]
4251 numHeights = power.shape[1]
4290
4252
4291 listPower = numpy.array_split(power, numBlocks, 0)
4253 listPower = numpy.array_split(power, numBlocks, 0)
4292 noise = numpy.zeros((power.shape[0], power.shape[1]))
4254 noise = numpy.zeros((power.shape[0], power.shape[1]))
4293 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
4255 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
4294
4256
4295 startInd = 0
4257 startInd = 0
4296 endInd = 0
4258 endInd = 0
4297
4259
4298 for i in range(numBlocks): #split por canal
4260 for i in range(numBlocks): #split por canal
4299 startInd = endInd
4261 startInd = endInd
4300 endInd = endInd + listPower[i].shape[0]
4262 endInd = endInd + listPower[i].shape[0]
4301
4263
4302 arrayBlock = listPower[i]
4264 arrayBlock = listPower[i]
4303 noiseAux = numpy.mean(arrayBlock, 0)
4265 noiseAux = numpy.mean(arrayBlock, 0)
4304 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
4266 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
4305
4267
4306 noiseAux1 = numpy.mean(arrayBlock)
4268 noiseAux1 = numpy.mean(arrayBlock)
4307 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
4269 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
4308
4270
4309 return noise, noise1
4271 return noise, noise1
4310
4272
4311 def __findMeteors(self, power, thresh):
4273 def __findMeteors(self, power, thresh):
4312 nProf = power.shape[0]
4274 nProf = power.shape[0]
4313 nHeights = power.shape[1]
4275 nHeights = power.shape[1]
4314 listMeteors = []
4276 listMeteors = []
4315
4277
4316 for i in range(nHeights):
4278 for i in range(nHeights):
4317 powerAux = power[:,i]
4279 powerAux = power[:,i]
4318 threshAux = thresh[:,i]
4280 threshAux = thresh[:,i]
4319
4281
4320 indUPthresh = numpy.where(powerAux > threshAux)[0]
4282 indUPthresh = numpy.where(powerAux > threshAux)[0]
4321 indDNthresh = numpy.where(powerAux <= threshAux)[0]
4283 indDNthresh = numpy.where(powerAux <= threshAux)[0]
4322
4284
4323 j = 0
4285 j = 0
4324
4286
4325 while (j < indUPthresh.size - 2):
4287 while (j < indUPthresh.size - 2):
4326 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
4288 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
4327 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
4289 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
4328 indDNthresh = indDNthresh[indDNAux]
4290 indDNthresh = indDNthresh[indDNAux]
4329
4291
4330 if (indDNthresh.size > 0):
4292 if (indDNthresh.size > 0):
4331 indEnd = indDNthresh[0] - 1
4293 indEnd = indDNthresh[0] - 1
4332 indInit = indUPthresh[j]
4294 indInit = indUPthresh[j]
4333
4295
4334 meteor = powerAux[indInit:indEnd + 1]
4296 meteor = powerAux[indInit:indEnd + 1]
4335 indPeak = meteor.argmax() + indInit
4297 indPeak = meteor.argmax() + indInit
4336 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
4298 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
4337
4299
4338 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
4300 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
4339 j = numpy.where(indUPthresh == indEnd)[0] + 1
4301 j = numpy.where(indUPthresh == indEnd)[0] + 1
4340 else: j+=1
4302 else: j+=1
4341 else: j+=1
4303 else: j+=1
4342
4304
4343 return listMeteors
4305 return listMeteors
4344
4306
4345 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
4307 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
4346
4308
4347 arrayMeteors = numpy.asarray(listMeteors)
4309 arrayMeteors = numpy.asarray(listMeteors)
4348 listMeteors1 = []
4310 listMeteors1 = []
4349
4311
4350 while arrayMeteors.shape[0] > 0:
4312 while arrayMeteors.shape[0] > 0:
4351 FLAs = arrayMeteors[:,4]
4313 FLAs = arrayMeteors[:,4]
4352 maxFLA = FLAs.argmax()
4314 maxFLA = FLAs.argmax()
4353 listMeteors1.append(arrayMeteors[maxFLA,:])
4315 listMeteors1.append(arrayMeteors[maxFLA,:])
4354
4316
4355 MeteorInitTime = arrayMeteors[maxFLA,1]
4317 MeteorInitTime = arrayMeteors[maxFLA,1]
4356 MeteorEndTime = arrayMeteors[maxFLA,3]
4318 MeteorEndTime = arrayMeteors[maxFLA,3]
4357 MeteorHeight = arrayMeteors[maxFLA,0]
4319 MeteorHeight = arrayMeteors[maxFLA,0]
4358
4320
4359 #Check neighborhood
4321 #Check neighborhood
4360 maxHeightIndex = MeteorHeight + rangeLimit
4322 maxHeightIndex = MeteorHeight + rangeLimit
4361 minHeightIndex = MeteorHeight - rangeLimit
4323 minHeightIndex = MeteorHeight - rangeLimit
4362 minTimeIndex = MeteorInitTime - timeLimit
4324 minTimeIndex = MeteorInitTime - timeLimit
4363 maxTimeIndex = MeteorEndTime + timeLimit
4325 maxTimeIndex = MeteorEndTime + timeLimit
4364
4326
4365 #Check Heights
4327 #Check Heights
4366 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
4328 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
4367 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
4329 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
4368 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
4330 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
4369
4331
4370 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
4332 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
4371
4333
4372 return listMeteors1
4334 return listMeteors1
4373
4335
4374 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
4336 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
4375 numHeights = volts.shape[2]
4337 numHeights = volts.shape[2]
4376 nChannel = volts.shape[0]
4338 nChannel = volts.shape[0]
4377
4339
4378 thresholdPhase = thresh[0]
4340 thresholdPhase = thresh[0]
4379 thresholdNoise = thresh[1]
4341 thresholdNoise = thresh[1]
4380 thresholdDB = float(thresh[2])
4342 thresholdDB = float(thresh[2])
4381
4343
4382 thresholdDB1 = 10**(thresholdDB/10)
4344 thresholdDB1 = 10**(thresholdDB/10)
4383 pairsarray = numpy.array(pairslist)
4345 pairsarray = numpy.array(pairslist)
4384 indSides = pairsarray[:,1]
4346 indSides = pairsarray[:,1]
4385
4347
4386 pairslist1 = list(pairslist)
4348 pairslist1 = list(pairslist)
4387 pairslist1.append((0,1))
4349 pairslist1.append((0,1))
4388 pairslist1.append((3,4))
4350 pairslist1.append((3,4))
4389
4351
4390 listMeteors1 = []
4352 listMeteors1 = []
4391 listPowerSeries = []
4353 listPowerSeries = []
4392 listVoltageSeries = []
4354 listVoltageSeries = []
4393 #volts has the war data
4355 #volts has the war data
4394
4356
4395 if frequency == 30e6:
4357 if frequency == 30e6:
4396 timeLag = 45*10**-3
4358 timeLag = 45*10**-3
4397 else:
4359 else:
4398 timeLag = 15*10**-3
4360 timeLag = 15*10**-3
4399 lag = numpy.ceil(timeLag/timeInterval)
4361 lag = numpy.ceil(timeLag/timeInterval)
4400
4362
4401 for i in range(len(listMeteors)):
4363 for i in range(len(listMeteors)):
4402
4364
4403 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
4365 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
4404 meteorAux = numpy.zeros(16)
4366 meteorAux = numpy.zeros(16)
4405
4367
4406 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
4368 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
4407 mHeight = listMeteors[i][0]
4369 mHeight = listMeteors[i][0]
4408 mStart = listMeteors[i][1]
4370 mStart = listMeteors[i][1]
4409 mPeak = listMeteors[i][2]
4371 mPeak = listMeteors[i][2]
4410 mEnd = listMeteors[i][3]
4372 mEnd = listMeteors[i][3]
4411
4373
4412 #get the volt data between the start and end times of the meteor
4374 #get the volt data between the start and end times of the meteor
4413 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
4375 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
4414 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4376 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4415
4377
4416 #3.6. Phase Difference estimation
4378 #3.6. Phase Difference estimation
4417 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
4379 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
4418
4380
4419 #3.7. Phase difference removal & meteor start, peak and end times reestimated
4381 #3.7. Phase difference removal & meteor start, peak and end times reestimated
4420 #meteorVolts0.- all Channels, all Profiles
4382 #meteorVolts0.- all Channels, all Profiles
4421 meteorVolts0 = volts[:,:,mHeight]
4383 meteorVolts0 = volts[:,:,mHeight]
4422 meteorThresh = noise[:,mHeight]*thresholdNoise
4384 meteorThresh = noise[:,mHeight]*thresholdNoise
4423 meteorNoise = noise[:,mHeight]
4385 meteorNoise = noise[:,mHeight]
4424 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
4386 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
4425 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
4387 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
4426
4388
4427 #Times reestimation
4389 #Times reestimation
4428 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
4390 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
4429 if mStart1.size > 0:
4391 if mStart1.size > 0:
4430 mStart1 = mStart1[-1] + 1
4392 mStart1 = mStart1[-1] + 1
4431
4393
4432 else:
4394 else:
4433 mStart1 = mPeak
4395 mStart1 = mPeak
4434
4396
4435 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
4397 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
4436 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
4398 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
4437 if mEndDecayTime1.size == 0:
4399 if mEndDecayTime1.size == 0:
4438 mEndDecayTime1 = powerNet0.size
4400 mEndDecayTime1 = powerNet0.size
4439 else:
4401 else:
4440 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
4402 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
4441
4403
4442 #meteorVolts1.- all Channels, from start to end
4404 #meteorVolts1.- all Channels, from start to end
4443 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
4405 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
4444 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
4406 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
4445 if meteorVolts2.shape[1] == 0:
4407 if meteorVolts2.shape[1] == 0:
4446 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
4408 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
4447 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
4409 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
4448 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
4410 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
4449 ##################### END PARAMETERS REESTIMATION #########################
4411 ##################### END PARAMETERS REESTIMATION #########################
4450
4412
4451 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
4413 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
4452 if meteorVolts2.shape[1] > 0:
4414 if meteorVolts2.shape[1] > 0:
4453 #Phase Difference re-estimation
4415 #Phase Difference re-estimation
4454 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
4416 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
4455 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
4417 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
4456 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
4418 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
4457 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
4419 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
4458
4420
4459 #Phase Difference RMS
4421 #Phase Difference RMS
4460 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
4422 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
4461 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
4423 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
4462 #Data from Meteor
4424 #Data from Meteor
4463 mPeak1 = powerNet1.argmax() + mStart1
4425 mPeak1 = powerNet1.argmax() + mStart1
4464 mPeakPower1 = powerNet1.max()
4426 mPeakPower1 = powerNet1.max()
4465 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
4427 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
4466 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
4428 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
4467 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
4429 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
4468 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
4430 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
4469 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
4431 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
4470 #Vectorize
4432 #Vectorize
4471 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
4433 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
4472 meteorAux[7:11] = phaseDiffint[0:4]
4434 meteorAux[7:11] = phaseDiffint[0:4]
4473
4435
4474 #Rejection Criterions
4436 #Rejection Criterions
4475 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
4437 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
4476 meteorAux[-1] = 17
4438 meteorAux[-1] = 17
4477 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
4439 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
4478 meteorAux[-1] = 1
4440 meteorAux[-1] = 1
4479
4441
4480
4442
4481 else:
4443 else:
4482 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
4444 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
4483 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
4445 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
4484 PowerSeries = 0
4446 PowerSeries = 0
4485
4447
4486 listMeteors1.append(meteorAux)
4448 listMeteors1.append(meteorAux)
4487 listPowerSeries.append(PowerSeries)
4449 listPowerSeries.append(PowerSeries)
4488 listVoltageSeries.append(meteorVolts1)
4450 listVoltageSeries.append(meteorVolts1)
4489
4451
4490 return listMeteors1, listPowerSeries, listVoltageSeries
4452 return listMeteors1, listPowerSeries, listVoltageSeries
4491
4453
4492 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
4454 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
4493
4455
4494 threshError = 10
4456 threshError = 10
4495 #Depending if it is 30 or 50 MHz
4457 #Depending if it is 30 or 50 MHz
4496 if frequency == 30e6:
4458 if frequency == 30e6:
4497 timeLag = 45*10**-3
4459 timeLag = 45*10**-3
4498 else:
4460 else:
4499 timeLag = 15*10**-3
4461 timeLag = 15*10**-3
4500 lag = numpy.ceil(timeLag/timeInterval)
4462 lag = numpy.ceil(timeLag/timeInterval)
4501
4463
4502 listMeteors1 = []
4464 listMeteors1 = []
4503
4465
4504 for i in range(len(listMeteors)):
4466 for i in range(len(listMeteors)):
4505 meteorPower = listPower[i]
4467 meteorPower = listPower[i]
4506 meteorAux = listMeteors[i]
4468 meteorAux = listMeteors[i]
4507
4469
4508 if meteorAux[-1] == 0:
4470 if meteorAux[-1] == 0:
4509
4471
4510 try:
4472 try:
4511 indmax = meteorPower.argmax()
4473 indmax = meteorPower.argmax()
4512 indlag = indmax + lag
4474 indlag = indmax + lag
4513
4475
4514 y = meteorPower[indlag:]
4476 y = meteorPower[indlag:]
4515 x = numpy.arange(0, y.size)*timeLag
4477 x = numpy.arange(0, y.size)*timeLag
4516
4478
4517 #first guess
4479 #first guess
4518 a = y[0]
4480 a = y[0]
4519 tau = timeLag
4481 tau = timeLag
4520 #exponential fit
4482 #exponential fit
4521 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
4483 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
4522 y1 = self.__exponential_function(x, *popt)
4484 y1 = self.__exponential_function(x, *popt)
4523 #error estimation
4485 #error estimation
4524 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
4486 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
4525
4487
4526 decayTime = popt[1]
4488 decayTime = popt[1]
4527 riseTime = indmax*timeInterval
4489 riseTime = indmax*timeInterval
4528 meteorAux[11:13] = [decayTime, error]
4490 meteorAux[11:13] = [decayTime, error]
4529
4491
4530 #Table items 7, 8 and 11
4492 #Table items 7, 8 and 11
4531 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
4493 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
4532 meteorAux[-1] = 7
4494 meteorAux[-1] = 7
4533 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
4495 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
4534 meteorAux[-1] = 8
4496 meteorAux[-1] = 8
4535 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
4497 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
4536 meteorAux[-1] = 11
4498 meteorAux[-1] = 11
4537
4499
4538
4500
4539 except:
4501 except:
4540 meteorAux[-1] = 11
4502 meteorAux[-1] = 11
4541
4503
4542
4504
4543 listMeteors1.append(meteorAux)
4505 listMeteors1.append(meteorAux)
4544
4506
4545 return listMeteors1
4507 return listMeteors1
4546
4508
4547 #Exponential Function
4509 #Exponential Function
4548
4510
4549 def __exponential_function(self, x, a, tau):
4511 def __exponential_function(self, x, a, tau):
4550 y = a*numpy.exp(-x/tau)
4512 y = a*numpy.exp(-x/tau)
4551 return y
4513 return y
4552
4514
4553 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
4515 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
4554
4516
4555 pairslist1 = list(pairslist)
4517 pairslist1 = list(pairslist)
4556 pairslist1.append((0,1))
4518 pairslist1.append((0,1))
4557 pairslist1.append((3,4))
4519 pairslist1.append((3,4))
4558 numPairs = len(pairslist1)
4520 numPairs = len(pairslist1)
4559 #Time Lag
4521 #Time Lag
4560 timeLag = 45*10**-3
4522 timeLag = 45*10**-3
4561 c = 3e8
4523 c = 3e8
4562 lag = numpy.ceil(timeLag/timeInterval)
4524 lag = numpy.ceil(timeLag/timeInterval)
4563 freq = 30e6
4525 freq = 30e6
4564
4526
4565 listMeteors1 = []
4527 listMeteors1 = []
4566
4528
4567 for i in range(len(listMeteors)):
4529 for i in range(len(listMeteors)):
4568 meteorAux = listMeteors[i]
4530 meteorAux = listMeteors[i]
4569 if meteorAux[-1] == 0:
4531 if meteorAux[-1] == 0:
4570 mStart = listMeteors[i][1]
4532 mStart = listMeteors[i][1]
4571 mPeak = listMeteors[i][2]
4533 mPeak = listMeteors[i][2]
4572 mLag = mPeak - mStart + lag
4534 mLag = mPeak - mStart + lag
4573
4535
4574 #get the volt data between the start and end times of the meteor
4536 #get the volt data between the start and end times of the meteor
4575 meteorVolts = listVolts[i]
4537 meteorVolts = listVolts[i]
4576 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4538 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4577
4539
4578 #Get CCF
4540 #Get CCF
4579 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
4541 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
4580
4542
4581 #Method 2
4543 #Method 2
4582 slopes = numpy.zeros(numPairs)
4544 slopes = numpy.zeros(numPairs)
4583 time = numpy.array([-2,-1,1,2])*timeInterval
4545 time = numpy.array([-2,-1,1,2])*timeInterval
4584 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
4546 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
4585
4547
4586 #Correct phases
4548 #Correct phases
4587 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
4549 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
4588 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4550 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4589
4551
4590 if indDer[0].shape[0] > 0:
4552 if indDer[0].shape[0] > 0:
4591 for i in range(indDer[0].shape[0]):
4553 for i in range(indDer[0].shape[0]):
4592 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
4554 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
4593 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
4555 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
4594
4556
4595 for j in range(numPairs):
4557 for j in range(numPairs):
4596 fit = stats.linregress(time, angAllCCF[j,:])
4558 fit = stats.linregress(time, angAllCCF[j,:])
4597 slopes[j] = fit[0]
4559 slopes[j] = fit[0]
4598
4560
4599 #Remove Outlier
4561 #Remove Outlier
4600 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
4562 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
4601 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
4563 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
4602 meteorAux[-2] = radialError
4564 meteorAux[-2] = radialError
4603 meteorAux[-3] = radialVelocity
4565 meteorAux[-3] = radialVelocity
4604
4566
4605 #Setting Error
4567 #Setting Error
4606 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
4568 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
4607 if numpy.abs(radialVelocity) > 200:
4569 if numpy.abs(radialVelocity) > 200:
4608 meteorAux[-1] = 15
4570 meteorAux[-1] = 15
4609 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
4571 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
4610 elif radialError > radialStdThresh:
4572 elif radialError > radialStdThresh:
4611 meteorAux[-1] = 12
4573 meteorAux[-1] = 12
4612
4574
4613 listMeteors1.append(meteorAux)
4575 listMeteors1.append(meteorAux)
4614 return listMeteors1
4576 return listMeteors1
4615
4577
4616 def __setNewArrays(self, listMeteors, date, heiRang):
4578 def __setNewArrays(self, listMeteors, date, heiRang):
4617
4579
4618 #New arrays
4580 #New arrays
4619 arrayMeteors = numpy.array(listMeteors)
4581 arrayMeteors = numpy.array(listMeteors)
4620 arrayParameters = numpy.zeros((len(listMeteors), 13))
4582 arrayParameters = numpy.zeros((len(listMeteors), 13))
4621
4583
4622 #Date inclusion
4584 #Date inclusion
4623 arrayDate = numpy.tile(date, (len(listMeteors)))
4585 arrayDate = numpy.tile(date, (len(listMeteors)))
4624
4586
4625 #Meteor array
4587 #Meteor array
4626 #Parameters Array
4588 #Parameters Array
4627 arrayParameters[:,0] = arrayDate #Date
4589 arrayParameters[:,0] = arrayDate #Date
4628 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
4590 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
4629 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
4591 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
4630 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
4592 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
4631 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
4593 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
4632
4594
4633
4595
4634 return arrayParameters
4596 return arrayParameters
4635
4597
4636 class CorrectSMPhases(Operation):
4598 class CorrectSMPhases(Operation):
4637
4599
4638 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
4600 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
4639
4601
4640 arrayParameters = dataOut.data_param
4602 arrayParameters = dataOut.data_param
4641 pairsList = []
4603 pairsList = []
4642 pairx = (0,1)
4604 pairx = (0,1)
4643 pairy = (2,3)
4605 pairy = (2,3)
4644 pairsList.append(pairx)
4606 pairsList.append(pairx)
4645 pairsList.append(pairy)
4607 pairsList.append(pairy)
4646 jph = numpy.zeros(4)
4608 jph = numpy.zeros(4)
4647
4609
4648 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4610 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4649 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4611 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4650 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
4612 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
4651
4613
4652 meteorOps = SMOperations()
4614 meteorOps = SMOperations()
4653 if channelPositions is None:
4615 if channelPositions is None:
4654 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4616 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4655 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4617 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4656
4618
4657 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4619 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4658 h = (hmin,hmax)
4620 h = (hmin,hmax)
4659
4621
4660 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4622 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4661
4623
4662 dataOut.data_param = arrayParameters
4624 dataOut.data_param = arrayParameters
4663 return
4625 return
4664
4626
4665 class SMPhaseCalibration(Operation):
4627 class SMPhaseCalibration(Operation):
4666
4628
4667 __buffer = None
4629 __buffer = None
4668
4630
4669 __initime = None
4631 __initime = None
4670
4632
4671 __dataReady = False
4633 __dataReady = False
4672
4634
4673 __isConfig = False
4635 __isConfig = False
4674
4636
4675 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
4637 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
4676
4638
4677 dataTime = currentTime + paramInterval
4639 dataTime = currentTime + paramInterval
4678 deltaTime = dataTime - initTime
4640 deltaTime = dataTime - initTime
4679
4641
4680 if deltaTime >= outputInterval or deltaTime < 0:
4642 if deltaTime >= outputInterval or deltaTime < 0:
4681 return True
4643 return True
4682
4644
4683 return False
4645 return False
4684
4646
4685 def __getGammas(self, pairs, d, phases):
4647 def __getGammas(self, pairs, d, phases):
4686 gammas = numpy.zeros(2)
4648 gammas = numpy.zeros(2)
4687
4649
4688 for i in range(len(pairs)):
4650 for i in range(len(pairs)):
4689
4651
4690 pairi = pairs[i]
4652 pairi = pairs[i]
4691
4653
4692 phip3 = phases[:,pairi[0]]
4654 phip3 = phases[:,pairi[0]]
4693 d3 = d[pairi[0]]
4655 d3 = d[pairi[0]]
4694 phip2 = phases[:,pairi[1]]
4656 phip2 = phases[:,pairi[1]]
4695 d2 = d[pairi[1]]
4657 d2 = d[pairi[1]]
4696 #Calculating gamma
4658 #Calculating gamma
4697 jgamma = -phip2*d3/d2 - phip3
4659 jgamma = -phip2*d3/d2 - phip3
4698 jgamma = numpy.angle(numpy.exp(1j*jgamma))
4660 jgamma = numpy.angle(numpy.exp(1j*jgamma))
4699
4661
4700 #Revised distribution
4662 #Revised distribution
4701 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
4663 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
4702
4664
4703 #Histogram
4665 #Histogram
4704 nBins = 64
4666 nBins = 64
4705 rmin = -0.5*numpy.pi
4667 rmin = -0.5*numpy.pi
4706 rmax = 0.5*numpy.pi
4668 rmax = 0.5*numpy.pi
4707 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
4669 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
4708
4670
4709 meteorsY = phaseHisto[0]
4671 meteorsY = phaseHisto[0]
4710 phasesX = phaseHisto[1][:-1]
4672 phasesX = phaseHisto[1][:-1]
4711 width = phasesX[1] - phasesX[0]
4673 width = phasesX[1] - phasesX[0]
4712 phasesX += width/2
4674 phasesX += width/2
4713
4675
4714 #Gaussian aproximation
4676 #Gaussian aproximation
4715 bpeak = meteorsY.argmax()
4677 bpeak = meteorsY.argmax()
4716 peak = meteorsY.max()
4678 peak = meteorsY.max()
4717 jmin = bpeak - 5
4679 jmin = bpeak - 5
4718 jmax = bpeak + 5 + 1
4680 jmax = bpeak + 5 + 1
4719
4681
4720 if jmin<0:
4682 if jmin<0:
4721 jmin = 0
4683 jmin = 0
4722 jmax = 6
4684 jmax = 6
4723 elif jmax > meteorsY.size:
4685 elif jmax > meteorsY.size:
4724 jmin = meteorsY.size - 6
4686 jmin = meteorsY.size - 6
4725 jmax = meteorsY.size
4687 jmax = meteorsY.size
4726
4688
4727 x0 = numpy.array([peak,bpeak,50])
4689 x0 = numpy.array([peak,bpeak,50])
4728 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
4690 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
4729
4691
4730 #Gammas
4692 #Gammas
4731 gammas[i] = coeff[0][1]
4693 gammas[i] = coeff[0][1]
4732
4694
4733 return gammas
4695 return gammas
4734
4696
4735 def __residualFunction(self, coeffs, y, t):
4697 def __residualFunction(self, coeffs, y, t):
4736
4698
4737 return y - self.__gauss_function(t, coeffs)
4699 return y - self.__gauss_function(t, coeffs)
4738
4700
4739 def __gauss_function(self, t, coeffs):
4701 def __gauss_function(self, t, coeffs):
4740
4702
4741 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
4703 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
4742
4704
4743 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
4705 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
4744 meteorOps = SMOperations()
4706 meteorOps = SMOperations()
4745 nchan = 4
4707 nchan = 4
4746 pairx = pairsList[0] #x es 0
4708 pairx = pairsList[0] #x es 0
4747 pairy = pairsList[1] #y es 1
4709 pairy = pairsList[1] #y es 1
4748 center_xangle = 0
4710 center_xangle = 0
4749 center_yangle = 0
4711 center_yangle = 0
4750 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
4712 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
4751 ntimes = len(range_angle)
4713 ntimes = len(range_angle)
4752
4714
4753 nstepsx = 20
4715 nstepsx = 20
4754 nstepsy = 20
4716 nstepsy = 20
4755
4717
4756 for iz in range(ntimes):
4718 for iz in range(ntimes):
4757 min_xangle = -range_angle[iz]/2 + center_xangle
4719 min_xangle = -range_angle[iz]/2 + center_xangle
4758 max_xangle = range_angle[iz]/2 + center_xangle
4720 max_xangle = range_angle[iz]/2 + center_xangle
4759 min_yangle = -range_angle[iz]/2 + center_yangle
4721 min_yangle = -range_angle[iz]/2 + center_yangle
4760 max_yangle = range_angle[iz]/2 + center_yangle
4722 max_yangle = range_angle[iz]/2 + center_yangle
4761
4723
4762 inc_x = (max_xangle-min_xangle)/nstepsx
4724 inc_x = (max_xangle-min_xangle)/nstepsx
4763 inc_y = (max_yangle-min_yangle)/nstepsy
4725 inc_y = (max_yangle-min_yangle)/nstepsy
4764
4726
4765 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
4727 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
4766 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
4728 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
4767 penalty = numpy.zeros((nstepsx,nstepsy))
4729 penalty = numpy.zeros((nstepsx,nstepsy))
4768 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
4730 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
4769 jph = numpy.zeros(nchan)
4731 jph = numpy.zeros(nchan)
4770
4732
4771 # Iterations looking for the offset
4733 # Iterations looking for the offset
4772 for iy in range(int(nstepsy)):
4734 for iy in range(int(nstepsy)):
4773 for ix in range(int(nstepsx)):
4735 for ix in range(int(nstepsx)):
4774 d3 = d[pairsList[1][0]]
4736 d3 = d[pairsList[1][0]]
4775 d2 = d[pairsList[1][1]]
4737 d2 = d[pairsList[1][1]]
4776 d5 = d[pairsList[0][0]]
4738 d5 = d[pairsList[0][0]]
4777 d4 = d[pairsList[0][1]]
4739 d4 = d[pairsList[0][1]]
4778
4740
4779 alp2 = alpha_y[iy] #gamma 1
4741 alp2 = alpha_y[iy] #gamma 1
4780 alp4 = alpha_x[ix] #gamma 0
4742 alp4 = alpha_x[ix] #gamma 0
4781
4743
4782 alp3 = -alp2*d3/d2 - gammas[1]
4744 alp3 = -alp2*d3/d2 - gammas[1]
4783 alp5 = -alp4*d5/d4 - gammas[0]
4745 alp5 = -alp4*d5/d4 - gammas[0]
4784 jph[pairsList[0][1]] = alp4
4746 jph[pairsList[0][1]] = alp4
4785 jph[pairsList[0][0]] = alp5
4747 jph[pairsList[0][0]] = alp5
4786 jph[pairsList[1][0]] = alp3
4748 jph[pairsList[1][0]] = alp3
4787 jph[pairsList[1][1]] = alp2
4749 jph[pairsList[1][1]] = alp2
4788 jph_array[:,ix,iy] = jph
4750 jph_array[:,ix,iy] = jph
4789 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
4751 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
4790 error = meteorsArray1[:,-1]
4752 error = meteorsArray1[:,-1]
4791 ind1 = numpy.where(error==0)[0]
4753 ind1 = numpy.where(error==0)[0]
4792 penalty[ix,iy] = ind1.size
4754 penalty[ix,iy] = ind1.size
4793
4755
4794 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
4756 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
4795 phOffset = jph_array[:,i,j]
4757 phOffset = jph_array[:,i,j]
4796
4758
4797 center_xangle = phOffset[pairx[1]]
4759 center_xangle = phOffset[pairx[1]]
4798 center_yangle = phOffset[pairy[1]]
4760 center_yangle = phOffset[pairy[1]]
4799
4761
4800 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
4762 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
4801 phOffset = phOffset*180/numpy.pi
4763 phOffset = phOffset*180/numpy.pi
4802 return phOffset
4764 return phOffset
4803
4765
4804
4766
4805 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
4767 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
4806
4768
4807 dataOut.flagNoData = True
4769 dataOut.flagNoData = True
4808 self.__dataReady = False
4770 self.__dataReady = False
4809 dataOut.outputInterval = nHours*3600
4771 dataOut.outputInterval = nHours*3600
4810
4772
4811 if self.__isConfig == False:
4773 if self.__isConfig == False:
4812 #Get Initial LTC time
4774 #Get Initial LTC time
4813 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4775 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4814 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4776 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4815
4777
4816 self.__isConfig = True
4778 self.__isConfig = True
4817
4779
4818 if self.__buffer is None:
4780 if self.__buffer is None:
4819 self.__buffer = dataOut.data_param.copy()
4781 self.__buffer = dataOut.data_param.copy()
4820
4782
4821 else:
4783 else:
4822 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4784 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4823
4785
4824 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4786 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4825
4787
4826 if self.__dataReady:
4788 if self.__dataReady:
4827 dataOut.utctimeInit = self.__initime
4789 dataOut.utctimeInit = self.__initime
4828 self.__initime += dataOut.outputInterval #to erase time offset
4790 self.__initime += dataOut.outputInterval #to erase time offset
4829
4791
4830 freq = dataOut.frequency
4792 freq = dataOut.frequency
4831 c = dataOut.C #m/s
4793 c = dataOut.C #m/s
4832 lamb = c/freq
4794 lamb = c/freq
4833 k = 2*numpy.pi/lamb
4795 k = 2*numpy.pi/lamb
4834 azimuth = 0
4796 azimuth = 0
4835 h = (hmin, hmax)
4797 h = (hmin, hmax)
4836
4798
4837 if channelPositions is None:
4799 if channelPositions is None:
4838 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4800 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4839 meteorOps = SMOperations()
4801 meteorOps = SMOperations()
4840 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4802 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4841
4803
4842 #Checking correct order of pairs
4804 #Checking correct order of pairs
4843 pairs = []
4805 pairs = []
4844 if distances[1] > distances[0]:
4806 if distances[1] > distances[0]:
4845 pairs.append((1,0))
4807 pairs.append((1,0))
4846 else:
4808 else:
4847 pairs.append((0,1))
4809 pairs.append((0,1))
4848
4810
4849 if distances[3] > distances[2]:
4811 if distances[3] > distances[2]:
4850 pairs.append((3,2))
4812 pairs.append((3,2))
4851 else:
4813 else:
4852 pairs.append((2,3))
4814 pairs.append((2,3))
4853
4815
4854 meteorsArray = self.__buffer
4816 meteorsArray = self.__buffer
4855 error = meteorsArray[:,-1]
4817 error = meteorsArray[:,-1]
4856 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
4818 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
4857 ind1 = numpy.where(boolError)[0]
4819 ind1 = numpy.where(boolError)[0]
4858 meteorsArray = meteorsArray[ind1,:]
4820 meteorsArray = meteorsArray[ind1,:]
4859 meteorsArray[:,-1] = 0
4821 meteorsArray[:,-1] = 0
4860 phases = meteorsArray[:,8:12]
4822 phases = meteorsArray[:,8:12]
4861
4823
4862 #Calculate Gammas
4824 #Calculate Gammas
4863 gammas = self.__getGammas(pairs, distances, phases)
4825 gammas = self.__getGammas(pairs, distances, phases)
4864 #Calculate Phases
4826 #Calculate Phases
4865 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
4827 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
4866 phasesOff = phasesOff.reshape((1,phasesOff.size))
4828 phasesOff = phasesOff.reshape((1,phasesOff.size))
4867 dataOut.data_output = -phasesOff
4829 dataOut.data_output = -phasesOff
4868 dataOut.flagNoData = False
4830 dataOut.flagNoData = False
4869 self.__buffer = None
4831 self.__buffer = None
4870
4832
4871
4833
4872 return
4834 return
4873
4835
4874 class SMOperations():
4836 class SMOperations():
4875
4837
4876 def __init__(self):
4838 def __init__(self):
4877
4839
4878 return
4840 return
4879
4841
4880 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
4842 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
4881
4843
4882 arrayParameters = arrayParameters0.copy()
4844 arrayParameters = arrayParameters0.copy()
4883 hmin = h[0]
4845 hmin = h[0]
4884 hmax = h[1]
4846 hmax = h[1]
4885
4847
4886 #Calculate AOA (Error N 3, 4)
4848 #Calculate AOA (Error N 3, 4)
4887 #JONES ET AL. 1998
4849 #JONES ET AL. 1998
4888 AOAthresh = numpy.pi/8
4850 AOAthresh = numpy.pi/8
4889 error = arrayParameters[:,-1]
4851 error = arrayParameters[:,-1]
4890 phases = -arrayParameters[:,8:12] + jph
4852 phases = -arrayParameters[:,8:12] + jph
4891 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
4853 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
4892
4854
4893 #Calculate Heights (Error N 13 and 14)
4855 #Calculate Heights (Error N 13 and 14)
4894 error = arrayParameters[:,-1]
4856 error = arrayParameters[:,-1]
4895 Ranges = arrayParameters[:,1]
4857 Ranges = arrayParameters[:,1]
4896 zenith = arrayParameters[:,4]
4858 zenith = arrayParameters[:,4]
4897 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
4859 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
4898
4860
4899 #----------------------- Get Final data ------------------------------------
4861 #----------------------- Get Final data ------------------------------------
4900
4862
4901 return arrayParameters
4863 return arrayParameters
4902
4864
4903 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
4865 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
4904
4866
4905 arrayAOA = numpy.zeros((phases.shape[0],3))
4867 arrayAOA = numpy.zeros((phases.shape[0],3))
4906 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
4868 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
4907
4869
4908 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
4870 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
4909 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
4871 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
4910 arrayAOA[:,2] = cosDirError
4872 arrayAOA[:,2] = cosDirError
4911
4873
4912 azimuthAngle = arrayAOA[:,0]
4874 azimuthAngle = arrayAOA[:,0]
4913 zenithAngle = arrayAOA[:,1]
4875 zenithAngle = arrayAOA[:,1]
4914
4876
4915 #Setting Error
4877 #Setting Error
4916 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
4878 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
4917 error[indError] = 0
4879 error[indError] = 0
4918 #Number 3: AOA not fesible
4880 #Number 3: AOA not fesible
4919 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
4881 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
4920 error[indInvalid] = 3
4882 error[indInvalid] = 3
4921 #Number 4: Large difference in AOAs obtained from different antenna baselines
4883 #Number 4: Large difference in AOAs obtained from different antenna baselines
4922 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
4884 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
4923 error[indInvalid] = 4
4885 error[indInvalid] = 4
4924 return arrayAOA, error
4886 return arrayAOA, error
4925
4887
4926 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
4888 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
4927
4889
4928 #Initializing some variables
4890 #Initializing some variables
4929 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
4891 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
4930 ang_aux = ang_aux.reshape(1,ang_aux.size)
4892 ang_aux = ang_aux.reshape(1,ang_aux.size)
4931
4893
4932 cosdir = numpy.zeros((arrayPhase.shape[0],2))
4894 cosdir = numpy.zeros((arrayPhase.shape[0],2))
4933 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
4895 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
4934
4896
4935
4897
4936 for i in range(2):
4898 for i in range(2):
4937 ph0 = arrayPhase[:,pairsList[i][0]]
4899 ph0 = arrayPhase[:,pairsList[i][0]]
4938 ph1 = arrayPhase[:,pairsList[i][1]]
4900 ph1 = arrayPhase[:,pairsList[i][1]]
4939 d0 = distances[pairsList[i][0]]
4901 d0 = distances[pairsList[i][0]]
4940 d1 = distances[pairsList[i][1]]
4902 d1 = distances[pairsList[i][1]]
4941
4903
4942 ph0_aux = ph0 + ph1
4904 ph0_aux = ph0 + ph1
4943 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
4905 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
4944 #First Estimation
4906 #First Estimation
4945 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
4907 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
4946
4908
4947 #Most-Accurate Second Estimation
4909 #Most-Accurate Second Estimation
4948 phi1_aux = ph0 - ph1
4910 phi1_aux = ph0 - ph1
4949 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
4911 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
4950 #Direction Cosine 1
4912 #Direction Cosine 1
4951 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
4913 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
4952
4914
4953 #Searching the correct Direction Cosine
4915 #Searching the correct Direction Cosine
4954 cosdir0_aux = cosdir0[:,i]
4916 cosdir0_aux = cosdir0[:,i]
4955 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
4917 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
4956 #Minimum Distance
4918 #Minimum Distance
4957 cosDiff = (cosdir1 - cosdir0_aux)**2
4919 cosDiff = (cosdir1 - cosdir0_aux)**2
4958 indcos = cosDiff.argmin(axis = 1)
4920 indcos = cosDiff.argmin(axis = 1)
4959 #Saving Value obtained
4921 #Saving Value obtained
4960 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
4922 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
4961
4923
4962 return cosdir0, cosdir
4924 return cosdir0, cosdir
4963
4925
4964 def __calculateAOA(self, cosdir, azimuth):
4926 def __calculateAOA(self, cosdir, azimuth):
4965 cosdirX = cosdir[:,0]
4927 cosdirX = cosdir[:,0]
4966 cosdirY = cosdir[:,1]
4928 cosdirY = cosdir[:,1]
4967
4929
4968 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
4930 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
4969 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
4931 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
4970 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
4932 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
4971
4933
4972 return angles
4934 return angles
4973
4935
4974 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
4936 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
4975
4937
4976 Ramb = 375 #Ramb = c/(2*PRF)
4938 Ramb = 375 #Ramb = c/(2*PRF)
4977 Re = 6371 #Earth Radius
4939 Re = 6371 #Earth Radius
4978 heights = numpy.zeros(Ranges.shape)
4940 heights = numpy.zeros(Ranges.shape)
4979
4941
4980 R_aux = numpy.array([0,1,2])*Ramb
4942 R_aux = numpy.array([0,1,2])*Ramb
4981 R_aux = R_aux.reshape(1,R_aux.size)
4943 R_aux = R_aux.reshape(1,R_aux.size)
4982
4944
4983 Ranges = Ranges.reshape(Ranges.size,1)
4945 Ranges = Ranges.reshape(Ranges.size,1)
4984
4946
4985 Ri = Ranges + R_aux
4947 Ri = Ranges + R_aux
4986 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
4948 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
4987
4949
4988 #Check if there is a height between 70 and 110 km
4950 #Check if there is a height between 70 and 110 km
4989 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
4951 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
4990 ind_h = numpy.where(h_bool == 1)[0]
4952 ind_h = numpy.where(h_bool == 1)[0]
4991
4953
4992 hCorr = hi[ind_h, :]
4954 hCorr = hi[ind_h, :]
4993 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
4955 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
4994
4956
4995 hCorr = hi[ind_hCorr][:len(ind_h)]
4957 hCorr = hi[ind_hCorr][:len(ind_h)]
4996 heights[ind_h] = hCorr
4958 heights[ind_h] = hCorr
4997
4959
4998 #Setting Error
4960 #Setting Error
4999 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
4961 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5000 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
4962 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5001 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
4963 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5002 error[indError] = 0
4964 error[indError] = 0
5003 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
4965 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5004 error[indInvalid2] = 14
4966 error[indInvalid2] = 14
5005 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
4967 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5006 error[indInvalid1] = 13
4968 error[indInvalid1] = 13
5007
4969
5008 return heights, error
4970 return heights, error
5009
4971
5010 def getPhasePairs(self, channelPositions):
4972 def getPhasePairs(self, channelPositions):
5011 chanPos = numpy.array(channelPositions)
4973 chanPos = numpy.array(channelPositions)
5012 listOper = list(itertools.combinations(list(range(5)),2))
4974 listOper = list(itertools.combinations(list(range(5)),2))
5013
4975
5014 distances = numpy.zeros(4)
4976 distances = numpy.zeros(4)
5015 axisX = []
4977 axisX = []
5016 axisY = []
4978 axisY = []
5017 distX = numpy.zeros(3)
4979 distX = numpy.zeros(3)
5018 distY = numpy.zeros(3)
4980 distY = numpy.zeros(3)
5019 ix = 0
4981 ix = 0
5020 iy = 0
4982 iy = 0
5021
4983
5022 pairX = numpy.zeros((2,2))
4984 pairX = numpy.zeros((2,2))
5023 pairY = numpy.zeros((2,2))
4985 pairY = numpy.zeros((2,2))
5024
4986
5025 for i in range(len(listOper)):
4987 for i in range(len(listOper)):
5026 pairi = listOper[i]
4988 pairi = listOper[i]
5027
4989
5028 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
4990 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
5029
4991
5030 if posDif[0] == 0:
4992 if posDif[0] == 0:
5031 axisY.append(pairi)
4993 axisY.append(pairi)
5032 distY[iy] = posDif[1]
4994 distY[iy] = posDif[1]
5033 iy += 1
4995 iy += 1
5034 elif posDif[1] == 0:
4996 elif posDif[1] == 0:
5035 axisX.append(pairi)
4997 axisX.append(pairi)
5036 distX[ix] = posDif[0]
4998 distX[ix] = posDif[0]
5037 ix += 1
4999 ix += 1
5038
5000
5039 for i in range(2):
5001 for i in range(2):
5040 if i==0:
5002 if i==0:
5041 dist0 = distX
5003 dist0 = distX
5042 axis0 = axisX
5004 axis0 = axisX
5043 else:
5005 else:
5044 dist0 = distY
5006 dist0 = distY
5045 axis0 = axisY
5007 axis0 = axisY
5046
5008
5047 side = numpy.argsort(dist0)[:-1]
5009 side = numpy.argsort(dist0)[:-1]
5048 axis0 = numpy.array(axis0)[side,:]
5010 axis0 = numpy.array(axis0)[side,:]
5049 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
5011 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
5050 axis1 = numpy.unique(numpy.reshape(axis0,4))
5012 axis1 = numpy.unique(numpy.reshape(axis0,4))
5051 side = axis1[axis1 != chanC]
5013 side = axis1[axis1 != chanC]
5052 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
5014 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
5053 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
5015 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
5054 if diff1<0:
5016 if diff1<0:
5055 chan2 = side[0]
5017 chan2 = side[0]
5056 d2 = numpy.abs(diff1)
5018 d2 = numpy.abs(diff1)
5057 chan1 = side[1]
5019 chan1 = side[1]
5058 d1 = numpy.abs(diff2)
5020 d1 = numpy.abs(diff2)
5059 else:
5021 else:
5060 chan2 = side[1]
5022 chan2 = side[1]
5061 d2 = numpy.abs(diff2)
5023 d2 = numpy.abs(diff2)
5062 chan1 = side[0]
5024 chan1 = side[0]
5063 d1 = numpy.abs(diff1)
5025 d1 = numpy.abs(diff1)
5064
5026
5065 if i==0:
5027 if i==0:
5066 chanCX = chanC
5028 chanCX = chanC
5067 chan1X = chan1
5029 chan1X = chan1
5068 chan2X = chan2
5030 chan2X = chan2
5069 distances[0:2] = numpy.array([d1,d2])
5031 distances[0:2] = numpy.array([d1,d2])
5070 else:
5032 else:
5071 chanCY = chanC
5033 chanCY = chanC
5072 chan1Y = chan1
5034 chan1Y = chan1
5073 chan2Y = chan2
5035 chan2Y = chan2
5074 distances[2:4] = numpy.array([d1,d2])
5036 distances[2:4] = numpy.array([d1,d2])
5075 # axisXsides = numpy.reshape(axisX[ix,:],4)
5037 # axisXsides = numpy.reshape(axisX[ix,:],4)
5076 #
5038 #
5077 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
5039 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
5078 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
5040 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
5079 #
5041 #
5080 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
5042 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
5081 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
5043 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
5082 # channel25X = int(pairX[0,ind25X])
5044 # channel25X = int(pairX[0,ind25X])
5083 # channel20X = int(pairX[1,ind20X])
5045 # channel20X = int(pairX[1,ind20X])
5084 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
5046 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
5085 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
5047 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
5086 # channel25Y = int(pairY[0,ind25Y])
5048 # channel25Y = int(pairY[0,ind25Y])
5087 # channel20Y = int(pairY[1,ind20Y])
5049 # channel20Y = int(pairY[1,ind20Y])
5088
5050
5089 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
5051 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
5090 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
5052 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
5091
5053
5092 return pairslist, distances
5054 return pairslist, distances
5093 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
5055 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
5094 #
5056 #
5095 # arrayAOA = numpy.zeros((phases.shape[0],3))
5057 # arrayAOA = numpy.zeros((phases.shape[0],3))
5096 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
5058 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
5097 #
5059 #
5098 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5060 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5099 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5061 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5100 # arrayAOA[:,2] = cosDirError
5062 # arrayAOA[:,2] = cosDirError
5101 #
5063 #
5102 # azimuthAngle = arrayAOA[:,0]
5064 # azimuthAngle = arrayAOA[:,0]
5103 # zenithAngle = arrayAOA[:,1]
5065 # zenithAngle = arrayAOA[:,1]
5104 #
5066 #
5105 # #Setting Error
5067 # #Setting Error
5106 # #Number 3: AOA not fesible
5068 # #Number 3: AOA not fesible
5107 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5069 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5108 # error[indInvalid] = 3
5070 # error[indInvalid] = 3
5109 # #Number 4: Large difference in AOAs obtained from different antenna baselines
5071 # #Number 4: Large difference in AOAs obtained from different antenna baselines
5110 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5072 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5111 # error[indInvalid] = 4
5073 # error[indInvalid] = 4
5112 # return arrayAOA, error
5074 # return arrayAOA, error
5113 #
5075 #
5114 # def __getDirectionCosines(self, arrayPhase, pairsList):
5076 # def __getDirectionCosines(self, arrayPhase, pairsList):
5115 #
5077 #
5116 # #Initializing some variables
5078 # #Initializing some variables
5117 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5079 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5118 # ang_aux = ang_aux.reshape(1,ang_aux.size)
5080 # ang_aux = ang_aux.reshape(1,ang_aux.size)
5119 #
5081 #
5120 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
5082 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
5121 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5083 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5122 #
5084 #
5123 #
5085 #
5124 # for i in range(2):
5086 # for i in range(2):
5125 # #First Estimation
5087 # #First Estimation
5126 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
5088 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
5127 # #Dealias
5089 # #Dealias
5128 # indcsi = numpy.where(phi0_aux > numpy.pi)
5090 # indcsi = numpy.where(phi0_aux > numpy.pi)
5129 # phi0_aux[indcsi] -= 2*numpy.pi
5091 # phi0_aux[indcsi] -= 2*numpy.pi
5130 # indcsi = numpy.where(phi0_aux < -numpy.pi)
5092 # indcsi = numpy.where(phi0_aux < -numpy.pi)
5131 # phi0_aux[indcsi] += 2*numpy.pi
5093 # phi0_aux[indcsi] += 2*numpy.pi
5132 # #Direction Cosine 0
5094 # #Direction Cosine 0
5133 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
5095 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
5134 #
5096 #
5135 # #Most-Accurate Second Estimation
5097 # #Most-Accurate Second Estimation
5136 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
5098 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
5137 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5099 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5138 # #Direction Cosine 1
5100 # #Direction Cosine 1
5139 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
5101 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
5140 #
5102 #
5141 # #Searching the correct Direction Cosine
5103 # #Searching the correct Direction Cosine
5142 # cosdir0_aux = cosdir0[:,i]
5104 # cosdir0_aux = cosdir0[:,i]
5143 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5105 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5144 # #Minimum Distance
5106 # #Minimum Distance
5145 # cosDiff = (cosdir1 - cosdir0_aux)**2
5107 # cosDiff = (cosdir1 - cosdir0_aux)**2
5146 # indcos = cosDiff.argmin(axis = 1)
5108 # indcos = cosDiff.argmin(axis = 1)
5147 # #Saving Value obtained
5109 # #Saving Value obtained
5148 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5110 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5149 #
5111 #
5150 # return cosdir0, cosdir
5112 # return cosdir0, cosdir
5151 #
5113 #
5152 # def __calculateAOA(self, cosdir, azimuth):
5114 # def __calculateAOA(self, cosdir, azimuth):
5153 # cosdirX = cosdir[:,0]
5115 # cosdirX = cosdir[:,0]
5154 # cosdirY = cosdir[:,1]
5116 # cosdirY = cosdir[:,1]
5155 #
5117 #
5156 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5118 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5157 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
5119 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
5158 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5120 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5159 #
5121 #
5160 # return angles
5122 # return angles
5161 #
5123 #
5162 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5124 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5163 #
5125 #
5164 # Ramb = 375 #Ramb = c/(2*PRF)
5126 # Ramb = 375 #Ramb = c/(2*PRF)
5165 # Re = 6371 #Earth Radius
5127 # Re = 6371 #Earth Radius
5166 # heights = numpy.zeros(Ranges.shape)
5128 # heights = numpy.zeros(Ranges.shape)
5167 #
5129 #
5168 # R_aux = numpy.array([0,1,2])*Ramb
5130 # R_aux = numpy.array([0,1,2])*Ramb
5169 # R_aux = R_aux.reshape(1,R_aux.size)
5131 # R_aux = R_aux.reshape(1,R_aux.size)
5170 #
5132 #
5171 # Ranges = Ranges.reshape(Ranges.size,1)
5133 # Ranges = Ranges.reshape(Ranges.size,1)
5172 #
5134 #
5173 # Ri = Ranges + R_aux
5135 # Ri = Ranges + R_aux
5174 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5136 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5175 #
5137 #
5176 # #Check if there is a height between 70 and 110 km
5138 # #Check if there is a height between 70 and 110 km
5177 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5139 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5178 # ind_h = numpy.where(h_bool == 1)[0]
5140 # ind_h = numpy.where(h_bool == 1)[0]
5179 #
5141 #
5180 # hCorr = hi[ind_h, :]
5142 # hCorr = hi[ind_h, :]
5181 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5143 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5182 #
5144 #
5183 # hCorr = hi[ind_hCorr]
5145 # hCorr = hi[ind_hCorr]
5184 # heights[ind_h] = hCorr
5146 # heights[ind_h] = hCorr
5185 #
5147 #
5186 # #Setting Error
5148 # #Setting Error
5187 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5149 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5188 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5150 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5189 #
5151 #
5190 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5152 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5191 # error[indInvalid2] = 14
5153 # error[indInvalid2] = 14
5192 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5154 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5193 # error[indInvalid1] = 13
5155 # error[indInvalid1] = 13
5194 #
5156 #
5195 # return heights, error
5157 # return heights, error
5196
5158
5197 class IGRFModel(Operation):
5159 class IGRFModel(Operation):
5198 """Operation to calculate Geomagnetic parameters.
5160 """Operation to calculate Geomagnetic parameters.
5199
5161
5200 Parameters:
5162 Parameters:
5201 -----------
5163 -----------
5202 None
5164 None
5203
5165
5204 Example
5166 Example
5205 --------
5167 --------
5206
5168
5207 op = proc_unit.addOperation(name='IGRFModel', optype='other')
5169 op = proc_unit.addOperation(name='IGRFModel', optype='other')
5208
5170
5209 """
5171 """
5210
5172
5211 def __init__(self, **kwargs):
5173 def __init__(self, **kwargs):
5212
5174
5213 Operation.__init__(self, **kwargs)
5175 Operation.__init__(self, **kwargs)
5214
5176
5215 self.aux=1
5177 self.aux=1
5216
5178
5217 def run(self,dataOut):
5179 def run(self,dataOut):
5218
5180
5219 try:
5181 try:
5220 from schainpy.model.proc import mkfact_short_2020
5182 from schainpy.model.proc import mkfact_short_2020
5221 except:
5183 except:
5222 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
5184 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
5223
5185
5224 if self.aux==1:
5186 if self.aux==1:
5225
5187
5226 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
5188 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
5227 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
5189 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
5228 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
5190 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
5229 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
5191 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
5230 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
5192 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
5231 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
5193 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
5232
5194
5233 self.aux=0
5195 self.aux=0
5234
5196
5235 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
5197 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
5236 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5198 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5237 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
5199 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
5238 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5200 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5239 dataOut.thb=numpy.array(dataOut.thb,order='F')
5201 dataOut.thb=numpy.array(dataOut.thb,order='F')
5240 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5202 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5241 dataOut.bki=numpy.array(dataOut.bki,order='F')
5203 dataOut.bki=numpy.array(dataOut.bki,order='F')
5242
5204
5243 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
5205 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
5244
5206
5245 return dataOut
5207 return dataOut
5208
5209 class MergeProc(ProcessingUnit):
5210
5211 def __init__(self):
5212 ProcessingUnit.__init__(self)
5213
5214 def run(self, attr_data, attr_data_2 = None, attr_data_3 = None, attr_data_4 = None, attr_data_5 = None, mode=0):
5215
5216 self.dataOut = getattr(self, self.inputs[0])
5217 data_inputs = [getattr(self, attr) for attr in self.inputs]
5218 #print(self.inputs)
5219 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
5220 #exit(1)
5221 if mode==0:
5222 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
5223 setattr(self.dataOut, attr_data, data)
5224
5225 if mode==1: #Hybrid
5226 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
5227 #setattr(self.dataOut, attr_data, data)
5228 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
5229 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
5230 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
5231 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
5232 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
5233 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
5234 '''
5235 print(self.dataOut.dataLag_spc_LP.shape)
5236 print(self.dataOut.dataLag_cspc_LP.shape)
5237 exit(1)
5238 '''
5239
5240 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
5241 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
5242 '''
5243 print("Merge")
5244 print(numpy.shape(self.dataOut.dataLag_spc))
5245 print(numpy.shape(self.dataOut.dataLag_spc_LP))
5246 print(numpy.shape(self.dataOut.dataLag_cspc))
5247 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
5248 exit(1)
5249 '''
5250 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
5251 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
5252 #exit(1)
5253 #print(self.dataOut.NDP)
5254 #print(self.dataOut.nNoiseProfiles)
5255
5256 #self.dataOut.nIncohInt_LP = 128
5257 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
5258 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
5259 self.dataOut.NLAG = 16
5260 self.dataOut.NRANGE = 200
5261 self.dataOut.NSCAN = 128
5262 #print(numpy.shape(self.dataOut.data_spc))
5263
5264 #exit(1)
5265
5266 if mode==2: #HAE 2022
5267 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
5268 setattr(self.dataOut, attr_data, data)
5269
5270 self.dataOut.nIncohInt *= 2
5271 #meta = self.dataOut.getFreqRange(1)/1000.
5272 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
5273
5274 #exit(1)
5275
5276 if mode==4: #Hybrid LP-SSheightProfiles
5277 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
5278 #setattr(self.dataOut, attr_data, data)
5279 setattr(self.dataOut, 'dataLag_spc', getattr(data_inputs[0], attr_data)) #DP
5280 setattr(self.dataOut, 'dataLag_cspc', getattr(data_inputs[0], attr_data_2)) #DP
5281 setattr(self.dataOut, 'dataLag_spc_LP', getattr(data_inputs[1], attr_data_3)) #LP
5282 #setattr(self.dataOut, 'dataLag_cspc_LP', getattr(data_inputs[1], attr_data_4)) #LP
5283 #setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
5284 setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
5285 #print("Merge data_acf: ",self.dataOut.data_acf.shape)
5286 #exit(1)
5287 #print(self.dataOut.data_spc_LP.shape)
5288 #print("Exit")
5289 #exit(1)
5290 #setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
5291 #setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
5292 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
5293 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
5294 '''
5295 print(self.dataOut.dataLag_spc_LP.shape)
5296 print(self.dataOut.dataLag_cspc_LP.shape)
5297 exit(1)
5298 '''
5299 '''
5300 print(self.dataOut.dataLag_spc_LP[0,:,100])
5301 print(self.dataOut.dataLag_spc_LP[1,:,100])
5302 exit(1)
5303 '''
5304 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
5305 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
5306 '''
5307 print("Merge")
5308 print(numpy.shape(self.dataOut.dataLag_spc))
5309 print(numpy.shape(self.dataOut.dataLag_spc_LP))
5310 print(numpy.shape(self.dataOut.dataLag_cspc))
5311 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
5312 exit(1)
5313 '''
5314 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
5315 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
5316 #exit(1)
5317 #print(self.dataOut.NDP)
5318 #print(self.dataOut.nNoiseProfiles)
5319
5320 #self.dataOut.nIncohInt_LP = 128
5321 #self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
5322 self.dataOut.nProfiles_LP = 16#28#self.dataOut.nIncohInt_LP
5323 self.dataOut.nProfiles_LP = self.dataOut.data_acf.shape[1]#28#self.dataOut.nIncohInt_LP
5324 self.dataOut.NSCAN = 128
5325 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt*self.dataOut.NSCAN
5326 #print("sahpi",self.dataOut.nIncohInt_LP)
5327 #exit(1)
5328 self.dataOut.NLAG = 16
5329 self.dataOut.NRANGE = self.dataOut.data_acf.shape[-1]
5330
5331 #print(numpy.shape(self.dataOut.data_spc))
5332
5333 #exit(1)
5334 if mode==5:
5335 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
5336 setattr(self.dataOut, attr_data, data)
5337 data = numpy.concatenate([getattr(data, attr_data_2) for data in data_inputs])
5338 setattr(self.dataOut, attr_data_2, data)
5339 #data = numpy.concatenate([getattr(data, attr_data_3) for data in data_inputs])
5340 #setattr(self.dataOut, attr_data_3, data)
5341 #print(self.dataOut.moments.shape,self.dataOut.data_snr.shape,self.dataOut.heightList.shape) No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now