##// END OF EJS Templates
comentario e identacion
Alexander Valdez -
r1705:9e4b98696352
parent child
Show More
@@ -1,6252 +1,6239
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
15
16 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
17 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
18 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
19 from schainpy.model.data.jrodata import Spectra
19 from schainpy.model.data.jrodata import Spectra
20 from scipy import asarray as ar,exp
20 from scipy import asarray as ar,exp
21 from scipy.optimize import fmin, curve_fit
21 from scipy.optimize import fmin, curve_fit
22 from schainpy.utils import log
22 from schainpy.utils import log
23 import warnings
23 import warnings
24 from numpy import NaN
24 from numpy import NaN
25 from scipy.optimize.optimize import OptimizeWarning
25 from scipy.optimize.optimize import OptimizeWarning
26 warnings.filterwarnings('ignore')
26 warnings.filterwarnings('ignore')
27
27
28
28
29 SPEED_OF_LIGHT = 299792458
29 SPEED_OF_LIGHT = 299792458
30
30
31 '''solving pickling issue'''
31 '''solving pickling issue'''
32
32
33 def _pickle_method(method):
33 def _pickle_method(method):
34 func_name = method.__func__.__name__
34 func_name = method.__func__.__name__
35 obj = method.__self__
35 obj = method.__self__
36 cls = method.__self__.__class__
36 cls = method.__self__.__class__
37 return _unpickle_method, (func_name, obj, cls)
37 return _unpickle_method, (func_name, obj, cls)
38
38
39 def _unpickle_method(func_name, obj, cls):
39 def _unpickle_method(func_name, obj, cls):
40 for cls in cls.mro():
40 for cls in cls.mro():
41 try:
41 try:
42 func = cls.__dict__[func_name]
42 func = cls.__dict__[func_name]
43 except KeyError:
43 except KeyError:
44 pass
44 pass
45 else:
45 else:
46 break
46 break
47 return func.__get__(obj, cls)
47 return func.__get__(obj, cls)
48
48
49
49
50 class ParametersProc(ProcessingUnit):
50 class ParametersProc(ProcessingUnit):
51
51
52 METHODS = {}
52 METHODS = {}
53 nSeconds = None
53 nSeconds = None
54
54
55 def __init__(self):
55 def __init__(self):
56 ProcessingUnit.__init__(self)
56 ProcessingUnit.__init__(self)
57
57
58 self.buffer = None
58 self.buffer = None
59 self.firstdatatime = None
59 self.firstdatatime = None
60 self.profIndex = 0
60 self.profIndex = 0
61 self.dataOut = Parameters()
61 self.dataOut = Parameters()
62 self.setupReq = False #Agregar a todas las unidades de proc
62 self.setupReq = False #Agregar a todas las unidades de proc
63
63
64 def __updateObjFromInput(self):
64 def __updateObjFromInput(self):
65
65
66 self.dataOut.inputUnit = self.dataIn.type
66 self.dataOut.inputUnit = self.dataIn.type
67
67
68 self.dataOut.timeZone = self.dataIn.timeZone
68 self.dataOut.timeZone = self.dataIn.timeZone
69 self.dataOut.dstFlag = self.dataIn.dstFlag
69 self.dataOut.dstFlag = self.dataIn.dstFlag
70 self.dataOut.errorCount = self.dataIn.errorCount
70 self.dataOut.errorCount = self.dataIn.errorCount
71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
72
72
73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
75 self.dataOut.channelList = self.dataIn.channelList
75 self.dataOut.channelList = self.dataIn.channelList
76 self.dataOut.heightList = self.dataIn.heightList
76 self.dataOut.heightList = self.dataIn.heightList
77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
78 # self.dataOut.nBaud = self.dataIn.nBaud
78 # self.dataOut.nBaud = self.dataIn.nBaud
79 # self.dataOut.nCode = self.dataIn.nCode
79 # self.dataOut.nCode = self.dataIn.nCode
80 # self.dataOut.code = self.dataIn.code
80 # self.dataOut.code = self.dataIn.code
81 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
81 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
82 self.dataOut.utctime = self.dataIn.utctime
82 self.dataOut.utctime = self.dataIn.utctime
83 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
83 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
84 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
84 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
85 self.dataOut.nCohInt = self.dataIn.nCohInt
85 self.dataOut.nCohInt = self.dataIn.nCohInt
86 self.dataOut.timeInterval1 = self.dataIn.timeInterval
86 self.dataOut.timeInterval1 = self.dataIn.timeInterval
87 self.dataOut.heightList = self.dataIn.heightList
87 self.dataOut.heightList = self.dataIn.heightList
88 self.dataOut.frequency = self.dataIn.frequency
88 self.dataOut.frequency = self.dataIn.frequency
89 self.dataOut.runNextUnit = self.dataIn.runNextUnit
89 self.dataOut.runNextUnit = self.dataIn.runNextUnit
90
90
91 def run(self, runNextUnit=0):
91 def run(self, runNextUnit=0):
92
92
93 self.dataIn.runNextUnit = runNextUnit
93 self.dataIn.runNextUnit = runNextUnit
94 #---------------------- Voltage Data ---------------------------
94 #---------------------- Voltage Data ---------------------------
95
95
96 if self.dataIn.type == "Voltage":
96 if self.dataIn.type == "Voltage":
97
97
98 self.__updateObjFromInput()
98 self.__updateObjFromInput()
99 self.dataOut.data_pre = self.dataIn.data.copy()
99 self.dataOut.data_pre = self.dataIn.data.copy()
100 self.dataOut.flagNoData = False
100 self.dataOut.flagNoData = False
101 self.dataOut.utctimeInit = self.dataIn.utctime
101 self.dataOut.utctimeInit = self.dataIn.utctime
102 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
102 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
103 if hasattr(self.dataIn, 'dataPP_POW'):
103 if hasattr(self.dataIn, 'dataPP_POW'):
104 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
104 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
105
105
106 if hasattr(self.dataIn, 'dataPP_POWER'):
106 if hasattr(self.dataIn, 'dataPP_POWER'):
107 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
107 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
108
108
109 if hasattr(self.dataIn, 'dataPP_DOP'):
109 if hasattr(self.dataIn, 'dataPP_DOP'):
110 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
110 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
111
111
112 if hasattr(self.dataIn, 'dataPP_SNR'):
112 if hasattr(self.dataIn, 'dataPP_SNR'):
113 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
113 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
114
114
115 if hasattr(self.dataIn, 'dataPP_WIDTH'):
115 if hasattr(self.dataIn, 'dataPP_WIDTH'):
116 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
116 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
117 return
117 return
118
118
119 #---------------------- Spectra Data ---------------------------
119 #---------------------- Spectra Data ---------------------------
120
120
121 if self.dataIn.type == "Spectra":
121 if self.dataIn.type == "Spectra":
122
122
123 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
123 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
124 self.dataOut.data_spc = self.dataIn.data_spc
124 self.dataOut.data_spc = self.dataIn.data_spc
125 self.dataOut.data_cspc = self.dataIn.data_cspc
125 self.dataOut.data_cspc = self.dataIn.data_cspc
126 self.dataOut.nProfiles = self.dataIn.nProfiles
126 self.dataOut.nProfiles = self.dataIn.nProfiles
127 self.dataOut.nIncohInt = self.dataIn.nIncohInt
127 self.dataOut.nIncohInt = self.dataIn.nIncohInt
128 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
128 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
129 self.dataOut.ippFactor = self.dataIn.ippFactor
129 self.dataOut.ippFactor = self.dataIn.ippFactor
130 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
130 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
131 self.dataOut.spc_noise = self.dataIn.getNoise()
131 self.dataOut.spc_noise = self.dataIn.getNoise()
132 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
132 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
133 # self.dataOut.normFactor = self.dataIn.normFactor
133 # self.dataOut.normFactor = self.dataIn.normFactor
134 self.dataOut.pairsList = self.dataIn.pairsList
134 self.dataOut.pairsList = self.dataIn.pairsList
135 self.dataOut.groupList = self.dataIn.pairsList
135 self.dataOut.groupList = self.dataIn.pairsList
136 self.dataOut.flagNoData = False
136 self.dataOut.flagNoData = False
137
137
138 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
138 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
139 self.dataOut.ChanDist = self.dataIn.ChanDist
139 self.dataOut.ChanDist = self.dataIn.ChanDist
140 else: self.dataOut.ChanDist = None
140 else: self.dataOut.ChanDist = None
141
141
142 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
142 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
143 # self.dataOut.VelRange = self.dataIn.VelRange
143 # self.dataOut.VelRange = self.dataIn.VelRange
144 #else: self.dataOut.VelRange = None
144 #else: self.dataOut.VelRange = None
145
145
146 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
146 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
147 self.dataOut.RadarConst = self.dataIn.RadarConst
147 self.dataOut.RadarConst = self.dataIn.RadarConst
148
148
149 if hasattr(self.dataIn, 'NPW'): #NPW
149 if hasattr(self.dataIn, 'NPW'): #NPW
150 self.dataOut.NPW = self.dataIn.NPW
150 self.dataOut.NPW = self.dataIn.NPW
151
151
152 if hasattr(self.dataIn, 'COFA'): #COFA
152 if hasattr(self.dataIn, 'COFA'): #COFA
153 self.dataOut.COFA = self.dataIn.COFA
153 self.dataOut.COFA = self.dataIn.COFA
154
154
155
155
156
156
157 #---------------------- Correlation Data ---------------------------
157 #---------------------- Correlation Data ---------------------------
158
158
159 if self.dataIn.type == "Correlation":
159 if self.dataIn.type == "Correlation":
160 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
160 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
161
161
162 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
162 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
163 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
163 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
164 self.dataOut.groupList = (acf_pairs, ccf_pairs)
164 self.dataOut.groupList = (acf_pairs, ccf_pairs)
165
165
166 self.dataOut.abscissaList = self.dataIn.lagRange
166 self.dataOut.abscissaList = self.dataIn.lagRange
167 self.dataOut.noise = self.dataIn.noise
167 self.dataOut.noise = self.dataIn.noise
168 self.dataOut.data_snr = self.dataIn.SNR
168 self.dataOut.data_snr = self.dataIn.SNR
169 self.dataOut.flagNoData = False
169 self.dataOut.flagNoData = False
170 self.dataOut.nAvg = self.dataIn.nAvg
170 self.dataOut.nAvg = self.dataIn.nAvg
171
171
172 #---------------------- Parameters Data ---------------------------
172 #---------------------- Parameters Data ---------------------------
173
173
174 if self.dataIn.type == "Parameters":
174 if self.dataIn.type == "Parameters":
175 self.dataOut.copy(self.dataIn)
175 self.dataOut.copy(self.dataIn)
176 self.dataOut.flagNoData = False
176 self.dataOut.flagNoData = False
177
177
178 return True
178 return True
179
179
180 self.__updateObjFromInput()
180 self.__updateObjFromInput()
181 self.dataOut.utctimeInit = self.dataIn.utctime
181 self.dataOut.utctimeInit = self.dataIn.utctime
182 self.dataOut.paramInterval = self.dataIn.timeInterval
182 self.dataOut.paramInterval = self.dataIn.timeInterval
183
183
184 return
184 return
185
185
186
186
187 def target(tups):
187 def target(tups):
188
188
189 obj, args = tups
189 obj, args = tups
190
190
191 return obj.FitGau(args)
191 return obj.FitGau(args)
192
192
193 class RemoveWideGC(Operation):
193 class RemoveWideGC(Operation):
194 ''' This class remove the wide clutter and replace it with a simple interpolation points
194 ''' This class remove the wide clutter and replace it with a simple interpolation points
195 This mainly applies to CLAIRE radar
195 This mainly applies to CLAIRE radar
196
196
197 ClutterWidth : Width to look for the clutter peak
197 ClutterWidth : Width to look for the clutter peak
198
198
199 Input:
199 Input:
200
200
201 self.dataOut.data_pre : SPC and CSPC
201 self.dataOut.data_pre : SPC and CSPC
202 self.dataOut.spc_range : To select wind and rainfall velocities
202 self.dataOut.spc_range : To select wind and rainfall velocities
203
203
204 Affected:
204 Affected:
205
205
206 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
206 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
207
207
208 Written by D. ScipiΓ³n 25.02.2021
208 Written by D. ScipiΓ³n 25.02.2021
209 '''
209 '''
210 def __init__(self):
210 def __init__(self):
211 Operation.__init__(self)
211 Operation.__init__(self)
212 self.i = 0
212 self.i = 0
213 self.ich = 0
213 self.ich = 0
214 self.ir = 0
214 self.ir = 0
215
215
216 def run(self, dataOut, ClutterWidth=2.5):
216 def run(self, dataOut, ClutterWidth=2.5):
217
217
218 self.spc = dataOut.data_pre[0].copy()
218 self.spc = dataOut.data_pre[0].copy()
219 self.spc_out = dataOut.data_pre[0].copy()
219 self.spc_out = dataOut.data_pre[0].copy()
220 self.Num_Chn = self.spc.shape[0]
220 self.Num_Chn = self.spc.shape[0]
221 self.Num_Hei = self.spc.shape[2]
221 self.Num_Hei = self.spc.shape[2]
222 VelRange = dataOut.spc_range[2][:-1]
222 VelRange = dataOut.spc_range[2][:-1]
223 dv = VelRange[1]-VelRange[0]
223 dv = VelRange[1]-VelRange[0]
224
224
225 # Find the velocities that corresponds to zero
225 # Find the velocities that corresponds to zero
226 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
226 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
227
227
228 # Removing novalid data from the spectra
228 # Removing novalid data from the spectra
229 for ich in range(self.Num_Chn) :
229 for ich in range(self.Num_Chn) :
230 for ir in range(self.Num_Hei) :
230 for ir in range(self.Num_Hei) :
231 # Estimate the noise at each range
231 # Estimate the noise at each range
232 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
232 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
233
233
234 # Removing the noise floor at each range
234 # Removing the noise floor at each range
235 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
235 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
236 self.spc[ich,novalid,ir] = HSn
236 self.spc[ich,novalid,ir] = HSn
237
237
238 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
238 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
239 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
239 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
240 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
240 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
241 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
241 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
242 continue
242 continue
243 junk3 = numpy.squeeze(numpy.diff(j1index))
243 junk3 = numpy.squeeze(numpy.diff(j1index))
244 junk4 = numpy.squeeze(numpy.diff(j2index))
244 junk4 = numpy.squeeze(numpy.diff(j2index))
245
245
246 valleyindex = j2index[numpy.where(junk4>1)]
246 valleyindex = j2index[numpy.where(junk4>1)]
247 peakindex = j1index[numpy.where(junk3>1)]
247 peakindex = j1index[numpy.where(junk3>1)]
248
248
249 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
249 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
250 if numpy.size(isvalid) == 0 :
250 if numpy.size(isvalid) == 0 :
251 continue
251 continue
252 if numpy.size(isvalid) >1 :
252 if numpy.size(isvalid) >1 :
253 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
253 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
254 isvalid = isvalid[vindex]
254 isvalid = isvalid[vindex]
255
255
256 # clutter peak
256 # clutter peak
257 gcpeak = peakindex[isvalid]
257 gcpeak = peakindex[isvalid]
258 vl = numpy.where(valleyindex < gcpeak)
258 vl = numpy.where(valleyindex < gcpeak)
259 if numpy.size(vl) == 0:
259 if numpy.size(vl) == 0:
260 continue
260 continue
261 gcvl = valleyindex[vl[0][-1]]
261 gcvl = valleyindex[vl[0][-1]]
262 vr = numpy.where(valleyindex > gcpeak)
262 vr = numpy.where(valleyindex > gcpeak)
263 if numpy.size(vr) == 0:
263 if numpy.size(vr) == 0:
264 continue
264 continue
265 gcvr = valleyindex[vr[0][0]]
265 gcvr = valleyindex[vr[0][0]]
266
266
267 # Removing the clutter
267 # Removing the clutter
268 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
268 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
269 gcindex = gc_values[gcvl+1:gcvr-1]
269 gcindex = gc_values[gcvl+1:gcvr-1]
270 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
270 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
271
271
272 dataOut.data_pre[0] = self.spc_out
272 dataOut.data_pre[0] = self.spc_out
273
273
274 return dataOut
274 return dataOut
275
275
276 class SpectralFilters(Operation):
276 class SpectralFilters(Operation):
277 ''' This class allows to replace the novalid values with noise for each channel
277 ''' This class allows to replace the novalid values with noise for each channel
278 This applies to CLAIRE RADAR
278 This applies to CLAIRE RADAR
279
279
280 PositiveLimit : RightLimit of novalid data
280 PositiveLimit : RightLimit of novalid data
281 NegativeLimit : LeftLimit of novalid data
281 NegativeLimit : LeftLimit of novalid data
282
282
283 Input:
283 Input:
284
284
285 self.dataOut.data_pre : SPC and CSPC
285 self.dataOut.data_pre : SPC and CSPC
286 self.dataOut.spc_range : To select wind and rainfall velocities
286 self.dataOut.spc_range : To select wind and rainfall velocities
287
287
288 Affected:
288 Affected:
289
289
290 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
290 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
291
291
292 Written by D. ScipiΓ³n 29.01.2021
292 Written by D. ScipiΓ³n 29.01.2021
293 '''
293 '''
294 def __init__(self):
294 def __init__(self):
295 Operation.__init__(self)
295 Operation.__init__(self)
296 self.i = 0
296 self.i = 0
297
297
298 def run(self, dataOut, ):
298 def run(self, dataOut, ):
299
299
300 self.spc = dataOut.data_pre[0].copy()
300 self.spc = dataOut.data_pre[0].copy()
301 self.Num_Chn = self.spc.shape[0]
301 self.Num_Chn = self.spc.shape[0]
302 VelRange = dataOut.spc_range[2]
302 VelRange = dataOut.spc_range[2]
303
303
304 # novalid corresponds to data within the Negative and PositiveLimit
304 # novalid corresponds to data within the Negative and PositiveLimit
305
305
306
306
307 # Removing novalid data from the spectra
307 # Removing novalid data from the spectra
308 for i in range(self.Num_Chn):
308 for i in range(self.Num_Chn):
309 self.spc[i,novalid,:] = dataOut.noise[i]
309 self.spc[i,novalid,:] = dataOut.noise[i]
310 dataOut.data_pre[0] = self.spc
310 dataOut.data_pre[0] = self.spc
311 return dataOut
311 return dataOut
312
312
313
313
314 class GaussianFit(Operation):
314 class GaussianFit(Operation):
315
315
316 '''
316 '''
317 Function that fit of one and two generalized gaussians (gg) based
317 Function that fit of one and two generalized gaussians (gg) based
318 on the PSD shape across an "power band" identified from a cumsum of
318 on the PSD shape across an "power band" identified from a cumsum of
319 the measured spectrum - noise.
319 the measured spectrum - noise.
320
320
321 Input:
321 Input:
322 self.dataOut.data_pre : SelfSpectra
322 self.dataOut.data_pre : SelfSpectra
323
323
324 Output:
324 Output:
325 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
325 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
326
326
327 '''
327 '''
328 def __init__(self):
328 def __init__(self):
329 Operation.__init__(self)
329 Operation.__init__(self)
330 self.i=0
330 self.i=0
331
331
332 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
332 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
333 """This routine will find a couple of generalized Gaussians to a power spectrum
333 """This routine will find a couple of generalized Gaussians to a power spectrum
334 methods: generalized, squared
334 methods: generalized, squared
335 input: spc
335 input: spc
336 output:
336 output:
337 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
337 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
338 """
338 """
339 print ('Entering ',method,' double Gaussian fit')
339 print ('Entering ',method,' double Gaussian fit')
340 self.spc = dataOut.data_pre[0].copy()
340 self.spc = dataOut.data_pre[0].copy()
341 self.Num_Hei = self.spc.shape[2]
341 self.Num_Hei = self.spc.shape[2]
342 self.Num_Bin = self.spc.shape[1]
342 self.Num_Bin = self.spc.shape[1]
343 self.Num_Chn = self.spc.shape[0]
343 self.Num_Chn = self.spc.shape[0]
344
344
345 start_time = time.time()
345 start_time = time.time()
346
346
347 pool = Pool(processes=self.Num_Chn)
347 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)]
348 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)]
349 objs = [self for __ in range(self.Num_Chn)]
350 attrs = list(zip(objs, args))
350 attrs = list(zip(objs, args))
351 DGauFitParam = pool.map(target, attrs)
351 DGauFitParam = pool.map(target, attrs)
352 # Parameters:
352 # Parameters:
353 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
353 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
354 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
354 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
355
355
356 # Double Gaussian Curves
356 # Double Gaussian Curves
357 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
357 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
358 gau0[:] = numpy.NaN
358 gau0[:] = numpy.NaN
359 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
359 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
360 gau1[:] = numpy.NaN
360 gau1[:] = numpy.NaN
361 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
361 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
362 for iCh in range(self.Num_Chn):
362 for iCh in range(self.Num_Chn):
363 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
363 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))
364 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))
365 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))
366 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))
367 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))
368 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))
369 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))
370 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
371 if method == 'generalized':
371 if method == 'generalized':
372 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
372 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))
373 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
374 elif method == 'squared':
374 elif method == 'squared':
375 p0 = 2.
375 p0 = 2.
376 p1 = 2.
376 p1 = 2.
377 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
377 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
378 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
379 dataOut.GaussFit0 = gau0
379 dataOut.GaussFit0 = gau0
380 dataOut.GaussFit1 = gau1
380 dataOut.GaussFit1 = gau1
381
381
382 print('Leaving ',method ,' double Gaussian fit')
382 print('Leaving ',method ,' double Gaussian fit')
383 return dataOut
383 return dataOut
384
384
385 def FitGau(self, X):
385 def FitGau(self, X):
386 # print('Entering FitGau')
386 # print('Entering FitGau')
387 # Assigning the variables
387 # Assigning the variables
388 Vrange, ch, wnoise, num_intg, SNRlimit = X
388 Vrange, ch, wnoise, num_intg, SNRlimit = X
389 # Noise Limits
389 # Noise Limits
390 noisebl = wnoise * 0.9
390 noisebl = wnoise * 0.9
391 noisebh = wnoise * 1.1
391 noisebh = wnoise * 1.1
392 # Radar Velocity
392 # Radar Velocity
393 Va = max(Vrange)
393 Va = max(Vrange)
394 deltav = Vrange[1] - Vrange[0]
394 deltav = Vrange[1] - Vrange[0]
395 x = numpy.arange(self.Num_Bin)
395 x = numpy.arange(self.Num_Bin)
396
396
397 # print ('stop 0')
397 # print ('stop 0')
398
398
399 # 5 parameters, 2 Gaussians
399 # 5 parameters, 2 Gaussians
400 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
400 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
401 DGauFitParam[:] = numpy.NaN
401 DGauFitParam[:] = numpy.NaN
402
402
403 # SPCparam = []
403 # SPCparam = []
404 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
404 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
405 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
405 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
406 # SPC_ch1[:] = 0 #numpy.NaN
406 # SPC_ch1[:] = 0 #numpy.NaN
407 # SPC_ch2[:] = 0 #numpy.NaN
407 # SPC_ch2[:] = 0 #numpy.NaN
408 # print ('stop 1')
408 # print ('stop 1')
409 for ht in range(self.Num_Hei):
409 for ht in range(self.Num_Hei):
410 # print (ht)
410 # print (ht)
411 # print ('stop 2')
411 # print ('stop 2')
412 # Spectra at each range
412 # Spectra at each range
413 spc = numpy.asarray(self.spc)[ch,:,ht]
413 spc = numpy.asarray(self.spc)[ch,:,ht]
414 snr = ( spc.mean() - wnoise ) / wnoise
414 snr = ( spc.mean() - wnoise ) / wnoise
415 snrdB = 10.*numpy.log10(snr)
415 snrdB = 10.*numpy.log10(snr)
416
416
417 #print ('stop 3')
417 #print ('stop 3')
418 if snrdB < SNRlimit :
418 if snrdB < SNRlimit :
419 # snr = numpy.NaN
419 # snr = numpy.NaN
420 # SPC_ch1[:,ht] = 0#numpy.NaN
420 # SPC_ch1[:,ht] = 0#numpy.NaN
421 # SPC_ch1[:,ht] = 0#numpy.NaN
421 # SPC_ch1[:,ht] = 0#numpy.NaN
422 # SPCparam = (SPC_ch1,SPC_ch2)
422 # SPCparam = (SPC_ch1,SPC_ch2)
423 # print ('SNR less than SNRth')
423 # print ('SNR less than SNRth')
424 continue
424 continue
425 # wnoise = hildebrand_sekhon(spc,num_intg)
425 # wnoise = hildebrand_sekhon(spc,num_intg)
426 # print ('stop 2.01')
426 # print ('stop 2.01')
427 #############################################
427 #############################################
428 # normalizing spc and noise
428 # normalizing spc and noise
429 # This part differs from gg1
429 # This part differs from gg1
430 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
430 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
431 #spc = spc / spc_norm_max
431 #spc = spc / spc_norm_max
432 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
432 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
433 #############################################
433 #############################################
434
434
435 # print ('stop 2.1')
435 # print ('stop 2.1')
436 fatspectra=1.0
436 fatspectra=1.0
437 # noise per channel.... we might want to use the noise at each range
437 # noise per channel.... we might want to use the noise at each range
438
438
439 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
439 # 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
440 #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
441 #if wnoise>1.1*pnoise: # to be tested later
442 # wnoise=pnoise
442 # wnoise=pnoise
443 # noisebl = wnoise*0.9
443 # noisebl = wnoise*0.9
444 # noisebh = wnoise*1.1
444 # noisebh = wnoise*1.1
445 spc = spc - wnoise # signal
445 spc = spc - wnoise # signal
446
446
447 # print ('stop 2.2')
447 # print ('stop 2.2')
448 minx = numpy.argmin(spc)
448 minx = numpy.argmin(spc)
449 #spcs=spc.copy()
449 #spcs=spc.copy()
450 spcs = numpy.roll(spc,-minx)
450 spcs = numpy.roll(spc,-minx)
451 cum = numpy.cumsum(spcs)
451 cum = numpy.cumsum(spcs)
452 # tot_noise = wnoise * self.Num_Bin #64;
452 # tot_noise = wnoise * self.Num_Bin #64;
453
453
454 # print ('stop 2.3')
454 # print ('stop 2.3')
455 # snr = sum(spcs) / tot_noise
455 # snr = sum(spcs) / tot_noise
456 # snrdB = 10.*numpy.log10(snr)
456 # snrdB = 10.*numpy.log10(snr)
457 #print ('stop 3')
457 #print ('stop 3')
458 # if snrdB < SNRlimit :
458 # if snrdB < SNRlimit :
459 # snr = numpy.NaN
459 # snr = numpy.NaN
460 # SPC_ch1[:,ht] = 0#numpy.NaN
460 # SPC_ch1[:,ht] = 0#numpy.NaN
461 # SPC_ch1[:,ht] = 0#numpy.NaN
461 # SPC_ch1[:,ht] = 0#numpy.NaN
462 # SPCparam = (SPC_ch1,SPC_ch2)
462 # SPCparam = (SPC_ch1,SPC_ch2)
463 # print ('SNR less than SNRth')
463 # print ('SNR less than SNRth')
464 # continue
464 # continue
465
465
466
466
467 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
467 #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
468 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
469 # print ('stop 4')
469 # print ('stop 4')
470 cummax = max(cum)
470 cummax = max(cum)
471 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
471 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
472 cumlo = cummax * epsi
472 cumlo = cummax * epsi
473 cumhi = cummax * (1-epsi)
473 cumhi = cummax * (1-epsi)
474 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
474 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
475
475
476 # print ('stop 5')
476 # print ('stop 5')
477 if len(powerindex) < 1:# case for powerindex 0
477 if len(powerindex) < 1:# case for powerindex 0
478 # print ('powerindex < 1')
478 # print ('powerindex < 1')
479 continue
479 continue
480 powerlo = powerindex[0]
480 powerlo = powerindex[0]
481 powerhi = powerindex[-1]
481 powerhi = powerindex[-1]
482 powerwidth = powerhi-powerlo
482 powerwidth = powerhi-powerlo
483 if powerwidth <= 1:
483 if powerwidth <= 1:
484 # print('powerwidth <= 1')
484 # print('powerwidth <= 1')
485 continue
485 continue
486
486
487 # print ('stop 6')
487 # print ('stop 6')
488 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
488 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
489 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
489 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
490 midpeak = (firstpeak + secondpeak)/2.
490 midpeak = (firstpeak + secondpeak)/2.
491 firstamp = spcs[int(firstpeak)]
491 firstamp = spcs[int(firstpeak)]
492 secondamp = spcs[int(secondpeak)]
492 secondamp = spcs[int(secondpeak)]
493 midamp = spcs[int(midpeak)]
493 midamp = spcs[int(midpeak)]
494
494
495 y_data = spc + wnoise
495 y_data = spc + wnoise
496
496
497 ''' single Gaussian '''
497 ''' single Gaussian '''
498 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
498 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
499 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
499 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
500 power0 = 2.
500 power0 = 2.
501 amplitude0 = midamp
501 amplitude0 = midamp
502 state0 = [shift0,width0,amplitude0,power0,wnoise]
502 state0 = [shift0,width0,amplitude0,power0,wnoise]
503 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
503 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)
504 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
505 # print ('stop 7.1')
505 # print ('stop 7.1')
506 # print (bnds)
506 # print (bnds)
507
507
508 chiSq1=lsq1[1]
508 chiSq1=lsq1[1]
509
509
510 # print ('stop 8')
510 # print ('stop 8')
511 if fatspectra<1.0 and powerwidth<4:
511 if fatspectra<1.0 and powerwidth<4:
512 choice=0
512 choice=0
513 Amplitude0=lsq1[0][2]
513 Amplitude0=lsq1[0][2]
514 shift0=lsq1[0][0]
514 shift0=lsq1[0][0]
515 width0=lsq1[0][1]
515 width0=lsq1[0][1]
516 p0=lsq1[0][3]
516 p0=lsq1[0][3]
517 Amplitude1=0.
517 Amplitude1=0.
518 shift1=0.
518 shift1=0.
519 width1=0.
519 width1=0.
520 p1=0.
520 p1=0.
521 noise=lsq1[0][4]
521 noise=lsq1[0][4]
522 #return (numpy.array([shift0,width0,Amplitude0,p0]),
522 #return (numpy.array([shift0,width0,Amplitude0,p0]),
523 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
523 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
524 # print ('stop 9')
524 # print ('stop 9')
525 ''' two Gaussians '''
525 ''' two Gaussians '''
526 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
526 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
527 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
527 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
528 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
528 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
529 width0 = powerwidth/6.
529 width0 = powerwidth/6.
530 width1 = width0
530 width1 = width0
531 power0 = 2.
531 power0 = 2.
532 power1 = power0
532 power1 = power0
533 amplitude0 = firstamp
533 amplitude0 = firstamp
534 amplitude1 = secondamp
534 amplitude1 = secondamp
535 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
535 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))
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,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))
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.),(0.1,0.5))
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
539
540 # print ('stop 10')
540 # print ('stop 10')
541 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
541 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
542
542
543 # print ('stop 11')
543 # print ('stop 11')
544 chiSq2 = lsq2[1]
544 chiSq2 = lsq2[1]
545
545
546 # print ('stop 12')
546 # print ('stop 12')
547
547
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)
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
549
550 # print ('stop 13')
550 # print ('stop 13')
551 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
551 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
552 if oneG:
552 if oneG:
553 choice = 0
553 choice = 0
554 else:
554 else:
555 w1 = lsq2[0][1]; w2 = lsq2[0][5]
555 w1 = lsq2[0][1]; w2 = lsq2[0][5]
556 a1 = lsq2[0][2]; a2 = lsq2[0][6]
556 a1 = lsq2[0][2]; a2 = lsq2[0][6]
557 p1 = lsq2[0][3]; p2 = lsq2[0][7]
557 p1 = lsq2[0][3]; p2 = lsq2[0][7]
558 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
558 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
559 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
559 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
560 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
561
561
562 if gp1>gp2:
562 if gp1>gp2:
563 if a1>0.7*a2:
563 if a1>0.7*a2:
564 choice = 1
564 choice = 1
565 else:
565 else:
566 choice = 2
566 choice = 2
567 elif gp2>gp1:
567 elif gp2>gp1:
568 if a2>0.7*a1:
568 if a2>0.7*a1:
569 choice = 2
569 choice = 2
570 else:
570 else:
571 choice = 1
571 choice = 1
572 else:
572 else:
573 choice = numpy.argmax([a1,a2])+1
573 choice = numpy.argmax([a1,a2])+1
574 #else:
574 #else:
575 #choice=argmin([std2a,std2b])+1
575 #choice=argmin([std2a,std2b])+1
576
576
577 else: # with low SNR go to the most energetic peak
577 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]])
578 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
579
579
580 # print ('stop 14')
580 # print ('stop 14')
581 shift0 = lsq2[0][0]
581 shift0 = lsq2[0][0]
582 vel0 = Vrange[0] + shift0 * deltav
582 vel0 = Vrange[0] + shift0 * deltav
583 shift1 = lsq2[0][4]
583 shift1 = lsq2[0][4]
584 # vel1=Vrange[0] + shift1 * deltav
584 # vel1=Vrange[0] + shift1 * deltav
585
585
586 # max_vel = 1.0
586 # max_vel = 1.0
587 # Va = max(Vrange)
587 # Va = max(Vrange)
588 # deltav = Vrange[1]-Vrange[0]
588 # deltav = Vrange[1]-Vrange[0]
589 # print ('stop 15')
589 # print ('stop 15')
590 #first peak will be 0, second peak will be 1
590 #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
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 > -Va and vel0 < Va : #first peak is in the correct range
592 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
593 shift0 = lsq2[0][0]
593 shift0 = lsq2[0][0]
594 width0 = lsq2[0][1]
594 width0 = lsq2[0][1]
595 Amplitude0 = lsq2[0][2]
595 Amplitude0 = lsq2[0][2]
596 p0 = lsq2[0][3]
596 p0 = lsq2[0][3]
597
597
598 shift1 = lsq2[0][4]
598 shift1 = lsq2[0][4]
599 width1 = lsq2[0][5]
599 width1 = lsq2[0][5]
600 Amplitude1 = lsq2[0][6]
600 Amplitude1 = lsq2[0][6]
601 p1 = lsq2[0][7]
601 p1 = lsq2[0][7]
602 noise = lsq2[0][8]
602 noise = lsq2[0][8]
603 else:
603 else:
604 shift1 = lsq2[0][0]
604 shift1 = lsq2[0][0]
605 width1 = lsq2[0][1]
605 width1 = lsq2[0][1]
606 Amplitude1 = lsq2[0][2]
606 Amplitude1 = lsq2[0][2]
607 p1 = lsq2[0][3]
607 p1 = lsq2[0][3]
608
608
609 shift0 = lsq2[0][4]
609 shift0 = lsq2[0][4]
610 width0 = lsq2[0][5]
610 width0 = lsq2[0][5]
611 Amplitude0 = lsq2[0][6]
611 Amplitude0 = lsq2[0][6]
612 p0 = lsq2[0][7]
612 p0 = lsq2[0][7]
613 noise = lsq2[0][8]
613 noise = lsq2[0][8]
614
614
615 if Amplitude0<0.05: # in case the peak is noise
615 if Amplitude0<0.05: # in case the peak is noise
616 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
616 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
617 if Amplitude1<0.05:
617 if Amplitude1<0.05:
618 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
618 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
619
619
620 # print ('stop 16 ')
620 # print ('stop 16 ')
621 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
621 # 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)
622 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
623 # SPCparam = (SPC_ch1,SPC_ch2)
623 # SPCparam = (SPC_ch1,SPC_ch2)
624
624
625 DGauFitParam[0,ht,0] = noise
625 DGauFitParam[0,ht,0] = noise
626 DGauFitParam[0,ht,1] = noise
626 DGauFitParam[0,ht,1] = noise
627 DGauFitParam[1,ht,0] = Amplitude0
627 DGauFitParam[1,ht,0] = Amplitude0
628 DGauFitParam[1,ht,1] = Amplitude1
628 DGauFitParam[1,ht,1] = Amplitude1
629 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
629 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
630 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
630 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
631 DGauFitParam[3,ht,0] = width0 * deltav
631 DGauFitParam[3,ht,0] = width0 * deltav
632 DGauFitParam[3,ht,1] = width1 * deltav
632 DGauFitParam[3,ht,1] = width1 * deltav
633 DGauFitParam[4,ht,0] = p0
633 DGauFitParam[4,ht,0] = p0
634 DGauFitParam[4,ht,1] = p1
634 DGauFitParam[4,ht,1] = p1
635
635
636 return DGauFitParam
636 return DGauFitParam
637
637
638 def y_model1(self,x,state):
638 def y_model1(self,x,state):
639 shift0, width0, amplitude0, power0, noise = state
639 shift0, width0, amplitude0, power0, noise = state
640 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
640 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)
641 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)
642 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
643 return model0 + model0u + model0d + noise
643 return model0 + model0u + model0d + noise
644
644
645 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
645 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
646 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
646 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
647 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
647 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)
648 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)
649 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
650
650
651 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
651 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)
652 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)
653 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
654 return model0 + model0u + model0d + model1 + model1u + model1d + noise
654 return model0 + model0u + model0d + model1 + model1u + model1d + noise
655
655
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.
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
657
658 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
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
659
660 def misfit2(self,state,y_data,x,num_intg):
660 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.)
661 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
662
662
663 class Oblique_Gauss_Fit(Operation):
663 class Oblique_Gauss_Fit(Operation):
664 '''
664 '''
665 Written by R. Flores
665 Written by R. Flores
666 '''
666 '''
667 def __init__(self):
667 def __init__(self):
668 Operation.__init__(self)
668 Operation.__init__(self)
669
669
670 def Gauss_fit(self,spc,x,nGauss):
670 def Gauss_fit(self,spc,x,nGauss):
671
671
672
672
673 def gaussian(x, a, b, c, d):
673 def gaussian(x, a, b, c, d):
674 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
674 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
675 return val
675 return val
676
676
677 if nGauss == 'first':
677 if nGauss == 'first':
678 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
678 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
679 spc_2_aux = numpy.flip(spc_1_aux)
679 spc_2_aux = numpy.flip(spc_1_aux)
680 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
680 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
681
681
682 len_dif = len(x)-len(spc_3_aux)
682 len_dif = len(x)-len(spc_3_aux)
683
683
684 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
684 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
685
685
686 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
686 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
687
687
688 y = spc_new
688 y = spc_new
689
689
690 elif nGauss == 'second':
690 elif nGauss == 'second':
691 y = spc
691 y = spc
692
692
693
693
694 # estimate starting values from the data
694 # estimate starting values from the data
695 a = y.max()
695 a = y.max()
696 b = x[numpy.argmax(y)]
696 b = x[numpy.argmax(y)]
697 if nGauss == 'first':
697 if nGauss == 'first':
698 c = 1.#b#b#numpy.std(spc)
698 c = 1.#b#b#numpy.std(spc)
699 elif nGauss == 'second':
699 elif nGauss == 'second':
700 c = b
700 c = b
701 else:
701 else:
702 print("ERROR")
702 print("ERROR")
703
703
704 d = numpy.mean(y[-100:])
704 d = numpy.mean(y[-100:])
705
705
706 # define a least squares function to optimize
706 # define a least squares function to optimize
707 def minfunc(params):
707 def minfunc(params):
708 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
708 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
709
709
710 # fit
710 # fit
711 popt = fmin(minfunc,[a,b,c,d],disp=False)
711 popt = fmin(minfunc,[a,b,c,d],disp=False)
712 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
712 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
713
713
714
714
715 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
715 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
716
716
717
717
718 def Gauss_fit_2(self,spc,x,nGauss):
718 def Gauss_fit_2(self,spc,x,nGauss):
719
719
720
720
721 def gaussian(x, a, b, c, d):
721 def gaussian(x, a, b, c, d):
722 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
722 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
723 return val
723 return val
724
724
725 if nGauss == 'first':
725 if nGauss == 'first':
726 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
726 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
727 spc_2_aux = numpy.flip(spc_1_aux)
727 spc_2_aux = numpy.flip(spc_1_aux)
728 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
728 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
729
729
730 len_dif = len(x)-len(spc_3_aux)
730 len_dif = len(x)-len(spc_3_aux)
731
731
732 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
732 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
733
733
734 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
734 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
735
735
736 y = spc_new
736 y = spc_new
737
737
738 elif nGauss == 'second':
738 elif nGauss == 'second':
739 y = spc
739 y = spc
740
740
741
741
742 # estimate starting values from the data
742 # estimate starting values from the data
743 a = y.max()
743 a = y.max()
744 b = x[numpy.argmax(y)]
744 b = x[numpy.argmax(y)]
745 if nGauss == 'first':
745 if nGauss == 'first':
746 c = 1.#b#b#numpy.std(spc)
746 c = 1.#b#b#numpy.std(spc)
747 elif nGauss == 'second':
747 elif nGauss == 'second':
748 c = b
748 c = b
749 else:
749 else:
750 print("ERROR")
750 print("ERROR")
751
751
752 d = numpy.mean(y[-100:])
752 d = numpy.mean(y[-100:])
753 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
753 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
754 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
754 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
755
755
756 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
756 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
757
757
758 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
758 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
759 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
759 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
760 return val
760 return val
761
761
762
762
763 y = spc
763 y = spc
764
764
765 # estimate starting values from the data
765 # estimate starting values from the data
766 a1 = A1
766 a1 = A1
767 b1 = B1
767 b1 = B1
768 c1 = C1#numpy.std(spc)
768 c1 = C1#numpy.std(spc)
769
769
770 a2 = A2#y.max()
770 a2 = A2#y.max()
771 b2 = B2#x[numpy.argmax(y)]
771 b2 = B2#x[numpy.argmax(y)]
772 c2 = C2#numpy.std(spc)
772 c2 = C2#numpy.std(spc)
773 d = D
773 d = D
774
774
775 # define a least squares function to optimize
775 # define a least squares function to optimize
776 def minfunc(params):
776 def minfunc(params):
777 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
777 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
778
778
779 # fit
779 # fit
780 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
780 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
781
781
782 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]
782 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]
783
783
784 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
784 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
785
785
786 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
786 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
787 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
787 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
788 return val
788 return val
789
789
790
790
791 y = spc
791 y = spc
792
792
793 # estimate starting values from the data
793 # estimate starting values from the data
794 a1 = A1
794 a1 = A1
795 b1 = B1
795 b1 = B1
796 c1 = C1#numpy.std(spc)
796 c1 = C1#numpy.std(spc)
797
797
798 a2 = A2#y.max()
798 a2 = A2#y.max()
799 b2 = B2#x[numpy.argmax(y)]
799 b2 = B2#x[numpy.argmax(y)]
800 c2 = C2#numpy.std(spc)
800 c2 = C2#numpy.std(spc)
801 d = D
801 d = D
802
802
803 # fit
803 # fit
804 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
804 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
805 error = numpy.sqrt(numpy.diag(pcov))
805 error = numpy.sqrt(numpy.diag(pcov))
806
806
807 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]
807 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]
808
808
809 def windowing_double(self,spc,x,A1,B1,C1,A2,B2,C2,D):
809 def windowing_double(self,spc,x,A1,B1,C1,A2,B2,C2,D):
810 from scipy.optimize import curve_fit,fmin
810 from scipy.optimize import curve_fit,fmin
811
811
812 def R_gaussian(x, a, b, c):
812 def R_gaussian(x, a, b, c):
813 N = int(numpy.shape(x)[0])
813 N = int(numpy.shape(x)[0])
814 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
814 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
815 return val
815 return val
816
816
817 def T(x,N):
817 def T(x,N):
818 T = 1-abs(x)/N
818 T = 1-abs(x)/N
819 return T
819 return T
820
820
821 def R_T_spc_fun(x, a1, b1, c1, a2, b2, c2, d):
821 def R_T_spc_fun(x, a1, b1, c1, a2, b2, c2, d):
822
822
823 N = int(numpy.shape(x)[0])
823 N = int(numpy.shape(x)[0])
824
824
825 x_max = x[-1]
825 x_max = x[-1]
826
826
827 x_pos = x[1600:]
827 x_pos = x[1600:]
828 x_neg = x[:1600]
828 x_neg = x[:1600]
829
829
830 R_T_neg_1 = R_gaussian(x, a1, b1, c1)[:1600]*T(x_neg,-x[0])
830 R_T_neg_1 = R_gaussian(x, a1, b1, c1)[:1600]*T(x_neg,-x[0])
831 R_T_pos_1 = R_gaussian(x, a1, b1, c1)[1600:]*T(x_pos,x[-1])
831 R_T_pos_1 = R_gaussian(x, a1, b1, c1)[1600:]*T(x_pos,x[-1])
832 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
832 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
833 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
833 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
834 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
834 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
835 max_val_1 = numpy.max(R_T_spc_1)
835 max_val_1 = numpy.max(R_T_spc_1)
836 R_T_spc_1 = R_T_spc_1*a1/max_val_1
836 R_T_spc_1 = R_T_spc_1*a1/max_val_1
837
837
838 R_T_neg_2 = R_gaussian(x, a2, b2, c2)[:1600]*T(x_neg,-x[0])
838 R_T_neg_2 = R_gaussian(x, a2, b2, c2)[:1600]*T(x_neg,-x[0])
839 R_T_pos_2 = R_gaussian(x, a2, b2, c2)[1600:]*T(x_pos,x[-1])
839 R_T_pos_2 = R_gaussian(x, a2, b2, c2)[1600:]*T(x_pos,x[-1])
840 R_T_sum_2 = R_T_pos_2 + R_T_neg_2
840 R_T_sum_2 = R_T_pos_2 + R_T_neg_2
841 R_T_spc_2 = numpy.fft.fft(R_T_sum_2).real
841 R_T_spc_2 = numpy.fft.fft(R_T_sum_2).real
842 R_T_spc_2 = numpy.fft.fftshift(R_T_spc_2)
842 R_T_spc_2 = numpy.fft.fftshift(R_T_spc_2)
843 max_val_2 = numpy.max(R_T_spc_2)
843 max_val_2 = numpy.max(R_T_spc_2)
844 R_T_spc_2 = R_T_spc_2*a2/max_val_2
844 R_T_spc_2 = R_T_spc_2*a2/max_val_2
845
845
846 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
846 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
847 R_T_d_neg = R_T_d[:1600]*T(x_neg,-x[0])
847 R_T_d_neg = R_T_d[:1600]*T(x_neg,-x[0])
848 R_T_d_pos = R_T_d[1600:]*T(x_pos,x[-1])
848 R_T_d_pos = R_T_d[1600:]*T(x_pos,x[-1])
849 R_T_d_sum = R_T_d_pos + R_T_d_neg
849 R_T_d_sum = R_T_d_pos + R_T_d_neg
850 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
850 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
851 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
851 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
852
852
853 R_T_final = R_T_spc_1 + R_T_spc_2 + R_T_spc_3
853 R_T_final = R_T_spc_1 + R_T_spc_2 + R_T_spc_3
854
854
855 return R_T_final
855 return R_T_final
856
856
857 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
857 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
858
858
859 from scipy.stats import norm
859 from scipy.stats import norm
860 mean,std=norm.fit(spc)
860 mean,std=norm.fit(spc)
861
861
862 # estimate starting values from the data
862 # estimate starting values from the data
863 a1 = A1
863 a1 = A1
864 b1 = B1
864 b1 = B1
865 c1 = C1#numpy.std(spc)
865 c1 = C1#numpy.std(spc)
866
866
867 a2 = A2#y.max()
867 a2 = A2#y.max()
868 b2 = B2#x[numpy.argmax(y)]
868 b2 = B2#x[numpy.argmax(y)]
869 c2 = C2#numpy.std(spc)
869 c2 = C2#numpy.std(spc)
870 d = D
870 d = D
871
871
872 ippSeconds = 250*20*1.e-6/3
872 ippSeconds = 250*20*1.e-6/3
873
873
874 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
874 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
875
875
876 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
876 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
877
877
878 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
878 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
879 x_freq = numpy.fft.fftshift(x_freq)
879 x_freq = numpy.fft.fftshift(x_freq)
880
880
881 # define a least squares function to optimize
881 # define a least squares function to optimize
882 def minfunc(params):
882 def minfunc(params):
883 return sum((y-R_T_spc_fun(x_t,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
883 return sum((y-R_T_spc_fun(x_t,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
884
884
885 # fit
885 # fit
886 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],full_output=True)
886 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],full_output=True)
887 popt = popt_full[0]
887 popt = popt_full[0]
888
888
889 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
889 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
890
890
891 def Double_Gauss_fit_weight(self,spc,x,A1,B1,C1,A2,B2,C2,D):
891 def Double_Gauss_fit_weight(self,spc,x,A1,B1,C1,A2,B2,C2,D):
892 from scipy.optimize import curve_fit,fmin
892 from scipy.optimize import curve_fit,fmin
893
893
894 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
894 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
895 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
895 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
896 return val
896 return val
897
897
898 y = spc
898 y = spc
899
899
900 from scipy.stats import norm
900 from scipy.stats import norm
901 mean,std=norm.fit(spc)
901 mean,std=norm.fit(spc)
902
902
903 # estimate starting values from the data
903 # estimate starting values from the data
904 a1 = A1
904 a1 = A1
905 b1 = B1
905 b1 = B1
906 c1 = C1#numpy.std(spc)
906 c1 = C1#numpy.std(spc)
907
907
908 a2 = A2#y.max()
908 a2 = A2#y.max()
909 b2 = B2#x[numpy.argmax(y)]
909 b2 = B2#x[numpy.argmax(y)]
910 c2 = C2#numpy.std(spc)
910 c2 = C2#numpy.std(spc)
911 d = D
911 d = D
912
912
913 y_clean = signal.medfilt(y)
913 y_clean = signal.medfilt(y)
914 # define a least squares function to optimize
914 # define a least squares function to optimize
915 def minfunc(params):
915 def minfunc(params):
916 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/(y_clean**2/1))
916 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/(y_clean**2/1))
917
917
918 # fit
918 # fit
919 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d], disp =False, full_output=True)
919 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d], disp =False, full_output=True)
920 #print("nIter", popt_full[2])
920 #print("nIter", popt_full[2])
921 popt = popt_full[0]
921 popt = popt_full[0]
922 #popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
922 #popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
923
923
924 #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]
924 #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]
925 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
925 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
926
926
927 def DH_mode(self,spectra,VelRange):
927 def DH_mode(self,spectra,VelRange):
928
928
929 from scipy.optimize import curve_fit
929 from scipy.optimize import curve_fit
930
930
931 def double_gauss(x, a1,b1,c1, a2,b2,c2, d):
931 def double_gauss(x, a1,b1,c1, a2,b2,c2, d):
932 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
932 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
933 return val
933 return val
934
934
935 spec = (spectra.copy()).flatten()
935 spec = (spectra.copy()).flatten()
936 amp=spec.max()
936 amp=spec.max()
937 params=numpy.array([amp,-400,30,amp/4,-200,150,1.0e7])
937 params=numpy.array([amp,-400,30,amp/4,-200,150,1.0e7])
938 #try:
938 #try:
939 popt,pcov=curve_fit(double_gauss, VelRange, spec, p0=params,bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf]))
939 popt,pcov=curve_fit(double_gauss, VelRange, spec, p0=params,bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf]))
940
940
941 error = numpy.sqrt(numpy.diag(pcov))
941 error = numpy.sqrt(numpy.diag(pcov))
942 #doppler_2=popt[4]
942 #doppler_2=popt[4]
943 #err_2 = numpy.sqrt(pcov[4][4])
943 #err_2 = numpy.sqrt(pcov[4][4])
944
944
945 #except:
945 #except:
946 #pass
946 #pass
947 #doppler_2=numpy.NAN
947 #doppler_2=numpy.NAN
948 #err_2 = numpy.NAN
948 #err_2 = numpy.NAN
949
949
950 #return doppler_2, err_2
950 #return doppler_2, err_2
951
951
952 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]
952 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]
953
953
954 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
954 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
955
955
956 from scipy.optimize import least_squares
956 from scipy.optimize import least_squares
957
957
958 freq_max = numpy.max(numpy.abs(freq))
958 freq_max = numpy.max(numpy.abs(freq))
959 spc_max = numpy.max(spc)
959 spc_max = numpy.max(spc)
960
960
961 def tri_gaussian(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, d):
961 def tri_gaussian(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, d):
962 z1 = (x-b1)/c1
962 z1 = (x-b1)/c1
963 z2 = (x-b2)/c2
963 z2 = (x-b2)/c2
964 z3 = (x-b3)/c3
964 z3 = (x-b3)/c3
965 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + a3 * numpy.exp(-z3**2/2) + d
965 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + a3 * numpy.exp(-z3**2/2) + d
966 return val
966 return val
967
967
968 from scipy.signal import medfilt
968 from scipy.signal import medfilt
969 Nincoh = 20
969 Nincoh = 20
970 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
970 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
971 c1 = abs(c1)
971 c1 = abs(c1)
972 c2 = abs(c2)
972 c2 = abs(c2)
973
973
974 # define a least squares function to optimize
974 # define a least squares function to optimize
975 def lsq_func(params):
975 def lsq_func(params):
976 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9]))/spcm
976 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9]))/spcm
977
977
978 # fit
978 # fit
979 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0,0,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,600,numpy.inf,numpy.inf])
979 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0,0,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,600,numpy.inf,numpy.inf])
980
980
981 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
981 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
982 #print(a1,b1,c1,a2,b2,c2,d)
982 #print(a1,b1,c1,a2,b2,c2,d)
983 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,a2/4,-b1,c1,d],x_scale=params_scale,bounds=bounds)
983 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,a2/4,-b1,c1,d],x_scale=params_scale,bounds=bounds)
984
984
985 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
985 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
986 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
986 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
987 A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
987 A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
988 Df = popt.x[9]
988 Df = popt.x[9]
989
989
990 return A1f, B1f, C1f, A2f, B2f, C2f, Df
990 return A1f, B1f, C1f, A2f, B2f, C2f, Df
991
991
992 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
992 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
993
993
994 from scipy.optimize import least_squares
994 from scipy.optimize import least_squares
995
995
996 freq_max = numpy.max(numpy.abs(freq))
996 freq_max = numpy.max(numpy.abs(freq))
997 spc_max = numpy.max(spc)
997 spc_max = numpy.max(spc)
998
998
999 def duo_gaussian(x, a1, b1, c1, a2, b2, c2, d):
999 def duo_gaussian(x, a1, b1, c1, a2, b2, c2, d):
1000 z1 = (x-b1)/c1
1000 z1 = (x-b1)/c1
1001 z2 = (x-b2)/c2
1001 z2 = (x-b2)/c2
1002 #z3 = (x-b3)/c3
1002 #z3 = (x-b3)/c3
1003 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1003 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1004 return val
1004 return val
1005
1005
1006 from scipy.signal import medfilt
1006 from scipy.signal import medfilt
1007 Nincoh = 20
1007 Nincoh = 20
1008 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1008 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1009 c1 = abs(c1)
1009 c1 = abs(c1)
1010 c2 = abs(c2)
1010 c2 = abs(c2)
1011
1011
1012 # define a least squares function to optimize
1012 # define a least squares function to optimize
1013 def lsq_func(params):
1013 def lsq_func(params):
1014 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1014 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1015
1015
1016 # fit
1016 # fit
1017 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1017 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1018
1018
1019 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1019 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1020 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,d],x_scale=params_scale,bounds=bounds)
1020 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,d],x_scale=params_scale,bounds=bounds)
1021
1021
1022 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1022 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1023 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1023 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1024 #A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
1024 #A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
1025 Df = popt.x[9]
1025 Df = popt.x[9]
1026
1026
1027 return A1f, B1f, C1f, A2f, B2f, C2f, Df
1027 return A1f, B1f, C1f, A2f, B2f, C2f, Df
1028
1028
1029 def double_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, d):
1029 def double_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, d):
1030 z1 = (x-b1)/c1
1030 z1 = (x-b1)/c1
1031 z2 = (x-b2)/c2
1031 z2 = (x-b2)/c2
1032 h2 = 1-k2*z2
1032 h2 = 1-k2*z2
1033 h2[h2<0] = 0
1033 h2[h2<0] = 0
1034 y2 = -1/k2*numpy.log(h2)
1034 y2 = -1/k2*numpy.log(h2)
1035 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1035 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1036 return val
1036 return val
1037
1037
1038 def gaussian(self, x, a, b, c, d):
1038 def gaussian(self, x, a, b, c, d):
1039 z = (x-b)/c
1039 z = (x-b)/c
1040 val = a * numpy.exp(-z**2/2) + d
1040 val = a * numpy.exp(-z**2/2) + d
1041 return val
1041 return val
1042
1042
1043 def double_gaussian(self, x, a1, b1, c1, a2, b2, c2, d):
1043 def double_gaussian(self, x, a1, b1, c1, a2, b2, c2, d):
1044 z1 = (x-b1)/c1
1044 z1 = (x-b1)/c1
1045 z2 = (x-b2)/c2
1045 z2 = (x-b2)/c2
1046 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1046 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1047 return val
1047 return val
1048
1048
1049 def double_gaussian_double_skew(self,x, a1, b1, c1, k1, a2, b2, c2, k2, d):
1049 def double_gaussian_double_skew(self,x, a1, b1, c1, k1, a2, b2, c2, k2, d):
1050
1050
1051 z1 = (x-b1)/c1
1051 z1 = (x-b1)/c1
1052 h1 = 1-k1*z1
1052 h1 = 1-k1*z1
1053 h1[h1<0] = 0
1053 h1[h1<0] = 0
1054 y1 = -1/k1*numpy.log(h1)
1054 y1 = -1/k1*numpy.log(h1)
1055
1055
1056 z2 = (x-b2)/c2
1056 z2 = (x-b2)/c2
1057 h2 = 1-k2*z2
1057 h2 = 1-k2*z2
1058 h2[h2<0] = 0
1058 h2[h2<0] = 0
1059 y2 = -1/k2*numpy.log(h2)
1059 y2 = -1/k2*numpy.log(h2)
1060
1060
1061 val = a1 * numpy.exp(-y1**2/2)/(1-k1*z1) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1061 val = a1 * numpy.exp(-y1**2/2)/(1-k1*z1) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1062 return val
1062 return val
1063
1063
1064 def gaussian_skew(self,x, a2, b2, c2, k2, d):
1064 def gaussian_skew(self,x, a2, b2, c2, k2, d):
1065 z2 = (x-b2)/c2
1065 z2 = (x-b2)/c2
1066 h2 = 1-k2*z2
1066 h2 = 1-k2*z2
1067 h2[h2<0] = 0
1067 h2[h2<0] = 0
1068 y2 = -1/k2*numpy.log(h2)
1068 y2 = -1/k2*numpy.log(h2)
1069 val = a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1069 val = a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1070 return val
1070 return val
1071
1071
1072 def triple_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, a3, b3, c3, k3, d):
1072 def triple_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, a3, b3, c3, k3, d):
1073 z1 = (x-b1)/c1
1073 z1 = (x-b1)/c1
1074 z2 = (x-b2)/c2
1074 z2 = (x-b2)/c2
1075 z3 = (x-b3)/c3
1075 z3 = (x-b3)/c3
1076 h2 = 1-k2*z2
1076 h2 = 1-k2*z2
1077 h2[h2<0] = 0
1077 h2[h2<0] = 0
1078 y2 = -1/k2*numpy.log(h2)
1078 y2 = -1/k2*numpy.log(h2)
1079 h3 = 1-k3*z3
1079 h3 = 1-k3*z3
1080 h3[h3<0] = 0
1080 h3[h3<0] = 0
1081 y3 = -1/k3*numpy.log(h3)
1081 y3 = -1/k3*numpy.log(h3)
1082 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + a3 * numpy.exp(-y3**2/2)/(1-k3*z3) + d
1082 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + a3 * numpy.exp(-y3**2/2)/(1-k3*z3) + d
1083 return val
1083 return val
1084
1084
1085 def Double_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1085 def Double_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1086
1086
1087 from scipy.optimize import least_squares
1087 from scipy.optimize import least_squares
1088
1088
1089 freq_max = numpy.max(numpy.abs(freq))
1089 freq_max = numpy.max(numpy.abs(freq))
1090 spc_max = numpy.max(spc)
1090 spc_max = numpy.max(spc)
1091
1091
1092 from scipy.signal import medfilt
1092 from scipy.signal import medfilt
1093 Nincoh = 20
1093 Nincoh = 20
1094 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1094 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1095
1095
1096 # define a least squares function to optimize
1096 # define a least squares function to optimize
1097 def lsq_func(params):
1097 def lsq_func(params):
1098 return (spc-self.double_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7]))/spcm
1098 return (spc-self.double_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7]))/spcm
1099
1099
1100 # fit
1100 # fit
1101 bounds=([0,-numpy.inf,0,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1101 bounds=([0,-numpy.inf,0,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1102
1102
1103 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max]
1103 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max]
1104 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,1.0e7])
1104 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,1.0e7])
1105 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1105 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1106 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1106 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1107 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1107 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1108 Df = popt.x[7]
1108 Df = popt.x[7]
1109
1109
1110 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1110 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1111 doppler = freq[numpy.argmax(aux)]
1111 doppler = freq[numpy.argmax(aux)]
1112
1112
1113 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, Df, doppler
1113 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, Df, doppler
1114
1114
1115 def Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh,hei):
1115 def Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh,hei):
1116
1116
1117 from scipy.optimize import least_squares
1117 from scipy.optimize import least_squares
1118
1118
1119 freq_max = numpy.max(numpy.abs(freq))
1119 freq_max = numpy.max(numpy.abs(freq))
1120 spc_max = numpy.max(spc)
1120 spc_max = numpy.max(spc)
1121
1121
1122 #from scipy.signal import medfilt
1122 #from scipy.signal import medfilt
1123 #Nincoh = 20
1123 #Nincoh = 20
1124 #Nincoh = 80
1124 #Nincoh = 80
1125 Nincoh = Nincoh
1125 Nincoh = Nincoh
1126 #spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1126 #spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1127 spcm = spc/numpy.sqrt(Nincoh)
1127 spcm = spc/numpy.sqrt(Nincoh)
1128
1128
1129 # define a least squares function to optimize
1129 # define a least squares function to optimize
1130 def lsq_func(params):
1130 def lsq_func(params):
1131 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1131 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1132
1132
1133 # fit
1133 # fit
1134 bounds=([0,-numpy.inf,0,-5,0,-400,0,0,0],[numpy.inf,-200,numpy.inf,5,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1134 bounds=([0,-numpy.inf,0,-5,0,-400,0,0,0],[numpy.inf,-200,numpy.inf,5,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1135
1135
1136 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1136 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1137
1137
1138 dop1_x0 = freq[numpy.argmax(spc)]
1138 dop1_x0 = freq[numpy.argmax(spc)]
1139 if dop1_x0 < 0:
1139 if dop1_x0 < 0:
1140 dop2_x0 = dop1_x0 + 100
1140 dop2_x0 = dop1_x0 + 100
1141 if dop1_x0 > 0:
1141 if dop1_x0 > 0:
1142 dop2_x0 = dop1_x0 - 100
1142 dop2_x0 = dop1_x0 - 100
1143
1143
1144 x0_value = numpy.array([spc_max,dop1_x0,30,-.1,spc_max/4, dop2_x0,150,1,1.0e7])
1144 x0_value = numpy.array([spc_max,dop1_x0,30,-.1,spc_max/4, dop2_x0,150,1,1.0e7])
1145 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1145 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1146 J = popt.jac
1146 J = popt.jac
1147
1147
1148 try:
1148 try:
1149 cov = numpy.linalg.inv(J.T.dot(J))
1149 cov = numpy.linalg.inv(J.T.dot(J))
1150 error = numpy.sqrt(numpy.diagonal(cov))
1150 error = numpy.sqrt(numpy.diagonal(cov))
1151 except:
1151 except:
1152 error = numpy.ones((9))*numpy.NAN
1152 error = numpy.ones((9))*numpy.NAN
1153
1153
1154 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1154 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1155 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1155 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1156 Df = popt.x[8]
1156 Df = popt.x[8]
1157 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1157 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1158 doppler1 = freq[numpy.argmax(aux1)]
1158 doppler1 = freq[numpy.argmax(aux1)]
1159
1159
1160 aux2 = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1160 aux2 = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1161 doppler2 = freq[numpy.argmax(aux2)]
1161 doppler2 = freq[numpy.argmax(aux2)]
1162 #print("error",error)
1162 #print("error",error)
1163 #exit(1)
1163 #exit(1)
1164
1164
1165
1165
1166 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler1, doppler2, error
1166 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler1, doppler2, error
1167
1167
1168 def Double_Gauss_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1168 def Double_Gauss_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1169
1169
1170 from scipy.optimize import least_squares
1170 from scipy.optimize import least_squares
1171
1171
1172 freq_max = numpy.max(numpy.abs(freq))
1172 freq_max = numpy.max(numpy.abs(freq))
1173 spc_max = numpy.max(spc)
1173 spc_max = numpy.max(spc)
1174
1174
1175 from scipy.signal import medfilt
1175 from scipy.signal import medfilt
1176 Nincoh = 20
1176 Nincoh = 20
1177 Nincoh = 80
1177 Nincoh = 80
1178 Nincoh = Nincoh
1178 Nincoh = Nincoh
1179 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1179 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1180
1180
1181 # define a least squares function to optimize
1181 # define a least squares function to optimize
1182 def lsq_func(params):
1182 def lsq_func(params):
1183 return (spc-self.double_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1183 return (spc-self.double_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1184
1184
1185 # fit
1185 # fit
1186 # bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf])
1186 # bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf])
1187 # bounds=([0,-numpy.inf,0,0,-numpy.inf,0,-numpy.inf,0],[numpy.inf,-200,numpy.inf,numpy.inf,0,numpy.inf,0,numpy.inf])
1187 # bounds=([0,-numpy.inf,0,0,-numpy.inf,0,-numpy.inf,0],[numpy.inf,-200,numpy.inf,numpy.inf,0,numpy.inf,0,numpy.inf])
1188 #print(a1,b1,c1,a2,b2,c2,k2,d)
1188 #print(a1,b1,c1,a2,b2,c2,k2,d)
1189
1189
1190 dop1_x0 = freq[numpy.argmax(spcm)]
1190 dop1_x0 = freq[numpy.argmax(spcm)]
1191
1191
1192 bounds=([0,-numpy.inf,0,0,dop1_x0-50,0,0],[numpy.inf,-300,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1192 bounds=([0,-numpy.inf,0,0,dop1_x0-50,0,0],[numpy.inf,-300,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1193 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1193 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1194 x0_value = numpy.array([spc_max,-400.5,30,spc_max/4,dop1_x0,150,1.0e7])
1194 x0_value = numpy.array([spc_max,-400.5,30,spc_max/4,dop1_x0,150,1.0e7])
1195 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1195 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1196 J = popt.jac
1196 J = popt.jac
1197
1197
1198 try:
1198 try:
1199 cov = numpy.linalg.inv(J.T.dot(J))
1199 cov = numpy.linalg.inv(J.T.dot(J))
1200 error = numpy.sqrt(numpy.diagonal(cov))
1200 error = numpy.sqrt(numpy.diagonal(cov))
1201 except:
1201 except:
1202 error = numpy.ones((7))*numpy.NAN
1202 error = numpy.ones((7))*numpy.NAN
1203
1203
1204 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1204 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1205 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1205 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1206 Df = popt.x[6]
1206 Df = popt.x[6]
1207 return A1f, B1f, C1f, A2f, B2f, C2f, Df, error
1207 return A1f, B1f, C1f, A2f, B2f, C2f, Df, error
1208
1208
1209 def Double_Gauss_Double_Skew_fit_weight_bound_with_inputs(self, spc, freq, a1, b1, c1, a2, b2, c2, k2, d):
1209 def Double_Gauss_Double_Skew_fit_weight_bound_with_inputs(self, spc, freq, a1, b1, c1, a2, b2, c2, k2, d):
1210
1210
1211 from scipy.optimize import least_squares
1211 from scipy.optimize import least_squares
1212
1212
1213 freq_max = numpy.max(numpy.abs(freq))
1213 freq_max = numpy.max(numpy.abs(freq))
1214 spc_max = numpy.max(spc)
1214 spc_max = numpy.max(spc)
1215
1215
1216 from scipy.signal import medfilt
1216 from scipy.signal import medfilt
1217 Nincoh = dataOut.nIncohInt
1217 Nincoh = dataOut.nIncohInt
1218 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1218 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1219
1219
1220 # define a least squares function to optimize
1220 # define a least squares function to optimize
1221 def lsq_func(params):
1221 def lsq_func(params):
1222 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1222 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1223
1223
1224
1224
1225 bounds=([0,-numpy.inf,0,-numpy.inf,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,0,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1225 bounds=([0,-numpy.inf,0,-numpy.inf,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,0,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1226
1226
1227 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1227 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1228
1228
1229 x0_value = numpy.array([a1,b1,c1,-.1,a2,b2,c2,k2,d])
1229 x0_value = numpy.array([a1,b1,c1,-.1,a2,b2,c2,k2,d])
1230
1230
1231 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1231 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1232
1232
1233 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1233 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1234 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1234 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1235 Df = popt.x[8]
1235 Df = popt.x[8]
1236
1236
1237 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1237 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1238 doppler = x[numpy.argmax(aux)]
1238 doppler = x[numpy.argmax(aux)]
1239
1239
1240 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler
1240 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler
1241
1241
1242 def Triple_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1242 def Triple_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1243
1243
1244 from scipy.optimize import least_squares
1244 from scipy.optimize import least_squares
1245
1245
1246 freq_max = numpy.max(numpy.abs(freq))
1246 freq_max = numpy.max(numpy.abs(freq))
1247 spc_max = numpy.max(spc)
1247 spc_max = numpy.max(spc)
1248
1248
1249 from scipy.signal import medfilt
1249 from scipy.signal import medfilt
1250 Nincoh = 20
1250 Nincoh = 20
1251 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1251 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1252
1252
1253 # define a least squares function to optimize
1253 # define a least squares function to optimize
1254 def lsq_func(params):
1254 def lsq_func(params):
1255 return (spc-self.triple_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11]))/spcm
1255 return (spc-self.triple_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11]))/spcm
1256
1256
1257 # fit
1257 # fit
1258 bounds=([0,-numpy.inf,0,0,-400,0,0,0,0,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1258 bounds=([0,-numpy.inf,0,0,-400,0,0,0,0,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1259
1259
1260 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1260 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1261 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,spc_max/4,400,150,1,1.0e7])
1261 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,spc_max/4,400,150,1,1.0e7])
1262 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1262 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1263
1263
1264 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1264 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1265 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1265 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1266 A3f = popt.x[7]; B3f = popt.x[8]; C3f = popt.x[9]; K3f = popt.x[10]
1266 A3f = popt.x[7]; B3f = popt.x[8]; C3f = popt.x[9]; K3f = popt.x[10]
1267 Df = popt.x[11]
1267 Df = popt.x[11]
1268
1268
1269 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1269 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1270 doppler = freq[numpy.argmax(aux)]
1270 doppler = freq[numpy.argmax(aux)]
1271
1271
1272 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, A3f, B3f, C3f, K3f, Df, doppler
1272 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, A3f, B3f, C3f, K3f, Df, doppler
1273
1273
1274 def CEEJ_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1274 def CEEJ_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1275
1275
1276 from scipy.optimize import least_squares
1276 from scipy.optimize import least_squares
1277
1277
1278 freq_max = numpy.max(numpy.abs(freq))
1278 freq_max = numpy.max(numpy.abs(freq))
1279 spc_max = numpy.max(spc)
1279 spc_max = numpy.max(spc)
1280
1280
1281 from scipy.signal import medfilt
1281 from scipy.signal import medfilt
1282 Nincoh = 20
1282 Nincoh = 20
1283 Nincoh = 80
1283 Nincoh = 80
1284 Nincoh = Nincoh
1284 Nincoh = Nincoh
1285 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1285 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1286
1286
1287 # define a least squares function to optimize
1287 # define a least squares function to optimize
1288 def lsq_func(params):
1288 def lsq_func(params):
1289 return (spc-self.gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4]))#/spcm
1289 return (spc-self.gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4]))#/spcm
1290
1290
1291
1291
1292 bounds=([0,0,0,-numpy.inf,0],[numpy.inf,numpy.inf,numpy.inf,0,numpy.inf])
1292 bounds=([0,0,0,-numpy.inf,0],[numpy.inf,numpy.inf,numpy.inf,0,numpy.inf])
1293
1293
1294 params_scale = [spc_max,freq_max,freq_max,1,spc_max]
1294 params_scale = [spc_max,freq_max,freq_max,1,spc_max]
1295
1295
1296 x0_value = numpy.array([spc_max,freq[numpy.argmax(spc)],30,-.1,numpy.mean(spc[:50])])
1296 x0_value = numpy.array([spc_max,freq[numpy.argmax(spc)],30,-.1,numpy.mean(spc[:50])])
1297
1297
1298 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1298 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1299
1299
1300 J = popt.jac
1300 J = popt.jac
1301
1301
1302 try:
1302 try:
1303 error = numpy.ones((9))*numpy.NAN
1303 error = numpy.ones((9))*numpy.NAN
1304 cov = numpy.linalg.inv(J.T.dot(J))
1304 cov = numpy.linalg.inv(J.T.dot(J))
1305 error[:4] = numpy.sqrt(numpy.diagonal(cov))[:4]
1305 error[:4] = numpy.sqrt(numpy.diagonal(cov))[:4]
1306 error[-1] = numpy.sqrt(numpy.diagonal(cov))[-1]
1306 error[-1] = numpy.sqrt(numpy.diagonal(cov))[-1]
1307 except:
1307 except:
1308 error = numpy.ones((9))*numpy.NAN
1308 error = numpy.ones((9))*numpy.NAN
1309
1309
1310 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1310 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1311 Df = popt.x[4]
1311 Df = popt.x[4]
1312
1312
1313 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1313 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1314 doppler1 = freq[numpy.argmax(aux1)]
1314 doppler1 = freq[numpy.argmax(aux1)]
1315 #print("CEEJ ERROR:",error)
1315 #print("CEEJ ERROR:",error)
1316
1316
1317 return A1f, B1f, C1f, K1f, numpy.NAN, numpy.NAN, numpy.NAN, numpy.NAN, Df, doppler1, numpy.NAN, error
1317 return A1f, B1f, C1f, K1f, numpy.NAN, numpy.NAN, numpy.NAN, numpy.NAN, Df, doppler1, numpy.NAN, error
1318
1318
1319 def CEEJ_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1319 def CEEJ_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1320
1320
1321 from scipy.optimize import least_squares
1321 from scipy.optimize import least_squares
1322
1322
1323 freq_max = numpy.max(numpy.abs(freq))
1323 freq_max = numpy.max(numpy.abs(freq))
1324 spc_max = numpy.max(spc)
1324 spc_max = numpy.max(spc)
1325
1325
1326 from scipy.signal import medfilt
1326 from scipy.signal import medfilt
1327 Nincoh = 20
1327 Nincoh = 20
1328 Nincoh = 80
1328 Nincoh = 80
1329 Nincoh = Nincoh
1329 Nincoh = Nincoh
1330 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1330 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1331
1331
1332 # define a least squares function to optimize
1332 # define a least squares function to optimize
1333 def lsq_func(params):
1333 def lsq_func(params):
1334 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))#/spcm
1334 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))#/spcm
1335
1335
1336
1336
1337 bounds=([0,0,0,0],[numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1337 bounds=([0,0,0,0],[numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1338
1338
1339 params_scale = [spc_max,freq_max,freq_max,spc_max]
1339 params_scale = [spc_max,freq_max,freq_max,spc_max]
1340
1340
1341 x0_value = numpy.array([spc_max,freq[numpy.argmax(spcm)],30,numpy.mean(spc[:50])])
1341 x0_value = numpy.array([spc_max,freq[numpy.argmax(spcm)],30,numpy.mean(spc[:50])])
1342
1342
1343 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1343 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1344
1344
1345 J = popt.jac
1345 J = popt.jac
1346
1346
1347 try:
1347 try:
1348 error = numpy.ones((4))*numpy.NAN
1348 error = numpy.ones((4))*numpy.NAN
1349 cov = numpy.linalg.inv(J.T.dot(J))
1349 cov = numpy.linalg.inv(J.T.dot(J))
1350 error = numpy.sqrt(numpy.diagonal(cov))
1350 error = numpy.sqrt(numpy.diagonal(cov))
1351 except:
1351 except:
1352 error = numpy.ones((4))*numpy.NAN
1352 error = numpy.ones((4))*numpy.NAN
1353
1353
1354 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1354 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1355 Df = popt.x[3]
1355 Df = popt.x[3]
1356
1356
1357 return A1f, B1f, C1f, Df, error
1357 return A1f, B1f, C1f, Df, error
1358
1358
1359 def Simple_fit_bound(self,spc,freq,Nincoh):
1359 def Simple_fit_bound(self,spc,freq,Nincoh):
1360
1360
1361 freq_max = numpy.max(numpy.abs(freq))
1361 freq_max = numpy.max(numpy.abs(freq))
1362 spc_max = numpy.max(spc)
1362 spc_max = numpy.max(spc)
1363
1363
1364 Nincoh = Nincoh
1364 Nincoh = Nincoh
1365
1365
1366 def lsq_func(params):
1366 def lsq_func(params):
1367 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))
1367 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))
1368
1368
1369 bounds=([0,-50,0,0],[numpy.inf,+50,numpy.inf,numpy.inf])
1369 bounds=([0,-50,0,0],[numpy.inf,+50,numpy.inf,numpy.inf])
1370
1370
1371 params_scale = [spc_max,freq_max,freq_max,spc_max]
1371 params_scale = [spc_max,freq_max,freq_max,spc_max]
1372
1372
1373 x0_value = numpy.array([spc_max,-20.5,5,1.0e7])
1373 x0_value = numpy.array([spc_max,-20.5,5,1.0e7])
1374
1374
1375 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1375 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1376
1376
1377 J = popt.jac
1377 J = popt.jac
1378
1378
1379 try:
1379 try:
1380 cov = numpy.linalg.inv(J.T.dot(J))
1380 cov = numpy.linalg.inv(J.T.dot(J))
1381 error = numpy.sqrt(numpy.diagonal(cov))
1381 error = numpy.sqrt(numpy.diagonal(cov))
1382 except:
1382 except:
1383 error = numpy.ones((4))*numpy.NAN
1383 error = numpy.ones((4))*numpy.NAN
1384
1384
1385 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1385 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1386 Df = popt.x[3]
1386 Df = popt.x[3]
1387
1387
1388 return A1f, B1f, C1f, Df, error
1388 return A1f, B1f, C1f, Df, error
1389
1389
1390 def clean_outliers(self,param):
1390 def clean_outliers(self,param):
1391
1391
1392 threshold = 700
1392 threshold = 700
1393
1393
1394 param = numpy.where(param < -threshold, numpy.nan, param)
1394 param = numpy.where(param < -threshold, numpy.nan, param)
1395 param = numpy.where(param > +threshold, numpy.nan, param)
1395 param = numpy.where(param > +threshold, numpy.nan, param)
1396
1396
1397 return param
1397 return param
1398
1398
1399 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1399 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1400 from scipy.optimize import curve_fit,fmin
1400 from scipy.optimize import curve_fit,fmin
1401
1401
1402 def R_gaussian(x, a, b, c):
1402 def R_gaussian(x, a, b, c):
1403 N = int(numpy.shape(x)[0])
1403 N = int(numpy.shape(x)[0])
1404 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1404 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1405 return val
1405 return val
1406
1406
1407 def T(x,N):
1407 def T(x,N):
1408 T = 1-abs(x)/N
1408 T = 1-abs(x)/N
1409 return T
1409 return T
1410
1410
1411 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1411 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1412
1412
1413 N = int(numpy.shape(x)[0])
1413 N = int(numpy.shape(x)[0])
1414
1414
1415 x_max = x[-1]
1415 x_max = x[-1]
1416
1416
1417 x_pos = x[int(nFFTPoints/2):]
1417 x_pos = x[int(nFFTPoints/2):]
1418 x_neg = x[:int(nFFTPoints/2)]
1418 x_neg = x[:int(nFFTPoints/2)]
1419
1419
1420 R_T_neg_1 = R_gaussian(x, a, b, c)[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1420 R_T_neg_1 = R_gaussian(x, a, b, c)[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1421 R_T_pos_1 = R_gaussian(x, a, b, c)[int(nFFTPoints/2):]*T(x_pos,x[-1])
1421 R_T_pos_1 = R_gaussian(x, a, b, c)[int(nFFTPoints/2):]*T(x_pos,x[-1])
1422 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1422 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1423 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1423 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1424 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1424 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1425 max_val_1 = numpy.max(R_T_spc_1)
1425 max_val_1 = numpy.max(R_T_spc_1)
1426 R_T_spc_1 = R_T_spc_1*a/max_val_1
1426 R_T_spc_1 = R_T_spc_1*a/max_val_1
1427
1427
1428 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1428 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1429 R_T_d_neg = R_T_d[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1429 R_T_d_neg = R_T_d[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1430 R_T_d_pos = R_T_d[int(nFFTPoints/2):]*T(x_pos,x[-1])
1430 R_T_d_pos = R_T_d[int(nFFTPoints/2):]*T(x_pos,x[-1])
1431 R_T_d_sum = R_T_d_pos + R_T_d_neg
1431 R_T_d_sum = R_T_d_pos + R_T_d_neg
1432 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1432 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1433 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1433 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1434
1434
1435 R_T_final = R_T_spc_1 + R_T_spc_3
1435 R_T_final = R_T_spc_1 + R_T_spc_3
1436
1436
1437 return R_T_final
1437 return R_T_final
1438
1438
1439 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1439 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1440
1440
1441 from scipy.stats import norm
1441 from scipy.stats import norm
1442 mean,std=norm.fit(spc)
1442 mean,std=norm.fit(spc)
1443
1443
1444 # estimate starting values from the data
1444 # estimate starting values from the data
1445 a = A
1445 a = A
1446 b = B
1446 b = B
1447 c = C#numpy.std(spc)
1447 c = C#numpy.std(spc)
1448 d = D
1448 d = D
1449 '''
1449 '''
1450 ippSeconds = 250*20*1.e-6/3
1450 ippSeconds = 250*20*1.e-6/3
1451
1451
1452 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
1452 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
1453
1453
1454 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1454 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1455
1455
1456 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1456 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1457 x_freq = numpy.fft.fftshift(x_freq)
1457 x_freq = numpy.fft.fftshift(x_freq)
1458 '''
1458 '''
1459 # define a least squares function to optimize
1459 # define a least squares function to optimize
1460 def minfunc(params):
1460 def minfunc(params):
1461 return sum((y-R_T_spc_fun(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
1461 return sum((y-R_T_spc_fun(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
1462
1462
1463 # fit
1463 # fit
1464
1464
1465 popt_full = fmin(minfunc,[a,b,c,d],full_output=True)
1465 popt_full = fmin(minfunc,[a,b,c,d],full_output=True)
1466 #print("nIter", popt_full[2])
1466 #print("nIter", popt_full[2])
1467 popt = popt_full[0]
1467 popt = popt_full[0]
1468
1468
1469 #return R_T_spc_fun(x_t,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]
1469 #return R_T_spc_fun(x_t,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]
1470 return popt[0], popt[1], popt[2], popt[3]
1470 return popt[0], popt[1], popt[2], popt[3]
1471
1471
1472 def run(self, dataOut, mode = 0, Hmin1 = None, Hmax1 = None, Hmin2 = None, Hmax2 = None, Dop = 'Shift'):
1472 def run(self, dataOut, mode = 0, Hmin1 = None, Hmax1 = None, Hmin2 = None, Hmax2 = None, Dop = 'Shift'):
1473
1473
1474 pwcode = 1
1474 pwcode = 1
1475
1475
1476 if dataOut.flagDecodeData:
1476 if dataOut.flagDecodeData:
1477 pwcode = numpy.sum(dataOut.code[0]**2)
1477 pwcode = numpy.sum(dataOut.code[0]**2)
1478 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
1478 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
1479 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
1479 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
1480 factor = normFactor
1480 factor = normFactor
1481 z = dataOut.data_spc / factor
1481 z = dataOut.data_spc / factor
1482 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1482 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1483 dataOut.power = numpy.average(z, axis=1)
1483 dataOut.power = numpy.average(z, axis=1)
1484 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
1484 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
1485
1485
1486 x = dataOut.getVelRange(0)
1486 x = dataOut.getVelRange(0)
1487
1487
1488 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1488 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1489 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1489 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1490 dataOut.dplr_2_u = numpy.ones((1,1,dataOut.nHeights))*numpy.NAN
1490 dataOut.dplr_2_u = numpy.ones((1,1,dataOut.nHeights))*numpy.NAN
1491
1491
1492 if mode == 6:
1492 if mode == 6:
1493 dataOut.Oblique_params = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1493 dataOut.Oblique_params = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1494 elif mode == 7:
1494 elif mode == 7:
1495 dataOut.Oblique_params = numpy.ones((1,13,dataOut.nHeights))*numpy.NAN
1495 dataOut.Oblique_params = numpy.ones((1,13,dataOut.nHeights))*numpy.NAN
1496 elif mode == 8:
1496 elif mode == 8:
1497 dataOut.Oblique_params = numpy.ones((1,10,dataOut.nHeights))*numpy.NAN
1497 dataOut.Oblique_params = numpy.ones((1,10,dataOut.nHeights))*numpy.NAN
1498 elif mode == 9:
1498 elif mode == 9:
1499 dataOut.Oblique_params = numpy.ones((1,11,dataOut.nHeights))*numpy.NAN
1499 dataOut.Oblique_params = numpy.ones((1,11,dataOut.nHeights))*numpy.NAN
1500 dataOut.Oblique_param_errors = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1500 dataOut.Oblique_param_errors = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1501 elif mode == 11:
1501 elif mode == 11:
1502 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1502 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1503 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1503 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1504 elif mode == 10: #150 km
1504 elif mode == 10: #150 km
1505 dataOut.Oblique_params = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1505 dataOut.Oblique_params = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1506 dataOut.Oblique_param_errors = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1506 dataOut.Oblique_param_errors = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1507 dataOut.snr_log10 = numpy.ones((1,dataOut.nHeights))*numpy.NAN
1507 dataOut.snr_log10 = numpy.ones((1,dataOut.nHeights))*numpy.NAN
1508
1508
1509 dataOut.VelRange = x
1509 dataOut.VelRange = x
1510
1510
1511
1511
1512
1512
1513 #l1=range(22,36) #+62
1513 #l1=range(22,36) #+62
1514 #l1=range(32,36)
1514 #l1=range(32,36)
1515 #l2=range(58,99) #+62
1515 #l2=range(58,99) #+62
1516
1516
1517 #if Hmin1 == None or Hmax1 == None or Hmin2 == None or Hmax2 == None:
1517 #if Hmin1 == None or Hmax1 == None or Hmin2 == None or Hmax2 == None:
1518
1518
1519 minHei1 = 105.
1519 minHei1 = 105.
1520 maxHei1 = 122.5
1520 maxHei1 = 122.5
1521 maxHei1 = 130.5
1521 maxHei1 = 130.5
1522
1522
1523 if mode == 10: #150 km
1523 if mode == 10: #150 km
1524 minHei1 = 100
1524 minHei1 = 100
1525 maxHei1 = 100
1525 maxHei1 = 100
1526
1526
1527 inda1 = numpy.where(dataOut.heightList >= minHei1)
1527 inda1 = numpy.where(dataOut.heightList >= minHei1)
1528 indb1 = numpy.where(dataOut.heightList <= maxHei1)
1528 indb1 = numpy.where(dataOut.heightList <= maxHei1)
1529
1529
1530 minIndex1 = inda1[0][0]
1530 minIndex1 = inda1[0][0]
1531 maxIndex1 = indb1[0][-1]
1531 maxIndex1 = indb1[0][-1]
1532
1532
1533 minHei2 = 150.
1533 minHei2 = 150.
1534 maxHei2 = 201.25
1534 maxHei2 = 201.25
1535 maxHei2 = 225.3
1535 maxHei2 = 225.3
1536
1536
1537 if mode == 10: #150 km
1537 if mode == 10: #150 km
1538 minHei2 = 110
1538 minHei2 = 110
1539 maxHei2 = 165
1539 maxHei2 = 165
1540
1540
1541 inda2 = numpy.where(dataOut.heightList >= minHei2)
1541 inda2 = numpy.where(dataOut.heightList >= minHei2)
1542 indb2 = numpy.where(dataOut.heightList <= maxHei2)
1542 indb2 = numpy.where(dataOut.heightList <= maxHei2)
1543
1543
1544 minIndex2 = inda2[0][0]
1544 minIndex2 = inda2[0][0]
1545 maxIndex2 = indb2[0][-1]
1545 maxIndex2 = indb2[0][-1]
1546
1546
1547 l1=range(minIndex1,maxIndex1)
1547 l1=range(minIndex1,maxIndex1)
1548 l2=range(minIndex2,maxIndex2)
1548 l2=range(minIndex2,maxIndex2)
1549
1549
1550 if mode == 4:
1550 if mode == 4:
1551 '''
1551 '''
1552 for ind in range(dataOut.nHeights):
1552 for ind in range(dataOut.nHeights):
1553 if(dataOut.heightList[ind]>=168 and dataOut.heightList[ind]<188):
1553 if(dataOut.heightList[ind]>=168 and dataOut.heightList[ind]<188):
1554 try:
1554 try:
1555 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1555 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1556 except:
1556 except:
1557 pass
1557 pass
1558 '''
1558 '''
1559 for ind in itertools.chain(l1, l2):
1559 for ind in itertools.chain(l1, l2):
1560
1560
1561 try:
1561 try:
1562 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1562 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1563 dataOut.dplr_2_u[0,0,ind] = dataOut.Oblique_params[0,4,ind]/numpy.sin(numpy.arccos(102/dataOut.heightList[ind]))
1563 dataOut.dplr_2_u[0,0,ind] = dataOut.Oblique_params[0,4,ind]/numpy.sin(numpy.arccos(102/dataOut.heightList[ind]))
1564 except:
1564 except:
1565 pass
1565 pass
1566
1566
1567 else:
1567 else:
1568 for hei in itertools.chain(l1, l2):
1568 for hei in itertools.chain(l1, l2):
1569 if numpy.isnan(dataOut.snl[0,hei]) or dataOut.snl[0,hei]<.0:
1569 if numpy.isnan(dataOut.snl[0,hei]) or dataOut.snl[0,hei]<.0:
1570
1570
1571 continue #Avoids the analysis when there is only noise
1571 continue #Avoids the analysis when there is only noise
1572
1572
1573 try:
1573 try:
1574 spc = dataOut.data_spc[0,:,hei]
1574 spc = dataOut.data_spc[0,:,hei]
1575
1575
1576 if mode == 6: #Skew Weighted Bounded
1576 if mode == 6: #Skew Weighted Bounded
1577 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1577 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1578 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,8,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1578 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,8,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1579
1579
1580 elif mode == 7: #Triple Skew Weighted Bounded
1580 elif mode == 7: #Triple Skew Weighted Bounded
1581 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_params[0,11,hei],dataOut.Oblique_params[0,12,hei] = self.Triple_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1581 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_params[0,11,hei],dataOut.Oblique_params[0,12,hei] = self.Triple_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1582 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,12,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1582 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,12,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1583
1583
1584 elif mode == 8: #Double Skewed Weighted Bounded with inputs
1584 elif mode == 8: #Double Skewed Weighted Bounded with inputs
1585 a1, b1, c1, a2, b2, c2, k2, d, dopp = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1585 a1, b1, c1, a2, b2, c2, k2, d, dopp = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1586 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x, a1, b1, c1, a2, b2, c2, k2, d)
1586 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x, a1, b1, c1, a2, b2, c2, k2, d)
1587 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,9,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1587 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,9,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1588
1588
1589 elif mode == 9: #Double Skewed Weighted Bounded no inputs
1589 elif mode == 9: #Double Skewed Weighted Bounded no inputs
1590 #if numpy.max(spc) <= 0:
1590 #if numpy.max(spc) <= 0:
1591 from scipy.signal import medfilt
1591 from scipy.signal import medfilt
1592 spcm = medfilt(spc,11)
1592 spcm = medfilt(spc,11)
1593 if x[numpy.argmax(spcm)] <= 0:
1593 if x[numpy.argmax(spcm)] <= 0:
1594 #print("EEJ", dataOut.heightList[hei], hei)
1594 #print("EEJ", dataOut.heightList[hei], hei)
1595 #if hei != 70:
1595 #if hei != 70:
1596 #continue
1596 #continue
1597 #else:
1597 #else:
1598 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt,dataOut.heightList[hei])
1598 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt,dataOut.heightList[hei])
1599 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1599 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1600 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1600 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1601 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1601 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1602
1602
1603 else:
1603 else:
1604 #print("CEEJ")
1604 #print("CEEJ")
1605 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.CEEJ_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt)
1605 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_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.CEEJ_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt)
1606 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1606 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1607 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1607 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1608 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1608 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1609 elif mode == 11: #Double Weighted Bounded no inputs
1609 elif mode == 11: #Double Weighted Bounded no inputs
1610 #if numpy.max(spc) <= 0:
1610 #if numpy.max(spc) <= 0:
1611 from scipy.signal import medfilt
1611 from scipy.signal import medfilt
1612 spcm = medfilt(spc,11)
1612 spcm = medfilt(spc,11)
1613
1613
1614 if x[numpy.argmax(spcm)] <= 0:
1614 if x[numpy.argmax(spcm)] <= 0:
1615 #print("EEJ")
1615 #print("EEJ")
1616 #print("EEJ",dataOut.heightList[hei])
1616 #print("EEJ",dataOut.heightList[hei])
1617 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,:,hei] = self.Double_Gauss_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1617 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,:,hei] = self.Double_Gauss_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1618 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1618 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1619 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1619 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1620 else:
1620 else:
1621 #print("CEEJ",dataOut.heightList[hei])
1621 #print("CEEJ",dataOut.heightList[hei])
1622 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_param_errors[0,:,hei] = self.CEEJ_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1622 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_param_errors[0,:,hei] = self.CEEJ_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1623
1623
1624 elif mode == 10: #150km
1624 elif mode == 10: #150km
1625 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_param_errors[0,:,hei] = self.Simple_fit_bound(spc,x,dataOut.nIncohInt)
1625 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_param_errors[0,:,hei] = self.Simple_fit_bound(spc,x,dataOut.nIncohInt)
1626 snr = (dataOut.power[0,hei]*factor - dataOut.Oblique_params[0,3,hei])/dataOut.Oblique_params[0,3,hei]
1626 snr = (dataOut.power[0,hei]*factor - dataOut.Oblique_params[0,3,hei])/dataOut.Oblique_params[0,3,hei]
1627 dataOut.snr_log10[0,hei] = numpy.log10(snr)
1627 dataOut.snr_log10[0,hei] = numpy.log10(snr)
1628
1628
1629 else:
1629 else:
1630 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
1630 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
1631
1631
1632 spc_diff = spc - spc_fit
1632 spc_diff = spc - spc_fit
1633 spc_diff[spc_diff < 0] = 0
1633 spc_diff[spc_diff < 0] = 0
1634
1634
1635 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
1635 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
1636
1636
1637 D = (D1+D2)
1637 D = (D1+D2)
1638
1638
1639 if mode == 0: #Double Fit
1639 if mode == 0: #Double Fit
1640 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)
1640 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)
1641 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
1641 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
1642
1642
1643 elif mode == 1: #Double Fit Windowed
1643 elif mode == 1: #Double Fit Windowed
1644 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] = self.windowing_double(spc,dataOut.getFreqRange(0),A1,B1,C1,A2,B2,C2,D)
1644 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] = self.windowing_double(spc,dataOut.getFreqRange(0),A1,B1,C1,A2,B2,C2,D)
1645
1645
1646 elif mode == 2: #Double Fit Weight
1646 elif mode == 2: #Double Fit Weight
1647 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] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1647 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] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1648
1648
1649 elif mode == 3: #Simple Fit
1649 elif mode == 3: #Simple Fit
1650 dataOut.Oblique_params[0,0,hei] = A1
1650 dataOut.Oblique_params[0,0,hei] = A1
1651 dataOut.Oblique_params[0,1,hei] = B1
1651 dataOut.Oblique_params[0,1,hei] = B1
1652 dataOut.Oblique_params[0,2,hei] = C1
1652 dataOut.Oblique_params[0,2,hei] = C1
1653 dataOut.Oblique_params[0,3,hei] = A2
1653 dataOut.Oblique_params[0,3,hei] = A2
1654 dataOut.Oblique_params[0,4,hei] = B2
1654 dataOut.Oblique_params[0,4,hei] = B2
1655 dataOut.Oblique_params[0,5,hei] = C2
1655 dataOut.Oblique_params[0,5,hei] = C2
1656 dataOut.Oblique_params[0,6,hei] = D
1656 dataOut.Oblique_params[0,6,hei] = D
1657
1657
1658 elif mode == 5: #Triple Fit Weight
1658 elif mode == 5: #Triple Fit Weight
1659 if hei in l1:
1659 if hei in l1:
1660 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] = self.duo_Marco(spc,x,A1,B1,C1,A2,B2,C2,D)
1660 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] = self.duo_Marco(spc,x,A1,B1,C1,A2,B2,C2,D)
1661 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1661 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1662 #print(dataOut.Oblique_params[0,0,hei])
1662 #print(dataOut.Oblique_params[0,0,hei])
1663 #print(dataOut.dplr_2_u[0,0,hei])
1663 #print(dataOut.dplr_2_u[0,0,hei])
1664 else:
1664 else:
1665 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] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1665 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] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1666 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1666 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1667
1667
1668
1668
1669 except:
1669 except:
1670 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
1670 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
1671 pass
1671 pass
1672
1672
1673 #exit(1)
1673 #exit(1)
1674 dataOut.paramInterval = dataOut.nProfiles*dataOut.nCohInt*dataOut.ippSeconds
1674 dataOut.paramInterval = dataOut.nProfiles*dataOut.nCohInt*dataOut.ippSeconds
1675 dataOut.lat=-11.95
1675 dataOut.lat=-11.95
1676 dataOut.lon=-76.87
1676 dataOut.lon=-76.87
1677 '''
1677 '''
1678 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<-700, numpy.nan, dop_t1)
1678 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<-700, numpy.nan, dop_t1)
1679 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<+700, numpy.nan, dop_t1)
1679 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<+700, numpy.nan, dop_t1)
1680 AquΓ­ debo exceptuar las amplitudes
1680 AquΓ­ debo exceptuar las amplitudes
1681 '''
1681 '''
1682 if mode == 9: #Double Skew Gaussian
1682 if mode == 9: #Double Skew Gaussian
1683 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1683 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1684 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1684 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1685 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1685 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1686 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1686 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1687 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1687 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1688 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,6,:]
1688 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,6,:]
1689 if Dop == 'Shift':
1689 if Dop == 'Shift':
1690 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1690 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1691 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1691 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1692 elif Dop == 'Max':
1692 elif Dop == 'Max':
1693 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1693 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1694 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1694 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1695
1695
1696 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:] #En realidad este es el error?
1696 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:] #En realidad este es el error?
1697 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1697 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1698 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,5,:] #En realidad este es el error?
1698 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,5,:] #En realidad este es el error?
1699 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,6,:]
1699 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,6,:]
1700
1700
1701 elif mode == 11: #Double Gaussian
1701 elif mode == 11: #Double Gaussian
1702 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:]
1702 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:]
1703 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1703 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1704 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,4,:]
1704 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,4,:]
1705 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,5,:]
1705 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,5,:]
1706
1706
1707 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:]
1707 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:]
1708 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1708 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1709 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,4,:]
1709 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,4,:]
1710 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,5,:]
1710 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,5,:]
1711
1711
1712 #print("Before: ", dataOut.Dop_EEJ_T2)
1712 #print("Before: ", dataOut.Dop_EEJ_T2)
1713 dataOut.Spec_W_T1 = self.clean_outliers(dataOut.Spec_W_T1)
1713 dataOut.Spec_W_T1 = self.clean_outliers(dataOut.Spec_W_T1)
1714 dataOut.Spec_W_T2 = self.clean_outliers(dataOut.Spec_W_T2)
1714 dataOut.Spec_W_T2 = self.clean_outliers(dataOut.Spec_W_T2)
1715 dataOut.Dop_EEJ_T1 = self.clean_outliers(dataOut.Dop_EEJ_T1)
1715 dataOut.Dop_EEJ_T1 = self.clean_outliers(dataOut.Dop_EEJ_T1)
1716 dataOut.Dop_EEJ_T2 = self.clean_outliers(dataOut.Dop_EEJ_T2)
1716 dataOut.Dop_EEJ_T2 = self.clean_outliers(dataOut.Dop_EEJ_T2)
1717 #print("After: ", dataOut.Dop_EEJ_T2)
1717 #print("After: ", dataOut.Dop_EEJ_T2)
1718 dataOut.Err_Spec_W_T1 = self.clean_outliers(dataOut.Err_Spec_W_T1)
1718 dataOut.Err_Spec_W_T1 = self.clean_outliers(dataOut.Err_Spec_W_T1)
1719 dataOut.Err_Spec_W_T2 = self.clean_outliers(dataOut.Err_Spec_W_T2)
1719 dataOut.Err_Spec_W_T2 = self.clean_outliers(dataOut.Err_Spec_W_T2)
1720 dataOut.Err_Dop_EEJ_T1 = self.clean_outliers(dataOut.Err_Dop_EEJ_T1)
1720 dataOut.Err_Dop_EEJ_T1 = self.clean_outliers(dataOut.Err_Dop_EEJ_T1)
1721 dataOut.Err_Dop_EEJ_T2 = self.clean_outliers(dataOut.Err_Dop_EEJ_T2)
1721 dataOut.Err_Dop_EEJ_T2 = self.clean_outliers(dataOut.Err_Dop_EEJ_T2)
1722 #print("Before data_snr: ", dataOut.data_snr)
1722 #print("Before data_snr: ", dataOut.data_snr)
1723 #dataOut.data_snr = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.data_snr)
1723 #dataOut.data_snr = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.data_snr)
1724 dataOut.snl = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.snl)
1724 dataOut.snl = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.snl)
1725
1725
1726 #print("After data_snr: ", dataOut.data_snr)
1726 #print("After data_snr: ", dataOut.data_snr)
1727 dataOut.mode = mode
1727 dataOut.mode = mode
1728 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.Dop_EEJ_T1)) #Si todos los valores son NaN no se prosigue
1728 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.Dop_EEJ_T1)) #Si todos los valores son NaN no se prosigue
1729 ###dataOut.flagNoData = False #Descomentar solo para ploteo sino mantener comentado (para guardado)
1729 ###dataOut.flagNoData = False #Descomentar solo para ploteo sino mantener comentado (para guardado)
1730
1730
1731 return dataOut
1731 return dataOut
1732
1732
1733 class Gaussian_Windowed(Operation):
1733 class Gaussian_Windowed(Operation):
1734 '''
1734 '''
1735 Written by R. Flores
1735 Written by R. Flores
1736 '''
1736 '''
1737 def __init__(self):
1737 def __init__(self):
1738 Operation.__init__(self)
1738 Operation.__init__(self)
1739
1739
1740 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1740 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1741 from scipy.optimize import curve_fit,fmin
1741 from scipy.optimize import curve_fit,fmin
1742
1742
1743 def gaussian(x, a, b, c, d):
1743 def gaussian(x, a, b, c, d):
1744 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
1744 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
1745 return val
1745 return val
1746
1746
1747 def R_gaussian(x, a, b, c):
1747 def R_gaussian(x, a, b, c):
1748 N = int(numpy.shape(x)[0])
1748 N = int(numpy.shape(x)[0])
1749 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1749 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1750 return val
1750 return val
1751
1751
1752 def T(x,N):
1752 def T(x,N):
1753 T = 1-abs(x)/N
1753 T = 1-abs(x)/N
1754 return T
1754 return T
1755
1755
1756 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1756 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1757
1757
1758 N = int(numpy.shape(x)[0])
1758 N = int(numpy.shape(x)[0])
1759
1759
1760 x_max = x[-1]
1760 x_max = x[-1]
1761
1761
1762 x_pos = x[nFFTPoints:]
1762 x_pos = x[nFFTPoints:]
1763 x_neg = x[:nFFTPoints]
1763 x_neg = x[:nFFTPoints]
1764 #print([int(nFFTPoints/2))
1764 #print([int(nFFTPoints/2))
1765 #print("x: ", x)
1765 #print("x: ", x)
1766 #print("x_neg: ", x_neg)
1766 #print("x_neg: ", x_neg)
1767 #print("x_pos: ", x_pos)
1767 #print("x_pos: ", x_pos)
1768
1768
1769
1769
1770 R_T_neg_1 = R_gaussian(x, a, b, c)[:nFFTPoints]*T(x_neg,-x[0])
1770 R_T_neg_1 = R_gaussian(x, a, b, c)[:nFFTPoints]*T(x_neg,-x[0])
1771 R_T_pos_1 = R_gaussian(x, a, b, c)[nFFTPoints:]*T(x_pos,x[-1])
1771 R_T_pos_1 = R_gaussian(x, a, b, c)[nFFTPoints:]*T(x_pos,x[-1])
1772 #print(T(x_pos,x[-1]),x_pos,x[-1])
1772 #print(T(x_pos,x[-1]),x_pos,x[-1])
1773 #print(R_T_neg_1.shape,R_T_pos_1.shape)
1773 #print(R_T_neg_1.shape,R_T_pos_1.shape)
1774 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1774 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1775 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1775 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1776 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1776 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1777 max_val_1 = numpy.max(R_T_spc_1)
1777 max_val_1 = numpy.max(R_T_spc_1)
1778 R_T_spc_1 = R_T_spc_1*a/max_val_1
1778 R_T_spc_1 = R_T_spc_1*a/max_val_1
1779
1779
1780 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1780 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1781 R_T_d_neg = R_T_d[:nFFTPoints]*T(x_neg,-x[0])
1781 R_T_d_neg = R_T_d[:nFFTPoints]*T(x_neg,-x[0])
1782 R_T_d_pos = R_T_d[nFFTPoints:]*T(x_pos,x[-1])
1782 R_T_d_pos = R_T_d[nFFTPoints:]*T(x_pos,x[-1])
1783 R_T_d_sum = R_T_d_pos + R_T_d_neg
1783 R_T_d_sum = R_T_d_pos + R_T_d_neg
1784 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1784 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1785 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1785 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1786
1786
1787 R_T_final = R_T_spc_1 + R_T_spc_3
1787 R_T_final = R_T_spc_1 + R_T_spc_3
1788
1788
1789 return R_T_final
1789 return R_T_final
1790
1790
1791 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1791 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1792
1792
1793 from scipy.stats import norm
1793 from scipy.stats import norm
1794 mean,std=norm.fit(spc)
1794 mean,std=norm.fit(spc)
1795
1795
1796 # estimate starting values from the data
1796 # estimate starting values from the data
1797 a = A
1797 a = A
1798 b = B
1798 b = B
1799 c = C#numpy.std(spc)
1799 c = C#numpy.std(spc)
1800 d = D
1800 d = D
1801 #'''
1801 #'''
1802 #ippSeconds = 250*20*1.e-6/3
1802 #ippSeconds = 250*20*1.e-6/3
1803
1803
1804 #x_t = ippSeconds * (numpy.arange(nFFTPoints) - nFFTPoints / 2.)
1804 #x_t = ippSeconds * (numpy.arange(nFFTPoints) - nFFTPoints / 2.)
1805
1805
1806 #x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1806 #x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1807 #print("x_t: ", x_t)
1807 #print("x_t: ", x_t)
1808 #print("nFFTPoints: ", nFFTPoints)
1808 #print("nFFTPoints: ", nFFTPoints)
1809 x_vel = numpy.linspace(x[0],x[-1],int(2*nFFTPoints))
1809 x_vel = numpy.linspace(x[0],x[-1],int(2*nFFTPoints))
1810 #print("x_vel: ", x_vel)
1810 #print("x_vel: ", x_vel)
1811 #x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1811 #x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1812 #x_freq = numpy.fft.fftshift(x_freq)
1812 #x_freq = numpy.fft.fftshift(x_freq)
1813 #'''
1813 #'''
1814 # define a least squares function to optimize
1814 # define a least squares function to optimize
1815 def minfunc(params):
1815 def minfunc(params):
1816 #print("y.shape: ", numpy.shape(y))
1816 #print("y.shape: ", numpy.shape(y))
1817 return sum((y-R_T_spc_fun(x_vel,params[0],params[1],params[2],params[3],nFFTPoints))**2/1)#y**2)
1817 return sum((y-R_T_spc_fun(x_vel,params[0],params[1],params[2],params[3],nFFTPoints))**2/1)#y**2)
1818
1818
1819 # fit
1819 # fit
1820
1820
1821 popt_full = fmin(minfunc,[a,b,c,d], disp=False)
1821 popt_full = fmin(minfunc,[a,b,c,d], disp=False)
1822 #print("nIter", popt_full[2])
1822 #print("nIter", popt_full[2])
1823 popt = popt_full#[0]
1823 popt = popt_full#[0]
1824
1824
1825 fun = gaussian(x, popt[0], popt[1], popt[2], popt[3])
1825 fun = gaussian(x, popt[0], popt[1], popt[2], popt[3])
1826
1826
1827 #return R_T_spc_fun(x_t,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]
1827 #return R_T_spc_fun(x_t,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]
1828 return fun, popt[0], popt[1], popt[2], popt[3]
1828 return fun, popt[0], popt[1], popt[2], popt[3]
1829
1829
1830 def run(self, dataOut):
1830 def run(self, dataOut):
1831
1831
1832 from scipy.signal import medfilt
1832 from scipy.signal import medfilt
1833 import matplotlib.pyplot as plt
1833 import matplotlib.pyplot as plt
1834 dataOut.moments = numpy.ones((dataOut.nChannels,4,dataOut.nHeights))*numpy.NAN
1834 dataOut.moments = numpy.ones((dataOut.nChannels,4,dataOut.nHeights))*numpy.NAN
1835 dataOut.VelRange = dataOut.getVelRange(0)
1835 dataOut.VelRange = dataOut.getVelRange(0)
1836 for nChannel in range(dataOut.nChannels):
1836 for nChannel in range(dataOut.nChannels):
1837 for hei in range(dataOut.heightList.shape[0]):
1837 for hei in range(dataOut.heightList.shape[0]):
1838 #print("ipp: ", dataOut.ippSeconds)
1838 #print("ipp: ", dataOut.ippSeconds)
1839 spc = numpy.copy(dataOut.data_spc[nChannel,:,hei])
1839 spc = numpy.copy(dataOut.data_spc[nChannel,:,hei])
1840
1840
1841 #print(VelRange)
1841 #print(VelRange)
1842 #print(dataOut.getFreqRange(64))
1842 #print(dataOut.getFreqRange(64))
1843 spcm = medfilt(spc,11)
1843 spcm = medfilt(spc,11)
1844 spc_max = numpy.max(spcm)
1844 spc_max = numpy.max(spcm)
1845 dop1_x0 = dataOut.VelRange[numpy.argmax(spcm)]
1845 dop1_x0 = dataOut.VelRange[numpy.argmax(spcm)]
1846 D = numpy.min(spcm)
1846 D = numpy.min(spcm)
1847
1847
1848 fun, A, B, C, D = self.windowing_single(spc,dataOut.VelRange,spc_max,dop1_x0,abs(dop1_x0),D,dataOut.nFFTPoints)
1848 fun, A, B, C, D = self.windowing_single(spc,dataOut.VelRange,spc_max,dop1_x0,abs(dop1_x0),D,dataOut.nFFTPoints)
1849 dataOut.moments[nChannel,0,hei] = A
1849 dataOut.moments[nChannel,0,hei] = A
1850 dataOut.moments[nChannel,1,hei] = B
1850 dataOut.moments[nChannel,1,hei] = B
1851 dataOut.moments[nChannel,2,hei] = C
1851 dataOut.moments[nChannel,2,hei] = C
1852 dataOut.moments[nChannel,3,hei] = D
1852 dataOut.moments[nChannel,3,hei] = D
1853 '''
1853 '''
1854 plt.figure()
1854 plt.figure()
1855 plt.plot(VelRange,spc,marker='*',linestyle='')
1855 plt.plot(VelRange,spc,marker='*',linestyle='')
1856 plt.plot(VelRange,fun)
1856 plt.plot(VelRange,fun)
1857 plt.title(dataOut.heightList[hei])
1857 plt.title(dataOut.heightList[hei])
1858 plt.show()
1858 plt.show()
1859 '''
1859 '''
1860
1860
1861 return dataOut
1861 return dataOut
1862
1862
1863 class PrecipitationProc(Operation):
1863 class PrecipitationProc(Operation):
1864
1864
1865 '''
1865 '''
1866 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
1866 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
1867
1867
1868 Input:
1868 Input:
1869 self.dataOut.data_pre : SelfSpectra
1869 self.dataOut.data_pre : SelfSpectra
1870
1870
1871 Output:
1871 Output:
1872
1872
1873 self.dataOut.data_output : Reflectivity factor, rainfall Rate
1873 self.dataOut.data_output : Reflectivity factor, rainfall Rate
1874
1874
1875
1875
1876 Parameters affected:
1876 Parameters affected:
1877 '''
1877 '''
1878
1878
1879 def __init__(self):
1879 def __init__(self):
1880 Operation.__init__(self)
1880 Operation.__init__(self)
1881 self.i=0
1881 self.i=0
1882
1882
1883 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
1883 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
1884 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30,
1884 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30,
1885 channel=None):
1885 channel=None):
1886
1886
1887 # print ('Entering PrecepitationProc ... ')
1887 # print ('Entering PrecepitationProc ... ')
1888
1888
1889 if radar == "MIRA35C" :
1889 if radar == "MIRA35C" :
1890
1890
1891 self.spc = dataOut.data_pre[0].copy()
1891 self.spc = dataOut.data_pre[0].copy()
1892 self.Num_Hei = self.spc.shape[2]
1892 self.Num_Hei = self.spc.shape[2]
1893 self.Num_Bin = self.spc.shape[1]
1893 self.Num_Bin = self.spc.shape[1]
1894 self.Num_Chn = self.spc.shape[0]
1894 self.Num_Chn = self.spc.shape[0]
1895 Ze = self.dBZeMODE2(dataOut)
1895 Ze = self.dBZeMODE2(dataOut)
1896
1896
1897 else:
1897 else:
1898
1898
1899 self.spc = dataOut.data_pre[0].copy()
1899 self.spc = dataOut.data_pre[0].copy()
1900
1900
1901 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
1901 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
1902 self.spc[:,:,0:7]= numpy.NaN
1902 self.spc[:,:,0:7]= numpy.NaN
1903
1903
1904 self.Num_Hei = self.spc.shape[2]
1904 self.Num_Hei = self.spc.shape[2]
1905 self.Num_Bin = self.spc.shape[1]
1905 self.Num_Bin = self.spc.shape[1]
1906 self.Num_Chn = self.spc.shape[0]
1906 self.Num_Chn = self.spc.shape[0]
1907
1907
1908 VelRange = dataOut.spc_range[2]
1908 VelRange = dataOut.spc_range[2]
1909
1909
1910 ''' Se obtiene la constante del RADAR '''
1910 ''' Se obtiene la constante del RADAR '''
1911
1911
1912 self.Pt = Pt
1912 self.Pt = Pt
1913 self.Gt = Gt
1913 self.Gt = Gt
1914 self.Gr = Gr
1914 self.Gr = Gr
1915 self.Lambda = Lambda
1915 self.Lambda = Lambda
1916 self.aL = aL
1916 self.aL = aL
1917 self.tauW = tauW
1917 self.tauW = tauW
1918 self.ThetaT = ThetaT
1918 self.ThetaT = ThetaT
1919 self.ThetaR = ThetaR
1919 self.ThetaR = ThetaR
1920 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
1920 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
1921 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
1921 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
1922 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
1922 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
1923
1923
1924 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1924 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1925 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
1925 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
1926 RadarConstant = 10e-26 * Numerator / Denominator #
1926 RadarConstant = 10e-26 * Numerator / Denominator #
1927 ExpConstant = 10**(40/10) #Constante Experimental
1927 ExpConstant = 10**(40/10) #Constante Experimental
1928
1928
1929 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
1929 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
1930 for i in range(self.Num_Chn):
1930 for i in range(self.Num_Chn):
1931 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
1931 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
1932 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
1932 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
1933
1933
1934 if channel is None:
1934 if channel is None:
1935 SPCmean = numpy.mean(SignalPower, 0)
1935 SPCmean = numpy.mean(SignalPower, 0)
1936 else:
1936 else:
1937 SPCmean = SignalPower[channel]
1937 SPCmean = SignalPower[channel]
1938 Pr = SPCmean[:,:]/dataOut.normFactor
1938 Pr = SPCmean[:,:]/dataOut.normFactor
1939
1939
1940 # Declaring auxiliary variables
1940 # Declaring auxiliary variables
1941 Range = dataOut.heightList*1000. #Range in m
1941 Range = dataOut.heightList*1000. #Range in m
1942 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
1942 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
1943 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
1943 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
1944 zMtrx = rMtrx+Altitude
1944 zMtrx = rMtrx+Altitude
1945 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
1945 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
1946 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
1946 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
1947
1947
1948 # height dependence to air density Foote and Du Toit (1969)
1948 # height dependence to air density Foote and Du Toit (1969)
1949 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
1949 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
1950 VMtrx = VelMtrx / delv_z #Normalized velocity
1950 VMtrx = VelMtrx / delv_z #Normalized velocity
1951 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
1951 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
1952 # Diameter is related to the fall speed of falling drops
1952 # Diameter is related to the fall speed of falling drops
1953 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
1953 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
1954 # Only valid for D>= 0.16 mm
1954 # Only valid for D>= 0.16 mm
1955 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
1955 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
1956
1956
1957 #Calculate Radar Reflectivity ETAn
1957 #Calculate Radar Reflectivity ETAn
1958 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
1958 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
1959 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
1959 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
1960 # Radar Cross Section
1960 # Radar Cross Section
1961 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
1961 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
1962 # Drop Size Distribution
1962 # Drop Size Distribution
1963 DSD = ETAn / sigmaD
1963 DSD = ETAn / sigmaD
1964 # Equivalente Reflectivy
1964 # Equivalente Reflectivy
1965 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
1965 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
1966 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
1966 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
1967 # RainFall Rate
1967 # RainFall Rate
1968 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
1968 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
1969
1969
1970 # Censoring the data
1970 # Censoring the data
1971 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
1971 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
1972 SNRth = 10**(SNRdBlimit/10) #-30dB
1972 SNRth = 10**(SNRdBlimit/10) #-30dB
1973 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
1973 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
1974 W = numpy.nanmean(dataOut.data_dop,0)
1974 W = numpy.nanmean(dataOut.data_dop,0)
1975 W[novalid] = numpy.NaN
1975 W[novalid] = numpy.NaN
1976 Ze_org[novalid] = numpy.NaN
1976 Ze_org[novalid] = numpy.NaN
1977 RR[novalid] = numpy.NaN
1977 RR[novalid] = numpy.NaN
1978
1978
1979 dataOut.data_output = RR[8]
1979 dataOut.data_output = RR[8]
1980 dataOut.data_param = numpy.ones([3,self.Num_Hei])
1980 dataOut.data_param = numpy.ones([3,self.Num_Hei])
1981 dataOut.channelList = [0,1,2]
1981 dataOut.channelList = [0,1,2]
1982
1982
1983 dataOut.data_param[0]=10*numpy.log10(Ze_org)
1983 dataOut.data_param[0]=10*numpy.log10(Ze_org)
1984 dataOut.data_param[1]=-W
1984 dataOut.data_param[1]=-W
1985 dataOut.data_param[2]=RR
1985 dataOut.data_param[2]=RR
1986
1986
1987 # print ('Leaving PrecepitationProc ... ')
1987 # print ('Leaving PrecepitationProc ... ')
1988 return dataOut
1988 return dataOut
1989
1989
1990 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
1990 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
1991
1991
1992 NPW = dataOut.NPW
1992 NPW = dataOut.NPW
1993 COFA = dataOut.COFA
1993 COFA = dataOut.COFA
1994
1994
1995 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
1995 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
1996 RadarConst = dataOut.RadarConst
1996 RadarConst = dataOut.RadarConst
1997 #frequency = 34.85*10**9
1997 #frequency = 34.85*10**9
1998
1998
1999 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1999 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
2000 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
2000 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
2001
2001
2002 ETA = numpy.sum(SNR,1)
2002 ETA = numpy.sum(SNR,1)
2003
2003
2004 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
2004 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
2005
2005
2006 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
2006 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
2007
2007
2008 for r in range(self.Num_Hei):
2008 for r in range(self.Num_Hei):
2009
2009
2010 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
2010 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
2011 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
2011 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
2012
2012
2013 return Ze
2013 return Ze
2014
2014
2015 # def GetRadarConstant(self):
2015 # def GetRadarConstant(self):
2016 #
2016 #
2017 # """
2017 # """
2018 # Constants:
2018 # Constants:
2019 #
2019 #
2020 # Pt: Transmission Power dB 5kW 5000
2020 # Pt: Transmission Power dB 5kW 5000
2021 # Gt: Transmission Gain dB 24.7 dB 295.1209
2021 # Gt: Transmission Gain dB 24.7 dB 295.1209
2022 # Gr: Reception Gain dB 18.5 dB 70.7945
2022 # Gr: Reception Gain dB 18.5 dB 70.7945
2023 # Lambda: Wavelenght m 0.6741 m 0.6741
2023 # Lambda: Wavelenght m 0.6741 m 0.6741
2024 # aL: Attenuation loses dB 4dB 2.5118
2024 # aL: Attenuation loses dB 4dB 2.5118
2025 # tauW: Width of transmission pulse s 4us 4e-6
2025 # tauW: Width of transmission pulse s 4us 4e-6
2026 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
2026 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
2027 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
2027 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
2028 #
2028 #
2029 # """
2029 # """
2030 #
2030 #
2031 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
2031 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
2032 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
2032 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
2033 # RadarConstant = Numerator / Denominator
2033 # RadarConstant = Numerator / Denominator
2034 #
2034 #
2035 # return RadarConstant
2035 # return RadarConstant
2036
2036
2037
2037
2038 class FullSpectralAnalysis(Operation):
2038 class FullSpectralAnalysis(Operation):
2039
2039
2040 """
2040 """
2041 Function that implements Full Spectral Analysis technique.
2041 Function that implements Full Spectral Analysis technique.
2042
2042
2043 Input:
2043 Input:
2044 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
2044 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
2045 self.dataOut.groupList : Pairlist of channels
2045 self.dataOut.groupList : Pairlist of channels
2046 self.dataOut.ChanDist : Physical distance between receivers
2046 self.dataOut.ChanDist : Physical distance between receivers
2047
2047
2048
2048
2049 Output:
2049 Output:
2050
2050
2051 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
2051 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
2052
2052
2053
2053
2054 Parameters affected: Winds, height range, SNR
2054 Parameters affected: Winds, height range, SNR
2055
2055
2056 """
2056 """
2057 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
2057 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
2058 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
2058 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
2059
2059
2060 spc = dataOut.data_pre[0].copy()
2060 spc = dataOut.data_pre[0].copy()
2061 cspc = dataOut.data_pre[1]
2061 cspc = dataOut.data_pre[1]
2062 nHeights = spc.shape[2]
2062 nHeights = spc.shape[2]
2063
2063
2064 # first_height = 0.75 #km (ref: data header 20170822)
2064 # first_height = 0.75 #km (ref: data header 20170822)
2065 # resolution_height = 0.075 #km
2065 # resolution_height = 0.075 #km
2066 '''
2066 '''
2067 finding height range. check this when radar parameters are changed!
2067 finding height range. check this when radar parameters are changed!
2068 '''
2068 '''
2069 if maxheight is not None:
2069 if maxheight is not None:
2070 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
2070 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
2071 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
2071 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
2072 else:
2072 else:
2073 range_max = nHeights
2073 range_max = nHeights
2074 if minheight is not None:
2074 if minheight is not None:
2075 # range_min = int((minheight - first_height) / resolution_height) # theoretical
2075 # range_min = int((minheight - first_height) / resolution_height) # theoretical
2076 range_min = int(13.26 * minheight - 5) # empirical, works better
2076 range_min = int(13.26 * minheight - 5) # empirical, works better
2077 if range_min < 0:
2077 if range_min < 0:
2078 range_min = 0
2078 range_min = 0
2079 else:
2079 else:
2080 range_min = 0
2080 range_min = 0
2081
2081
2082 pairsList = dataOut.groupList
2082 pairsList = dataOut.groupList
2083 if dataOut.ChanDist is not None :
2083 if dataOut.ChanDist is not None :
2084 ChanDist = dataOut.ChanDist
2084 ChanDist = dataOut.ChanDist
2085 else:
2085 else:
2086 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
2086 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
2087
2087
2088 # 4 variables: zonal, meridional, vertical, and average SNR
2088 # 4 variables: zonal, meridional, vertical, and average SNR
2089 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
2089 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
2090 velocityX = numpy.zeros([nHeights]) * numpy.NaN
2090 velocityX = numpy.zeros([nHeights]) * numpy.NaN
2091 velocityY = numpy.zeros([nHeights]) * numpy.NaN
2091 velocityY = numpy.zeros([nHeights]) * numpy.NaN
2092 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
2092 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
2093
2093
2094 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
2094 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
2095
2095
2096 '''***********************************************WIND ESTIMATION**************************************'''
2096 '''***********************************************WIND ESTIMATION**************************************'''
2097 for Height in range(nHeights):
2097 for Height in range(nHeights):
2098
2098
2099 if Height >= range_min and Height < range_max:
2099 if Height >= range_min and Height < range_max:
2100 # error_code will be useful in future analysis
2100 # error_code will be useful in future analysis
2101 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
2101 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
2102 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
2102 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
2103
2103
2104 if abs(Vzon) < 100. and abs(Vmer) < 100.:
2104 if abs(Vzon) < 100. and abs(Vmer) < 100.:
2105 velocityX[Height] = Vzon
2105 velocityX[Height] = Vzon
2106 velocityY[Height] = -Vmer
2106 velocityY[Height] = -Vmer
2107 velocityZ[Height] = Vver
2107 velocityZ[Height] = Vver
2108
2108
2109 # Censoring data with SNR threshold
2109 # Censoring data with SNR threshold
2110 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
2110 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
2111
2111
2112 data_param[0] = velocityX
2112 data_param[0] = velocityX
2113 data_param[1] = velocityY
2113 data_param[1] = velocityY
2114 data_param[2] = velocityZ
2114 data_param[2] = velocityZ
2115 data_param[3] = dbSNR
2115 data_param[3] = dbSNR
2116 dataOut.data_param = data_param
2116 dataOut.data_param = data_param
2117 return dataOut
2117 return dataOut
2118
2118
2119 def moving_average(self,x, N=2):
2119 def moving_average(self,x, N=2):
2120 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
2120 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
2121 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
2121 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
2122
2122
2123 def gaus(self,xSamples,Amp,Mu,Sigma):
2123 def gaus(self,xSamples,Amp,Mu,Sigma):
2124 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
2124 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
2125
2125
2126 def Moments(self, ySamples, xSamples):
2126 def Moments(self, ySamples, xSamples):
2127 Power = numpy.nanmean(ySamples) # Power, 0th Moment
2127 Power = numpy.nanmean(ySamples) # Power, 0th Moment
2128 yNorm = ySamples / numpy.nansum(ySamples)
2128 yNorm = ySamples / numpy.nansum(ySamples)
2129 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
2129 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
2130 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
2130 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
2131 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
2131 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
2132 return numpy.array([Power,RadVel,StdDev])
2132 return numpy.array([Power,RadVel,StdDev])
2133
2133
2134 def StopWindEstimation(self, error_code):
2134 def StopWindEstimation(self, error_code):
2135 Vzon = numpy.NaN
2135 Vzon = numpy.NaN
2136 Vmer = numpy.NaN
2136 Vmer = numpy.NaN
2137 Vver = numpy.NaN
2137 Vver = numpy.NaN
2138 return Vzon, Vmer, Vver, error_code
2138 return Vzon, Vmer, Vver, error_code
2139
2139
2140 def AntiAliasing(self, interval, maxstep):
2140 def AntiAliasing(self, interval, maxstep):
2141 """
2141 """
2142 function to prevent errors from aliased values when computing phaseslope
2142 function to prevent errors from aliased values when computing phaseslope
2143 """
2143 """
2144 antialiased = numpy.zeros(len(interval))
2144 antialiased = numpy.zeros(len(interval))
2145 copyinterval = interval.copy()
2145 copyinterval = interval.copy()
2146
2146
2147 antialiased[0] = copyinterval[0]
2147 antialiased[0] = copyinterval[0]
2148
2148
2149 for i in range(1,len(antialiased)):
2149 for i in range(1,len(antialiased)):
2150 step = interval[i] - interval[i-1]
2150 step = interval[i] - interval[i-1]
2151 if step > maxstep:
2151 if step > maxstep:
2152 copyinterval -= 2*numpy.pi
2152 copyinterval -= 2*numpy.pi
2153 antialiased[i] = copyinterval[i]
2153 antialiased[i] = copyinterval[i]
2154 elif step < maxstep*(-1):
2154 elif step < maxstep*(-1):
2155 copyinterval += 2*numpy.pi
2155 copyinterval += 2*numpy.pi
2156 antialiased[i] = copyinterval[i]
2156 antialiased[i] = copyinterval[i]
2157 else:
2157 else:
2158 antialiased[i] = copyinterval[i].copy()
2158 antialiased[i] = copyinterval[i].copy()
2159
2159
2160 return antialiased
2160 return antialiased
2161
2161
2162 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
2162 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
2163 """
2163 """
2164 Function that Calculates Zonal, Meridional and Vertical wind velocities.
2164 Function that Calculates Zonal, Meridional and Vertical wind velocities.
2165 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
2165 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
2166
2166
2167 Input:
2167 Input:
2168 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
2168 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
2169 pairsList : Pairlist of channels
2169 pairsList : Pairlist of channels
2170 ChanDist : array of xi_ij and eta_ij
2170 ChanDist : array of xi_ij and eta_ij
2171 Height : height at which data is processed
2171 Height : height at which data is processed
2172 noise : noise in [channels] format for specific height
2172 noise : noise in [channels] format for specific height
2173 Abbsisarange : range of the frequencies or velocities
2173 Abbsisarange : range of the frequencies or velocities
2174 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
2174 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
2175
2175
2176 Output:
2176 Output:
2177 Vzon, Vmer, Vver : wind velocities
2177 Vzon, Vmer, Vver : wind velocities
2178 error_code : int that states where code is terminated
2178 error_code : int that states where code is terminated
2179
2179
2180 0 : no error detected
2180 0 : no error detected
2181 1 : Gaussian of mean spc exceeds widthlimit
2181 1 : Gaussian of mean spc exceeds widthlimit
2182 2 : no Gaussian of mean spc found
2182 2 : no Gaussian of mean spc found
2183 3 : SNR to low or velocity to high -> prec. e.g.
2183 3 : SNR to low or velocity to high -> prec. e.g.
2184 4 : at least one Gaussian of cspc exceeds widthlimit
2184 4 : at least one Gaussian of cspc exceeds widthlimit
2185 5 : zero out of three cspc Gaussian fits converged
2185 5 : zero out of three cspc Gaussian fits converged
2186 6 : phase slope fit could not be found
2186 6 : phase slope fit could not be found
2187 7 : arrays used to fit phase have different length
2187 7 : arrays used to fit phase have different length
2188 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
2188 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
2189
2189
2190 """
2190 """
2191
2191
2192 error_code = 0
2192 error_code = 0
2193
2193
2194 nChan = spc.shape[0]
2194 nChan = spc.shape[0]
2195 nProf = spc.shape[1]
2195 nProf = spc.shape[1]
2196 nPair = cspc.shape[0]
2196 nPair = cspc.shape[0]
2197
2197
2198 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
2198 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
2199 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
2199 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
2200 phase = numpy.zeros([nPair, nProf]) # phase between channels
2200 phase = numpy.zeros([nPair, nProf]) # phase between channels
2201 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
2201 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
2202 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
2202 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
2203 xFrec = AbbsisaRange[0][:-1] # frequency range
2203 xFrec = AbbsisaRange[0][:-1] # frequency range
2204 xVel = AbbsisaRange[2][:-1] # velocity range
2204 xVel = AbbsisaRange[2][:-1] # velocity range
2205 xSamples = xFrec # the frequency range is taken
2205 xSamples = xFrec # the frequency range is taken
2206 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
2206 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
2207
2207
2208 # only consider velocities with in NegativeLimit and PositiveLimit
2208 # only consider velocities with in NegativeLimit and PositiveLimit
2209 if (NegativeLimit is None):
2209 if (NegativeLimit is None):
2210 NegativeLimit = numpy.min(xVel)
2210 NegativeLimit = numpy.min(xVel)
2211 if (PositiveLimit is None):
2211 if (PositiveLimit is None):
2212 PositiveLimit = numpy.max(xVel)
2212 PositiveLimit = numpy.max(xVel)
2213 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
2213 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
2214 xSamples_zoom = xSamples[xvalid]
2214 xSamples_zoom = xSamples[xvalid]
2215
2215
2216 '''Getting Eij and Nij'''
2216 '''Getting Eij and Nij'''
2217 Xi01, Xi02, Xi12 = ChanDist[:,0]
2217 Xi01, Xi02, Xi12 = ChanDist[:,0]
2218 Eta01, Eta02, Eta12 = ChanDist[:,1]
2218 Eta01, Eta02, Eta12 = ChanDist[:,1]
2219
2219
2220 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
2220 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
2221 widthlimit = 10
2221 widthlimit = 10
2222 '''************************* SPC is normalized ********************************'''
2222 '''************************* SPC is normalized ********************************'''
2223 spc_norm = spc.copy()
2223 spc_norm = spc.copy()
2224 # For each channel
2224 # For each channel
2225 for i in range(nChan):
2225 for i in range(nChan):
2226 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
2226 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
2227 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
2227 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
2228
2228
2229 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
2229 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
2230
2230
2231 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
2231 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
2232 you only fit the curve and don't need the absolute value of height for calculation,
2232 you only fit the curve and don't need the absolute value of height for calculation,
2233 only for estimation of width. for normalization of cross spectra, you need initial,
2233 only for estimation of width. for normalization of cross spectra, you need initial,
2234 unnormalized self-spectra With noise.
2234 unnormalized self-spectra With noise.
2235
2235
2236 Technically, you don't even need to normalize the self-spectra, as you only need the
2236 Technically, you don't even need to normalize the self-spectra, as you only need the
2237 width of the peak. However, it was left this way. Note that the normalization has a flaw:
2237 width of the peak. However, it was left this way. Note that the normalization has a flaw:
2238 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
2238 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
2239 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
2239 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
2240 """
2240 """
2241 # initial conditions
2241 # initial conditions
2242 popt = [1e-10,0,1e-10]
2242 popt = [1e-10,0,1e-10]
2243 # Spectra average
2243 # Spectra average
2244 SPCMean = numpy.average(SPC_Samples,0)
2244 SPCMean = numpy.average(SPC_Samples,0)
2245 # Moments in frequency
2245 # Moments in frequency
2246 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
2246 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
2247
2247
2248 # Gauss Fit SPC in frequency domain
2248 # Gauss Fit SPC in frequency domain
2249 if dbSNR > SNRlimit: # only if SNR > SNRth
2249 if dbSNR > SNRlimit: # only if SNR > SNRth
2250 try:
2250 try:
2251 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
2251 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
2252 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
2252 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
2253 return self.StopWindEstimation(error_code = 1)
2253 return self.StopWindEstimation(error_code = 1)
2254 FitGauss = self.gaus(xSamples_zoom,*popt)
2254 FitGauss = self.gaus(xSamples_zoom,*popt)
2255 except :#RuntimeError:
2255 except :#RuntimeError:
2256 return self.StopWindEstimation(error_code = 2)
2256 return self.StopWindEstimation(error_code = 2)
2257 else:
2257 else:
2258 return self.StopWindEstimation(error_code = 3)
2258 return self.StopWindEstimation(error_code = 3)
2259
2259
2260 '''***************************** CSPC Normalization *************************
2260 '''***************************** CSPC Normalization *************************
2261 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
2261 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
2262 influence the norm which is not desired. First, a range is identified where the
2262 influence the norm which is not desired. First, a range is identified where the
2263 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
2263 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
2264 around it gets cut off and values replaced by mean determined by the boundary
2264 around it gets cut off and values replaced by mean determined by the boundary
2265 data -> sum_noise (spc is not normalized here, thats why the noise is important)
2265 data -> sum_noise (spc is not normalized here, thats why the noise is important)
2266
2266
2267 The sums are then added and multiplied by range/datapoints, because you need
2267 The sums are then added and multiplied by range/datapoints, because you need
2268 an integral and not a sum for normalization.
2268 an integral and not a sum for normalization.
2269
2269
2270 A norm is found according to Briggs 92.
2270 A norm is found according to Briggs 92.
2271 '''
2271 '''
2272 # for each pair
2272 # for each pair
2273 for i in range(nPair):
2273 for i in range(nPair):
2274 cspc_norm = cspc[i,:].copy()
2274 cspc_norm = cspc[i,:].copy()
2275 chan_index0 = pairsList[i][0]
2275 chan_index0 = pairsList[i][0]
2276 chan_index1 = pairsList[i][1]
2276 chan_index1 = pairsList[i][1]
2277 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
2277 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
2278 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
2278 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
2279
2279
2280 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
2280 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
2281 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
2281 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
2282 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
2282 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
2283
2283
2284 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
2284 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
2285 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
2285 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
2286
2286
2287 '''*******************************FIT GAUSS CSPC************************************'''
2287 '''*******************************FIT GAUSS CSPC************************************'''
2288 try:
2288 try:
2289 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
2289 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
2290 if popt01[2] > widthlimit: # CONDITION
2290 if popt01[2] > widthlimit: # CONDITION
2291 return self.StopWindEstimation(error_code = 4)
2291 return self.StopWindEstimation(error_code = 4)
2292 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
2292 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
2293 if popt02[2] > widthlimit: # CONDITION
2293 if popt02[2] > widthlimit: # CONDITION
2294 return self.StopWindEstimation(error_code = 4)
2294 return self.StopWindEstimation(error_code = 4)
2295 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
2295 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
2296 if popt12[2] > widthlimit: # CONDITION
2296 if popt12[2] > widthlimit: # CONDITION
2297 return self.StopWindEstimation(error_code = 4)
2297 return self.StopWindEstimation(error_code = 4)
2298
2298
2299 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
2299 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
2300 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
2300 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
2301 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
2301 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
2302 except:
2302 except:
2303 return self.StopWindEstimation(error_code = 5)
2303 return self.StopWindEstimation(error_code = 5)
2304
2304
2305
2305
2306 '''************* Getting Fij ***************'''
2306 '''************* Getting Fij ***************'''
2307 # x-axis point of the gaussian where the center is located from GaussFit of spectra
2307 # x-axis point of the gaussian where the center is located from GaussFit of spectra
2308 GaussCenter = popt[1]
2308 GaussCenter = popt[1]
2309 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
2309 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
2310 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
2310 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
2311
2311
2312 # Point where e^-1 is located in the gaussian
2312 # Point where e^-1 is located in the gaussian
2313 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
2313 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
2314 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
2314 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
2315 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
2315 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
2316 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
2316 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
2317
2317
2318 '''********** Taking frequency ranges from mean SPCs **********'''
2318 '''********** Taking frequency ranges from mean SPCs **********'''
2319 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
2319 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
2320 Range = numpy.empty(2)
2320 Range = numpy.empty(2)
2321 Range[0] = GaussCenter - GauWidth
2321 Range[0] = GaussCenter - GauWidth
2322 Range[1] = GaussCenter + GauWidth
2322 Range[1] = GaussCenter + GauWidth
2323 # Point in x-axis where the bandwidth is located (min:max)
2323 # Point in x-axis where the bandwidth is located (min:max)
2324 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
2324 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
2325 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
2325 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
2326 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
2326 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
2327 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
2327 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
2328 Range = numpy.array([ PointRangeMin, PointRangeMax ])
2328 Range = numpy.array([ PointRangeMin, PointRangeMax ])
2329 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
2329 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
2330
2330
2331 '''************************** Getting Phase Slope ***************************'''
2331 '''************************** Getting Phase Slope ***************************'''
2332 for i in range(nPair):
2332 for i in range(nPair):
2333 if len(FrecRange) > 5:
2333 if len(FrecRange) > 5:
2334 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
2334 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
2335 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
2335 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
2336 if len(FrecRange) == len(PhaseRange):
2336 if len(FrecRange) == len(PhaseRange):
2337 try:
2337 try:
2338 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
2338 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
2339 PhaseSlope[i] = slope
2339 PhaseSlope[i] = slope
2340 PhaseInter[i] = intercept
2340 PhaseInter[i] = intercept
2341 except:
2341 except:
2342 return self.StopWindEstimation(error_code = 6)
2342 return self.StopWindEstimation(error_code = 6)
2343 else:
2343 else:
2344 return self.StopWindEstimation(error_code = 7)
2344 return self.StopWindEstimation(error_code = 7)
2345 else:
2345 else:
2346 return self.StopWindEstimation(error_code = 8)
2346 return self.StopWindEstimation(error_code = 8)
2347
2347
2348 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
2348 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
2349
2349
2350 '''Getting constant C'''
2350 '''Getting constant C'''
2351 cC=(Fij*numpy.pi)**2
2351 cC=(Fij*numpy.pi)**2
2352
2352
2353 '''****** Getting constants F and G ******'''
2353 '''****** Getting constants F and G ******'''
2354 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
2354 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
2355 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
2355 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
2356 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
2356 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
2357 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
2357 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
2358 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
2358 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
2359 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
2359 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
2360 MijResults = numpy.array([MijResult1, MijResult2])
2360 MijResults = numpy.array([MijResult1, MijResult2])
2361 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
2361 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
2362
2362
2363 '''****** Getting constants A, B and H ******'''
2363 '''****** Getting constants A, B and H ******'''
2364 W01 = numpy.nanmax( FitGauss01 )
2364 W01 = numpy.nanmax( FitGauss01 )
2365 W02 = numpy.nanmax( FitGauss02 )
2365 W02 = numpy.nanmax( FitGauss02 )
2366 W12 = numpy.nanmax( FitGauss12 )
2366 W12 = numpy.nanmax( FitGauss12 )
2367
2367
2368 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
2368 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
2369 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
2369 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
2370 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
2370 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
2371 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
2371 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
2372
2372
2373 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
2373 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
2374 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
2374 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
2375
2375
2376 VxVy = numpy.array([[cA,cH],[cH,cB]])
2376 VxVy = numpy.array([[cA,cH],[cH,cB]])
2377 VxVyResults = numpy.array([-cF,-cG])
2377 VxVyResults = numpy.array([-cF,-cG])
2378 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
2378 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
2379 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
2379 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
2380 error_code = 0
2380 error_code = 0
2381
2381
2382 return Vzon, Vmer, Vver, error_code
2382 return Vzon, Vmer, Vver, error_code
2383
2383
2384 class SpectralMoments(Operation):
2384 class SpectralMoments(Operation):
2385
2385
2386 '''
2386 '''
2387 Function SpectralMoments()
2387 Function SpectralMoments()
2388
2388
2389 Calculates moments (power, mean, standard deviation) and SNR of the signal
2389 Calculates moments (power, mean, standard deviation) and SNR of the signal
2390
2390
2391 Type of dataIn: Spectra
2391 Type of dataIn: Spectra
2392
2392
2393 Configuration Parameters:
2393 Configuration Parameters:
2394
2394
2395 dirCosx : Cosine director in X axis
2395 dirCosx : Cosine director in X axis
2396 dirCosy : Cosine director in Y axis
2396 dirCosy : Cosine director in Y axis
2397
2397
2398 elevation :
2398 elevation :
2399 azimuth :
2399 azimuth :
2400
2400
2401 Input:
2401 Input:
2402 channelList : simple channel list to select e.g. [2,3,7]
2402 channelList : simple channel list to select e.g. [2,3,7]
2403 self.dataOut.data_pre : Spectral data
2403 self.dataOut.data_pre : Spectral data
2404 self.dataOut.abscissaList : List of frequencies
2404 self.dataOut.abscissaList : List of frequencies
2405 self.dataOut.noise : Noise level per channel
2405 self.dataOut.noise : Noise level per channel
2406
2406
2407 Affected:
2407 Affected:
2408 self.dataOut.moments : Parameters per channel
2408 self.dataOut.moments : Parameters per channel
2409 self.dataOut.data_snr : SNR per channel
2409 self.dataOut.data_snr : SNR per channel
2410
2410
2411 '''
2411 '''
2412
2412
2413 def run(self, dataOut, proc_type=0):
2413 def run(self, dataOut, proc_type=0):
2414
2414
2415 absc = dataOut.abscissaList[:-1]
2415 absc = dataOut.abscissaList[:-1]
2416 nChannel = dataOut.data_pre[0].shape[0]
2416 nChannel = dataOut.data_pre[0].shape[0]
2417 nHei = dataOut.data_pre[0].shape[2]
2417 nHei = dataOut.data_pre[0].shape[2]
2418 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
2418 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
2419
2419
2420 if proc_type == 1:
2420 if proc_type == 1:
2421 fwindow = numpy.zeros(absc.size) + 1
2421 fwindow = numpy.zeros(absc.size) + 1
2422 b=64
2422 b=64
2423 #b=16
2423 #b=16
2424 fwindow[0:absc.size//2 - b] = 0
2424 fwindow[0:absc.size//2 - b] = 0
2425 fwindow[absc.size//2 + b:] = 0
2425 fwindow[absc.size//2 + b:] = 0
2426 type1 = 1 # moments calculation & gaussean fitting
2426 type1 = 1 # moments calculation & gaussean fitting
2427 nProfiles = dataOut.nProfiles
2427 nProfiles = dataOut.nProfiles
2428 nCohInt = dataOut.nCohInt
2428 nCohInt = dataOut.nCohInt
2429 nIncohInt = dataOut.nIncohInt
2429 nIncohInt = dataOut.nIncohInt
2430 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
2430 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
2431 N = numpy.array(M / nIncohInt,dtype='float32')
2431 N = numpy.array(M / nIncohInt,dtype='float32')
2432 data = dataOut.data_pre[0] * N
2432 data = dataOut.data_pre[0] * N
2433 #noise = dataOut.noise * N
2433 #noise = dataOut.noise * N
2434 noise = numpy.zeros(nChannel)
2434 noise = numpy.zeros(nChannel)
2435 for ind in range(nChannel):
2435 for ind in range(nChannel):
2436 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
2436 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
2437 smooth=3
2437 smooth=3
2438 else:
2438 else:
2439 data = dataOut.data_pre[0]
2439 data = dataOut.data_pre[0]
2440 noise = dataOut.noise
2440 noise = dataOut.noise
2441 fwindow = None
2441 fwindow = None
2442 type1 = 0
2442 type1 = 0
2443 nIncohInt = None
2443 nIncohInt = None
2444 smooth=None
2444 smooth=None
2445
2445
2446 for ind in range(nChannel):
2446 for ind in range(nChannel):
2447 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, id_ch=ind)
2447 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, id_ch=ind)
2448
2448
2449 if proc_type == 1:
2449 if proc_type == 1:
2450 dataOut.moments = data_param[:,1:,:]
2450 dataOut.moments = data_param[:,1:,:]
2451 dataOut.data_dop = data_param[:,2]
2451 dataOut.data_dop = data_param[:,2]
2452 dataOut.data_width = data_param[:,1]
2452 dataOut.data_width = data_param[:,1]
2453 dataOut.data_snr = data_param[:,0]
2453 dataOut.data_snr = data_param[:,0]
2454 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
2454 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
2455 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
2455 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
2456 else:
2456 else:
2457 dataOut.moments = data_param[:,1:,:]
2457 dataOut.moments = data_param[:,1:,:]
2458 dataOut.data_snr = data_param[:,0]
2458 dataOut.data_snr = data_param[:,0]
2459 dataOut.data_pow = data_param[:,1]
2459 dataOut.data_pow = data_param[:,1]
2460 dataOut.data_dop = data_param[:,2]
2460 dataOut.data_dop = data_param[:,2]
2461 dataOut.data_width = data_param[:,3]
2461 dataOut.data_width = data_param[:,3]
2462 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
2462 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
2463
2463
2464 return dataOut
2464 return dataOut
2465
2465
2466 def __calculateMoments(self, oldspec, oldfreq, n0,
2466 def __calculateMoments(self, oldspec, oldfreq, n0,
2467 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,id_ch=0):
2467 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,id_ch=0):
2468
2468
2469 def __GAUSSWINFIT1(A, flagPDER=0):
2469 def __GAUSSWINFIT1(A, flagPDER=0):
2470 nonlocal truex, xvalid
2470 nonlocal truex, xvalid
2471 nparams = 4
2471 nparams = 4
2472 M=truex.size
2472 M=truex.size
2473 mm=numpy.arange(M,dtype='f4')
2473 mm=numpy.arange(M,dtype='f4')
2474 delta = numpy.zeros(M,dtype='f4')
2474 delta = numpy.zeros(M,dtype='f4')
2475 delta[0] = 1.0
2475 delta[0] = 1.0
2476 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
2476 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
2477 jj = -1j
2477 jj = -1j
2478 #if self.winauto is None: self.winauto = (1.0 - mm/M)
2478 #if self.winauto is None: self.winauto = (1.0 - mm/M)
2479 winauto = (1.0 - mm/M)
2479 winauto = (1.0 - mm/M)
2480 winauto = winauto/winauto.max() # Normalized to 1
2480 winauto = winauto/winauto.max() # Normalized to 1
2481 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
2481 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
2482 A[0] = numpy.abs(A[0])
2482 A[0] = numpy.abs(A[0])
2483 A[2] = numpy.abs(A[2])
2483 A[2] = numpy.abs(A[2])
2484 A[3] = numpy.abs(A[3])
2484 A[3] = numpy.abs(A[3])
2485 pi=numpy.array([numpy.pi],dtype='f4')[0]
2485 pi=numpy.array([numpy.pi],dtype='f4')[0]
2486 if A[2] != 0:
2486 if A[2] != 0:
2487 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
2487 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
2488 else:
2488 else:
2489 Z = mm*0.0
2489 Z = mm*0.0
2490 A[0] = 0.0
2490 A[0] = 0.0
2491 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
2491 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
2492 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
2492 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
2493 F = junkF[xvalid]
2493 F = junkF[xvalid]
2494 if flagPDER == 0: #NEED PARTIAL?
2494 if flagPDER == 0: #NEED PARTIAL?
2495 return F
2495 return F
2496 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
2496 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
2497 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
2497 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
2498 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
2498 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
2499 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
2499 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
2500 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
2500 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
2501 PDER = PDER[xvalid,:]
2501 PDER = PDER[xvalid,:]
2502 return F, PDER
2502 return F, PDER
2503
2503
2504 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
2504 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
2505 itmax=20, tol=None):
2505 itmax=20, tol=None):
2506 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
2506 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
2507 if tol == None:
2507 if tol == None:
2508 tol = numpy.array([1.e-3],dtype='f4')[0]
2508 tol = numpy.array([1.e-3],dtype='f4')[0]
2509 typ=a.dtype
2509 typ=a.dtype
2510 double = 1 if typ == numpy.float64 else 0
2510 double = 1 if typ == numpy.float64 else 0
2511 if typ != numpy.float32:
2511 if typ != numpy.float32:
2512 a=a.astype(numpy.float32) #Make params floating
2512 a=a.astype(numpy.float32) #Make params floating
2513 # if we will be estimating partial derivates then compute machine precision
2513 # if we will be estimating partial derivates then compute machine precision
2514 if FlagNoDerivative == 1:
2514 if FlagNoDerivative == 1:
2515 res=numpy.MachAr(float_conv=numpy.float32)
2515 res=numpy.MachAr(float_conv=numpy.float32)
2516 eps=numpy.sqrt(res.eps)
2516 eps=numpy.sqrt(res.eps)
2517
2517
2518 nterms = a.size # Number of parameters
2518 nterms = a.size # Number of parameters
2519 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
2519 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
2520 if nfree <= 0: print('Curvefit - not enough data points.')
2520 if nfree <= 0: print('Curvefit - not enough data points.')
2521 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
2521 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
2522 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
2522 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
2523 # Use diag method in python
2523 # Use diag method in python
2524 converge=1
2524 converge=1
2525
2525
2526 #Define the partial derivative array
2526 #Define the partial derivative array
2527 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
2527 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
2528
2528
2529 for Niter in range(itmax): #Iteration loop
2529 for Niter in range(itmax): #Iteration loop
2530
2530
2531 if FlagNoDerivative == 1:
2531 if FlagNoDerivative == 1:
2532 #Evaluate function and estimate partial derivatives
2532 #Evaluate function and estimate partial derivatives
2533 yfit = __GAUSSWINFIT1(a)
2533 yfit = __GAUSSWINFIT1(a)
2534 for term in range(nterms):
2534 for term in range(nterms):
2535 p=a.copy() # Copy current parameters
2535 p=a.copy() # Copy current parameters
2536 #Increment size for forward difference derivative
2536 #Increment size for forward difference derivative
2537 inc = eps * abs(p[term])
2537 inc = eps * abs(p[term])
2538 if inc == 0: inc = eps
2538 if inc == 0: inc = eps
2539 p[term] = p[term] + inc
2539 p[term] = p[term] + inc
2540 yfit1 = __GAUSSWINFIT1(p)
2540 yfit1 = __GAUSSWINFIT1(p)
2541 PDER[term,:] = (yfit1-yfit)/inc
2541 PDER[term,:] = (yfit1-yfit)/inc
2542 else:
2542 else:
2543 #The user's procedure will return partial derivatives
2543 #The user's procedure will return partial derivatives
2544 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
2544 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
2545
2545
2546 beta = numpy.dot(PDER,(y-yfit)*Weights)
2546 beta = numpy.dot(PDER,(y-yfit)*Weights)
2547 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
2547 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
2548 # save current values of return parameters
2548 # save current values of return parameters
2549 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
2549 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
2550 sigma = sigma1
2550 sigma = sigma1
2551
2551
2552 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
2552 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
2553 chisq = chisq1
2553 chisq = chisq1
2554 yfit1 = yfit
2554 yfit1 = yfit
2555 elev7=numpy.array([1.0e7],dtype='f4')[0]
2555 elev7=numpy.array([1.0e7],dtype='f4')[0]
2556 compara =numpy.sum(abs(y))/elev7/nfree
2556 compara =numpy.sum(abs(y))/elev7/nfree
2557 done_early = chisq1 < compara
2557 done_early = chisq1 < compara
2558
2558
2559 if done_early:
2559 if done_early:
2560 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2560 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2561 if done_early: Niter -= 1
2561 if done_early: Niter -= 1
2562 #save_tp(chisq,Niter,yfit)
2562 #save_tp(chisq,Niter,yfit)
2563 return yfit, a, converge, sigma, chisq # return result
2563 return yfit, a, converge, sigma, chisq # return result
2564 #c = numpy.dot(c, c) # this operator implemented at the next lines
2564 #c = numpy.dot(c, c) # this operator implemented at the next lines
2565 c_tmp = numpy.sqrt(numpy.diag(alpha))
2565 c_tmp = numpy.sqrt(numpy.diag(alpha))
2566 siz=len(c_tmp)
2566 siz=len(c_tmp)
2567 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
2567 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
2568 lambdaCount = 0
2568 lambdaCount = 0
2569 while True:
2569 while True:
2570 lambdaCount += 1
2570 lambdaCount += 1
2571 # Normalize alpha to have unit diagonal.
2571 # Normalize alpha to have unit diagonal.
2572 array = alpha / c
2572 array = alpha / c
2573 # Augment the diagonal.
2573 # Augment the diagonal.
2574 one=numpy.array([1.],dtype='f4')[0]
2574 one=numpy.array([1.],dtype='f4')[0]
2575 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
2575 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
2576 # Invert modified curvature matrix to find new parameters.
2576 # Invert modified curvature matrix to find new parameters.
2577 try:
2577 try:
2578 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
2578 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
2579 except Exception as e:
2579 except Exception as e:
2580 print(e)
2580 print(e)
2581 array[:]=numpy.NaN
2581 array[:]=numpy.NaN
2582
2582
2583 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
2583 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
2584 yfit = __GAUSSWINFIT1(b) # Evaluate function
2584 yfit = __GAUSSWINFIT1(b) # Evaluate function
2585 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
2585 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
2586 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
2586 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
2587 if (numpy.isfinite(chisq) == 0) or \
2587 if (numpy.isfinite(chisq) == 0) or \
2588 (lambdaCount > 30 and chisq >= chisq1):
2588 (lambdaCount > 30 and chisq >= chisq1):
2589 # Reject changes made this iteration, use old values.
2589 # Reject changes made this iteration, use old values.
2590 yfit = yfit1
2590 yfit = yfit1
2591 sigma = sigma1
2591 sigma = sigma1
2592 chisq = chisq1
2592 chisq = chisq1
2593 converge = 0
2593 converge = 0
2594 #print('Failed to converge.')
2594 #print('Failed to converge.')
2595 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2595 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2596 if done_early: Niter -= 1
2596 if done_early: Niter -= 1
2597 #save_tp(chisq,Niter,yfit)
2597 #save_tp(chisq,Niter,yfit)
2598 return yfit, a, converge, sigma, chisq, chi2 # return result
2598 return yfit, a, converge, sigma, chisq, chi2 # return result
2599 ten=numpy.array([10.0],dtype='f4')[0]
2599 ten=numpy.array([10.0],dtype='f4')[0]
2600 flambda *= ten # Assume fit got worse
2600 flambda *= ten # Assume fit got worse
2601 if chisq <= chisq1:
2601 if chisq <= chisq1:
2602 break
2602 break
2603 hundred=numpy.array([100.0],dtype='f4')[0]
2603 hundred=numpy.array([100.0],dtype='f4')[0]
2604 flambda /= hundred
2604 flambda /= hundred
2605
2605
2606 a=b # Save new parameter estimate.
2606 a=b # Save new parameter estimate.
2607 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
2607 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
2608 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2608 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2609 if done_early: Niter -= 1
2609 if done_early: Niter -= 1
2610 #save_tp(chisq,Niter,yfit)
2610 #save_tp(chisq,Niter,yfit)
2611 return yfit, a, converge, sigma, chisq, chi2 # return result
2611 return yfit, a, converge, sigma, chisq, chi2 # return result
2612 converge = 0
2612 converge = 0
2613 chi2 = chisq
2613 chi2 = chisq
2614 #print('Failed to converge.')
2614 #print('Failed to converge.')
2615 #save_tp(chisq,Niter,yfit)
2615 #save_tp(chisq,Niter,yfit)
2616 return yfit, a, converge, sigma, chisq, chi2
2616 return yfit, a, converge, sigma, chisq, chi2
2617
2617
2618 if (nicoh is None): nicoh = 1
2618 if (nicoh is None): nicoh = 1
2619 if (graph is None): graph = 0
2619 if (graph is None): graph = 0
2620 if (smooth is None): smooth = 0
2620 if (smooth is None): smooth = 0
2621 elif (self.smooth < 3): smooth = 0
2621 elif (self.smooth < 3): smooth = 0
2622
2622
2623 if (type1 is None): type1 = 0
2623 if (type1 is None): type1 = 0
2624 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2624 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2625 if (snrth is None): snrth = -20.0
2625 if (snrth is None): snrth = -20.0
2626 if (dc is None): dc = 0
2626 if (dc is None): dc = 0
2627 if (aliasing is None): aliasing = 0
2627 if (aliasing is None): aliasing = 0
2628 if (oldfd is None): oldfd = 0
2628 if (oldfd is None): oldfd = 0
2629 if (wwauto is None): wwauto = 0
2629 if (wwauto is None): wwauto = 0
2630
2630
2631 if (n0 < 1.e-20): n0 = 1.e-20
2631 if (n0 < 1.e-20): n0 = 1.e-20
2632
2632
2633 xvalid = numpy.where(fwindow == 1)[0]
2633 xvalid = numpy.where(fwindow == 1)[0]
2634 freq = oldfreq
2634 freq = oldfreq
2635 truex = oldfreq
2635 truex = oldfreq
2636 vec_power = numpy.zeros(oldspec.shape[1])
2636 vec_power = numpy.zeros(oldspec.shape[1])
2637 vec_fd = numpy.zeros(oldspec.shape[1])
2637 vec_fd = numpy.zeros(oldspec.shape[1])
2638 vec_w = numpy.zeros(oldspec.shape[1])
2638 vec_w = numpy.zeros(oldspec.shape[1])
2639 vec_snr = numpy.zeros(oldspec.shape[1])
2639 vec_snr = numpy.zeros(oldspec.shape[1])
2640 vec_n1 = numpy.empty(oldspec.shape[1])
2640 vec_n1 = numpy.empty(oldspec.shape[1])
2641 vec_fp = numpy.empty(oldspec.shape[1])
2641 vec_fp = numpy.empty(oldspec.shape[1])
2642 vec_sigma_fd = numpy.empty(oldspec.shape[1])
2642 vec_sigma_fd = numpy.empty(oldspec.shape[1])
2643
2643
2644 for ind in range(oldspec.shape[1]):
2644 for ind in range(oldspec.shape[1]):
2645
2645
2646 spec = oldspec[:,ind]
2646 spec = oldspec[:,ind]
2647 if (smooth == 0):
2647 if (smooth == 0):
2648 spec2 = spec
2648 spec2 = spec
2649 else:
2649 else:
2650 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2650 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2651
2651
2652 aux = spec2*fwindow
2652 aux = spec2*fwindow
2653 max_spec = aux.max()
2653 max_spec = aux.max()
2654 m = aux.tolist().index(max_spec)
2654 m = aux.tolist().index(max_spec)
2655
2655
2656 if m > 2 and m < oldfreq.size - 3:
2656 if m > 2 and m < oldfreq.size - 3:
2657 newindex = m + numpy.array([-2,-1,0,1,2])
2657 newindex = m + numpy.array([-2,-1,0,1,2])
2658 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
2658 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
2659 #peakspec = SPLINE(,)
2659 #peakspec = SPLINE(,)
2660 tck = interpolate.splrep(freq[newindex], spec2[newindex])
2660 tck = interpolate.splrep(freq[newindex], spec2[newindex])
2661 peakspec = interpolate.splev(newfreq, tck)
2661 peakspec = interpolate.splev(newfreq, tck)
2662 # max_spec = MAX(peakspec,)
2662 # max_spec = MAX(peakspec,)
2663 max_spec = numpy.max(peakspec)
2663 max_spec = numpy.max(peakspec)
2664 mnew = numpy.argmax(peakspec)
2664 mnew = numpy.argmax(peakspec)
2665 #fp = newfreq(mnew)
2665 #fp = newfreq(mnew)
2666 fp = newfreq[mnew]
2666 fp = newfreq[mnew]
2667 else:
2667 else:
2668 fp = freq[m]
2668 fp = freq[m]
2669
2669
2670 if type1==0:
2670 if type1==0:
2671
2671
2672 # Moments Estimation
2672 # Moments Estimation
2673 bb = spec2[numpy.arange(m,spec2.size)]
2673 bb = spec2[numpy.arange(m,spec2.size)]
2674 bb = (bb<n0).nonzero()
2674 bb = (bb<n0).nonzero()
2675 bb = bb[0]
2675 bb = bb[0]
2676
2676
2677 ss = spec2[numpy.arange(0,m + 1)]
2677 ss = spec2[numpy.arange(0,m + 1)]
2678 ss = (ss<n0).nonzero()
2678 ss = (ss<n0).nonzero()
2679 ss = ss[0]
2679 ss = ss[0]
2680
2680
2681 if (bb.size == 0):
2681 if (bb.size == 0):
2682 bb0 = spec.size - 1 - m
2682 bb0 = spec.size - 1 - m
2683 else:
2683 else:
2684 bb0 = bb[0] - 1
2684 bb0 = bb[0] - 1
2685 if (bb0 < 0):
2685 if (bb0 < 0):
2686 bb0 = 0
2686 bb0 = 0
2687
2687
2688 if (ss.size == 0):
2688 if (ss.size == 0):
2689 ss1 = 1
2689 ss1 = 1
2690 else:
2690 else:
2691 ss1 = max(ss) + 1
2691 ss1 = max(ss) + 1
2692
2692
2693 if (ss1 > m):
2693 if (ss1 > m):
2694 ss1 = m
2694 ss1 = m
2695
2695
2696 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2696 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2697
2697
2698 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2698 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2699 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2699 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2700 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
2700 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
2701 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
2701 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
2702 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
2702 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
2703 snr = (spec2.mean()-n0)/n0
2703 snr = (spec2.mean()-n0)/n0
2704 if (snr < 1.e-20): snr = 1.e-20
2704 if (snr < 1.e-20): snr = 1.e-20
2705
2705
2706 vec_power[ind] = total_power
2706 vec_power[ind] = total_power
2707 vec_fd[ind] = fd
2707 vec_fd[ind] = fd
2708 vec_w[ind] = w
2708 vec_w[ind] = w
2709 vec_snr[ind] = snr
2709 vec_snr[ind] = snr
2710 else:
2710 else:
2711 # Noise by heights
2711 # Noise by heights
2712 n1, stdv = self.__get_noise2(spec, nicoh)
2712 n1, stdv = self.__get_noise2(spec, nicoh)
2713 # Moments Estimation
2713 # Moments Estimation
2714 bb = spec2[numpy.arange(m,spec2.size)]
2714 bb = spec2[numpy.arange(m,spec2.size)]
2715 bb = (bb<n1).nonzero()
2715 bb = (bb<n1).nonzero()
2716 bb = bb[0]
2716 bb = bb[0]
2717
2717
2718 ss = spec2[numpy.arange(0,m + 1)]
2718 ss = spec2[numpy.arange(0,m + 1)]
2719 ss = (ss<n1).nonzero()
2719 ss = (ss<n1).nonzero()
2720 ss = ss[0]
2720 ss = ss[0]
2721
2721
2722 if (bb.size == 0):
2722 if (bb.size == 0):
2723 bb0 = spec.size - 1 - m
2723 bb0 = spec.size - 1 - m
2724 else:
2724 else:
2725 bb0 = bb[0] - 1
2725 bb0 = bb[0] - 1
2726 if (bb0 < 0):
2726 if (bb0 < 0):
2727 bb0 = 0
2727 bb0 = 0
2728
2728
2729 if (ss.size == 0):
2729 if (ss.size == 0):
2730 ss1 = 1
2730 ss1 = 1
2731 else:
2731 else:
2732 ss1 = max(ss) + 1
2732 ss1 = max(ss) + 1
2733
2733
2734 if (ss1 > m):
2734 if (ss1 > m):
2735 ss1 = m
2735 ss1 = m
2736
2736
2737 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2737 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2738 power = ((spec[valid] - n1)*fwindow[valid]).sum()
2738 power = ((spec[valid] - n1)*fwindow[valid]).sum()
2739 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
2739 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
2740 try:
2740 try:
2741 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2741 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2742 except:
2742 except:
2743 w = float("NaN")
2743 w = float("NaN")
2744 snr = power/(n0*fwindow.sum())
2744 snr = power/(n0*fwindow.sum())
2745 if snr < 1.e-20: snr = 1.e-20
2745 if snr < 1.e-20: snr = 1.e-20
2746
2746
2747 # Here start gaussean adjustment
2747 # Here start gaussean adjustment
2748
2748
2749 if snr > numpy.power(10,0.1*snrth):
2749 if snr > numpy.power(10,0.1*snrth):
2750
2750
2751 a = numpy.zeros(4,dtype='f4')
2751 a = numpy.zeros(4,dtype='f4')
2752 a[0] = snr * n0
2752 a[0] = snr * n0
2753 a[1] = fd
2753 a[1] = fd
2754 a[2] = w
2754 a[2] = w
2755 a[3] = n0
2755 a[3] = n0
2756
2756
2757 np = spec.size
2757 np = spec.size
2758 aold = a.copy()
2758 aold = a.copy()
2759 spec2 = spec.copy()
2759 spec2 = spec.copy()
2760 oldxvalid = xvalid.copy()
2760 oldxvalid = xvalid.copy()
2761
2761
2762 for i in range(2):
2762 for i in range(2):
2763
2763
2764 ww = 1.0/(numpy.power(spec2,2)/nicoh)
2764 ww = 1.0/(numpy.power(spec2,2)/nicoh)
2765 ww[np//2] = 0.0
2765 ww[np//2] = 0.0
2766
2766
2767 a = aold.copy()
2767 a = aold.copy()
2768 xvalid = oldxvalid.copy()
2768 xvalid = oldxvalid.copy()
2769 #self.show_var(xvalid)
2769 #self.show_var(xvalid)
2770
2770
2771 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
2771 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
2772 a = gaussfn[1]
2772 a = gaussfn[1]
2773 converge = gaussfn[2]
2773 converge = gaussfn[2]
2774
2774
2775 xvalid = numpy.arange(np)
2775 xvalid = numpy.arange(np)
2776 spec2 = __GAUSSWINFIT1(a)
2776 spec2 = __GAUSSWINFIT1(a)
2777
2777
2778 xvalid = oldxvalid.copy()
2778 xvalid = oldxvalid.copy()
2779 power = a[0] * np
2779 power = a[0] * np
2780 fd = a[1]
2780 fd = a[1]
2781 sigma_fd = gaussfn[3][1]
2781 sigma_fd = gaussfn[3][1]
2782 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
2782 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
2783 w = numpy.abs(a[2])
2783 w = numpy.abs(a[2])
2784 n1 = max(a[3], n0)
2784 n1 = max(a[3], n0)
2785
2785
2786 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
2786 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
2787 else:
2787 else:
2788 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
2788 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
2789
2789
2790 vec_fd[ind] = fd
2790 vec_fd[ind] = fd
2791 vec_w[ind] = w
2791 vec_w[ind] = w
2792 vec_snr[ind] = snr
2792 vec_snr[ind] = snr
2793 vec_n1[ind] = n1
2793 vec_n1[ind] = n1
2794 vec_fp[ind] = fp
2794 vec_fp[ind] = fp
2795 vec_sigma_fd[ind] = sigma_fd
2795 vec_sigma_fd[ind] = sigma_fd
2796 vec_power[ind] = power # to compare with type 0 proccessing
2796 vec_power[ind] = power # to compare with type 0 proccessing
2797
2797
2798 if type1==1:
2798 if type1==1:
2799 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
2799 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
2800 else:
2800 else:
2801 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2801 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2802
2802
2803 def __get_noise2(self,POWER, fft_avg, TALK=0):
2803 def __get_noise2(self,POWER, fft_avg, TALK=0):
2804 '''
2804 '''
2805 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
2805 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
2806 '''
2806 '''
2807 SPECT_PTS = len(POWER)
2807 SPECT_PTS = len(POWER)
2808 fft_avg = fft_avg*1.0
2808 fft_avg = fft_avg*1.0
2809 NOMIT = 0
2809 NOMIT = 0
2810 NN = SPECT_PTS - NOMIT
2810 NN = SPECT_PTS - NOMIT
2811 N = NN//2
2811 N = NN//2
2812 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
2812 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
2813 ARR = numpy.sort(ARR)
2813 ARR = numpy.sort(ARR)
2814 NUMS_MIN = (SPECT_PTS+7)//8
2814 NUMS_MIN = (SPECT_PTS+7)//8
2815 RTEST = (1.0+1.0/fft_avg)
2815 RTEST = (1.0+1.0/fft_avg)
2816 SUM = 0.0
2816 SUM = 0.0
2817 SUMSQ = 0.0
2817 SUMSQ = 0.0
2818 J = 0
2818 J = 0
2819 for I in range(NN):
2819 for I in range(NN):
2820 J = J + 1
2820 J = J + 1
2821 SUM = SUM + ARR[I]
2821 SUM = SUM + ARR[I]
2822 SUMSQ = SUMSQ + ARR[I]*ARR[I]
2822 SUMSQ = SUMSQ + ARR[I]*ARR[I]
2823 AVE = SUM*1.0/J
2823 AVE = SUM*1.0/J
2824 if J > NUMS_MIN:
2824 if J > NUMS_MIN:
2825 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
2825 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
2826 else:
2826 else:
2827 if J == NUMS_MIN: RNOISE = AVE
2827 if J == NUMS_MIN: RNOISE = AVE
2828 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
2828 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
2829 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2829 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2830 return RNOISE, stdv
2830 return RNOISE, stdv
2831
2831
2832 def __get_noise1(self, power, fft_avg, TALK=0):
2832 def __get_noise1(self, power, fft_avg, TALK=0):
2833 '''
2833 '''
2834 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
2834 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
2835 '''
2835 '''
2836 num_pts = numpy.size(power)
2836 num_pts = numpy.size(power)
2837 #print('num_pts',num_pts)
2837 #print('num_pts',num_pts)
2838 #print('power',power.shape)
2838 #print('power',power.shape)
2839 #print(power[256:267,0:2])
2839 #print(power[256:267,0:2])
2840 fft_avg = fft_avg*1.0
2840 fft_avg = fft_avg*1.0
2841
2841
2842 ind = numpy.argsort(power, axis=None, kind='stable')
2842 ind = numpy.argsort(power, axis=None, kind='stable')
2843 #ind = numpy.argsort(numpy.reshape(power,-1))
2843 #ind = numpy.argsort(numpy.reshape(power,-1))
2844 #print(ind.shape)
2844 #print(ind.shape)
2845 #print(ind[0:11])
2845 #print(ind[0:11])
2846 #print(numpy.reshape(power,-1)[ind[0:11]])
2846 #print(numpy.reshape(power,-1)[ind[0:11]])
2847 ARR = numpy.reshape(power,-1)[ind]
2847 ARR = numpy.reshape(power,-1)[ind]
2848 #print('ARR',len(ARR))
2848 #print('ARR',len(ARR))
2849 #print('ARR',ARR.shape)
2849 #print('ARR',ARR.shape)
2850 NUMS_MIN = num_pts//10
2850 NUMS_MIN = num_pts//10
2851 RTEST = (1.0+1.0/fft_avg)
2851 RTEST = (1.0+1.0/fft_avg)
2852 SUM = 0.0
2852 SUM = 0.0
2853 SUMSQ = 0.0
2853 SUMSQ = 0.0
2854 J = 0
2854 J = 0
2855 cont = 1
2855 cont = 1
2856 while cont == 1 and J < num_pts:
2856 while cont == 1 and J < num_pts:
2857
2857
2858 SUM = SUM + ARR[J]
2858 SUM = SUM + ARR[J]
2859 SUMSQ = SUMSQ + ARR[J]*ARR[J]
2859 SUMSQ = SUMSQ + ARR[J]*ARR[J]
2860 J = J + 1
2860 J = J + 1
2861
2861
2862 if J > NUMS_MIN:
2862 if J > NUMS_MIN:
2863 if (SUMSQ*J <= RTEST*SUM*SUM):
2863 if (SUMSQ*J <= RTEST*SUM*SUM):
2864 LNOISE = SUM*1.0/J
2864 LNOISE = SUM*1.0/J
2865 else:
2865 else:
2866 J = J - 1
2866 J = J - 1
2867 SUM = SUM - ARR[J]
2867 SUM = SUM - ARR[J]
2868 SUMSQ = SUMSQ - ARR[J]*ARR[J]
2868 SUMSQ = SUMSQ - ARR[J]*ARR[J]
2869 cont = 0
2869 cont = 0
2870 else:
2870 else:
2871 if J == NUMS_MIN: LNOISE = SUM*1.0/J
2871 if J == NUMS_MIN: LNOISE = SUM*1.0/J
2872 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
2872 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
2873 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2873 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2874 return LNOISE, stdv
2874 return LNOISE, stdv
2875
2875
2876 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
2876 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
2877
2877
2878 val_frq = numpy.arange(num_prof-2)+1
2878 val_frq = numpy.arange(num_prof-2)+1
2879 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
2879 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
2880 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
2880 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
2881 junkid = numpy.argsort(junkspc)
2881 junkid = numpy.argsort(junkspc)
2882 noisezone = val_frq[junkid[0:num_prof//2]]
2882 noisezone = val_frq[junkid[0:num_prof//2]]
2883 specnoise = spectra[noisezone,:]
2883 specnoise = spectra[noisezone,:]
2884 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
2884 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
2885
2885
2886 if talk:
2886 if talk:
2887 print('noise =', noise)
2887 print('noise =', noise)
2888 return noise
2888 return noise
2889 #------------------ Get SA Parameters --------------------------
2889 #------------------ Get SA Parameters --------------------------
2890
2890
2891 def GetSAParameters(self):
2891 def GetSAParameters(self):
2892 #SA en frecuencia
2892 #SA en frecuencia
2893 pairslist = self.dataOut.groupList
2893 pairslist = self.dataOut.groupList
2894 num_pairs = len(pairslist)
2894 num_pairs = len(pairslist)
2895
2895
2896 vel = self.dataOut.abscissaList
2896 vel = self.dataOut.abscissaList
2897 spectra = self.dataOut.data_pre
2897 spectra = self.dataOut.data_pre
2898 cspectra = self.dataIn.data_cspc
2898 cspectra = self.dataIn.data_cspc
2899 delta_v = vel[1] - vel[0]
2899 delta_v = vel[1] - vel[0]
2900
2900
2901 #Calculating the power spectrum
2901 #Calculating the power spectrum
2902 spc_pow = numpy.sum(spectra, 3)*delta_v
2902 spc_pow = numpy.sum(spectra, 3)*delta_v
2903 #Normalizing Spectra
2903 #Normalizing Spectra
2904 norm_spectra = spectra/spc_pow
2904 norm_spectra = spectra/spc_pow
2905 #Calculating the norm_spectra at peak
2905 #Calculating the norm_spectra at peak
2906 max_spectra = numpy.max(norm_spectra, 3)
2906 max_spectra = numpy.max(norm_spectra, 3)
2907
2907
2908 #Normalizing Cross Spectra
2908 #Normalizing Cross Spectra
2909 norm_cspectra = numpy.zeros(cspectra.shape)
2909 norm_cspectra = numpy.zeros(cspectra.shape)
2910
2910
2911 for i in range(num_chan):
2911 for i in range(num_chan):
2912 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
2912 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
2913
2913
2914 max_cspectra = numpy.max(norm_cspectra,2)
2914 max_cspectra = numpy.max(norm_cspectra,2)
2915 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
2915 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
2916
2916
2917 for i in range(num_pairs):
2917 for i in range(num_pairs):
2918 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
2918 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
2919 #------------------- Get Lags ----------------------------------
2919 #------------------- Get Lags ----------------------------------
2920
2920
2921 class JULIADriftsEstimation(Operation):
2921 class JULIADriftsEstimation(Operation):
2922
2922
2923 def __init__(self):
2923 def __init__(self):
2924 Operation.__init__(self)
2924 Operation.__init__(self)
2925
2925
2926 def newtotal(self, data):
2926 def newtotal(self, data):
2927 return numpy.nansum(data)
2927 return numpy.nansum(data)
2928
2928
2929 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
2929 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
2930
2930
2931 Sz0 = parm.shape # Sz0: h,p
2931 Sz0 = parm.shape # Sz0: h,p
2932 drift = parm[:,0]
2932 drift = parm[:,0]
2933 sw = 2*parm[:,1]
2933 sw = 2*parm[:,1]
2934 snr = 10*numpy.log10(parm[:,2])
2934 snr = 10*numpy.log10(parm[:,2])
2935 Sz = drift.shape # Sz: h
2935 Sz = drift.shape # Sz: h
2936 mask = numpy.ones((Sz[0]))
2936 mask = numpy.ones((Sz[0]))
2937 th=0
2937 th=0
2938 valid=numpy.where(numpy.isfinite(snr))
2938 valid=numpy.where(numpy.isfinite(snr))
2939 cvalid = len(valid[0])
2939 cvalid = len(valid[0])
2940 if cvalid >= 1:
2940 if cvalid >= 1:
2941 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
2941 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
2942 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
2942 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
2943 h = numpy.histogram(snr,bins=nbins)
2943 h = numpy.histogram(snr,bins=nbins)
2944 hist = h[0]
2944 hist = h[0]
2945 values = numpy.round_(h[1])
2945 values = numpy.round_(h[1])
2946 moda = values[numpy.where(hist == numpy.max(hist))]
2946 moda = values[numpy.where(hist == numpy.max(hist))]
2947 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
2947 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
2948
2948
2949 noise = snr[indNoise]
2949 noise = snr[indNoise]
2950 noise_mean = numpy.sum(noise)/len(noise)
2950 noise_mean = numpy.sum(noise)/len(noise)
2951 # CΓ‘lculo de media de snr
2951 # CΓ‘lculo de media de snr
2952 med = numpy.median(snr)
2952 med = numpy.median(snr)
2953 # Establece el umbral de snr
2953 # Establece el umbral de snr
2954 if noise_mean > med + 3:
2954 if noise_mean > med + 3:
2955 th = med
2955 th = med
2956 else:
2956 else:
2957 th = noise_mean + 3
2957 th = noise_mean + 3
2958 # Establece mΓ‘scara
2958 # Establece mΓ‘scara
2959 novalid = numpy.where(snr <= th)[0]
2959 novalid = numpy.where(snr <= th)[0]
2960 mask[novalid] = numpy.nan
2960 mask[novalid] = numpy.nan
2961 # Elimina datos que no sobrepasen el umbral: PARAMETRO
2961 # Elimina datos que no sobrepasen el umbral: PARAMETRO
2962 novalid = numpy.where(snr <= snrth)
2962 novalid = numpy.where(snr <= snrth)
2963 cnovalid = len(novalid[0])
2963 cnovalid = len(novalid[0])
2964 if cnovalid > 0:
2964 if cnovalid > 0:
2965 mask[novalid] = numpy.nan
2965 mask[novalid] = numpy.nan
2966 novalid = numpy.where(numpy.isnan(snr))
2966 novalid = numpy.where(numpy.isnan(snr))
2967 cnovalid = len(novalid[0])
2967 cnovalid = len(novalid[0])
2968 if cnovalid > 0:
2968 if cnovalid > 0:
2969 mask[novalid] = numpy.nan
2969 mask[novalid] = numpy.nan
2970 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
2970 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
2971 for h in range(Sz0[0]):
2971 for h in range(Sz0[0]):
2972 for p in range(Sz0[1]):
2972 for p in range(Sz0[1]):
2973 if numpy.isnan(mask[h]):
2973 if numpy.isnan(mask[h]):
2974 new_parm[h,p]=numpy.nan
2974 new_parm[h,p]=numpy.nan
2975 else:
2975 else:
2976 new_parm[h,p]=parm[h,p]
2976 new_parm[h,p]=parm[h,p]
2977
2977
2978 return new_parm, th
2978 return new_parm, th
2979
2979
2980 def run(self, dataOut, zenith, zenithCorrection,heights=None, statistics=0, otype=0):
2980 def run(self, dataOut, zenith, zenithCorrection,heights=None, statistics=0, otype=0):
2981
2981
2982 dataOut.lat=-11.95
2982 dataOut.lat=-11.95
2983 dataOut.lon=-76.87
2983 dataOut.lon=-76.87
2984 nCh=dataOut.spcpar.shape[0]
2984 nCh=dataOut.spcpar.shape[0]
2985 nHei=dataOut.spcpar.shape[1]
2985 nHei=dataOut.spcpar.shape[1]
2986 nParam=dataOut.spcpar.shape[2]
2986 nParam=dataOut.spcpar.shape[2]
2987 # SelecciΓ³n de alturas
2987 # SelecciΓ³n de alturas
2988
2988
2989 if not heights:
2989 if not heights:
2990 parm = numpy.zeros((nCh,nHei,nParam))
2990 parm = numpy.zeros((nCh,nHei,nParam))
2991 parm[:] = dataOut.spcpar[:]
2991 parm[:] = dataOut.spcpar[:]
2992 else:
2992 else:
2993 hei=dataOut.heightList
2993 hei=dataOut.heightList
2994 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
2994 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
2995 nhvalid=len(hvalid)
2995 nhvalid=len(hvalid)
2996 dataOut.heightList = hei[hvalid]
2996 dataOut.heightList = hei[hvalid]
2997 parm = numpy.zeros((nCh,nhvalid,nParam))
2997 parm = numpy.zeros((nCh,nhvalid,nParam))
2998 parm[:] = dataOut.spcpar[:,hvalid,:]
2998 parm[:] = dataOut.spcpar[:,hvalid,:]
2999
2999
3000
3000
3001 # Primer filtrado: Umbral de SNR
3001 # Primer filtrado: Umbral de SNR
3002 for i in range(nCh):
3002 for i in range(nCh):
3003 parm[i,:,:] = self.data_filter(parm[i,:,:])[0]
3003 parm[i,:,:] = self.data_filter(parm[i,:,:])[0]
3004
3004
3005 zenith = numpy.array(zenith)
3005 zenith = numpy.array(zenith)
3006 zenith -= zenithCorrection
3006 zenith -= zenithCorrection
3007 zenith *= numpy.pi/180
3007 zenith *= numpy.pi/180
3008 alpha = zenith[0]
3008 alpha = zenith[0]
3009 beta = zenith[1]
3009 beta = zenith[1]
3010 dopplerCH0 = parm[0,:,0]
3010 dopplerCH0 = parm[0,:,0]
3011 dopplerCH1 = parm[1,:,0]
3011 dopplerCH1 = parm[1,:,0]
3012 swCH0 = parm[0,:,1]
3012 swCH0 = parm[0,:,1]
3013 swCH1 = parm[1,:,1]
3013 swCH1 = parm[1,:,1]
3014 snrCH0 = 10*numpy.log10(parm[0,:,2])
3014 snrCH0 = 10*numpy.log10(parm[0,:,2])
3015 snrCH1 = 10*numpy.log10(parm[1,:,2])
3015 snrCH1 = 10*numpy.log10(parm[1,:,2])
3016 noiseCH0 = parm[0,:,3]
3016 noiseCH0 = parm[0,:,3]
3017 noiseCH1 = parm[1,:,3]
3017 noiseCH1 = parm[1,:,3]
3018 wErrCH0 = parm[0,:,5]
3018 wErrCH0 = parm[0,:,5]
3019 wErrCH1 = parm[1,:,5]
3019 wErrCH1 = parm[1,:,5]
3020
3020
3021 # Vertical and zonal calculation according to geometry
3021 # Vertical and zonal calculation according to geometry
3022 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
3022 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
3023 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
3023 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
3024 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
3024 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
3025 snr = (snrCH0 + snrCH1)/2
3025 snr = (snrCH0 + snrCH1)/2
3026 noise = (noiseCH0 + noiseCH1)/2
3026 noise = (noiseCH0 + noiseCH1)/2
3027 sw = (swCH0 + swCH1)/2
3027 sw = (swCH0 + swCH1)/2
3028 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))
3028 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))
3029 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))
3029 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))
3030
3030
3031 # for statistics150km
3031 # for statistics150km
3032 if statistics:
3032 if statistics:
3033 print('Implemented offline.')
3033 print('Implemented offline.')
3034
3034
3035 if otype == 0:
3035 if otype == 0:
3036 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
3036 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
3037 elif otype == 3:
3037 elif otype == 3:
3038 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
3038 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
3039 elif otype == 4:
3039 elif otype == 4:
3040 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
3040 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
3041
3041
3042 snr1 = numpy.vstack((snrCH0, snrCH1))
3042 snr1 = numpy.vstack((snrCH0, snrCH1))
3043 dataOut.data_output = winds
3043 dataOut.data_output = winds
3044 dataOut.data_snr = snr1
3044 dataOut.data_snr = snr1
3045
3045
3046 dataOut.utctimeInit = dataOut.utctime
3046 dataOut.utctimeInit = dataOut.utctime
3047 dataOut.outputInterval = dataOut.timeInterval
3047 dataOut.outputInterval = dataOut.timeInterval
3048 try:
3048 try:
3049 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.data_output[0])) # NAN vectors are not written MADRIGAL CASE
3049 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.data_output[0])) # NAN vectors are not written MADRIGAL CASE
3050 except:
3050 except:
3051 print("Check there is no Data")
3051 print("Check there is no Data")
3052
3052
3053 return dataOut
3053 return dataOut
3054
3054
3055 class SALags(Operation):
3055 class SALags(Operation):
3056 '''
3056 '''
3057 Function GetMoments()
3057 Function GetMoments()
3058
3058
3059 Input:
3059 Input:
3060 self.dataOut.data_pre
3060 self.dataOut.data_pre
3061 self.dataOut.abscissaList
3061 self.dataOut.abscissaList
3062 self.dataOut.noise
3062 self.dataOut.noise
3063 self.dataOut.normFactor
3063 self.dataOut.normFactor
3064 self.dataOut.data_snr
3064 self.dataOut.data_snr
3065 self.dataOut.groupList
3065 self.dataOut.groupList
3066 self.dataOut.nChannels
3066 self.dataOut.nChannels
3067
3067
3068 Affected:
3068 Affected:
3069 self.dataOut.data_param
3069 self.dataOut.data_param
3070
3070
3071 '''
3071 '''
3072 def run(self, dataOut):
3072 def run(self, dataOut):
3073 data_acf = dataOut.data_pre[0]
3073 data_acf = dataOut.data_pre[0]
3074 data_ccf = dataOut.data_pre[1]
3074 data_ccf = dataOut.data_pre[1]
3075 normFactor_acf = dataOut.normFactor[0]
3075 normFactor_acf = dataOut.normFactor[0]
3076 normFactor_ccf = dataOut.normFactor[1]
3076 normFactor_ccf = dataOut.normFactor[1]
3077 pairs_acf = dataOut.groupList[0]
3077 pairs_acf = dataOut.groupList[0]
3078 pairs_ccf = dataOut.groupList[1]
3078 pairs_ccf = dataOut.groupList[1]
3079
3079
3080 nHeights = dataOut.nHeights
3080 nHeights = dataOut.nHeights
3081 absc = dataOut.abscissaList
3081 absc = dataOut.abscissaList
3082 noise = dataOut.noise
3082 noise = dataOut.noise
3083 SNR = dataOut.data_snr
3083 SNR = dataOut.data_snr
3084 nChannels = dataOut.nChannels
3084 nChannels = dataOut.nChannels
3085 for l in range(len(pairs_acf)):
3085 for l in range(len(pairs_acf)):
3086 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
3086 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
3087
3087
3088 for l in range(len(pairs_ccf)):
3088 for l in range(len(pairs_ccf)):
3089 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
3089 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
3090
3090
3091 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
3091 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
3092 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
3092 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
3093 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
3093 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
3094 return
3094 return
3095
3095
3096 def __calculateTaus(self, data_acf, data_ccf, lagRange):
3096 def __calculateTaus(self, data_acf, data_ccf, lagRange):
3097
3097
3098 lag0 = data_acf.shape[1]/2
3098 lag0 = data_acf.shape[1]/2
3099 #Funcion de Autocorrelacion
3099 #Funcion de Autocorrelacion
3100 mean_acf = stats.nanmean(data_acf, axis = 0)
3100 mean_acf = stats.nanmean(data_acf, axis = 0)
3101
3101
3102 #Obtencion Indice de TauCross
3102 #Obtencion Indice de TauCross
3103 ind_ccf = data_ccf.argmax(axis = 1)
3103 ind_ccf = data_ccf.argmax(axis = 1)
3104 #Obtencion Indice de TauAuto
3104 #Obtencion Indice de TauAuto
3105 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
3105 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
3106 ccf_lag0 = data_ccf[:,lag0,:]
3106 ccf_lag0 = data_ccf[:,lag0,:]
3107
3107
3108 for i in range(ccf_lag0.shape[0]):
3108 for i in range(ccf_lag0.shape[0]):
3109 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
3109 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
3110
3110
3111 #Obtencion de TauCross y TauAuto
3111 #Obtencion de TauCross y TauAuto
3112 tau_ccf = lagRange[ind_ccf]
3112 tau_ccf = lagRange[ind_ccf]
3113 tau_acf = lagRange[ind_acf]
3113 tau_acf = lagRange[ind_acf]
3114
3114
3115 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
3115 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
3116
3116
3117 tau_ccf[Nan1,Nan2] = numpy.nan
3117 tau_ccf[Nan1,Nan2] = numpy.nan
3118 tau_acf[Nan1,Nan2] = numpy.nan
3118 tau_acf[Nan1,Nan2] = numpy.nan
3119 tau = numpy.vstack((tau_ccf,tau_acf))
3119 tau = numpy.vstack((tau_ccf,tau_acf))
3120
3120
3121 return tau
3121 return tau
3122
3122
3123 def __calculateLag1Phase(self, data, lagTRange):
3123 def __calculateLag1Phase(self, data, lagTRange):
3124 data1 = stats.nanmean(data, axis = 0)
3124 data1 = stats.nanmean(data, axis = 0)
3125 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
3125 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
3126
3126
3127 phase = numpy.angle(data1[lag1,:])
3127 phase = numpy.angle(data1[lag1,:])
3128
3128
3129 return phase
3129 return phase
3130
3130
3131 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
3131 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
3132 z = (x - a1) / a2
3132 z = (x - a1) / a2
3133 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
3133 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
3134 return y
3134 return y
3135
3135
3136
3136
3137 class SpectralFitting(Operation):
3137 class SpectralFitting(Operation):
3138 '''
3138 '''
3139 Function GetMoments()
3139 Function GetMoments()
3140
3140
3141 Input:
3141 Input:
3142 Output:
3142 Output:
3143 Variables modified:
3143 Variables modified:
3144 '''
3144 '''
3145 isConfig = False
3145 isConfig = False
3146 __dataReady = False
3146 __dataReady = False
3147 bloques = None
3147 bloques = None
3148 bloque0 = None
3148 bloque0 = None
3149 index = 0
3149 index = 0
3150 fint = 0
3150 fint = 0
3151 buffer = 0
3151 buffer = 0
3152 buffer2 = 0
3152 buffer2 = 0
3153 buffer3 = 0
3153 buffer3 = 0
3154
3154
3155 def __init__(self):
3155 def __init__(self):
3156 Operation.__init__(self)
3156 Operation.__init__(self)
3157 self.i=0
3157 self.i=0
3158 self.isConfig = False
3158 self.isConfig = False
3159
3159
3160
3160
3161 def setup(self,dataOut,groupList,path,file,filec):
3161 def setup(self,dataOut,groupList,path,file,filec):
3162 self.__dataReady = False
3162 self.__dataReady = False
3163 # new
3163 # new
3164 self.nChannels = dataOut.nChannels
3164 self.nChannels = dataOut.nChannels
3165 self.channels = dataOut.channelList
3165 self.channels = dataOut.channelList
3166 self.nHeights = dataOut.heightList.size
3166 self.nHeights = dataOut.heightList.size
3167 self.heights = dataOut.heightList
3167 self.heights = dataOut.heightList
3168 self.nProf = dataOut.nProfiles
3168 self.nProf = dataOut.nProfiles
3169 self.nIncohInt = dataOut.nIncohInt
3169 self.nIncohInt = dataOut.nIncohInt
3170 self.absc = dataOut.abscissaList[:-1]
3170 self.absc = dataOut.abscissaList[:-1]
3171
3171
3172
3172
3173 #To be inserted as a parameter
3173 #To be inserted as a parameter
3174 try:
3174 try:
3175 self.groupArray = numpy.array(groupList)#groupArray = numpy.array([[0,1],[2,3]])
3175 self.groupArray = numpy.array(groupList)#groupArray = numpy.array([[0,1],[2,3]])
3176 except:
3176 except:
3177 print("Please insert groupList. Example (0,1),(2,3) format multilist")
3177 print("Please insert groupList. Example (0,1),(2,3) format multilist")
3178 dataOut.groupList = self.groupArray
3178 dataOut.groupList = self.groupArray
3179 self.crosspairs = dataOut.groupList
3179 self.crosspairs = dataOut.groupList
3180 self.nPairs = len(self.crosspairs)
3180 self.nPairs = len(self.crosspairs)
3181 self.nGroups = self.groupArray.shape[0]
3181 self.nGroups = self.groupArray.shape[0]
3182
3182
3183 #List of possible combinations
3183 #List of possible combinations
3184
3184
3185 self.listComb = itertools.combinations(numpy.arange(self.groupArray.shape[1]),2)
3185 self.listComb = itertools.combinations(numpy.arange(self.groupArray.shape[1]),2)
3186 self.indCross = numpy.zeros(len(list(self.listComb)), dtype = 'int')
3186 self.indCross = numpy.zeros(len(list(self.listComb)), dtype = 'int')
3187
3187
3188 #Parameters Array
3188 #Parameters Array
3189 dataOut.data_param = None
3189 dataOut.data_param = None
3190 dataOut.data_paramC = None
3190 dataOut.data_paramC = None
3191 dataOut.clean_num_aver = None
3191 dataOut.clean_num_aver = None
3192 dataOut.coh_num_aver = None
3192 dataOut.coh_num_aver = None
3193 dataOut.tmp_spectra_i = None
3193 dataOut.tmp_spectra_i = None
3194 dataOut.tmp_cspectra_i = None
3194 dataOut.tmp_cspectra_i = None
3195 dataOut.tmp_spectra_c = None
3195 dataOut.tmp_spectra_c = None
3196 dataOut.tmp_cspectra_c = None
3196 dataOut.tmp_cspectra_c = None
3197 dataOut.index = None
3197 dataOut.index = None
3198
3198
3199 if path != None:
3199 if path != None:
3200 sys.path.append(path)
3200 sys.path.append(path)
3201 self.library = importlib.import_module(file)
3201 self.library = importlib.import_module(file)
3202 if filec != None:
3202 if filec != None:
3203 self.weightf = importlib.import_module(filec)
3203 self.weightf = importlib.import_module(filec)
3204
3204
3205 #Set constants
3205 #Set constants
3206 self.constants = self.library.setConstants(dataOut)
3206 self.constants = self.library.setConstants(dataOut)
3207 dataOut.constants = self.constants
3207 dataOut.constants = self.constants
3208 self.M = dataOut.normFactor
3208 self.M = dataOut.normFactor
3209 self.N = dataOut.nFFTPoints
3209 self.N = dataOut.nFFTPoints
3210 self.ippSeconds = dataOut.ippSeconds
3210 self.ippSeconds = dataOut.ippSeconds
3211 self.K = dataOut.nIncohInt
3211 self.K = dataOut.nIncohInt
3212 self.pairsArray = numpy.array(dataOut.pairsList)
3212 self.pairsArray = numpy.array(dataOut.pairsList)
3213 self.snrth = 20
3213 self.snrth = 20
3214
3214
3215 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):
3215 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):
3216
3216
3217 if (nicoh is None): nicoh = 1
3217 if (nicoh is None): nicoh = 1
3218 if (graph is None): graph = 0
3218 if (graph is None): graph = 0
3219 if (smooth is None): smooth = 0
3219 if (smooth is None): smooth = 0
3220 elif (self.smooth < 3): smooth = 0
3220 elif (self.smooth < 3): smooth = 0
3221
3221
3222 if (type1 is None): type1 = 0
3222 if (type1 is None): type1 = 0
3223 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
3223 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
3224 if (snrth is None): snrth = -3
3224 if (snrth is None): snrth = -3
3225 if (dc is None): dc = 0
3225 if (dc is None): dc = 0
3226 if (aliasing is None): aliasing = 0
3226 if (aliasing is None): aliasing = 0
3227 if (oldfd is None): oldfd = 0
3227 if (oldfd is None): oldfd = 0
3228 if (wwauto is None): wwauto = 0
3228 if (wwauto is None): wwauto = 0
3229
3229
3230 if (n0 < 1.e-20): n0 = 1.e-20
3230 if (n0 < 1.e-20): n0 = 1.e-20
3231
3231
3232 freq = oldfreq
3232 freq = oldfreq
3233 vec_power = numpy.zeros(oldspec.shape[1])
3233 vec_power = numpy.zeros(oldspec.shape[1])
3234 vec_fd = numpy.zeros(oldspec.shape[1])
3234 vec_fd = numpy.zeros(oldspec.shape[1])
3235 vec_w = numpy.zeros(oldspec.shape[1])
3235 vec_w = numpy.zeros(oldspec.shape[1])
3236 vec_snr = numpy.zeros(oldspec.shape[1])
3236 vec_snr = numpy.zeros(oldspec.shape[1])
3237
3237
3238 oldspec = numpy.ma.masked_invalid(oldspec)
3238 oldspec = numpy.ma.masked_invalid(oldspec)
3239
3239
3240 for ind in range(oldspec.shape[1]):
3240 for ind in range(oldspec.shape[1]):
3241
3241
3242 spec = oldspec[:,ind]
3242 spec = oldspec[:,ind]
3243 aux = spec*fwindow
3243 aux = spec*fwindow
3244 max_spec = aux.max()
3244 max_spec = aux.max()
3245 m = list(aux).index(max_spec)
3245 m = list(aux).index(max_spec)
3246
3246
3247 #Smooth
3247 #Smooth
3248 if (smooth == 0): spec2 = spec
3248 if (smooth == 0): spec2 = spec
3249 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
3249 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
3250
3250
3251 # Calculo de Momentos
3251 # Calculo de Momentos
3252 bb = spec2[list(range(m,spec2.size))]
3252 bb = spec2[list(range(m,spec2.size))]
3253 bb = (bb<n0).nonzero()
3253 bb = (bb<n0).nonzero()
3254 bb = bb[0]
3254 bb = bb[0]
3255
3255
3256 ss = spec2[list(range(0,m + 1))]
3256 ss = spec2[list(range(0,m + 1))]
3257 ss = (ss<n0).nonzero()
3257 ss = (ss<n0).nonzero()
3258 ss = ss[0]
3258 ss = ss[0]
3259
3259
3260 if (bb.size == 0):
3260 if (bb.size == 0):
3261 bb0 = spec.size - 1 - m
3261 bb0 = spec.size - 1 - m
3262 else:
3262 else:
3263 bb0 = bb[0] - 1
3263 bb0 = bb[0] - 1
3264 if (bb0 < 0):
3264 if (bb0 < 0):
3265 bb0 = 0
3265 bb0 = 0
3266
3266
3267 if (ss.size == 0): ss1 = 1
3267 if (ss.size == 0): ss1 = 1
3268 else: ss1 = max(ss) + 1
3268 else: ss1 = max(ss) + 1
3269
3269
3270 if (ss1 > m): ss1 = m
3270 if (ss1 > m): ss1 = m
3271
3271
3272 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
3272 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
3273 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
3273 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
3274 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
3274 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
3275 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
3275 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
3276 snr = (spec2.mean()-n0)/n0
3276 snr = (spec2.mean()-n0)/n0
3277
3277
3278 if (snr < 1.e-20) :
3278 if (snr < 1.e-20) :
3279 snr = 1.e-20
3279 snr = 1.e-20
3280
3280
3281 vec_power[ind] = power
3281 vec_power[ind] = power
3282 vec_fd[ind] = fd
3282 vec_fd[ind] = fd
3283 vec_w[ind] = w
3283 vec_w[ind] = w
3284 vec_snr[ind] = snr
3284 vec_snr[ind] = snr
3285
3285
3286 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
3286 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
3287 return moments
3287 return moments
3288
3288
3289 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
3289 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
3290
3290
3291 nProf = dataOut.nProfiles
3291 nProf = dataOut.nProfiles
3292 heights = dataOut.heightList
3292 heights = dataOut.heightList
3293 nHei = len(heights)
3293 nHei = len(heights)
3294 channels = dataOut.channelList
3294 channels = dataOut.channelList
3295 nChan = len(channels)
3295 nChan = len(channels)
3296 crosspairs = dataOut.groupList
3296 crosspairs = dataOut.groupList
3297 nPairs = len(crosspairs)
3297 nPairs = len(crosspairs)
3298 #Separar espectros incoherentes de coherentes snr > 20 dB'
3298 #Separar espectros incoherentes de coherentes snr > 20 dB'
3299 snr_th = 10**(snrth/10.0)
3299 snr_th = 10**(snrth/10.0)
3300 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
3300 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
3301 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
3301 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
3302 my_incoh_aver = numpy.zeros([nChan, nHei])
3302 my_incoh_aver = numpy.zeros([nChan, nHei])
3303 my_coh_aver = numpy.zeros([nChan, nHei])
3303 my_coh_aver = numpy.zeros([nChan, nHei])
3304
3304
3305 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3305 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3306 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3306 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3307 coh_aver = numpy.zeros([nChan, nHei])
3307 coh_aver = numpy.zeros([nChan, nHei])
3308
3308
3309 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3309 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3310 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3310 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3311 incoh_aver = numpy.zeros([nChan, nHei])
3311 incoh_aver = numpy.zeros([nChan, nHei])
3312 power = numpy.sum(spectra, axis=1)
3312 power = numpy.sum(spectra, axis=1)
3313
3313
3314 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
3314 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
3315 if hei_th == None : hei_th = numpy.array([60,300,650])
3315 if hei_th == None : hei_th = numpy.array([60,300,650])
3316 for ic in range(nPairs):
3316 for ic in range(nPairs):
3317 pair = crosspairs[ic]
3317 pair = crosspairs[ic]
3318 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
3318 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
3319 s_n0 = power[pair[0],:]/noise[pair[0]]
3319 s_n0 = power[pair[0],:]/noise[pair[0]]
3320 s_n1 = power[pair[1],:]/noise[pair[1]]
3320 s_n1 = power[pair[1],:]/noise[pair[1]]
3321 valid1 =(s_n0>=snr_th).nonzero()
3321 valid1 =(s_n0>=snr_th).nonzero()
3322 valid2 = (s_n1>=snr_th).nonzero()
3322 valid2 = (s_n1>=snr_th).nonzero()
3323 valid1 = numpy.array(valid1[0])
3323 valid1 = numpy.array(valid1[0])
3324 valid2 = numpy.array(valid2[0])
3324 valid2 = numpy.array(valid2[0])
3325 valid = valid1
3325 valid = valid1
3326 for iv in range(len(valid2)):
3326 for iv in range(len(valid2)):
3327 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3327 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3328 if len(indv[0]) == 0 :
3328 if len(indv[0]) == 0 :
3329 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3329 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3330 if len(valid)>0:
3330 if len(valid)>0:
3331 my_coh_aver[pair[0],valid]=1
3331 my_coh_aver[pair[0],valid]=1
3332 my_coh_aver[pair[1],valid]=1
3332 my_coh_aver[pair[1],valid]=1
3333 # si la coherencia es mayor a la coherencia threshold los datos se toman
3333 # si la coherencia es mayor a la coherencia threshold los datos se toman
3334 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)))
3334 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)))
3335 for ih in range(len(hei_th)):
3335 for ih in range(len(hei_th)):
3336 hvalid = (heights>hei_th[ih]).nonzero()
3336 hvalid = (heights>hei_th[ih]).nonzero()
3337 hvalid = hvalid[0]
3337 hvalid = hvalid[0]
3338 if len(hvalid)>0:
3338 if len(hvalid)>0:
3339 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
3339 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
3340 valid = valid[0]
3340 valid = valid[0]
3341 if len(valid)>0:
3341 if len(valid)>0:
3342 my_coh_aver[pair[0],hvalid[valid]] =1
3342 my_coh_aver[pair[0],hvalid[valid]] =1
3343 my_coh_aver[pair[1],hvalid[valid]] =1
3343 my_coh_aver[pair[1],hvalid[valid]] =1
3344
3344
3345 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
3345 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
3346 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
3346 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
3347 incoh_echoes = incoh_echoes[0]
3347 incoh_echoes = incoh_echoes[0]
3348 if len(incoh_echoes) > 0:
3348 if len(incoh_echoes) > 0:
3349 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3349 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3350 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3350 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3351 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3351 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3352 my_incoh_aver[pair[0],incoh_echoes] = 1
3352 my_incoh_aver[pair[0],incoh_echoes] = 1
3353 my_incoh_aver[pair[1],incoh_echoes] = 1
3353 my_incoh_aver[pair[1],incoh_echoes] = 1
3354
3354
3355
3355
3356 for ic in range(nPairs):
3356 for ic in range(nPairs):
3357 pair = crosspairs[ic]
3357 pair = crosspairs[ic]
3358
3358
3359 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
3359 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
3360 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
3360 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
3361 valid1 = numpy.array(valid1[0])
3361 valid1 = numpy.array(valid1[0])
3362 valid2 = numpy.array(valid2[0])
3362 valid2 = numpy.array(valid2[0])
3363 valid = valid1
3363 valid = valid1
3364
3364
3365 for iv in range(len(valid2)):
3365 for iv in range(len(valid2)):
3366
3366
3367 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3367 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3368 if len(indv[0]) == 0 :
3368 if len(indv[0]) == 0 :
3369 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3369 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3370 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
3370 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
3371 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
3371 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
3372 valid1 = numpy.array(valid1[0])
3372 valid1 = numpy.array(valid1[0])
3373 valid2 = numpy.array(valid2[0])
3373 valid2 = numpy.array(valid2[0])
3374 incoh_echoes = valid1
3374 incoh_echoes = valid1
3375 for iv in range(len(valid2)):
3375 for iv in range(len(valid2)):
3376
3376
3377 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3377 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3378 if len(indv[0]) == 0 :
3378 if len(indv[0]) == 0 :
3379 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
3379 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
3380
3380
3381 if len(valid)>0:
3381 if len(valid)>0:
3382 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
3382 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
3383 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
3383 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
3384 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
3384 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
3385 coh_aver[pair[0],valid]=1
3385 coh_aver[pair[0],valid]=1
3386 coh_aver[pair[1],valid]=1
3386 coh_aver[pair[1],valid]=1
3387 if len(incoh_echoes)>0:
3387 if len(incoh_echoes)>0:
3388 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3388 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3389 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3389 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3390 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3390 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3391 incoh_aver[pair[0],incoh_echoes]=1
3391 incoh_aver[pair[0],incoh_echoes]=1
3392 incoh_aver[pair[1],incoh_echoes]=1
3392 incoh_aver[pair[1],incoh_echoes]=1
3393 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
3393 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
3394
3394
3395
3395 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
3396 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
3396
3397
3397 nProf = dataOut.nProfiles
3398 nProf = dataOut.nProfiles
3398 heights = dataOut.heightList
3399 heights = dataOut.heightList
3399 nHei = len(heights)
3400 nHei = len(heights)
3400 channels = dataOut.channelList
3401 channels = dataOut.channelList
3401 nChan = len(channels)
3402 nChan = len(channels)
3402 crosspairs = dataOut.groupList
3403 crosspairs = dataOut.groupList
3403 nPairs = len(crosspairs)
3404 nPairs = len(crosspairs)
3404
3405
3405 absc = dataOut.abscissaList[:-1]
3406 absc = dataOut.abscissaList[:-1]
3406 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
3407 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
3407 clean_coh_spectra = spectra.copy()
3408 clean_coh_spectra = spectra.copy()
3408 clean_coh_cspectra = cspectra.copy()
3409 clean_coh_cspectra = cspectra.copy()
3409 clean_coh_aver = coh_aver.copy()
3410 clean_coh_aver = coh_aver.copy()
3410
3411
3411 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
3412 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
3412 coh_th = 0.75
3413 coh_th = 0.75
3413
3414
3414 rtime0 = [6,18] # periodo sin ESF
3415 rtime0 = [6,18] # periodo sin ESF
3415 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
3416 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
3416
3417
3417 time = index*5./60 # en base a 5 min de proceso
3418 time = index*5./60 # en base a 5 min de proceso
3418 if clean_coh_echoes == 1 :
3419 if clean_coh_echoes == 1 :
3419 for ind in range(nChan):
3420 for ind in range(nChan):
3420 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
3421 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
3421 spwd = data_param[:,3]
3422 spwd = data_param[:,3]
3422 # 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
3423 # 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
3423 # para obtener spwd
3424 # para obtener spwd
3424 for ic in range(nPairs):
3425 for ic in range(nPairs):
3425 pair = crosspairs[ic]
3426 pair = crosspairs[ic]
3426 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)))
3427 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)))
3427 for ih in range(nHei) :
3428 for ih in range(nHei) :
3428 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
3429 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
3429 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
3430 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
3430 # Checking coherence
3431 # Checking coherence
3431 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
3432 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
3432 # Checking spectral widths
3433 # Checking spectral widths
3433 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
3434 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
3434 # satelite
3435 # satelite
3435 clean_coh_spectra[pair,ih,:] = 0.0
3436 clean_coh_spectra[pair,ih,:] = 0.0
3436 clean_coh_cspectra[ic,ih,:] = 0.0
3437 clean_coh_cspectra[ic,ih,:] = 0.0
3437 clean_coh_aver[pair,ih] = 0
3438 clean_coh_aver[pair,ih] = 0
3438 else :
3439 else :
3439 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
3440 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
3440 # Especial event like sun.
3441 # Especial event like sun.
3441 clean_coh_spectra[pair,ih,:] = 0.0
3442 clean_coh_spectra[pair,ih,:] = 0.0
3442 clean_coh_cspectra[ic,ih,:] = 0.0
3443 clean_coh_cspectra[ic,ih,:] = 0.0
3443 clean_coh_aver[pair,ih] = 0
3444 clean_coh_aver[pair,ih] = 0
3444
3445
3445 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
3446 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
3446
3447
3447 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
3448 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
3448
3449
3449 rfunc = cspectra.copy()
3450 rfunc = cspectra.copy()
3450 n_funct = len(rfunc[0,:,0,0])
3451 n_funct = len(rfunc[0,:,0,0])
3451 val_spc = spectra*0.0
3452 val_spc = spectra*0.0
3452 val_cspc = cspectra*0.0
3453 val_cspc = cspectra*0.0
3453 in_sat_spectra = spectra.copy()
3454 in_sat_spectra = spectra.copy()
3454 in_sat_cspectra = cspectra.copy()
3455 in_sat_cspectra = cspectra.copy()
3455
3456
3456 min_hei = 200
3457 min_hei = 200
3457 nProf = dataOut.nProfiles
3458 nProf = dataOut.nProfiles
3458 heights = dataOut.heightList
3459 heights = dataOut.heightList
3459 nHei = len(heights)
3460 nHei = len(heights)
3460 channels = dataOut.channelList
3461 channels = dataOut.channelList
3461 nChan = len(channels)
3462 nChan = len(channels)
3462 crosspairs = dataOut.groupList
3463 crosspairs = dataOut.groupList
3463 nPairs = len(crosspairs)
3464 nPairs = len(crosspairs)
3464 hval=(heights >= min_hei).nonzero()
3465 hval=(heights >= min_hei).nonzero()
3465 ih=hval[0]
3466 ih=hval[0]
3466 for ih in range(hval[0][0],nHei):
3467 for ih in range(hval[0][0],nHei):
3467 for ifreq in range(nProf):
3468 for ifreq in range(nProf):
3468 for ii in range(n_funct):
3469 for ii in range(n_funct):
3469
3470
3470 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
3471 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
3471 val = (numpy.isfinite(func2clean)==True).nonzero()
3472 val = (numpy.isfinite(func2clean)==True).nonzero()
3472 if len(val)>0:
3473 if len(val)>0:
3473 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
3474 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
3474 if min_val <= -40 : min_val = -40
3475 if min_val <= -40 : min_val = -40
3475 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
3476 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
3476 if max_val >= 200 : max_val = 200
3477 if max_val >= 200 : max_val = 200
3477 step = 1
3478 step = 1
3478 #Getting bins and the histogram
3479 #Getting bins and the histogram
3479 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
3480 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
3480 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
3481 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
3481 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
3482 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
3482 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
3483 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
3483 parg = [numpy.amax(y_dist),mean,sigma]
3484 parg = [numpy.amax(y_dist),mean,sigma]
3484 try :
3485 try :
3485 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
3486 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
3486 mode = gauss_fit[1]
3487 mode = gauss_fit[1]
3487 stdv = gauss_fit[2]
3488 stdv = gauss_fit[2]
3488 except:
3489 except:
3489 mode = mean
3490 mode = mean
3490 stdv = sigma
3491 stdv = sigma
3491
3492
3492 #Removing echoes greater than mode + 3*stdv
3493 #Removing echoes greater than mode + 3*stdv
3493 factor_stdv = 2.5
3494 factor_stdv = 2.5
3494 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
3495 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
3495
3496
3496 if len(noval[0]) > 0:
3497 if len(noval[0]) > 0:
3497 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
3498 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
3498 cross_pairs = crosspairs[ii]
3499 cross_pairs = crosspairs[ii]
3499 #Getting coherent echoes which are removed.
3500 #Getting coherent echoes which are removed.
3500 if len(novall[0]) > 0:
3501 if len(novall[0]) > 0:
3501 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
3502 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
3502 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
3503 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
3503 val_cspc[novall[0],ii,ifreq,ih] = 1
3504 val_cspc[novall[0],ii,ifreq,ih] = 1
3504 #Removing coherent from ISR data
3505 #Removing coherent from ISR data
3505 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
3506 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
3506 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
3507 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
3507 cspectra[noval,ii,ifreq,ih] = numpy.nan
3508 cspectra[noval,ii,ifreq,ih] = numpy.nan
3508
3509
3509 #Getting average of the spectra and cross-spectra from incoherent echoes.
3510 #Getting average of the spectra and cross-spectra from incoherent echoes.
3510 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
3511 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
3511 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
3512 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
3512 for ih in range(nHei):
3513 for ih in range(nHei):
3513 for ifreq in range(nProf):
3514 for ifreq in range(nProf):
3514 for ich in range(nChan):
3515 for ich in range(nChan):
3515 tmp = spectra[:,ich,ifreq,ih]
3516 tmp = spectra[:,ich,ifreq,ih]
3516 valid = (numpy.isfinite(tmp[:])==True).nonzero()
3517 valid = (numpy.isfinite(tmp[:])==True).nonzero()
3517 if len(valid[0]) >0 :
3518 if len(valid[0]) >0 :
3518 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3519 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3519 for icr in range(nPairs):
3520 for icr in range(nPairs):
3520 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
3521 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
3521 valid = (numpy.isfinite(tmp)==True).nonzero()
3522 valid = (numpy.isfinite(tmp)==True).nonzero()
3522 if len(valid[0]) > 0:
3523 if len(valid[0]) > 0:
3523 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3524 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3524 #Removing fake coherent echoes (at least 4 points around the point)
3525 #Removing fake coherent echoes (at least 4 points around the point)
3525 val_spectra = numpy.sum(val_spc,0)
3526 val_spectra = numpy.sum(val_spc,0)
3526 val_cspectra = numpy.sum(val_cspc,0)
3527 val_cspectra = numpy.sum(val_cspc,0)
3527
3528
3528 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
3529 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
3529 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
3530 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
3530
3531
3531 for i in range(nChan):
3532 for i in range(nChan):
3532 for j in range(nProf):
3533 for j in range(nProf):
3533 for k in range(nHei):
3534 for k in range(nHei):
3534 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
3535 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
3535 val_spc[:,i,j,k] = 0.0
3536 val_spc[:,i,j,k] = 0.0
3536 for i in range(nPairs):
3537 for i in range(nPairs):
3537 for j in range(nProf):
3538 for j in range(nProf):
3538 for k in range(nHei):
3539 for k in range(nHei):
3539 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
3540 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
3540 val_cspc[:,i,j,k] = 0.0
3541 val_cspc[:,i,j,k] = 0.0
3541
3542
3542 tmp_sat_spectra = spectra.copy()
3543 tmp_sat_spectra = spectra.copy()
3543 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
3544 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
3544 tmp_sat_cspectra = cspectra.copy()
3545 tmp_sat_cspectra = cspectra.copy()
3545 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
3546 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
3546 val = (val_spc > 0).nonzero()
3547 val = (val_spc > 0).nonzero()
3547 if len(val[0]) > 0:
3548 if len(val[0]) > 0:
3548 tmp_sat_spectra[val] = in_sat_spectra[val]
3549 tmp_sat_spectra[val] = in_sat_spectra[val]
3549
3550
3550 val = (val_cspc > 0).nonzero()
3551 val = (val_cspc > 0).nonzero()
3551 if len(val[0]) > 0:
3552 if len(val[0]) > 0:
3552 tmp_sat_cspectra[val] = in_sat_cspectra[val]
3553 tmp_sat_cspectra[val] = in_sat_cspectra[val]
3553
3554
3554 #Getting average of the spectra and cross-spectra from incoherent echoes.
3555 #Getting average of the spectra and cross-spectra from incoherent echoes.
3555 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
3556 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
3556 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
3557 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
3557 for ih in range(nHei):
3558 for ih in range(nHei):
3558 for ifreq in range(nProf):
3559 for ifreq in range(nProf):
3559 for ich in range(nChan):
3560 for ich in range(nChan):
3560 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
3561 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
3561 valid = (numpy.isfinite(tmp)).nonzero()
3562 valid = (numpy.isfinite(tmp)).nonzero()
3562 if len(valid[0]) > 0:
3563 if len(valid[0]) > 0:
3563 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3564 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3564
3565
3565 for icr in range(nPairs):
3566 for icr in range(nPairs):
3566 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
3567 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
3567 valid = (numpy.isfinite(tmp)).nonzero()
3568 valid = (numpy.isfinite(tmp)).nonzero()
3568 if len(valid[0]) > 0:
3569 if len(valid[0]) > 0:
3569 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3570 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3570 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
3571 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
3571
3572
3572 def REM_ISOLATED_POINTS(self,array,rth):
3573 def REM_ISOLATED_POINTS(self,array,rth):
3573 if rth == None : rth = 4
3574 if rth == None : rth = 4
3574 num_prof = len(array[0,:,0])
3575 num_prof = len(array[0,:,0])
3575 num_hei = len(array[0,0,:])
3576 num_hei = len(array[0,0,:])
3576 n2d = len(array[:,0,0])
3577 n2d = len(array[:,0,0])
3577
3578
3578 for ii in range(n2d) :
3579 for ii in range(n2d) :
3579 tmp = array[ii,:,:]
3580 tmp = array[ii,:,:]
3580 tmp = numpy.reshape(tmp,num_prof*num_hei)
3581 tmp = numpy.reshape(tmp,num_prof*num_hei)
3581 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
3582 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
3582 indxs2 = (tmp > 0).nonzero()
3583 indxs2 = (tmp > 0).nonzero()
3583 indxs1 = (indxs1[0])
3584 indxs1 = (indxs1[0])
3584 indxs2 = indxs2[0]
3585 indxs2 = indxs2[0]
3585 indxs = None
3586 indxs = None
3586 for iv in range(len(indxs2)):
3587 for iv in range(len(indxs2)):
3587 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
3588 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
3588 if len(indv[0]) > 0 :
3589 if len(indv[0]) > 0 :
3589 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
3590 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
3590 indxs = indxs[1:]
3591 indxs = indxs[1:]
3591 if len(indxs) < 4 :
3592 if len(indxs) < 4 :
3592 array[ii,:,:] = 0.
3593 array[ii,:,:] = 0.
3593 return
3594 return
3594
3595
3595 xpos = numpy.mod(indxs ,num_hei)
3596 xpos = numpy.mod(indxs ,num_hei)
3596 ypos = (indxs / num_hei)
3597 ypos = (indxs / num_hei)
3597 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
3598 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
3598 xpos = xpos[sx]
3599 xpos = xpos[sx]
3599 ypos = ypos[sx]
3600 ypos = ypos[sx]
3600 # *********************************** Cleaning isolated points **********************************
3601 # *********************************** Cleaning isolated points **********************************
3601 ic = 0
3602 ic = 0
3602 while True :
3603 while True :
3603 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
3604 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
3604 no_coh1 = (numpy.isfinite(r)==True).nonzero()
3605 no_coh1 = (numpy.isfinite(r)==True).nonzero()
3605 no_coh2 = (r <= rth).nonzero()
3606 no_coh2 = (r <= rth).nonzero()
3606 no_coh1 = numpy.array(no_coh1[0])
3607 no_coh1 = numpy.array(no_coh1[0])
3607 no_coh2 = numpy.array(no_coh2[0])
3608 no_coh2 = numpy.array(no_coh2[0])
3608 no_coh = None
3609 no_coh = None
3609 for iv in range(len(no_coh2)):
3610 for iv in range(len(no_coh2)):
3610 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
3611 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
3611 if len(indv[0]) > 0 :
3612 if len(indv[0]) > 0 :
3612 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
3613 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
3613 no_coh = no_coh[1:]
3614 no_coh = no_coh[1:]
3614 if len(no_coh) < 4 :
3615 if len(no_coh) < 4 :
3615 xpos[ic] = numpy.nan
3616 xpos[ic] = numpy.nan
3616 ypos[ic] = numpy.nan
3617 ypos[ic] = numpy.nan
3617
3618
3618 ic = ic + 1
3619 ic = ic + 1
3619 if (ic == len(indxs)) :
3620 if (ic == len(indxs)) :
3620 break
3621 break
3621 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
3622 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
3622 if len(indxs[0]) < 4 :
3623 if len(indxs[0]) < 4 :
3623 array[ii,:,:] = 0.
3624 array[ii,:,:] = 0.
3624 return
3625 return
3625
3626
3626 xpos = xpos[indxs[0]]
3627 xpos = xpos[indxs[0]]
3627 ypos = ypos[indxs[0]]
3628 ypos = ypos[indxs[0]]
3628 for i in range(0,len(ypos)):
3629 for i in range(0,len(ypos)):
3629 ypos[i]=int(ypos[i])
3630 ypos[i]=int(ypos[i])
3630 junk = tmp
3631 junk = tmp
3631 tmp = junk*0.0
3632 tmp = junk*0.0
3632
3633
3633 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
3634 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
3634 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
3635 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
3635 return array
3636 return array
3636
3637
3637 def moments(self,doppler,yarray,npoints):
3638 def moments(self,doppler,yarray,npoints):
3638 ytemp = yarray
3639 ytemp = yarray
3639 val = (ytemp > 0).nonzero()
3640 val = (ytemp > 0).nonzero()
3640 val = val[0]
3641 val = val[0]
3641 if len(val) == 0 : val = range(npoints-1)
3642 if len(val) == 0 : val = range(npoints-1)
3642
3643
3643 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
3644 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
3644 ytemp[len(ytemp):] = [ynew]
3645 ytemp[len(ytemp):] = [ynew]
3645
3646
3646 index = 0
3647 index = 0
3647 index = numpy.argmax(ytemp)
3648 index = numpy.argmax(ytemp)
3648 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
3649 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
3649 ytemp = ytemp[0:npoints-1]
3650 ytemp = ytemp[0:npoints-1]
3650
3651
3651 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
3652 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
3652 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
3653 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
3653 return [fmom,numpy.sqrt(smom)]
3654 return [fmom,numpy.sqrt(smom)]
3654
3655
3655 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):
3656 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):
3656 if not self.isConfig:
3657 if not self.isConfig:
3657 self.setup(dataOut = dataOut,groupList=groupList,path=path,file=file,filec=filec)
3658 self.setup(dataOut = dataOut,groupList=groupList,path=path,file=file,filec=filec)
3658 self.isConfig = True
3659 self.isConfig = True
3659
3660
3660 if not numpy.any(proc):
3661 if not numpy.any(proc):
3661 if numpy.any(taver):
3662 if numpy.any(taver):
3662 taver = int(taver)
3663 taver = int(taver)
3663 else :
3664 else :
3664 taver = 5
3665 taver = 5
3665 tini = time.localtime(dataOut.utctime)
3666 tini = time.localtime(dataOut.utctime)
3666 if (tini.tm_min % taver) == 0 and (tini.tm_sec < 5 and self.fint==0):
3667 if (tini.tm_min % taver) == 0 and (tini.tm_sec < 5 and self.fint==0):
3667 self.index = 0
3668 self.index = 0
3668 jspc = self.buffer
3669 jspc = self.buffer
3669 jcspc = self.buffer2
3670 jcspc = self.buffer2
3670 jnoise = self.buffer3
3671 jnoise = self.buffer3
3671 self.buffer = dataOut.data_spc
3672 self.buffer = dataOut.data_spc
3672 self.buffer2 = dataOut.data_cspc
3673 self.buffer2 = dataOut.data_cspc
3673 self.buffer3 = dataOut.noise
3674 self.buffer3 = dataOut.noise
3674 self.fint = 1
3675 self.fint = 1
3675 if numpy.any(jspc) :
3676 if numpy.any(jspc) :
3676 jspc = numpy.reshape(jspc ,(int(len(jspc) / self.nChannels) , self.nChannels ,self.nProf,self.nHeights ))
3677 jspc = numpy.reshape(jspc ,(int(len(jspc) / self.nChannels) , self.nChannels ,self.nProf,self.nHeights ))
3677 jcspc = numpy.reshape(jcspc ,(int(len(jcspc) /int(self.nChannels/2)),int(self.nChannels/2),self.nProf,self.nHeights ))
3678 jcspc = numpy.reshape(jcspc ,(int(len(jcspc) /int(self.nChannels/2)),int(self.nChannels/2),self.nProf,self.nHeights ))
3678 jnoise = numpy.reshape(jnoise,(int(len(jnoise)/ self.nChannels) , self.nChannels))
3679 jnoise = numpy.reshape(jnoise,(int(len(jnoise)/ self.nChannels) , self.nChannels))
3679 else:
3680 else:
3680 dataOut.flagNoData = True
3681 dataOut.flagNoData = True
3681 return dataOut
3682 return dataOut
3682 else :
3683 else :
3683 if (tini.tm_min % taver) == 0 :
3684 if (tini.tm_min % taver) == 0 :
3684 self.fint = 1
3685 self.fint = 1
3685 else :
3686 else :
3686 self.fint = 0
3687 self.fint = 0
3687
3688
3688 self.index += 1
3689 self.index += 1
3689 if numpy.any(self.buffer):
3690 if numpy.any(self.buffer):
3690 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
3691 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
3691 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
3692 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
3692 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
3693 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
3693 else:
3694 else:
3694 self.buffer = dataOut.data_spc
3695 self.buffer = dataOut.data_spc
3695 self.buffer2 = dataOut.data_cspc
3696 self.buffer2 = dataOut.data_cspc
3696 self.buffer3 = dataOut.noise
3697 self.buffer3 = dataOut.noise
3697 dataOut.flagNoData = True
3698 dataOut.flagNoData = True
3698 return dataOut
3699 return dataOut
3699
3700
3700 jnoise = jnoise/self.N# creo que falta dividirlo entre N
3701 jnoise = jnoise/self.N# creo que falta dividirlo entre N
3701 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
3702 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
3702 index = tini.tm_hour*12+tini.tm_min/taver
3703 index = tini.tm_hour*12+tini.tm_min/taver
3703 dataOut.index = index
3704 dataOut.index = index
3704 jspc = jspc/self.N/self.N
3705 jspc = jspc/self.N/self.N
3705 jcspc = jcspc/self.N/self.N
3706 jcspc = jcspc/self.N/self.N
3706
3707
3707 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
3708 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
3708 jspectra = tmp_spectra * len(jspc[:,0,0,0])
3709 jspectra = tmp_spectra * len(jspc[:,0,0,0])
3709 jcspectra = tmp_cspectra * len(jspc[:,0,0,0])
3710 jcspectra = tmp_cspectra * len(jspc[:,0,0,0])
3710
3711
3711 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, self.snrth,coh_th, hei_th)
3712 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, self.snrth,coh_th, hei_th)
3712 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(self.snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
3713 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(self.snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
3713
3714
3714 dataOut.data_spc = incoh_spectra
3715 dataOut.data_spc = incoh_spectra
3715 dataOut.data_cspc = incoh_cspectra
3716 dataOut.data_cspc = incoh_cspectra
3716 clean_num_aver = incoh_aver * len(jspc[:,0,0,0])
3717 clean_num_aver = incoh_aver * len(jspc[:,0,0,0])
3717 coh_num_aver = clean_coh_aver* len(jspc[:,0,0,0])
3718 coh_num_aver = clean_coh_aver* len(jspc[:,0,0,0])
3718 dataOut.clean_num_aver = clean_num_aver
3719 dataOut.clean_num_aver = clean_num_aver
3719 dataOut.coh_num_aver = coh_num_aver
3720 dataOut.coh_num_aver = coh_num_aver
3720
3721
3721 #List of possible combinations
3722 #listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
3723 #indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
3724 #if getSNR:
3725 # listChannels = groupArray.reshape((groupArray.size))
3726 # listChannels.sort()
3727 # print("AQUI ESTOY")
3728 # dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
3729 else:
3722 else:
3730 clean_num_aver = dataOut.clean_num_aver
3723 clean_num_aver = dataOut.clean_num_aver
3731 coh_num_aver = dataOut.coh_num_aver
3724 coh_num_aver = dataOut.coh_num_aver
3732 dataOut.data_spc = dataOut.tmp_spectra_i
3725 dataOut.data_spc = dataOut.tmp_spectra_i
3733 dataOut.data_cspc = dataOut.tmp_cspectra_i
3726 dataOut.data_cspc = dataOut.tmp_cspectra_i
3734 clean_coh_spectra = dataOut.tmp_spectra_c
3727 clean_coh_spectra = dataOut.tmp_spectra_c
3735 clean_coh_cspectra = dataOut.tmp_cspectra_c
3728 clean_coh_cspectra = dataOut.tmp_cspectra_c
3736 jspectra = dataOut.data_spc+clean_coh_spectra
3729 jspectra = dataOut.data_spc+clean_coh_spectra
3737 nHeights = len(dataOut.heightList) # nhei
3730 nHeights = len(dataOut.heightList) # nhei
3738 nProf = int(dataOut.nProfiles)
3731 nProf = int(dataOut.nProfiles)
3739 dataOut.nProfiles = nProf
3732 dataOut.nProfiles = nProf
3740 dataOut.data_param = None
3733 dataOut.data_param = None
3741 dataOut.data_paramC = None
3734 dataOut.data_paramC = None
3742 dataOut.code = numpy.array([[-1.,-1.,1.],[1.,1.,-1.]])
3735 dataOut.code = numpy.array([[-1.,-1.,1.],[1.,1.,-1.]])
3743 #M=600
3736 #M=600
3744 #N=200
3737 #N=200
3745 dataOut.flagDecodeData=True
3738 dataOut.flagDecodeData=True
3746 M = int(dataOut.normFactor)
3739 M = int(dataOut.normFactor)
3747 N = int(dataOut.nFFTPoints)
3740 N = int(dataOut.nFFTPoints)
3748 dataOut.nFFTPoints = N
3741 dataOut.nFFTPoints = N
3749 dataOut.nIncohInt= int(dataOut.nIncohInt)
3742 dataOut.nIncohInt= int(dataOut.nIncohInt)
3750 dataOut.nProfiles = int(dataOut.nProfiles)
3743 dataOut.nProfiles = int(dataOut.nProfiles)
3751 dataOut.nCohInt = int(dataOut.nCohInt)
3744 dataOut.nCohInt = int(dataOut.nCohInt)
3752 #dataOut.nFFTPoints=nprofs
3745 #dataOut.nFFTPoints=nprofs
3753 #dataOut.normFactor = nprofs
3746 #dataOut.normFactor = nprofs
3754 dataOut.channelList = channelList
3747 dataOut.channelList = channelList
3755 #dataOut.ippFactor=1
3748 #dataOut.ippFactor=1
3756 #ipp = ipp/150*1.e-3
3749 #ipp = ipp/150*1.e-3
3757 vmax = (300000000/49920000.0/2) / (dataOut.ippSeconds)
3750 vmax = (300000000/49920000.0/2) / (dataOut.ippSeconds)
3758 #dataOut.ippSeconds=ipp
3751 #dataOut.ippSeconds=ipp
3759 absc = vmax*( numpy.arange(nProf,dtype='float')-nProf/2.)/nProf
3752 absc = vmax*( numpy.arange(nProf,dtype='float')-nProf/2.)/nProf
3760 if path != None:
3753 if path != None:
3761 sys.path.append(path)
3754 sys.path.append(path)
3762 self.library = importlib.import_module(file)
3755 self.library = importlib.import_module(file)
3763 constants = self.library.setConstants(dataOut)
3756 constants = self.library.setConstants(dataOut)
3764 constants['M'] = M
3757 constants['M'] = M
3765 dataOut.constants = constants
3758 dataOut.constants = constants
3766
3759
3767 #List of possible combinations
3760 #List of possible combinations
3768 listComb = itertools.combinations(numpy.arange(self.groupArray.shape[1]),2)
3761 listComb = itertools.combinations(numpy.arange(self.groupArray.shape[1]),2)
3769 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
3762 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
3770 if dataOut.data_paramC is None:
3763 if dataOut.data_paramC is None:
3771 dataOut.data_paramC = numpy.zeros((self.nGroups*4, self.nHeights ,2))*numpy.nan
3764 dataOut.data_paramC = numpy.zeros((self.nGroups*4, self.nHeights ,2))*numpy.nan
3772 for i in range(self.nGroups):
3765 for i in range(self.nGroups):
3773 coord = self.groupArray[i,:]
3766 coord = self.groupArray[i,:]
3774 #Input data array
3767 #Input data array
3775 data = dataOut.data_spc[coord,:,:]/(self.M*self.N)
3768 data = dataOut.data_spc[coord,:,:]/(self.M*self.N)
3776 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
3769 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
3777
3770
3778 #Cross Spectra data array for Covariance Matrixes
3771 #Cross Spectra data array for Covariance Matrixes
3779 ind = 0
3772 ind = 0
3780 for pairs in listComb:
3773 for pairs in listComb:
3781 pairsSel = numpy.array([coord[x],coord[y]])
3774 pairsSel = numpy.array([coord[x],coord[y]])
3782 indCross[ind] = int(numpy.where(numpy.all(self.pairsArray == pairsSel, axis = 1))[0][0])
3775 indCross[ind] = int(numpy.where(numpy.all(self.pairsArray == pairsSel, axis = 1))[0][0])
3783 ind += 1
3776 ind += 1
3784 dataCross = dataOut.data_cspc[indCross,:,:]/(self.M*self.N)
3777 dataCross = dataOut.data_cspc[indCross,:,:]/(self.M*self.N)
3785 dataCross = dataCross**2
3778 dataCross = dataCross**2
3786 nhei = self.nHeights
3779 nhei = self.nHeights
3787 poweri = numpy.sum(dataOut.data_spc[:,1:self.nProf-0,:],axis=1)/clean_num_aver[:,:]
3780 poweri = numpy.sum(dataOut.data_spc[:,1:self.nProf-0,:],axis=1)/clean_num_aver[:,:]
3788
3781
3789 if i == 0 : my_noises = numpy.zeros(4,dtype=float)
3782 if i == 0 : my_noises = numpy.zeros(4,dtype=float)
3790 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(self.nProf-1)
3783 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(self.nProf-1)
3791 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(self.nProf-1)
3784 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(self.nProf-1)
3792 n0 = n0i
3785 n0 = n0i
3793 n1= n1i
3786 n1= n1i
3794 my_noises[2*i+0] = n0
3787 my_noises[2*i+0] = n0
3795 my_noises[2*i+1] = n1
3788 my_noises[2*i+1] = n1
3796 snrth = -15.0 # -4 -16 -25
3789 snrth = -15.0 # -4 -16 -25
3797 snrth = 10**(snrth/10.0)
3790 snrth = 10**(snrth/10.0)
3798 jvelr = numpy.zeros(self.nHeights, dtype = 'float')
3791 jvelr = numpy.zeros(self.nHeights, dtype = 'float')
3799 hvalid = [0]
3792 hvalid = [0]
3800 coh2 = abs(dataOut.data_cspc[i,1:self.nProf,:])**2/(dataOut.data_spc[0+i*2,1:self.nProf-0,:]*dataOut.data_spc[1+i*2,1:self.nProf-0,:])
3793 coh2 = abs(dataOut.data_cspc[i,1:self.nProf,:])**2/(dataOut.data_spc[0+i*2,1:self.nProf-0,:]*dataOut.data_spc[1+i*2,1:self.nProf-0,:])
3801
3794
3802 for h in range(self.nHeights):
3795 for h in range(self.nHeights):
3803 smooth = clean_num_aver[i+1,h]
3796 smooth = clean_num_aver[i+1,h]
3804 signalpn0 = (dataOut.data_spc[i*2,1:(self.nProf-0),h])/smooth
3797 signalpn0 = (dataOut.data_spc[i*2,1:(self.nProf-0),h])/smooth
3805 signalpn1 = (dataOut.data_spc[i*2+1,1:(self.nProf-0),h])/smooth
3798 signalpn1 = (dataOut.data_spc[i*2+1,1:(self.nProf-0),h])/smooth
3806 signal0 = signalpn0-n0
3799 signal0 = signalpn0-n0
3807 signal1 = signalpn1-n1
3800 signal1 = signalpn1-n1
3808 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3801 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3809 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3802 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3810 gamma = coh2[:,h]
3803 gamma = coh2[:,h]
3811 indxs = (numpy.isfinite(list(gamma))==True).nonzero()
3804 indxs = (numpy.isfinite(list(gamma))==True).nonzero()
3812 if len(indxs) >0:
3805 if len(indxs) >0:
3813 if numpy.nanmean(gamma) > 0.07:
3806 if numpy.nanmean(gamma) > 0.07:
3814 maxp0 = numpy.argmax(signal0*gamma)
3807 maxp0 = numpy.argmax(signal0*gamma)
3815 maxp1 = numpy.argmax(signal1*gamma)
3808 maxp1 = numpy.argmax(signal1*gamma)
3816 #print('usa gamma',numpy.nanmean(gamma))
3809 #print('usa gamma',numpy.nanmean(gamma))
3817 else:
3810 else:
3818 maxp0 = numpy.argmax(signal0)
3811 maxp0 = numpy.argmax(signal0)
3819 maxp1 = numpy.argmax(signal1)
3812 maxp1 = numpy.argmax(signal1)
3820 jvelr[h] = (self.absc[maxp0]+self.absc[maxp1])/2.
3813 jvelr[h] = (self.absc[maxp0]+self.absc[maxp1])/2.
3821 else: jvelr[h] = self.absc[0]
3814 else: jvelr[h] = self.absc[0]
3822 if snr0 > 0.1 and snr1 > 0.1: hvalid = numpy.concatenate((hvalid,h), axis=None)
3815 if snr0 > 0.1 and snr1 > 0.1: hvalid = numpy.concatenate((hvalid,h), axis=None)
3823 #print(maxp0,absc[maxp0],snr0,jvelr[h])
3816 #print(maxp0,absc[maxp0],snr0,jvelr[h])
3824
3817
3825 if len(hvalid)> 1: fd0 = numpy.median(jvelr[hvalid[1:]])*-1
3818 if len(hvalid)> 1: fd0 = numpy.median(jvelr[hvalid[1:]])*-1
3826 else: fd0 = numpy.nan
3819 else: fd0 = numpy.nan
3827 for h in range(self.nHeights):
3820 for h in range(self.nHeights):
3828 d = data[:,h]
3821 d = data[:,h]
3829 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
3822 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
3830 signalpn0 = (dataOut.data_spc[i*2,1:(self.nProf-0),h])/smooth
3823 signalpn0 = (dataOut.data_spc[i*2,1:(self.nProf-0),h])/smooth
3831 signalpn1 = (dataOut.data_spc[i*2+1,1:(self.nProf-0),h])/smooth
3824 signalpn1 = (dataOut.data_spc[i*2+1,1:(self.nProf-0),h])/smooth
3832 signal0 = signalpn0-n0
3825 signal0 = signalpn0-n0
3833 signal1 = signalpn1-n1
3826 signal1 = signalpn1-n1
3834 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3827 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3835 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3828 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3836 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
3829 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
3837 #Covariance Matrix
3830 #Covariance Matrix
3838 D = numpy.diag(d**2)
3831 D = numpy.diag(d**2)
3839 ind = 0
3832 ind = 0
3840 for pairs in listComb:
3833 for pairs in listComb:
3841 #Coordinates in Covariance Matrix
3834 #Coordinates in Covariance Matrix
3842 x = pairs[0]
3835 x = pairs[0]
3843 y = pairs[1]
3836 y = pairs[1]
3844 #Channel Index
3837 #Channel Index
3845 S12 = dataCross[ind,:,h]
3838 S12 = dataCross[ind,:,h]
3846 D12 = numpy.diag(S12)
3839 D12 = numpy.diag(S12)
3847 #Completing Covariance Matrix with Cross Spectras
3840 #Completing Covariance Matrix with Cross Spectras
3848 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
3841 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
3849 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
3842 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
3850 ind += 1
3843 ind += 1
3851 diagD = numpy.zeros(256)
3844 diagD = numpy.zeros(256)
3852
3845
3853 try:
3846 try:
3854 Dinv=numpy.linalg.inv(D)
3847 Dinv=numpy.linalg.inv(D)
3855 L=numpy.linalg.cholesky(Dinv)
3848 L=numpy.linalg.cholesky(Dinv)
3856 except:
3849 except:
3857 Dinv = D*numpy.nan
3850 Dinv = D*numpy.nan
3858 L= D*numpy.nan
3851 L= D*numpy.nan
3859 LT=L.T
3852 LT=L.T
3860
3853
3861 dp = numpy.dot(LT,d)
3854 dp = numpy.dot(LT,d)
3862 #Initial values
3855 #Initial values
3863 data_spc = dataOut.data_spc[coord,:,h]
3856 data_spc = dataOut.data_spc[coord,:,h]
3864 w = data_spc/data_spc
3857 w = data_spc/data_spc
3865 if filec != None:
3858 if filec != None:
3866 w = self.weightf.weightfit(w,tini.tm_year,tini.tm_yday,index,h,i)
3859 w = self.weightf.weightfit(w,tini.tm_year,tini.tm_yday,index,h,i)
3867 if (h>6)and(error1[3]<25):
3860 if (h>6)and(error1[3]<25):
3868 p0 = dataOut.data_param[i,:,h-1].copy()
3861 p0 = dataOut.data_param[i,:,h-1].copy()
3869 else:
3862 else:
3870 p0 = numpy.array(self.library.initialValuesFunction(data_spc*w, self.constants))# sin el i(data_spc, constants, i)
3863 p0 = numpy.array(self.library.initialValuesFunction(data_spc*w, self.constants))# sin el i(data_spc, constants, i)
3871 p0[3] = fd0
3864 p0[3] = fd0
3872
3865
3873 if filec != None:
3866 if filec != None:
3874 p0 = self.weightf.Vrfit(p0,tini.tm_year,tini.tm_yday,index,h,i)
3867 p0 = self.weightf.Vrfit(p0,tini.tm_year,tini.tm_yday,index,h,i)
3875
3868
3876 try:
3869 try:
3877 #Least Squares
3870 #Least Squares
3878 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,self.constants),full_output=True)
3871 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,self.constants),full_output=True)
3879 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
3872 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
3880 #Chi square error
3873 #Chi square error
3881 error0 = numpy.sum(infodict['fvec']**2)/(2*self.N)
3874 error0 = numpy.sum(infodict['fvec']**2)/(2*self.N)
3882 #Error with Jacobian
3875 #Error with Jacobian
3883 error1 = self.library.errorFunction(minp,self.constants,LT)
3876 error1 = self.library.errorFunction(minp,self.constants,LT)
3884
3877
3885 except:
3878 except:
3886 minp = p0*numpy.nan
3879 minp = p0*numpy.nan
3887 error0 = numpy.nan
3880 error0 = numpy.nan
3888 error1 = p0*numpy.nan
3881 error1 = p0*numpy.nan
3889 else :
3882 else :
3890 data_spc = dataOut.data_spc[coord,:,h]
3883 data_spc = dataOut.data_spc[coord,:,h]
3891 p0 = numpy.array(self.library.initialValuesFunction(data_spc, self.constants))
3884 p0 = numpy.array(self.library.initialValuesFunction(data_spc, self.constants))
3892 minp = p0*numpy.nan
3885 minp = p0*numpy.nan
3893 error0 = numpy.nan
3886 error0 = numpy.nan
3894 error1 = p0*numpy.nan
3887 error1 = p0*numpy.nan
3895 if dataOut.data_param is None:
3888 if dataOut.data_param is None:
3896 dataOut.data_param = numpy.zeros((self.nGroups, p0.size, self.nHeights ))*numpy.nan
3889 dataOut.data_param = numpy.zeros((self.nGroups, p0.size, self.nHeights ))*numpy.nan
3897 dataOut.data_error = numpy.zeros((self.nGroups, p0.size + 1, self.nHeights ))*numpy.nan
3890 dataOut.data_error = numpy.zeros((self.nGroups, p0.size + 1, self.nHeights ))*numpy.nan
3898 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
3891 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
3899 dataOut.data_param[i,:,h] = minp
3892 dataOut.data_param[i,:,h] = minp
3900
3893
3901 for ht in range(self.nHeights-1) :
3894 for ht in range(self.nHeights-1) :
3902 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
3895 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
3903 dataOut.data_paramC[4*i,ht,1] = smooth
3896 dataOut.data_paramC[4*i,ht,1] = smooth
3904 signalpn0 = (clean_coh_spectra[i*2 ,1:(self.nProf-0),ht])/smooth #coh_spectra
3897 signalpn0 = (clean_coh_spectra[i*2 ,1:(self.nProf-0),ht])/smooth #coh_spectra
3905 signalpn1 = (clean_coh_spectra[i*2+1,1:(self.nProf-0),ht])/smooth
3898 signalpn1 = (clean_coh_spectra[i*2+1,1:(self.nProf-0),ht])/smooth
3906 val0 = (signalpn0 > 0).nonzero()
3899 val0 = (signalpn0 > 0).nonzero()
3907 val0 = val0[0]
3900 val0 = val0[0]
3908 if len(val0) == 0 : val0_npoints = self.nProf
3901 if len(val0) == 0 : val0_npoints = self.nProf
3909 else : val0_npoints = len(val0)
3902 else : val0_npoints = len(val0)
3910
3903
3911 val1 = (signalpn1 > 0).nonzero()
3904 val1 = (signalpn1 > 0).nonzero()
3912 val1 = val1[0]
3905 val1 = val1[0]
3913 if len(val1) == 0 : val1_npoints = self.nProf
3906 if len(val1) == 0 : val1_npoints = self.nProf
3914 else : val1_npoints = len(val1)
3907 else : val1_npoints = len(val1)
3915
3908
3916 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
3909 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
3917 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
3910 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
3918
3911
3919 signal0 = (signalpn0-n0)
3912 signal0 = (signalpn0-n0)
3920 vali = (signal0 < 0).nonzero()
3913 vali = (signal0 < 0).nonzero()
3921 vali = vali[0]
3914 vali = vali[0]
3922 if len(vali) > 0 : signal0[vali] = 0
3915 if len(vali) > 0 : signal0[vali] = 0
3923 signal1 = (signalpn1-n1)
3916 signal1 = (signalpn1-n1)
3924 vali = (signal1 < 0).nonzero()
3917 vali = (signal1 < 0).nonzero()
3925 vali = vali[0]
3918 vali = vali[0]
3926 if len(vali) > 0 : signal1[vali] = 0
3919 if len(vali) > 0 : signal1[vali] = 0
3927 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3920 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3928 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3921 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3929 doppler = self.absc[1:]
3922 doppler = self.absc[1:]
3930 if snr0 >= snrth and snr1 >= snrth and smooth :
3923 if snr0 >= snrth and snr1 >= snrth and smooth :
3931 signalpn0_n0 = signalpn0
3924 signalpn0_n0 = signalpn0
3932 signalpn0_n0[val0] = signalpn0[val0] - n0
3925 signalpn0_n0[val0] = signalpn0[val0] - n0
3933 mom0 = self.moments(doppler,signalpn0-n0,self.nProf)
3926 mom0 = self.moments(doppler,signalpn0-n0,self.nProf)
3934 signalpn1_n1 = signalpn1
3927 signalpn1_n1 = signalpn1
3935 signalpn1_n1[val1] = signalpn1[val1] - n1
3928 signalpn1_n1[val1] = signalpn1[val1] - n1
3936 mom1 = self.moments(doppler,signalpn1_n1,self.nProf)
3929 mom1 = self.moments(doppler,signalpn1_n1,self.nProf)
3937 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
3930 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
3938 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
3931 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
3939 dataOut.data_spc = jspectra
3932 dataOut.data_spc = jspectra
3940 dataOut.spc_noise = my_noises*self.nProf*self.M
3933 dataOut.spc_noise = my_noises*self.nProf*self.M
3941 if numpy.any(proc): dataOut.spc_noise = my_noises*self.nProf*self.M
3934 if numpy.any(proc): dataOut.spc_noise = my_noises*self.nProf*self.M
3942 if getSNR:
3935 if getSNR:
3943 print("self.groupArray",self.groupArray.size,self.groupArray)
3944 listChannels = self.groupArray.reshape((self.groupArray.size))
3936 listChannels = self.groupArray.reshape((self.groupArray.size))
3945 listChannels.sort()
3937 listChannels.sort()
3946 # TEST
3938 # TEST
3947 noise_C = numpy.zeros(self.nChannels)
3939 noise_C = numpy.zeros(self.nChannels)
3948 noise_C = dataOut.getNoise()
3940 noise_C = dataOut.getNoise()
3949 print("noise_C",noise_C)
3941 #print("noise_C",noise_C)
3950 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:],noise_C/(600.0*1.15))# PRUEBA *nProf*M
3942 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:],noise_C/(600.0*1.15))# PRUEBA *nProf*M
3951 #dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise_C[listChannels])# PRUEBA *nProf*M
3943 #dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise_C[listChannels])# PRUEBA *nProf*M
3952 dataOut.flagNoData = False
3944 dataOut.flagNoData = False
3953 return dataOut
3945 return dataOut
3954
3946
3955 def __residFunction(self, p, dp, LT, constants):
3947 def __residFunction(self, p, dp, LT, constants):
3956
3948
3957 fm = self.library.modelFunction(p, constants)
3949 fm = self.library.modelFunction(p, constants)
3958 fmp=numpy.dot(LT,fm)
3950 fmp=numpy.dot(LT,fm)
3959 return dp-fmp
3951 return dp-fmp
3960
3952
3961 def __getSNR(self, z, noise):
3953 def __getSNR(self, z, noise):
3962
3954
3963 avg = numpy.average(z, axis=1)
3955 avg = numpy.average(z, axis=1)
3964 SNR = (avg.T-noise)/noise
3956 SNR = (avg.T-noise)/noise
3965 print("------------------------------------------------------")
3966 print("T - Noise", noise.shape)
3967 print("T - Noise", 10*numpy.log10(noise[0]))
3968 print("T - avg.T" , avg.T.shape)
3969 print("T - avg.T" , 10*numpy.log10(avg.T[:,0]))
3970 SNR = SNR.T
3957 SNR = SNR.T
3971 return SNR
3958 return SNR
3972
3959
3973 def __chisq(self, p, chindex, hindex):
3960 def __chisq(self, p, chindex, hindex):
3974 #similar to Resid but calculates CHI**2
3961 #similar to Resid but calculates CHI**2
3975 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
3962 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
3976 dp=numpy.dot(LT,d)
3963 dp=numpy.dot(LT,d)
3977 fmp=numpy.dot(LT,fm)
3964 fmp=numpy.dot(LT,fm)
3978 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
3965 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
3979 return chisq
3966 return chisq
3980
3967
3981 class WindProfiler(Operation):
3968 class WindProfiler(Operation):
3982
3969
3983 __isConfig = False
3970 __isConfig = False
3984
3971
3985 __initime = None
3972 __initime = None
3986 __lastdatatime = None
3973 __lastdatatime = None
3987 __integrationtime = None
3974 __integrationtime = None
3988
3975
3989 __buffer = None
3976 __buffer = None
3990
3977
3991 __dataReady = False
3978 __dataReady = False
3992
3979
3993 __firstdata = None
3980 __firstdata = None
3994
3981
3995 n = None
3982 n = None
3996
3983
3997 def __init__(self):
3984 def __init__(self):
3998 Operation.__init__(self)
3985 Operation.__init__(self)
3999
3986
4000 def __calculateCosDir(self, elev, azim):
3987 def __calculateCosDir(self, elev, azim):
4001 zen = (90 - elev)*numpy.pi/180
3988 zen = (90 - elev)*numpy.pi/180
4002 azim = azim*numpy.pi/180
3989 azim = azim*numpy.pi/180
4003 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
3990 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
4004 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
3991 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
4005
3992
4006 signX = numpy.sign(numpy.cos(azim))
3993 signX = numpy.sign(numpy.cos(azim))
4007 signY = numpy.sign(numpy.sin(azim))
3994 signY = numpy.sign(numpy.sin(azim))
4008
3995
4009 cosDirX = numpy.copysign(cosDirX, signX)
3996 cosDirX = numpy.copysign(cosDirX, signX)
4010 cosDirY = numpy.copysign(cosDirY, signY)
3997 cosDirY = numpy.copysign(cosDirY, signY)
4011 return cosDirX, cosDirY
3998 return cosDirX, cosDirY
4012
3999
4013 def __calculateAngles(self, theta_x, theta_y, azimuth):
4000 def __calculateAngles(self, theta_x, theta_y, azimuth):
4014
4001
4015 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
4002 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
4016 zenith_arr = numpy.arccos(dir_cosw)
4003 zenith_arr = numpy.arccos(dir_cosw)
4017 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
4004 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
4018
4005
4019 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
4006 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
4020 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
4007 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
4021
4008
4022 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
4009 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
4023
4010
4024 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
4011 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
4025
4012
4026 if horOnly:
4013 if horOnly:
4027 A = numpy.c_[dir_cosu,dir_cosv]
4014 A = numpy.c_[dir_cosu,dir_cosv]
4028 else:
4015 else:
4029 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
4016 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
4030 A = numpy.asmatrix(A)
4017 A = numpy.asmatrix(A)
4031 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
4018 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
4032
4019
4033 return A1
4020 return A1
4034
4021
4035 def __correctValues(self, heiRang, phi, velRadial, SNR):
4022 def __correctValues(self, heiRang, phi, velRadial, SNR):
4036 listPhi = phi.tolist()
4023 listPhi = phi.tolist()
4037 maxid = listPhi.index(max(listPhi))
4024 maxid = listPhi.index(max(listPhi))
4038 minid = listPhi.index(min(listPhi))
4025 minid = listPhi.index(min(listPhi))
4039
4026
4040 rango = list(range(len(phi)))
4027 rango = list(range(len(phi)))
4041
4028
4042 heiRang1 = heiRang*math.cos(phi[maxid])
4029 heiRang1 = heiRang*math.cos(phi[maxid])
4043 heiRangAux = heiRang*math.cos(phi[minid])
4030 heiRangAux = heiRang*math.cos(phi[minid])
4044 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4031 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4045 heiRang1 = numpy.delete(heiRang1,indOut)
4032 heiRang1 = numpy.delete(heiRang1,indOut)
4046
4033
4047 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4034 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4048 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4035 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4049
4036
4050 for i in rango:
4037 for i in rango:
4051 x = heiRang*math.cos(phi[i])
4038 x = heiRang*math.cos(phi[i])
4052 y1 = velRadial[i,:]
4039 y1 = velRadial[i,:]
4053 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
4040 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
4054
4041
4055 x1 = heiRang1
4042 x1 = heiRang1
4056 y11 = f1(x1)
4043 y11 = f1(x1)
4057
4044
4058 y2 = SNR[i,:]
4045 y2 = SNR[i,:]
4059 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
4046 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
4060 y21 = f2(x1)
4047 y21 = f2(x1)
4061
4048
4062 velRadial1[i,:] = y11
4049 velRadial1[i,:] = y11
4063 SNR1[i,:] = y21
4050 SNR1[i,:] = y21
4064
4051
4065 return heiRang1, velRadial1, SNR1
4052 return heiRang1, velRadial1, SNR1
4066
4053
4067 def __calculateVelUVW(self, A, velRadial):
4054 def __calculateVelUVW(self, A, velRadial):
4068
4055
4069 #Operacion Matricial
4056 #Operacion Matricial
4070 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
4057 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
4071 velUVW[:,:] = numpy.dot(A,velRadial)
4058 velUVW[:,:] = numpy.dot(A,velRadial)
4072
4059
4073
4060
4074 return velUVW
4061 return velUVW
4075
4062
4076 def techniqueDBS(self, kwargs):
4063 def techniqueDBS(self, kwargs):
4077 """
4064 """
4078 Function that implements Doppler Beam Swinging (DBS) technique.
4065 Function that implements Doppler Beam Swinging (DBS) technique.
4079
4066
4080 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4067 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4081 Direction correction (if necessary), Ranges and SNR
4068 Direction correction (if necessary), Ranges and SNR
4082
4069
4083 Output: Winds estimation (Zonal, Meridional and Vertical)
4070 Output: Winds estimation (Zonal, Meridional and Vertical)
4084
4071
4085 Parameters affected: Winds, height range, SNR
4072 Parameters affected: Winds, height range, SNR
4086 """
4073 """
4087 velRadial0 = kwargs['velRadial']
4074 velRadial0 = kwargs['velRadial']
4088 heiRang = kwargs['heightList']
4075 heiRang = kwargs['heightList']
4089 SNR0 = kwargs['SNR']
4076 SNR0 = kwargs['SNR']
4090
4077
4091 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
4078 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
4092 theta_x = numpy.array(kwargs['dirCosx'])
4079 theta_x = numpy.array(kwargs['dirCosx'])
4093 theta_y = numpy.array(kwargs['dirCosy'])
4080 theta_y = numpy.array(kwargs['dirCosy'])
4094 else:
4081 else:
4095 elev = numpy.array(kwargs['elevation'])
4082 elev = numpy.array(kwargs['elevation'])
4096 azim = numpy.array(kwargs['azimuth'])
4083 azim = numpy.array(kwargs['azimuth'])
4097 theta_x, theta_y = self.__calculateCosDir(elev, azim)
4084 theta_x, theta_y = self.__calculateCosDir(elev, azim)
4098 azimuth = kwargs['correctAzimuth']
4085 azimuth = kwargs['correctAzimuth']
4099 if 'horizontalOnly' in kwargs:
4086 if 'horizontalOnly' in kwargs:
4100 horizontalOnly = kwargs['horizontalOnly']
4087 horizontalOnly = kwargs['horizontalOnly']
4101 else: horizontalOnly = False
4088 else: horizontalOnly = False
4102 if 'correctFactor' in kwargs:
4089 if 'correctFactor' in kwargs:
4103 correctFactor = kwargs['correctFactor']
4090 correctFactor = kwargs['correctFactor']
4104 else: correctFactor = 1
4091 else: correctFactor = 1
4105 if 'channelList' in kwargs:
4092 if 'channelList' in kwargs:
4106 channelList = kwargs['channelList']
4093 channelList = kwargs['channelList']
4107 if len(channelList) == 2:
4094 if len(channelList) == 2:
4108 horizontalOnly = True
4095 horizontalOnly = True
4109 arrayChannel = numpy.array(channelList)
4096 arrayChannel = numpy.array(channelList)
4110 param = param[arrayChannel,:,:]
4097 param = param[arrayChannel,:,:]
4111 theta_x = theta_x[arrayChannel]
4098 theta_x = theta_x[arrayChannel]
4112 theta_y = theta_y[arrayChannel]
4099 theta_y = theta_y[arrayChannel]
4113
4100
4114 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4101 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4115 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
4102 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
4116 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
4103 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
4117
4104
4118 #Calculo de Componentes de la velocidad con DBS
4105 #Calculo de Componentes de la velocidad con DBS
4119 winds = self.__calculateVelUVW(A,velRadial1)
4106 winds = self.__calculateVelUVW(A,velRadial1)
4120
4107
4121 return winds, heiRang1, SNR1
4108 return winds, heiRang1, SNR1
4122
4109
4123 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
4110 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
4124
4111
4125 nPairs = len(pairs_ccf)
4112 nPairs = len(pairs_ccf)
4126 posx = numpy.asarray(posx)
4113 posx = numpy.asarray(posx)
4127 posy = numpy.asarray(posy)
4114 posy = numpy.asarray(posy)
4128
4115
4129 #Rotacion Inversa para alinear con el azimuth
4116 #Rotacion Inversa para alinear con el azimuth
4130 if azimuth!= None:
4117 if azimuth!= None:
4131 azimuth = azimuth*math.pi/180
4118 azimuth = azimuth*math.pi/180
4132 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
4119 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
4133 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
4120 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
4134 else:
4121 else:
4135 posx1 = posx
4122 posx1 = posx
4136 posy1 = posy
4123 posy1 = posy
4137
4124
4138 #Calculo de Distancias
4125 #Calculo de Distancias
4139 distx = numpy.zeros(nPairs)
4126 distx = numpy.zeros(nPairs)
4140 disty = numpy.zeros(nPairs)
4127 disty = numpy.zeros(nPairs)
4141 dist = numpy.zeros(nPairs)
4128 dist = numpy.zeros(nPairs)
4142 ang = numpy.zeros(nPairs)
4129 ang = numpy.zeros(nPairs)
4143
4130
4144 for i in range(nPairs):
4131 for i in range(nPairs):
4145 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
4132 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
4146 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
4133 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
4147 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
4134 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
4148 ang[i] = numpy.arctan2(disty[i],distx[i])
4135 ang[i] = numpy.arctan2(disty[i],distx[i])
4149
4136
4150 return distx, disty, dist, ang
4137 return distx, disty, dist, ang
4151 #Calculo de Matrices
4138 #Calculo de Matrices
4152
4139
4153
4140
4154 def __calculateVelVer(self, phase, lagTRange, _lambda):
4141 def __calculateVelVer(self, phase, lagTRange, _lambda):
4155
4142
4156 Ts = lagTRange[1] - lagTRange[0]
4143 Ts = lagTRange[1] - lagTRange[0]
4157 velW = -_lambda*phase/(4*math.pi*Ts)
4144 velW = -_lambda*phase/(4*math.pi*Ts)
4158
4145
4159 return velW
4146 return velW
4160
4147
4161 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
4148 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
4162 nPairs = tau1.shape[0]
4149 nPairs = tau1.shape[0]
4163 nHeights = tau1.shape[1]
4150 nHeights = tau1.shape[1]
4164 vel = numpy.zeros((nPairs,3,nHeights))
4151 vel = numpy.zeros((nPairs,3,nHeights))
4165 dist1 = numpy.reshape(dist, (dist.size,1))
4152 dist1 = numpy.reshape(dist, (dist.size,1))
4166
4153
4167 angCos = numpy.cos(ang)
4154 angCos = numpy.cos(ang)
4168 angSin = numpy.sin(ang)
4155 angSin = numpy.sin(ang)
4169
4156
4170 vel0 = dist1*tau1/(2*tau2**2)
4157 vel0 = dist1*tau1/(2*tau2**2)
4171 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
4158 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
4172 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
4159 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
4173
4160
4174 ind = numpy.where(numpy.isinf(vel))
4161 ind = numpy.where(numpy.isinf(vel))
4175 vel[ind] = numpy.nan
4162 vel[ind] = numpy.nan
4176
4163
4177 return vel
4164 return vel
4178
4165
4179 def techniqueSA(self, kwargs):
4166 def techniqueSA(self, kwargs):
4180
4167
4181 """
4168 """
4182 Function that implements Spaced Antenna (SA) technique.
4169 Function that implements Spaced Antenna (SA) technique.
4183
4170
4184 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4171 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4185 Direction correction (if necessary), Ranges and SNR
4172 Direction correction (if necessary), Ranges and SNR
4186
4173
4187 Output: Winds estimation (Zonal, Meridional and Vertical)
4174 Output: Winds estimation (Zonal, Meridional and Vertical)
4188
4175
4189 Parameters affected: Winds
4176 Parameters affected: Winds
4190 """
4177 """
4191 position_x = kwargs['positionX']
4178 position_x = kwargs['positionX']
4192 position_y = kwargs['positionY']
4179 position_y = kwargs['positionY']
4193 azimuth = kwargs['azimuth']
4180 azimuth = kwargs['azimuth']
4194
4181
4195 if 'correctFactor' in kwargs:
4182 if 'correctFactor' in kwargs:
4196 correctFactor = kwargs['correctFactor']
4183 correctFactor = kwargs['correctFactor']
4197 else:
4184 else:
4198 correctFactor = 1
4185 correctFactor = 1
4199
4186
4200 groupList = kwargs['groupList']
4187 groupList = kwargs['groupList']
4201 pairs_ccf = groupList[1]
4188 pairs_ccf = groupList[1]
4202 tau = kwargs['tau']
4189 tau = kwargs['tau']
4203 _lambda = kwargs['_lambda']
4190 _lambda = kwargs['_lambda']
4204
4191
4205 #Cross Correlation pairs obtained
4192 #Cross Correlation pairs obtained
4206
4193
4207 indtau = tau.shape[0]/2
4194 indtau = tau.shape[0]/2
4208 tau1 = tau[:indtau,:]
4195 tau1 = tau[:indtau,:]
4209 tau2 = tau[indtau:-1,:]
4196 tau2 = tau[indtau:-1,:]
4210 phase1 = tau[-1,:]
4197 phase1 = tau[-1,:]
4211
4198
4212 #---------------------------------------------------------------------
4199 #---------------------------------------------------------------------
4213 #Metodo Directo
4200 #Metodo Directo
4214 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
4201 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
4215 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
4202 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
4216 winds = stats.nanmean(winds, axis=0)
4203 winds = stats.nanmean(winds, axis=0)
4217 #---------------------------------------------------------------------
4204 #---------------------------------------------------------------------
4218 #Metodo General
4205 #Metodo General
4219
4206
4220 #---------------------------------------------------------------------
4207 #---------------------------------------------------------------------
4221 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
4208 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
4222 winds = correctFactor*winds
4209 winds = correctFactor*winds
4223 return winds
4210 return winds
4224
4211
4225 def __checkTime(self, currentTime, paramInterval, outputInterval):
4212 def __checkTime(self, currentTime, paramInterval, outputInterval):
4226
4213
4227 dataTime = currentTime + paramInterval
4214 dataTime = currentTime + paramInterval
4228 deltaTime = dataTime - self.__initime
4215 deltaTime = dataTime - self.__initime
4229
4216
4230 if deltaTime >= outputInterval or deltaTime < 0:
4217 if deltaTime >= outputInterval or deltaTime < 0:
4231 self.__dataReady = True
4218 self.__dataReady = True
4232 return
4219 return
4233
4220
4234 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
4221 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
4235 '''
4222 '''
4236 Function that implements winds estimation technique with detected meteors.
4223 Function that implements winds estimation technique with detected meteors.
4237
4224
4238 Input: Detected meteors, Minimum meteor quantity to wind estimation
4225 Input: Detected meteors, Minimum meteor quantity to wind estimation
4239
4226
4240 Output: Winds estimation (Zonal and Meridional)
4227 Output: Winds estimation (Zonal and Meridional)
4241
4228
4242 Parameters affected: Winds
4229 Parameters affected: Winds
4243 '''
4230 '''
4244 #Settings
4231 #Settings
4245 nInt = (heightMax - heightMin)/2
4232 nInt = (heightMax - heightMin)/2
4246 nInt = int(nInt)
4233 nInt = int(nInt)
4247 winds = numpy.zeros((2,nInt))*numpy.nan
4234 winds = numpy.zeros((2,nInt))*numpy.nan
4248
4235
4249 #Filter errors
4236 #Filter errors
4250 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
4237 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
4251 finalMeteor = arrayMeteor[error,:]
4238 finalMeteor = arrayMeteor[error,:]
4252
4239
4253 #Meteor Histogram
4240 #Meteor Histogram
4254 finalHeights = finalMeteor[:,2]
4241 finalHeights = finalMeteor[:,2]
4255 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
4242 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
4256 nMeteorsPerI = hist[0]
4243 nMeteorsPerI = hist[0]
4257 heightPerI = hist[1]
4244 heightPerI = hist[1]
4258
4245
4259 #Sort of meteors
4246 #Sort of meteors
4260 indSort = finalHeights.argsort()
4247 indSort = finalHeights.argsort()
4261 finalMeteor2 = finalMeteor[indSort,:]
4248 finalMeteor2 = finalMeteor[indSort,:]
4262
4249
4263 # Calculating winds
4250 # Calculating winds
4264 ind1 = 0
4251 ind1 = 0
4265 ind2 = 0
4252 ind2 = 0
4266
4253
4267 for i in range(nInt):
4254 for i in range(nInt):
4268 nMet = nMeteorsPerI[i]
4255 nMet = nMeteorsPerI[i]
4269 ind1 = ind2
4256 ind1 = ind2
4270 ind2 = ind1 + nMet
4257 ind2 = ind1 + nMet
4271
4258
4272 meteorAux = finalMeteor2[ind1:ind2,:]
4259 meteorAux = finalMeteor2[ind1:ind2,:]
4273
4260
4274 if meteorAux.shape[0] >= meteorThresh:
4261 if meteorAux.shape[0] >= meteorThresh:
4275 vel = meteorAux[:, 6]
4262 vel = meteorAux[:, 6]
4276 zen = meteorAux[:, 4]*numpy.pi/180
4263 zen = meteorAux[:, 4]*numpy.pi/180
4277 azim = meteorAux[:, 3]*numpy.pi/180
4264 azim = meteorAux[:, 3]*numpy.pi/180
4278
4265
4279 n = numpy.cos(zen)
4266 n = numpy.cos(zen)
4280 l = numpy.sin(zen)*numpy.sin(azim)
4267 l = numpy.sin(zen)*numpy.sin(azim)
4281 m = numpy.sin(zen)*numpy.cos(azim)
4268 m = numpy.sin(zen)*numpy.cos(azim)
4282
4269
4283 A = numpy.vstack((l, m)).transpose()
4270 A = numpy.vstack((l, m)).transpose()
4284 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
4271 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
4285 windsAux = numpy.dot(A1, vel)
4272 windsAux = numpy.dot(A1, vel)
4286
4273
4287 winds[0,i] = windsAux[0]
4274 winds[0,i] = windsAux[0]
4288 winds[1,i] = windsAux[1]
4275 winds[1,i] = windsAux[1]
4289
4276
4290 return winds, heightPerI[:-1]
4277 return winds, heightPerI[:-1]
4291
4278
4292 def techniqueNSM_SA(self, **kwargs):
4279 def techniqueNSM_SA(self, **kwargs):
4293 metArray = kwargs['metArray']
4280 metArray = kwargs['metArray']
4294 heightList = kwargs['heightList']
4281 heightList = kwargs['heightList']
4295 timeList = kwargs['timeList']
4282 timeList = kwargs['timeList']
4296
4283
4297 rx_location = kwargs['rx_location']
4284 rx_location = kwargs['rx_location']
4298 groupList = kwargs['groupList']
4285 groupList = kwargs['groupList']
4299 azimuth = kwargs['azimuth']
4286 azimuth = kwargs['azimuth']
4300 dfactor = kwargs['dfactor']
4287 dfactor = kwargs['dfactor']
4301 k = kwargs['k']
4288 k = kwargs['k']
4302
4289
4303 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
4290 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
4304 d = dist*dfactor
4291 d = dist*dfactor
4305 #Phase calculation
4292 #Phase calculation
4306 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
4293 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
4307
4294
4308 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
4295 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
4309
4296
4310 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4297 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4311 azimuth1 = azimuth1*numpy.pi/180
4298 azimuth1 = azimuth1*numpy.pi/180
4312
4299
4313 for i in range(heightList.size):
4300 for i in range(heightList.size):
4314 h = heightList[i]
4301 h = heightList[i]
4315 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
4302 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
4316 metHeight = metArray1[indH,:]
4303 metHeight = metArray1[indH,:]
4317 if metHeight.shape[0] >= 2:
4304 if metHeight.shape[0] >= 2:
4318 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
4305 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
4319 iazim = metHeight[:,1].astype(int)
4306 iazim = metHeight[:,1].astype(int)
4320 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
4307 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
4321 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
4308 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
4322 A = numpy.asmatrix(A)
4309 A = numpy.asmatrix(A)
4323 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
4310 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
4324 velHor = numpy.dot(A1,velAux)
4311 velHor = numpy.dot(A1,velAux)
4325
4312
4326 velEst[i,:] = numpy.squeeze(velHor)
4313 velEst[i,:] = numpy.squeeze(velHor)
4327 return velEst
4314 return velEst
4328
4315
4329 def __getPhaseSlope(self, metArray, heightList, timeList):
4316 def __getPhaseSlope(self, metArray, heightList, timeList):
4330 meteorList = []
4317 meteorList = []
4331 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
4318 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
4332 #Putting back together the meteor matrix
4319 #Putting back together the meteor matrix
4333 utctime = metArray[:,0]
4320 utctime = metArray[:,0]
4334 uniqueTime = numpy.unique(utctime)
4321 uniqueTime = numpy.unique(utctime)
4335
4322
4336 phaseDerThresh = 0.5
4323 phaseDerThresh = 0.5
4337 ippSeconds = timeList[1] - timeList[0]
4324 ippSeconds = timeList[1] - timeList[0]
4338 sec = numpy.where(timeList>1)[0][0]
4325 sec = numpy.where(timeList>1)[0][0]
4339 nPairs = metArray.shape[1] - 6
4326 nPairs = metArray.shape[1] - 6
4340 nHeights = len(heightList)
4327 nHeights = len(heightList)
4341
4328
4342 for t in uniqueTime:
4329 for t in uniqueTime:
4343 metArray1 = metArray[utctime==t,:]
4330 metArray1 = metArray[utctime==t,:]
4344 tmet = metArray1[:,1].astype(int)
4331 tmet = metArray1[:,1].astype(int)
4345 hmet = metArray1[:,2].astype(int)
4332 hmet = metArray1[:,2].astype(int)
4346
4333
4347 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
4334 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
4348 metPhase[:,:] = numpy.nan
4335 metPhase[:,:] = numpy.nan
4349 metPhase[:,hmet,tmet] = metArray1[:,6:].T
4336 metPhase[:,hmet,tmet] = metArray1[:,6:].T
4350
4337
4351 #Delete short trails
4338 #Delete short trails
4352 metBool = ~numpy.isnan(metPhase[0,:,:])
4339 metBool = ~numpy.isnan(metPhase[0,:,:])
4353 heightVect = numpy.sum(metBool, axis = 1)
4340 heightVect = numpy.sum(metBool, axis = 1)
4354 metBool[heightVect<sec,:] = False
4341 metBool[heightVect<sec,:] = False
4355 metPhase[:,heightVect<sec,:] = numpy.nan
4342 metPhase[:,heightVect<sec,:] = numpy.nan
4356
4343
4357 #Derivative
4344 #Derivative
4358 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
4345 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
4359 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
4346 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
4360 metPhase[phDerAux] = numpy.nan
4347 metPhase[phDerAux] = numpy.nan
4361
4348
4362 #--------------------------METEOR DETECTION -----------------------------------------
4349 #--------------------------METEOR DETECTION -----------------------------------------
4363 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
4350 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
4364
4351
4365 for p in numpy.arange(nPairs):
4352 for p in numpy.arange(nPairs):
4366 phase = metPhase[p,:,:]
4353 phase = metPhase[p,:,:]
4367 phDer = metDer[p,:,:]
4354 phDer = metDer[p,:,:]
4368
4355
4369 for h in indMet:
4356 for h in indMet:
4370 height = heightList[h]
4357 height = heightList[h]
4371 phase1 = phase[h,:] #82
4358 phase1 = phase[h,:] #82
4372 phDer1 = phDer[h,:]
4359 phDer1 = phDer[h,:]
4373
4360
4374 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
4361 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
4375
4362
4376 indValid = numpy.where(~numpy.isnan(phase1))[0]
4363 indValid = numpy.where(~numpy.isnan(phase1))[0]
4377 initMet = indValid[0]
4364 initMet = indValid[0]
4378 endMet = 0
4365 endMet = 0
4379
4366
4380 for i in range(len(indValid)-1):
4367 for i in range(len(indValid)-1):
4381
4368
4382 #Time difference
4369 #Time difference
4383 inow = indValid[i]
4370 inow = indValid[i]
4384 inext = indValid[i+1]
4371 inext = indValid[i+1]
4385 idiff = inext - inow
4372 idiff = inext - inow
4386 #Phase difference
4373 #Phase difference
4387 phDiff = numpy.abs(phase1[inext] - phase1[inow])
4374 phDiff = numpy.abs(phase1[inext] - phase1[inow])
4388
4375
4389 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
4376 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
4390 sizeTrail = inow - initMet + 1
4377 sizeTrail = inow - initMet + 1
4391 if sizeTrail>3*sec: #Too short meteors
4378 if sizeTrail>3*sec: #Too short meteors
4392 x = numpy.arange(initMet,inow+1)*ippSeconds
4379 x = numpy.arange(initMet,inow+1)*ippSeconds
4393 y = phase1[initMet:inow+1]
4380 y = phase1[initMet:inow+1]
4394 ynnan = ~numpy.isnan(y)
4381 ynnan = ~numpy.isnan(y)
4395 x = x[ynnan]
4382 x = x[ynnan]
4396 y = y[ynnan]
4383 y = y[ynnan]
4397 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
4384 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
4398 ylin = x*slope + intercept
4385 ylin = x*slope + intercept
4399 rsq = r_value**2
4386 rsq = r_value**2
4400 if rsq > 0.5:
4387 if rsq > 0.5:
4401 vel = slope#*height*1000/(k*d)
4388 vel = slope#*height*1000/(k*d)
4402 estAux = numpy.array([utctime,p,height, vel, rsq])
4389 estAux = numpy.array([utctime,p,height, vel, rsq])
4403 meteorList.append(estAux)
4390 meteorList.append(estAux)
4404 initMet = inext
4391 initMet = inext
4405 metArray2 = numpy.array(meteorList)
4392 metArray2 = numpy.array(meteorList)
4406
4393
4407 return metArray2
4394 return metArray2
4408
4395
4409 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
4396 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
4410
4397
4411 azimuth1 = numpy.zeros(len(pairslist))
4398 azimuth1 = numpy.zeros(len(pairslist))
4412 dist = numpy.zeros(len(pairslist))
4399 dist = numpy.zeros(len(pairslist))
4413
4400
4414 for i in range(len(rx_location)):
4401 for i in range(len(rx_location)):
4415 ch0 = pairslist[i][0]
4402 ch0 = pairslist[i][0]
4416 ch1 = pairslist[i][1]
4403 ch1 = pairslist[i][1]
4417
4404
4418 diffX = rx_location[ch0][0] - rx_location[ch1][0]
4405 diffX = rx_location[ch0][0] - rx_location[ch1][0]
4419 diffY = rx_location[ch0][1] - rx_location[ch1][1]
4406 diffY = rx_location[ch0][1] - rx_location[ch1][1]
4420 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
4407 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
4421 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
4408 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
4422
4409
4423 azimuth1 -= azimuth0
4410 azimuth1 -= azimuth0
4424 return azimuth1, dist
4411 return azimuth1, dist
4425
4412
4426 def techniqueNSM_DBS(self, **kwargs):
4413 def techniqueNSM_DBS(self, **kwargs):
4427 metArray = kwargs['metArray']
4414 metArray = kwargs['metArray']
4428 heightList = kwargs['heightList']
4415 heightList = kwargs['heightList']
4429 timeList = kwargs['timeList']
4416 timeList = kwargs['timeList']
4430 azimuth = kwargs['azimuth']
4417 azimuth = kwargs['azimuth']
4431 theta_x = numpy.array(kwargs['theta_x'])
4418 theta_x = numpy.array(kwargs['theta_x'])
4432 theta_y = numpy.array(kwargs['theta_y'])
4419 theta_y = numpy.array(kwargs['theta_y'])
4433
4420
4434 utctime = metArray[:,0]
4421 utctime = metArray[:,0]
4435 cmet = metArray[:,1].astype(int)
4422 cmet = metArray[:,1].astype(int)
4436 hmet = metArray[:,3].astype(int)
4423 hmet = metArray[:,3].astype(int)
4437 SNRmet = metArray[:,4]
4424 SNRmet = metArray[:,4]
4438 vmet = metArray[:,5]
4425 vmet = metArray[:,5]
4439 spcmet = metArray[:,6]
4426 spcmet = metArray[:,6]
4440
4427
4441 nChan = numpy.max(cmet) + 1
4428 nChan = numpy.max(cmet) + 1
4442 nHeights = len(heightList)
4429 nHeights = len(heightList)
4443
4430
4444 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4431 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4445 hmet = heightList[hmet]
4432 hmet = heightList[hmet]
4446 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
4433 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
4447
4434
4448 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4435 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4449
4436
4450 for i in range(nHeights - 1):
4437 for i in range(nHeights - 1):
4451 hmin = heightList[i]
4438 hmin = heightList[i]
4452 hmax = heightList[i + 1]
4439 hmax = heightList[i + 1]
4453
4440
4454 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
4441 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
4455 indthisH = numpy.where(thisH)
4442 indthisH = numpy.where(thisH)
4456
4443
4457 if numpy.size(indthisH) > 3:
4444 if numpy.size(indthisH) > 3:
4458
4445
4459 vel_aux = vmet[thisH]
4446 vel_aux = vmet[thisH]
4460 chan_aux = cmet[thisH]
4447 chan_aux = cmet[thisH]
4461 cosu_aux = dir_cosu[chan_aux]
4448 cosu_aux = dir_cosu[chan_aux]
4462 cosv_aux = dir_cosv[chan_aux]
4449 cosv_aux = dir_cosv[chan_aux]
4463 cosw_aux = dir_cosw[chan_aux]
4450 cosw_aux = dir_cosw[chan_aux]
4464
4451
4465 nch = numpy.size(numpy.unique(chan_aux))
4452 nch = numpy.size(numpy.unique(chan_aux))
4466 if nch > 1:
4453 if nch > 1:
4467 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
4454 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
4468 velEst[i,:] = numpy.dot(A,vel_aux)
4455 velEst[i,:] = numpy.dot(A,vel_aux)
4469
4456
4470 return velEst
4457 return velEst
4471
4458
4472 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
4459 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
4473
4460
4474 param = dataOut.moments
4461 param = dataOut.moments
4475 if numpy.any(dataOut.abscissaList):
4462 if numpy.any(dataOut.abscissaList):
4476 absc = dataOut.abscissaList[:-1]
4463 absc = dataOut.abscissaList[:-1]
4477 # noise = dataOut.noise
4464 # noise = dataOut.noise
4478 heightList = dataOut.heightList
4465 heightList = dataOut.heightList
4479 SNR = dataOut.data_snr
4466 SNR = dataOut.data_snr
4480
4467
4481 if technique == 'DBS':
4468 if technique == 'DBS':
4482
4469
4483 kwargs['velRadial'] = param[:,1,:] #Radial velocity
4470 kwargs['velRadial'] = param[:,1,:] #Radial velocity
4484 kwargs['heightList'] = heightList
4471 kwargs['heightList'] = heightList
4485 kwargs['SNR'] = SNR
4472 kwargs['SNR'] = SNR
4486
4473
4487 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
4474 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
4488 dataOut.utctimeInit = dataOut.utctime
4475 dataOut.utctimeInit = dataOut.utctime
4489 dataOut.outputInterval = dataOut.paramInterval
4476 dataOut.outputInterval = dataOut.paramInterval
4490
4477
4491 elif technique == 'SA':
4478 elif technique == 'SA':
4492
4479
4493 #Parameters
4480 #Parameters
4494 kwargs['groupList'] = dataOut.groupList
4481 kwargs['groupList'] = dataOut.groupList
4495 kwargs['tau'] = dataOut.data_param
4482 kwargs['tau'] = dataOut.data_param
4496 kwargs['_lambda'] = dataOut.C/dataOut.frequency
4483 kwargs['_lambda'] = dataOut.C/dataOut.frequency
4497 dataOut.data_output = self.techniqueSA(kwargs)
4484 dataOut.data_output = self.techniqueSA(kwargs)
4498 dataOut.utctimeInit = dataOut.utctime
4485 dataOut.utctimeInit = dataOut.utctime
4499 dataOut.outputInterval = dataOut.timeInterval
4486 dataOut.outputInterval = dataOut.timeInterval
4500
4487
4501 elif technique == 'Meteors':
4488 elif technique == 'Meteors':
4502 dataOut.flagNoData = True
4489 dataOut.flagNoData = True
4503 self.__dataReady = False
4490 self.__dataReady = False
4504
4491
4505 if 'nHours' in kwargs:
4492 if 'nHours' in kwargs:
4506 nHours = kwargs['nHours']
4493 nHours = kwargs['nHours']
4507 else:
4494 else:
4508 nHours = 1
4495 nHours = 1
4509
4496
4510 if 'meteorsPerBin' in kwargs:
4497 if 'meteorsPerBin' in kwargs:
4511 meteorThresh = kwargs['meteorsPerBin']
4498 meteorThresh = kwargs['meteorsPerBin']
4512 else:
4499 else:
4513 meteorThresh = 6
4500 meteorThresh = 6
4514
4501
4515 if 'hmin' in kwargs:
4502 if 'hmin' in kwargs:
4516 hmin = kwargs['hmin']
4503 hmin = kwargs['hmin']
4517 else: hmin = 70
4504 else: hmin = 70
4518 if 'hmax' in kwargs:
4505 if 'hmax' in kwargs:
4519 hmax = kwargs['hmax']
4506 hmax = kwargs['hmax']
4520 else: hmax = 110
4507 else: hmax = 110
4521
4508
4522 dataOut.outputInterval = nHours*3600
4509 dataOut.outputInterval = nHours*3600
4523
4510
4524 if self.__isConfig == False:
4511 if self.__isConfig == False:
4525 #Get Initial LTC time
4512 #Get Initial LTC time
4526 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4513 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4527 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4514 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4528
4515
4529 self.__isConfig = True
4516 self.__isConfig = True
4530
4517
4531 if self.__buffer is None:
4518 if self.__buffer is None:
4532 self.__buffer = dataOut.data_param
4519 self.__buffer = dataOut.data_param
4533 self.__firstdata = copy.copy(dataOut)
4520 self.__firstdata = copy.copy(dataOut)
4534
4521
4535 else:
4522 else:
4536 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4523 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4537
4524
4538 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4525 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4539
4526
4540 if self.__dataReady:
4527 if self.__dataReady:
4541 dataOut.utctimeInit = self.__initime
4528 dataOut.utctimeInit = self.__initime
4542
4529
4543 self.__initime += dataOut.outputInterval #to erase time offset
4530 self.__initime += dataOut.outputInterval #to erase time offset
4544
4531
4545 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
4532 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
4546 dataOut.flagNoData = False
4533 dataOut.flagNoData = False
4547 self.__buffer = None
4534 self.__buffer = None
4548
4535
4549 elif technique == 'Meteors1':
4536 elif technique == 'Meteors1':
4550 dataOut.flagNoData = True
4537 dataOut.flagNoData = True
4551 self.__dataReady = False
4538 self.__dataReady = False
4552
4539
4553 if 'nMins' in kwargs:
4540 if 'nMins' in kwargs:
4554 nMins = kwargs['nMins']
4541 nMins = kwargs['nMins']
4555 else: nMins = 20
4542 else: nMins = 20
4556 if 'rx_location' in kwargs:
4543 if 'rx_location' in kwargs:
4557 rx_location = kwargs['rx_location']
4544 rx_location = kwargs['rx_location']
4558 else: rx_location = [(0,1),(1,1),(1,0)]
4545 else: rx_location = [(0,1),(1,1),(1,0)]
4559 if 'azimuth' in kwargs:
4546 if 'azimuth' in kwargs:
4560 azimuth = kwargs['azimuth']
4547 azimuth = kwargs['azimuth']
4561 else: azimuth = 51.06
4548 else: azimuth = 51.06
4562 if 'dfactor' in kwargs:
4549 if 'dfactor' in kwargs:
4563 dfactor = kwargs['dfactor']
4550 dfactor = kwargs['dfactor']
4564 if 'mode' in kwargs:
4551 if 'mode' in kwargs:
4565 mode = kwargs['mode']
4552 mode = kwargs['mode']
4566 if 'theta_x' in kwargs:
4553 if 'theta_x' in kwargs:
4567 theta_x = kwargs['theta_x']
4554 theta_x = kwargs['theta_x']
4568 if 'theta_y' in kwargs:
4555 if 'theta_y' in kwargs:
4569 theta_y = kwargs['theta_y']
4556 theta_y = kwargs['theta_y']
4570 else: mode = 'SA'
4557 else: mode = 'SA'
4571
4558
4572 #Borrar luego esto
4559 #Borrar luego esto
4573 if dataOut.groupList is None:
4560 if dataOut.groupList is None:
4574 dataOut.groupList = [(0,1),(0,2),(1,2)]
4561 dataOut.groupList = [(0,1),(0,2),(1,2)]
4575 groupList = dataOut.groupList
4562 groupList = dataOut.groupList
4576 C = 3e8
4563 C = 3e8
4577 freq = 50e6
4564 freq = 50e6
4578 lamb = C/freq
4565 lamb = C/freq
4579 k = 2*numpy.pi/lamb
4566 k = 2*numpy.pi/lamb
4580
4567
4581 timeList = dataOut.abscissaList
4568 timeList = dataOut.abscissaList
4582 heightList = dataOut.heightList
4569 heightList = dataOut.heightList
4583
4570
4584 if self.__isConfig == False:
4571 if self.__isConfig == False:
4585 dataOut.outputInterval = nMins*60
4572 dataOut.outputInterval = nMins*60
4586 #Get Initial LTC time
4573 #Get Initial LTC time
4587 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4574 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4588 minuteAux = initime.minute
4575 minuteAux = initime.minute
4589 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
4576 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
4590 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4577 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4591
4578
4592 self.__isConfig = True
4579 self.__isConfig = True
4593
4580
4594 if self.__buffer is None:
4581 if self.__buffer is None:
4595 self.__buffer = dataOut.data_param
4582 self.__buffer = dataOut.data_param
4596 self.__firstdata = copy.copy(dataOut)
4583 self.__firstdata = copy.copy(dataOut)
4597
4584
4598 else:
4585 else:
4599 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4586 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4600
4587
4601 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4588 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4602
4589
4603 if self.__dataReady:
4590 if self.__dataReady:
4604 dataOut.utctimeInit = self.__initime
4591 dataOut.utctimeInit = self.__initime
4605 self.__initime += dataOut.outputInterval #to erase time offset
4592 self.__initime += dataOut.outputInterval #to erase time offset
4606
4593
4607 metArray = self.__buffer
4594 metArray = self.__buffer
4608 if mode == 'SA':
4595 if mode == 'SA':
4609 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
4596 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
4610 elif mode == 'DBS':
4597 elif mode == 'DBS':
4611 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
4598 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
4612 dataOut.data_output = dataOut.data_output.T
4599 dataOut.data_output = dataOut.data_output.T
4613 dataOut.flagNoData = False
4600 dataOut.flagNoData = False
4614 self.__buffer = None
4601 self.__buffer = None
4615
4602
4616 return dataOut
4603 return dataOut
4617
4604
4618 class EWDriftsEstimation(Operation):
4605 class EWDriftsEstimation(Operation):
4619
4606
4620 def __init__(self):
4607 def __init__(self):
4621 Operation.__init__(self)
4608 Operation.__init__(self)
4622
4609
4623 def __correctValues(self, heiRang, phi, velRadial, SNR):
4610 def __correctValues(self, heiRang, phi, velRadial, SNR):
4624 listPhi = phi.tolist()
4611 listPhi = phi.tolist()
4625 maxid = listPhi.index(max(listPhi))
4612 maxid = listPhi.index(max(listPhi))
4626 minid = listPhi.index(min(listPhi))
4613 minid = listPhi.index(min(listPhi))
4627
4614
4628 rango = list(range(len(phi)))
4615 rango = list(range(len(phi)))
4629 heiRang1 = heiRang*math.cos(phi[maxid])
4616 heiRang1 = heiRang*math.cos(phi[maxid])
4630 heiRangAux = heiRang*math.cos(phi[minid])
4617 heiRangAux = heiRang*math.cos(phi[minid])
4631 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4618 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4632 heiRang1 = numpy.delete(heiRang1,indOut)
4619 heiRang1 = numpy.delete(heiRang1,indOut)
4633
4620
4634 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4621 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4635 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4622 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4636
4623
4637 for i in rango:
4624 for i in rango:
4638 x = heiRang*math.cos(phi[i])
4625 x = heiRang*math.cos(phi[i])
4639 y1 = velRadial[i,:]
4626 y1 = velRadial[i,:]
4640 vali= (numpy.isfinite(y1)==True).nonzero()
4627 vali= (numpy.isfinite(y1)==True).nonzero()
4641 y1=y1[vali]
4628 y1=y1[vali]
4642 x = x[vali]
4629 x = x[vali]
4643 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
4630 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
4644 x1 = heiRang1
4631 x1 = heiRang1
4645 y11 = f1(x1)
4632 y11 = f1(x1)
4646 y2 = SNR[i,:]
4633 y2 = SNR[i,:]
4647 x = heiRang*math.cos(phi[i])
4634 x = heiRang*math.cos(phi[i])
4648 vali= (y2 != -1).nonzero()
4635 vali= (y2 != -1).nonzero()
4649 y2 = y2[vali]
4636 y2 = y2[vali]
4650 x = x[vali]
4637 x = x[vali]
4651 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
4638 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
4652 y21 = f2(x1)
4639 y21 = f2(x1)
4653
4640
4654 velRadial1[i,:] = y11
4641 velRadial1[i,:] = y11
4655 SNR1[i,:] = y21
4642 SNR1[i,:] = y21
4656
4643
4657 return heiRang1, velRadial1, SNR1
4644 return heiRang1, velRadial1, SNR1
4658
4645
4659 def run(self, dataOut, zenith, zenithCorrection,fileDrifts):
4646 def run(self, dataOut, zenith, zenithCorrection,fileDrifts):
4660
4647
4661 dataOut.lat=-11.95
4648 dataOut.lat=-11.95
4662 dataOut.lon=-76.87
4649 dataOut.lon=-76.87
4663 heiRang = dataOut.heightList
4650 heiRang = dataOut.heightList
4664 velRadial = dataOut.data_param[:,3,:]
4651 velRadial = dataOut.data_param[:,3,:]
4665 velRadialm = dataOut.data_param[:,2:4,:]*-1
4652 velRadialm = dataOut.data_param[:,2:4,:]*-1
4666 rbufc=dataOut.data_paramC[:,:,0]
4653 rbufc=dataOut.data_paramC[:,:,0]
4667 ebufc=dataOut.data_paramC[:,:,1]
4654 ebufc=dataOut.data_paramC[:,:,1]
4668 SNR = dataOut.data_snr
4655 SNR = dataOut.data_snr
4669 velRerr = dataOut.data_error[:,4,:]
4656 velRerr = dataOut.data_error[:,4,:]
4670 channels = dataOut.channelList
4657 channels = dataOut.channelList
4671 nChan = len(channels)
4658 nChan = len(channels)
4672 my_nbeams = nChan/2
4659 my_nbeams = nChan/2
4673 if my_nbeams == 2:
4660 if my_nbeams == 2:
4674 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
4661 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
4675 else :
4662 else :
4676 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]]))
4663 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]]))
4677 dataOut.moments=moments
4664 dataOut.moments=moments
4678 # Coherent
4665 # Coherent
4679 smooth_wC = ebufc[0,:]
4666 smooth_wC = ebufc[0,:]
4680 p_w0C = rbufc[0,:]
4667 p_w0C = rbufc[0,:]
4681 p_w1C = rbufc[1,:]
4668 p_w1C = rbufc[1,:]
4682 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
4669 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
4683 t_wC = rbufc[3,:]
4670 t_wC = rbufc[3,:]
4684 if my_nbeams == 1:
4671 if my_nbeams == 1:
4685 w = velRadial[0,:]
4672 w = velRadial[0,:]
4686 winds = velRadial.copy()
4673 winds = velRadial.copy()
4687 w_err = velRerr[0,:]
4674 w_err = velRerr[0,:]
4688 snr1 = 10*numpy.log10(SNR[0])
4675 snr1 = 10*numpy.log10(SNR[0])
4689 if my_nbeams == 2:
4676 if my_nbeams == 2:
4690 zenith = numpy.array(zenith)
4677 zenith = numpy.array(zenith)
4691 zenith -= zenithCorrection
4678 zenith -= zenithCorrection
4692 zenith *= numpy.pi/180
4679 zenith *= numpy.pi/180
4693 if zenithCorrection != 0 :
4680 if zenithCorrection != 0 :
4694 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
4681 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
4695 else :
4682 else :
4696 heiRang1 = heiRang
4683 heiRang1 = heiRang
4697 velRadial1 = velRadial
4684 velRadial1 = velRadial
4698 SNR1 = SNR
4685 SNR1 = SNR
4699
4686
4700 alp = zenith[0]
4687 alp = zenith[0]
4701 bet = zenith[1]
4688 bet = zenith[1]
4702
4689
4703 w_w = velRadial1[0,:]
4690 w_w = velRadial1[0,:]
4704 w_e = velRadial1[1,:]
4691 w_e = velRadial1[1,:]
4705 w_w_err = velRerr[0,:]
4692 w_w_err = velRerr[0,:]
4706 w_e_err = velRerr[1,:]
4693 w_e_err = velRerr[1,:]
4707
4694
4708 val = (numpy.isfinite(w_w)==False).nonzero()
4695 val = (numpy.isfinite(w_w)==False).nonzero()
4709 val = val[0]
4696 val = val[0]
4710 bad = val
4697 bad = val
4711 if len(bad) > 0 :
4698 if len(bad) > 0 :
4712 w_w[bad] = w_wC[bad]
4699 w_w[bad] = w_wC[bad]
4713 w_w_err[bad]= numpy.nan
4700 w_w_err[bad]= numpy.nan
4714 smooth_eC=ebufc[4,:]
4701 smooth_eC=ebufc[4,:]
4715 p_e0C = rbufc[4,:]
4702 p_e0C = rbufc[4,:]
4716 p_e1C = rbufc[5,:]
4703 p_e1C = rbufc[5,:]
4717 w_eC = rbufc[6,:]*-1
4704 w_eC = rbufc[6,:]*-1
4718 t_eC = rbufc[7,:]
4705 t_eC = rbufc[7,:]
4719 val = (numpy.isfinite(w_e)==False).nonzero()
4706 val = (numpy.isfinite(w_e)==False).nonzero()
4720 val = val[0]
4707 val = val[0]
4721 bad = val
4708 bad = val
4722 if len(bad) > 0 :
4709 if len(bad) > 0 :
4723 w_e[bad] = w_eC[bad]
4710 w_e[bad] = w_eC[bad]
4724 w_e_err[bad]= numpy.nan
4711 w_e_err[bad]= numpy.nan
4725
4712
4726 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
4713 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
4727 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
4714 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
4728
4715
4729 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))
4716 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))
4730 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))
4717 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))
4731
4718
4732 winds = numpy.vstack((w,u))
4719 winds = numpy.vstack((w,u))
4733
4720
4734 dataOut.heightList = heiRang1
4721 dataOut.heightList = heiRang1
4735 snr1 = 10*numpy.log10(SNR1[0])
4722 snr1 = 10*numpy.log10(SNR1[0])
4736 dataOut.data_output = winds
4723 dataOut.data_output = winds
4737 #snr1 = 10*numpy.log10(SNR1[0])# estaba comentado
4724 #snr1 = 10*numpy.log10(SNR1[0])# estaba comentado
4738 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
4725 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
4739 print("data_snr1",dataOut.data_snr1)
4726 #print("data_snr1",dataOut.data_snr1)
4740 dataOut.utctimeInit = dataOut.utctime
4727 dataOut.utctimeInit = dataOut.utctime
4741 dataOut.outputInterval = dataOut.timeInterval
4728 dataOut.outputInterval = dataOut.timeInterval
4742
4729
4743 hei_aver0 = 218
4730 hei_aver0 = 218
4744 jrange = 450 #900 para HA drifts
4731 jrange = 450 #900 para HA drifts
4745 deltah = 15.0 #dataOut.spacing(0) 25 HAD
4732 deltah = 15.0 #dataOut.spacing(0) 25 HAD
4746 h0 = 0.0 #dataOut.first_height(0)
4733 h0 = 0.0 #dataOut.first_height(0)
4747 heights = dataOut.heightList
4734 heights = dataOut.heightList
4748 nhei = len(heights)
4735 nhei = len(heights)
4749
4736
4750 range1 = numpy.arange(nhei) * deltah + h0
4737 range1 = numpy.arange(nhei) * deltah + h0
4751 jhei = (range1 >= hei_aver0).nonzero()
4738 jhei = (range1 >= hei_aver0).nonzero()
4752 if len(jhei[0]) > 0 :
4739 if len(jhei[0]) > 0 :
4753 h0_index = jhei[0][0] # Initial height for getting averages 218km
4740 h0_index = jhei[0][0] # Initial height for getting averages 218km
4754
4741
4755 mynhei = 7
4742 mynhei = 7
4756 nhei_avg = int(jrange/deltah)
4743 nhei_avg = int(jrange/deltah)
4757 h_avgs = int(nhei_avg/mynhei)
4744 h_avgs = int(nhei_avg/mynhei)
4758 nhei_avg = h_avgs*(mynhei-1)+mynhei
4745 nhei_avg = h_avgs*(mynhei-1)+mynhei
4759
4746
4760 navgs = numpy.zeros(mynhei,dtype='float')
4747 navgs = numpy.zeros(mynhei,dtype='float')
4761 delta_h = numpy.zeros(mynhei,dtype='float')
4748 delta_h = numpy.zeros(mynhei,dtype='float')
4762 range_aver = numpy.zeros(mynhei,dtype='float')
4749 range_aver = numpy.zeros(mynhei,dtype='float')
4763 for ih in range( mynhei-1 ):
4750 for ih in range( mynhei-1 ):
4764 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
4751 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
4765 navgs[ih] = h_avgs
4752 navgs[ih] = h_avgs
4766 delta_h[ih] = deltah*h_avgs
4753 delta_h[ih] = deltah*h_avgs
4767
4754
4768 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
4755 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
4769 navgs[mynhei-1] = 6*h_avgs
4756 navgs[mynhei-1] = 6*h_avgs
4770 delta_h[mynhei-1] = deltah*6*h_avgs
4757 delta_h[mynhei-1] = deltah*6*h_avgs
4771
4758
4772 wA = w[h0_index:h0_index+nhei_avg-0]
4759 wA = w[h0_index:h0_index+nhei_avg-0]
4773 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
4760 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
4774 for i in range(5) :
4761 for i in range(5) :
4775 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
4762 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
4776 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
4763 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
4777 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4764 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4778 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4765 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4779 wA[6*h_avgs+i] = avg
4766 wA[6*h_avgs+i] = avg
4780 wA_err[6*h_avgs+i] = sigma
4767 wA_err[6*h_avgs+i] = sigma
4781
4768
4782
4769
4783 vals = wA[0:6*h_avgs-0]
4770 vals = wA[0:6*h_avgs-0]
4784 errs=wA_err[0:6*h_avgs-0]
4771 errs=wA_err[0:6*h_avgs-0]
4785 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
4772 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
4786 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4773 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4787 wA[nhei_avg-1] = avg
4774 wA[nhei_avg-1] = avg
4788 wA_err[nhei_avg-1] = sigma
4775 wA_err[nhei_avg-1] = sigma
4789
4776
4790 wA = wA[6*h_avgs:nhei_avg-0]
4777 wA = wA[6*h_avgs:nhei_avg-0]
4791 wA_err=wA_err[6*h_avgs:nhei_avg-0]
4778 wA_err=wA_err[6*h_avgs:nhei_avg-0]
4792 if my_nbeams == 2 :
4779 if my_nbeams == 2 :
4793 uA = u[h0_index:h0_index+nhei_avg]
4780 uA = u[h0_index:h0_index+nhei_avg]
4794 uA_err=u_err[h0_index:h0_index+nhei_avg]
4781 uA_err=u_err[h0_index:h0_index+nhei_avg]
4795
4782
4796 for i in range(5) :
4783 for i in range(5) :
4797 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
4784 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
4798 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
4785 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
4799 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4786 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4800 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4787 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4801 uA[6*h_avgs+i] = avg
4788 uA[6*h_avgs+i] = avg
4802 uA_err[6*h_avgs+i]=sigma
4789 uA_err[6*h_avgs+i]=sigma
4803
4790
4804 vals = uA[0:6*h_avgs-0]
4791 vals = uA[0:6*h_avgs-0]
4805 errs = uA_err[0:6*h_avgs-0]
4792 errs = uA_err[0:6*h_avgs-0]
4806 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4793 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4807 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4794 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4808 uA[nhei_avg-1] = avg
4795 uA[nhei_avg-1] = avg
4809 uA_err[nhei_avg-1] = sigma
4796 uA_err[nhei_avg-1] = sigma
4810 uA = uA[6*h_avgs:nhei_avg-0]
4797 uA = uA[6*h_avgs:nhei_avg-0]
4811 uA_err = uA_err[6*h_avgs:nhei_avg-0]
4798 uA_err = uA_err[6*h_avgs:nhei_avg-0]
4812 dataOut.drifts_avg = numpy.vstack((wA,uA))
4799 dataOut.drifts_avg = numpy.vstack((wA,uA))
4813 if my_nbeams == 1: dataOut.drifts_avg = wA
4800 if my_nbeams == 1: dataOut.drifts_avg = wA
4814 tini=time.localtime(dataOut.utctime)
4801 tini=time.localtime(dataOut.utctime)
4815 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
4802 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
4816 nfile = fileDrifts+'/jro'+datefile+'drifts.txt'
4803 nfile = fileDrifts+'/jro'+datefile+'drifts.txt'
4817 f1 = open(nfile,'a')
4804 f1 = open(nfile,'a')
4818 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
4805 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
4819 driftavgstr=str(dataOut.drifts_avg)
4806 driftavgstr=str(dataOut.drifts_avg)
4820 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
4807 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
4821 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
4808 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
4822 f1.close()
4809 f1.close()
4823
4810
4824 return dataOut
4811 return dataOut
4825
4812
4826 #--------------- Non Specular Meteor ----------------
4813 #--------------- Non Specular Meteor ----------------
4827
4814
4828 class NonSpecularMeteorDetection(Operation):
4815 class NonSpecularMeteorDetection(Operation):
4829
4816
4830 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
4817 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
4831 data_acf = dataOut.data_pre[0]
4818 data_acf = dataOut.data_pre[0]
4832 data_ccf = dataOut.data_pre[1]
4819 data_ccf = dataOut.data_pre[1]
4833 pairsList = dataOut.groupList[1]
4820 pairsList = dataOut.groupList[1]
4834
4821
4835 lamb = dataOut.C/dataOut.frequency
4822 lamb = dataOut.C/dataOut.frequency
4836 tSamp = dataOut.ippSeconds*dataOut.nCohInt
4823 tSamp = dataOut.ippSeconds*dataOut.nCohInt
4837 paramInterval = dataOut.paramInterval
4824 paramInterval = dataOut.paramInterval
4838
4825
4839 nChannels = data_acf.shape[0]
4826 nChannels = data_acf.shape[0]
4840 nLags = data_acf.shape[1]
4827 nLags = data_acf.shape[1]
4841 nProfiles = data_acf.shape[2]
4828 nProfiles = data_acf.shape[2]
4842 nHeights = dataOut.nHeights
4829 nHeights = dataOut.nHeights
4843 nCohInt = dataOut.nCohInt
4830 nCohInt = dataOut.nCohInt
4844 sec = numpy.round(nProfiles/dataOut.paramInterval)
4831 sec = numpy.round(nProfiles/dataOut.paramInterval)
4845 heightList = dataOut.heightList
4832 heightList = dataOut.heightList
4846 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
4833 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
4847 utctime = dataOut.utctime
4834 utctime = dataOut.utctime
4848
4835
4849 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
4836 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
4850
4837
4851 #------------------------ SNR --------------------------------------
4838 #------------------------ SNR --------------------------------------
4852 power = data_acf[:,0,:,:].real
4839 power = data_acf[:,0,:,:].real
4853 noise = numpy.zeros(nChannels)
4840 noise = numpy.zeros(nChannels)
4854 SNR = numpy.zeros(power.shape)
4841 SNR = numpy.zeros(power.shape)
4855 for i in range(nChannels):
4842 for i in range(nChannels):
4856 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
4843 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
4857 SNR[i] = (power[i]-noise[i])/noise[i]
4844 SNR[i] = (power[i]-noise[i])/noise[i]
4858 SNRm = numpy.nanmean(SNR, axis = 0)
4845 SNRm = numpy.nanmean(SNR, axis = 0)
4859 SNRdB = 10*numpy.log10(SNR)
4846 SNRdB = 10*numpy.log10(SNR)
4860
4847
4861 if mode == 'SA':
4848 if mode == 'SA':
4862 dataOut.groupList = dataOut.groupList[1]
4849 dataOut.groupList = dataOut.groupList[1]
4863 nPairs = data_ccf.shape[0]
4850 nPairs = data_ccf.shape[0]
4864 #---------------------- Coherence and Phase --------------------------
4851 #---------------------- Coherence and Phase --------------------------
4865 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
4852 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
4866 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
4853 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
4867
4854
4868 for p in range(nPairs):
4855 for p in range(nPairs):
4869 ch0 = pairsList[p][0]
4856 ch0 = pairsList[p][0]
4870 ch1 = pairsList[p][1]
4857 ch1 = pairsList[p][1]
4871 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
4858 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
4872 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
4859 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
4873 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
4860 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
4874 coh = numpy.nanmax(coh1, axis = 0)
4861 coh = numpy.nanmax(coh1, axis = 0)
4875 #---------------------- Radial Velocity ----------------------------
4862 #---------------------- Radial Velocity ----------------------------
4876 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
4863 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
4877 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
4864 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
4878
4865
4879 if allData:
4866 if allData:
4880 boolMetFin = ~numpy.isnan(SNRm)
4867 boolMetFin = ~numpy.isnan(SNRm)
4881 else:
4868 else:
4882 #------------------------ Meteor mask ---------------------------------
4869 #------------------------ Meteor mask ---------------------------------
4883
4870
4884 #Coherence mask
4871 #Coherence mask
4885 boolMet1 = coh > 0.75
4872 boolMet1 = coh > 0.75
4886 struc = numpy.ones((30,1))
4873 struc = numpy.ones((30,1))
4887 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
4874 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
4888
4875
4889 #Derivative mask
4876 #Derivative mask
4890 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4877 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4891 boolMet2 = derPhase < 0.2
4878 boolMet2 = derPhase < 0.2
4892 boolMet2 = ndimage.median_filter(boolMet2,size=5)
4879 boolMet2 = ndimage.median_filter(boolMet2,size=5)
4893 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
4880 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
4894 boolMetFin = boolMet1&boolMet2
4881 boolMetFin = boolMet1&boolMet2
4895 #Creating data_param
4882 #Creating data_param
4896 coordMet = numpy.where(boolMetFin)
4883 coordMet = numpy.where(boolMetFin)
4897
4884
4898 tmet = coordMet[0]
4885 tmet = coordMet[0]
4899 hmet = coordMet[1]
4886 hmet = coordMet[1]
4900
4887
4901 data_param = numpy.zeros((tmet.size, 6 + nPairs))
4888 data_param = numpy.zeros((tmet.size, 6 + nPairs))
4902 data_param[:,0] = utctime
4889 data_param[:,0] = utctime
4903 data_param[:,1] = tmet
4890 data_param[:,1] = tmet
4904 data_param[:,2] = hmet
4891 data_param[:,2] = hmet
4905 data_param[:,3] = SNRm[tmet,hmet]
4892 data_param[:,3] = SNRm[tmet,hmet]
4906 data_param[:,4] = velRad[tmet,hmet]
4893 data_param[:,4] = velRad[tmet,hmet]
4907 data_param[:,5] = coh[tmet,hmet]
4894 data_param[:,5] = coh[tmet,hmet]
4908 data_param[:,6:] = phase[:,tmet,hmet].T
4895 data_param[:,6:] = phase[:,tmet,hmet].T
4909
4896
4910 elif mode == 'DBS':
4897 elif mode == 'DBS':
4911 dataOut.groupList = numpy.arange(nChannels)
4898 dataOut.groupList = numpy.arange(nChannels)
4912
4899
4913 #Radial Velocities
4900 #Radial Velocities
4914 phase = numpy.angle(data_acf[:,1,:,:])
4901 phase = numpy.angle(data_acf[:,1,:,:])
4915 velRad = phase*lamb/(4*numpy.pi*tSamp)
4902 velRad = phase*lamb/(4*numpy.pi*tSamp)
4916
4903
4917 #Spectral width
4904 #Spectral width
4918 acf1 = data_acf[:,1,:,:]
4905 acf1 = data_acf[:,1,:,:]
4919 acf2 = data_acf[:,2,:,:]
4906 acf2 = data_acf[:,2,:,:]
4920
4907
4921 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4908 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4922 if allData:
4909 if allData:
4923 boolMetFin = ~numpy.isnan(SNRdB)
4910 boolMetFin = ~numpy.isnan(SNRdB)
4924 else:
4911 else:
4925 #SNR
4912 #SNR
4926 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4913 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4927 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4914 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4928
4915
4929 #Radial velocity
4916 #Radial velocity
4930 boolMet2 = numpy.abs(velRad) < 20
4917 boolMet2 = numpy.abs(velRad) < 20
4931 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4918 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4932
4919
4933 #Spectral Width
4920 #Spectral Width
4934 boolMet3 = spcWidth < 30
4921 boolMet3 = spcWidth < 30
4935 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4922 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4936 boolMetFin = boolMet1&boolMet2&boolMet3
4923 boolMetFin = boolMet1&boolMet2&boolMet3
4937
4924
4938 #Creating data_param
4925 #Creating data_param
4939 coordMet = numpy.where(boolMetFin)
4926 coordMet = numpy.where(boolMetFin)
4940
4927
4941 cmet = coordMet[0]
4928 cmet = coordMet[0]
4942 tmet = coordMet[1]
4929 tmet = coordMet[1]
4943 hmet = coordMet[2]
4930 hmet = coordMet[2]
4944
4931
4945 data_param = numpy.zeros((tmet.size, 7))
4932 data_param = numpy.zeros((tmet.size, 7))
4946 data_param[:,0] = utctime
4933 data_param[:,0] = utctime
4947 data_param[:,1] = cmet
4934 data_param[:,1] = cmet
4948 data_param[:,2] = tmet
4935 data_param[:,2] = tmet
4949 data_param[:,3] = hmet
4936 data_param[:,3] = hmet
4950 data_param[:,4] = SNR[cmet,tmet,hmet].T
4937 data_param[:,4] = SNR[cmet,tmet,hmet].T
4951 data_param[:,5] = velRad[cmet,tmet,hmet].T
4938 data_param[:,5] = velRad[cmet,tmet,hmet].T
4952 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4939 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4953
4940
4954 if len(data_param) == 0:
4941 if len(data_param) == 0:
4955 dataOut.flagNoData = True
4942 dataOut.flagNoData = True
4956 else:
4943 else:
4957 dataOut.data_param = data_param
4944 dataOut.data_param = data_param
4958
4945
4959 def __erase_small(self, binArray, threshX, threshY):
4946 def __erase_small(self, binArray, threshX, threshY):
4960 labarray, numfeat = ndimage.measurements.label(binArray)
4947 labarray, numfeat = ndimage.measurements.label(binArray)
4961 binArray1 = numpy.copy(binArray)
4948 binArray1 = numpy.copy(binArray)
4962
4949
4963 for i in range(1,numfeat + 1):
4950 for i in range(1,numfeat + 1):
4964 auxBin = (labarray==i)
4951 auxBin = (labarray==i)
4965 auxSize = auxBin.sum()
4952 auxSize = auxBin.sum()
4966
4953
4967 x,y = numpy.where(auxBin)
4954 x,y = numpy.where(auxBin)
4968 widthX = x.max() - x.min()
4955 widthX = x.max() - x.min()
4969 widthY = y.max() - y.min()
4956 widthY = y.max() - y.min()
4970
4957
4971 #width X: 3 seg -> 12.5*3
4958 #width X: 3 seg -> 12.5*3
4972 #width Y:
4959 #width Y:
4973
4960
4974 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
4961 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
4975 binArray1[auxBin] = False
4962 binArray1[auxBin] = False
4976
4963
4977 return binArray1
4964 return binArray1
4978
4965
4979 #--------------- Specular Meteor ----------------
4966 #--------------- Specular Meteor ----------------
4980
4967
4981 class SMDetection(Operation):
4968 class SMDetection(Operation):
4982 '''
4969 '''
4983 Function DetectMeteors()
4970 Function DetectMeteors()
4984 Project developed with paper:
4971 Project developed with paper:
4985 HOLDSWORTH ET AL. 2004
4972 HOLDSWORTH ET AL. 2004
4986
4973
4987 Input:
4974 Input:
4988 self.dataOut.data_pre
4975 self.dataOut.data_pre
4989
4976
4990 centerReceiverIndex: From the channels, which is the center receiver
4977 centerReceiverIndex: From the channels, which is the center receiver
4991
4978
4992 hei_ref: Height reference for the Beacon signal extraction
4979 hei_ref: Height reference for the Beacon signal extraction
4993 tauindex:
4980 tauindex:
4994 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4981 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4995
4982
4996 cohDetection: Whether to user Coherent detection or not
4983 cohDetection: Whether to user Coherent detection or not
4997 cohDet_timeStep: Coherent Detection calculation time step
4984 cohDet_timeStep: Coherent Detection calculation time step
4998 cohDet_thresh: Coherent Detection phase threshold to correct phases
4985 cohDet_thresh: Coherent Detection phase threshold to correct phases
4999
4986
5000 noise_timeStep: Noise calculation time step
4987 noise_timeStep: Noise calculation time step
5001 noise_multiple: Noise multiple to define signal threshold
4988 noise_multiple: Noise multiple to define signal threshold
5002
4989
5003 multDet_timeLimit: Multiple Detection Removal time limit in seconds
4990 multDet_timeLimit: Multiple Detection Removal time limit in seconds
5004 multDet_rangeLimit: Multiple Detection Removal range limit in km
4991 multDet_rangeLimit: Multiple Detection Removal range limit in km
5005
4992
5006 phaseThresh: Maximum phase difference between receiver to be consider a meteor
4993 phaseThresh: Maximum phase difference between receiver to be consider a meteor
5007 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
4994 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
5008
4995
5009 hmin: Minimum Height of the meteor to use it in the further wind estimations
4996 hmin: Minimum Height of the meteor to use it in the further wind estimations
5010 hmax: Maximum Height of the meteor to use it in the further wind estimations
4997 hmax: Maximum Height of the meteor to use it in the further wind estimations
5011 azimuth: Azimuth angle correction
4998 azimuth: Azimuth angle correction
5012
4999
5013 Affected:
5000 Affected:
5014 self.dataOut.data_param
5001 self.dataOut.data_param
5015
5002
5016 Rejection Criteria (Errors):
5003 Rejection Criteria (Errors):
5017 0: No error; analysis OK
5004 0: No error; analysis OK
5018 1: SNR < SNR threshold
5005 1: SNR < SNR threshold
5019 2: angle of arrival (AOA) ambiguously determined
5006 2: angle of arrival (AOA) ambiguously determined
5020 3: AOA estimate not feasible
5007 3: AOA estimate not feasible
5021 4: Large difference in AOAs obtained from different antenna baselines
5008 4: Large difference in AOAs obtained from different antenna baselines
5022 5: echo at start or end of time series
5009 5: echo at start or end of time series
5023 6: echo less than 5 examples long; too short for analysis
5010 6: echo less than 5 examples long; too short for analysis
5024 7: echo rise exceeds 0.3s
5011 7: echo rise exceeds 0.3s
5025 8: echo decay time less than twice rise time
5012 8: echo decay time less than twice rise time
5026 9: large power level before echo
5013 9: large power level before echo
5027 10: large power level after echo
5014 10: large power level after echo
5028 11: poor fit to amplitude for estimation of decay time
5015 11: poor fit to amplitude for estimation of decay time
5029 12: poor fit to CCF phase variation for estimation of radial drift velocity
5016 12: poor fit to CCF phase variation for estimation of radial drift velocity
5030 13: height unresolvable echo: not valid height within 70 to 110 km
5017 13: height unresolvable echo: not valid height within 70 to 110 km
5031 14: height ambiguous echo: more then one possible height within 70 to 110 km
5018 14: height ambiguous echo: more then one possible height within 70 to 110 km
5032 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
5019 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
5033 16: oscilatory echo, indicating event most likely not an underdense echo
5020 16: oscilatory echo, indicating event most likely not an underdense echo
5034
5021
5035 17: phase difference in meteor Reestimation
5022 17: phase difference in meteor Reestimation
5036
5023
5037 Data Storage:
5024 Data Storage:
5038 Meteors for Wind Estimation (8):
5025 Meteors for Wind Estimation (8):
5039 Utc Time | Range Height
5026 Utc Time | Range Height
5040 Azimuth Zenith errorCosDir
5027 Azimuth Zenith errorCosDir
5041 VelRad errorVelRad
5028 VelRad errorVelRad
5042 Phase0 Phase1 Phase2 Phase3
5029 Phase0 Phase1 Phase2 Phase3
5043 TypeError
5030 TypeError
5044
5031
5045 '''
5032 '''
5046
5033
5047 def run(self, dataOut, hei_ref = None, tauindex = 0,
5034 def run(self, dataOut, hei_ref = None, tauindex = 0,
5048 phaseOffsets = None,
5035 phaseOffsets = None,
5049 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
5036 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
5050 noise_timeStep = 4, noise_multiple = 4,
5037 noise_timeStep = 4, noise_multiple = 4,
5051 multDet_timeLimit = 1, multDet_rangeLimit = 3,
5038 multDet_timeLimit = 1, multDet_rangeLimit = 3,
5052 phaseThresh = 20, SNRThresh = 5,
5039 phaseThresh = 20, SNRThresh = 5,
5053 hmin = 50, hmax=150, azimuth = 0,
5040 hmin = 50, hmax=150, azimuth = 0,
5054 channelPositions = None) :
5041 channelPositions = None) :
5055
5042
5056
5043
5057 #Getting Pairslist
5044 #Getting Pairslist
5058 if channelPositions is None:
5045 if channelPositions is None:
5059 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5046 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5060 meteorOps = SMOperations()
5047 meteorOps = SMOperations()
5061 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5048 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5062 heiRang = dataOut.heightList
5049 heiRang = dataOut.heightList
5063 #Get Beacon signal - No Beacon signal anymore
5050 #Get Beacon signal - No Beacon signal anymore
5064 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
5051 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
5065 # see if the user put in pre defined phase shifts
5052 # see if the user put in pre defined phase shifts
5066 voltsPShift = dataOut.data_pre.copy()
5053 voltsPShift = dataOut.data_pre.copy()
5067
5054
5068 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
5055 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
5069
5056
5070 #Remove DC
5057 #Remove DC
5071 voltsDC = numpy.mean(voltsPShift,1)
5058 voltsDC = numpy.mean(voltsPShift,1)
5072 voltsDC = numpy.mean(voltsDC,1)
5059 voltsDC = numpy.mean(voltsDC,1)
5073 for i in range(voltsDC.shape[0]):
5060 for i in range(voltsDC.shape[0]):
5074 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
5061 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
5075
5062
5076 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
5063 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
5077
5064
5078 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
5065 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
5079 #Coherent Detection
5066 #Coherent Detection
5080 if cohDetection:
5067 if cohDetection:
5081 #use coherent detection to get the net power
5068 #use coherent detection to get the net power
5082 cohDet_thresh = cohDet_thresh*numpy.pi/180
5069 cohDet_thresh = cohDet_thresh*numpy.pi/180
5083 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
5070 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
5084
5071
5085 #Non-coherent detection!
5072 #Non-coherent detection!
5086 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
5073 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
5087 #********** END OF COH/NON-COH POWER CALCULATION**********************
5074 #********** END OF COH/NON-COH POWER CALCULATION**********************
5088
5075
5089 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
5076 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
5090 #Get noise
5077 #Get noise
5091 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
5078 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
5092 #Get signal threshold
5079 #Get signal threshold
5093 signalThresh = noise_multiple*noise
5080 signalThresh = noise_multiple*noise
5094 #Meteor echoes detection
5081 #Meteor echoes detection
5095 listMeteors = self.__findMeteors(powerNet, signalThresh)
5082 listMeteors = self.__findMeteors(powerNet, signalThresh)
5096 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
5083 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
5097
5084
5098 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
5085 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
5099 #Parameters
5086 #Parameters
5100 heiRange = dataOut.heightList
5087 heiRange = dataOut.heightList
5101 rangeInterval = heiRange[1] - heiRange[0]
5088 rangeInterval = heiRange[1] - heiRange[0]
5102 rangeLimit = multDet_rangeLimit/rangeInterval
5089 rangeLimit = multDet_rangeLimit/rangeInterval
5103 timeLimit = multDet_timeLimit/dataOut.timeInterval
5090 timeLimit = multDet_timeLimit/dataOut.timeInterval
5104 #Multiple detection removals
5091 #Multiple detection removals
5105 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
5092 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
5106 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
5093 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
5107
5094
5108 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
5095 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
5109 #Parameters
5096 #Parameters
5110 phaseThresh = phaseThresh*numpy.pi/180
5097 phaseThresh = phaseThresh*numpy.pi/180
5111 thresh = [phaseThresh, noise_multiple, SNRThresh]
5098 thresh = [phaseThresh, noise_multiple, SNRThresh]
5112 #Meteor reestimation (Errors N 1, 6, 12, 17)
5099 #Meteor reestimation (Errors N 1, 6, 12, 17)
5113 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
5100 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
5114 #Estimation of decay times (Errors N 7, 8, 11)
5101 #Estimation of decay times (Errors N 7, 8, 11)
5115 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
5102 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
5116 #******************* END OF METEOR REESTIMATION *******************
5103 #******************* END OF METEOR REESTIMATION *******************
5117
5104
5118 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
5105 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
5119 #Calculating Radial Velocity (Error N 15)
5106 #Calculating Radial Velocity (Error N 15)
5120 radialStdThresh = 10
5107 radialStdThresh = 10
5121 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
5108 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
5122
5109
5123 if len(listMeteors4) > 0:
5110 if len(listMeteors4) > 0:
5124 #Setting New Array
5111 #Setting New Array
5125 date = dataOut.utctime
5112 date = dataOut.utctime
5126 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
5113 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
5127
5114
5128 #Correcting phase offset
5115 #Correcting phase offset
5129 if phaseOffsets != None:
5116 if phaseOffsets != None:
5130 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5117 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5131 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5118 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5132
5119
5133 #Second Pairslist
5120 #Second Pairslist
5134 pairsList = []
5121 pairsList = []
5135 pairx = (0,1)
5122 pairx = (0,1)
5136 pairy = (2,3)
5123 pairy = (2,3)
5137 pairsList.append(pairx)
5124 pairsList.append(pairx)
5138 pairsList.append(pairy)
5125 pairsList.append(pairy)
5139
5126
5140 jph = numpy.array([0,0,0,0])
5127 jph = numpy.array([0,0,0,0])
5141 h = (hmin,hmax)
5128 h = (hmin,hmax)
5142 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5129 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5143 dataOut.data_param = arrayParameters
5130 dataOut.data_param = arrayParameters
5144
5131
5145 if arrayParameters is None:
5132 if arrayParameters is None:
5146 dataOut.flagNoData = True
5133 dataOut.flagNoData = True
5147 else:
5134 else:
5148 dataOut.flagNoData = True
5135 dataOut.flagNoData = True
5149
5136
5150 return
5137 return
5151
5138
5152 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
5139 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
5153
5140
5154 minIndex = min(newheis[0])
5141 minIndex = min(newheis[0])
5155 maxIndex = max(newheis[0])
5142 maxIndex = max(newheis[0])
5156
5143
5157 voltage = voltage0[:,:,minIndex:maxIndex+1]
5144 voltage = voltage0[:,:,minIndex:maxIndex+1]
5158 nLength = voltage.shape[1]/n
5145 nLength = voltage.shape[1]/n
5159 nMin = 0
5146 nMin = 0
5160 nMax = 0
5147 nMax = 0
5161 phaseOffset = numpy.zeros((len(pairslist),n))
5148 phaseOffset = numpy.zeros((len(pairslist),n))
5162
5149
5163 for i in range(n):
5150 for i in range(n):
5164 nMax += nLength
5151 nMax += nLength
5165 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
5152 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
5166 phaseCCF = numpy.mean(phaseCCF, axis = 2)
5153 phaseCCF = numpy.mean(phaseCCF, axis = 2)
5167 phaseOffset[:,i] = phaseCCF.transpose()
5154 phaseOffset[:,i] = phaseCCF.transpose()
5168 nMin = nMax
5155 nMin = nMax
5169
5156
5170 #Remove Outliers
5157 #Remove Outliers
5171 factor = 2
5158 factor = 2
5172 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
5159 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
5173 dw = numpy.std(wt,axis = 1)
5160 dw = numpy.std(wt,axis = 1)
5174 dw = dw.reshape((dw.size,1))
5161 dw = dw.reshape((dw.size,1))
5175 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
5162 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
5176 phaseOffset[ind] = numpy.nan
5163 phaseOffset[ind] = numpy.nan
5177 phaseOffset = stats.nanmean(phaseOffset, axis=1)
5164 phaseOffset = stats.nanmean(phaseOffset, axis=1)
5178
5165
5179 return phaseOffset
5166 return phaseOffset
5180
5167
5181 def __shiftPhase(self, data, phaseShift):
5168 def __shiftPhase(self, data, phaseShift):
5182 #this will shift the phase of a complex number
5169 #this will shift the phase of a complex number
5183 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
5170 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
5184 return dataShifted
5171 return dataShifted
5185
5172
5186 def __estimatePhaseDifference(self, array, pairslist):
5173 def __estimatePhaseDifference(self, array, pairslist):
5187 nChannel = array.shape[0]
5174 nChannel = array.shape[0]
5188 nHeights = array.shape[2]
5175 nHeights = array.shape[2]
5189 numPairs = len(pairslist)
5176 numPairs = len(pairslist)
5190 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
5177 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
5191
5178
5192 #Correct phases
5179 #Correct phases
5193 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
5180 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
5194 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5181 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5195
5182
5196 if indDer[0].shape[0] > 0:
5183 if indDer[0].shape[0] > 0:
5197 for i in range(indDer[0].shape[0]):
5184 for i in range(indDer[0].shape[0]):
5198 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
5185 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
5199 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
5186 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
5200
5187
5201 #Linear
5188 #Linear
5202 phaseInt = numpy.zeros((numPairs,1))
5189 phaseInt = numpy.zeros((numPairs,1))
5203 angAllCCF = phaseCCF[:,[0,1,3,4],0]
5190 angAllCCF = phaseCCF[:,[0,1,3,4],0]
5204 for j in range(numPairs):
5191 for j in range(numPairs):
5205 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
5192 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
5206 phaseInt[j] = fit[1]
5193 phaseInt[j] = fit[1]
5207 #Phase Differences
5194 #Phase Differences
5208 phaseDiff = phaseInt - phaseCCF[:,2,:]
5195 phaseDiff = phaseInt - phaseCCF[:,2,:]
5209 phaseArrival = phaseInt.reshape(phaseInt.size)
5196 phaseArrival = phaseInt.reshape(phaseInt.size)
5210
5197
5211 #Dealias
5198 #Dealias
5212 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
5199 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
5213
5200
5214 return phaseDiff, phaseArrival
5201 return phaseDiff, phaseArrival
5215
5202
5216 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
5203 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
5217 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
5204 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
5218 #find the phase shifts of each channel over 1 second intervals
5205 #find the phase shifts of each channel over 1 second intervals
5219 #only look at ranges below the beacon signal
5206 #only look at ranges below the beacon signal
5220 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5207 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5221 numBlocks = int(volts.shape[1]/numProfPerBlock)
5208 numBlocks = int(volts.shape[1]/numProfPerBlock)
5222 numHeights = volts.shape[2]
5209 numHeights = volts.shape[2]
5223 nChannel = volts.shape[0]
5210 nChannel = volts.shape[0]
5224 voltsCohDet = volts.copy()
5211 voltsCohDet = volts.copy()
5225
5212
5226 pairsarray = numpy.array(pairslist)
5213 pairsarray = numpy.array(pairslist)
5227 indSides = pairsarray[:,1]
5214 indSides = pairsarray[:,1]
5228 listBlocks = numpy.array_split(volts, numBlocks, 1)
5215 listBlocks = numpy.array_split(volts, numBlocks, 1)
5229
5216
5230 startInd = 0
5217 startInd = 0
5231 endInd = 0
5218 endInd = 0
5232
5219
5233 for i in range(numBlocks):
5220 for i in range(numBlocks):
5234 startInd = endInd
5221 startInd = endInd
5235 endInd = endInd + listBlocks[i].shape[1]
5222 endInd = endInd + listBlocks[i].shape[1]
5236
5223
5237 arrayBlock = listBlocks[i]
5224 arrayBlock = listBlocks[i]
5238
5225
5239 #Estimate the Phase Difference
5226 #Estimate the Phase Difference
5240 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
5227 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
5241 #Phase Difference RMS
5228 #Phase Difference RMS
5242 arrayPhaseRMS = numpy.abs(phaseDiff)
5229 arrayPhaseRMS = numpy.abs(phaseDiff)
5243 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
5230 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
5244 indPhase = numpy.where(phaseRMSaux==4)
5231 indPhase = numpy.where(phaseRMSaux==4)
5245 #Shifting
5232 #Shifting
5246 if indPhase[0].shape[0] > 0:
5233 if indPhase[0].shape[0] > 0:
5247 for j in range(indSides.size):
5234 for j in range(indSides.size):
5248 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
5235 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
5249 voltsCohDet[:,startInd:endInd,:] = arrayBlock
5236 voltsCohDet[:,startInd:endInd,:] = arrayBlock
5250
5237
5251 return voltsCohDet
5238 return voltsCohDet
5252
5239
5253 def __calculateCCF(self, volts, pairslist ,laglist):
5240 def __calculateCCF(self, volts, pairslist ,laglist):
5254
5241
5255 nHeights = volts.shape[2]
5242 nHeights = volts.shape[2]
5256 nPoints = volts.shape[1]
5243 nPoints = volts.shape[1]
5257 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
5244 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
5258
5245
5259 for i in range(len(pairslist)):
5246 for i in range(len(pairslist)):
5260 volts1 = volts[pairslist[i][0]]
5247 volts1 = volts[pairslist[i][0]]
5261 volts2 = volts[pairslist[i][1]]
5248 volts2 = volts[pairslist[i][1]]
5262
5249
5263 for t in range(len(laglist)):
5250 for t in range(len(laglist)):
5264 idxT = laglist[t]
5251 idxT = laglist[t]
5265 if idxT >= 0:
5252 if idxT >= 0:
5266 vStacked = numpy.vstack((volts2[idxT:,:],
5253 vStacked = numpy.vstack((volts2[idxT:,:],
5267 numpy.zeros((idxT, nHeights),dtype='complex')))
5254 numpy.zeros((idxT, nHeights),dtype='complex')))
5268 else:
5255 else:
5269 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
5256 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
5270 volts2[:(nPoints + idxT),:]))
5257 volts2[:(nPoints + idxT),:]))
5271 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
5258 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
5272
5259
5273 vStacked = None
5260 vStacked = None
5274 return voltsCCF
5261 return voltsCCF
5275
5262
5276 def __getNoise(self, power, timeSegment, timeInterval):
5263 def __getNoise(self, power, timeSegment, timeInterval):
5277 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5264 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5278 numBlocks = int(power.shape[0]/numProfPerBlock)
5265 numBlocks = int(power.shape[0]/numProfPerBlock)
5279 numHeights = power.shape[1]
5266 numHeights = power.shape[1]
5280
5267
5281 listPower = numpy.array_split(power, numBlocks, 0)
5268 listPower = numpy.array_split(power, numBlocks, 0)
5282 noise = numpy.zeros((power.shape[0], power.shape[1]))
5269 noise = numpy.zeros((power.shape[0], power.shape[1]))
5283 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
5270 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
5284
5271
5285 startInd = 0
5272 startInd = 0
5286 endInd = 0
5273 endInd = 0
5287
5274
5288 for i in range(numBlocks): #split por canal
5275 for i in range(numBlocks): #split por canal
5289 startInd = endInd
5276 startInd = endInd
5290 endInd = endInd + listPower[i].shape[0]
5277 endInd = endInd + listPower[i].shape[0]
5291
5278
5292 arrayBlock = listPower[i]
5279 arrayBlock = listPower[i]
5293 noiseAux = numpy.mean(arrayBlock, 0)
5280 noiseAux = numpy.mean(arrayBlock, 0)
5294 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
5281 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
5295
5282
5296 noiseAux1 = numpy.mean(arrayBlock)
5283 noiseAux1 = numpy.mean(arrayBlock)
5297 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
5284 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
5298
5285
5299 return noise, noise1
5286 return noise, noise1
5300
5287
5301 def __findMeteors(self, power, thresh):
5288 def __findMeteors(self, power, thresh):
5302 nProf = power.shape[0]
5289 nProf = power.shape[0]
5303 nHeights = power.shape[1]
5290 nHeights = power.shape[1]
5304 listMeteors = []
5291 listMeteors = []
5305
5292
5306 for i in range(nHeights):
5293 for i in range(nHeights):
5307 powerAux = power[:,i]
5294 powerAux = power[:,i]
5308 threshAux = thresh[:,i]
5295 threshAux = thresh[:,i]
5309
5296
5310 indUPthresh = numpy.where(powerAux > threshAux)[0]
5297 indUPthresh = numpy.where(powerAux > threshAux)[0]
5311 indDNthresh = numpy.where(powerAux <= threshAux)[0]
5298 indDNthresh = numpy.where(powerAux <= threshAux)[0]
5312
5299
5313 j = 0
5300 j = 0
5314
5301
5315 while (j < indUPthresh.size - 2):
5302 while (j < indUPthresh.size - 2):
5316 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
5303 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
5317 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
5304 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
5318 indDNthresh = indDNthresh[indDNAux]
5305 indDNthresh = indDNthresh[indDNAux]
5319
5306
5320 if (indDNthresh.size > 0):
5307 if (indDNthresh.size > 0):
5321 indEnd = indDNthresh[0] - 1
5308 indEnd = indDNthresh[0] - 1
5322 indInit = indUPthresh[j]
5309 indInit = indUPthresh[j]
5323
5310
5324 meteor = powerAux[indInit:indEnd + 1]
5311 meteor = powerAux[indInit:indEnd + 1]
5325 indPeak = meteor.argmax() + indInit
5312 indPeak = meteor.argmax() + indInit
5326 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
5313 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
5327
5314
5328 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
5315 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
5329 j = numpy.where(indUPthresh == indEnd)[0] + 1
5316 j = numpy.where(indUPthresh == indEnd)[0] + 1
5330 else: j+=1
5317 else: j+=1
5331 else: j+=1
5318 else: j+=1
5332
5319
5333 return listMeteors
5320 return listMeteors
5334
5321
5335 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
5322 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
5336
5323
5337 arrayMeteors = numpy.asarray(listMeteors)
5324 arrayMeteors = numpy.asarray(listMeteors)
5338 listMeteors1 = []
5325 listMeteors1 = []
5339
5326
5340 while arrayMeteors.shape[0] > 0:
5327 while arrayMeteors.shape[0] > 0:
5341 FLAs = arrayMeteors[:,4]
5328 FLAs = arrayMeteors[:,4]
5342 maxFLA = FLAs.argmax()
5329 maxFLA = FLAs.argmax()
5343 listMeteors1.append(arrayMeteors[maxFLA,:])
5330 listMeteors1.append(arrayMeteors[maxFLA,:])
5344
5331
5345 MeteorInitTime = arrayMeteors[maxFLA,1]
5332 MeteorInitTime = arrayMeteors[maxFLA,1]
5346 MeteorEndTime = arrayMeteors[maxFLA,3]
5333 MeteorEndTime = arrayMeteors[maxFLA,3]
5347 MeteorHeight = arrayMeteors[maxFLA,0]
5334 MeteorHeight = arrayMeteors[maxFLA,0]
5348
5335
5349 #Check neighborhood
5336 #Check neighborhood
5350 maxHeightIndex = MeteorHeight + rangeLimit
5337 maxHeightIndex = MeteorHeight + rangeLimit
5351 minHeightIndex = MeteorHeight - rangeLimit
5338 minHeightIndex = MeteorHeight - rangeLimit
5352 minTimeIndex = MeteorInitTime - timeLimit
5339 minTimeIndex = MeteorInitTime - timeLimit
5353 maxTimeIndex = MeteorEndTime + timeLimit
5340 maxTimeIndex = MeteorEndTime + timeLimit
5354
5341
5355 #Check Heights
5342 #Check Heights
5356 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
5343 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
5357 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
5344 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
5358 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
5345 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
5359
5346
5360 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
5347 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
5361
5348
5362 return listMeteors1
5349 return listMeteors1
5363
5350
5364 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
5351 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
5365 numHeights = volts.shape[2]
5352 numHeights = volts.shape[2]
5366 nChannel = volts.shape[0]
5353 nChannel = volts.shape[0]
5367
5354
5368 thresholdPhase = thresh[0]
5355 thresholdPhase = thresh[0]
5369 thresholdNoise = thresh[1]
5356 thresholdNoise = thresh[1]
5370 thresholdDB = float(thresh[2])
5357 thresholdDB = float(thresh[2])
5371
5358
5372 thresholdDB1 = 10**(thresholdDB/10)
5359 thresholdDB1 = 10**(thresholdDB/10)
5373 pairsarray = numpy.array(pairslist)
5360 pairsarray = numpy.array(pairslist)
5374 indSides = pairsarray[:,1]
5361 indSides = pairsarray[:,1]
5375
5362
5376 pairslist1 = list(pairslist)
5363 pairslist1 = list(pairslist)
5377 pairslist1.append((0,1))
5364 pairslist1.append((0,1))
5378 pairslist1.append((3,4))
5365 pairslist1.append((3,4))
5379
5366
5380 listMeteors1 = []
5367 listMeteors1 = []
5381 listPowerSeries = []
5368 listPowerSeries = []
5382 listVoltageSeries = []
5369 listVoltageSeries = []
5383 #volts has the war data
5370 #volts has the war data
5384
5371
5385 if frequency == 30e6:
5372 if frequency == 30e6:
5386 timeLag = 45*10**-3
5373 timeLag = 45*10**-3
5387 else:
5374 else:
5388 timeLag = 15*10**-3
5375 timeLag = 15*10**-3
5389 lag = numpy.ceil(timeLag/timeInterval)
5376 lag = numpy.ceil(timeLag/timeInterval)
5390
5377
5391 for i in range(len(listMeteors)):
5378 for i in range(len(listMeteors)):
5392
5379
5393 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
5380 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
5394 meteorAux = numpy.zeros(16)
5381 meteorAux = numpy.zeros(16)
5395
5382
5396 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
5383 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
5397 mHeight = listMeteors[i][0]
5384 mHeight = listMeteors[i][0]
5398 mStart = listMeteors[i][1]
5385 mStart = listMeteors[i][1]
5399 mPeak = listMeteors[i][2]
5386 mPeak = listMeteors[i][2]
5400 mEnd = listMeteors[i][3]
5387 mEnd = listMeteors[i][3]
5401
5388
5402 #get the volt data between the start and end times of the meteor
5389 #get the volt data between the start and end times of the meteor
5403 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
5390 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
5404 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5391 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5405
5392
5406 #3.6. Phase Difference estimation
5393 #3.6. Phase Difference estimation
5407 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
5394 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
5408
5395
5409 #3.7. Phase difference removal & meteor start, peak and end times reestimated
5396 #3.7. Phase difference removal & meteor start, peak and end times reestimated
5410 #meteorVolts0.- all Channels, all Profiles
5397 #meteorVolts0.- all Channels, all Profiles
5411 meteorVolts0 = volts[:,:,mHeight]
5398 meteorVolts0 = volts[:,:,mHeight]
5412 meteorThresh = noise[:,mHeight]*thresholdNoise
5399 meteorThresh = noise[:,mHeight]*thresholdNoise
5413 meteorNoise = noise[:,mHeight]
5400 meteorNoise = noise[:,mHeight]
5414 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
5401 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
5415 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
5402 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
5416
5403
5417 #Times reestimation
5404 #Times reestimation
5418 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
5405 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
5419 if mStart1.size > 0:
5406 if mStart1.size > 0:
5420 mStart1 = mStart1[-1] + 1
5407 mStart1 = mStart1[-1] + 1
5421
5408
5422 else:
5409 else:
5423 mStart1 = mPeak
5410 mStart1 = mPeak
5424
5411
5425 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
5412 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
5426 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
5413 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
5427 if mEndDecayTime1.size == 0:
5414 if mEndDecayTime1.size == 0:
5428 mEndDecayTime1 = powerNet0.size
5415 mEndDecayTime1 = powerNet0.size
5429 else:
5416 else:
5430 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
5417 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
5431
5418
5432 #meteorVolts1.- all Channels, from start to end
5419 #meteorVolts1.- all Channels, from start to end
5433 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
5420 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
5434 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
5421 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
5435 if meteorVolts2.shape[1] == 0:
5422 if meteorVolts2.shape[1] == 0:
5436 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
5423 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
5437 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
5424 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
5438 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
5425 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
5439 ##################### END PARAMETERS REESTIMATION #########################
5426 ##################### END PARAMETERS REESTIMATION #########################
5440
5427
5441 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
5428 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
5442 if meteorVolts2.shape[1] > 0:
5429 if meteorVolts2.shape[1] > 0:
5443 #Phase Difference re-estimation
5430 #Phase Difference re-estimation
5444 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
5431 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
5445 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
5432 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
5446 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
5433 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
5447 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
5434 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
5448
5435
5449 #Phase Difference RMS
5436 #Phase Difference RMS
5450 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
5437 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
5451 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
5438 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
5452 #Data from Meteor
5439 #Data from Meteor
5453 mPeak1 = powerNet1.argmax() + mStart1
5440 mPeak1 = powerNet1.argmax() + mStart1
5454 mPeakPower1 = powerNet1.max()
5441 mPeakPower1 = powerNet1.max()
5455 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
5442 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
5456 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
5443 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
5457 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
5444 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
5458 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
5445 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
5459 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
5446 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
5460 #Vectorize
5447 #Vectorize
5461 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
5448 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
5462 meteorAux[7:11] = phaseDiffint[0:4]
5449 meteorAux[7:11] = phaseDiffint[0:4]
5463
5450
5464 #Rejection Criterions
5451 #Rejection Criterions
5465 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
5452 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
5466 meteorAux[-1] = 17
5453 meteorAux[-1] = 17
5467 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
5454 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
5468 meteorAux[-1] = 1
5455 meteorAux[-1] = 1
5469
5456
5470
5457
5471 else:
5458 else:
5472 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
5459 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
5473 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
5460 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
5474 PowerSeries = 0
5461 PowerSeries = 0
5475
5462
5476 listMeteors1.append(meteorAux)
5463 listMeteors1.append(meteorAux)
5477 listPowerSeries.append(PowerSeries)
5464 listPowerSeries.append(PowerSeries)
5478 listVoltageSeries.append(meteorVolts1)
5465 listVoltageSeries.append(meteorVolts1)
5479
5466
5480 return listMeteors1, listPowerSeries, listVoltageSeries
5467 return listMeteors1, listPowerSeries, listVoltageSeries
5481
5468
5482 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
5469 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
5483
5470
5484 threshError = 10
5471 threshError = 10
5485 #Depending if it is 30 or 50 MHz
5472 #Depending if it is 30 or 50 MHz
5486 if frequency == 30e6:
5473 if frequency == 30e6:
5487 timeLag = 45*10**-3
5474 timeLag = 45*10**-3
5488 else:
5475 else:
5489 timeLag = 15*10**-3
5476 timeLag = 15*10**-3
5490 lag = numpy.ceil(timeLag/timeInterval)
5477 lag = numpy.ceil(timeLag/timeInterval)
5491
5478
5492 listMeteors1 = []
5479 listMeteors1 = []
5493
5480
5494 for i in range(len(listMeteors)):
5481 for i in range(len(listMeteors)):
5495 meteorPower = listPower[i]
5482 meteorPower = listPower[i]
5496 meteorAux = listMeteors[i]
5483 meteorAux = listMeteors[i]
5497
5484
5498 if meteorAux[-1] == 0:
5485 if meteorAux[-1] == 0:
5499
5486
5500 try:
5487 try:
5501 indmax = meteorPower.argmax()
5488 indmax = meteorPower.argmax()
5502 indlag = indmax + lag
5489 indlag = indmax + lag
5503
5490
5504 y = meteorPower[indlag:]
5491 y = meteorPower[indlag:]
5505 x = numpy.arange(0, y.size)*timeLag
5492 x = numpy.arange(0, y.size)*timeLag
5506
5493
5507 #first guess
5494 #first guess
5508 a = y[0]
5495 a = y[0]
5509 tau = timeLag
5496 tau = timeLag
5510 #exponential fit
5497 #exponential fit
5511 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
5498 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
5512 y1 = self.__exponential_function(x, *popt)
5499 y1 = self.__exponential_function(x, *popt)
5513 #error estimation
5500 #error estimation
5514 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
5501 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
5515
5502
5516 decayTime = popt[1]
5503 decayTime = popt[1]
5517 riseTime = indmax*timeInterval
5504 riseTime = indmax*timeInterval
5518 meteorAux[11:13] = [decayTime, error]
5505 meteorAux[11:13] = [decayTime, error]
5519
5506
5520 #Table items 7, 8 and 11
5507 #Table items 7, 8 and 11
5521 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
5508 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
5522 meteorAux[-1] = 7
5509 meteorAux[-1] = 7
5523 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
5510 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
5524 meteorAux[-1] = 8
5511 meteorAux[-1] = 8
5525 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
5512 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
5526 meteorAux[-1] = 11
5513 meteorAux[-1] = 11
5527
5514
5528
5515
5529 except:
5516 except:
5530 meteorAux[-1] = 11
5517 meteorAux[-1] = 11
5531
5518
5532
5519
5533 listMeteors1.append(meteorAux)
5520 listMeteors1.append(meteorAux)
5534
5521
5535 return listMeteors1
5522 return listMeteors1
5536
5523
5537 #Exponential Function
5524 #Exponential Function
5538
5525
5539 def __exponential_function(self, x, a, tau):
5526 def __exponential_function(self, x, a, tau):
5540 y = a*numpy.exp(-x/tau)
5527 y = a*numpy.exp(-x/tau)
5541 return y
5528 return y
5542
5529
5543 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
5530 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
5544
5531
5545 pairslist1 = list(pairslist)
5532 pairslist1 = list(pairslist)
5546 pairslist1.append((0,1))
5533 pairslist1.append((0,1))
5547 pairslist1.append((3,4))
5534 pairslist1.append((3,4))
5548 numPairs = len(pairslist1)
5535 numPairs = len(pairslist1)
5549 #Time Lag
5536 #Time Lag
5550 timeLag = 45*10**-3
5537 timeLag = 45*10**-3
5551 c = 3e8
5538 c = 3e8
5552 lag = numpy.ceil(timeLag/timeInterval)
5539 lag = numpy.ceil(timeLag/timeInterval)
5553 freq = 30e6
5540 freq = 30e6
5554
5541
5555 listMeteors1 = []
5542 listMeteors1 = []
5556
5543
5557 for i in range(len(listMeteors)):
5544 for i in range(len(listMeteors)):
5558 meteorAux = listMeteors[i]
5545 meteorAux = listMeteors[i]
5559 if meteorAux[-1] == 0:
5546 if meteorAux[-1] == 0:
5560 mStart = listMeteors[i][1]
5547 mStart = listMeteors[i][1]
5561 mPeak = listMeteors[i][2]
5548 mPeak = listMeteors[i][2]
5562 mLag = mPeak - mStart + lag
5549 mLag = mPeak - mStart + lag
5563
5550
5564 #get the volt data between the start and end times of the meteor
5551 #get the volt data between the start and end times of the meteor
5565 meteorVolts = listVolts[i]
5552 meteorVolts = listVolts[i]
5566 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5553 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5567
5554
5568 #Get CCF
5555 #Get CCF
5569 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
5556 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
5570
5557
5571 #Method 2
5558 #Method 2
5572 slopes = numpy.zeros(numPairs)
5559 slopes = numpy.zeros(numPairs)
5573 time = numpy.array([-2,-1,1,2])*timeInterval
5560 time = numpy.array([-2,-1,1,2])*timeInterval
5574 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
5561 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
5575
5562
5576 #Correct phases
5563 #Correct phases
5577 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
5564 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
5578 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5565 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5579
5566
5580 if indDer[0].shape[0] > 0:
5567 if indDer[0].shape[0] > 0:
5581 for i in range(indDer[0].shape[0]):
5568 for i in range(indDer[0].shape[0]):
5582 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
5569 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
5583 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
5570 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
5584
5571
5585 for j in range(numPairs):
5572 for j in range(numPairs):
5586 fit = stats.linregress(time, angAllCCF[j,:])
5573 fit = stats.linregress(time, angAllCCF[j,:])
5587 slopes[j] = fit[0]
5574 slopes[j] = fit[0]
5588
5575
5589 #Remove Outlier
5576 #Remove Outlier
5590 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
5577 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
5591 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
5578 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
5592 meteorAux[-2] = radialError
5579 meteorAux[-2] = radialError
5593 meteorAux[-3] = radialVelocity
5580 meteorAux[-3] = radialVelocity
5594
5581
5595 #Setting Error
5582 #Setting Error
5596 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
5583 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
5597 if numpy.abs(radialVelocity) > 200:
5584 if numpy.abs(radialVelocity) > 200:
5598 meteorAux[-1] = 15
5585 meteorAux[-1] = 15
5599 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
5586 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
5600 elif radialError > radialStdThresh:
5587 elif radialError > radialStdThresh:
5601 meteorAux[-1] = 12
5588 meteorAux[-1] = 12
5602
5589
5603 listMeteors1.append(meteorAux)
5590 listMeteors1.append(meteorAux)
5604 return listMeteors1
5591 return listMeteors1
5605
5592
5606 def __setNewArrays(self, listMeteors, date, heiRang):
5593 def __setNewArrays(self, listMeteors, date, heiRang):
5607
5594
5608 #New arrays
5595 #New arrays
5609 arrayMeteors = numpy.array(listMeteors)
5596 arrayMeteors = numpy.array(listMeteors)
5610 arrayParameters = numpy.zeros((len(listMeteors), 13))
5597 arrayParameters = numpy.zeros((len(listMeteors), 13))
5611
5598
5612 #Date inclusion
5599 #Date inclusion
5613 arrayDate = numpy.tile(date, (len(listMeteors)))
5600 arrayDate = numpy.tile(date, (len(listMeteors)))
5614
5601
5615 #Meteor array
5602 #Meteor array
5616 #Parameters Array
5603 #Parameters Array
5617 arrayParameters[:,0] = arrayDate #Date
5604 arrayParameters[:,0] = arrayDate #Date
5618 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
5605 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
5619 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
5606 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
5620 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
5607 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
5621 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
5608 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
5622
5609
5623
5610
5624 return arrayParameters
5611 return arrayParameters
5625
5612
5626 class CorrectSMPhases(Operation):
5613 class CorrectSMPhases(Operation):
5627
5614
5628 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
5615 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
5629
5616
5630 arrayParameters = dataOut.data_param
5617 arrayParameters = dataOut.data_param
5631 pairsList = []
5618 pairsList = []
5632 pairx = (0,1)
5619 pairx = (0,1)
5633 pairy = (2,3)
5620 pairy = (2,3)
5634 pairsList.append(pairx)
5621 pairsList.append(pairx)
5635 pairsList.append(pairy)
5622 pairsList.append(pairy)
5636 jph = numpy.zeros(4)
5623 jph = numpy.zeros(4)
5637
5624
5638 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5625 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5639 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5626 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5640 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
5627 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
5641
5628
5642 meteorOps = SMOperations()
5629 meteorOps = SMOperations()
5643 if channelPositions is None:
5630 if channelPositions is None:
5644 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5631 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5645 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5632 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5646
5633
5647 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5634 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5648 h = (hmin,hmax)
5635 h = (hmin,hmax)
5649
5636
5650 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5637 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5651
5638
5652 dataOut.data_param = arrayParameters
5639 dataOut.data_param = arrayParameters
5653 return
5640 return
5654
5641
5655 class SMPhaseCalibration(Operation):
5642 class SMPhaseCalibration(Operation):
5656
5643
5657 __buffer = None
5644 __buffer = None
5658
5645
5659 __initime = None
5646 __initime = None
5660
5647
5661 __dataReady = False
5648 __dataReady = False
5662
5649
5663 __isConfig = False
5650 __isConfig = False
5664
5651
5665 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
5652 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
5666
5653
5667 dataTime = currentTime + paramInterval
5654 dataTime = currentTime + paramInterval
5668 deltaTime = dataTime - initTime
5655 deltaTime = dataTime - initTime
5669
5656
5670 if deltaTime >= outputInterval or deltaTime < 0:
5657 if deltaTime >= outputInterval or deltaTime < 0:
5671 return True
5658 return True
5672
5659
5673 return False
5660 return False
5674
5661
5675 def __getGammas(self, pairs, d, phases):
5662 def __getGammas(self, pairs, d, phases):
5676 gammas = numpy.zeros(2)
5663 gammas = numpy.zeros(2)
5677
5664
5678 for i in range(len(pairs)):
5665 for i in range(len(pairs)):
5679
5666
5680 pairi = pairs[i]
5667 pairi = pairs[i]
5681
5668
5682 phip3 = phases[:,pairi[0]]
5669 phip3 = phases[:,pairi[0]]
5683 d3 = d[pairi[0]]
5670 d3 = d[pairi[0]]
5684 phip2 = phases[:,pairi[1]]
5671 phip2 = phases[:,pairi[1]]
5685 d2 = d[pairi[1]]
5672 d2 = d[pairi[1]]
5686 #Calculating gamma
5673 #Calculating gamma
5687 jgamma = -phip2*d3/d2 - phip3
5674 jgamma = -phip2*d3/d2 - phip3
5688 jgamma = numpy.angle(numpy.exp(1j*jgamma))
5675 jgamma = numpy.angle(numpy.exp(1j*jgamma))
5689
5676
5690 #Revised distribution
5677 #Revised distribution
5691 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
5678 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
5692
5679
5693 #Histogram
5680 #Histogram
5694 nBins = 64
5681 nBins = 64
5695 rmin = -0.5*numpy.pi
5682 rmin = -0.5*numpy.pi
5696 rmax = 0.5*numpy.pi
5683 rmax = 0.5*numpy.pi
5697 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
5684 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
5698
5685
5699 meteorsY = phaseHisto[0]
5686 meteorsY = phaseHisto[0]
5700 phasesX = phaseHisto[1][:-1]
5687 phasesX = phaseHisto[1][:-1]
5701 width = phasesX[1] - phasesX[0]
5688 width = phasesX[1] - phasesX[0]
5702 phasesX += width/2
5689 phasesX += width/2
5703
5690
5704 #Gaussian aproximation
5691 #Gaussian aproximation
5705 bpeak = meteorsY.argmax()
5692 bpeak = meteorsY.argmax()
5706 peak = meteorsY.max()
5693 peak = meteorsY.max()
5707 jmin = bpeak - 5
5694 jmin = bpeak - 5
5708 jmax = bpeak + 5 + 1
5695 jmax = bpeak + 5 + 1
5709
5696
5710 if jmin<0:
5697 if jmin<0:
5711 jmin = 0
5698 jmin = 0
5712 jmax = 6
5699 jmax = 6
5713 elif jmax > meteorsY.size:
5700 elif jmax > meteorsY.size:
5714 jmin = meteorsY.size - 6
5701 jmin = meteorsY.size - 6
5715 jmax = meteorsY.size
5702 jmax = meteorsY.size
5716
5703
5717 x0 = numpy.array([peak,bpeak,50])
5704 x0 = numpy.array([peak,bpeak,50])
5718 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
5705 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
5719
5706
5720 #Gammas
5707 #Gammas
5721 gammas[i] = coeff[0][1]
5708 gammas[i] = coeff[0][1]
5722
5709
5723 return gammas
5710 return gammas
5724
5711
5725 def __residualFunction(self, coeffs, y, t):
5712 def __residualFunction(self, coeffs, y, t):
5726
5713
5727 return y - self.__gauss_function(t, coeffs)
5714 return y - self.__gauss_function(t, coeffs)
5728
5715
5729 def __gauss_function(self, t, coeffs):
5716 def __gauss_function(self, t, coeffs):
5730
5717
5731 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
5718 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
5732
5719
5733 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
5720 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
5734 meteorOps = SMOperations()
5721 meteorOps = SMOperations()
5735 nchan = 4
5722 nchan = 4
5736 pairx = pairsList[0] #x es 0
5723 pairx = pairsList[0] #x es 0
5737 pairy = pairsList[1] #y es 1
5724 pairy = pairsList[1] #y es 1
5738 center_xangle = 0
5725 center_xangle = 0
5739 center_yangle = 0
5726 center_yangle = 0
5740 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
5727 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
5741 ntimes = len(range_angle)
5728 ntimes = len(range_angle)
5742
5729
5743 nstepsx = 20
5730 nstepsx = 20
5744 nstepsy = 20
5731 nstepsy = 20
5745
5732
5746 for iz in range(ntimes):
5733 for iz in range(ntimes):
5747 min_xangle = -range_angle[iz]/2 + center_xangle
5734 min_xangle = -range_angle[iz]/2 + center_xangle
5748 max_xangle = range_angle[iz]/2 + center_xangle
5735 max_xangle = range_angle[iz]/2 + center_xangle
5749 min_yangle = -range_angle[iz]/2 + center_yangle
5736 min_yangle = -range_angle[iz]/2 + center_yangle
5750 max_yangle = range_angle[iz]/2 + center_yangle
5737 max_yangle = range_angle[iz]/2 + center_yangle
5751
5738
5752 inc_x = (max_xangle-min_xangle)/nstepsx
5739 inc_x = (max_xangle-min_xangle)/nstepsx
5753 inc_y = (max_yangle-min_yangle)/nstepsy
5740 inc_y = (max_yangle-min_yangle)/nstepsy
5754
5741
5755 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
5742 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
5756 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
5743 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
5757 penalty = numpy.zeros((nstepsx,nstepsy))
5744 penalty = numpy.zeros((nstepsx,nstepsy))
5758 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
5745 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
5759 jph = numpy.zeros(nchan)
5746 jph = numpy.zeros(nchan)
5760
5747
5761 # Iterations looking for the offset
5748 # Iterations looking for the offset
5762 for iy in range(int(nstepsy)):
5749 for iy in range(int(nstepsy)):
5763 for ix in range(int(nstepsx)):
5750 for ix in range(int(nstepsx)):
5764 d3 = d[pairsList[1][0]]
5751 d3 = d[pairsList[1][0]]
5765 d2 = d[pairsList[1][1]]
5752 d2 = d[pairsList[1][1]]
5766 d5 = d[pairsList[0][0]]
5753 d5 = d[pairsList[0][0]]
5767 d4 = d[pairsList[0][1]]
5754 d4 = d[pairsList[0][1]]
5768
5755
5769 alp2 = alpha_y[iy] #gamma 1
5756 alp2 = alpha_y[iy] #gamma 1
5770 alp4 = alpha_x[ix] #gamma 0
5757 alp4 = alpha_x[ix] #gamma 0
5771
5758
5772 alp3 = -alp2*d3/d2 - gammas[1]
5759 alp3 = -alp2*d3/d2 - gammas[1]
5773 alp5 = -alp4*d5/d4 - gammas[0]
5760 alp5 = -alp4*d5/d4 - gammas[0]
5774 jph[pairsList[0][1]] = alp4
5761 jph[pairsList[0][1]] = alp4
5775 jph[pairsList[0][0]] = alp5
5762 jph[pairsList[0][0]] = alp5
5776 jph[pairsList[1][0]] = alp3
5763 jph[pairsList[1][0]] = alp3
5777 jph[pairsList[1][1]] = alp2
5764 jph[pairsList[1][1]] = alp2
5778 jph_array[:,ix,iy] = jph
5765 jph_array[:,ix,iy] = jph
5779 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
5766 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
5780 error = meteorsArray1[:,-1]
5767 error = meteorsArray1[:,-1]
5781 ind1 = numpy.where(error==0)[0]
5768 ind1 = numpy.where(error==0)[0]
5782 penalty[ix,iy] = ind1.size
5769 penalty[ix,iy] = ind1.size
5783
5770
5784 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
5771 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
5785 phOffset = jph_array[:,i,j]
5772 phOffset = jph_array[:,i,j]
5786
5773
5787 center_xangle = phOffset[pairx[1]]
5774 center_xangle = phOffset[pairx[1]]
5788 center_yangle = phOffset[pairy[1]]
5775 center_yangle = phOffset[pairy[1]]
5789
5776
5790 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
5777 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
5791 phOffset = phOffset*180/numpy.pi
5778 phOffset = phOffset*180/numpy.pi
5792 return phOffset
5779 return phOffset
5793
5780
5794
5781
5795 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
5782 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
5796
5783
5797 dataOut.flagNoData = True
5784 dataOut.flagNoData = True
5798 self.__dataReady = False
5785 self.__dataReady = False
5799 dataOut.outputInterval = nHours*3600
5786 dataOut.outputInterval = nHours*3600
5800
5787
5801 if self.__isConfig == False:
5788 if self.__isConfig == False:
5802 #Get Initial LTC time
5789 #Get Initial LTC time
5803 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
5790 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
5804 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
5791 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
5805
5792
5806 self.__isConfig = True
5793 self.__isConfig = True
5807
5794
5808 if self.__buffer is None:
5795 if self.__buffer is None:
5809 self.__buffer = dataOut.data_param.copy()
5796 self.__buffer = dataOut.data_param.copy()
5810
5797
5811 else:
5798 else:
5812 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5799 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5813
5800
5814 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5801 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5815
5802
5816 if self.__dataReady:
5803 if self.__dataReady:
5817 dataOut.utctimeInit = self.__initime
5804 dataOut.utctimeInit = self.__initime
5818 self.__initime += dataOut.outputInterval #to erase time offset
5805 self.__initime += dataOut.outputInterval #to erase time offset
5819
5806
5820 freq = dataOut.frequency
5807 freq = dataOut.frequency
5821 c = dataOut.C #m/s
5808 c = dataOut.C #m/s
5822 lamb = c/freq
5809 lamb = c/freq
5823 k = 2*numpy.pi/lamb
5810 k = 2*numpy.pi/lamb
5824 azimuth = 0
5811 azimuth = 0
5825 h = (hmin, hmax)
5812 h = (hmin, hmax)
5826
5813
5827 if channelPositions is None:
5814 if channelPositions is None:
5828 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5815 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5829 meteorOps = SMOperations()
5816 meteorOps = SMOperations()
5830 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5817 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5831
5818
5832 #Checking correct order of pairs
5819 #Checking correct order of pairs
5833 pairs = []
5820 pairs = []
5834 if distances[1] > distances[0]:
5821 if distances[1] > distances[0]:
5835 pairs.append((1,0))
5822 pairs.append((1,0))
5836 else:
5823 else:
5837 pairs.append((0,1))
5824 pairs.append((0,1))
5838
5825
5839 if distances[3] > distances[2]:
5826 if distances[3] > distances[2]:
5840 pairs.append((3,2))
5827 pairs.append((3,2))
5841 else:
5828 else:
5842 pairs.append((2,3))
5829 pairs.append((2,3))
5843
5830
5844 meteorsArray = self.__buffer
5831 meteorsArray = self.__buffer
5845 error = meteorsArray[:,-1]
5832 error = meteorsArray[:,-1]
5846 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5833 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5847 ind1 = numpy.where(boolError)[0]
5834 ind1 = numpy.where(boolError)[0]
5848 meteorsArray = meteorsArray[ind1,:]
5835 meteorsArray = meteorsArray[ind1,:]
5849 meteorsArray[:,-1] = 0
5836 meteorsArray[:,-1] = 0
5850 phases = meteorsArray[:,8:12]
5837 phases = meteorsArray[:,8:12]
5851
5838
5852 #Calculate Gammas
5839 #Calculate Gammas
5853 gammas = self.__getGammas(pairs, distances, phases)
5840 gammas = self.__getGammas(pairs, distances, phases)
5854 #Calculate Phases
5841 #Calculate Phases
5855 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5842 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5856 phasesOff = phasesOff.reshape((1,phasesOff.size))
5843 phasesOff = phasesOff.reshape((1,phasesOff.size))
5857 dataOut.data_output = -phasesOff
5844 dataOut.data_output = -phasesOff
5858 dataOut.flagNoData = False
5845 dataOut.flagNoData = False
5859 self.__buffer = None
5846 self.__buffer = None
5860
5847
5861
5848
5862 return
5849 return
5863
5850
5864 class SMOperations():
5851 class SMOperations():
5865
5852
5866 def __init__(self):
5853 def __init__(self):
5867
5854
5868 return
5855 return
5869
5856
5870 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5857 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5871
5858
5872 arrayParameters = arrayParameters0.copy()
5859 arrayParameters = arrayParameters0.copy()
5873 hmin = h[0]
5860 hmin = h[0]
5874 hmax = h[1]
5861 hmax = h[1]
5875
5862
5876 #Calculate AOA (Error N 3, 4)
5863 #Calculate AOA (Error N 3, 4)
5877 #JONES ET AL. 1998
5864 #JONES ET AL. 1998
5878 AOAthresh = numpy.pi/8
5865 AOAthresh = numpy.pi/8
5879 error = arrayParameters[:,-1]
5866 error = arrayParameters[:,-1]
5880 phases = -arrayParameters[:,8:12] + jph
5867 phases = -arrayParameters[:,8:12] + jph
5881 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5868 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5882
5869
5883 #Calculate Heights (Error N 13 and 14)
5870 #Calculate Heights (Error N 13 and 14)
5884 error = arrayParameters[:,-1]
5871 error = arrayParameters[:,-1]
5885 Ranges = arrayParameters[:,1]
5872 Ranges = arrayParameters[:,1]
5886 zenith = arrayParameters[:,4]
5873 zenith = arrayParameters[:,4]
5887 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5874 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5888
5875
5889 #----------------------- Get Final data ------------------------------------
5876 #----------------------- Get Final data ------------------------------------
5890
5877
5891 return arrayParameters
5878 return arrayParameters
5892
5879
5893 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5880 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5894
5881
5895 arrayAOA = numpy.zeros((phases.shape[0],3))
5882 arrayAOA = numpy.zeros((phases.shape[0],3))
5896 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5883 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5897
5884
5898 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5885 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5899 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5886 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5900 arrayAOA[:,2] = cosDirError
5887 arrayAOA[:,2] = cosDirError
5901
5888
5902 azimuthAngle = arrayAOA[:,0]
5889 azimuthAngle = arrayAOA[:,0]
5903 zenithAngle = arrayAOA[:,1]
5890 zenithAngle = arrayAOA[:,1]
5904
5891
5905 #Setting Error
5892 #Setting Error
5906 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5893 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5907 error[indError] = 0
5894 error[indError] = 0
5908 #Number 3: AOA not fesible
5895 #Number 3: AOA not fesible
5909 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5896 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5910 error[indInvalid] = 3
5897 error[indInvalid] = 3
5911 #Number 4: Large difference in AOAs obtained from different antenna baselines
5898 #Number 4: Large difference in AOAs obtained from different antenna baselines
5912 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5899 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5913 error[indInvalid] = 4
5900 error[indInvalid] = 4
5914 return arrayAOA, error
5901 return arrayAOA, error
5915
5902
5916 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5903 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5917
5904
5918 #Initializing some variables
5905 #Initializing some variables
5919 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5906 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5920 ang_aux = ang_aux.reshape(1,ang_aux.size)
5907 ang_aux = ang_aux.reshape(1,ang_aux.size)
5921
5908
5922 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5909 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5923 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5910 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5924
5911
5925
5912
5926 for i in range(2):
5913 for i in range(2):
5927 ph0 = arrayPhase[:,pairsList[i][0]]
5914 ph0 = arrayPhase[:,pairsList[i][0]]
5928 ph1 = arrayPhase[:,pairsList[i][1]]
5915 ph1 = arrayPhase[:,pairsList[i][1]]
5929 d0 = distances[pairsList[i][0]]
5916 d0 = distances[pairsList[i][0]]
5930 d1 = distances[pairsList[i][1]]
5917 d1 = distances[pairsList[i][1]]
5931
5918
5932 ph0_aux = ph0 + ph1
5919 ph0_aux = ph0 + ph1
5933 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5920 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5934 #First Estimation
5921 #First Estimation
5935 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5922 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5936
5923
5937 #Most-Accurate Second Estimation
5924 #Most-Accurate Second Estimation
5938 phi1_aux = ph0 - ph1
5925 phi1_aux = ph0 - ph1
5939 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5926 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5940 #Direction Cosine 1
5927 #Direction Cosine 1
5941 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5928 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5942
5929
5943 #Searching the correct Direction Cosine
5930 #Searching the correct Direction Cosine
5944 cosdir0_aux = cosdir0[:,i]
5931 cosdir0_aux = cosdir0[:,i]
5945 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5932 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5946 #Minimum Distance
5933 #Minimum Distance
5947 cosDiff = (cosdir1 - cosdir0_aux)**2
5934 cosDiff = (cosdir1 - cosdir0_aux)**2
5948 indcos = cosDiff.argmin(axis = 1)
5935 indcos = cosDiff.argmin(axis = 1)
5949 #Saving Value obtained
5936 #Saving Value obtained
5950 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5937 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5951
5938
5952 return cosdir0, cosdir
5939 return cosdir0, cosdir
5953
5940
5954 def __calculateAOA(self, cosdir, azimuth):
5941 def __calculateAOA(self, cosdir, azimuth):
5955 cosdirX = cosdir[:,0]
5942 cosdirX = cosdir[:,0]
5956 cosdirY = cosdir[:,1]
5943 cosdirY = cosdir[:,1]
5957
5944
5958 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5945 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5959 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5946 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5960 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5947 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5961
5948
5962 return angles
5949 return angles
5963
5950
5964 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5951 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5965
5952
5966 Ramb = 375 #Ramb = c/(2*PRF)
5953 Ramb = 375 #Ramb = c/(2*PRF)
5967 Re = 6371 #Earth Radius
5954 Re = 6371 #Earth Radius
5968 heights = numpy.zeros(Ranges.shape)
5955 heights = numpy.zeros(Ranges.shape)
5969
5956
5970 R_aux = numpy.array([0,1,2])*Ramb
5957 R_aux = numpy.array([0,1,2])*Ramb
5971 R_aux = R_aux.reshape(1,R_aux.size)
5958 R_aux = R_aux.reshape(1,R_aux.size)
5972
5959
5973 Ranges = Ranges.reshape(Ranges.size,1)
5960 Ranges = Ranges.reshape(Ranges.size,1)
5974
5961
5975 Ri = Ranges + R_aux
5962 Ri = Ranges + R_aux
5976 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5963 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5977
5964
5978 #Check if there is a height between 70 and 110 km
5965 #Check if there is a height between 70 and 110 km
5979 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5966 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5980 ind_h = numpy.where(h_bool == 1)[0]
5967 ind_h = numpy.where(h_bool == 1)[0]
5981
5968
5982 hCorr = hi[ind_h, :]
5969 hCorr = hi[ind_h, :]
5983 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5970 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5984
5971
5985 hCorr = hi[ind_hCorr][:len(ind_h)]
5972 hCorr = hi[ind_hCorr][:len(ind_h)]
5986 heights[ind_h] = hCorr
5973 heights[ind_h] = hCorr
5987
5974
5988 #Setting Error
5975 #Setting Error
5989 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5976 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5990 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5977 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5991 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5978 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5992 error[indError] = 0
5979 error[indError] = 0
5993 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5980 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5994 error[indInvalid2] = 14
5981 error[indInvalid2] = 14
5995 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5982 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5996 error[indInvalid1] = 13
5983 error[indInvalid1] = 13
5997
5984
5998 return heights, error
5985 return heights, error
5999
5986
6000 def getPhasePairs(self, channelPositions):
5987 def getPhasePairs(self, channelPositions):
6001 chanPos = numpy.array(channelPositions)
5988 chanPos = numpy.array(channelPositions)
6002 listOper = list(itertools.combinations(list(range(5)),2))
5989 listOper = list(itertools.combinations(list(range(5)),2))
6003
5990
6004 distances = numpy.zeros(4)
5991 distances = numpy.zeros(4)
6005 axisX = []
5992 axisX = []
6006 axisY = []
5993 axisY = []
6007 distX = numpy.zeros(3)
5994 distX = numpy.zeros(3)
6008 distY = numpy.zeros(3)
5995 distY = numpy.zeros(3)
6009 ix = 0
5996 ix = 0
6010 iy = 0
5997 iy = 0
6011
5998
6012 pairX = numpy.zeros((2,2))
5999 pairX = numpy.zeros((2,2))
6013 pairY = numpy.zeros((2,2))
6000 pairY = numpy.zeros((2,2))
6014
6001
6015 for i in range(len(listOper)):
6002 for i in range(len(listOper)):
6016 pairi = listOper[i]
6003 pairi = listOper[i]
6017
6004
6018 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
6005 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
6019
6006
6020 if posDif[0] == 0:
6007 if posDif[0] == 0:
6021 axisY.append(pairi)
6008 axisY.append(pairi)
6022 distY[iy] = posDif[1]
6009 distY[iy] = posDif[1]
6023 iy += 1
6010 iy += 1
6024 elif posDif[1] == 0:
6011 elif posDif[1] == 0:
6025 axisX.append(pairi)
6012 axisX.append(pairi)
6026 distX[ix] = posDif[0]
6013 distX[ix] = posDif[0]
6027 ix += 1
6014 ix += 1
6028
6015
6029 for i in range(2):
6016 for i in range(2):
6030 if i==0:
6017 if i==0:
6031 dist0 = distX
6018 dist0 = distX
6032 axis0 = axisX
6019 axis0 = axisX
6033 else:
6020 else:
6034 dist0 = distY
6021 dist0 = distY
6035 axis0 = axisY
6022 axis0 = axisY
6036
6023
6037 side = numpy.argsort(dist0)[:-1]
6024 side = numpy.argsort(dist0)[:-1]
6038 axis0 = numpy.array(axis0)[side,:]
6025 axis0 = numpy.array(axis0)[side,:]
6039 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
6026 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
6040 axis1 = numpy.unique(numpy.reshape(axis0,4))
6027 axis1 = numpy.unique(numpy.reshape(axis0,4))
6041 side = axis1[axis1 != chanC]
6028 side = axis1[axis1 != chanC]
6042 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
6029 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
6043 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
6030 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
6044 if diff1<0:
6031 if diff1<0:
6045 chan2 = side[0]
6032 chan2 = side[0]
6046 d2 = numpy.abs(diff1)
6033 d2 = numpy.abs(diff1)
6047 chan1 = side[1]
6034 chan1 = side[1]
6048 d1 = numpy.abs(diff2)
6035 d1 = numpy.abs(diff2)
6049 else:
6036 else:
6050 chan2 = side[1]
6037 chan2 = side[1]
6051 d2 = numpy.abs(diff2)
6038 d2 = numpy.abs(diff2)
6052 chan1 = side[0]
6039 chan1 = side[0]
6053 d1 = numpy.abs(diff1)
6040 d1 = numpy.abs(diff1)
6054
6041
6055 if i==0:
6042 if i==0:
6056 chanCX = chanC
6043 chanCX = chanC
6057 chan1X = chan1
6044 chan1X = chan1
6058 chan2X = chan2
6045 chan2X = chan2
6059 distances[0:2] = numpy.array([d1,d2])
6046 distances[0:2] = numpy.array([d1,d2])
6060 else:
6047 else:
6061 chanCY = chanC
6048 chanCY = chanC
6062 chan1Y = chan1
6049 chan1Y = chan1
6063 chan2Y = chan2
6050 chan2Y = chan2
6064 distances[2:4] = numpy.array([d1,d2])
6051 distances[2:4] = numpy.array([d1,d2])
6065
6052
6066 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
6053 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
6067
6054
6068 return pairslist, distances
6055 return pairslist, distances
6069
6056
6070 class IGRFModel(Operation):
6057 class IGRFModel(Operation):
6071 """Operation to calculate Geomagnetic parameters.
6058 """Operation to calculate Geomagnetic parameters.
6072
6059
6073 Parameters:
6060 Parameters:
6074 -----------
6061 -----------
6075 None
6062 None
6076
6063
6077 Example
6064 Example
6078 --------
6065 --------
6079
6066
6080 op = proc_unit.addOperation(name='IGRFModel', optype='other')
6067 op = proc_unit.addOperation(name='IGRFModel', optype='other')
6081
6068
6082 """
6069 """
6083
6070
6084 def __init__(self, **kwargs):
6071 def __init__(self, **kwargs):
6085
6072
6086 Operation.__init__(self, **kwargs)
6073 Operation.__init__(self, **kwargs)
6087
6074
6088 self.aux=1
6075 self.aux=1
6089
6076
6090 def run(self,dataOut):
6077 def run(self,dataOut):
6091
6078
6092 try:
6079 try:
6093 from schainpy.model.proc import mkfact_short_2020
6080 from schainpy.model.proc import mkfact_short_2020
6094 except:
6081 except:
6095 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
6082 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
6096
6083
6097 if self.aux==1:
6084 if self.aux==1:
6098
6085
6099 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
6086 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
6100 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
6087 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
6101 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
6088 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
6102 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
6089 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
6103 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
6090 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
6104 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
6091 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
6105
6092
6106 self.aux=0
6093 self.aux=0
6107
6094
6108 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
6095 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
6109 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6096 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6110 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
6097 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
6111 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6098 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6112 dataOut.thb=numpy.array(dataOut.thb,order='F')
6099 dataOut.thb=numpy.array(dataOut.thb,order='F')
6113 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6100 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6114 dataOut.bki=numpy.array(dataOut.bki,order='F')
6101 dataOut.bki=numpy.array(dataOut.bki,order='F')
6115
6102
6116 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
6103 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
6117
6104
6118 return dataOut
6105 return dataOut
6119
6106
6120 class MergeProc(ProcessingUnit):
6107 class MergeProc(ProcessingUnit):
6121
6108
6122 def __init__(self):
6109 def __init__(self):
6123 ProcessingUnit.__init__(self)
6110 ProcessingUnit.__init__(self)
6124
6111
6125 def run(self, attr_data, attr_data_2 = None, attr_data_3 = None, attr_data_4 = None, attr_data_5 = None, mode=0):
6112 def run(self, attr_data, attr_data_2 = None, attr_data_3 = None, attr_data_4 = None, attr_data_5 = None, mode=0):
6126
6113
6127 self.dataOut = getattr(self, self.inputs[0])
6114 self.dataOut = getattr(self, self.inputs[0])
6128 data_inputs = [getattr(self, attr) for attr in self.inputs]
6115 data_inputs = [getattr(self, attr) for attr in self.inputs]
6129 #print(self.inputs)
6116 #print(self.inputs)
6130 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
6117 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
6131 #exit(1)
6118 #exit(1)
6132 if mode==0:
6119 if mode==0:
6133 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6120 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6134 setattr(self.dataOut, attr_data, data)
6121 setattr(self.dataOut, attr_data, data)
6135
6122
6136 if mode==1: #Hybrid
6123 if mode==1: #Hybrid
6137 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6124 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6138 #setattr(self.dataOut, attr_data, data)
6125 #setattr(self.dataOut, attr_data, data)
6139 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
6126 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
6140 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
6127 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
6141 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6128 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6142 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6129 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6143 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6130 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6144 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6131 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6145 '''
6132 '''
6146 print(self.dataOut.dataLag_spc_LP.shape)
6133 print(self.dataOut.dataLag_spc_LP.shape)
6147 print(self.dataOut.dataLag_cspc_LP.shape)
6134 print(self.dataOut.dataLag_cspc_LP.shape)
6148 exit(1)
6135 exit(1)
6149 '''
6136 '''
6150
6137
6151 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6138 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6152 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6139 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6153 '''
6140 '''
6154 print("Merge")
6141 print("Merge")
6155 print(numpy.shape(self.dataOut.dataLag_spc))
6142 print(numpy.shape(self.dataOut.dataLag_spc))
6156 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6143 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6157 print(numpy.shape(self.dataOut.dataLag_cspc))
6144 print(numpy.shape(self.dataOut.dataLag_cspc))
6158 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6145 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6159 exit(1)
6146 exit(1)
6160 '''
6147 '''
6161 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6148 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6162 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6149 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6163 #exit(1)
6150 #exit(1)
6164 #print(self.dataOut.NDP)
6151 #print(self.dataOut.NDP)
6165 #print(self.dataOut.nNoiseProfiles)
6152 #print(self.dataOut.nNoiseProfiles)
6166
6153
6167 #self.dataOut.nIncohInt_LP = 128
6154 #self.dataOut.nIncohInt_LP = 128
6168 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6155 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6169 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
6156 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
6170 self.dataOut.NLAG = 16
6157 self.dataOut.NLAG = 16
6171 self.dataOut.NRANGE = 200
6158 self.dataOut.NRANGE = 200
6172 self.dataOut.NSCAN = 128
6159 self.dataOut.NSCAN = 128
6173 #print(numpy.shape(self.dataOut.data_spc))
6160 #print(numpy.shape(self.dataOut.data_spc))
6174
6161
6175 #exit(1)
6162 #exit(1)
6176
6163
6177 if mode==2: #HAE 2022
6164 if mode==2: #HAE 2022
6178 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
6165 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
6179 setattr(self.dataOut, attr_data, data)
6166 setattr(self.dataOut, attr_data, data)
6180
6167
6181 self.dataOut.nIncohInt *= 2
6168 self.dataOut.nIncohInt *= 2
6182 #meta = self.dataOut.getFreqRange(1)/1000.
6169 #meta = self.dataOut.getFreqRange(1)/1000.
6183 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
6170 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
6184
6171
6185 #exit(1)
6172 #exit(1)
6186
6173
6187 if mode==4: #Hybrid LP-SSheightProfiles
6174 if mode==4: #Hybrid LP-SSheightProfiles
6188 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6175 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6189 #setattr(self.dataOut, attr_data, data)
6176 #setattr(self.dataOut, attr_data, data)
6190 setattr(self.dataOut, 'dataLag_spc', getattr(data_inputs[0], attr_data)) #DP
6177 setattr(self.dataOut, 'dataLag_spc', getattr(data_inputs[0], attr_data)) #DP
6191 setattr(self.dataOut, 'dataLag_cspc', getattr(data_inputs[0], attr_data_2)) #DP
6178 setattr(self.dataOut, 'dataLag_cspc', getattr(data_inputs[0], attr_data_2)) #DP
6192 setattr(self.dataOut, 'dataLag_spc_LP', getattr(data_inputs[1], attr_data_3)) #LP
6179 setattr(self.dataOut, 'dataLag_spc_LP', getattr(data_inputs[1], attr_data_3)) #LP
6193 #setattr(self.dataOut, 'dataLag_cspc_LP', getattr(data_inputs[1], attr_data_4)) #LP
6180 #setattr(self.dataOut, 'dataLag_cspc_LP', getattr(data_inputs[1], attr_data_4)) #LP
6194 #setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6181 #setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6195 setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6182 setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6196 #print("Merge data_acf: ",self.dataOut.data_acf.shape)
6183 #print("Merge data_acf: ",self.dataOut.data_acf.shape)
6197 #exit(1)
6184 #exit(1)
6198 #print(self.dataOut.data_spc_LP.shape)
6185 #print(self.dataOut.data_spc_LP.shape)
6199 #print("Exit")
6186 #print("Exit")
6200 #exit(1)
6187 #exit(1)
6201 #setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6188 #setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6202 #setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6189 #setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6203 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6190 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6204 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6191 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6205 '''
6192 '''
6206 print(self.dataOut.dataLag_spc_LP.shape)
6193 print(self.dataOut.dataLag_spc_LP.shape)
6207 print(self.dataOut.dataLag_cspc_LP.shape)
6194 print(self.dataOut.dataLag_cspc_LP.shape)
6208 exit(1)
6195 exit(1)
6209 '''
6196 '''
6210 '''
6197 '''
6211 print(self.dataOut.dataLag_spc_LP[0,:,100])
6198 print(self.dataOut.dataLag_spc_LP[0,:,100])
6212 print(self.dataOut.dataLag_spc_LP[1,:,100])
6199 print(self.dataOut.dataLag_spc_LP[1,:,100])
6213 exit(1)
6200 exit(1)
6214 '''
6201 '''
6215 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6202 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6216 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6203 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6217 '''
6204 '''
6218 print("Merge")
6205 print("Merge")
6219 print(numpy.shape(self.dataOut.dataLag_spc))
6206 print(numpy.shape(self.dataOut.dataLag_spc))
6220 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6207 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6221 print(numpy.shape(self.dataOut.dataLag_cspc))
6208 print(numpy.shape(self.dataOut.dataLag_cspc))
6222 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6209 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6223 exit(1)
6210 exit(1)
6224 '''
6211 '''
6225 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6212 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6226 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6213 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6227 #exit(1)
6214 #exit(1)
6228 #print(self.dataOut.NDP)
6215 #print(self.dataOut.NDP)
6229 #print(self.dataOut.nNoiseProfiles)
6216 #print(self.dataOut.nNoiseProfiles)
6230
6217
6231 #self.dataOut.nIncohInt_LP = 128
6218 #self.dataOut.nIncohInt_LP = 128
6232 #self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6219 #self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6233 self.dataOut.nProfiles_LP = 16#28#self.dataOut.nIncohInt_LP
6220 self.dataOut.nProfiles_LP = 16#28#self.dataOut.nIncohInt_LP
6234 self.dataOut.nProfiles_LP = self.dataOut.data_acf.shape[1]#28#self.dataOut.nIncohInt_LP
6221 self.dataOut.nProfiles_LP = self.dataOut.data_acf.shape[1]#28#self.dataOut.nIncohInt_LP
6235 self.dataOut.NSCAN = 128
6222 self.dataOut.NSCAN = 128
6236 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt*self.dataOut.NSCAN
6223 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt*self.dataOut.NSCAN
6237 #print("sahpi",self.dataOut.nIncohInt_LP)
6224 #print("sahpi",self.dataOut.nIncohInt_LP)
6238 #exit(1)
6225 #exit(1)
6239 self.dataOut.NLAG = 16
6226 self.dataOut.NLAG = 16
6240 self.dataOut.NRANGE = self.dataOut.data_acf.shape[-1]
6227 self.dataOut.NRANGE = self.dataOut.data_acf.shape[-1]
6241
6228
6242 #print(numpy.shape(self.dataOut.data_spc))
6229 #print(numpy.shape(self.dataOut.data_spc))
6243
6230
6244 #exit(1)
6231 #exit(1)
6245 if mode==5:
6232 if mode==5:
6246 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6233 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6247 setattr(self.dataOut, attr_data, data)
6234 setattr(self.dataOut, attr_data, data)
6248 data = numpy.concatenate([getattr(data, attr_data_2) for data in data_inputs])
6235 data = numpy.concatenate([getattr(data, attr_data_2) for data in data_inputs])
6249 setattr(self.dataOut, attr_data_2, data)
6236 setattr(self.dataOut, attr_data_2, data)
6250 #data = numpy.concatenate([getattr(data, attr_data_3) for data in data_inputs])
6237 #data = numpy.concatenate([getattr(data, attr_data_3) for data in data_inputs])
6251 #setattr(self.dataOut, attr_data_3, data)
6238 #setattr(self.dataOut, attr_data_3, data)
6252 #print(self.dataOut.moments.shape,self.dataOut.data_snr.shape,self.dataOut.heightList.shape) No newline at end of file
6239 #print(self.dataOut.moments.shape,self.dataOut.data_snr.shape,self.dataOut.heightList.shape)
General Comments 0
You need to be logged in to leave comments. Login now