##// END OF EJS Templates
Class to filter data by snr threshold. To calculate vertical and zonal velocities, vertical and zonal errors and SNR.
imanay -
r1662:30ff981335bb
parent child
Show More
@@ -1,5446 +1,5597
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 scipy import asarray as ar,exp
19 from scipy import asarray as ar,exp
20 from scipy.optimize import fmin, curve_fit
20 from scipy.optimize import fmin, curve_fit
21 from schainpy.utils import log
21 from schainpy.utils import log
22 import warnings
22 import warnings
23 from numpy import NaN
23 from numpy import NaN
24 from scipy.optimize.optimize import OptimizeWarning
24 from scipy.optimize.optimize import OptimizeWarning
25 warnings.filterwarnings('ignore')
25 warnings.filterwarnings('ignore')
26
26
27
27
28 SPEED_OF_LIGHT = 299792458
28 SPEED_OF_LIGHT = 299792458
29
29
30 '''solving pickling issue'''
30 '''solving pickling issue'''
31
31
32 def _pickle_method(method):
32 def _pickle_method(method):
33 func_name = method.__func__.__name__
33 func_name = method.__func__.__name__
34 obj = method.__self__
34 obj = method.__self__
35 cls = method.__self__.__class__
35 cls = method.__self__.__class__
36 return _unpickle_method, (func_name, obj, cls)
36 return _unpickle_method, (func_name, obj, cls)
37
37
38 def _unpickle_method(func_name, obj, cls):
38 def _unpickle_method(func_name, obj, cls):
39 for cls in cls.mro():
39 for cls in cls.mro():
40 try:
40 try:
41 func = cls.__dict__[func_name]
41 func = cls.__dict__[func_name]
42 except KeyError:
42 except KeyError:
43 pass
43 pass
44 else:
44 else:
45 break
45 break
46 return func.__get__(obj, cls)
46 return func.__get__(obj, cls)
47
47
48 # @MPDecorator
48 # @MPDecorator
49 class ParametersProc(ProcessingUnit):
49 class ParametersProc(ProcessingUnit):
50
50
51 METHODS = {}
51 METHODS = {}
52 nSeconds = None
52 nSeconds = None
53
53
54 def __init__(self):
54 def __init__(self):
55 ProcessingUnit.__init__(self)
55 ProcessingUnit.__init__(self)
56
56
57 self.buffer = None
57 self.buffer = None
58 self.firstdatatime = None
58 self.firstdatatime = None
59 self.profIndex = 0
59 self.profIndex = 0
60 self.dataOut = Parameters()
60 self.dataOut = Parameters()
61 self.setupReq = False #Agregar a todas las unidades de proc
61 self.setupReq = False #Agregar a todas las unidades de proc
62
62
63 def __updateObjFromInput(self):
63 def __updateObjFromInput(self):
64
64
65 self.dataOut.inputUnit = self.dataIn.type
65 self.dataOut.inputUnit = self.dataIn.type
66
66
67 self.dataOut.timeZone = self.dataIn.timeZone
67 self.dataOut.timeZone = self.dataIn.timeZone
68 self.dataOut.dstFlag = self.dataIn.dstFlag
68 self.dataOut.dstFlag = self.dataIn.dstFlag
69 self.dataOut.errorCount = self.dataIn.errorCount
69 self.dataOut.errorCount = self.dataIn.errorCount
70 self.dataOut.useLocalTime = self.dataIn.useLocalTime
70 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71
71
72 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
72 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
73 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 self.dataOut.channelList = self.dataIn.channelList
74 self.dataOut.channelList = self.dataIn.channelList
75 self.dataOut.heightList = self.dataIn.heightList
75 self.dataOut.heightList = self.dataIn.heightList
76 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
76 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 # self.dataOut.nHeights = self.dataIn.nHeights
77 # self.dataOut.nHeights = self.dataIn.nHeights
78 # self.dataOut.nChannels = self.dataIn.nChannels
78 # self.dataOut.nChannels = self.dataIn.nChannels
79 # self.dataOut.nBaud = self.dataIn.nBaud
79 # self.dataOut.nBaud = self.dataIn.nBaud
80 # self.dataOut.nCode = self.dataIn.nCode
80 # self.dataOut.nCode = self.dataIn.nCode
81 # self.dataOut.code = self.dataIn.code
81 # self.dataOut.code = self.dataIn.code
82 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
82 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
83 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
83 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
84 # self.dataOut.utctime = self.firstdatatime
84 # self.dataOut.utctime = self.firstdatatime
85 self.dataOut.utctime = self.dataIn.utctime
85 self.dataOut.utctime = self.dataIn.utctime
86 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
86 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
87 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
87 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
88 self.dataOut.nCohInt = self.dataIn.nCohInt
88 self.dataOut.nCohInt = self.dataIn.nCohInt
89 # self.dataOut.nIncohInt = 1
89 # self.dataOut.nIncohInt = 1
90 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
90 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
91 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
91 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
92 self.dataOut.timeInterval1 = self.dataIn.timeInterval
92 self.dataOut.timeInterval1 = self.dataIn.timeInterval
93 self.dataOut.heightList = self.dataIn.heightList
93 self.dataOut.heightList = self.dataIn.heightList
94 self.dataOut.frequency = self.dataIn.frequency
94 self.dataOut.frequency = self.dataIn.frequency
95 #self.dataOut.noise = self.dataIn.noise
95 #self.dataOut.noise = self.dataIn.noise
96
96
97 def run(self):
97 def run(self):
98
98
99 #---------------------- Voltage Data ---------------------------
99 #---------------------- Voltage Data ---------------------------
100
100
101 if self.dataIn.type == "Voltage":
101 if self.dataIn.type == "Voltage":
102
102
103 self.__updateObjFromInput()
103 self.__updateObjFromInput()
104 self.dataOut.data_pre = self.dataIn.data.copy()
104 self.dataOut.data_pre = self.dataIn.data.copy()
105 self.dataOut.flagNoData = False
105 self.dataOut.flagNoData = False
106 self.dataOut.utctimeInit = self.dataIn.utctime
106 self.dataOut.utctimeInit = self.dataIn.utctime
107 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
107 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
108 if hasattr(self.dataIn, 'dataPP_POW'):
108 if hasattr(self.dataIn, 'dataPP_POW'):
109 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
109 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
110
110
111 if hasattr(self.dataIn, 'dataPP_POWER'):
111 if hasattr(self.dataIn, 'dataPP_POWER'):
112 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
112 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
113
113
114 if hasattr(self.dataIn, 'dataPP_DOP'):
114 if hasattr(self.dataIn, 'dataPP_DOP'):
115 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
115 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
116
116
117 if hasattr(self.dataIn, 'dataPP_SNR'):
117 if hasattr(self.dataIn, 'dataPP_SNR'):
118 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
118 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
119
119
120 if hasattr(self.dataIn, 'dataPP_WIDTH'):
120 if hasattr(self.dataIn, 'dataPP_WIDTH'):
121 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
121 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
122 return
122 return
123
123
124 #---------------------- Spectra Data ---------------------------
124 #---------------------- Spectra Data ---------------------------
125
125
126 if self.dataIn.type == "Spectra":
126 if self.dataIn.type == "Spectra":
127
127
128 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
128 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
129 self.dataOut.data_spc = self.dataIn.data_spc
129 self.dataOut.data_spc = self.dataIn.data_spc
130 self.dataOut.data_cspc = self.dataIn.data_cspc
130 self.dataOut.data_cspc = self.dataIn.data_cspc
131 self.dataOut.nProfiles = self.dataIn.nProfiles
131 self.dataOut.nProfiles = self.dataIn.nProfiles
132 self.dataOut.nIncohInt = self.dataIn.nIncohInt
132 self.dataOut.nIncohInt = self.dataIn.nIncohInt
133 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
133 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
134 self.dataOut.ippFactor = self.dataIn.ippFactor
134 self.dataOut.ippFactor = self.dataIn.ippFactor
135 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
135 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
136 self.dataOut.spc_noise = self.dataIn.getNoise()
136 self.dataOut.spc_noise = self.dataIn.getNoise()
137 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
137 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
138 # self.dataOut.normFactor = self.dataIn.normFactor
138 # self.dataOut.normFactor = self.dataIn.normFactor
139 self.dataOut.pairsList = self.dataIn.pairsList
139 self.dataOut.pairsList = self.dataIn.pairsList
140 self.dataOut.groupList = self.dataIn.pairsList
140 self.dataOut.groupList = self.dataIn.pairsList
141 self.dataOut.flagNoData = False
141 self.dataOut.flagNoData = False
142
142
143 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
143 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
144 self.dataOut.ChanDist = self.dataIn.ChanDist
144 self.dataOut.ChanDist = self.dataIn.ChanDist
145 else: self.dataOut.ChanDist = None
145 else: self.dataOut.ChanDist = None
146
146
147 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
147 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
148 # self.dataOut.VelRange = self.dataIn.VelRange
148 # self.dataOut.VelRange = self.dataIn.VelRange
149 #else: self.dataOut.VelRange = None
149 #else: self.dataOut.VelRange = None
150
150
151 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
151 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
152 self.dataOut.RadarConst = self.dataIn.RadarConst
152 self.dataOut.RadarConst = self.dataIn.RadarConst
153
153
154 if hasattr(self.dataIn, 'NPW'): #NPW
154 if hasattr(self.dataIn, 'NPW'): #NPW
155 self.dataOut.NPW = self.dataIn.NPW
155 self.dataOut.NPW = self.dataIn.NPW
156
156
157 if hasattr(self.dataIn, 'COFA'): #COFA
157 if hasattr(self.dataIn, 'COFA'): #COFA
158 self.dataOut.COFA = self.dataIn.COFA
158 self.dataOut.COFA = self.dataIn.COFA
159
159
160
160
161
161
162 #---------------------- Correlation Data ---------------------------
162 #---------------------- Correlation Data ---------------------------
163
163
164 if self.dataIn.type == "Correlation":
164 if self.dataIn.type == "Correlation":
165 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
165 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
166
166
167 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
167 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
168 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
168 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
169 self.dataOut.groupList = (acf_pairs, ccf_pairs)
169 self.dataOut.groupList = (acf_pairs, ccf_pairs)
170
170
171 self.dataOut.abscissaList = self.dataIn.lagRange
171 self.dataOut.abscissaList = self.dataIn.lagRange
172 self.dataOut.noise = self.dataIn.noise
172 self.dataOut.noise = self.dataIn.noise
173 self.dataOut.data_snr = self.dataIn.SNR
173 self.dataOut.data_snr = self.dataIn.SNR
174 self.dataOut.flagNoData = False
174 self.dataOut.flagNoData = False
175 self.dataOut.nAvg = self.dataIn.nAvg
175 self.dataOut.nAvg = self.dataIn.nAvg
176
176
177 #---------------------- Parameters Data ---------------------------
177 #---------------------- Parameters Data ---------------------------
178
178
179 if self.dataIn.type == "Parameters":
179 if self.dataIn.type == "Parameters":
180 self.dataOut.copy(self.dataIn)
180 self.dataOut.copy(self.dataIn)
181 self.dataOut.flagNoData = False
181 self.dataOut.flagNoData = False
182
182
183 return True
183 return True
184
184
185 self.__updateObjFromInput()
185 self.__updateObjFromInput()
186 self.dataOut.utctimeInit = self.dataIn.utctime
186 self.dataOut.utctimeInit = self.dataIn.utctime
187 self.dataOut.paramInterval = self.dataIn.timeInterval
187 self.dataOut.paramInterval = self.dataIn.timeInterval
188
188
189 return
189 return
190
190
191
191
192 def target(tups):
192 def target(tups):
193
193
194 obj, args = tups
194 obj, args = tups
195
195
196 return obj.FitGau(args)
196 return obj.FitGau(args)
197
197
198 class RemoveWideGC(Operation):
198 class RemoveWideGC(Operation):
199 ''' This class remove the wide clutter and replace it with a simple interpolation points
199 ''' This class remove the wide clutter and replace it with a simple interpolation points
200 This mainly applies to CLAIRE radar
200 This mainly applies to CLAIRE radar
201
201
202 ClutterWidth : Width to look for the clutter peak
202 ClutterWidth : Width to look for the clutter peak
203
203
204 Input:
204 Input:
205
205
206 self.dataOut.data_pre : SPC and CSPC
206 self.dataOut.data_pre : SPC and CSPC
207 self.dataOut.spc_range : To select wind and rainfall velocities
207 self.dataOut.spc_range : To select wind and rainfall velocities
208
208
209 Affected:
209 Affected:
210
210
211 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
211 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
212
212
213 Written by D. ScipiΓ³n 25.02.2021
213 Written by D. ScipiΓ³n 25.02.2021
214 '''
214 '''
215 def __init__(self):
215 def __init__(self):
216 Operation.__init__(self)
216 Operation.__init__(self)
217 self.i = 0
217 self.i = 0
218 self.ich = 0
218 self.ich = 0
219 self.ir = 0
219 self.ir = 0
220
220
221 def run(self, dataOut, ClutterWidth=2.5):
221 def run(self, dataOut, ClutterWidth=2.5):
222
222
223 self.spc = dataOut.data_pre[0].copy()
223 self.spc = dataOut.data_pre[0].copy()
224 self.spc_out = dataOut.data_pre[0].copy()
224 self.spc_out = dataOut.data_pre[0].copy()
225 self.Num_Chn = self.spc.shape[0]
225 self.Num_Chn = self.spc.shape[0]
226 self.Num_Hei = self.spc.shape[2]
226 self.Num_Hei = self.spc.shape[2]
227 VelRange = dataOut.spc_range[2][:-1]
227 VelRange = dataOut.spc_range[2][:-1]
228 dv = VelRange[1]-VelRange[0]
228 dv = VelRange[1]-VelRange[0]
229
229
230 # Find the velocities that corresponds to zero
230 # Find the velocities that corresponds to zero
231 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
231 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
232
232
233 # Removing novalid data from the spectra
233 # Removing novalid data from the spectra
234 for ich in range(self.Num_Chn) :
234 for ich in range(self.Num_Chn) :
235 for ir in range(self.Num_Hei) :
235 for ir in range(self.Num_Hei) :
236 # Estimate the noise at each range
236 # Estimate the noise at each range
237 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
237 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
238
238
239 # Removing the noise floor at each range
239 # Removing the noise floor at each range
240 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
240 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
241 self.spc[ich,novalid,ir] = HSn
241 self.spc[ich,novalid,ir] = HSn
242
242
243 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
243 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
244 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
244 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
245 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
245 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
246 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
246 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
247 continue
247 continue
248 junk3 = numpy.squeeze(numpy.diff(j1index))
248 junk3 = numpy.squeeze(numpy.diff(j1index))
249 junk4 = numpy.squeeze(numpy.diff(j2index))
249 junk4 = numpy.squeeze(numpy.diff(j2index))
250
250
251 valleyindex = j2index[numpy.where(junk4>1)]
251 valleyindex = j2index[numpy.where(junk4>1)]
252 peakindex = j1index[numpy.where(junk3>1)]
252 peakindex = j1index[numpy.where(junk3>1)]
253
253
254 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
254 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
255 if numpy.size(isvalid) == 0 :
255 if numpy.size(isvalid) == 0 :
256 continue
256 continue
257 if numpy.size(isvalid) >1 :
257 if numpy.size(isvalid) >1 :
258 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
258 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
259 isvalid = isvalid[vindex]
259 isvalid = isvalid[vindex]
260
260
261 # clutter peak
261 # clutter peak
262 gcpeak = peakindex[isvalid]
262 gcpeak = peakindex[isvalid]
263 vl = numpy.where(valleyindex < gcpeak)
263 vl = numpy.where(valleyindex < gcpeak)
264 if numpy.size(vl) == 0:
264 if numpy.size(vl) == 0:
265 continue
265 continue
266 gcvl = valleyindex[vl[0][-1]]
266 gcvl = valleyindex[vl[0][-1]]
267 vr = numpy.where(valleyindex > gcpeak)
267 vr = numpy.where(valleyindex > gcpeak)
268 if numpy.size(vr) == 0:
268 if numpy.size(vr) == 0:
269 continue
269 continue
270 gcvr = valleyindex[vr[0][0]]
270 gcvr = valleyindex[vr[0][0]]
271
271
272 # Removing the clutter
272 # Removing the clutter
273 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
273 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
274 gcindex = gc_values[gcvl+1:gcvr-1]
274 gcindex = gc_values[gcvl+1:gcvr-1]
275 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
275 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
276
276
277 dataOut.data_pre[0] = self.spc_out
277 dataOut.data_pre[0] = self.spc_out
278
278
279 return dataOut
279 return dataOut
280
280
281 class SpectralFilters(Operation):
281 class SpectralFilters(Operation):
282 ''' This class allows to replace the novalid values with noise for each channel
282 ''' This class allows to replace the novalid values with noise for each channel
283 This applies to CLAIRE RADAR
283 This applies to CLAIRE RADAR
284
284
285 PositiveLimit : RightLimit of novalid data
285 PositiveLimit : RightLimit of novalid data
286 NegativeLimit : LeftLimit of novalid data
286 NegativeLimit : LeftLimit of novalid data
287
287
288 Input:
288 Input:
289
289
290 self.dataOut.data_pre : SPC and CSPC
290 self.dataOut.data_pre : SPC and CSPC
291 self.dataOut.spc_range : To select wind and rainfall velocities
291 self.dataOut.spc_range : To select wind and rainfall velocities
292
292
293 Affected:
293 Affected:
294
294
295 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
295 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
296
296
297 Written by D. ScipiΓ³n 29.01.2021
297 Written by D. ScipiΓ³n 29.01.2021
298 '''
298 '''
299 def __init__(self):
299 def __init__(self):
300 Operation.__init__(self)
300 Operation.__init__(self)
301 self.i = 0
301 self.i = 0
302
302
303 def run(self, dataOut, ):
303 def run(self, dataOut, ):
304
304
305 self.spc = dataOut.data_pre[0].copy()
305 self.spc = dataOut.data_pre[0].copy()
306 self.Num_Chn = self.spc.shape[0]
306 self.Num_Chn = self.spc.shape[0]
307 VelRange = dataOut.spc_range[2]
307 VelRange = dataOut.spc_range[2]
308
308
309 # novalid corresponds to data within the Negative and PositiveLimit
309 # novalid corresponds to data within the Negative and PositiveLimit
310
310
311
311
312 # Removing novalid data from the spectra
312 # Removing novalid data from the spectra
313 for i in range(self.Num_Chn):
313 for i in range(self.Num_Chn):
314 self.spc[i,novalid,:] = dataOut.noise[i]
314 self.spc[i,novalid,:] = dataOut.noise[i]
315 dataOut.data_pre[0] = self.spc
315 dataOut.data_pre[0] = self.spc
316 return dataOut
316 return dataOut
317
317
318
318
319
319
320 class GaussianFit(Operation):
320 class GaussianFit(Operation):
321
321
322 '''
322 '''
323 Function that fit of one and two generalized gaussians (gg) based
323 Function that fit of one and two generalized gaussians (gg) based
324 on the PSD shape across an "power band" identified from a cumsum of
324 on the PSD shape across an "power band" identified from a cumsum of
325 the measured spectrum - noise.
325 the measured spectrum - noise.
326
326
327 Input:
327 Input:
328 self.dataOut.data_pre : SelfSpectra
328 self.dataOut.data_pre : SelfSpectra
329
329
330 Output:
330 Output:
331 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
331 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
332
332
333 '''
333 '''
334 def __init__(self):
334 def __init__(self):
335 Operation.__init__(self)
335 Operation.__init__(self)
336 self.i=0
336 self.i=0
337
337
338
338
339 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
339 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
340 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
340 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
341 """This routine will find a couple of generalized Gaussians to a power spectrum
341 """This routine will find a couple of generalized Gaussians to a power spectrum
342 methods: generalized, squared
342 methods: generalized, squared
343 input: spc
343 input: spc
344 output:
344 output:
345 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
345 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
346 """
346 """
347 print ('Entering ',method,' double Gaussian fit')
347 print ('Entering ',method,' double Gaussian fit')
348 self.spc = dataOut.data_pre[0].copy()
348 self.spc = dataOut.data_pre[0].copy()
349 self.Num_Hei = self.spc.shape[2]
349 self.Num_Hei = self.spc.shape[2]
350 self.Num_Bin = self.spc.shape[1]
350 self.Num_Bin = self.spc.shape[1]
351 self.Num_Chn = self.spc.shape[0]
351 self.Num_Chn = self.spc.shape[0]
352
352
353 start_time = time.time()
353 start_time = time.time()
354
354
355 pool = Pool(processes=self.Num_Chn)
355 pool = Pool(processes=self.Num_Chn)
356 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
356 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
357 objs = [self for __ in range(self.Num_Chn)]
357 objs = [self for __ in range(self.Num_Chn)]
358 attrs = list(zip(objs, args))
358 attrs = list(zip(objs, args))
359 DGauFitParam = pool.map(target, attrs)
359 DGauFitParam = pool.map(target, attrs)
360 # Parameters:
360 # Parameters:
361 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
361 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
362 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
362 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
363
363
364 # Double Gaussian Curves
364 # Double Gaussian Curves
365 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
365 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
366 gau0[:] = numpy.NaN
366 gau0[:] = numpy.NaN
367 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
367 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
368 gau1[:] = numpy.NaN
368 gau1[:] = numpy.NaN
369 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
369 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
370 for iCh in range(self.Num_Chn):
370 for iCh in range(self.Num_Chn):
371 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
371 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
372 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
372 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
373 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
373 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
374 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
374 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
375 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
375 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
376 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
376 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
377 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
377 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
378 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
378 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
379 if method == 'generalized':
379 if method == 'generalized':
380 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
380 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
381 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
381 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
382 elif method == 'squared':
382 elif method == 'squared':
383 p0 = 2.
383 p0 = 2.
384 p1 = 2.
384 p1 = 2.
385 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
385 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
386 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
386 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
387 dataOut.GaussFit0 = gau0
387 dataOut.GaussFit0 = gau0
388 dataOut.GaussFit1 = gau1
388 dataOut.GaussFit1 = gau1
389
389
390 print('Leaving ',method ,' double Gaussian fit')
390 print('Leaving ',method ,' double Gaussian fit')
391 return dataOut
391 return dataOut
392
392
393 def FitGau(self, X):
393 def FitGau(self, X):
394 # print('Entering FitGau')
394 # print('Entering FitGau')
395 # Assigning the variables
395 # Assigning the variables
396 Vrange, ch, wnoise, num_intg, SNRlimit = X
396 Vrange, ch, wnoise, num_intg, SNRlimit = X
397 # Noise Limits
397 # Noise Limits
398 noisebl = wnoise * 0.9
398 noisebl = wnoise * 0.9
399 noisebh = wnoise * 1.1
399 noisebh = wnoise * 1.1
400 # Radar Velocity
400 # Radar Velocity
401 Va = max(Vrange)
401 Va = max(Vrange)
402 deltav = Vrange[1] - Vrange[0]
402 deltav = Vrange[1] - Vrange[0]
403 x = numpy.arange(self.Num_Bin)
403 x = numpy.arange(self.Num_Bin)
404
404
405 # print ('stop 0')
405 # print ('stop 0')
406
406
407 # 5 parameters, 2 Gaussians
407 # 5 parameters, 2 Gaussians
408 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
408 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
409 DGauFitParam[:] = numpy.NaN
409 DGauFitParam[:] = numpy.NaN
410
410
411 # SPCparam = []
411 # SPCparam = []
412 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
412 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
413 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
413 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
414 # SPC_ch1[:] = 0 #numpy.NaN
414 # SPC_ch1[:] = 0 #numpy.NaN
415 # SPC_ch2[:] = 0 #numpy.NaN
415 # SPC_ch2[:] = 0 #numpy.NaN
416 # print ('stop 1')
416 # print ('stop 1')
417 for ht in range(self.Num_Hei):
417 for ht in range(self.Num_Hei):
418 # print (ht)
418 # print (ht)
419 # print ('stop 2')
419 # print ('stop 2')
420 # Spectra at each range
420 # Spectra at each range
421 spc = numpy.asarray(self.spc)[ch,:,ht]
421 spc = numpy.asarray(self.spc)[ch,:,ht]
422 snr = ( spc.mean() - wnoise ) / wnoise
422 snr = ( spc.mean() - wnoise ) / wnoise
423 snrdB = 10.*numpy.log10(snr)
423 snrdB = 10.*numpy.log10(snr)
424
424
425 #print ('stop 3')
425 #print ('stop 3')
426 if snrdB < SNRlimit :
426 if snrdB < SNRlimit :
427 # snr = numpy.NaN
427 # snr = numpy.NaN
428 # SPC_ch1[:,ht] = 0#numpy.NaN
428 # SPC_ch1[:,ht] = 0#numpy.NaN
429 # SPC_ch1[:,ht] = 0#numpy.NaN
429 # SPC_ch1[:,ht] = 0#numpy.NaN
430 # SPCparam = (SPC_ch1,SPC_ch2)
430 # SPCparam = (SPC_ch1,SPC_ch2)
431 # print ('SNR less than SNRth')
431 # print ('SNR less than SNRth')
432 continue
432 continue
433 # wnoise = hildebrand_sekhon(spc,num_intg)
433 # wnoise = hildebrand_sekhon(spc,num_intg)
434 # print ('stop 2.01')
434 # print ('stop 2.01')
435 #############################################
435 #############################################
436 # normalizing spc and noise
436 # normalizing spc and noise
437 # This part differs from gg1
437 # This part differs from gg1
438 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
438 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
439 #spc = spc / spc_norm_max
439 #spc = spc / spc_norm_max
440 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
440 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
441 #############################################
441 #############################################
442
442
443 # print ('stop 2.1')
443 # print ('stop 2.1')
444 fatspectra=1.0
444 fatspectra=1.0
445 # noise per channel.... we might want to use the noise at each range
445 # noise per channel.... we might want to use the noise at each range
446
446
447 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
447 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
448 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
448 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
449 #if wnoise>1.1*pnoise: # to be tested later
449 #if wnoise>1.1*pnoise: # to be tested later
450 # wnoise=pnoise
450 # wnoise=pnoise
451 # noisebl = wnoise*0.9
451 # noisebl = wnoise*0.9
452 # noisebh = wnoise*1.1
452 # noisebh = wnoise*1.1
453 spc = spc - wnoise # signal
453 spc = spc - wnoise # signal
454
454
455 # print ('stop 2.2')
455 # print ('stop 2.2')
456 minx = numpy.argmin(spc)
456 minx = numpy.argmin(spc)
457 #spcs=spc.copy()
457 #spcs=spc.copy()
458 spcs = numpy.roll(spc,-minx)
458 spcs = numpy.roll(spc,-minx)
459 cum = numpy.cumsum(spcs)
459 cum = numpy.cumsum(spcs)
460 # tot_noise = wnoise * self.Num_Bin #64;
460 # tot_noise = wnoise * self.Num_Bin #64;
461
461
462 # print ('stop 2.3')
462 # print ('stop 2.3')
463 # snr = sum(spcs) / tot_noise
463 # snr = sum(spcs) / tot_noise
464 # snrdB = 10.*numpy.log10(snr)
464 # snrdB = 10.*numpy.log10(snr)
465 #print ('stop 3')
465 #print ('stop 3')
466 # if snrdB < SNRlimit :
466 # if snrdB < SNRlimit :
467 # snr = numpy.NaN
467 # snr = numpy.NaN
468 # SPC_ch1[:,ht] = 0#numpy.NaN
468 # SPC_ch1[:,ht] = 0#numpy.NaN
469 # SPC_ch1[:,ht] = 0#numpy.NaN
469 # SPC_ch1[:,ht] = 0#numpy.NaN
470 # SPCparam = (SPC_ch1,SPC_ch2)
470 # SPCparam = (SPC_ch1,SPC_ch2)
471 # print ('SNR less than SNRth')
471 # print ('SNR less than SNRth')
472 # continue
472 # continue
473
473
474
474
475 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
475 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
476 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
476 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
477 # print ('stop 4')
477 # print ('stop 4')
478 cummax = max(cum)
478 cummax = max(cum)
479 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
479 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
480 cumlo = cummax * epsi
480 cumlo = cummax * epsi
481 cumhi = cummax * (1-epsi)
481 cumhi = cummax * (1-epsi)
482 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
482 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
483
483
484 # print ('stop 5')
484 # print ('stop 5')
485 if len(powerindex) < 1:# case for powerindex 0
485 if len(powerindex) < 1:# case for powerindex 0
486 # print ('powerindex < 1')
486 # print ('powerindex < 1')
487 continue
487 continue
488 powerlo = powerindex[0]
488 powerlo = powerindex[0]
489 powerhi = powerindex[-1]
489 powerhi = powerindex[-1]
490 powerwidth = powerhi-powerlo
490 powerwidth = powerhi-powerlo
491 if powerwidth <= 1:
491 if powerwidth <= 1:
492 # print('powerwidth <= 1')
492 # print('powerwidth <= 1')
493 continue
493 continue
494
494
495 # print ('stop 6')
495 # print ('stop 6')
496 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
496 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
497 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
497 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
498 midpeak = (firstpeak + secondpeak)/2.
498 midpeak = (firstpeak + secondpeak)/2.
499 firstamp = spcs[int(firstpeak)]
499 firstamp = spcs[int(firstpeak)]
500 secondamp = spcs[int(secondpeak)]
500 secondamp = spcs[int(secondpeak)]
501 midamp = spcs[int(midpeak)]
501 midamp = spcs[int(midpeak)]
502
502
503 y_data = spc + wnoise
503 y_data = spc + wnoise
504
504
505 ''' single Gaussian '''
505 ''' single Gaussian '''
506 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
506 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
507 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
507 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
508 power0 = 2.
508 power0 = 2.
509 amplitude0 = midamp
509 amplitude0 = midamp
510 state0 = [shift0,width0,amplitude0,power0,wnoise]
510 state0 = [shift0,width0,amplitude0,power0,wnoise]
511 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
511 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
512 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
512 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
513 # print ('stop 7.1')
513 # print ('stop 7.1')
514 # print (bnds)
514 # print (bnds)
515
515
516 chiSq1=lsq1[1]
516 chiSq1=lsq1[1]
517
517
518 # print ('stop 8')
518 # print ('stop 8')
519 if fatspectra<1.0 and powerwidth<4:
519 if fatspectra<1.0 and powerwidth<4:
520 choice=0
520 choice=0
521 Amplitude0=lsq1[0][2]
521 Amplitude0=lsq1[0][2]
522 shift0=lsq1[0][0]
522 shift0=lsq1[0][0]
523 width0=lsq1[0][1]
523 width0=lsq1[0][1]
524 p0=lsq1[0][3]
524 p0=lsq1[0][3]
525 Amplitude1=0.
525 Amplitude1=0.
526 shift1=0.
526 shift1=0.
527 width1=0.
527 width1=0.
528 p1=0.
528 p1=0.
529 noise=lsq1[0][4]
529 noise=lsq1[0][4]
530 #return (numpy.array([shift0,width0,Amplitude0,p0]),
530 #return (numpy.array([shift0,width0,Amplitude0,p0]),
531 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
531 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
532 # print ('stop 9')
532 # print ('stop 9')
533 ''' two Gaussians '''
533 ''' two Gaussians '''
534 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
534 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
535 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
535 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
536 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
536 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
537 width0 = powerwidth/6.
537 width0 = powerwidth/6.
538 width1 = width0
538 width1 = width0
539 power0 = 2.
539 power0 = 2.
540 power1 = power0
540 power1 = power0
541 amplitude0 = firstamp
541 amplitude0 = firstamp
542 amplitude1 = secondamp
542 amplitude1 = secondamp
543 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
543 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
544 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
544 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
545 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))
545 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))
546 #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))
546 #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))
547
547
548 # print ('stop 10')
548 # print ('stop 10')
549 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
549 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
550
550
551 # print ('stop 11')
551 # print ('stop 11')
552 chiSq2 = lsq2[1]
552 chiSq2 = lsq2[1]
553
553
554 # print ('stop 12')
554 # print ('stop 12')
555
555
556 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)
556 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)
557
557
558 # print ('stop 13')
558 # print ('stop 13')
559 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
559 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
560 if oneG:
560 if oneG:
561 choice = 0
561 choice = 0
562 else:
562 else:
563 w1 = lsq2[0][1]; w2 = lsq2[0][5]
563 w1 = lsq2[0][1]; w2 = lsq2[0][5]
564 a1 = lsq2[0][2]; a2 = lsq2[0][6]
564 a1 = lsq2[0][2]; a2 = lsq2[0][6]
565 p1 = lsq2[0][3]; p2 = lsq2[0][7]
565 p1 = lsq2[0][3]; p2 = lsq2[0][7]
566 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
566 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
567 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
567 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
568 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
568 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
569
569
570 if gp1>gp2:
570 if gp1>gp2:
571 if a1>0.7*a2:
571 if a1>0.7*a2:
572 choice = 1
572 choice = 1
573 else:
573 else:
574 choice = 2
574 choice = 2
575 elif gp2>gp1:
575 elif gp2>gp1:
576 if a2>0.7*a1:
576 if a2>0.7*a1:
577 choice = 2
577 choice = 2
578 else:
578 else:
579 choice = 1
579 choice = 1
580 else:
580 else:
581 choice = numpy.argmax([a1,a2])+1
581 choice = numpy.argmax([a1,a2])+1
582 #else:
582 #else:
583 #choice=argmin([std2a,std2b])+1
583 #choice=argmin([std2a,std2b])+1
584
584
585 else: # with low SNR go to the most energetic peak
585 else: # with low SNR go to the most energetic peak
586 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
586 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
587
587
588 # print ('stop 14')
588 # print ('stop 14')
589 shift0 = lsq2[0][0]
589 shift0 = lsq2[0][0]
590 vel0 = Vrange[0] + shift0 * deltav
590 vel0 = Vrange[0] + shift0 * deltav
591 shift1 = lsq2[0][4]
591 shift1 = lsq2[0][4]
592 # vel1=Vrange[0] + shift1 * deltav
592 # vel1=Vrange[0] + shift1 * deltav
593
593
594 # max_vel = 1.0
594 # max_vel = 1.0
595 # Va = max(Vrange)
595 # Va = max(Vrange)
596 # deltav = Vrange[1]-Vrange[0]
596 # deltav = Vrange[1]-Vrange[0]
597 # print ('stop 15')
597 # print ('stop 15')
598 #first peak will be 0, second peak will be 1
598 #first peak will be 0, second peak will be 1
599 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
599 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
600 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
600 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
601 shift0 = lsq2[0][0]
601 shift0 = lsq2[0][0]
602 width0 = lsq2[0][1]
602 width0 = lsq2[0][1]
603 Amplitude0 = lsq2[0][2]
603 Amplitude0 = lsq2[0][2]
604 p0 = lsq2[0][3]
604 p0 = lsq2[0][3]
605
605
606 shift1 = lsq2[0][4]
606 shift1 = lsq2[0][4]
607 width1 = lsq2[0][5]
607 width1 = lsq2[0][5]
608 Amplitude1 = lsq2[0][6]
608 Amplitude1 = lsq2[0][6]
609 p1 = lsq2[0][7]
609 p1 = lsq2[0][7]
610 noise = lsq2[0][8]
610 noise = lsq2[0][8]
611 else:
611 else:
612 shift1 = lsq2[0][0]
612 shift1 = lsq2[0][0]
613 width1 = lsq2[0][1]
613 width1 = lsq2[0][1]
614 Amplitude1 = lsq2[0][2]
614 Amplitude1 = lsq2[0][2]
615 p1 = lsq2[0][3]
615 p1 = lsq2[0][3]
616
616
617 shift0 = lsq2[0][4]
617 shift0 = lsq2[0][4]
618 width0 = lsq2[0][5]
618 width0 = lsq2[0][5]
619 Amplitude0 = lsq2[0][6]
619 Amplitude0 = lsq2[0][6]
620 p0 = lsq2[0][7]
620 p0 = lsq2[0][7]
621 noise = lsq2[0][8]
621 noise = lsq2[0][8]
622
622
623 if Amplitude0<0.05: # in case the peak is noise
623 if Amplitude0<0.05: # in case the peak is noise
624 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
624 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
625 if Amplitude1<0.05:
625 if Amplitude1<0.05:
626 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
626 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
627
627
628 # print ('stop 16 ')
628 # print ('stop 16 ')
629 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
629 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
630 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
630 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
631 # SPCparam = (SPC_ch1,SPC_ch2)
631 # SPCparam = (SPC_ch1,SPC_ch2)
632
632
633 DGauFitParam[0,ht,0] = noise
633 DGauFitParam[0,ht,0] = noise
634 DGauFitParam[0,ht,1] = noise
634 DGauFitParam[0,ht,1] = noise
635 DGauFitParam[1,ht,0] = Amplitude0
635 DGauFitParam[1,ht,0] = Amplitude0
636 DGauFitParam[1,ht,1] = Amplitude1
636 DGauFitParam[1,ht,1] = Amplitude1
637 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
637 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
638 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
638 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
639 DGauFitParam[3,ht,0] = width0 * deltav
639 DGauFitParam[3,ht,0] = width0 * deltav
640 DGauFitParam[3,ht,1] = width1 * deltav
640 DGauFitParam[3,ht,1] = width1 * deltav
641 DGauFitParam[4,ht,0] = p0
641 DGauFitParam[4,ht,0] = p0
642 DGauFitParam[4,ht,1] = p1
642 DGauFitParam[4,ht,1] = p1
643
643
644 return DGauFitParam
644 return DGauFitParam
645
645
646 def y_model1(self,x,state):
646 def y_model1(self,x,state):
647 shift0, width0, amplitude0, power0, noise = state
647 shift0, width0, amplitude0, power0, noise = state
648 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
648 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
649 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
649 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
650 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
650 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
651 return model0 + model0u + model0d + noise
651 return model0 + model0u + model0d + noise
652
652
653 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
653 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
654 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
654 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
655 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
655 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
656 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
656 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
657 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
657 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
658
658
659 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
659 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
660 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
660 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
661 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
661 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
662 return model0 + model0u + model0d + model1 + model1u + model1d + noise
662 return model0 + model0u + model0d + model1 + model1u + model1d + noise
663
663
664 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.
664 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.
665
665
666 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
666 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
667
667
668 def misfit2(self,state,y_data,x,num_intg):
668 def misfit2(self,state,y_data,x,num_intg):
669 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
669 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
670
670
671 class Oblique_Gauss_Fit(Operation):
671 class Oblique_Gauss_Fit(Operation):
672
672
673 def __init__(self):
673 def __init__(self):
674 Operation.__init__(self)
674 Operation.__init__(self)
675
675
676 def Gauss_fit(self,spc,x,nGauss):
676 def Gauss_fit(self,spc,x,nGauss):
677
677
678
678
679 def gaussian(x, a, b, c, d):
679 def gaussian(x, a, b, c, d):
680 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
680 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
681 return val
681 return val
682
682
683 if nGauss == 'first':
683 if nGauss == 'first':
684 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
684 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
685 spc_2_aux = numpy.flip(spc_1_aux)
685 spc_2_aux = numpy.flip(spc_1_aux)
686 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
686 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
687
687
688 len_dif = len(x)-len(spc_3_aux)
688 len_dif = len(x)-len(spc_3_aux)
689
689
690 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
690 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
691
691
692 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
692 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
693
693
694 y = spc_new
694 y = spc_new
695
695
696 elif nGauss == 'second':
696 elif nGauss == 'second':
697 y = spc
697 y = spc
698
698
699
699
700 # estimate starting values from the data
700 # estimate starting values from the data
701 a = y.max()
701 a = y.max()
702 b = x[numpy.argmax(y)]
702 b = x[numpy.argmax(y)]
703 if nGauss == 'first':
703 if nGauss == 'first':
704 c = 1.#b#b#numpy.std(spc)
704 c = 1.#b#b#numpy.std(spc)
705 elif nGauss == 'second':
705 elif nGauss == 'second':
706 c = b
706 c = b
707 else:
707 else:
708 print("ERROR")
708 print("ERROR")
709
709
710 d = numpy.mean(y[-100:])
710 d = numpy.mean(y[-100:])
711
711
712 # define a least squares function to optimize
712 # define a least squares function to optimize
713 def minfunc(params):
713 def minfunc(params):
714 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
714 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
715
715
716 # fit
716 # fit
717 popt = fmin(minfunc,[a,b,c,d],disp=False)
717 popt = fmin(minfunc,[a,b,c,d],disp=False)
718 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
718 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
719
719
720
720
721 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
721 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
722
722
723
723
724 def Gauss_fit_2(self,spc,x,nGauss):
724 def Gauss_fit_2(self,spc,x,nGauss):
725
725
726
726
727 def gaussian(x, a, b, c, d):
727 def gaussian(x, a, b, c, d):
728 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
728 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
729 return val
729 return val
730
730
731 if nGauss == 'first':
731 if nGauss == 'first':
732 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
732 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
733 spc_2_aux = numpy.flip(spc_1_aux)
733 spc_2_aux = numpy.flip(spc_1_aux)
734 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
734 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
735
735
736 len_dif = len(x)-len(spc_3_aux)
736 len_dif = len(x)-len(spc_3_aux)
737
737
738 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
738 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
739
739
740 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
740 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
741
741
742 y = spc_new
742 y = spc_new
743
743
744 elif nGauss == 'second':
744 elif nGauss == 'second':
745 y = spc
745 y = spc
746
746
747
747
748 # estimate starting values from the data
748 # estimate starting values from the data
749 a = y.max()
749 a = y.max()
750 b = x[numpy.argmax(y)]
750 b = x[numpy.argmax(y)]
751 if nGauss == 'first':
751 if nGauss == 'first':
752 c = 1.#b#b#numpy.std(spc)
752 c = 1.#b#b#numpy.std(spc)
753 elif nGauss == 'second':
753 elif nGauss == 'second':
754 c = b
754 c = b
755 else:
755 else:
756 print("ERROR")
756 print("ERROR")
757
757
758 d = numpy.mean(y[-100:])
758 d = numpy.mean(y[-100:])
759
759
760 # define a least squares function to optimize
760 # define a least squares function to optimize
761 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
761 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
762 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
762 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
763
763
764
764
765 #return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
765 #return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
766 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
766 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
767
767
768 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
768 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
769
769
770 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
770 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
771 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
771 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
772 return val
772 return val
773
773
774
774
775 y = spc
775 y = spc
776
776
777 # estimate starting values from the data
777 # estimate starting values from the data
778 a1 = A1
778 a1 = A1
779 b1 = B1
779 b1 = B1
780 c1 = C1#numpy.std(spc)
780 c1 = C1#numpy.std(spc)
781
781
782 a2 = A2#y.max()
782 a2 = A2#y.max()
783 b2 = B2#x[numpy.argmax(y)]
783 b2 = B2#x[numpy.argmax(y)]
784 c2 = C2#numpy.std(spc)
784 c2 = C2#numpy.std(spc)
785 d = D
785 d = D
786
786
787 # define a least squares function to optimize
787 # define a least squares function to optimize
788 def minfunc(params):
788 def minfunc(params):
789 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
789 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
790
790
791 # fit
791 # fit
792 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
792 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
793
793
794 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]
794 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]
795
795
796 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
796 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
797
797
798 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
798 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
799 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
799 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
800 return val
800 return val
801
801
802
802
803 y = spc
803 y = spc
804
804
805 # estimate starting values from the data
805 # estimate starting values from the data
806 a1 = A1
806 a1 = A1
807 b1 = B1
807 b1 = B1
808 c1 = C1#numpy.std(spc)
808 c1 = C1#numpy.std(spc)
809
809
810 a2 = A2#y.max()
810 a2 = A2#y.max()
811 b2 = B2#x[numpy.argmax(y)]
811 b2 = B2#x[numpy.argmax(y)]
812 c2 = C2#numpy.std(spc)
812 c2 = C2#numpy.std(spc)
813 d = D
813 d = D
814
814
815 # fit
815 # fit
816
816
817 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
817 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
818
818
819 error = numpy.sqrt(numpy.diag(pcov))
819 error = numpy.sqrt(numpy.diag(pcov))
820
820
821 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]
821 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]
822
822
823 def run(self, dataOut):
823 def run(self, dataOut):
824
824
825 pwcode = 1
825 pwcode = 1
826
826
827 if dataOut.flagDecodeData:
827 if dataOut.flagDecodeData:
828 pwcode = numpy.sum(dataOut.code[0]**2)
828 pwcode = numpy.sum(dataOut.code[0]**2)
829 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
829 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
830 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
830 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
831 factor = normFactor
831 factor = normFactor
832 z = dataOut.data_spc / factor
832 z = dataOut.data_spc / factor
833 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
833 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
834 dataOut.power = numpy.average(z, axis=1)
834 dataOut.power = numpy.average(z, axis=1)
835 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
835 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
836
836
837
837
838 x = dataOut.getVelRange(0)
838 x = dataOut.getVelRange(0)
839
839
840 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
840 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
841 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
841 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
842
842
843 dataOut.VelRange = x
843 dataOut.VelRange = x
844
844
845
845
846 l1=range(22,36)
846 l1=range(22,36)
847 l2=range(58,99)
847 l2=range(58,99)
848
848
849 for hei in itertools.chain(l1, l2):
849 for hei in itertools.chain(l1, l2):
850
850
851 try:
851 try:
852 spc = dataOut.data_spc[0,:,hei]
852 spc = dataOut.data_spc[0,:,hei]
853
853
854 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
854 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
855
855
856 spc_diff = spc - spc_fit
856 spc_diff = spc - spc_fit
857 spc_diff[spc_diff < 0] = 0
857 spc_diff[spc_diff < 0] = 0
858
858
859 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
859 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
860
860
861 D = (D1+D2)
861 D = (D1+D2)
862
862
863 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)
863 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)
864 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
864 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
865
865
866 except:
866 except:
867 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
867 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
868 pass
868 pass
869
869
870 return dataOut
870 return dataOut
871
871
872 class PrecipitationProc(Operation):
872 class PrecipitationProc(Operation):
873
873
874 '''
874 '''
875 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
875 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
876
876
877 Input:
877 Input:
878 self.dataOut.data_pre : SelfSpectra
878 self.dataOut.data_pre : SelfSpectra
879
879
880 Output:
880 Output:
881
881
882 self.dataOut.data_output : Reflectivity factor, rainfall Rate
882 self.dataOut.data_output : Reflectivity factor, rainfall Rate
883
883
884
884
885 Parameters affected:
885 Parameters affected:
886 '''
886 '''
887
887
888 def __init__(self):
888 def __init__(self):
889 Operation.__init__(self)
889 Operation.__init__(self)
890 self.i=0
890 self.i=0
891
891
892 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
892 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
893 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350, SNRdBlimit=-30,
893 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350, SNRdBlimit=-30,
894 channel=None):
894 channel=None):
895
895
896 # print ('Entering PrecepitationProc ... ')
896 # print ('Entering PrecepitationProc ... ')
897
897
898 if radar == "MIRA35C" :
898 if radar == "MIRA35C" :
899
899
900 self.spc = dataOut.data_pre[0].copy()
900 self.spc = dataOut.data_pre[0].copy()
901 self.Num_Hei = self.spc.shape[2]
901 self.Num_Hei = self.spc.shape[2]
902 self.Num_Bin = self.spc.shape[1]
902 self.Num_Bin = self.spc.shape[1]
903 self.Num_Chn = self.spc.shape[0]
903 self.Num_Chn = self.spc.shape[0]
904 Ze = self.dBZeMODE2(dataOut)
904 Ze = self.dBZeMODE2(dataOut)
905
905
906 else:
906 else:
907
907
908 self.spc = dataOut.data_pre[0].copy()
908 self.spc = dataOut.data_pre[0].copy()
909
909
910 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
910 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
911 self.spc[:,:,0:7]= numpy.NaN
911 self.spc[:,:,0:7]= numpy.NaN
912
912
913 self.Num_Hei = self.spc.shape[2]
913 self.Num_Hei = self.spc.shape[2]
914 self.Num_Bin = self.spc.shape[1]
914 self.Num_Bin = self.spc.shape[1]
915 self.Num_Chn = self.spc.shape[0]
915 self.Num_Chn = self.spc.shape[0]
916
916
917 VelRange = dataOut.spc_range[2]
917 VelRange = dataOut.spc_range[2]
918
918
919 ''' Se obtiene la constante del RADAR '''
919 ''' Se obtiene la constante del RADAR '''
920
920
921 self.Pt = Pt
921 self.Pt = Pt
922 self.Gt = Gt
922 self.Gt = Gt
923 self.Gr = Gr
923 self.Gr = Gr
924 self.Lambda = Lambda
924 self.Lambda = Lambda
925 self.aL = aL
925 self.aL = aL
926 self.tauW = tauW
926 self.tauW = tauW
927 self.ThetaT = ThetaT
927 self.ThetaT = ThetaT
928 self.ThetaR = ThetaR
928 self.ThetaR = ThetaR
929 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
929 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
930 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
930 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
931 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
931 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
932
932
933 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
933 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
934 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
934 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
935 RadarConstant = 10e-26 * Numerator / Denominator #
935 RadarConstant = 10e-26 * Numerator / Denominator #
936 ExpConstant = 10**(40/10) #Constante Experimental
936 ExpConstant = 10**(40/10) #Constante Experimental
937
937
938 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
938 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
939 for i in range(self.Num_Chn):
939 for i in range(self.Num_Chn):
940 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
940 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
941 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
941 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
942
942
943 if channel is None:
943 if channel is None:
944 SPCmean = numpy.mean(SignalPower, 0)
944 SPCmean = numpy.mean(SignalPower, 0)
945 else:
945 else:
946 SPCmean = SignalPower[channel]
946 SPCmean = SignalPower[channel]
947 Pr = SPCmean[:,:]/dataOut.normFactor
947 Pr = SPCmean[:,:]/dataOut.normFactor
948
948
949 # Declaring auxiliary variables
949 # Declaring auxiliary variables
950 Range = dataOut.heightList*1000. #Range in m
950 Range = dataOut.heightList*1000. #Range in m
951 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
951 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
952 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
952 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
953 zMtrx = rMtrx+Altitude
953 zMtrx = rMtrx+Altitude
954 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
954 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
955 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
955 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
956
956
957 # height dependence to air density Foote and Du Toit (1969)
957 # height dependence to air density Foote and Du Toit (1969)
958 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
958 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
959 VMtrx = VelMtrx / delv_z #Normalized velocity
959 VMtrx = VelMtrx / delv_z #Normalized velocity
960 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
960 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
961 # Diameter is related to the fall speed of falling drops
961 # Diameter is related to the fall speed of falling drops
962 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
962 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
963 # Only valid for D>= 0.16 mm
963 # Only valid for D>= 0.16 mm
964 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
964 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
965
965
966 #Calculate Radar Reflectivity ETAn
966 #Calculate Radar Reflectivity ETAn
967 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
967 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
968 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
968 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
969 # Radar Cross Section
969 # Radar Cross Section
970 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
970 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
971 # Drop Size Distribution
971 # Drop Size Distribution
972 DSD = ETAn / sigmaD
972 DSD = ETAn / sigmaD
973 # Equivalente Reflectivy
973 # Equivalente Reflectivy
974 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
974 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
975 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
975 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
976 # RainFall Rate
976 # RainFall Rate
977 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
977 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
978
978
979 # Censoring the data
979 # Censoring the data
980 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
980 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
981 SNRth = 10**(SNRdBlimit/10) #-30dB
981 SNRth = 10**(SNRdBlimit/10) #-30dB
982 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
982 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
983 W = numpy.nanmean(dataOut.data_dop,0)
983 W = numpy.nanmean(dataOut.data_dop,0)
984 W[novalid] = numpy.NaN
984 W[novalid] = numpy.NaN
985 Ze_org[novalid] = numpy.NaN
985 Ze_org[novalid] = numpy.NaN
986 RR[novalid] = numpy.NaN
986 RR[novalid] = numpy.NaN
987
987
988 dataOut.data_output = RR[8]
988 dataOut.data_output = RR[8]
989 dataOut.data_param = numpy.ones([3,self.Num_Hei])
989 dataOut.data_param = numpy.ones([3,self.Num_Hei])
990 dataOut.channelList = [0,1,2]
990 dataOut.channelList = [0,1,2]
991
991
992 dataOut.data_param[0]=10*numpy.log10(Ze_org)
992 dataOut.data_param[0]=10*numpy.log10(Ze_org)
993 dataOut.data_param[1]=-W
993 dataOut.data_param[1]=-W
994 dataOut.data_param[2]=RR
994 dataOut.data_param[2]=RR
995
995
996 # print ('Leaving PrecepitationProc ... ')
996 # print ('Leaving PrecepitationProc ... ')
997 return dataOut
997 return dataOut
998
998
999 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
999 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
1000
1000
1001 NPW = dataOut.NPW
1001 NPW = dataOut.NPW
1002 COFA = dataOut.COFA
1002 COFA = dataOut.COFA
1003
1003
1004 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
1004 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
1005 RadarConst = dataOut.RadarConst
1005 RadarConst = dataOut.RadarConst
1006 #frequency = 34.85*10**9
1006 #frequency = 34.85*10**9
1007
1007
1008 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1008 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1009 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
1009 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
1010
1010
1011 ETA = numpy.sum(SNR,1)
1011 ETA = numpy.sum(SNR,1)
1012
1012
1013 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
1013 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
1014
1014
1015 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
1015 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
1016
1016
1017 for r in range(self.Num_Hei):
1017 for r in range(self.Num_Hei):
1018
1018
1019 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
1019 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
1020 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
1020 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
1021
1021
1022 return Ze
1022 return Ze
1023
1023
1024 # def GetRadarConstant(self):
1024 # def GetRadarConstant(self):
1025 #
1025 #
1026 # """
1026 # """
1027 # Constants:
1027 # Constants:
1028 #
1028 #
1029 # Pt: Transmission Power dB 5kW 5000
1029 # Pt: Transmission Power dB 5kW 5000
1030 # Gt: Transmission Gain dB 24.7 dB 295.1209
1030 # Gt: Transmission Gain dB 24.7 dB 295.1209
1031 # Gr: Reception Gain dB 18.5 dB 70.7945
1031 # Gr: Reception Gain dB 18.5 dB 70.7945
1032 # Lambda: Wavelenght m 0.6741 m 0.6741
1032 # Lambda: Wavelenght m 0.6741 m 0.6741
1033 # aL: Attenuation loses dB 4dB 2.5118
1033 # aL: Attenuation loses dB 4dB 2.5118
1034 # tauW: Width of transmission pulse s 4us 4e-6
1034 # tauW: Width of transmission pulse s 4us 4e-6
1035 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
1035 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
1036 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
1036 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
1037 #
1037 #
1038 # """
1038 # """
1039 #
1039 #
1040 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1040 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1041 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1041 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1042 # RadarConstant = Numerator / Denominator
1042 # RadarConstant = Numerator / Denominator
1043 #
1043 #
1044 # return RadarConstant
1044 # return RadarConstant
1045
1045
1046
1046
1047 class FullSpectralAnalysis(Operation):
1047 class FullSpectralAnalysis(Operation):
1048
1048
1049 """
1049 """
1050 Function that implements Full Spectral Analysis technique.
1050 Function that implements Full Spectral Analysis technique.
1051
1051
1052 Input:
1052 Input:
1053 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
1053 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
1054 self.dataOut.groupList : Pairlist of channels
1054 self.dataOut.groupList : Pairlist of channels
1055 self.dataOut.ChanDist : Physical distance between receivers
1055 self.dataOut.ChanDist : Physical distance between receivers
1056
1056
1057
1057
1058 Output:
1058 Output:
1059
1059
1060 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
1060 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
1061
1061
1062
1062
1063 Parameters affected: Winds, height range, SNR
1063 Parameters affected: Winds, height range, SNR
1064
1064
1065 """
1065 """
1066 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
1066 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
1067 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
1067 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
1068
1068
1069 spc = dataOut.data_pre[0].copy()
1069 spc = dataOut.data_pre[0].copy()
1070 cspc = dataOut.data_pre[1]
1070 cspc = dataOut.data_pre[1]
1071 nHeights = spc.shape[2]
1071 nHeights = spc.shape[2]
1072
1072
1073 # first_height = 0.75 #km (ref: data header 20170822)
1073 # first_height = 0.75 #km (ref: data header 20170822)
1074 # resolution_height = 0.075 #km
1074 # resolution_height = 0.075 #km
1075 '''
1075 '''
1076 finding height range. check this when radar parameters are changed!
1076 finding height range. check this when radar parameters are changed!
1077 '''
1077 '''
1078 if maxheight is not None:
1078 if maxheight is not None:
1079 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
1079 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
1080 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
1080 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
1081 else:
1081 else:
1082 range_max = nHeights
1082 range_max = nHeights
1083 if minheight is not None:
1083 if minheight is not None:
1084 # range_min = int((minheight - first_height) / resolution_height) # theoretical
1084 # range_min = int((minheight - first_height) / resolution_height) # theoretical
1085 range_min = int(13.26 * minheight - 5) # empirical, works better
1085 range_min = int(13.26 * minheight - 5) # empirical, works better
1086 if range_min < 0:
1086 if range_min < 0:
1087 range_min = 0
1087 range_min = 0
1088 else:
1088 else:
1089 range_min = 0
1089 range_min = 0
1090
1090
1091 pairsList = dataOut.groupList
1091 pairsList = dataOut.groupList
1092 if dataOut.ChanDist is not None :
1092 if dataOut.ChanDist is not None :
1093 ChanDist = dataOut.ChanDist
1093 ChanDist = dataOut.ChanDist
1094 else:
1094 else:
1095 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
1095 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
1096
1096
1097 # 4 variables: zonal, meridional, vertical, and average SNR
1097 # 4 variables: zonal, meridional, vertical, and average SNR
1098 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
1098 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
1099 velocityX = numpy.zeros([nHeights]) * numpy.NaN
1099 velocityX = numpy.zeros([nHeights]) * numpy.NaN
1100 velocityY = numpy.zeros([nHeights]) * numpy.NaN
1100 velocityY = numpy.zeros([nHeights]) * numpy.NaN
1101 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
1101 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
1102
1102
1103 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
1103 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
1104
1104
1105 '''***********************************************WIND ESTIMATION**************************************'''
1105 '''***********************************************WIND ESTIMATION**************************************'''
1106 for Height in range(nHeights):
1106 for Height in range(nHeights):
1107
1107
1108 if Height >= range_min and Height < range_max:
1108 if Height >= range_min and Height < range_max:
1109 # error_code will be useful in future analysis
1109 # error_code will be useful in future analysis
1110 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
1110 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
1111 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
1111 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
1112
1112
1113 if abs(Vzon) < 100. and abs(Vmer) < 100.:
1113 if abs(Vzon) < 100. and abs(Vmer) < 100.:
1114 velocityX[Height] = Vzon
1114 velocityX[Height] = Vzon
1115 velocityY[Height] = -Vmer
1115 velocityY[Height] = -Vmer
1116 velocityZ[Height] = Vver
1116 velocityZ[Height] = Vver
1117
1117
1118 # Censoring data with SNR threshold
1118 # Censoring data with SNR threshold
1119 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
1119 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
1120
1120
1121 data_param[0] = velocityX
1121 data_param[0] = velocityX
1122 data_param[1] = velocityY
1122 data_param[1] = velocityY
1123 data_param[2] = velocityZ
1123 data_param[2] = velocityZ
1124 data_param[3] = dbSNR
1124 data_param[3] = dbSNR
1125 dataOut.data_param = data_param
1125 dataOut.data_param = data_param
1126 return dataOut
1126 return dataOut
1127
1127
1128 def moving_average(self,x, N=2):
1128 def moving_average(self,x, N=2):
1129 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
1129 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
1130 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1130 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1131
1131
1132 def gaus(self,xSamples,Amp,Mu,Sigma):
1132 def gaus(self,xSamples,Amp,Mu,Sigma):
1133 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
1133 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
1134
1134
1135 def Moments(self, ySamples, xSamples):
1135 def Moments(self, ySamples, xSamples):
1136 Power = numpy.nanmean(ySamples) # Power, 0th Moment
1136 Power = numpy.nanmean(ySamples) # Power, 0th Moment
1137 yNorm = ySamples / numpy.nansum(ySamples)
1137 yNorm = ySamples / numpy.nansum(ySamples)
1138 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
1138 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
1139 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
1139 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
1140 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
1140 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
1141 return numpy.array([Power,RadVel,StdDev])
1141 return numpy.array([Power,RadVel,StdDev])
1142
1142
1143 def StopWindEstimation(self, error_code):
1143 def StopWindEstimation(self, error_code):
1144 Vzon = numpy.NaN
1144 Vzon = numpy.NaN
1145 Vmer = numpy.NaN
1145 Vmer = numpy.NaN
1146 Vver = numpy.NaN
1146 Vver = numpy.NaN
1147 return Vzon, Vmer, Vver, error_code
1147 return Vzon, Vmer, Vver, error_code
1148
1148
1149 def AntiAliasing(self, interval, maxstep):
1149 def AntiAliasing(self, interval, maxstep):
1150 """
1150 """
1151 function to prevent errors from aliased values when computing phaseslope
1151 function to prevent errors from aliased values when computing phaseslope
1152 """
1152 """
1153 antialiased = numpy.zeros(len(interval))
1153 antialiased = numpy.zeros(len(interval))
1154 copyinterval = interval.copy()
1154 copyinterval = interval.copy()
1155
1155
1156 antialiased[0] = copyinterval[0]
1156 antialiased[0] = copyinterval[0]
1157
1157
1158 for i in range(1,len(antialiased)):
1158 for i in range(1,len(antialiased)):
1159 step = interval[i] - interval[i-1]
1159 step = interval[i] - interval[i-1]
1160 if step > maxstep:
1160 if step > maxstep:
1161 copyinterval -= 2*numpy.pi
1161 copyinterval -= 2*numpy.pi
1162 antialiased[i] = copyinterval[i]
1162 antialiased[i] = copyinterval[i]
1163 elif step < maxstep*(-1):
1163 elif step < maxstep*(-1):
1164 copyinterval += 2*numpy.pi
1164 copyinterval += 2*numpy.pi
1165 antialiased[i] = copyinterval[i]
1165 antialiased[i] = copyinterval[i]
1166 else:
1166 else:
1167 antialiased[i] = copyinterval[i].copy()
1167 antialiased[i] = copyinterval[i].copy()
1168
1168
1169 return antialiased
1169 return antialiased
1170
1170
1171 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1171 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1172 """
1172 """
1173 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1173 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1174 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1174 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1175
1175
1176 Input:
1176 Input:
1177 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1177 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1178 pairsList : Pairlist of channels
1178 pairsList : Pairlist of channels
1179 ChanDist : array of xi_ij and eta_ij
1179 ChanDist : array of xi_ij and eta_ij
1180 Height : height at which data is processed
1180 Height : height at which data is processed
1181 noise : noise in [channels] format for specific height
1181 noise : noise in [channels] format for specific height
1182 Abbsisarange : range of the frequencies or velocities
1182 Abbsisarange : range of the frequencies or velocities
1183 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1183 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1184
1184
1185 Output:
1185 Output:
1186 Vzon, Vmer, Vver : wind velocities
1186 Vzon, Vmer, Vver : wind velocities
1187 error_code : int that states where code is terminated
1187 error_code : int that states where code is terminated
1188
1188
1189 0 : no error detected
1189 0 : no error detected
1190 1 : Gaussian of mean spc exceeds widthlimit
1190 1 : Gaussian of mean spc exceeds widthlimit
1191 2 : no Gaussian of mean spc found
1191 2 : no Gaussian of mean spc found
1192 3 : SNR to low or velocity to high -> prec. e.g.
1192 3 : SNR to low or velocity to high -> prec. e.g.
1193 4 : at least one Gaussian of cspc exceeds widthlimit
1193 4 : at least one Gaussian of cspc exceeds widthlimit
1194 5 : zero out of three cspc Gaussian fits converged
1194 5 : zero out of three cspc Gaussian fits converged
1195 6 : phase slope fit could not be found
1195 6 : phase slope fit could not be found
1196 7 : arrays used to fit phase have different length
1196 7 : arrays used to fit phase have different length
1197 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1197 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1198
1198
1199 """
1199 """
1200
1200
1201 error_code = 0
1201 error_code = 0
1202
1202
1203 nChan = spc.shape[0]
1203 nChan = spc.shape[0]
1204 nProf = spc.shape[1]
1204 nProf = spc.shape[1]
1205 nPair = cspc.shape[0]
1205 nPair = cspc.shape[0]
1206
1206
1207 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1207 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1208 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1208 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1209 phase = numpy.zeros([nPair, nProf]) # phase between channels
1209 phase = numpy.zeros([nPair, nProf]) # phase between channels
1210 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1210 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1211 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1211 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1212 xFrec = AbbsisaRange[0][:-1] # frequency range
1212 xFrec = AbbsisaRange[0][:-1] # frequency range
1213 xVel = AbbsisaRange[2][:-1] # velocity range
1213 xVel = AbbsisaRange[2][:-1] # velocity range
1214 xSamples = xFrec # the frequency range is taken
1214 xSamples = xFrec # the frequency range is taken
1215 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1215 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1216
1216
1217 # only consider velocities with in NegativeLimit and PositiveLimit
1217 # only consider velocities with in NegativeLimit and PositiveLimit
1218 if (NegativeLimit is None):
1218 if (NegativeLimit is None):
1219 NegativeLimit = numpy.min(xVel)
1219 NegativeLimit = numpy.min(xVel)
1220 if (PositiveLimit is None):
1220 if (PositiveLimit is None):
1221 PositiveLimit = numpy.max(xVel)
1221 PositiveLimit = numpy.max(xVel)
1222 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1222 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1223 xSamples_zoom = xSamples[xvalid]
1223 xSamples_zoom = xSamples[xvalid]
1224
1224
1225 '''Getting Eij and Nij'''
1225 '''Getting Eij and Nij'''
1226 Xi01, Xi02, Xi12 = ChanDist[:,0]
1226 Xi01, Xi02, Xi12 = ChanDist[:,0]
1227 Eta01, Eta02, Eta12 = ChanDist[:,1]
1227 Eta01, Eta02, Eta12 = ChanDist[:,1]
1228
1228
1229 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1229 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1230 widthlimit = 10
1230 widthlimit = 10
1231 '''************************* SPC is normalized ********************************'''
1231 '''************************* SPC is normalized ********************************'''
1232 spc_norm = spc.copy()
1232 spc_norm = spc.copy()
1233 # For each channel
1233 # For each channel
1234 for i in range(nChan):
1234 for i in range(nChan):
1235 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1235 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1236 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1236 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1237
1237
1238 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1238 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1239
1239
1240 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1240 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1241 you only fit the curve and don't need the absolute value of height for calculation,
1241 you only fit the curve and don't need the absolute value of height for calculation,
1242 only for estimation of width. for normalization of cross spectra, you need initial,
1242 only for estimation of width. for normalization of cross spectra, you need initial,
1243 unnormalized self-spectra With noise.
1243 unnormalized self-spectra With noise.
1244
1244
1245 Technically, you don't even need to normalize the self-spectra, as you only need the
1245 Technically, you don't even need to normalize the self-spectra, as you only need the
1246 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1246 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1247 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1247 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1248 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1248 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1249 """
1249 """
1250 # initial conditions
1250 # initial conditions
1251 popt = [1e-10,0,1e-10]
1251 popt = [1e-10,0,1e-10]
1252 # Spectra average
1252 # Spectra average
1253 SPCMean = numpy.average(SPC_Samples,0)
1253 SPCMean = numpy.average(SPC_Samples,0)
1254 # Moments in frequency
1254 # Moments in frequency
1255 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1255 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1256
1256
1257 # Gauss Fit SPC in frequency domain
1257 # Gauss Fit SPC in frequency domain
1258 if dbSNR > SNRlimit: # only if SNR > SNRth
1258 if dbSNR > SNRlimit: # only if SNR > SNRth
1259 try:
1259 try:
1260 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1260 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1261 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1261 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1262 return self.StopWindEstimation(error_code = 1)
1262 return self.StopWindEstimation(error_code = 1)
1263 FitGauss = self.gaus(xSamples_zoom,*popt)
1263 FitGauss = self.gaus(xSamples_zoom,*popt)
1264 except :#RuntimeError:
1264 except :#RuntimeError:
1265 return self.StopWindEstimation(error_code = 2)
1265 return self.StopWindEstimation(error_code = 2)
1266 else:
1266 else:
1267 return self.StopWindEstimation(error_code = 3)
1267 return self.StopWindEstimation(error_code = 3)
1268
1268
1269 '''***************************** CSPC Normalization *************************
1269 '''***************************** CSPC Normalization *************************
1270 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1270 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1271 influence the norm which is not desired. First, a range is identified where the
1271 influence the norm which is not desired. First, a range is identified where the
1272 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1272 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1273 around it gets cut off and values replaced by mean determined by the boundary
1273 around it gets cut off and values replaced by mean determined by the boundary
1274 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1274 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1275
1275
1276 The sums are then added and multiplied by range/datapoints, because you need
1276 The sums are then added and multiplied by range/datapoints, because you need
1277 an integral and not a sum for normalization.
1277 an integral and not a sum for normalization.
1278
1278
1279 A norm is found according to Briggs 92.
1279 A norm is found according to Briggs 92.
1280 '''
1280 '''
1281 # for each pair
1281 # for each pair
1282 for i in range(nPair):
1282 for i in range(nPair):
1283 cspc_norm = cspc[i,:].copy()
1283 cspc_norm = cspc[i,:].copy()
1284 chan_index0 = pairsList[i][0]
1284 chan_index0 = pairsList[i][0]
1285 chan_index1 = pairsList[i][1]
1285 chan_index1 = pairsList[i][1]
1286 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1286 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1287 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1287 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1288
1288
1289 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1289 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1290 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1290 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1291 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1291 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1292
1292
1293 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1293 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1294 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1294 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1295
1295
1296 '''*******************************FIT GAUSS CSPC************************************'''
1296 '''*******************************FIT GAUSS CSPC************************************'''
1297 try:
1297 try:
1298 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1298 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1299 if popt01[2] > widthlimit: # CONDITION
1299 if popt01[2] > widthlimit: # CONDITION
1300 return self.StopWindEstimation(error_code = 4)
1300 return self.StopWindEstimation(error_code = 4)
1301 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1301 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1302 if popt02[2] > widthlimit: # CONDITION
1302 if popt02[2] > widthlimit: # CONDITION
1303 return self.StopWindEstimation(error_code = 4)
1303 return self.StopWindEstimation(error_code = 4)
1304 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1304 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1305 if popt12[2] > widthlimit: # CONDITION
1305 if popt12[2] > widthlimit: # CONDITION
1306 return self.StopWindEstimation(error_code = 4)
1306 return self.StopWindEstimation(error_code = 4)
1307
1307
1308 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1308 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1309 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1309 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1310 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1310 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1311 except:
1311 except:
1312 return self.StopWindEstimation(error_code = 5)
1312 return self.StopWindEstimation(error_code = 5)
1313
1313
1314
1314
1315 '''************* Getting Fij ***************'''
1315 '''************* Getting Fij ***************'''
1316 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1316 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1317 GaussCenter = popt[1]
1317 GaussCenter = popt[1]
1318 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1318 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1319 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1319 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1320
1320
1321 # Point where e^-1 is located in the gaussian
1321 # Point where e^-1 is located in the gaussian
1322 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1322 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1323 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1323 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1324 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1324 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1325 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1325 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1326
1326
1327 '''********** Taking frequency ranges from mean SPCs **********'''
1327 '''********** Taking frequency ranges from mean SPCs **********'''
1328 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1328 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1329 Range = numpy.empty(2)
1329 Range = numpy.empty(2)
1330 Range[0] = GaussCenter - GauWidth
1330 Range[0] = GaussCenter - GauWidth
1331 Range[1] = GaussCenter + GauWidth
1331 Range[1] = GaussCenter + GauWidth
1332 # Point in x-axis where the bandwidth is located (min:max)
1332 # Point in x-axis where the bandwidth is located (min:max)
1333 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1333 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1334 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1334 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1335 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1335 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1336 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1336 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1337 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1337 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1338 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1338 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1339
1339
1340 '''************************** Getting Phase Slope ***************************'''
1340 '''************************** Getting Phase Slope ***************************'''
1341 for i in range(nPair):
1341 for i in range(nPair):
1342 if len(FrecRange) > 5:
1342 if len(FrecRange) > 5:
1343 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1343 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1344 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1344 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1345 if len(FrecRange) == len(PhaseRange):
1345 if len(FrecRange) == len(PhaseRange):
1346 try:
1346 try:
1347 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1347 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1348 PhaseSlope[i] = slope
1348 PhaseSlope[i] = slope
1349 PhaseInter[i] = intercept
1349 PhaseInter[i] = intercept
1350 except:
1350 except:
1351 return self.StopWindEstimation(error_code = 6)
1351 return self.StopWindEstimation(error_code = 6)
1352 else:
1352 else:
1353 return self.StopWindEstimation(error_code = 7)
1353 return self.StopWindEstimation(error_code = 7)
1354 else:
1354 else:
1355 return self.StopWindEstimation(error_code = 8)
1355 return self.StopWindEstimation(error_code = 8)
1356
1356
1357 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1357 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1358
1358
1359 '''Getting constant C'''
1359 '''Getting constant C'''
1360 cC=(Fij*numpy.pi)**2
1360 cC=(Fij*numpy.pi)**2
1361
1361
1362 '''****** Getting constants F and G ******'''
1362 '''****** Getting constants F and G ******'''
1363 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1363 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1364 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1364 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1365 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1365 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1366 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1366 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1367 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1367 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1368 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1368 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1369 MijResults = numpy.array([MijResult1, MijResult2])
1369 MijResults = numpy.array([MijResult1, MijResult2])
1370 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1370 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1371
1371
1372 '''****** Getting constants A, B and H ******'''
1372 '''****** Getting constants A, B and H ******'''
1373 W01 = numpy.nanmax( FitGauss01 )
1373 W01 = numpy.nanmax( FitGauss01 )
1374 W02 = numpy.nanmax( FitGauss02 )
1374 W02 = numpy.nanmax( FitGauss02 )
1375 W12 = numpy.nanmax( FitGauss12 )
1375 W12 = numpy.nanmax( FitGauss12 )
1376
1376
1377 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1377 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1378 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1378 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1379 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1379 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1380 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1380 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1381
1381
1382 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1382 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1383 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1383 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1384
1384
1385 VxVy = numpy.array([[cA,cH],[cH,cB]])
1385 VxVy = numpy.array([[cA,cH],[cH,cB]])
1386 VxVyResults = numpy.array([-cF,-cG])
1386 VxVyResults = numpy.array([-cF,-cG])
1387 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1387 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1388 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1388 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1389 error_code = 0
1389 error_code = 0
1390
1390
1391 return Vzon, Vmer, Vver, error_code
1391 return Vzon, Vmer, Vver, error_code
1392
1392
1393 class SpectralMoments(Operation):
1393 class SpectralMoments(Operation):
1394
1394
1395 '''
1395 '''
1396 Function SpectralMoments()
1396 Function SpectralMoments()
1397
1397
1398 Calculates moments (power, mean, standard deviation) and SNR of the signal
1398 Calculates moments (power, mean, standard deviation) and SNR of the signal
1399
1399
1400 Type of dataIn: Spectra
1400 Type of dataIn: Spectra
1401
1401
1402 Configuration Parameters:
1402 Configuration Parameters:
1403
1403
1404 dirCosx : Cosine director in X axis
1404 dirCosx : Cosine director in X axis
1405 dirCosy : Cosine director in Y axis
1405 dirCosy : Cosine director in Y axis
1406
1406
1407 elevation :
1407 elevation :
1408 azimuth :
1408 azimuth :
1409
1409
1410 Input:
1410 Input:
1411 channelList : simple channel list to select e.g. [2,3,7]
1411 channelList : simple channel list to select e.g. [2,3,7]
1412 self.dataOut.data_pre : Spectral data
1412 self.dataOut.data_pre : Spectral data
1413 self.dataOut.abscissaList : List of frequencies
1413 self.dataOut.abscissaList : List of frequencies
1414 self.dataOut.noise : Noise level per channel
1414 self.dataOut.noise : Noise level per channel
1415
1415
1416 Affected:
1416 Affected:
1417 self.dataOut.moments : Parameters per channel
1417 self.dataOut.moments : Parameters per channel
1418 self.dataOut.data_snr : SNR per channel
1418 self.dataOut.data_snr : SNR per channel
1419
1419
1420 '''
1420 '''
1421
1421
1422 def run(self, dataOut, proc_type=0):
1422 def run(self, dataOut, proc_type=0):
1423
1423
1424 absc = dataOut.abscissaList[:-1]
1424 absc = dataOut.abscissaList[:-1]
1425 #noise = dataOut.noise
1425 #noise = dataOut.noise
1426 nChannel = dataOut.data_pre[0].shape[0]
1426 nChannel = dataOut.data_pre[0].shape[0]
1427 nHei = dataOut.data_pre[0].shape[2]
1427 nHei = dataOut.data_pre[0].shape[2]
1428 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
1428 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
1429
1429
1430 if proc_type == 1:
1430 if proc_type == 1:
1431 fwindow = numpy.zeros(absc.size) + 1
1431 fwindow = numpy.zeros(absc.size) + 1
1432 b=64
1432 b=64
1433 #b=16
1433 #b=16
1434 fwindow[0:absc.size//2 - b] = 0
1434 fwindow[0:absc.size//2 - b] = 0
1435 fwindow[absc.size//2 + b:] = 0
1435 fwindow[absc.size//2 + b:] = 0
1436 type1 = 1 # moments calculation
1436 type1 = 1 # moments calculation
1437 nProfiles = dataOut.nProfiles
1437 nProfiles = dataOut.nProfiles
1438 nCohInt = dataOut.nCohInt
1438 nCohInt = dataOut.nCohInt
1439 nIncohInt = dataOut.nIncohInt
1439 nIncohInt = dataOut.nIncohInt
1440 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
1440 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
1441 N = numpy.array(M / nIncohInt,dtype='float32')
1441 N = numpy.array(M / nIncohInt,dtype='float32')
1442 data = dataOut.data_pre[0] * N
1442 data = dataOut.data_pre[0] * N
1443 #noise = dataOut.noise * N
1443 #noise = dataOut.noise * N
1444 noise = numpy.zeros(nChannel)
1444 noise = numpy.zeros(nChannel)
1445 for ind in range(nChannel):
1445 for ind in range(nChannel):
1446 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
1446 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
1447 smooth=3
1447 smooth=3
1448 else:
1448 else:
1449 data = dataOut.data_pre[0]
1449 data = dataOut.data_pre[0]
1450 noise = dataOut.noise
1450 noise = dataOut.noise
1451 fwindow = None
1451 fwindow = None
1452 type1 = 0
1452 type1 = 0
1453 nIncohInt = None
1453 nIncohInt = None
1454 smooth=None
1454 smooth=None
1455
1455
1456 for ind in range(nChannel):
1456 for ind in range(nChannel):
1457 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow)
1457 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow)
1458
1458
1459 if proc_type == 1:
1459 if proc_type == 1:
1460 dataOut.moments = data_param[:,1:,:]
1460 dataOut.moments = data_param[:,1:,:]
1461 #dataOut.data_dop = data_param[:,0]
1461 #dataOut.data_dop = data_param[:,0]
1462 dataOut.data_dop = data_param[:,2]
1462 dataOut.data_dop = data_param[:,2]
1463 dataOut.data_width = data_param[:,1]
1463 dataOut.data_width = data_param[:,1]
1464 # dataOut.data_snr = data_param[:,2]
1464 # dataOut.data_snr = data_param[:,2]
1465 dataOut.data_snr = data_param[:,0]
1465 dataOut.data_snr = data_param[:,0]
1466 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
1466 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
1467 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
1467 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
1468
1468
1469 else:
1469 else:
1470 dataOut.moments = data_param[:,1:,:]
1470 dataOut.moments = data_param[:,1:,:]
1471 dataOut.data_snr = data_param[:,0]
1471 dataOut.data_snr = data_param[:,0]
1472 dataOut.data_pow = data_param[:,1]
1472 dataOut.data_pow = data_param[:,1]
1473 dataOut.data_dop = data_param[:,2]
1473 dataOut.data_dop = data_param[:,2]
1474 dataOut.data_width = data_param[:,3]
1474 dataOut.data_width = data_param[:,3]
1475 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
1475 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
1476
1476
1477 return dataOut
1477 return dataOut
1478
1478
1479 def __calculateMoments(self, oldspec, oldfreq, n0,
1479 def __calculateMoments(self, oldspec, oldfreq, n0,
1480 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1480 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1481
1481
1482 def __GAUSSWINFIT1(A, flagPDER=0):
1482 def __GAUSSWINFIT1(A, flagPDER=0):
1483 nonlocal truex, xvalid
1483 nonlocal truex, xvalid
1484 nparams = 4
1484 nparams = 4
1485 M=truex.size
1485 M=truex.size
1486 mm=numpy.arange(M,dtype='f4')
1486 mm=numpy.arange(M,dtype='f4')
1487 delta = numpy.zeros(M,dtype='f4')
1487 delta = numpy.zeros(M,dtype='f4')
1488 delta[0] = 1.0
1488 delta[0] = 1.0
1489 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
1489 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
1490 jj = -1j
1490 jj = -1j
1491 #if self.winauto is None: self.winauto = (1.0 - mm/M)
1491 #if self.winauto is None: self.winauto = (1.0 - mm/M)
1492 winauto = (1.0 - mm/M)
1492 winauto = (1.0 - mm/M)
1493 winauto = winauto/winauto.max() # Normalized to 1
1493 winauto = winauto/winauto.max() # Normalized to 1
1494 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
1494 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
1495 A[0] = numpy.abs(A[0])
1495 A[0] = numpy.abs(A[0])
1496 A[2] = numpy.abs(A[2])
1496 A[2] = numpy.abs(A[2])
1497 A[3] = numpy.abs(A[3])
1497 A[3] = numpy.abs(A[3])
1498 pi=numpy.array([numpy.pi],dtype='f4')[0]
1498 pi=numpy.array([numpy.pi],dtype='f4')[0]
1499 if A[2] != 0:
1499 if A[2] != 0:
1500 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
1500 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
1501 else:
1501 else:
1502 Z = mm*0.0
1502 Z = mm*0.0
1503 A[0] = 0.0
1503 A[0] = 0.0
1504 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
1504 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
1505 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
1505 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
1506 F = junkF[xvalid]
1506 F = junkF[xvalid]
1507 if flagPDER == 0: #NEED PARTIAL?
1507 if flagPDER == 0: #NEED PARTIAL?
1508 return F
1508 return F
1509 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
1509 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
1510 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
1510 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
1511 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
1511 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
1512 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
1512 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
1513 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
1513 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
1514 PDER = PDER[xvalid,:]
1514 PDER = PDER[xvalid,:]
1515 return F, PDER
1515 return F, PDER
1516
1516
1517 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
1517 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
1518 itmax=20, tol=None):
1518 itmax=20, tol=None):
1519 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
1519 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
1520 if tol == None:
1520 if tol == None:
1521 tol = numpy.array([1.e-3],dtype='f4')[0]
1521 tol = numpy.array([1.e-3],dtype='f4')[0]
1522 typ=a.dtype
1522 typ=a.dtype
1523 double = 1 if typ == numpy.float64 else 0
1523 double = 1 if typ == numpy.float64 else 0
1524 if typ != numpy.float32:
1524 if typ != numpy.float32:
1525 a=a.astype(numpy.float32) #Make params floating
1525 a=a.astype(numpy.float32) #Make params floating
1526 # if we will be estimating partial derivates then compute machine precision
1526 # if we will be estimating partial derivates then compute machine precision
1527 if FlagNoDerivative == 1:
1527 if FlagNoDerivative == 1:
1528 res=numpy.MachAr(float_conv=numpy.float32)
1528 res=numpy.MachAr(float_conv=numpy.float32)
1529 eps=numpy.sqrt(res.eps)
1529 eps=numpy.sqrt(res.eps)
1530
1530
1531 nterms = a.size # Number of parameters
1531 nterms = a.size # Number of parameters
1532 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
1532 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
1533 if nfree <= 0: print('Curvefit - not enough data points.')
1533 if nfree <= 0: print('Curvefit - not enough data points.')
1534 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
1534 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
1535 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
1535 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
1536 # Use diag method in python
1536 # Use diag method in python
1537 converge=1
1537 converge=1
1538
1538
1539 #Define the partial derivative array
1539 #Define the partial derivative array
1540 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
1540 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
1541
1541
1542 for Niter in range(itmax): #Iteration loop
1542 for Niter in range(itmax): #Iteration loop
1543
1543
1544 if FlagNoDerivative == 1:
1544 if FlagNoDerivative == 1:
1545 #Evaluate function and estimate partial derivatives
1545 #Evaluate function and estimate partial derivatives
1546 yfit = __GAUSSWINFIT1(a)
1546 yfit = __GAUSSWINFIT1(a)
1547 for term in range(nterms):
1547 for term in range(nterms):
1548 p=a.copy() # Copy current parameters
1548 p=a.copy() # Copy current parameters
1549 #Increment size for forward difference derivative
1549 #Increment size for forward difference derivative
1550 inc = eps * abs(p[term])
1550 inc = eps * abs(p[term])
1551 if inc == 0: inc = eps
1551 if inc == 0: inc = eps
1552 p[term] = p[term] + inc
1552 p[term] = p[term] + inc
1553 yfit1 = __GAUSSWINFIT1(p)
1553 yfit1 = __GAUSSWINFIT1(p)
1554 PDER[term,:] = (yfit1-yfit)/inc
1554 PDER[term,:] = (yfit1-yfit)/inc
1555 else:
1555 else:
1556 #The user's procedure will return partial derivatives
1556 #The user's procedure will return partial derivatives
1557 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
1557 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
1558
1558
1559 beta = numpy.dot(PDER,(y-yfit)*Weights)
1559 beta = numpy.dot(PDER,(y-yfit)*Weights)
1560 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
1560 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
1561 # save current values of return parameters
1561 # save current values of return parameters
1562 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
1562 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
1563 sigma = sigma1
1563 sigma = sigma1
1564
1564
1565 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
1565 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
1566 chisq = chisq1
1566 chisq = chisq1
1567 yfit1 = yfit
1567 yfit1 = yfit
1568 elev7=numpy.array([1.0e7],dtype='f4')[0]
1568 elev7=numpy.array([1.0e7],dtype='f4')[0]
1569 compara =numpy.sum(abs(y))/elev7/nfree
1569 compara =numpy.sum(abs(y))/elev7/nfree
1570 done_early = chisq1 < compara
1570 done_early = chisq1 < compara
1571
1571
1572 if done_early:
1572 if done_early:
1573 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1573 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1574 if done_early: Niter -= 1
1574 if done_early: Niter -= 1
1575 #save_tp(chisq,Niter,yfit)
1575 #save_tp(chisq,Niter,yfit)
1576 return yfit, a, converge, sigma, chisq # return result
1576 return yfit, a, converge, sigma, chisq # return result
1577 #c = numpy.dot(c, c) # this operator implemented at the next lines
1577 #c = numpy.dot(c, c) # this operator implemented at the next lines
1578 c_tmp = numpy.sqrt(numpy.diag(alpha))
1578 c_tmp = numpy.sqrt(numpy.diag(alpha))
1579 siz=len(c_tmp)
1579 siz=len(c_tmp)
1580 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
1580 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
1581 lambdaCount = 0
1581 lambdaCount = 0
1582 while True:
1582 while True:
1583 lambdaCount += 1
1583 lambdaCount += 1
1584 # Normalize alpha to have unit diagonal.
1584 # Normalize alpha to have unit diagonal.
1585 array = alpha / c
1585 array = alpha / c
1586 # Augment the diagonal.
1586 # Augment the diagonal.
1587 one=numpy.array([1.],dtype='f4')[0]
1587 one=numpy.array([1.],dtype='f4')[0]
1588 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
1588 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
1589 # Invert modified curvature matrix to find new parameters.
1589 # Invert modified curvature matrix to find new parameters.
1590
1590
1591 try:
1591 try:
1592 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
1592 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
1593 except Exception as e:
1593 except Exception as e:
1594 print(e)
1594 print(e)
1595 array[:]=numpy.NaN
1595 array[:]=numpy.NaN
1596
1596
1597 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
1597 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
1598 yfit = __GAUSSWINFIT1(b) # Evaluate function
1598 yfit = __GAUSSWINFIT1(b) # Evaluate function
1599 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
1599 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
1600 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
1600 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
1601 if (numpy.isfinite(chisq) == 0) or \
1601 if (numpy.isfinite(chisq) == 0) or \
1602 (lambdaCount > 30 and chisq >= chisq1):
1602 (lambdaCount > 30 and chisq >= chisq1):
1603 # Reject changes made this iteration, use old values.
1603 # Reject changes made this iteration, use old values.
1604 yfit = yfit1
1604 yfit = yfit1
1605 sigma = sigma1
1605 sigma = sigma1
1606 chisq = chisq1
1606 chisq = chisq1
1607 converge = 0
1607 converge = 0
1608 #print('Failed to converge.')
1608 #print('Failed to converge.')
1609 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1609 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1610 if done_early: Niter -= 1
1610 if done_early: Niter -= 1
1611 #save_tp(chisq,Niter,yfit)
1611 #save_tp(chisq,Niter,yfit)
1612 return yfit, a, converge, sigma, chisq, chi2 # return result
1612 return yfit, a, converge, sigma, chisq, chi2 # return result
1613 ten=numpy.array([10.0],dtype='f4')[0]
1613 ten=numpy.array([10.0],dtype='f4')[0]
1614 flambda *= ten # Assume fit got worse
1614 flambda *= ten # Assume fit got worse
1615 if chisq <= chisq1:
1615 if chisq <= chisq1:
1616 break
1616 break
1617 hundred=numpy.array([100.0],dtype='f4')[0]
1617 hundred=numpy.array([100.0],dtype='f4')[0]
1618 flambda /= hundred
1618 flambda /= hundred
1619
1619
1620 a=b # Save new parameter estimate.
1620 a=b # Save new parameter estimate.
1621 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
1621 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
1622 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1622 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1623 if done_early: Niter -= 1
1623 if done_early: Niter -= 1
1624 #save_tp(chisq,Niter,yfit)
1624 #save_tp(chisq,Niter,yfit)
1625 return yfit, a, converge, sigma, chisq, chi2 # return result
1625 return yfit, a, converge, sigma, chisq, chi2 # return result
1626 converge = 0
1626 converge = 0
1627 chi2 = chisq
1627 chi2 = chisq
1628 #print('Failed to converge.')
1628 #print('Failed to converge.')
1629 #save_tp(chisq,Niter,yfit)
1629 #save_tp(chisq,Niter,yfit)
1630 return yfit, a, converge, sigma, chisq, chi2
1630 return yfit, a, converge, sigma, chisq, chi2
1631
1631
1632 if (nicoh is None): nicoh = 1
1632 if (nicoh is None): nicoh = 1
1633 if (smooth is None): smooth = 0
1633 if (smooth is None): smooth = 0
1634 if (type1 is None): type1 = 0
1634 if (type1 is None): type1 = 0
1635 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1635 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1636 if (snrth is None): snrth = -20.0
1636 if (snrth is None): snrth = -20.0
1637 if (dc is None): dc = 0
1637 if (dc is None): dc = 0
1638 if (aliasing is None): aliasing = 0
1638 if (aliasing is None): aliasing = 0
1639 if (oldfd is None): oldfd = 0
1639 if (oldfd is None): oldfd = 0
1640 if (wwauto is None): wwauto = 0
1640 if (wwauto is None): wwauto = 0
1641
1641
1642 if (n0 < 1.e-20): n0 = 1.e-20
1642 if (n0 < 1.e-20): n0 = 1.e-20
1643
1643
1644 xvalid = numpy.where(fwindow == 1)[0]
1644 xvalid = numpy.where(fwindow == 1)[0]
1645 freq = oldfreq
1645 freq = oldfreq
1646 truex = oldfreq
1646 truex = oldfreq
1647 vec_power = numpy.zeros(oldspec.shape[1])
1647 vec_power = numpy.zeros(oldspec.shape[1])
1648 vec_fd = numpy.zeros(oldspec.shape[1])
1648 vec_fd = numpy.zeros(oldspec.shape[1])
1649 vec_w = numpy.zeros(oldspec.shape[1])
1649 vec_w = numpy.zeros(oldspec.shape[1])
1650 vec_snr = numpy.zeros(oldspec.shape[1])
1650 vec_snr = numpy.zeros(oldspec.shape[1])
1651 vec_n1 = numpy.empty(oldspec.shape[1])
1651 vec_n1 = numpy.empty(oldspec.shape[1])
1652 vec_fp = numpy.empty(oldspec.shape[1])
1652 vec_fp = numpy.empty(oldspec.shape[1])
1653 vec_sigma_fd = numpy.empty(oldspec.shape[1])
1653 vec_sigma_fd = numpy.empty(oldspec.shape[1])
1654
1654
1655 for ind in range(oldspec.shape[1]):
1655 for ind in range(oldspec.shape[1]):
1656
1656
1657 spec = oldspec[:,ind]
1657 spec = oldspec[:,ind]
1658 if (smooth == 0):
1658 if (smooth == 0):
1659 spec2 = spec
1659 spec2 = spec
1660 else:
1660 else:
1661 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1661 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1662
1662
1663 aux = spec2*fwindow
1663 aux = spec2*fwindow
1664 max_spec = aux.max()
1664 max_spec = aux.max()
1665 m = aux.tolist().index(max_spec)
1665 m = aux.tolist().index(max_spec)
1666
1666
1667 if m > 2 and m < oldfreq.size - 3:
1667 if m > 2 and m < oldfreq.size - 3:
1668 newindex = m + numpy.array([-2,-1,0,1,2])
1668 newindex = m + numpy.array([-2,-1,0,1,2])
1669 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
1669 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
1670 #peakspec = SPLINE(,)
1670 #peakspec = SPLINE(,)
1671 tck = interpolate.splrep(freq[newindex], spec2[newindex])
1671 tck = interpolate.splrep(freq[newindex], spec2[newindex])
1672 peakspec = interpolate.splev(newfreq, tck)
1672 peakspec = interpolate.splev(newfreq, tck)
1673 # max_spec = MAX(peakspec,)
1673 # max_spec = MAX(peakspec,)
1674 max_spec = numpy.max(peakspec)
1674 max_spec = numpy.max(peakspec)
1675 mnew = numpy.argmax(peakspec)
1675 mnew = numpy.argmax(peakspec)
1676 #fp = newfreq(mnew)
1676 #fp = newfreq(mnew)
1677 fp = newfreq[mnew]
1677 fp = newfreq[mnew]
1678 else:
1678 else:
1679 fp = freq[m]
1679 fp = freq[m]
1680
1680
1681 if type1==0:
1681 if type1==0:
1682
1682
1683 # Moments Estimation
1683 # Moments Estimation
1684 bb = spec2[numpy.arange(m,spec2.size)]
1684 bb = spec2[numpy.arange(m,spec2.size)]
1685 bb = (bb<n0).nonzero()
1685 bb = (bb<n0).nonzero()
1686 bb = bb[0]
1686 bb = bb[0]
1687
1687
1688 ss = spec2[numpy.arange(0,m + 1)]
1688 ss = spec2[numpy.arange(0,m + 1)]
1689 ss = (ss<n0).nonzero()
1689 ss = (ss<n0).nonzero()
1690 ss = ss[0]
1690 ss = ss[0]
1691
1691
1692 if (bb.size == 0):
1692 if (bb.size == 0):
1693 bb0 = spec.size - 1 - m
1693 bb0 = spec.size - 1 - m
1694 else:
1694 else:
1695 bb0 = bb[0] - 1
1695 bb0 = bb[0] - 1
1696 if (bb0 < 0):
1696 if (bb0 < 0):
1697 bb0 = 0
1697 bb0 = 0
1698
1698
1699 if (ss.size == 0):
1699 if (ss.size == 0):
1700 ss1 = 1
1700 ss1 = 1
1701 else:
1701 else:
1702 ss1 = max(ss) + 1
1702 ss1 = max(ss) + 1
1703
1703
1704 if (ss1 > m):
1704 if (ss1 > m):
1705 ss1 = m
1705 ss1 = m
1706
1706
1707 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1707 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1708
1708
1709 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1709 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1710 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1710 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1711 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1711 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1712 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1712 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1713 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1713 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1714 snr = (spec2.mean()-n0)/n0
1714 snr = (spec2.mean()-n0)/n0
1715 if (snr < 1.e-20): snr = 1.e-20
1715 if (snr < 1.e-20): snr = 1.e-20
1716
1716
1717 vec_power[ind] = total_power
1717 vec_power[ind] = total_power
1718 vec_fd[ind] = fd
1718 vec_fd[ind] = fd
1719 vec_w[ind] = w
1719 vec_w[ind] = w
1720 vec_snr[ind] = snr
1720 vec_snr[ind] = snr
1721 else:
1721 else:
1722 # Noise by heights
1722 # Noise by heights
1723 n1, stdv = self.__get_noise2(spec, nicoh)
1723 n1, stdv = self.__get_noise2(spec, nicoh)
1724 # Moments Estimation
1724 # Moments Estimation
1725 bb = spec2[numpy.arange(m,spec2.size)]
1725 bb = spec2[numpy.arange(m,spec2.size)]
1726 bb = (bb<n1).nonzero()
1726 bb = (bb<n1).nonzero()
1727 bb = bb[0]
1727 bb = bb[0]
1728
1728
1729 ss = spec2[numpy.arange(0,m + 1)]
1729 ss = spec2[numpy.arange(0,m + 1)]
1730 ss = (ss<n1).nonzero()
1730 ss = (ss<n1).nonzero()
1731 ss = ss[0]
1731 ss = ss[0]
1732
1732
1733 if (bb.size == 0):
1733 if (bb.size == 0):
1734 bb0 = spec.size - 1 - m
1734 bb0 = spec.size - 1 - m
1735 else:
1735 else:
1736 bb0 = bb[0] - 1
1736 bb0 = bb[0] - 1
1737 if (bb0 < 0):
1737 if (bb0 < 0):
1738 bb0 = 0
1738 bb0 = 0
1739
1739
1740 if (ss.size == 0):
1740 if (ss.size == 0):
1741 ss1 = 1
1741 ss1 = 1
1742 else:
1742 else:
1743 ss1 = max(ss) + 1
1743 ss1 = max(ss) + 1
1744
1744
1745 if (ss1 > m):
1745 if (ss1 > m):
1746 ss1 = m
1746 ss1 = m
1747
1747
1748 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1748 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1749
1749
1750 power = ((spec[valid] - n1)*fwindow[valid]).sum()
1750 power = ((spec[valid] - n1)*fwindow[valid]).sum()
1751 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
1751 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
1752 try:
1752 try:
1753 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1753 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1754 except:
1754 except:
1755 w = float("NaN")
1755 w = float("NaN")
1756 snr = power/(n0*fwindow.sum())
1756 snr = power/(n0*fwindow.sum())
1757 if snr < 1.e-20: snr = 1.e-20
1757 if snr < 1.e-20: snr = 1.e-20
1758
1758
1759 # Here start gaussean adjustment
1759 # Here start gaussean adjustment
1760
1760
1761 if snr > numpy.power(10,0.1*snrth):
1761 if snr > numpy.power(10,0.1*snrth):
1762
1762
1763 a = numpy.zeros(4,dtype='f4')
1763 a = numpy.zeros(4,dtype='f4')
1764 a[0] = snr * n0
1764 a[0] = snr * n0
1765 a[1] = fd
1765 a[1] = fd
1766 a[2] = w
1766 a[2] = w
1767 a[3] = n0
1767 a[3] = n0
1768
1768
1769 np = spec.size
1769 np = spec.size
1770 aold = a.copy()
1770 aold = a.copy()
1771 spec2 = spec.copy()
1771 spec2 = spec.copy()
1772 oldxvalid = xvalid.copy()
1772 oldxvalid = xvalid.copy()
1773
1773
1774 for i in range(2):
1774 for i in range(2):
1775
1775
1776 ww = 1.0/(numpy.power(spec2,2)/nicoh)
1776 ww = 1.0/(numpy.power(spec2,2)/nicoh)
1777 ww[np//2] = 0.0
1777 ww[np//2] = 0.0
1778
1778
1779 a = aold.copy()
1779 a = aold.copy()
1780 xvalid = oldxvalid.copy()
1780 xvalid = oldxvalid.copy()
1781 #self.show_var(xvalid)
1781 #self.show_var(xvalid)
1782
1782
1783 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
1783 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
1784 a = gaussfn[1]
1784 a = gaussfn[1]
1785 converge = gaussfn[2]
1785 converge = gaussfn[2]
1786
1786
1787 xvalid = numpy.arange(np)
1787 xvalid = numpy.arange(np)
1788 spec2 = __GAUSSWINFIT1(a)
1788 spec2 = __GAUSSWINFIT1(a)
1789
1789
1790 xvalid = oldxvalid.copy()
1790 xvalid = oldxvalid.copy()
1791 power = a[0] * np
1791 power = a[0] * np
1792 fd = a[1]
1792 fd = a[1]
1793 sigma_fd = gaussfn[3][1]
1793 sigma_fd = gaussfn[3][1]
1794 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
1794 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
1795 w = numpy.abs(a[2])
1795 w = numpy.abs(a[2])
1796 n1 = max(a[3], n0)
1796 n1 = max(a[3], n0)
1797
1797
1798 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
1798 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
1799 else:
1799 else:
1800 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
1800 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
1801
1801
1802 vec_fd[ind] = fd
1802 vec_fd[ind] = fd
1803 vec_w[ind] = w
1803 vec_w[ind] = w
1804 vec_snr[ind] = snr
1804 vec_snr[ind] = snr
1805 vec_n1[ind] = n1
1805 vec_n1[ind] = n1
1806 vec_fp[ind] = fp
1806 vec_fp[ind] = fp
1807 vec_sigma_fd[ind] = sigma_fd
1807 vec_sigma_fd[ind] = sigma_fd
1808 vec_power[ind] = power # to compare with type 0 proccessing
1808 vec_power[ind] = power # to compare with type 0 proccessing
1809
1809
1810 if type1==1:
1810 if type1==1:
1811 #return numpy.vstack((vec_fd, vec_w, vec_snr, vec_n1, vec_fp, vec_sigma_fd, vec_power))
1811 #return numpy.vstack((vec_fd, vec_w, vec_snr, vec_n1, vec_fp, vec_sigma_fd, vec_power))
1812 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
1812 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
1813 else:
1813 else:
1814 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1814 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1815
1815
1816 def __get_noise2(self,POWER, fft_avg, TALK=0):
1816 def __get_noise2(self,POWER, fft_avg, TALK=0):
1817 '''
1817 '''
1818 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
1818 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
1819 '''
1819 '''
1820 SPECT_PTS = len(POWER)
1820 SPECT_PTS = len(POWER)
1821 fft_avg = fft_avg*1.0
1821 fft_avg = fft_avg*1.0
1822 NOMIT = 0
1822 NOMIT = 0
1823 NN = SPECT_PTS - NOMIT
1823 NN = SPECT_PTS - NOMIT
1824 N = NN//2
1824 N = NN//2
1825 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
1825 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
1826 ARR = numpy.sort(ARR)
1826 ARR = numpy.sort(ARR)
1827 NUMS_MIN = (SPECT_PTS+7)//8
1827 NUMS_MIN = (SPECT_PTS+7)//8
1828 RTEST = (1.0+1.0/fft_avg)
1828 RTEST = (1.0+1.0/fft_avg)
1829 SUM = 0.0
1829 SUM = 0.0
1830 SUMSQ = 0.0
1830 SUMSQ = 0.0
1831 J = 0
1831 J = 0
1832 for I in range(NN):
1832 for I in range(NN):
1833 J = J + 1
1833 J = J + 1
1834 SUM = SUM + ARR[I]
1834 SUM = SUM + ARR[I]
1835 SUMSQ = SUMSQ + ARR[I]*ARR[I]
1835 SUMSQ = SUMSQ + ARR[I]*ARR[I]
1836 AVE = SUM*1.0/J
1836 AVE = SUM*1.0/J
1837 if J > NUMS_MIN:
1837 if J > NUMS_MIN:
1838 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
1838 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
1839 else:
1839 else:
1840 if J == NUMS_MIN: RNOISE = AVE
1840 if J == NUMS_MIN: RNOISE = AVE
1841 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
1841 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
1842 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1842 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1843 return RNOISE, stdv
1843 return RNOISE, stdv
1844
1844
1845 def __get_noise1(self, power, fft_avg, TALK=0):
1845 def __get_noise1(self, power, fft_avg, TALK=0):
1846 '''
1846 '''
1847 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
1847 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
1848 '''
1848 '''
1849 num_pts = numpy.size(power)
1849 num_pts = numpy.size(power)
1850 #print('num_pts',num_pts)
1850 #print('num_pts',num_pts)
1851 #print('power',power.shape)
1851 #print('power',power.shape)
1852 #print(power[256:267,0:2])
1852 #print(power[256:267,0:2])
1853 fft_avg = fft_avg*1.0
1853 fft_avg = fft_avg*1.0
1854
1854
1855 ind = numpy.argsort(power, axis=None, kind='stable')
1855 ind = numpy.argsort(power, axis=None, kind='stable')
1856 #ind = numpy.argsort(numpy.reshape(power,-1))
1856 #ind = numpy.argsort(numpy.reshape(power,-1))
1857 #print(ind.shape)
1857 #print(ind.shape)
1858 #print(ind[0:11])
1858 #print(ind[0:11])
1859 #print(numpy.reshape(power,-1)[ind[0:11]])
1859 #print(numpy.reshape(power,-1)[ind[0:11]])
1860 ARR = numpy.reshape(power,-1)[ind]
1860 ARR = numpy.reshape(power,-1)[ind]
1861 #print('ARR',len(ARR))
1861 #print('ARR',len(ARR))
1862 #print('ARR',ARR.shape)
1862 #print('ARR',ARR.shape)
1863 NUMS_MIN = num_pts//10
1863 NUMS_MIN = num_pts//10
1864 RTEST = (1.0+1.0/fft_avg)
1864 RTEST = (1.0+1.0/fft_avg)
1865 SUM = 0.0
1865 SUM = 0.0
1866 SUMSQ = 0.0
1866 SUMSQ = 0.0
1867 J = 0
1867 J = 0
1868 cont = 1
1868 cont = 1
1869 while cont == 1 and J < num_pts:
1869 while cont == 1 and J < num_pts:
1870
1870
1871 SUM = SUM + ARR[J]
1871 SUM = SUM + ARR[J]
1872 SUMSQ = SUMSQ + ARR[J]*ARR[J]
1872 SUMSQ = SUMSQ + ARR[J]*ARR[J]
1873 J = J + 1
1873 J = J + 1
1874
1874
1875 if J > NUMS_MIN:
1875 if J > NUMS_MIN:
1876 if (SUMSQ*J <= RTEST*SUM*SUM):
1876 if (SUMSQ*J <= RTEST*SUM*SUM):
1877 LNOISE = SUM*1.0/J
1877 LNOISE = SUM*1.0/J
1878 else:
1878 else:
1879 J = J - 1
1879 J = J - 1
1880 SUM = SUM - ARR[J]
1880 SUM = SUM - ARR[J]
1881 SUMSQ = SUMSQ - ARR[J]*ARR[J]
1881 SUMSQ = SUMSQ - ARR[J]*ARR[J]
1882 cont = 0
1882 cont = 0
1883 else:
1883 else:
1884 if J == NUMS_MIN: LNOISE = SUM*1.0/J
1884 if J == NUMS_MIN: LNOISE = SUM*1.0/J
1885 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
1885 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
1886 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1886 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1887 return LNOISE, stdv
1887 return LNOISE, stdv
1888
1888
1889 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
1889 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
1890
1890
1891 val_frq = numpy.arange(num_prof-2)+1
1891 val_frq = numpy.arange(num_prof-2)+1
1892 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
1892 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
1893 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
1893 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
1894 junkid = numpy.argsort(junkspc)
1894 junkid = numpy.argsort(junkspc)
1895 noisezone = val_frq[junkid[0:num_prof//2]]
1895 noisezone = val_frq[junkid[0:num_prof//2]]
1896 specnoise = spectra[noisezone,:]
1896 specnoise = spectra[noisezone,:]
1897 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
1897 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
1898
1898
1899 if talk:
1899 if talk:
1900 print('noise =', noise)
1900 print('noise =', noise)
1901 return noise
1901 return noise
1902
1903 class JULIADriftsEstimation(Operation):
1904
1905 def __init__(self):
1906 Operation.__init__(self)
1907
1908
1909 def newtotal(self, data):
1910 return numpy.nansum(data)
1911
1912 #def data_filter(self, parm, snrth=-19.5, swth=20, wErrth=500):
1913 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
1914
1915 Sz0 = parm.shape # Sz0: h,p
1916 drift = parm[:,0]
1917 sw = 2*parm[:,1]
1918 snr = 10*numpy.log10(parm[:,2])
1919 Sz = drift.shape # Sz: h
1920 mask = numpy.ones((Sz[0]))
1921 th=0
1922 valid=numpy.where(numpy.isfinite(snr))
1923 cvalid = len(valid[0])
1924 if cvalid >= 1:
1925 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
1926 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
1927 h = numpy.histogram(snr,bins=nbins)
1928 hist = h[0]
1929 values = numpy.round_(h[1])
1930 moda = values[numpy.where(hist == numpy.max(hist))]
1931 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
1932
1933 noise = snr[indNoise]
1934 noise_mean = numpy.sum(noise)/len(noise)
1935 # CΓ‘lculo de media de snr
1936 med = numpy.median(snr)
1937 # Establece el umbral de snr
1938 if noise_mean > med + 3:
1939 th = med
1940 else:
1941 th = noise_mean + 3
1942 # Establece mΓ‘scara
1943 novalid = numpy.where(snr <= th)[0]
1944 mask[novalid] = numpy.nan
1945 # Elimina datos que no sobrepasen el umbral: PARAMETRO
1946 novalid = numpy.where(snr <= snrth)
1947 cnovalid = len(novalid[0])
1948 if cnovalid > 0:
1949 mask[novalid] = numpy.nan
1950 novalid = numpy.where(numpy.isnan(snr))
1951 cnovalid = len(novalid[0])
1952 if cnovalid > 0:
1953 mask[novalid] = numpy.nan
1954 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
1955 for h in range(Sz0[0]):
1956 for p in range(Sz0[1]):
1957 if numpy.isnan(mask[h]):
1958 new_parm[h,p]=numpy.nan
1959 else:
1960 new_parm[h,p]=parm[h,p]
1961
1962 return new_parm, th
1963
1964 def run(self, dataOut, zenith, zenithCorrection,heights=None, statistics=0, otype=0):
1965
1966 nCh=dataOut.spcpar.shape[0]
1967
1968 nHei=dataOut.spcpar.shape[1]
1969 nParam=dataOut.spcpar.shape[2]
1970 # Solo las alturas de interes
1971 hei=dataOut.heightList
1972 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
1973 nhvalid=len(hvalid)
1974 parm = numpy.zeros((nCh,nhvalid,nParam))
1975 parm = dataOut.spcpar[:,hvalid,:]
1976
1977 # Primer filtrado: Umbral de SNR
1978 #snrth=-19
1979 for i in range(nCh):
1980 #print('snr:',parm[i,:,2])
1981 #dataOut.spcpar[i,hvalid,:] = self.data_filter(parm[i,:,:],snrth)[0]
1982 dataOut.spcpar[i,hvalid,:] = self.data_filter(parm[i,:,:])[0]
1983 #print('dataOut.spcpar[0,:,2]',dataOut.spcpar[0,:,2])
1984 #print('dataOut.spcpar[1,:,2]',dataOut.spcpar[1,:,2])
1985 zenith = numpy.array(zenith)
1986 zenith -= zenithCorrection
1987 zenith *= numpy.pi/180
1988 alpha = zenith[0]
1989 beta = zenith[1]
1990
1991 dopplerCH0 = dataOut.spcpar[0,:,0]
1992 dopplerCH1 = dataOut.spcpar[1,:,0]
1993 swCH0 = dataOut.spcpar[0,:,1]
1994 swCH1 = dataOut.spcpar[1,:,1]
1995 snrCH0 = 10*numpy.log10(dataOut.spcpar[0,:,2])
1996 snrCH1 = 10*numpy.log10(dataOut.spcpar[1,:,2])
1997 noiseCH0 = dataOut.spcpar[0,:,3]
1998 noiseCH1 = dataOut.spcpar[1,:,3]
1999 wErrCH0 = dataOut.spcpar[0,:,5]
2000 wErrCH1 = dataOut.spcpar[1,:,5]
2001
2002 # Vertical and zonal calculation according to geometry
2003 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
2004 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
2005 '''
2006 print('drift.shape:',drift.shape)
2007 print('drift min:', numpy.nanmin(drift))
2008 print('drift max:', numpy.nanmax(drift))
2009 '''
1902
2010
2011 '''
2012 print('shape:', dopplerCH0[hvalid].shape)
2013 print('dopplerCH0:', dopplerCH0[hvalid])
2014 print('dopplerCH1:', dopplerCH1[hvalid])
2015 print('drift:', drift[hvalid])
2016 '''
2017 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
2018 '''
2019 print('zonal min:', numpy.nanmin(zonal))
2020 print('zonal max:', numpy.nanmax(zonal))
2021 '''
2022 #print('zonal:', zonal[hvalid])
2023 snr = (snrCH0 + snrCH1)/2
2024 '''
2025 print('snr min:', 10*numpy.log10(numpy.nanmin(snr)))
2026 print('snr max:', 10*numpy.log10(numpy.nanmax(snr)))
2027 '''
2028 noise = (noiseCH0 + noiseCH1)/2
2029 sw = (swCH0 + swCH1)/2
2030 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))
2031 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))
2032
2033 # for statistics150km
2034 if statistics:
2035 print('Implemented offline.')
2036
2037 if otype == 0:
2038 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
2039 elif otype == 3:
2040 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
2041 elif otype == 4:
2042 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
2043
2044 snr1 = numpy.vstack((snrCH0, snrCH1))
2045
2046 dataOut.data_output = winds
2047 dataOut.data_snr = snr1
2048
2049 dataOut.utctimeInit = dataOut.utctime
2050 dataOut.outputInterval = dataOut.timeInterval
2051
2052 return dataOut
2053
1903 class SALags(Operation):
2054 class SALags(Operation):
1904 '''
2055 '''
1905 Function GetMoments()
2056 Function GetMoments()
1906
2057
1907 Input:
2058 Input:
1908 self.dataOut.data_pre
2059 self.dataOut.data_pre
1909 self.dataOut.abscissaList
2060 self.dataOut.abscissaList
1910 self.dataOut.noise
2061 self.dataOut.noise
1911 self.dataOut.normFactor
2062 self.dataOut.normFactor
1912 self.dataOut.data_snr
2063 self.dataOut.data_snr
1913 self.dataOut.groupList
2064 self.dataOut.groupList
1914 self.dataOut.nChannels
2065 self.dataOut.nChannels
1915
2066
1916 Affected:
2067 Affected:
1917 self.dataOut.data_param
2068 self.dataOut.data_param
1918
2069
1919 '''
2070 '''
1920 def run(self, dataOut):
2071 def run(self, dataOut):
1921 data_acf = dataOut.data_pre[0]
2072 data_acf = dataOut.data_pre[0]
1922 data_ccf = dataOut.data_pre[1]
2073 data_ccf = dataOut.data_pre[1]
1923 normFactor_acf = dataOut.normFactor[0]
2074 normFactor_acf = dataOut.normFactor[0]
1924 normFactor_ccf = dataOut.normFactor[1]
2075 normFactor_ccf = dataOut.normFactor[1]
1925 pairs_acf = dataOut.groupList[0]
2076 pairs_acf = dataOut.groupList[0]
1926 pairs_ccf = dataOut.groupList[1]
2077 pairs_ccf = dataOut.groupList[1]
1927
2078
1928 nHeights = dataOut.nHeights
2079 nHeights = dataOut.nHeights
1929 absc = dataOut.abscissaList
2080 absc = dataOut.abscissaList
1930 noise = dataOut.noise
2081 noise = dataOut.noise
1931 SNR = dataOut.data_snr
2082 SNR = dataOut.data_snr
1932 nChannels = dataOut.nChannels
2083 nChannels = dataOut.nChannels
1933 # pairsList = dataOut.groupList
2084 # pairsList = dataOut.groupList
1934 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
2085 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1935
2086
1936 for l in range(len(pairs_acf)):
2087 for l in range(len(pairs_acf)):
1937 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
2088 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1938
2089
1939 for l in range(len(pairs_ccf)):
2090 for l in range(len(pairs_ccf)):
1940 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
2091 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1941
2092
1942 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
2093 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1943 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
2094 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1944 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
2095 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1945 return
2096 return
1946
2097
1947 # def __getPairsAutoCorr(self, pairsList, nChannels):
2098 # def __getPairsAutoCorr(self, pairsList, nChannels):
1948 #
2099 #
1949 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
2100 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1950 #
2101 #
1951 # for l in range(len(pairsList)):
2102 # for l in range(len(pairsList)):
1952 # firstChannel = pairsList[l][0]
2103 # firstChannel = pairsList[l][0]
1953 # secondChannel = pairsList[l][1]
2104 # secondChannel = pairsList[l][1]
1954 #
2105 #
1955 # #Obteniendo pares de Autocorrelacion
2106 # #Obteniendo pares de Autocorrelacion
1956 # if firstChannel == secondChannel:
2107 # if firstChannel == secondChannel:
1957 # pairsAutoCorr[firstChannel] = int(l)
2108 # pairsAutoCorr[firstChannel] = int(l)
1958 #
2109 #
1959 # pairsAutoCorr = pairsAutoCorr.astype(int)
2110 # pairsAutoCorr = pairsAutoCorr.astype(int)
1960 #
2111 #
1961 # pairsCrossCorr = range(len(pairsList))
2112 # pairsCrossCorr = range(len(pairsList))
1962 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
2113 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1963 #
2114 #
1964 # return pairsAutoCorr, pairsCrossCorr
2115 # return pairsAutoCorr, pairsCrossCorr
1965
2116
1966 def __calculateTaus(self, data_acf, data_ccf, lagRange):
2117 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1967
2118
1968 lag0 = data_acf.shape[1]/2
2119 lag0 = data_acf.shape[1]/2
1969 #Funcion de Autocorrelacion
2120 #Funcion de Autocorrelacion
1970 mean_acf = stats.nanmean(data_acf, axis = 0)
2121 mean_acf = stats.nanmean(data_acf, axis = 0)
1971
2122
1972 #Obtencion Indice de TauCross
2123 #Obtencion Indice de TauCross
1973 ind_ccf = data_ccf.argmax(axis = 1)
2124 ind_ccf = data_ccf.argmax(axis = 1)
1974 #Obtencion Indice de TauAuto
2125 #Obtencion Indice de TauAuto
1975 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
2126 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1976 ccf_lag0 = data_ccf[:,lag0,:]
2127 ccf_lag0 = data_ccf[:,lag0,:]
1977
2128
1978 for i in range(ccf_lag0.shape[0]):
2129 for i in range(ccf_lag0.shape[0]):
1979 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
2130 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1980
2131
1981 #Obtencion de TauCross y TauAuto
2132 #Obtencion de TauCross y TauAuto
1982 tau_ccf = lagRange[ind_ccf]
2133 tau_ccf = lagRange[ind_ccf]
1983 tau_acf = lagRange[ind_acf]
2134 tau_acf = lagRange[ind_acf]
1984
2135
1985 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
2136 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1986
2137
1987 tau_ccf[Nan1,Nan2] = numpy.nan
2138 tau_ccf[Nan1,Nan2] = numpy.nan
1988 tau_acf[Nan1,Nan2] = numpy.nan
2139 tau_acf[Nan1,Nan2] = numpy.nan
1989 tau = numpy.vstack((tau_ccf,tau_acf))
2140 tau = numpy.vstack((tau_ccf,tau_acf))
1990
2141
1991 return tau
2142 return tau
1992
2143
1993 def __calculateLag1Phase(self, data, lagTRange):
2144 def __calculateLag1Phase(self, data, lagTRange):
1994 data1 = stats.nanmean(data, axis = 0)
2145 data1 = stats.nanmean(data, axis = 0)
1995 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
2146 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1996
2147
1997 phase = numpy.angle(data1[lag1,:])
2148 phase = numpy.angle(data1[lag1,:])
1998
2149
1999 return phase
2150 return phase
2000
2151
2001 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
2152 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
2002 z = (x - a1) / a2
2153 z = (x - a1) / a2
2003 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
2154 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
2004 return y
2155 return y
2005
2156
2006
2157
2007 class SpectralFitting(Operation):
2158 class SpectralFitting(Operation):
2008 '''
2159 '''
2009 Function GetMoments()
2160 Function GetMoments()
2010
2161
2011 Input:
2162 Input:
2012 Output:
2163 Output:
2013 Variables modified:
2164 Variables modified:
2014 '''
2165 '''
2015 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):
2166 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):
2016
2167
2017 if (nicoh is None): nicoh = 1
2168 if (nicoh is None): nicoh = 1
2018 if (graph is None): graph = 0
2169 if (graph is None): graph = 0
2019 if (smooth is None): smooth = 0
2170 if (smooth is None): smooth = 0
2020 elif (self.smooth < 3): smooth = 0
2171 elif (self.smooth < 3): smooth = 0
2021
2172
2022 if (type1 is None): type1 = 0
2173 if (type1 is None): type1 = 0
2023 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2174 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2024 if (snrth is None): snrth = -3
2175 if (snrth is None): snrth = -3
2025 if (dc is None): dc = 0
2176 if (dc is None): dc = 0
2026 if (aliasing is None): aliasing = 0
2177 if (aliasing is None): aliasing = 0
2027 if (oldfd is None): oldfd = 0
2178 if (oldfd is None): oldfd = 0
2028 if (wwauto is None): wwauto = 0
2179 if (wwauto is None): wwauto = 0
2029
2180
2030 if (n0 < 1.e-20): n0 = 1.e-20
2181 if (n0 < 1.e-20): n0 = 1.e-20
2031
2182
2032 freq = oldfreq
2183 freq = oldfreq
2033 vec_power = numpy.zeros(oldspec.shape[1])
2184 vec_power = numpy.zeros(oldspec.shape[1])
2034 vec_fd = numpy.zeros(oldspec.shape[1])
2185 vec_fd = numpy.zeros(oldspec.shape[1])
2035 vec_w = numpy.zeros(oldspec.shape[1])
2186 vec_w = numpy.zeros(oldspec.shape[1])
2036 vec_snr = numpy.zeros(oldspec.shape[1])
2187 vec_snr = numpy.zeros(oldspec.shape[1])
2037
2188
2038 oldspec = numpy.ma.masked_invalid(oldspec)
2189 oldspec = numpy.ma.masked_invalid(oldspec)
2039
2190
2040 for ind in range(oldspec.shape[1]):
2191 for ind in range(oldspec.shape[1]):
2041
2192
2042 spec = oldspec[:,ind]
2193 spec = oldspec[:,ind]
2043 aux = spec*fwindow
2194 aux = spec*fwindow
2044 max_spec = aux.max()
2195 max_spec = aux.max()
2045 m = list(aux).index(max_spec)
2196 m = list(aux).index(max_spec)
2046
2197
2047 #Smooth
2198 #Smooth
2048 if (smooth == 0): spec2 = spec
2199 if (smooth == 0): spec2 = spec
2049 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2200 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2050
2201
2051 # Calculo de Momentos
2202 # Calculo de Momentos
2052 bb = spec2[list(range(m,spec2.size))]
2203 bb = spec2[list(range(m,spec2.size))]
2053 bb = (bb<n0).nonzero()
2204 bb = (bb<n0).nonzero()
2054 bb = bb[0]
2205 bb = bb[0]
2055
2206
2056 ss = spec2[list(range(0,m + 1))]
2207 ss = spec2[list(range(0,m + 1))]
2057 ss = (ss<n0).nonzero()
2208 ss = (ss<n0).nonzero()
2058 ss = ss[0]
2209 ss = ss[0]
2059
2210
2060 if (bb.size == 0):
2211 if (bb.size == 0):
2061 bb0 = spec.size - 1 - m
2212 bb0 = spec.size - 1 - m
2062 else:
2213 else:
2063 bb0 = bb[0] - 1
2214 bb0 = bb[0] - 1
2064 if (bb0 < 0):
2215 if (bb0 < 0):
2065 bb0 = 0
2216 bb0 = 0
2066
2217
2067 if (ss.size == 0): ss1 = 1
2218 if (ss.size == 0): ss1 = 1
2068 else: ss1 = max(ss) + 1
2219 else: ss1 = max(ss) + 1
2069
2220
2070 if (ss1 > m): ss1 = m
2221 if (ss1 > m): ss1 = m
2071
2222
2072 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
2223 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
2073 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
2224 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
2074 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
2225 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
2075 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2226 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2076 snr = (spec2.mean()-n0)/n0
2227 snr = (spec2.mean()-n0)/n0
2077
2228
2078 if (snr < 1.e-20) :
2229 if (snr < 1.e-20) :
2079 snr = 1.e-20
2230 snr = 1.e-20
2080
2231
2081 vec_power[ind] = power
2232 vec_power[ind] = power
2082 vec_fd[ind] = fd
2233 vec_fd[ind] = fd
2083 vec_w[ind] = w
2234 vec_w[ind] = w
2084 vec_snr[ind] = snr
2235 vec_snr[ind] = snr
2085
2236
2086 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2237 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2087 return moments
2238 return moments
2088
2239
2089 #def __DiffCoherent(self,snrth, spectra, cspectra, nProf, heights,nChan, nHei, nPairs, channels, noise, crosspairs):
2240 #def __DiffCoherent(self,snrth, spectra, cspectra, nProf, heights,nChan, nHei, nPairs, channels, noise, crosspairs):
2090 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
2241 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
2091
2242
2092 import matplotlib.pyplot as plt
2243 import matplotlib.pyplot as plt
2093 nProf = dataOut.nProfiles
2244 nProf = dataOut.nProfiles
2094 heights = dataOut.heightList
2245 heights = dataOut.heightList
2095 nHei = len(heights)
2246 nHei = len(heights)
2096 channels = dataOut.channelList
2247 channels = dataOut.channelList
2097 nChan = len(channels)
2248 nChan = len(channels)
2098 crosspairs = dataOut.groupList
2249 crosspairs = dataOut.groupList
2099 nPairs = len(crosspairs)
2250 nPairs = len(crosspairs)
2100 #Separar espectros incoherentes de coherentes snr > 20 dB'
2251 #Separar espectros incoherentes de coherentes snr > 20 dB'
2101 snr_th = 10**(snrth/10.0)
2252 snr_th = 10**(snrth/10.0)
2102 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
2253 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
2103 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
2254 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
2104 my_incoh_aver = numpy.zeros([nChan, nHei])
2255 my_incoh_aver = numpy.zeros([nChan, nHei])
2105 my_coh_aver = numpy.zeros([nChan, nHei])
2256 my_coh_aver = numpy.zeros([nChan, nHei])
2106
2257
2107 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2258 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2108 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2259 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2109 coh_aver = numpy.zeros([nChan, nHei])
2260 coh_aver = numpy.zeros([nChan, nHei])
2110
2261
2111 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2262 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2112 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2263 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2113 incoh_aver = numpy.zeros([nChan, nHei])
2264 incoh_aver = numpy.zeros([nChan, nHei])
2114 power = numpy.sum(spectra, axis=1)
2265 power = numpy.sum(spectra, axis=1)
2115
2266
2116 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
2267 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
2117 if hei_th == None : hei_th = numpy.array([60,300,650])
2268 if hei_th == None : hei_th = numpy.array([60,300,650])
2118 for ic in range(2):
2269 for ic in range(2):
2119 pair = crosspairs[ic]
2270 pair = crosspairs[ic]
2120 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
2271 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
2121 s_n0 = power[pair[0],:]/noise[pair[0]]
2272 s_n0 = power[pair[0],:]/noise[pair[0]]
2122 s_n1 = power[pair[1],:]/noise[pair[1]]
2273 s_n1 = power[pair[1],:]/noise[pair[1]]
2123
2274
2124 valid1 =(s_n0>=snr_th).nonzero()
2275 valid1 =(s_n0>=snr_th).nonzero()
2125 valid2 = (s_n1>=snr_th).nonzero()
2276 valid2 = (s_n1>=snr_th).nonzero()
2126 #valid = valid2 + valid1 #numpy.concatenate((valid1,valid2), axis=None)
2277 #valid = valid2 + valid1 #numpy.concatenate((valid1,valid2), axis=None)
2127 valid1 = numpy.array(valid1[0])
2278 valid1 = numpy.array(valid1[0])
2128 valid2 = numpy.array(valid2[0])
2279 valid2 = numpy.array(valid2[0])
2129 valid = valid1
2280 valid = valid1
2130 for iv in range(len(valid2)):
2281 for iv in range(len(valid2)):
2131 #for ivv in range(len(valid1)) :
2282 #for ivv in range(len(valid1)) :
2132 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2283 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2133 if len(indv[0]) == 0 :
2284 if len(indv[0]) == 0 :
2134 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2285 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2135 if len(valid)>0:
2286 if len(valid)>0:
2136 my_coh_aver[pair[0],valid]=1
2287 my_coh_aver[pair[0],valid]=1
2137 my_coh_aver[pair[1],valid]=1
2288 my_coh_aver[pair[1],valid]=1
2138 # si la coherencia es mayor a la coherencia threshold los datos se toman
2289 # si la coherencia es mayor a la coherencia threshold los datos se toman
2139 #print my_coh_aver[0,:]
2290 #print my_coh_aver[0,:]
2140 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)))
2291 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)))
2141 #print('coh',numpy.absolute(coh))
2292 #print('coh',numpy.absolute(coh))
2142 for ih in range(len(hei_th)):
2293 for ih in range(len(hei_th)):
2143 hvalid = (heights>hei_th[ih]).nonzero()
2294 hvalid = (heights>hei_th[ih]).nonzero()
2144 hvalid = hvalid[0]
2295 hvalid = hvalid[0]
2145 if len(hvalid)>0:
2296 if len(hvalid)>0:
2146 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
2297 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
2147 valid = valid[0]
2298 valid = valid[0]
2148 #print('hvalid:',hvalid)
2299 #print('hvalid:',hvalid)
2149 #print('valid', valid)
2300 #print('valid', valid)
2150 if len(valid)>0:
2301 if len(valid)>0:
2151 my_coh_aver[pair[0],hvalid[valid]] =1
2302 my_coh_aver[pair[0],hvalid[valid]] =1
2152 my_coh_aver[pair[1],hvalid[valid]] =1
2303 my_coh_aver[pair[1],hvalid[valid]] =1
2153
2304
2154 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
2305 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
2155 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
2306 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
2156 incoh_echoes = incoh_echoes[0]
2307 incoh_echoes = incoh_echoes[0]
2157 if len(incoh_echoes) > 0:
2308 if len(incoh_echoes) > 0:
2158 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2309 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2159 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2310 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2160 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2311 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2161 my_incoh_aver[pair[0],incoh_echoes] = 1
2312 my_incoh_aver[pair[0],incoh_echoes] = 1
2162 my_incoh_aver[pair[1],incoh_echoes] = 1
2313 my_incoh_aver[pair[1],incoh_echoes] = 1
2163
2314
2164
2315
2165 for ic in range(2):
2316 for ic in range(2):
2166 pair = crosspairs[ic]
2317 pair = crosspairs[ic]
2167
2318
2168 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
2319 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
2169 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
2320 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
2170 valid1 = numpy.array(valid1[0])
2321 valid1 = numpy.array(valid1[0])
2171 valid2 = numpy.array(valid2[0])
2322 valid2 = numpy.array(valid2[0])
2172 valid = valid1
2323 valid = valid1
2173 #print valid1 , valid2
2324 #print valid1 , valid2
2174 for iv in range(len(valid2)):
2325 for iv in range(len(valid2)):
2175 #for ivv in range(len(valid1)) :
2326 #for ivv in range(len(valid1)) :
2176 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2327 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2177 if len(indv[0]) == 0 :
2328 if len(indv[0]) == 0 :
2178 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2329 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2179 #print valid
2330 #print valid
2180 #valid = numpy.concatenate((valid1,valid2), axis=None)
2331 #valid = numpy.concatenate((valid1,valid2), axis=None)
2181 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
2332 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
2182 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
2333 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
2183 valid1 = numpy.array(valid1[0])
2334 valid1 = numpy.array(valid1[0])
2184 valid2 = numpy.array(valid2[0])
2335 valid2 = numpy.array(valid2[0])
2185 incoh_echoes = valid1
2336 incoh_echoes = valid1
2186 #print valid1, valid2
2337 #print valid1, valid2
2187 #incoh_echoes= numpy.concatenate((valid1,valid2), axis=None)
2338 #incoh_echoes= numpy.concatenate((valid1,valid2), axis=None)
2188 for iv in range(len(valid2)):
2339 for iv in range(len(valid2)):
2189 #for ivv in range(len(valid1)) :
2340 #for ivv in range(len(valid1)) :
2190 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2341 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2191 if len(indv[0]) == 0 :
2342 if len(indv[0]) == 0 :
2192 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
2343 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
2193 #print incoh_echoes
2344 #print incoh_echoes
2194 if len(valid)>0:
2345 if len(valid)>0:
2195 #print pair
2346 #print pair
2196 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
2347 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
2197 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
2348 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
2198 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
2349 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
2199 coh_aver[pair[0],valid]=1
2350 coh_aver[pair[0],valid]=1
2200 coh_aver[pair[1],valid]=1
2351 coh_aver[pair[1],valid]=1
2201 if len(incoh_echoes)>0:
2352 if len(incoh_echoes)>0:
2202 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2353 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2203 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2354 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2204 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2355 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2205 incoh_aver[pair[0],incoh_echoes]=1
2356 incoh_aver[pair[0],incoh_echoes]=1
2206 incoh_aver[pair[1],incoh_echoes]=1
2357 incoh_aver[pair[1],incoh_echoes]=1
2207 #plt.imshow(spectra[0,:,:],vmin=20000000)
2358 #plt.imshow(spectra[0,:,:],vmin=20000000)
2208 #plt.show()
2359 #plt.show()
2209 #my_incoh_aver = my_incoh_aver+1
2360 #my_incoh_aver = my_incoh_aver+1
2210
2361
2211 #spec = my_incoh_spectra.copy()
2362 #spec = my_incoh_spectra.copy()
2212 #cspec = my_incoh_cspectra.copy()
2363 #cspec = my_incoh_cspectra.copy()
2213 #print('######################', spec)
2364 #print('######################', spec)
2214 #print(self.numpy)
2365 #print(self.numpy)
2215 #return spec, cspec,coh_aver
2366 #return spec, cspec,coh_aver
2216 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
2367 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
2217
2368
2218 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
2369 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
2219
2370
2220 import matplotlib.pyplot as plt
2371 import matplotlib.pyplot as plt
2221 nProf = dataOut.nProfiles
2372 nProf = dataOut.nProfiles
2222 heights = dataOut.heightList
2373 heights = dataOut.heightList
2223 nHei = len(heights)
2374 nHei = len(heights)
2224 channels = dataOut.channelList
2375 channels = dataOut.channelList
2225 nChan = len(channels)
2376 nChan = len(channels)
2226 crosspairs = dataOut.groupList
2377 crosspairs = dataOut.groupList
2227 nPairs = len(crosspairs)
2378 nPairs = len(crosspairs)
2228
2379
2229 #data = dataOut.data_pre[0]
2380 #data = dataOut.data_pre[0]
2230 absc = dataOut.abscissaList[:-1]
2381 absc = dataOut.abscissaList[:-1]
2231 #noise = dataOut.noise
2382 #noise = dataOut.noise
2232 #nChannel = data.shape[0]
2383 #nChannel = data.shape[0]
2233 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
2384 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
2234
2385
2235
2386
2236 #plt.plot(absc)
2387 #plt.plot(absc)
2237 #plt.show()
2388 #plt.show()
2238 clean_coh_spectra = spectra.copy()
2389 clean_coh_spectra = spectra.copy()
2239 clean_coh_cspectra = cspectra.copy()
2390 clean_coh_cspectra = cspectra.copy()
2240 clean_coh_aver = coh_aver.copy()
2391 clean_coh_aver = coh_aver.copy()
2241
2392
2242 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
2393 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
2243 coh_th = 0.75
2394 coh_th = 0.75
2244
2395
2245 rtime0 = [6,18] # periodo sin ESF
2396 rtime0 = [6,18] # periodo sin ESF
2246 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
2397 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
2247
2398
2248 time = index*5./60
2399 time = index*5./60
2249 if clean_coh_echoes == 1 :
2400 if clean_coh_echoes == 1 :
2250 for ind in range(nChan):
2401 for ind in range(nChan):
2251 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
2402 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
2252 #print data_param[:,3]
2403 #print data_param[:,3]
2253 spwd = data_param[:,3]
2404 spwd = data_param[:,3]
2254 #print spwd.shape
2405 #print spwd.shape
2255 # 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
2406 # 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
2256 #spwd1=[ 1.65607, 1.43416, 0.500373, 0.208361, 0.000000, 26.7767, 22.5936, 26.7530, 20.6962, 29.1098, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 28.0300, 27.0511, 27.8810, 26.3126, 27.8445, 24.6181, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000]
2407 #spwd1=[ 1.65607, 1.43416, 0.500373, 0.208361, 0.000000, 26.7767, 22.5936, 26.7530, 20.6962, 29.1098, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 28.0300, 27.0511, 27.8810, 26.3126, 27.8445, 24.6181, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000]
2257 #spwd=numpy.array([spwd1,spwd1,spwd1,spwd1])
2408 #spwd=numpy.array([spwd1,spwd1,spwd1,spwd1])
2258 #print spwd.shape, heights.shape,coh_aver.shape
2409 #print spwd.shape, heights.shape,coh_aver.shape
2259 # para obtener spwd
2410 # para obtener spwd
2260 for ic in range(nPairs):
2411 for ic in range(nPairs):
2261 pair = crosspairs[ic]
2412 pair = crosspairs[ic]
2262 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)))
2413 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)))
2263 for ih in range(nHei) :
2414 for ih in range(nHei) :
2264 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
2415 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
2265 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
2416 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
2266 # Checking coherence
2417 # Checking coherence
2267 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
2418 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
2268 # Checking spectral widths
2419 # Checking spectral widths
2269 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
2420 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
2270 # satelite
2421 # satelite
2271 clean_coh_spectra[pair,ih,:] = 0.0
2422 clean_coh_spectra[pair,ih,:] = 0.0
2272 clean_coh_cspectra[ic,ih,:] = 0.0
2423 clean_coh_cspectra[ic,ih,:] = 0.0
2273 clean_coh_aver[pair,ih] = 0
2424 clean_coh_aver[pair,ih] = 0
2274 else :
2425 else :
2275 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
2426 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
2276 # Especial event like sun.
2427 # Especial event like sun.
2277 clean_coh_spectra[pair,ih,:] = 0.0
2428 clean_coh_spectra[pair,ih,:] = 0.0
2278 clean_coh_cspectra[ic,ih,:] = 0.0
2429 clean_coh_cspectra[ic,ih,:] = 0.0
2279 clean_coh_aver[pair,ih] = 0
2430 clean_coh_aver[pair,ih] = 0
2280
2431
2281 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
2432 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
2282
2433
2283 isConfig = False
2434 isConfig = False
2284 __dataReady = False
2435 __dataReady = False
2285 bloques = None
2436 bloques = None
2286 bloque0 = None
2437 bloque0 = None
2287
2438
2288 def __init__(self):
2439 def __init__(self):
2289 Operation.__init__(self)
2440 Operation.__init__(self)
2290 self.i=0
2441 self.i=0
2291 self.isConfig = False
2442 self.isConfig = False
2292
2443
2293
2444
2294 def setup(self,nChan,nProf,nHei,nBlocks):
2445 def setup(self,nChan,nProf,nHei,nBlocks):
2295 self.__dataReady = False
2446 self.__dataReady = False
2296 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
2447 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
2297 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
2448 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
2298
2449
2299 #def CleanRayleigh(self,dataOut,spectra,cspectra,out_spectra,out_cspectra,sat_spectra,sat_cspectra,crosspairs,heights, channels, nProf,nHei,nChan,nPairs,nIncohInt,nBlocks):
2450 #def CleanRayleigh(self,dataOut,spectra,cspectra,out_spectra,out_cspectra,sat_spectra,sat_cspectra,crosspairs,heights, channels, nProf,nHei,nChan,nPairs,nIncohInt,nBlocks):
2300 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
2451 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
2301 #import matplotlib.pyplot as plt
2452 #import matplotlib.pyplot as plt
2302 #for k in range(149):
2453 #for k in range(149):
2303
2454
2304 # self.bloque0[:,:,:,k] = spectra[:,:,0:nHei]
2455 # self.bloque0[:,:,:,k] = spectra[:,:,0:nHei]
2305 # self.bloques[:,:,:,k] = cspectra[:,:,0:nHei]
2456 # self.bloques[:,:,:,k] = cspectra[:,:,0:nHei]
2306 #if self.i==nBlocks:
2457 #if self.i==nBlocks:
2307 # self.i==0
2458 # self.i==0
2308 rfunc = cspectra.copy() #self.bloques
2459 rfunc = cspectra.copy() #self.bloques
2309 n_funct = len(rfunc[0,:,0,0])
2460 n_funct = len(rfunc[0,:,0,0])
2310 val_spc = spectra*0.0 #self.bloque0*0.0
2461 val_spc = spectra*0.0 #self.bloque0*0.0
2311 val_cspc = cspectra*0.0 #self.bloques*0.0
2462 val_cspc = cspectra*0.0 #self.bloques*0.0
2312 in_sat_spectra = spectra.copy() #self.bloque0
2463 in_sat_spectra = spectra.copy() #self.bloque0
2313 in_sat_cspectra = cspectra.copy() #self.bloques
2464 in_sat_cspectra = cspectra.copy() #self.bloques
2314
2465
2315 #print( rfunc.shape)
2466 #print( rfunc.shape)
2316 min_hei = 200
2467 min_hei = 200
2317 nProf = dataOut.nProfiles
2468 nProf = dataOut.nProfiles
2318 heights = dataOut.heightList
2469 heights = dataOut.heightList
2319 nHei = len(heights)
2470 nHei = len(heights)
2320 channels = dataOut.channelList
2471 channels = dataOut.channelList
2321 nChan = len(channels)
2472 nChan = len(channels)
2322 crosspairs = dataOut.groupList
2473 crosspairs = dataOut.groupList
2323 nPairs = len(crosspairs)
2474 nPairs = len(crosspairs)
2324 hval=(heights >= min_hei).nonzero()
2475 hval=(heights >= min_hei).nonzero()
2325 ih=hval[0]
2476 ih=hval[0]
2326 #print numpy.absolute(rfunc[:,0,0,14])
2477 #print numpy.absolute(rfunc[:,0,0,14])
2327 for ih in range(hval[0][0],nHei):
2478 for ih in range(hval[0][0],nHei):
2328 for ifreq in range(nProf):
2479 for ifreq in range(nProf):
2329 for ii in range(n_funct):
2480 for ii in range(n_funct):
2330
2481
2331 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
2482 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
2332 #print numpy.amin(func2clean)
2483 #print numpy.amin(func2clean)
2333 val = (numpy.isfinite(func2clean)==True).nonzero()
2484 val = (numpy.isfinite(func2clean)==True).nonzero()
2334 if len(val)>0:
2485 if len(val)>0:
2335 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
2486 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
2336 if min_val <= -40 : min_val = -40
2487 if min_val <= -40 : min_val = -40
2337 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
2488 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
2338 if max_val >= 200 : max_val = 200
2489 if max_val >= 200 : max_val = 200
2339 #print min_val, max_val
2490 #print min_val, max_val
2340 step = 1
2491 step = 1
2341 #Getting bins and the histogram
2492 #Getting bins and the histogram
2342 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
2493 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
2343 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
2494 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
2344 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
2495 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
2345 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
2496 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
2346 parg = [numpy.amax(y_dist),mean,sigma]
2497 parg = [numpy.amax(y_dist),mean,sigma]
2347 try :
2498 try :
2348 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
2499 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
2349 mode = gauss_fit[1]
2500 mode = gauss_fit[1]
2350 stdv = gauss_fit[2]
2501 stdv = gauss_fit[2]
2351 except:
2502 except:
2352 mode = mean
2503 mode = mean
2353 stdv = sigma
2504 stdv = sigma
2354 # if ih == 14 and ii == 0 and ifreq ==0 :
2505 # if ih == 14 and ii == 0 and ifreq ==0 :
2355 # print x_dist.shape, y_dist.shape
2506 # print x_dist.shape, y_dist.shape
2356 # print x_dist, y_dist
2507 # print x_dist, y_dist
2357 # print min_val, max_val, binstep
2508 # print min_val, max_val, binstep
2358 # print func2clean
2509 # print func2clean
2359 # print mean,sigma
2510 # print mean,sigma
2360 # mean1,std = norm.fit(y_dist)
2511 # mean1,std = norm.fit(y_dist)
2361 # print mean1, std, gauss_fit
2512 # print mean1, std, gauss_fit
2362 # print fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
2513 # print fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
2363 # 7.84616 53.9307 3.61863
2514 # 7.84616 53.9307 3.61863
2364 #stdv = 3.61863 # 2.99089
2515 #stdv = 3.61863 # 2.99089
2365 #mode = 53.9307 #7.79008
2516 #mode = 53.9307 #7.79008
2366
2517
2367 #Removing echoes greater than mode + 3*stdv
2518 #Removing echoes greater than mode + 3*stdv
2368 factor_stdv = 2.5
2519 factor_stdv = 2.5
2369 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
2520 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
2370
2521
2371 if len(noval[0]) > 0:
2522 if len(noval[0]) > 0:
2372 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
2523 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
2373 cross_pairs = crosspairs[ii]
2524 cross_pairs = crosspairs[ii]
2374 #Getting coherent echoes which are removed.
2525 #Getting coherent echoes which are removed.
2375 if len(novall[0]) > 0:
2526 if len(novall[0]) > 0:
2376 #val_spc[(0,1),novall[a],ih] = 1
2527 #val_spc[(0,1),novall[a],ih] = 1
2377 #val_spc[,(2,3),novall[a],ih] = 1
2528 #val_spc[,(2,3),novall[a],ih] = 1
2378 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
2529 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
2379 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
2530 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
2380 val_cspc[novall[0],ii,ifreq,ih] = 1
2531 val_cspc[novall[0],ii,ifreq,ih] = 1
2381 #print("OUT NOVALL 1")
2532 #print("OUT NOVALL 1")
2382 #Removing coherent from ISR data
2533 #Removing coherent from ISR data
2383 # if ih == 17 and ii == 0 and ifreq ==0 :
2534 # if ih == 17 and ii == 0 and ifreq ==0 :
2384 # print spectra[:,cross_pairs[0],ifreq,ih]
2535 # print spectra[:,cross_pairs[0],ifreq,ih]
2385 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
2536 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
2386 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
2537 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
2387 cspectra[noval,ii,ifreq,ih] = numpy.nan
2538 cspectra[noval,ii,ifreq,ih] = numpy.nan
2388 # if ih == 17 and ii == 0 and ifreq ==0 :
2539 # if ih == 17 and ii == 0 and ifreq ==0 :
2389 # print spectra[:,cross_pairs[0],ifreq,ih]
2540 # print spectra[:,cross_pairs[0],ifreq,ih]
2390 # print noval, len(noval[0])
2541 # print noval, len(noval[0])
2391 # print novall, len(novall[0])
2542 # print novall, len(novall[0])
2392 # print factor_stdv*stdv
2543 # print factor_stdv*stdv
2393 # print func2clean-mode
2544 # print func2clean-mode
2394 # print val_spc[:,cross_pairs[0],ifreq,ih]
2545 # print val_spc[:,cross_pairs[0],ifreq,ih]
2395 # print spectra[:,cross_pairs[0],ifreq,ih]
2546 # print spectra[:,cross_pairs[0],ifreq,ih]
2396 #no sale es para savedrifts >2
2547 #no sale es para savedrifts >2
2397 ''' channels = channels
2548 ''' channels = channels
2398 cross_pairs = cross_pairs
2549 cross_pairs = cross_pairs
2399 #print("OUT NOVALL 2")
2550 #print("OUT NOVALL 2")
2400
2551
2401 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
2552 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
2402 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
2553 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
2403 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
2554 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
2404 #print('vcros =', vcross)
2555 #print('vcros =', vcross)
2405
2556
2406 #Getting coherent echoes which are removed.
2557 #Getting coherent echoes which are removed.
2407 if len(novall) > 0:
2558 if len(novall) > 0:
2408 #val_spc[novall,ii,ifreq,ih] = 1
2559 #val_spc[novall,ii,ifreq,ih] = 1
2409 val_spc[ii,ifreq,ih,novall] = 1
2560 val_spc[ii,ifreq,ih,novall] = 1
2410 if len(vcross) > 0:
2561 if len(vcross) > 0:
2411 val_cspc[vcross,ifreq,ih,novall] = 1
2562 val_cspc[vcross,ifreq,ih,novall] = 1
2412
2563
2413 #Removing coherent from ISR data.
2564 #Removing coherent from ISR data.
2414 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
2565 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
2415 if len(vcross) > 0:
2566 if len(vcross) > 0:
2416 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
2567 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
2417 '''
2568 '''
2418 #Getting average of the spectra and cross-spectra from incoherent echoes.
2569 #Getting average of the spectra and cross-spectra from incoherent echoes.
2419 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
2570 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
2420 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
2571 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
2421 for ih in range(nHei):
2572 for ih in range(nHei):
2422 for ifreq in range(nProf):
2573 for ifreq in range(nProf):
2423 for ich in range(nChan):
2574 for ich in range(nChan):
2424 tmp = spectra[:,ich,ifreq,ih]
2575 tmp = spectra[:,ich,ifreq,ih]
2425 valid = (numpy.isfinite(tmp[:])==True).nonzero()
2576 valid = (numpy.isfinite(tmp[:])==True).nonzero()
2426 # if ich == 0 and ifreq == 0 and ih == 17 :
2577 # if ich == 0 and ifreq == 0 and ih == 17 :
2427 # print tmp
2578 # print tmp
2428 # print valid
2579 # print valid
2429 # print len(valid[0])
2580 # print len(valid[0])
2430 #print('TMP',tmp)
2581 #print('TMP',tmp)
2431 if len(valid[0]) >0 :
2582 if len(valid[0]) >0 :
2432 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2583 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2433 #for icr in range(nPairs):
2584 #for icr in range(nPairs):
2434 for icr in range(nPairs):
2585 for icr in range(nPairs):
2435 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
2586 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
2436 valid = (numpy.isfinite(tmp)==True).nonzero()
2587 valid = (numpy.isfinite(tmp)==True).nonzero()
2437 if len(valid[0]) > 0:
2588 if len(valid[0]) > 0:
2438 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2589 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2439 # print('##########################################################')
2590 # print('##########################################################')
2440 #Removing fake coherent echoes (at least 4 points around the point)
2591 #Removing fake coherent echoes (at least 4 points around the point)
2441
2592
2442 val_spectra = numpy.sum(val_spc,0)
2593 val_spectra = numpy.sum(val_spc,0)
2443 val_cspectra = numpy.sum(val_cspc,0)
2594 val_cspectra = numpy.sum(val_cspc,0)
2444
2595
2445 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
2596 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
2446 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
2597 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
2447
2598
2448 for i in range(nChan):
2599 for i in range(nChan):
2449 for j in range(nProf):
2600 for j in range(nProf):
2450 for k in range(nHei):
2601 for k in range(nHei):
2451 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
2602 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
2452 val_spc[:,i,j,k] = 0.0
2603 val_spc[:,i,j,k] = 0.0
2453 for i in range(nPairs):
2604 for i in range(nPairs):
2454 for j in range(nProf):
2605 for j in range(nProf):
2455 for k in range(nHei):
2606 for k in range(nHei):
2456 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
2607 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
2457 val_cspc[:,i,j,k] = 0.0
2608 val_cspc[:,i,j,k] = 0.0
2458 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHei*nChan))
2609 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHei*nChan))
2459 # if numpy.isfinite(val_spectra)==str(True):
2610 # if numpy.isfinite(val_spectra)==str(True):
2460 # noval = (val_spectra<1).nonzero()
2611 # noval = (val_spectra<1).nonzero()
2461 # if len(noval) > 0:
2612 # if len(noval) > 0:
2462 # val_spc[:,noval] = 0.0
2613 # val_spc[:,noval] = 0.0
2463 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHei))
2614 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHei))
2464
2615
2465 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHei*nProf))
2616 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHei*nProf))
2466 #if numpy.isfinite(val_cspectra)==str(True):
2617 #if numpy.isfinite(val_cspectra)==str(True):
2467 # noval = (val_cspectra<1).nonzero()
2618 # noval = (val_cspectra<1).nonzero()
2468 # if len(noval) > 0:
2619 # if len(noval) > 0:
2469 # val_cspc[:,noval] = 0.0
2620 # val_cspc[:,noval] = 0.0
2470 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHei))
2621 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHei))
2471
2622
2472 tmp_sat_spectra = spectra.copy()
2623 tmp_sat_spectra = spectra.copy()
2473 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
2624 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
2474 tmp_sat_cspectra = cspectra.copy()
2625 tmp_sat_cspectra = cspectra.copy()
2475 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
2626 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
2476
2627
2477 # fig = plt.figure(figsize=(6,5))
2628 # fig = plt.figure(figsize=(6,5))
2478 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2629 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2479 # ax = fig.add_axes([left, bottom, width, height])
2630 # ax = fig.add_axes([left, bottom, width, height])
2480 # cp = ax.contour(10*numpy.log10(numpy.absolute(spectra[0,0,:,:])))
2631 # cp = ax.contour(10*numpy.log10(numpy.absolute(spectra[0,0,:,:])))
2481 # ax.clabel(cp, inline=True,fontsize=10)
2632 # ax.clabel(cp, inline=True,fontsize=10)
2482 # plt.show()
2633 # plt.show()
2483
2634
2484 val = (val_spc > 0).nonzero()
2635 val = (val_spc > 0).nonzero()
2485 if len(val[0]) > 0:
2636 if len(val[0]) > 0:
2486 tmp_sat_spectra[val] = in_sat_spectra[val]
2637 tmp_sat_spectra[val] = in_sat_spectra[val]
2487
2638
2488 val = (val_cspc > 0).nonzero()
2639 val = (val_cspc > 0).nonzero()
2489 if len(val[0]) > 0:
2640 if len(val[0]) > 0:
2490 tmp_sat_cspectra[val] = in_sat_cspectra[val]
2641 tmp_sat_cspectra[val] = in_sat_cspectra[val]
2491
2642
2492 #Getting average of the spectra and cross-spectra from incoherent echoes.
2643 #Getting average of the spectra and cross-spectra from incoherent echoes.
2493 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
2644 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
2494 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
2645 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
2495 for ih in range(nHei):
2646 for ih in range(nHei):
2496 for ifreq in range(nProf):
2647 for ifreq in range(nProf):
2497 for ich in range(nChan):
2648 for ich in range(nChan):
2498 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
2649 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
2499 valid = (numpy.isfinite(tmp)).nonzero()
2650 valid = (numpy.isfinite(tmp)).nonzero()
2500 if len(valid[0]) > 0:
2651 if len(valid[0]) > 0:
2501 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2652 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2502
2653
2503 for icr in range(nPairs):
2654 for icr in range(nPairs):
2504 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
2655 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
2505 valid = (numpy.isfinite(tmp)).nonzero()
2656 valid = (numpy.isfinite(tmp)).nonzero()
2506 if len(valid[0]) > 0:
2657 if len(valid[0]) > 0:
2507 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2658 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2508 #self.__dataReady= True
2659 #self.__dataReady= True
2509 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
2660 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
2510 #if not self.__dataReady:
2661 #if not self.__dataReady:
2511 #return None, None
2662 #return None, None
2512 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
2663 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
2513 def REM_ISOLATED_POINTS(self,array,rth):
2664 def REM_ISOLATED_POINTS(self,array,rth):
2514 # import matplotlib.pyplot as plt
2665 # import matplotlib.pyplot as plt
2515 if rth == None : rth = 4
2666 if rth == None : rth = 4
2516
2667
2517 num_prof = len(array[0,:,0])
2668 num_prof = len(array[0,:,0])
2518 num_hei = len(array[0,0,:])
2669 num_hei = len(array[0,0,:])
2519 n2d = len(array[:,0,0])
2670 n2d = len(array[:,0,0])
2520
2671
2521 for ii in range(n2d) :
2672 for ii in range(n2d) :
2522 #print ii,n2d
2673 #print ii,n2d
2523 tmp = array[ii,:,:]
2674 tmp = array[ii,:,:]
2524 #print tmp.shape, array[ii,101,:],array[ii,102,:]
2675 #print tmp.shape, array[ii,101,:],array[ii,102,:]
2525
2676
2526 # fig = plt.figure(figsize=(6,5))
2677 # fig = plt.figure(figsize=(6,5))
2527 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2678 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2528 # ax = fig.add_axes([left, bottom, width, height])
2679 # ax = fig.add_axes([left, bottom, width, height])
2529 # x = range(num_prof)
2680 # x = range(num_prof)
2530 # y = range(num_hei)
2681 # y = range(num_hei)
2531 # cp = ax.contour(y,x,tmp)
2682 # cp = ax.contour(y,x,tmp)
2532 # ax.clabel(cp, inline=True,fontsize=10)
2683 # ax.clabel(cp, inline=True,fontsize=10)
2533 # plt.show()
2684 # plt.show()
2534
2685
2535 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
2686 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
2536 tmp = numpy.reshape(tmp,num_prof*num_hei)
2687 tmp = numpy.reshape(tmp,num_prof*num_hei)
2537 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
2688 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
2538 indxs2 = (tmp > 0).nonzero()
2689 indxs2 = (tmp > 0).nonzero()
2539
2690
2540 indxs1 = (indxs1[0])
2691 indxs1 = (indxs1[0])
2541 indxs2 = indxs2[0]
2692 indxs2 = indxs2[0]
2542 #indxs1 = numpy.array(indxs1[0])
2693 #indxs1 = numpy.array(indxs1[0])
2543 #indxs2 = numpy.array(indxs2[0])
2694 #indxs2 = numpy.array(indxs2[0])
2544 indxs = None
2695 indxs = None
2545 #print indxs1 , indxs2
2696 #print indxs1 , indxs2
2546 for iv in range(len(indxs2)):
2697 for iv in range(len(indxs2)):
2547 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
2698 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
2548 #print len(indxs2), indv
2699 #print len(indxs2), indv
2549 if len(indv[0]) > 0 :
2700 if len(indv[0]) > 0 :
2550 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
2701 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
2551 # print indxs
2702 # print indxs
2552 indxs = indxs[1:]
2703 indxs = indxs[1:]
2553 #print indxs, len(indxs)
2704 #print indxs, len(indxs)
2554 if len(indxs) < 4 :
2705 if len(indxs) < 4 :
2555 array[ii,:,:] = 0.
2706 array[ii,:,:] = 0.
2556 return
2707 return
2557
2708
2558 xpos = numpy.mod(indxs ,num_hei)
2709 xpos = numpy.mod(indxs ,num_hei)
2559 ypos = (indxs / num_hei)
2710 ypos = (indxs / num_hei)
2560 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
2711 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
2561 #print sx
2712 #print sx
2562 xpos = xpos[sx]
2713 xpos = xpos[sx]
2563 ypos = ypos[sx]
2714 ypos = ypos[sx]
2564
2715
2565 # *********************************** Cleaning isolated points **********************************
2716 # *********************************** Cleaning isolated points **********************************
2566 ic = 0
2717 ic = 0
2567 while True :
2718 while True :
2568 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
2719 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
2569 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
2720 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
2570 #plt.plot(r)
2721 #plt.plot(r)
2571 #plt.show()
2722 #plt.show()
2572 no_coh1 = (numpy.isfinite(r)==True).nonzero()
2723 no_coh1 = (numpy.isfinite(r)==True).nonzero()
2573 no_coh2 = (r <= rth).nonzero()
2724 no_coh2 = (r <= rth).nonzero()
2574 #print r, no_coh1, no_coh2
2725 #print r, no_coh1, no_coh2
2575 no_coh1 = numpy.array(no_coh1[0])
2726 no_coh1 = numpy.array(no_coh1[0])
2576 no_coh2 = numpy.array(no_coh2[0])
2727 no_coh2 = numpy.array(no_coh2[0])
2577 no_coh = None
2728 no_coh = None
2578 #print valid1 , valid2
2729 #print valid1 , valid2
2579 for iv in range(len(no_coh2)):
2730 for iv in range(len(no_coh2)):
2580 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
2731 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
2581 if len(indv[0]) > 0 :
2732 if len(indv[0]) > 0 :
2582 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
2733 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
2583 no_coh = no_coh[1:]
2734 no_coh = no_coh[1:]
2584 #print len(no_coh), no_coh
2735 #print len(no_coh), no_coh
2585 if len(no_coh) < 4 :
2736 if len(no_coh) < 4 :
2586 #print xpos[ic], ypos[ic], ic
2737 #print xpos[ic], ypos[ic], ic
2587 # plt.plot(r)
2738 # plt.plot(r)
2588 # plt.show()
2739 # plt.show()
2589 xpos[ic] = numpy.nan
2740 xpos[ic] = numpy.nan
2590 ypos[ic] = numpy.nan
2741 ypos[ic] = numpy.nan
2591
2742
2592 ic = ic + 1
2743 ic = ic + 1
2593 if (ic == len(indxs)) :
2744 if (ic == len(indxs)) :
2594 break
2745 break
2595 #print( xpos, ypos)
2746 #print( xpos, ypos)
2596
2747
2597 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
2748 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
2598 #print indxs[0]
2749 #print indxs[0]
2599 if len(indxs[0]) < 4 :
2750 if len(indxs[0]) < 4 :
2600 array[ii,:,:] = 0.
2751 array[ii,:,:] = 0.
2601 return
2752 return
2602
2753
2603 xpos = xpos[indxs[0]]
2754 xpos = xpos[indxs[0]]
2604 ypos = ypos[indxs[0]]
2755 ypos = ypos[indxs[0]]
2605 for i in range(0,len(ypos)):
2756 for i in range(0,len(ypos)):
2606 ypos[i]=int(ypos[i])
2757 ypos[i]=int(ypos[i])
2607 junk = tmp
2758 junk = tmp
2608 tmp = junk*0.0
2759 tmp = junk*0.0
2609
2760
2610 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
2761 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
2611 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
2762 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
2612
2763
2613 #print array.shape
2764 #print array.shape
2614 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
2765 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
2615 #print tmp.shape
2766 #print tmp.shape
2616
2767
2617 # fig = plt.figure(figsize=(6,5))
2768 # fig = plt.figure(figsize=(6,5))
2618 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2769 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2619 # ax = fig.add_axes([left, bottom, width, height])
2770 # ax = fig.add_axes([left, bottom, width, height])
2620 # x = range(num_prof)
2771 # x = range(num_prof)
2621 # y = range(num_hei)
2772 # y = range(num_hei)
2622 # cp = ax.contour(y,x,array[ii,:,:])
2773 # cp = ax.contour(y,x,array[ii,:,:])
2623 # ax.clabel(cp, inline=True,fontsize=10)
2774 # ax.clabel(cp, inline=True,fontsize=10)
2624 # plt.show()
2775 # plt.show()
2625 return array
2776 return array
2626 def moments(self,doppler,yarray,npoints):
2777 def moments(self,doppler,yarray,npoints):
2627 ytemp = yarray
2778 ytemp = yarray
2628 #val = WHERE(ytemp GT 0,cval)
2779 #val = WHERE(ytemp GT 0,cval)
2629 #if cval == 0 : val = range(npoints-1)
2780 #if cval == 0 : val = range(npoints-1)
2630 val = (ytemp > 0).nonzero()
2781 val = (ytemp > 0).nonzero()
2631 val = val[0]
2782 val = val[0]
2632 #print('hvalid:',hvalid)
2783 #print('hvalid:',hvalid)
2633 #print('valid', valid)
2784 #print('valid', valid)
2634 if len(val) == 0 : val = range(npoints-1)
2785 if len(val) == 0 : val = range(npoints-1)
2635
2786
2636 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
2787 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
2637 ytemp[len(ytemp):] = [ynew]
2788 ytemp[len(ytemp):] = [ynew]
2638
2789
2639 index = 0
2790 index = 0
2640 index = numpy.argmax(ytemp)
2791 index = numpy.argmax(ytemp)
2641 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
2792 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
2642 ytemp = ytemp[0:npoints-1]
2793 ytemp = ytemp[0:npoints-1]
2643
2794
2644 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
2795 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
2645 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
2796 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
2646 return [fmom,numpy.sqrt(smom)]
2797 return [fmom,numpy.sqrt(smom)]
2647 # **********************************************************************************************
2798 # **********************************************************************************************
2648 index = 0
2799 index = 0
2649 fint = 0
2800 fint = 0
2650 buffer = 0
2801 buffer = 0
2651 buffer2 = 0
2802 buffer2 = 0
2652 buffer3 = 0
2803 buffer3 = 0
2653 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
2804 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
2654 nChannels = dataOut.nChannels
2805 nChannels = dataOut.nChannels
2655 nHeights= dataOut.heightList.size
2806 nHeights= dataOut.heightList.size
2656 nProf = dataOut.nProfiles
2807 nProf = dataOut.nProfiles
2657 tini=time.localtime(dataOut.utctime)
2808 tini=time.localtime(dataOut.utctime)
2658 if (tini.tm_min % 5) == 0 and (tini.tm_sec < 5 and self.fint==0):
2809 if (tini.tm_min % 5) == 0 and (tini.tm_sec < 5 and self.fint==0):
2659 # print tini.tm_min
2810 # print tini.tm_min
2660 self.index = 0
2811 self.index = 0
2661 jspc = self.buffer
2812 jspc = self.buffer
2662 jcspc = self.buffer2
2813 jcspc = self.buffer2
2663 jnoise = self.buffer3
2814 jnoise = self.buffer3
2664 self.buffer = dataOut.data_spc
2815 self.buffer = dataOut.data_spc
2665 self.buffer2 = dataOut.data_cspc
2816 self.buffer2 = dataOut.data_cspc
2666 self.buffer3 = dataOut.noise
2817 self.buffer3 = dataOut.noise
2667 self.fint = 1
2818 self.fint = 1
2668 if numpy.any(jspc) :
2819 if numpy.any(jspc) :
2669 jspc= numpy.reshape(jspc,(int(len(jspc)/4),nChannels,nProf,nHeights))
2820 jspc= numpy.reshape(jspc,(int(len(jspc)/4),nChannels,nProf,nHeights))
2670 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/2),2,nProf,nHeights))
2821 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/2),2,nProf,nHeights))
2671 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/4),nChannels))
2822 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/4),nChannels))
2672 else:
2823 else:
2673 dataOut.flagNoData = True
2824 dataOut.flagNoData = True
2674 return dataOut
2825 return dataOut
2675 else :
2826 else :
2676 if (tini.tm_min % 5) == 0 : self.fint = 1
2827 if (tini.tm_min % 5) == 0 : self.fint = 1
2677 else : self.fint = 0
2828 else : self.fint = 0
2678 self.index += 1
2829 self.index += 1
2679 if numpy.any(self.buffer):
2830 if numpy.any(self.buffer):
2680 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
2831 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
2681 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
2832 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
2682 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
2833 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
2683 else:
2834 else:
2684 self.buffer = dataOut.data_spc
2835 self.buffer = dataOut.data_spc
2685 self.buffer2 = dataOut.data_cspc
2836 self.buffer2 = dataOut.data_cspc
2686 self.buffer3 = dataOut.noise
2837 self.buffer3 = dataOut.noise
2687 dataOut.flagNoData = True
2838 dataOut.flagNoData = True
2688 return dataOut
2839 return dataOut
2689 if path != None:
2840 if path != None:
2690 sys.path.append(path)
2841 sys.path.append(path)
2691 self.library = importlib.import_module(file)
2842 self.library = importlib.import_module(file)
2692
2843
2693 #To be inserted as a parameter
2844 #To be inserted as a parameter
2694 groupArray = numpy.array(groupList)
2845 groupArray = numpy.array(groupList)
2695 #groupArray = numpy.array([[0,1],[2,3]])
2846 #groupArray = numpy.array([[0,1],[2,3]])
2696 dataOut.groupList = groupArray
2847 dataOut.groupList = groupArray
2697
2848
2698 nGroups = groupArray.shape[0]
2849 nGroups = groupArray.shape[0]
2699 nChannels = dataOut.nChannels
2850 nChannels = dataOut.nChannels
2700 nHeights = dataOut.heightList.size
2851 nHeights = dataOut.heightList.size
2701
2852
2702 #Parameters Array
2853 #Parameters Array
2703 dataOut.data_param = None
2854 dataOut.data_param = None
2704 dataOut.data_paramC = None
2855 dataOut.data_paramC = None
2705
2856
2706 #Set constants
2857 #Set constants
2707 constants = self.library.setConstants(dataOut)
2858 constants = self.library.setConstants(dataOut)
2708 dataOut.constants = constants
2859 dataOut.constants = constants
2709 M = dataOut.normFactor
2860 M = dataOut.normFactor
2710 N = dataOut.nFFTPoints
2861 N = dataOut.nFFTPoints
2711 ippSeconds = dataOut.ippSeconds
2862 ippSeconds = dataOut.ippSeconds
2712 K = dataOut.nIncohInt
2863 K = dataOut.nIncohInt
2713 pairsArray = numpy.array(dataOut.pairsList)
2864 pairsArray = numpy.array(dataOut.pairsList)
2714
2865
2715 snrth= 20
2866 snrth= 20
2716 spectra = dataOut.data_spc
2867 spectra = dataOut.data_spc
2717 cspectra = dataOut.data_cspc
2868 cspectra = dataOut.data_cspc
2718 nProf = dataOut.nProfiles
2869 nProf = dataOut.nProfiles
2719 heights = dataOut.heightList
2870 heights = dataOut.heightList
2720 nHei = len(heights)
2871 nHei = len(heights)
2721 channels = dataOut.channelList
2872 channels = dataOut.channelList
2722 nChan = len(channels)
2873 nChan = len(channels)
2723 nIncohInt = dataOut.nIncohInt
2874 nIncohInt = dataOut.nIncohInt
2724 crosspairs = dataOut.groupList
2875 crosspairs = dataOut.groupList
2725 noise = dataOut.noise
2876 noise = dataOut.noise
2726 jnoise = jnoise/N
2877 jnoise = jnoise/N
2727 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
2878 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
2728 power = numpy.sum(spectra, axis=1)
2879 power = numpy.sum(spectra, axis=1)
2729 nPairs = len(crosspairs)
2880 nPairs = len(crosspairs)
2730 absc = dataOut.abscissaList[:-1]
2881 absc = dataOut.abscissaList[:-1]
2731
2882
2732 if not self.isConfig:
2883 if not self.isConfig:
2733 self.isConfig = True
2884 self.isConfig = True
2734
2885
2735 index = tini.tm_hour*12+tini.tm_min/5
2886 index = tini.tm_hour*12+tini.tm_min/5
2736 jspc = jspc/N/N
2887 jspc = jspc/N/N
2737 jcspc = jcspc/N/N
2888 jcspc = jcspc/N/N
2738 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
2889 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
2739 jspectra = tmp_spectra*len(jspc[:,0,0,0])
2890 jspectra = tmp_spectra*len(jspc[:,0,0,0])
2740 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
2891 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
2741 my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver = self.__DiffCoherent(jspectra, jcspectra, dataOut, noise, snrth, None, None)
2892 my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver = self.__DiffCoherent(jspectra, jcspectra, dataOut, noise, snrth, None, None)
2742 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
2893 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
2743 dataOut.data_spc = incoh_spectra
2894 dataOut.data_spc = incoh_spectra
2744 dataOut.data_cspc = incoh_cspectra
2895 dataOut.data_cspc = incoh_cspectra
2745
2896
2746 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
2897 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
2747 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
2898 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
2748 #List of possible combinations
2899 #List of possible combinations
2749 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
2900 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
2750 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
2901 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
2751
2902
2752 if getSNR:
2903 if getSNR:
2753 listChannels = groupArray.reshape((groupArray.size))
2904 listChannels = groupArray.reshape((groupArray.size))
2754 listChannels.sort()
2905 listChannels.sort()
2755 dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
2906 dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
2756 if dataOut.data_paramC is None:
2907 if dataOut.data_paramC is None:
2757 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
2908 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
2758 for i in range(nGroups):
2909 for i in range(nGroups):
2759 coord = groupArray[i,:]
2910 coord = groupArray[i,:]
2760 #Input data array
2911 #Input data array
2761 data = dataOut.data_spc[coord,:,:]/(M*N)
2912 data = dataOut.data_spc[coord,:,:]/(M*N)
2762 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
2913 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
2763
2914
2764 #Cross Spectra data array for Covariance Matrixes
2915 #Cross Spectra data array for Covariance Matrixes
2765 ind = 0
2916 ind = 0
2766 for pairs in listComb:
2917 for pairs in listComb:
2767 pairsSel = numpy.array([coord[x],coord[y]])
2918 pairsSel = numpy.array([coord[x],coord[y]])
2768 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
2919 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
2769 ind += 1
2920 ind += 1
2770 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
2921 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
2771 dataCross = dataCross**2
2922 dataCross = dataCross**2
2772 nhei = nHeights
2923 nhei = nHeights
2773 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
2924 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
2774 if i == 0 : my_noises = numpy.zeros(4,dtype=float) #FLTARR(4)
2925 if i == 0 : my_noises = numpy.zeros(4,dtype=float) #FLTARR(4)
2775 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
2926 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
2776 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
2927 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
2777 n0 = n0i
2928 n0 = n0i
2778 n1= n1i
2929 n1= n1i
2779 my_noises[2*i+0] = n0
2930 my_noises[2*i+0] = n0
2780 my_noises[2*i+1] = n1
2931 my_noises[2*i+1] = n1
2781 snrth = -16.0
2932 snrth = -16.0
2782 snrth = 10**(snrth/10.0)
2933 snrth = 10**(snrth/10.0)
2783
2934
2784 for h in range(nHeights):
2935 for h in range(nHeights):
2785 d = data[:,h]
2936 d = data[:,h]
2786 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
2937 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
2787 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
2938 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
2788 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
2939 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
2789 signal0 = signalpn0-n0
2940 signal0 = signalpn0-n0
2790 signal1 = signalpn1-n1
2941 signal1 = signalpn1-n1
2791 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2942 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2792 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2943 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2793 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
2944 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
2794 #Covariance Matrix
2945 #Covariance Matrix
2795 D = numpy.diag(d**2)
2946 D = numpy.diag(d**2)
2796 ind = 0
2947 ind = 0
2797 for pairs in listComb:
2948 for pairs in listComb:
2798 #Coordinates in Covariance Matrix
2949 #Coordinates in Covariance Matrix
2799 x = pairs[0]
2950 x = pairs[0]
2800 y = pairs[1]
2951 y = pairs[1]
2801 #Channel Index
2952 #Channel Index
2802 S12 = dataCross[ind,:,h]
2953 S12 = dataCross[ind,:,h]
2803 D12 = numpy.diag(S12)
2954 D12 = numpy.diag(S12)
2804 #Completing Covariance Matrix with Cross Spectras
2955 #Completing Covariance Matrix with Cross Spectras
2805 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
2956 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
2806 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
2957 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
2807 ind += 1
2958 ind += 1
2808 diagD = numpy.zeros(256)
2959 diagD = numpy.zeros(256)
2809 if h == 17 :
2960 if h == 17 :
2810 for ii in range(256): diagD[ii] = D[ii,ii]
2961 for ii in range(256): diagD[ii] = D[ii,ii]
2811 #Dinv=numpy.linalg.inv(D)
2962 #Dinv=numpy.linalg.inv(D)
2812 #L=numpy.linalg.cholesky(Dinv)
2963 #L=numpy.linalg.cholesky(Dinv)
2813 try:
2964 try:
2814 Dinv=numpy.linalg.inv(D)
2965 Dinv=numpy.linalg.inv(D)
2815 L=numpy.linalg.cholesky(Dinv)
2966 L=numpy.linalg.cholesky(Dinv)
2816 except:
2967 except:
2817 Dinv = D*numpy.nan
2968 Dinv = D*numpy.nan
2818 L= D*numpy.nan
2969 L= D*numpy.nan
2819 LT=L.T
2970 LT=L.T
2820
2971
2821 dp = numpy.dot(LT,d)
2972 dp = numpy.dot(LT,d)
2822
2973
2823 #Initial values
2974 #Initial values
2824 data_spc = dataOut.data_spc[coord,:,h]
2975 data_spc = dataOut.data_spc[coord,:,h]
2825
2976
2826 if (h>0)and(error1[3]<5):
2977 if (h>0)and(error1[3]<5):
2827 p0 = dataOut.data_param[i,:,h-1]
2978 p0 = dataOut.data_param[i,:,h-1]
2828 else:
2979 else:
2829 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))# sin el i(data_spc, constants, i)
2980 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))# sin el i(data_spc, constants, i)
2830 try:
2981 try:
2831 #Least Squares
2982 #Least Squares
2832 #print (dp,LT,constants)
2983 #print (dp,LT,constants)
2833 #value =self.__residFunction(p0,dp,LT,constants)
2984 #value =self.__residFunction(p0,dp,LT,constants)
2834 #print ("valueREADY",value.shape, type(value))
2985 #print ("valueREADY",value.shape, type(value))
2835 #optimize.leastsq(value)
2986 #optimize.leastsq(value)
2836 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
2987 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
2837 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
2988 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
2838 #Chi square error
2989 #Chi square error
2839 #print(minp,covp.infodict,mesg,ier)
2990 #print(minp,covp.infodict,mesg,ier)
2840 #print("REALIZA OPTIMIZ")
2991 #print("REALIZA OPTIMIZ")
2841 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
2992 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
2842 #Error with Jacobian
2993 #Error with Jacobian
2843 error1 = self.library.errorFunction(minp,constants,LT)
2994 error1 = self.library.errorFunction(minp,constants,LT)
2844 # print self.__residFunction(p0,dp,LT, constants)
2995 # print self.__residFunction(p0,dp,LT, constants)
2845 # print infodict['fvec']
2996 # print infodict['fvec']
2846 # print self.__residFunction(minp,dp,LT,constants)
2997 # print self.__residFunction(minp,dp,LT,constants)
2847
2998
2848 except:
2999 except:
2849 minp = p0*numpy.nan
3000 minp = p0*numpy.nan
2850 error0 = numpy.nan
3001 error0 = numpy.nan
2851 error1 = p0*numpy.nan
3002 error1 = p0*numpy.nan
2852 #print ("EXCEPT 0000000000")
3003 #print ("EXCEPT 0000000000")
2853 # s_sq = (self.__residFunction(minp,dp,LT,constants)).sum()/(len(dp)-len(p0))
3004 # s_sq = (self.__residFunction(minp,dp,LT,constants)).sum()/(len(dp)-len(p0))
2854 # covp = covp*s_sq
3005 # covp = covp*s_sq
2855 # #print("TRY___________________________________________1")
3006 # #print("TRY___________________________________________1")
2856 # error = []
3007 # error = []
2857 # for ip in range(len(minp)):
3008 # for ip in range(len(minp)):
2858 # try:
3009 # try:
2859 # error.append(numpy.absolute(covp[ip][ip])**0.5)
3010 # error.append(numpy.absolute(covp[ip][ip])**0.5)
2860 # except:
3011 # except:
2861 # error.append( 0.00 )
3012 # error.append( 0.00 )
2862 else :
3013 else :
2863 data_spc = dataOut.data_spc[coord,:,h]
3014 data_spc = dataOut.data_spc[coord,:,h]
2864 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
3015 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
2865 minp = p0*numpy.nan
3016 minp = p0*numpy.nan
2866 error0 = numpy.nan
3017 error0 = numpy.nan
2867 error1 = p0*numpy.nan
3018 error1 = p0*numpy.nan
2868 #Save
3019 #Save
2869 if dataOut.data_param is None:
3020 if dataOut.data_param is None:
2870 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
3021 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
2871 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
3022 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
2872
3023
2873 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
3024 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
2874 dataOut.data_param[i,:,h] = minp
3025 dataOut.data_param[i,:,h] = minp
2875
3026
2876 for ht in range(nHeights-1) :
3027 for ht in range(nHeights-1) :
2877 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
3028 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
2878 dataOut.data_paramC[4*i,ht,1] = smooth
3029 dataOut.data_paramC[4*i,ht,1] = smooth
2879 signalpn0 = (coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
3030 signalpn0 = (coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
2880 signalpn1 = (coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
3031 signalpn1 = (coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
2881
3032
2882 #val0 = WHERE(signalpn0 > 0,cval0)
3033 #val0 = WHERE(signalpn0 > 0,cval0)
2883 val0 = (signalpn0 > 0).nonzero()
3034 val0 = (signalpn0 > 0).nonzero()
2884 val0 = val0[0]
3035 val0 = val0[0]
2885 #print('hvalid:',hvalid)
3036 #print('hvalid:',hvalid)
2886 #print('valid', valid)
3037 #print('valid', valid)
2887 if len(val0) == 0 : val0_npoints = nProf
3038 if len(val0) == 0 : val0_npoints = nProf
2888 else : val0_npoints = len(val0)
3039 else : val0_npoints = len(val0)
2889
3040
2890 #val1 = WHERE(signalpn1 > 0,cval1)
3041 #val1 = WHERE(signalpn1 > 0,cval1)
2891 val1 = (signalpn1 > 0).nonzero()
3042 val1 = (signalpn1 > 0).nonzero()
2892 val1 = val1[0]
3043 val1 = val1[0]
2893 if len(val1) == 0 : val1_npoints = nProf
3044 if len(val1) == 0 : val1_npoints = nProf
2894 else : val1_npoints = len(val1)
3045 else : val1_npoints = len(val1)
2895
3046
2896 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
3047 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
2897 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
3048 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
2898
3049
2899 signal0 = (signalpn0-n0) # > 0
3050 signal0 = (signalpn0-n0) # > 0
2900 vali = (signal0 < 0).nonzero()
3051 vali = (signal0 < 0).nonzero()
2901 vali = vali[0]
3052 vali = vali[0]
2902 if len(vali) > 0 : signal0[vali] = 0
3053 if len(vali) > 0 : signal0[vali] = 0
2903 signal1 = (signalpn1-n1) #> 0
3054 signal1 = (signalpn1-n1) #> 0
2904 vali = (signal1 < 0).nonzero()
3055 vali = (signal1 < 0).nonzero()
2905 vali = vali[0]
3056 vali = vali[0]
2906 if len(vali) > 0 : signal1[vali] = 0
3057 if len(vali) > 0 : signal1[vali] = 0
2907 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3058 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2908 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3059 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2909 doppler = absc[1:]
3060 doppler = absc[1:]
2910 if snr0 >= snrth and snr1 >= snrth and smooth :
3061 if snr0 >= snrth and snr1 >= snrth and smooth :
2911 signalpn0_n0 = signalpn0
3062 signalpn0_n0 = signalpn0
2912 signalpn0_n0[val0] = signalpn0[val0] - n0
3063 signalpn0_n0[val0] = signalpn0[val0] - n0
2913 mom0 = self.moments(doppler,signalpn0-n0,nProf)
3064 mom0 = self.moments(doppler,signalpn0-n0,nProf)
2914 # sigtmp= numpy.transpose(numpy.tile(signalpn0, [4,1]))
3065 # sigtmp= numpy.transpose(numpy.tile(signalpn0, [4,1]))
2915 # momt= self.__calculateMoments( sigtmp, doppler , n0 )
3066 # momt= self.__calculateMoments( sigtmp, doppler , n0 )
2916 signalpn1_n1 = signalpn1
3067 signalpn1_n1 = signalpn1
2917 signalpn1_n1[val1] = signalpn1[val1] - n1
3068 signalpn1_n1[val1] = signalpn1[val1] - n1
2918 mom1 = self.moments(doppler,signalpn1_n1,nProf)
3069 mom1 = self.moments(doppler,signalpn1_n1,nProf)
2919 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
3070 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
2920 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
3071 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
2921 # if graph == 1 :
3072 # if graph == 1 :
2922 # window, 13
3073 # window, 13
2923 # plot,doppler,signalpn0
3074 # plot,doppler,signalpn0
2924 # oplot,doppler,signalpn1,linest=1
3075 # oplot,doppler,signalpn1,linest=1
2925 # oplot,mom0(0)*doppler/doppler,signalpn0
3076 # oplot,mom0(0)*doppler/doppler,signalpn0
2926 # oplot,mom1(0)*doppler/doppler,signalpn1
3077 # oplot,mom1(0)*doppler/doppler,signalpn1
2927 # print,interval/12.,beam,45+ht*15,snr0,snr1,mom0(0),mom1(0),mom0(1),mom1(1)
3078 # print,interval/12.,beam,45+ht*15,snr0,snr1,mom0(0),mom1(0),mom0(1),mom1(1)
2928 #ENDIF
3079 #ENDIF
2929 #ENDIF
3080 #ENDIF
2930 #ENDFOR End height
3081 #ENDFOR End height
2931
3082
2932 dataOut.data_spc = jspectra
3083 dataOut.data_spc = jspectra
2933 if getSNR:
3084 if getSNR:
2934 listChannels = groupArray.reshape((groupArray.size))
3085 listChannels = groupArray.reshape((groupArray.size))
2935 listChannels.sort()
3086 listChannels.sort()
2936
3087
2937 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels])
3088 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels])
2938 return dataOut
3089 return dataOut
2939
3090
2940 def __residFunction(self, p, dp, LT, constants):
3091 def __residFunction(self, p, dp, LT, constants):
2941
3092
2942 fm = self.library.modelFunction(p, constants)
3093 fm = self.library.modelFunction(p, constants)
2943 fmp=numpy.dot(LT,fm)
3094 fmp=numpy.dot(LT,fm)
2944 return dp-fmp
3095 return dp-fmp
2945
3096
2946 def __getSNR(self, z, noise):
3097 def __getSNR(self, z, noise):
2947
3098
2948 avg = numpy.average(z, axis=1)
3099 avg = numpy.average(z, axis=1)
2949 SNR = (avg.T-noise)/noise
3100 SNR = (avg.T-noise)/noise
2950 SNR = SNR.T
3101 SNR = SNR.T
2951 return SNR
3102 return SNR
2952
3103
2953 def __chisq(self, p, chindex, hindex):
3104 def __chisq(self, p, chindex, hindex):
2954 #similar to Resid but calculates CHI**2
3105 #similar to Resid but calculates CHI**2
2955 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
3106 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
2956 dp=numpy.dot(LT,d)
3107 dp=numpy.dot(LT,d)
2957 fmp=numpy.dot(LT,fm)
3108 fmp=numpy.dot(LT,fm)
2958 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
3109 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
2959 return chisq
3110 return chisq
2960
3111
2961 class WindProfiler(Operation):
3112 class WindProfiler(Operation):
2962
3113
2963 __isConfig = False
3114 __isConfig = False
2964
3115
2965 __initime = None
3116 __initime = None
2966 __lastdatatime = None
3117 __lastdatatime = None
2967 __integrationtime = None
3118 __integrationtime = None
2968
3119
2969 __buffer = None
3120 __buffer = None
2970
3121
2971 __dataReady = False
3122 __dataReady = False
2972
3123
2973 __firstdata = None
3124 __firstdata = None
2974
3125
2975 n = None
3126 n = None
2976
3127
2977 def __init__(self):
3128 def __init__(self):
2978 Operation.__init__(self)
3129 Operation.__init__(self)
2979
3130
2980 def __calculateCosDir(self, elev, azim):
3131 def __calculateCosDir(self, elev, azim):
2981 zen = (90 - elev)*numpy.pi/180
3132 zen = (90 - elev)*numpy.pi/180
2982 azim = azim*numpy.pi/180
3133 azim = azim*numpy.pi/180
2983 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
3134 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
2984 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
3135 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
2985
3136
2986 signX = numpy.sign(numpy.cos(azim))
3137 signX = numpy.sign(numpy.cos(azim))
2987 signY = numpy.sign(numpy.sin(azim))
3138 signY = numpy.sign(numpy.sin(azim))
2988
3139
2989 cosDirX = numpy.copysign(cosDirX, signX)
3140 cosDirX = numpy.copysign(cosDirX, signX)
2990 cosDirY = numpy.copysign(cosDirY, signY)
3141 cosDirY = numpy.copysign(cosDirY, signY)
2991 return cosDirX, cosDirY
3142 return cosDirX, cosDirY
2992
3143
2993 def __calculateAngles(self, theta_x, theta_y, azimuth):
3144 def __calculateAngles(self, theta_x, theta_y, azimuth):
2994
3145
2995 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
3146 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
2996 zenith_arr = numpy.arccos(dir_cosw)
3147 zenith_arr = numpy.arccos(dir_cosw)
2997 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
3148 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
2998
3149
2999 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
3150 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
3000 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
3151 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
3001
3152
3002 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
3153 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
3003
3154
3004 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
3155 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
3005
3156
3006 if horOnly:
3157 if horOnly:
3007 A = numpy.c_[dir_cosu,dir_cosv]
3158 A = numpy.c_[dir_cosu,dir_cosv]
3008 else:
3159 else:
3009 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
3160 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
3010 A = numpy.asmatrix(A)
3161 A = numpy.asmatrix(A)
3011 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
3162 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
3012
3163
3013 return A1
3164 return A1
3014
3165
3015 def __correctValues(self, heiRang, phi, velRadial, SNR):
3166 def __correctValues(self, heiRang, phi, velRadial, SNR):
3016 listPhi = phi.tolist()
3167 listPhi = phi.tolist()
3017 maxid = listPhi.index(max(listPhi))
3168 maxid = listPhi.index(max(listPhi))
3018 minid = listPhi.index(min(listPhi))
3169 minid = listPhi.index(min(listPhi))
3019
3170
3020 rango = list(range(len(phi)))
3171 rango = list(range(len(phi)))
3021 # rango = numpy.delete(rango,maxid)
3172 # rango = numpy.delete(rango,maxid)
3022
3173
3023 heiRang1 = heiRang*math.cos(phi[maxid])
3174 heiRang1 = heiRang*math.cos(phi[maxid])
3024 heiRangAux = heiRang*math.cos(phi[minid])
3175 heiRangAux = heiRang*math.cos(phi[minid])
3025 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3176 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3026 heiRang1 = numpy.delete(heiRang1,indOut)
3177 heiRang1 = numpy.delete(heiRang1,indOut)
3027
3178
3028 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3179 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3029 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3180 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3030
3181
3031 for i in rango:
3182 for i in rango:
3032 x = heiRang*math.cos(phi[i])
3183 x = heiRang*math.cos(phi[i])
3033 y1 = velRadial[i,:]
3184 y1 = velRadial[i,:]
3034 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
3185 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
3035
3186
3036 x1 = heiRang1
3187 x1 = heiRang1
3037 y11 = f1(x1)
3188 y11 = f1(x1)
3038
3189
3039 y2 = SNR[i,:]
3190 y2 = SNR[i,:]
3040 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
3191 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
3041 y21 = f2(x1)
3192 y21 = f2(x1)
3042
3193
3043 velRadial1[i,:] = y11
3194 velRadial1[i,:] = y11
3044 SNR1[i,:] = y21
3195 SNR1[i,:] = y21
3045
3196
3046 return heiRang1, velRadial1, SNR1
3197 return heiRang1, velRadial1, SNR1
3047
3198
3048 def __calculateVelUVW(self, A, velRadial):
3199 def __calculateVelUVW(self, A, velRadial):
3049
3200
3050 #Operacion Matricial
3201 #Operacion Matricial
3051 # velUVW = numpy.zeros((velRadial.shape[1],3))
3202 # velUVW = numpy.zeros((velRadial.shape[1],3))
3052 # for ind in range(velRadial.shape[1]):
3203 # for ind in range(velRadial.shape[1]):
3053 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
3204 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
3054 # velUVW = velUVW.transpose()
3205 # velUVW = velUVW.transpose()
3055 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
3206 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
3056 velUVW[:,:] = numpy.dot(A,velRadial)
3207 velUVW[:,:] = numpy.dot(A,velRadial)
3057
3208
3058
3209
3059 return velUVW
3210 return velUVW
3060
3211
3061 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
3212 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
3062
3213
3063 def techniqueDBS(self, kwargs):
3214 def techniqueDBS(self, kwargs):
3064 """
3215 """
3065 Function that implements Doppler Beam Swinging (DBS) technique.
3216 Function that implements Doppler Beam Swinging (DBS) technique.
3066
3217
3067 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3218 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3068 Direction correction (if necessary), Ranges and SNR
3219 Direction correction (if necessary), Ranges and SNR
3069
3220
3070 Output: Winds estimation (Zonal, Meridional and Vertical)
3221 Output: Winds estimation (Zonal, Meridional and Vertical)
3071
3222
3072 Parameters affected: Winds, height range, SNR
3223 Parameters affected: Winds, height range, SNR
3073 """
3224 """
3074 velRadial0 = kwargs['velRadial']
3225 velRadial0 = kwargs['velRadial']
3075 heiRang = kwargs['heightList']
3226 heiRang = kwargs['heightList']
3076 SNR0 = kwargs['SNR']
3227 SNR0 = kwargs['SNR']
3077
3228
3078 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
3229 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
3079 theta_x = numpy.array(kwargs['dirCosx'])
3230 theta_x = numpy.array(kwargs['dirCosx'])
3080 theta_y = numpy.array(kwargs['dirCosy'])
3231 theta_y = numpy.array(kwargs['dirCosy'])
3081 else:
3232 else:
3082 elev = numpy.array(kwargs['elevation'])
3233 elev = numpy.array(kwargs['elevation'])
3083 azim = numpy.array(kwargs['azimuth'])
3234 azim = numpy.array(kwargs['azimuth'])
3084 theta_x, theta_y = self.__calculateCosDir(elev, azim)
3235 theta_x, theta_y = self.__calculateCosDir(elev, azim)
3085 azimuth = kwargs['correctAzimuth']
3236 azimuth = kwargs['correctAzimuth']
3086 if 'horizontalOnly' in kwargs:
3237 if 'horizontalOnly' in kwargs:
3087 horizontalOnly = kwargs['horizontalOnly']
3238 horizontalOnly = kwargs['horizontalOnly']
3088 else: horizontalOnly = False
3239 else: horizontalOnly = False
3089 if 'correctFactor' in kwargs:
3240 if 'correctFactor' in kwargs:
3090 correctFactor = kwargs['correctFactor']
3241 correctFactor = kwargs['correctFactor']
3091 else: correctFactor = 1
3242 else: correctFactor = 1
3092 if 'channelList' in kwargs:
3243 if 'channelList' in kwargs:
3093 channelList = kwargs['channelList']
3244 channelList = kwargs['channelList']
3094 if len(channelList) == 2:
3245 if len(channelList) == 2:
3095 horizontalOnly = True
3246 horizontalOnly = True
3096 arrayChannel = numpy.array(channelList)
3247 arrayChannel = numpy.array(channelList)
3097 param = param[arrayChannel,:,:]
3248 param = param[arrayChannel,:,:]
3098 theta_x = theta_x[arrayChannel]
3249 theta_x = theta_x[arrayChannel]
3099 theta_y = theta_y[arrayChannel]
3250 theta_y = theta_y[arrayChannel]
3100
3251
3101 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3252 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3102 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
3253 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
3103 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
3254 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
3104
3255
3105 #Calculo de Componentes de la velocidad con DBS
3256 #Calculo de Componentes de la velocidad con DBS
3106 winds = self.__calculateVelUVW(A,velRadial1)
3257 winds = self.__calculateVelUVW(A,velRadial1)
3107
3258
3108 return winds, heiRang1, SNR1
3259 return winds, heiRang1, SNR1
3109
3260
3110 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
3261 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
3111
3262
3112 nPairs = len(pairs_ccf)
3263 nPairs = len(pairs_ccf)
3113 posx = numpy.asarray(posx)
3264 posx = numpy.asarray(posx)
3114 posy = numpy.asarray(posy)
3265 posy = numpy.asarray(posy)
3115
3266
3116 #Rotacion Inversa para alinear con el azimuth
3267 #Rotacion Inversa para alinear con el azimuth
3117 if azimuth!= None:
3268 if azimuth!= None:
3118 azimuth = azimuth*math.pi/180
3269 azimuth = azimuth*math.pi/180
3119 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
3270 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
3120 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
3271 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
3121 else:
3272 else:
3122 posx1 = posx
3273 posx1 = posx
3123 posy1 = posy
3274 posy1 = posy
3124
3275
3125 #Calculo de Distancias
3276 #Calculo de Distancias
3126 distx = numpy.zeros(nPairs)
3277 distx = numpy.zeros(nPairs)
3127 disty = numpy.zeros(nPairs)
3278 disty = numpy.zeros(nPairs)
3128 dist = numpy.zeros(nPairs)
3279 dist = numpy.zeros(nPairs)
3129 ang = numpy.zeros(nPairs)
3280 ang = numpy.zeros(nPairs)
3130
3281
3131 for i in range(nPairs):
3282 for i in range(nPairs):
3132 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
3283 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
3133 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
3284 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
3134 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
3285 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
3135 ang[i] = numpy.arctan2(disty[i],distx[i])
3286 ang[i] = numpy.arctan2(disty[i],distx[i])
3136
3287
3137 return distx, disty, dist, ang
3288 return distx, disty, dist, ang
3138 #Calculo de Matrices
3289 #Calculo de Matrices
3139 # nPairs = len(pairs)
3290 # nPairs = len(pairs)
3140 # ang1 = numpy.zeros((nPairs, 2, 1))
3291 # ang1 = numpy.zeros((nPairs, 2, 1))
3141 # dist1 = numpy.zeros((nPairs, 2, 1))
3292 # dist1 = numpy.zeros((nPairs, 2, 1))
3142 #
3293 #
3143 # for j in range(nPairs):
3294 # for j in range(nPairs):
3144 # dist1[j,0,0] = dist[pairs[j][0]]
3295 # dist1[j,0,0] = dist[pairs[j][0]]
3145 # dist1[j,1,0] = dist[pairs[j][1]]
3296 # dist1[j,1,0] = dist[pairs[j][1]]
3146 # ang1[j,0,0] = ang[pairs[j][0]]
3297 # ang1[j,0,0] = ang[pairs[j][0]]
3147 # ang1[j,1,0] = ang[pairs[j][1]]
3298 # ang1[j,1,0] = ang[pairs[j][1]]
3148 #
3299 #
3149 # return distx,disty, dist1,ang1
3300 # return distx,disty, dist1,ang1
3150
3301
3151
3302
3152 def __calculateVelVer(self, phase, lagTRange, _lambda):
3303 def __calculateVelVer(self, phase, lagTRange, _lambda):
3153
3304
3154 Ts = lagTRange[1] - lagTRange[0]
3305 Ts = lagTRange[1] - lagTRange[0]
3155 velW = -_lambda*phase/(4*math.pi*Ts)
3306 velW = -_lambda*phase/(4*math.pi*Ts)
3156
3307
3157 return velW
3308 return velW
3158
3309
3159 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
3310 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
3160 nPairs = tau1.shape[0]
3311 nPairs = tau1.shape[0]
3161 nHeights = tau1.shape[1]
3312 nHeights = tau1.shape[1]
3162 vel = numpy.zeros((nPairs,3,nHeights))
3313 vel = numpy.zeros((nPairs,3,nHeights))
3163 dist1 = numpy.reshape(dist, (dist.size,1))
3314 dist1 = numpy.reshape(dist, (dist.size,1))
3164
3315
3165 angCos = numpy.cos(ang)
3316 angCos = numpy.cos(ang)
3166 angSin = numpy.sin(ang)
3317 angSin = numpy.sin(ang)
3167
3318
3168 vel0 = dist1*tau1/(2*tau2**2)
3319 vel0 = dist1*tau1/(2*tau2**2)
3169 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
3320 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
3170 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
3321 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
3171
3322
3172 ind = numpy.where(numpy.isinf(vel))
3323 ind = numpy.where(numpy.isinf(vel))
3173 vel[ind] = numpy.nan
3324 vel[ind] = numpy.nan
3174
3325
3175 return vel
3326 return vel
3176
3327
3177 # def __getPairsAutoCorr(self, pairsList, nChannels):
3328 # def __getPairsAutoCorr(self, pairsList, nChannels):
3178 #
3329 #
3179 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
3330 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
3180 #
3331 #
3181 # for l in range(len(pairsList)):
3332 # for l in range(len(pairsList)):
3182 # firstChannel = pairsList[l][0]
3333 # firstChannel = pairsList[l][0]
3183 # secondChannel = pairsList[l][1]
3334 # secondChannel = pairsList[l][1]
3184 #
3335 #
3185 # #Obteniendo pares de Autocorrelacion
3336 # #Obteniendo pares de Autocorrelacion
3186 # if firstChannel == secondChannel:
3337 # if firstChannel == secondChannel:
3187 # pairsAutoCorr[firstChannel] = int(l)
3338 # pairsAutoCorr[firstChannel] = int(l)
3188 #
3339 #
3189 # pairsAutoCorr = pairsAutoCorr.astype(int)
3340 # pairsAutoCorr = pairsAutoCorr.astype(int)
3190 #
3341 #
3191 # pairsCrossCorr = range(len(pairsList))
3342 # pairsCrossCorr = range(len(pairsList))
3192 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
3343 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
3193 #
3344 #
3194 # return pairsAutoCorr, pairsCrossCorr
3345 # return pairsAutoCorr, pairsCrossCorr
3195
3346
3196 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
3347 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
3197 def techniqueSA(self, kwargs):
3348 def techniqueSA(self, kwargs):
3198
3349
3199 """
3350 """
3200 Function that implements Spaced Antenna (SA) technique.
3351 Function that implements Spaced Antenna (SA) technique.
3201
3352
3202 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3353 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3203 Direction correction (if necessary), Ranges and SNR
3354 Direction correction (if necessary), Ranges and SNR
3204
3355
3205 Output: Winds estimation (Zonal, Meridional and Vertical)
3356 Output: Winds estimation (Zonal, Meridional and Vertical)
3206
3357
3207 Parameters affected: Winds
3358 Parameters affected: Winds
3208 """
3359 """
3209 position_x = kwargs['positionX']
3360 position_x = kwargs['positionX']
3210 position_y = kwargs['positionY']
3361 position_y = kwargs['positionY']
3211 azimuth = kwargs['azimuth']
3362 azimuth = kwargs['azimuth']
3212
3363
3213 if 'correctFactor' in kwargs:
3364 if 'correctFactor' in kwargs:
3214 correctFactor = kwargs['correctFactor']
3365 correctFactor = kwargs['correctFactor']
3215 else:
3366 else:
3216 correctFactor = 1
3367 correctFactor = 1
3217
3368
3218 groupList = kwargs['groupList']
3369 groupList = kwargs['groupList']
3219 pairs_ccf = groupList[1]
3370 pairs_ccf = groupList[1]
3220 tau = kwargs['tau']
3371 tau = kwargs['tau']
3221 _lambda = kwargs['_lambda']
3372 _lambda = kwargs['_lambda']
3222
3373
3223 #Cross Correlation pairs obtained
3374 #Cross Correlation pairs obtained
3224 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
3375 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
3225 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
3376 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
3226 # pairsSelArray = numpy.array(pairsSelected)
3377 # pairsSelArray = numpy.array(pairsSelected)
3227 # pairs = []
3378 # pairs = []
3228 #
3379 #
3229 # #Wind estimation pairs obtained
3380 # #Wind estimation pairs obtained
3230 # for i in range(pairsSelArray.shape[0]/2):
3381 # for i in range(pairsSelArray.shape[0]/2):
3231 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
3382 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
3232 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
3383 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
3233 # pairs.append((ind1,ind2))
3384 # pairs.append((ind1,ind2))
3234
3385
3235 indtau = tau.shape[0]/2
3386 indtau = tau.shape[0]/2
3236 tau1 = tau[:indtau,:]
3387 tau1 = tau[:indtau,:]
3237 tau2 = tau[indtau:-1,:]
3388 tau2 = tau[indtau:-1,:]
3238 # tau1 = tau1[pairs,:]
3389 # tau1 = tau1[pairs,:]
3239 # tau2 = tau2[pairs,:]
3390 # tau2 = tau2[pairs,:]
3240 phase1 = tau[-1,:]
3391 phase1 = tau[-1,:]
3241
3392
3242 #---------------------------------------------------------------------
3393 #---------------------------------------------------------------------
3243 #Metodo Directo
3394 #Metodo Directo
3244 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
3395 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
3245 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
3396 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
3246 winds = stats.nanmean(winds, axis=0)
3397 winds = stats.nanmean(winds, axis=0)
3247 #---------------------------------------------------------------------
3398 #---------------------------------------------------------------------
3248 #Metodo General
3399 #Metodo General
3249 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
3400 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
3250 # #Calculo Coeficientes de Funcion de Correlacion
3401 # #Calculo Coeficientes de Funcion de Correlacion
3251 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
3402 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
3252 # #Calculo de Velocidades
3403 # #Calculo de Velocidades
3253 # winds = self.calculateVelUV(F,G,A,B,H)
3404 # winds = self.calculateVelUV(F,G,A,B,H)
3254
3405
3255 #---------------------------------------------------------------------
3406 #---------------------------------------------------------------------
3256 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
3407 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
3257 winds = correctFactor*winds
3408 winds = correctFactor*winds
3258 return winds
3409 return winds
3259
3410
3260 def __checkTime(self, currentTime, paramInterval, outputInterval):
3411 def __checkTime(self, currentTime, paramInterval, outputInterval):
3261
3412
3262 dataTime = currentTime + paramInterval
3413 dataTime = currentTime + paramInterval
3263 deltaTime = dataTime - self.__initime
3414 deltaTime = dataTime - self.__initime
3264
3415
3265 if deltaTime >= outputInterval or deltaTime < 0:
3416 if deltaTime >= outputInterval or deltaTime < 0:
3266 self.__dataReady = True
3417 self.__dataReady = True
3267 return
3418 return
3268
3419
3269 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
3420 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
3270 '''
3421 '''
3271 Function that implements winds estimation technique with detected meteors.
3422 Function that implements winds estimation technique with detected meteors.
3272
3423
3273 Input: Detected meteors, Minimum meteor quantity to wind estimation
3424 Input: Detected meteors, Minimum meteor quantity to wind estimation
3274
3425
3275 Output: Winds estimation (Zonal and Meridional)
3426 Output: Winds estimation (Zonal and Meridional)
3276
3427
3277 Parameters affected: Winds
3428 Parameters affected: Winds
3278 '''
3429 '''
3279 #Settings
3430 #Settings
3280 nInt = (heightMax - heightMin)/2
3431 nInt = (heightMax - heightMin)/2
3281 nInt = int(nInt)
3432 nInt = int(nInt)
3282 winds = numpy.zeros((2,nInt))*numpy.nan
3433 winds = numpy.zeros((2,nInt))*numpy.nan
3283
3434
3284 #Filter errors
3435 #Filter errors
3285 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
3436 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
3286 finalMeteor = arrayMeteor[error,:]
3437 finalMeteor = arrayMeteor[error,:]
3287
3438
3288 #Meteor Histogram
3439 #Meteor Histogram
3289 finalHeights = finalMeteor[:,2]
3440 finalHeights = finalMeteor[:,2]
3290 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
3441 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
3291 nMeteorsPerI = hist[0]
3442 nMeteorsPerI = hist[0]
3292 heightPerI = hist[1]
3443 heightPerI = hist[1]
3293
3444
3294 #Sort of meteors
3445 #Sort of meteors
3295 indSort = finalHeights.argsort()
3446 indSort = finalHeights.argsort()
3296 finalMeteor2 = finalMeteor[indSort,:]
3447 finalMeteor2 = finalMeteor[indSort,:]
3297
3448
3298 # Calculating winds
3449 # Calculating winds
3299 ind1 = 0
3450 ind1 = 0
3300 ind2 = 0
3451 ind2 = 0
3301
3452
3302 for i in range(nInt):
3453 for i in range(nInt):
3303 nMet = nMeteorsPerI[i]
3454 nMet = nMeteorsPerI[i]
3304 ind1 = ind2
3455 ind1 = ind2
3305 ind2 = ind1 + nMet
3456 ind2 = ind1 + nMet
3306
3457
3307 meteorAux = finalMeteor2[ind1:ind2,:]
3458 meteorAux = finalMeteor2[ind1:ind2,:]
3308
3459
3309 if meteorAux.shape[0] >= meteorThresh:
3460 if meteorAux.shape[0] >= meteorThresh:
3310 vel = meteorAux[:, 6]
3461 vel = meteorAux[:, 6]
3311 zen = meteorAux[:, 4]*numpy.pi/180
3462 zen = meteorAux[:, 4]*numpy.pi/180
3312 azim = meteorAux[:, 3]*numpy.pi/180
3463 azim = meteorAux[:, 3]*numpy.pi/180
3313
3464
3314 n = numpy.cos(zen)
3465 n = numpy.cos(zen)
3315 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
3466 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
3316 # l = m*numpy.tan(azim)
3467 # l = m*numpy.tan(azim)
3317 l = numpy.sin(zen)*numpy.sin(azim)
3468 l = numpy.sin(zen)*numpy.sin(azim)
3318 m = numpy.sin(zen)*numpy.cos(azim)
3469 m = numpy.sin(zen)*numpy.cos(azim)
3319
3470
3320 A = numpy.vstack((l, m)).transpose()
3471 A = numpy.vstack((l, m)).transpose()
3321 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
3472 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
3322 windsAux = numpy.dot(A1, vel)
3473 windsAux = numpy.dot(A1, vel)
3323
3474
3324 winds[0,i] = windsAux[0]
3475 winds[0,i] = windsAux[0]
3325 winds[1,i] = windsAux[1]
3476 winds[1,i] = windsAux[1]
3326
3477
3327 return winds, heightPerI[:-1]
3478 return winds, heightPerI[:-1]
3328
3479
3329 def techniqueNSM_SA(self, **kwargs):
3480 def techniqueNSM_SA(self, **kwargs):
3330 metArray = kwargs['metArray']
3481 metArray = kwargs['metArray']
3331 heightList = kwargs['heightList']
3482 heightList = kwargs['heightList']
3332 timeList = kwargs['timeList']
3483 timeList = kwargs['timeList']
3333
3484
3334 rx_location = kwargs['rx_location']
3485 rx_location = kwargs['rx_location']
3335 groupList = kwargs['groupList']
3486 groupList = kwargs['groupList']
3336 azimuth = kwargs['azimuth']
3487 azimuth = kwargs['azimuth']
3337 dfactor = kwargs['dfactor']
3488 dfactor = kwargs['dfactor']
3338 k = kwargs['k']
3489 k = kwargs['k']
3339
3490
3340 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
3491 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
3341 d = dist*dfactor
3492 d = dist*dfactor
3342 #Phase calculation
3493 #Phase calculation
3343 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
3494 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
3344
3495
3345 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
3496 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
3346
3497
3347 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3498 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3348 azimuth1 = azimuth1*numpy.pi/180
3499 azimuth1 = azimuth1*numpy.pi/180
3349
3500
3350 for i in range(heightList.size):
3501 for i in range(heightList.size):
3351 h = heightList[i]
3502 h = heightList[i]
3352 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
3503 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
3353 metHeight = metArray1[indH,:]
3504 metHeight = metArray1[indH,:]
3354 if metHeight.shape[0] >= 2:
3505 if metHeight.shape[0] >= 2:
3355 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
3506 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
3356 iazim = metHeight[:,1].astype(int)
3507 iazim = metHeight[:,1].astype(int)
3357 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
3508 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
3358 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
3509 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
3359 A = numpy.asmatrix(A)
3510 A = numpy.asmatrix(A)
3360 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
3511 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
3361 velHor = numpy.dot(A1,velAux)
3512 velHor = numpy.dot(A1,velAux)
3362
3513
3363 velEst[i,:] = numpy.squeeze(velHor)
3514 velEst[i,:] = numpy.squeeze(velHor)
3364 return velEst
3515 return velEst
3365
3516
3366 def __getPhaseSlope(self, metArray, heightList, timeList):
3517 def __getPhaseSlope(self, metArray, heightList, timeList):
3367 meteorList = []
3518 meteorList = []
3368 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
3519 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
3369 #Putting back together the meteor matrix
3520 #Putting back together the meteor matrix
3370 utctime = metArray[:,0]
3521 utctime = metArray[:,0]
3371 uniqueTime = numpy.unique(utctime)
3522 uniqueTime = numpy.unique(utctime)
3372
3523
3373 phaseDerThresh = 0.5
3524 phaseDerThresh = 0.5
3374 ippSeconds = timeList[1] - timeList[0]
3525 ippSeconds = timeList[1] - timeList[0]
3375 sec = numpy.where(timeList>1)[0][0]
3526 sec = numpy.where(timeList>1)[0][0]
3376 nPairs = metArray.shape[1] - 6
3527 nPairs = metArray.shape[1] - 6
3377 nHeights = len(heightList)
3528 nHeights = len(heightList)
3378
3529
3379 for t in uniqueTime:
3530 for t in uniqueTime:
3380 metArray1 = metArray[utctime==t,:]
3531 metArray1 = metArray[utctime==t,:]
3381 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
3532 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
3382 tmet = metArray1[:,1].astype(int)
3533 tmet = metArray1[:,1].astype(int)
3383 hmet = metArray1[:,2].astype(int)
3534 hmet = metArray1[:,2].astype(int)
3384
3535
3385 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
3536 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
3386 metPhase[:,:] = numpy.nan
3537 metPhase[:,:] = numpy.nan
3387 metPhase[:,hmet,tmet] = metArray1[:,6:].T
3538 metPhase[:,hmet,tmet] = metArray1[:,6:].T
3388
3539
3389 #Delete short trails
3540 #Delete short trails
3390 metBool = ~numpy.isnan(metPhase[0,:,:])
3541 metBool = ~numpy.isnan(metPhase[0,:,:])
3391 heightVect = numpy.sum(metBool, axis = 1)
3542 heightVect = numpy.sum(metBool, axis = 1)
3392 metBool[heightVect<sec,:] = False
3543 metBool[heightVect<sec,:] = False
3393 metPhase[:,heightVect<sec,:] = numpy.nan
3544 metPhase[:,heightVect<sec,:] = numpy.nan
3394
3545
3395 #Derivative
3546 #Derivative
3396 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
3547 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
3397 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
3548 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
3398 metPhase[phDerAux] = numpy.nan
3549 metPhase[phDerAux] = numpy.nan
3399
3550
3400 #--------------------------METEOR DETECTION -----------------------------------------
3551 #--------------------------METEOR DETECTION -----------------------------------------
3401 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
3552 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
3402
3553
3403 for p in numpy.arange(nPairs):
3554 for p in numpy.arange(nPairs):
3404 phase = metPhase[p,:,:]
3555 phase = metPhase[p,:,:]
3405 phDer = metDer[p,:,:]
3556 phDer = metDer[p,:,:]
3406
3557
3407 for h in indMet:
3558 for h in indMet:
3408 height = heightList[h]
3559 height = heightList[h]
3409 phase1 = phase[h,:] #82
3560 phase1 = phase[h,:] #82
3410 phDer1 = phDer[h,:]
3561 phDer1 = phDer[h,:]
3411
3562
3412 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
3563 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
3413
3564
3414 indValid = numpy.where(~numpy.isnan(phase1))[0]
3565 indValid = numpy.where(~numpy.isnan(phase1))[0]
3415 initMet = indValid[0]
3566 initMet = indValid[0]
3416 endMet = 0
3567 endMet = 0
3417
3568
3418 for i in range(len(indValid)-1):
3569 for i in range(len(indValid)-1):
3419
3570
3420 #Time difference
3571 #Time difference
3421 inow = indValid[i]
3572 inow = indValid[i]
3422 inext = indValid[i+1]
3573 inext = indValid[i+1]
3423 idiff = inext - inow
3574 idiff = inext - inow
3424 #Phase difference
3575 #Phase difference
3425 phDiff = numpy.abs(phase1[inext] - phase1[inow])
3576 phDiff = numpy.abs(phase1[inext] - phase1[inow])
3426
3577
3427 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
3578 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
3428 sizeTrail = inow - initMet + 1
3579 sizeTrail = inow - initMet + 1
3429 if sizeTrail>3*sec: #Too short meteors
3580 if sizeTrail>3*sec: #Too short meteors
3430 x = numpy.arange(initMet,inow+1)*ippSeconds
3581 x = numpy.arange(initMet,inow+1)*ippSeconds
3431 y = phase1[initMet:inow+1]
3582 y = phase1[initMet:inow+1]
3432 ynnan = ~numpy.isnan(y)
3583 ynnan = ~numpy.isnan(y)
3433 x = x[ynnan]
3584 x = x[ynnan]
3434 y = y[ynnan]
3585 y = y[ynnan]
3435 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
3586 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
3436 ylin = x*slope + intercept
3587 ylin = x*slope + intercept
3437 rsq = r_value**2
3588 rsq = r_value**2
3438 if rsq > 0.5:
3589 if rsq > 0.5:
3439 vel = slope#*height*1000/(k*d)
3590 vel = slope#*height*1000/(k*d)
3440 estAux = numpy.array([utctime,p,height, vel, rsq])
3591 estAux = numpy.array([utctime,p,height, vel, rsq])
3441 meteorList.append(estAux)
3592 meteorList.append(estAux)
3442 initMet = inext
3593 initMet = inext
3443 metArray2 = numpy.array(meteorList)
3594 metArray2 = numpy.array(meteorList)
3444
3595
3445 return metArray2
3596 return metArray2
3446
3597
3447 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
3598 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
3448
3599
3449 azimuth1 = numpy.zeros(len(pairslist))
3600 azimuth1 = numpy.zeros(len(pairslist))
3450 dist = numpy.zeros(len(pairslist))
3601 dist = numpy.zeros(len(pairslist))
3451
3602
3452 for i in range(len(rx_location)):
3603 for i in range(len(rx_location)):
3453 ch0 = pairslist[i][0]
3604 ch0 = pairslist[i][0]
3454 ch1 = pairslist[i][1]
3605 ch1 = pairslist[i][1]
3455
3606
3456 diffX = rx_location[ch0][0] - rx_location[ch1][0]
3607 diffX = rx_location[ch0][0] - rx_location[ch1][0]
3457 diffY = rx_location[ch0][1] - rx_location[ch1][1]
3608 diffY = rx_location[ch0][1] - rx_location[ch1][1]
3458 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
3609 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
3459 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
3610 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
3460
3611
3461 azimuth1 -= azimuth0
3612 azimuth1 -= azimuth0
3462 return azimuth1, dist
3613 return azimuth1, dist
3463
3614
3464 def techniqueNSM_DBS(self, **kwargs):
3615 def techniqueNSM_DBS(self, **kwargs):
3465 metArray = kwargs['metArray']
3616 metArray = kwargs['metArray']
3466 heightList = kwargs['heightList']
3617 heightList = kwargs['heightList']
3467 timeList = kwargs['timeList']
3618 timeList = kwargs['timeList']
3468 azimuth = kwargs['azimuth']
3619 azimuth = kwargs['azimuth']
3469 theta_x = numpy.array(kwargs['theta_x'])
3620 theta_x = numpy.array(kwargs['theta_x'])
3470 theta_y = numpy.array(kwargs['theta_y'])
3621 theta_y = numpy.array(kwargs['theta_y'])
3471
3622
3472 utctime = metArray[:,0]
3623 utctime = metArray[:,0]
3473 cmet = metArray[:,1].astype(int)
3624 cmet = metArray[:,1].astype(int)
3474 hmet = metArray[:,3].astype(int)
3625 hmet = metArray[:,3].astype(int)
3475 SNRmet = metArray[:,4]
3626 SNRmet = metArray[:,4]
3476 vmet = metArray[:,5]
3627 vmet = metArray[:,5]
3477 spcmet = metArray[:,6]
3628 spcmet = metArray[:,6]
3478
3629
3479 nChan = numpy.max(cmet) + 1
3630 nChan = numpy.max(cmet) + 1
3480 nHeights = len(heightList)
3631 nHeights = len(heightList)
3481
3632
3482 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3633 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3483 hmet = heightList[hmet]
3634 hmet = heightList[hmet]
3484 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
3635 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
3485
3636
3486 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3637 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3487
3638
3488 for i in range(nHeights - 1):
3639 for i in range(nHeights - 1):
3489 hmin = heightList[i]
3640 hmin = heightList[i]
3490 hmax = heightList[i + 1]
3641 hmax = heightList[i + 1]
3491
3642
3492 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
3643 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
3493 indthisH = numpy.where(thisH)
3644 indthisH = numpy.where(thisH)
3494
3645
3495 if numpy.size(indthisH) > 3:
3646 if numpy.size(indthisH) > 3:
3496
3647
3497 vel_aux = vmet[thisH]
3648 vel_aux = vmet[thisH]
3498 chan_aux = cmet[thisH]
3649 chan_aux = cmet[thisH]
3499 cosu_aux = dir_cosu[chan_aux]
3650 cosu_aux = dir_cosu[chan_aux]
3500 cosv_aux = dir_cosv[chan_aux]
3651 cosv_aux = dir_cosv[chan_aux]
3501 cosw_aux = dir_cosw[chan_aux]
3652 cosw_aux = dir_cosw[chan_aux]
3502
3653
3503 nch = numpy.size(numpy.unique(chan_aux))
3654 nch = numpy.size(numpy.unique(chan_aux))
3504 if nch > 1:
3655 if nch > 1:
3505 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
3656 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
3506 velEst[i,:] = numpy.dot(A,vel_aux)
3657 velEst[i,:] = numpy.dot(A,vel_aux)
3507
3658
3508 return velEst
3659 return velEst
3509
3660
3510 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
3661 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
3511
3662
3512 param = dataOut.data_param
3663 param = dataOut.data_param
3513 if dataOut.abscissaList != None:
3664 if dataOut.abscissaList != None:
3514 absc = dataOut.abscissaList[:-1]
3665 absc = dataOut.abscissaList[:-1]
3515 # noise = dataOut.noise
3666 # noise = dataOut.noise
3516 heightList = dataOut.heightList
3667 heightList = dataOut.heightList
3517 SNR = dataOut.data_snr
3668 SNR = dataOut.data_snr
3518
3669
3519 if technique == 'DBS':
3670 if technique == 'DBS':
3520
3671
3521 kwargs['velRadial'] = param[:,1,:] #Radial velocity
3672 kwargs['velRadial'] = param[:,1,:] #Radial velocity
3522 kwargs['heightList'] = heightList
3673 kwargs['heightList'] = heightList
3523 kwargs['SNR'] = SNR
3674 kwargs['SNR'] = SNR
3524
3675
3525 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
3676 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
3526 dataOut.utctimeInit = dataOut.utctime
3677 dataOut.utctimeInit = dataOut.utctime
3527 dataOut.outputInterval = dataOut.paramInterval
3678 dataOut.outputInterval = dataOut.paramInterval
3528
3679
3529 elif technique == 'SA':
3680 elif technique == 'SA':
3530
3681
3531 #Parameters
3682 #Parameters
3532 # position_x = kwargs['positionX']
3683 # position_x = kwargs['positionX']
3533 # position_y = kwargs['positionY']
3684 # position_y = kwargs['positionY']
3534 # azimuth = kwargs['azimuth']
3685 # azimuth = kwargs['azimuth']
3535 #
3686 #
3536 # if kwargs.has_key('crosspairsList'):
3687 # if kwargs.has_key('crosspairsList'):
3537 # pairs = kwargs['crosspairsList']
3688 # pairs = kwargs['crosspairsList']
3538 # else:
3689 # else:
3539 # pairs = None
3690 # pairs = None
3540 #
3691 #
3541 # if kwargs.has_key('correctFactor'):
3692 # if kwargs.has_key('correctFactor'):
3542 # correctFactor = kwargs['correctFactor']
3693 # correctFactor = kwargs['correctFactor']
3543 # else:
3694 # else:
3544 # correctFactor = 1
3695 # correctFactor = 1
3545
3696
3546 # tau = dataOut.data_param
3697 # tau = dataOut.data_param
3547 # _lambda = dataOut.C/dataOut.frequency
3698 # _lambda = dataOut.C/dataOut.frequency
3548 # pairsList = dataOut.groupList
3699 # pairsList = dataOut.groupList
3549 # nChannels = dataOut.nChannels
3700 # nChannels = dataOut.nChannels
3550
3701
3551 kwargs['groupList'] = dataOut.groupList
3702 kwargs['groupList'] = dataOut.groupList
3552 kwargs['tau'] = dataOut.data_param
3703 kwargs['tau'] = dataOut.data_param
3553 kwargs['_lambda'] = dataOut.C/dataOut.frequency
3704 kwargs['_lambda'] = dataOut.C/dataOut.frequency
3554 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
3705 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
3555 dataOut.data_output = self.techniqueSA(kwargs)
3706 dataOut.data_output = self.techniqueSA(kwargs)
3556 dataOut.utctimeInit = dataOut.utctime
3707 dataOut.utctimeInit = dataOut.utctime
3557 dataOut.outputInterval = dataOut.timeInterval
3708 dataOut.outputInterval = dataOut.timeInterval
3558
3709
3559 elif technique == 'Meteors':
3710 elif technique == 'Meteors':
3560 dataOut.flagNoData = True
3711 dataOut.flagNoData = True
3561 self.__dataReady = False
3712 self.__dataReady = False
3562
3713
3563 if 'nHours' in kwargs:
3714 if 'nHours' in kwargs:
3564 nHours = kwargs['nHours']
3715 nHours = kwargs['nHours']
3565 else:
3716 else:
3566 nHours = 1
3717 nHours = 1
3567
3718
3568 if 'meteorsPerBin' in kwargs:
3719 if 'meteorsPerBin' in kwargs:
3569 meteorThresh = kwargs['meteorsPerBin']
3720 meteorThresh = kwargs['meteorsPerBin']
3570 else:
3721 else:
3571 meteorThresh = 6
3722 meteorThresh = 6
3572
3723
3573 if 'hmin' in kwargs:
3724 if 'hmin' in kwargs:
3574 hmin = kwargs['hmin']
3725 hmin = kwargs['hmin']
3575 else: hmin = 70
3726 else: hmin = 70
3576 if 'hmax' in kwargs:
3727 if 'hmax' in kwargs:
3577 hmax = kwargs['hmax']
3728 hmax = kwargs['hmax']
3578 else: hmax = 110
3729 else: hmax = 110
3579
3730
3580 dataOut.outputInterval = nHours*3600
3731 dataOut.outputInterval = nHours*3600
3581
3732
3582 if self.__isConfig == False:
3733 if self.__isConfig == False:
3583 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3734 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3584 #Get Initial LTC time
3735 #Get Initial LTC time
3585 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3736 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3586 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3737 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3587
3738
3588 self.__isConfig = True
3739 self.__isConfig = True
3589
3740
3590 if self.__buffer is None:
3741 if self.__buffer is None:
3591 self.__buffer = dataOut.data_param
3742 self.__buffer = dataOut.data_param
3592 self.__firstdata = copy.copy(dataOut)
3743 self.__firstdata = copy.copy(dataOut)
3593
3744
3594 else:
3745 else:
3595 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3746 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3596
3747
3597 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3748 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3598
3749
3599 if self.__dataReady:
3750 if self.__dataReady:
3600 dataOut.utctimeInit = self.__initime
3751 dataOut.utctimeInit = self.__initime
3601
3752
3602 self.__initime += dataOut.outputInterval #to erase time offset
3753 self.__initime += dataOut.outputInterval #to erase time offset
3603
3754
3604 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
3755 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
3605 dataOut.flagNoData = False
3756 dataOut.flagNoData = False
3606 self.__buffer = None
3757 self.__buffer = None
3607
3758
3608 elif technique == 'Meteors1':
3759 elif technique == 'Meteors1':
3609 dataOut.flagNoData = True
3760 dataOut.flagNoData = True
3610 self.__dataReady = False
3761 self.__dataReady = False
3611
3762
3612 if 'nMins' in kwargs:
3763 if 'nMins' in kwargs:
3613 nMins = kwargs['nMins']
3764 nMins = kwargs['nMins']
3614 else: nMins = 20
3765 else: nMins = 20
3615 if 'rx_location' in kwargs:
3766 if 'rx_location' in kwargs:
3616 rx_location = kwargs['rx_location']
3767 rx_location = kwargs['rx_location']
3617 else: rx_location = [(0,1),(1,1),(1,0)]
3768 else: rx_location = [(0,1),(1,1),(1,0)]
3618 if 'azimuth' in kwargs:
3769 if 'azimuth' in kwargs:
3619 azimuth = kwargs['azimuth']
3770 azimuth = kwargs['azimuth']
3620 else: azimuth = 51.06
3771 else: azimuth = 51.06
3621 if 'dfactor' in kwargs:
3772 if 'dfactor' in kwargs:
3622 dfactor = kwargs['dfactor']
3773 dfactor = kwargs['dfactor']
3623 if 'mode' in kwargs:
3774 if 'mode' in kwargs:
3624 mode = kwargs['mode']
3775 mode = kwargs['mode']
3625 if 'theta_x' in kwargs:
3776 if 'theta_x' in kwargs:
3626 theta_x = kwargs['theta_x']
3777 theta_x = kwargs['theta_x']
3627 if 'theta_y' in kwargs:
3778 if 'theta_y' in kwargs:
3628 theta_y = kwargs['theta_y']
3779 theta_y = kwargs['theta_y']
3629 else: mode = 'SA'
3780 else: mode = 'SA'
3630
3781
3631 #Borrar luego esto
3782 #Borrar luego esto
3632 if dataOut.groupList is None:
3783 if dataOut.groupList is None:
3633 dataOut.groupList = [(0,1),(0,2),(1,2)]
3784 dataOut.groupList = [(0,1),(0,2),(1,2)]
3634 groupList = dataOut.groupList
3785 groupList = dataOut.groupList
3635 C = 3e8
3786 C = 3e8
3636 freq = 50e6
3787 freq = 50e6
3637 lamb = C/freq
3788 lamb = C/freq
3638 k = 2*numpy.pi/lamb
3789 k = 2*numpy.pi/lamb
3639
3790
3640 timeList = dataOut.abscissaList
3791 timeList = dataOut.abscissaList
3641 heightList = dataOut.heightList
3792 heightList = dataOut.heightList
3642
3793
3643 if self.__isConfig == False:
3794 if self.__isConfig == False:
3644 dataOut.outputInterval = nMins*60
3795 dataOut.outputInterval = nMins*60
3645 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3796 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3646 #Get Initial LTC time
3797 #Get Initial LTC time
3647 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3798 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3648 minuteAux = initime.minute
3799 minuteAux = initime.minute
3649 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
3800 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
3650 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3801 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3651
3802
3652 self.__isConfig = True
3803 self.__isConfig = True
3653
3804
3654 if self.__buffer is None:
3805 if self.__buffer is None:
3655 self.__buffer = dataOut.data_param
3806 self.__buffer = dataOut.data_param
3656 self.__firstdata = copy.copy(dataOut)
3807 self.__firstdata = copy.copy(dataOut)
3657
3808
3658 else:
3809 else:
3659 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3810 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3660
3811
3661 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3812 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3662
3813
3663 if self.__dataReady:
3814 if self.__dataReady:
3664 dataOut.utctimeInit = self.__initime
3815 dataOut.utctimeInit = self.__initime
3665 self.__initime += dataOut.outputInterval #to erase time offset
3816 self.__initime += dataOut.outputInterval #to erase time offset
3666
3817
3667 metArray = self.__buffer
3818 metArray = self.__buffer
3668 if mode == 'SA':
3819 if mode == 'SA':
3669 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
3820 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
3670 elif mode == 'DBS':
3821 elif mode == 'DBS':
3671 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
3822 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
3672 dataOut.data_output = dataOut.data_output.T
3823 dataOut.data_output = dataOut.data_output.T
3673 dataOut.flagNoData = False
3824 dataOut.flagNoData = False
3674 self.__buffer = None
3825 self.__buffer = None
3675
3826
3676 return
3827 return
3677
3828
3678 class EWDriftsEstimation(Operation):
3829 class EWDriftsEstimation(Operation):
3679
3830
3680 def __init__(self):
3831 def __init__(self):
3681 Operation.__init__(self)
3832 Operation.__init__(self)
3682
3833
3683 def __correctValues(self, heiRang, phi, velRadial, SNR):
3834 def __correctValues(self, heiRang, phi, velRadial, SNR):
3684 listPhi = phi.tolist()
3835 listPhi = phi.tolist()
3685 maxid = listPhi.index(max(listPhi))
3836 maxid = listPhi.index(max(listPhi))
3686 minid = listPhi.index(min(listPhi))
3837 minid = listPhi.index(min(listPhi))
3687
3838
3688 rango = list(range(len(phi)))
3839 rango = list(range(len(phi)))
3689 # rango = numpy.delete(rango,maxid)
3840 # rango = numpy.delete(rango,maxid)
3690
3841
3691 heiRang1 = heiRang*math.cos(phi[maxid])
3842 heiRang1 = heiRang*math.cos(phi[maxid])
3692 heiRangAux = heiRang*math.cos(phi[minid])
3843 heiRangAux = heiRang*math.cos(phi[minid])
3693 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3844 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3694 heiRang1 = numpy.delete(heiRang1,indOut)
3845 heiRang1 = numpy.delete(heiRang1,indOut)
3695
3846
3696 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3847 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3697 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3848 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3698
3849
3699 for i in rango:
3850 for i in rango:
3700 x = heiRang*math.cos(phi[i])
3851 x = heiRang*math.cos(phi[i])
3701 y1 = velRadial[i,:]
3852 y1 = velRadial[i,:]
3702 vali= (numpy.isfinite(y1)==True).nonzero()
3853 vali= (numpy.isfinite(y1)==True).nonzero()
3703 y1=y1[vali]
3854 y1=y1[vali]
3704 x = x[vali]
3855 x = x[vali]
3705 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
3856 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
3706
3857
3707 #heiRang1 = x*math.cos(phi[maxid])
3858 #heiRang1 = x*math.cos(phi[maxid])
3708 x1 = heiRang1
3859 x1 = heiRang1
3709 y11 = f1(x1)
3860 y11 = f1(x1)
3710
3861
3711 y2 = SNR[i,:]
3862 y2 = SNR[i,:]
3712 #print 'snr ', y2
3863 #print 'snr ', y2
3713 x = heiRang*math.cos(phi[i])
3864 x = heiRang*math.cos(phi[i])
3714 vali= (y2 != -1).nonzero()
3865 vali= (y2 != -1).nonzero()
3715 y2 = y2[vali]
3866 y2 = y2[vali]
3716 x = x[vali]
3867 x = x[vali]
3717 #print 'snr ',y2
3868 #print 'snr ',y2
3718 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
3869 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
3719 y21 = f2(x1)
3870 y21 = f2(x1)
3720
3871
3721 velRadial1[i,:] = y11
3872 velRadial1[i,:] = y11
3722 SNR1[i,:] = y21
3873 SNR1[i,:] = y21
3723
3874
3724 return heiRang1, velRadial1, SNR1
3875 return heiRang1, velRadial1, SNR1
3725
3876
3726
3877
3727
3878
3728 def run(self, dataOut, zenith, zenithCorrection):
3879 def run(self, dataOut, zenith, zenithCorrection):
3729
3880
3730 heiRang = dataOut.heightList
3881 heiRang = dataOut.heightList
3731 velRadial = dataOut.data_param[:,3,:]
3882 velRadial = dataOut.data_param[:,3,:]
3732 velRadialm = dataOut.data_param[:,2:4,:]*-1
3883 velRadialm = dataOut.data_param[:,2:4,:]*-1
3733
3884
3734 rbufc=dataOut.data_paramC[:,:,0]
3885 rbufc=dataOut.data_paramC[:,:,0]
3735 ebufc=dataOut.data_paramC[:,:,1]
3886 ebufc=dataOut.data_paramC[:,:,1]
3736 SNR = dataOut.data_snr
3887 SNR = dataOut.data_snr
3737 velRerr = dataOut.data_error[:,4,:]
3888 velRerr = dataOut.data_error[:,4,:]
3738 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
3889 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
3739 dataOut.moments=moments
3890 dataOut.moments=moments
3740 # Coherent
3891 # Coherent
3741 smooth_wC = ebufc[0,:]
3892 smooth_wC = ebufc[0,:]
3742 p_w0C = rbufc[0,:]
3893 p_w0C = rbufc[0,:]
3743 p_w1C = rbufc[1,:]
3894 p_w1C = rbufc[1,:]
3744 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
3895 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
3745 t_wC = rbufc[3,:]
3896 t_wC = rbufc[3,:]
3746 my_nbeams = 2
3897 my_nbeams = 2
3747
3898
3748 zenith = numpy.array(zenith)
3899 zenith = numpy.array(zenith)
3749 zenith -= zenithCorrection
3900 zenith -= zenithCorrection
3750 zenith *= numpy.pi/180
3901 zenith *= numpy.pi/180
3751 if zenithCorrection != 0 :
3902 if zenithCorrection != 0 :
3752 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
3903 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
3753 else :
3904 else :
3754 heiRang1 = heiRang
3905 heiRang1 = heiRang
3755 velRadial1 = velRadial
3906 velRadial1 = velRadial
3756 SNR1 = SNR
3907 SNR1 = SNR
3757
3908
3758 alp = zenith[0]
3909 alp = zenith[0]
3759 bet = zenith[1]
3910 bet = zenith[1]
3760
3911
3761 w_w = velRadial1[0,:]
3912 w_w = velRadial1[0,:]
3762 w_e = velRadial1[1,:]
3913 w_e = velRadial1[1,:]
3763 w_w_err = velRerr[0,:]
3914 w_w_err = velRerr[0,:]
3764 w_e_err = velRerr[1,:]
3915 w_e_err = velRerr[1,:]
3765
3916
3766 val = (numpy.isfinite(w_w)==False).nonzero()
3917 val = (numpy.isfinite(w_w)==False).nonzero()
3767 val = val[0]
3918 val = val[0]
3768 bad = val
3919 bad = val
3769 if len(bad) > 0 :
3920 if len(bad) > 0 :
3770 w_w[bad] = w_wC[bad]
3921 w_w[bad] = w_wC[bad]
3771 w_w_err[bad]= numpy.nan
3922 w_w_err[bad]= numpy.nan
3772 if my_nbeams == 2:
3923 if my_nbeams == 2:
3773 smooth_eC=ebufc[4,:]
3924 smooth_eC=ebufc[4,:]
3774 p_e0C = rbufc[4,:]
3925 p_e0C = rbufc[4,:]
3775 p_e1C = rbufc[5,:]
3926 p_e1C = rbufc[5,:]
3776 w_eC = rbufc[6,:]*-1
3927 w_eC = rbufc[6,:]*-1
3777 t_eC = rbufc[7,:]
3928 t_eC = rbufc[7,:]
3778 val = (numpy.isfinite(w_e)==False).nonzero()
3929 val = (numpy.isfinite(w_e)==False).nonzero()
3779 val = val[0]
3930 val = val[0]
3780 bad = val
3931 bad = val
3781 if len(bad) > 0 :
3932 if len(bad) > 0 :
3782 w_e[bad] = w_eC[bad]
3933 w_e[bad] = w_eC[bad]
3783 w_e_err[bad]= numpy.nan
3934 w_e_err[bad]= numpy.nan
3784
3935
3785 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
3936 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
3786 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
3937 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
3787
3938
3788 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))
3939 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))
3789 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))
3940 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))
3790
3941
3791 winds = numpy.vstack((w,u))
3942 winds = numpy.vstack((w,u))
3792
3943
3793 dataOut.heightList = heiRang1
3944 dataOut.heightList = heiRang1
3794 dataOut.data_output = winds
3945 dataOut.data_output = winds
3795
3946
3796 snr1 = 10*numpy.log10(SNR1[0])
3947 snr1 = 10*numpy.log10(SNR1[0])
3797 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
3948 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
3798 dataOut.utctimeInit = dataOut.utctime
3949 dataOut.utctimeInit = dataOut.utctime
3799 dataOut.outputInterval = dataOut.timeInterval
3950 dataOut.outputInterval = dataOut.timeInterval
3800
3951
3801 hei_aver0 = 218
3952 hei_aver0 = 218
3802 jrange = 450 #900 para HA drifts
3953 jrange = 450 #900 para HA drifts
3803 deltah = 15.0 #dataOut.spacing(0)
3954 deltah = 15.0 #dataOut.spacing(0)
3804 h0 = 0.0 #dataOut.first_height(0)
3955 h0 = 0.0 #dataOut.first_height(0)
3805 heights = dataOut.heightList
3956 heights = dataOut.heightList
3806 nhei = len(heights)
3957 nhei = len(heights)
3807
3958
3808 range1 = numpy.arange(nhei) * deltah + h0
3959 range1 = numpy.arange(nhei) * deltah + h0
3809
3960
3810 #jhei = WHERE(range1 GE hei_aver0 , jcount)
3961 #jhei = WHERE(range1 GE hei_aver0 , jcount)
3811 jhei = (range1 >= hei_aver0).nonzero()
3962 jhei = (range1 >= hei_aver0).nonzero()
3812 if len(jhei[0]) > 0 :
3963 if len(jhei[0]) > 0 :
3813 h0_index = jhei[0][0] # Initial height for getting averages 218km
3964 h0_index = jhei[0][0] # Initial height for getting averages 218km
3814
3965
3815 mynhei = 7
3966 mynhei = 7
3816 nhei_avg = int(jrange/deltah)
3967 nhei_avg = int(jrange/deltah)
3817 h_avgs = int(nhei_avg/mynhei)
3968 h_avgs = int(nhei_avg/mynhei)
3818 nhei_avg = h_avgs*(mynhei-1)+mynhei
3969 nhei_avg = h_avgs*(mynhei-1)+mynhei
3819
3970
3820 navgs = numpy.zeros(mynhei,dtype='float')
3971 navgs = numpy.zeros(mynhei,dtype='float')
3821 delta_h = numpy.zeros(mynhei,dtype='float')
3972 delta_h = numpy.zeros(mynhei,dtype='float')
3822 range_aver = numpy.zeros(mynhei,dtype='float')
3973 range_aver = numpy.zeros(mynhei,dtype='float')
3823 for ih in range( mynhei-1 ):
3974 for ih in range( mynhei-1 ):
3824 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
3975 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
3825 navgs[ih] = h_avgs
3976 navgs[ih] = h_avgs
3826 delta_h[ih] = deltah*h_avgs
3977 delta_h[ih] = deltah*h_avgs
3827
3978
3828 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
3979 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
3829 navgs[mynhei-1] = 6*h_avgs
3980 navgs[mynhei-1] = 6*h_avgs
3830 delta_h[mynhei-1] = deltah*6*h_avgs
3981 delta_h[mynhei-1] = deltah*6*h_avgs
3831
3982
3832 wA = w[h0_index:h0_index+nhei_avg-0]
3983 wA = w[h0_index:h0_index+nhei_avg-0]
3833 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
3984 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
3834
3985
3835 for i in range(5) :
3986 for i in range(5) :
3836 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
3987 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
3837 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
3988 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
3838 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3989 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3839 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3990 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3840 wA[6*h_avgs+i] = avg
3991 wA[6*h_avgs+i] = avg
3841 wA_err[6*h_avgs+i] = sigma
3992 wA_err[6*h_avgs+i] = sigma
3842
3993
3843
3994
3844 vals = wA[0:6*h_avgs-0]
3995 vals = wA[0:6*h_avgs-0]
3845 errs=wA_err[0:6*h_avgs-0]
3996 errs=wA_err[0:6*h_avgs-0]
3846 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
3997 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
3847 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3998 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3848 wA[nhei_avg-1] = avg
3999 wA[nhei_avg-1] = avg
3849 wA_err[nhei_avg-1] = sigma
4000 wA_err[nhei_avg-1] = sigma
3850
4001
3851 wA = wA[6*h_avgs:nhei_avg-0]
4002 wA = wA[6*h_avgs:nhei_avg-0]
3852 wA_err=wA_err[6*h_avgs:nhei_avg-0]
4003 wA_err=wA_err[6*h_avgs:nhei_avg-0]
3853 if my_nbeams == 2 :
4004 if my_nbeams == 2 :
3854
4005
3855 uA = u[h0_index:h0_index+nhei_avg]
4006 uA = u[h0_index:h0_index+nhei_avg]
3856 uA_err=u_err[h0_index:h0_index+nhei_avg]
4007 uA_err=u_err[h0_index:h0_index+nhei_avg]
3857
4008
3858 for i in range(5) :
4009 for i in range(5) :
3859 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
4010 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
3860 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
4011 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
3861 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4012 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3862 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4013 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3863 uA[6*h_avgs+i] = avg
4014 uA[6*h_avgs+i] = avg
3864 uA_err[6*h_avgs+i]=sigma
4015 uA_err[6*h_avgs+i]=sigma
3865
4016
3866 vals = uA[0:6*h_avgs-0]
4017 vals = uA[0:6*h_avgs-0]
3867 errs = uA_err[0:6*h_avgs-0]
4018 errs = uA_err[0:6*h_avgs-0]
3868 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4019 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3869 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4020 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3870 uA[nhei_avg-1] = avg
4021 uA[nhei_avg-1] = avg
3871 uA_err[nhei_avg-1] = sigma
4022 uA_err[nhei_avg-1] = sigma
3872 uA = uA[6*h_avgs:nhei_avg-0]
4023 uA = uA[6*h_avgs:nhei_avg-0]
3873 uA_err = uA_err[6*h_avgs:nhei_avg-0]
4024 uA_err = uA_err[6*h_avgs:nhei_avg-0]
3874
4025
3875 dataOut.drifts_avg = numpy.vstack((wA,uA))
4026 dataOut.drifts_avg = numpy.vstack((wA,uA))
3876
4027
3877 tini=time.localtime(dataOut.utctime)
4028 tini=time.localtime(dataOut.utctime)
3878 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
4029 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
3879 nfile = '/home/pcondor/Database/ewdriftsschain2019/jro'+datefile+'drifts_sch3.txt'
4030 nfile = '/home/pcondor/Database/ewdriftsschain2019/jro'+datefile+'drifts_sch3.txt'
3880
4031
3881 f1 = open(nfile,'a')
4032 f1 = open(nfile,'a')
3882
4033
3883 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
4034 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
3884 driftavgstr=str(dataOut.drifts_avg)
4035 driftavgstr=str(dataOut.drifts_avg)
3885
4036
3886 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
4037 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
3887 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
4038 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
3888 f1.close()
4039 f1.close()
3889
4040
3890 return dataOut
4041 return dataOut
3891
4042
3892 #--------------- Non Specular Meteor ----------------
4043 #--------------- Non Specular Meteor ----------------
3893
4044
3894 class NonSpecularMeteorDetection(Operation):
4045 class NonSpecularMeteorDetection(Operation):
3895
4046
3896 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
4047 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
3897 data_acf = dataOut.data_pre[0]
4048 data_acf = dataOut.data_pre[0]
3898 data_ccf = dataOut.data_pre[1]
4049 data_ccf = dataOut.data_pre[1]
3899 pairsList = dataOut.groupList[1]
4050 pairsList = dataOut.groupList[1]
3900
4051
3901 lamb = dataOut.C/dataOut.frequency
4052 lamb = dataOut.C/dataOut.frequency
3902 tSamp = dataOut.ippSeconds*dataOut.nCohInt
4053 tSamp = dataOut.ippSeconds*dataOut.nCohInt
3903 paramInterval = dataOut.paramInterval
4054 paramInterval = dataOut.paramInterval
3904
4055
3905 nChannels = data_acf.shape[0]
4056 nChannels = data_acf.shape[0]
3906 nLags = data_acf.shape[1]
4057 nLags = data_acf.shape[1]
3907 nProfiles = data_acf.shape[2]
4058 nProfiles = data_acf.shape[2]
3908 nHeights = dataOut.nHeights
4059 nHeights = dataOut.nHeights
3909 nCohInt = dataOut.nCohInt
4060 nCohInt = dataOut.nCohInt
3910 sec = numpy.round(nProfiles/dataOut.paramInterval)
4061 sec = numpy.round(nProfiles/dataOut.paramInterval)
3911 heightList = dataOut.heightList
4062 heightList = dataOut.heightList
3912 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
4063 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
3913 utctime = dataOut.utctime
4064 utctime = dataOut.utctime
3914
4065
3915 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
4066 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
3916
4067
3917 #------------------------ SNR --------------------------------------
4068 #------------------------ SNR --------------------------------------
3918 power = data_acf[:,0,:,:].real
4069 power = data_acf[:,0,:,:].real
3919 noise = numpy.zeros(nChannels)
4070 noise = numpy.zeros(nChannels)
3920 SNR = numpy.zeros(power.shape)
4071 SNR = numpy.zeros(power.shape)
3921 for i in range(nChannels):
4072 for i in range(nChannels):
3922 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
4073 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
3923 SNR[i] = (power[i]-noise[i])/noise[i]
4074 SNR[i] = (power[i]-noise[i])/noise[i]
3924 SNRm = numpy.nanmean(SNR, axis = 0)
4075 SNRm = numpy.nanmean(SNR, axis = 0)
3925 SNRdB = 10*numpy.log10(SNR)
4076 SNRdB = 10*numpy.log10(SNR)
3926
4077
3927 if mode == 'SA':
4078 if mode == 'SA':
3928 dataOut.groupList = dataOut.groupList[1]
4079 dataOut.groupList = dataOut.groupList[1]
3929 nPairs = data_ccf.shape[0]
4080 nPairs = data_ccf.shape[0]
3930 #---------------------- Coherence and Phase --------------------------
4081 #---------------------- Coherence and Phase --------------------------
3931 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
4082 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
3932 # phase1 = numpy.copy(phase)
4083 # phase1 = numpy.copy(phase)
3933 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
4084 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
3934
4085
3935 for p in range(nPairs):
4086 for p in range(nPairs):
3936 ch0 = pairsList[p][0]
4087 ch0 = pairsList[p][0]
3937 ch1 = pairsList[p][1]
4088 ch1 = pairsList[p][1]
3938 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
4089 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
3939 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
4090 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
3940 # phase1[p,:,:] = numpy.angle(ccf) #median filter
4091 # phase1[p,:,:] = numpy.angle(ccf) #median filter
3941 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
4092 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
3942 # coh1[p,:,:] = numpy.abs(ccf) #median filter
4093 # coh1[p,:,:] = numpy.abs(ccf) #median filter
3943 coh = numpy.nanmax(coh1, axis = 0)
4094 coh = numpy.nanmax(coh1, axis = 0)
3944 # struc = numpy.ones((5,1))
4095 # struc = numpy.ones((5,1))
3945 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
4096 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
3946 #---------------------- Radial Velocity ----------------------------
4097 #---------------------- Radial Velocity ----------------------------
3947 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
4098 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
3948 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
4099 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
3949
4100
3950 if allData:
4101 if allData:
3951 boolMetFin = ~numpy.isnan(SNRm)
4102 boolMetFin = ~numpy.isnan(SNRm)
3952 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4103 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
3953 else:
4104 else:
3954 #------------------------ Meteor mask ---------------------------------
4105 #------------------------ Meteor mask ---------------------------------
3955 # #SNR mask
4106 # #SNR mask
3956 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
4107 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
3957 #
4108 #
3958 # #Erase small objects
4109 # #Erase small objects
3959 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
4110 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
3960 #
4111 #
3961 # auxEEJ = numpy.sum(boolMet1,axis=0)
4112 # auxEEJ = numpy.sum(boolMet1,axis=0)
3962 # indOver = auxEEJ>nProfiles*0.8 #Use this later
4113 # indOver = auxEEJ>nProfiles*0.8 #Use this later
3963 # indEEJ = numpy.where(indOver)[0]
4114 # indEEJ = numpy.where(indOver)[0]
3964 # indNEEJ = numpy.where(~indOver)[0]
4115 # indNEEJ = numpy.where(~indOver)[0]
3965 #
4116 #
3966 # boolMetFin = boolMet1
4117 # boolMetFin = boolMet1
3967 #
4118 #
3968 # if indEEJ.size > 0:
4119 # if indEEJ.size > 0:
3969 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
4120 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
3970 #
4121 #
3971 # boolMet2 = coh > cohThresh
4122 # boolMet2 = coh > cohThresh
3972 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
4123 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
3973 #
4124 #
3974 # #Final Meteor mask
4125 # #Final Meteor mask
3975 # boolMetFin = boolMet1|boolMet2
4126 # boolMetFin = boolMet1|boolMet2
3976
4127
3977 #Coherence mask
4128 #Coherence mask
3978 boolMet1 = coh > 0.75
4129 boolMet1 = coh > 0.75
3979 struc = numpy.ones((30,1))
4130 struc = numpy.ones((30,1))
3980 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
4131 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
3981
4132
3982 #Derivative mask
4133 #Derivative mask
3983 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4134 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
3984 boolMet2 = derPhase < 0.2
4135 boolMet2 = derPhase < 0.2
3985 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
4136 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
3986 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
4137 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
3987 boolMet2 = ndimage.median_filter(boolMet2,size=5)
4138 boolMet2 = ndimage.median_filter(boolMet2,size=5)
3988 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
4139 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
3989 # #Final mask
4140 # #Final mask
3990 # boolMetFin = boolMet2
4141 # boolMetFin = boolMet2
3991 boolMetFin = boolMet1&boolMet2
4142 boolMetFin = boolMet1&boolMet2
3992 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
4143 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
3993 #Creating data_param
4144 #Creating data_param
3994 coordMet = numpy.where(boolMetFin)
4145 coordMet = numpy.where(boolMetFin)
3995
4146
3996 tmet = coordMet[0]
4147 tmet = coordMet[0]
3997 hmet = coordMet[1]
4148 hmet = coordMet[1]
3998
4149
3999 data_param = numpy.zeros((tmet.size, 6 + nPairs))
4150 data_param = numpy.zeros((tmet.size, 6 + nPairs))
4000 data_param[:,0] = utctime
4151 data_param[:,0] = utctime
4001 data_param[:,1] = tmet
4152 data_param[:,1] = tmet
4002 data_param[:,2] = hmet
4153 data_param[:,2] = hmet
4003 data_param[:,3] = SNRm[tmet,hmet]
4154 data_param[:,3] = SNRm[tmet,hmet]
4004 data_param[:,4] = velRad[tmet,hmet]
4155 data_param[:,4] = velRad[tmet,hmet]
4005 data_param[:,5] = coh[tmet,hmet]
4156 data_param[:,5] = coh[tmet,hmet]
4006 data_param[:,6:] = phase[:,tmet,hmet].T
4157 data_param[:,6:] = phase[:,tmet,hmet].T
4007
4158
4008 elif mode == 'DBS':
4159 elif mode == 'DBS':
4009 dataOut.groupList = numpy.arange(nChannels)
4160 dataOut.groupList = numpy.arange(nChannels)
4010
4161
4011 #Radial Velocities
4162 #Radial Velocities
4012 phase = numpy.angle(data_acf[:,1,:,:])
4163 phase = numpy.angle(data_acf[:,1,:,:])
4013 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
4164 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
4014 velRad = phase*lamb/(4*numpy.pi*tSamp)
4165 velRad = phase*lamb/(4*numpy.pi*tSamp)
4015
4166
4016 #Spectral width
4167 #Spectral width
4017 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
4168 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
4018 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
4169 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
4019 acf1 = data_acf[:,1,:,:]
4170 acf1 = data_acf[:,1,:,:]
4020 acf2 = data_acf[:,2,:,:]
4171 acf2 = data_acf[:,2,:,:]
4021
4172
4022 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4173 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4023 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
4174 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
4024 if allData:
4175 if allData:
4025 boolMetFin = ~numpy.isnan(SNRdB)
4176 boolMetFin = ~numpy.isnan(SNRdB)
4026 else:
4177 else:
4027 #SNR
4178 #SNR
4028 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4179 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4029 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4180 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4030
4181
4031 #Radial velocity
4182 #Radial velocity
4032 boolMet2 = numpy.abs(velRad) < 20
4183 boolMet2 = numpy.abs(velRad) < 20
4033 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4184 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4034
4185
4035 #Spectral Width
4186 #Spectral Width
4036 boolMet3 = spcWidth < 30
4187 boolMet3 = spcWidth < 30
4037 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4188 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4038 # boolMetFin = self.__erase_small(boolMet1, 10,5)
4189 # boolMetFin = self.__erase_small(boolMet1, 10,5)
4039 boolMetFin = boolMet1&boolMet2&boolMet3
4190 boolMetFin = boolMet1&boolMet2&boolMet3
4040
4191
4041 #Creating data_param
4192 #Creating data_param
4042 coordMet = numpy.where(boolMetFin)
4193 coordMet = numpy.where(boolMetFin)
4043
4194
4044 cmet = coordMet[0]
4195 cmet = coordMet[0]
4045 tmet = coordMet[1]
4196 tmet = coordMet[1]
4046 hmet = coordMet[2]
4197 hmet = coordMet[2]
4047
4198
4048 data_param = numpy.zeros((tmet.size, 7))
4199 data_param = numpy.zeros((tmet.size, 7))
4049 data_param[:,0] = utctime
4200 data_param[:,0] = utctime
4050 data_param[:,1] = cmet
4201 data_param[:,1] = cmet
4051 data_param[:,2] = tmet
4202 data_param[:,2] = tmet
4052 data_param[:,3] = hmet
4203 data_param[:,3] = hmet
4053 data_param[:,4] = SNR[cmet,tmet,hmet].T
4204 data_param[:,4] = SNR[cmet,tmet,hmet].T
4054 data_param[:,5] = velRad[cmet,tmet,hmet].T
4205 data_param[:,5] = velRad[cmet,tmet,hmet].T
4055 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4206 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4056
4207
4057 # self.dataOut.data_param = data_int
4208 # self.dataOut.data_param = data_int
4058 if len(data_param) == 0:
4209 if len(data_param) == 0:
4059 dataOut.flagNoData = True
4210 dataOut.flagNoData = True
4060 else:
4211 else:
4061 dataOut.data_param = data_param
4212 dataOut.data_param = data_param
4062
4213
4063 def __erase_small(self, binArray, threshX, threshY):
4214 def __erase_small(self, binArray, threshX, threshY):
4064 labarray, numfeat = ndimage.measurements.label(binArray)
4215 labarray, numfeat = ndimage.measurements.label(binArray)
4065 binArray1 = numpy.copy(binArray)
4216 binArray1 = numpy.copy(binArray)
4066
4217
4067 for i in range(1,numfeat + 1):
4218 for i in range(1,numfeat + 1):
4068 auxBin = (labarray==i)
4219 auxBin = (labarray==i)
4069 auxSize = auxBin.sum()
4220 auxSize = auxBin.sum()
4070
4221
4071 x,y = numpy.where(auxBin)
4222 x,y = numpy.where(auxBin)
4072 widthX = x.max() - x.min()
4223 widthX = x.max() - x.min()
4073 widthY = y.max() - y.min()
4224 widthY = y.max() - y.min()
4074
4225
4075 #width X: 3 seg -> 12.5*3
4226 #width X: 3 seg -> 12.5*3
4076 #width Y:
4227 #width Y:
4077
4228
4078 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
4229 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
4079 binArray1[auxBin] = False
4230 binArray1[auxBin] = False
4080
4231
4081 return binArray1
4232 return binArray1
4082
4233
4083 #--------------- Specular Meteor ----------------
4234 #--------------- Specular Meteor ----------------
4084
4235
4085 class SMDetection(Operation):
4236 class SMDetection(Operation):
4086 '''
4237 '''
4087 Function DetectMeteors()
4238 Function DetectMeteors()
4088 Project developed with paper:
4239 Project developed with paper:
4089 HOLDSWORTH ET AL. 2004
4240 HOLDSWORTH ET AL. 2004
4090
4241
4091 Input:
4242 Input:
4092 self.dataOut.data_pre
4243 self.dataOut.data_pre
4093
4244
4094 centerReceiverIndex: From the channels, which is the center receiver
4245 centerReceiverIndex: From the channels, which is the center receiver
4095
4246
4096 hei_ref: Height reference for the Beacon signal extraction
4247 hei_ref: Height reference for the Beacon signal extraction
4097 tauindex:
4248 tauindex:
4098 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4249 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4099
4250
4100 cohDetection: Whether to user Coherent detection or not
4251 cohDetection: Whether to user Coherent detection or not
4101 cohDet_timeStep: Coherent Detection calculation time step
4252 cohDet_timeStep: Coherent Detection calculation time step
4102 cohDet_thresh: Coherent Detection phase threshold to correct phases
4253 cohDet_thresh: Coherent Detection phase threshold to correct phases
4103
4254
4104 noise_timeStep: Noise calculation time step
4255 noise_timeStep: Noise calculation time step
4105 noise_multiple: Noise multiple to define signal threshold
4256 noise_multiple: Noise multiple to define signal threshold
4106
4257
4107 multDet_timeLimit: Multiple Detection Removal time limit in seconds
4258 multDet_timeLimit: Multiple Detection Removal time limit in seconds
4108 multDet_rangeLimit: Multiple Detection Removal range limit in km
4259 multDet_rangeLimit: Multiple Detection Removal range limit in km
4109
4260
4110 phaseThresh: Maximum phase difference between receiver to be consider a meteor
4261 phaseThresh: Maximum phase difference between receiver to be consider a meteor
4111 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
4262 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
4112
4263
4113 hmin: Minimum Height of the meteor to use it in the further wind estimations
4264 hmin: Minimum Height of the meteor to use it in the further wind estimations
4114 hmax: Maximum Height of the meteor to use it in the further wind estimations
4265 hmax: Maximum Height of the meteor to use it in the further wind estimations
4115 azimuth: Azimuth angle correction
4266 azimuth: Azimuth angle correction
4116
4267
4117 Affected:
4268 Affected:
4118 self.dataOut.data_param
4269 self.dataOut.data_param
4119
4270
4120 Rejection Criteria (Errors):
4271 Rejection Criteria (Errors):
4121 0: No error; analysis OK
4272 0: No error; analysis OK
4122 1: SNR < SNR threshold
4273 1: SNR < SNR threshold
4123 2: angle of arrival (AOA) ambiguously determined
4274 2: angle of arrival (AOA) ambiguously determined
4124 3: AOA estimate not feasible
4275 3: AOA estimate not feasible
4125 4: Large difference in AOAs obtained from different antenna baselines
4276 4: Large difference in AOAs obtained from different antenna baselines
4126 5: echo at start or end of time series
4277 5: echo at start or end of time series
4127 6: echo less than 5 examples long; too short for analysis
4278 6: echo less than 5 examples long; too short for analysis
4128 7: echo rise exceeds 0.3s
4279 7: echo rise exceeds 0.3s
4129 8: echo decay time less than twice rise time
4280 8: echo decay time less than twice rise time
4130 9: large power level before echo
4281 9: large power level before echo
4131 10: large power level after echo
4282 10: large power level after echo
4132 11: poor fit to amplitude for estimation of decay time
4283 11: poor fit to amplitude for estimation of decay time
4133 12: poor fit to CCF phase variation for estimation of radial drift velocity
4284 12: poor fit to CCF phase variation for estimation of radial drift velocity
4134 13: height unresolvable echo: not valid height within 70 to 110 km
4285 13: height unresolvable echo: not valid height within 70 to 110 km
4135 14: height ambiguous echo: more then one possible height within 70 to 110 km
4286 14: height ambiguous echo: more then one possible height within 70 to 110 km
4136 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
4287 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
4137 16: oscilatory echo, indicating event most likely not an underdense echo
4288 16: oscilatory echo, indicating event most likely not an underdense echo
4138
4289
4139 17: phase difference in meteor Reestimation
4290 17: phase difference in meteor Reestimation
4140
4291
4141 Data Storage:
4292 Data Storage:
4142 Meteors for Wind Estimation (8):
4293 Meteors for Wind Estimation (8):
4143 Utc Time | Range Height
4294 Utc Time | Range Height
4144 Azimuth Zenith errorCosDir
4295 Azimuth Zenith errorCosDir
4145 VelRad errorVelRad
4296 VelRad errorVelRad
4146 Phase0 Phase1 Phase2 Phase3
4297 Phase0 Phase1 Phase2 Phase3
4147 TypeError
4298 TypeError
4148
4299
4149 '''
4300 '''
4150
4301
4151 def run(self, dataOut, hei_ref = None, tauindex = 0,
4302 def run(self, dataOut, hei_ref = None, tauindex = 0,
4152 phaseOffsets = None,
4303 phaseOffsets = None,
4153 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
4304 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
4154 noise_timeStep = 4, noise_multiple = 4,
4305 noise_timeStep = 4, noise_multiple = 4,
4155 multDet_timeLimit = 1, multDet_rangeLimit = 3,
4306 multDet_timeLimit = 1, multDet_rangeLimit = 3,
4156 phaseThresh = 20, SNRThresh = 5,
4307 phaseThresh = 20, SNRThresh = 5,
4157 hmin = 50, hmax=150, azimuth = 0,
4308 hmin = 50, hmax=150, azimuth = 0,
4158 channelPositions = None) :
4309 channelPositions = None) :
4159
4310
4160
4311
4161 #Getting Pairslist
4312 #Getting Pairslist
4162 if channelPositions is None:
4313 if channelPositions is None:
4163 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4314 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4164 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4315 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4165 meteorOps = SMOperations()
4316 meteorOps = SMOperations()
4166 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4317 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4167 heiRang = dataOut.heightList
4318 heiRang = dataOut.heightList
4168 #Get Beacon signal - No Beacon signal anymore
4319 #Get Beacon signal - No Beacon signal anymore
4169 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
4320 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
4170 #
4321 #
4171 # if hei_ref != None:
4322 # if hei_ref != None:
4172 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
4323 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
4173 #
4324 #
4174
4325
4175
4326
4176 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
4327 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
4177 # see if the user put in pre defined phase shifts
4328 # see if the user put in pre defined phase shifts
4178 voltsPShift = dataOut.data_pre.copy()
4329 voltsPShift = dataOut.data_pre.copy()
4179
4330
4180 # if predefinedPhaseShifts != None:
4331 # if predefinedPhaseShifts != None:
4181 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
4332 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
4182 #
4333 #
4183 # # elif beaconPhaseShifts:
4334 # # elif beaconPhaseShifts:
4184 # # #get hardware phase shifts using beacon signal
4335 # # #get hardware phase shifts using beacon signal
4185 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
4336 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
4186 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
4337 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
4187 #
4338 #
4188 # else:
4339 # else:
4189 # hardwarePhaseShifts = numpy.zeros(5)
4340 # hardwarePhaseShifts = numpy.zeros(5)
4190 #
4341 #
4191 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
4342 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
4192 # for i in range(self.dataOut.data_pre.shape[0]):
4343 # for i in range(self.dataOut.data_pre.shape[0]):
4193 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
4344 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
4194
4345
4195 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
4346 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
4196
4347
4197 #Remove DC
4348 #Remove DC
4198 voltsDC = numpy.mean(voltsPShift,1)
4349 voltsDC = numpy.mean(voltsPShift,1)
4199 voltsDC = numpy.mean(voltsDC,1)
4350 voltsDC = numpy.mean(voltsDC,1)
4200 for i in range(voltsDC.shape[0]):
4351 for i in range(voltsDC.shape[0]):
4201 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
4352 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
4202
4353
4203 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
4354 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
4204 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
4355 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
4205
4356
4206 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
4357 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
4207 #Coherent Detection
4358 #Coherent Detection
4208 if cohDetection:
4359 if cohDetection:
4209 #use coherent detection to get the net power
4360 #use coherent detection to get the net power
4210 cohDet_thresh = cohDet_thresh*numpy.pi/180
4361 cohDet_thresh = cohDet_thresh*numpy.pi/180
4211 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
4362 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
4212
4363
4213 #Non-coherent detection!
4364 #Non-coherent detection!
4214 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
4365 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
4215 #********** END OF COH/NON-COH POWER CALCULATION**********************
4366 #********** END OF COH/NON-COH POWER CALCULATION**********************
4216
4367
4217 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
4368 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
4218 #Get noise
4369 #Get noise
4219 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
4370 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
4220 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
4371 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
4221 #Get signal threshold
4372 #Get signal threshold
4222 signalThresh = noise_multiple*noise
4373 signalThresh = noise_multiple*noise
4223 #Meteor echoes detection
4374 #Meteor echoes detection
4224 listMeteors = self.__findMeteors(powerNet, signalThresh)
4375 listMeteors = self.__findMeteors(powerNet, signalThresh)
4225 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
4376 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
4226
4377
4227 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
4378 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
4228 #Parameters
4379 #Parameters
4229 heiRange = dataOut.heightList
4380 heiRange = dataOut.heightList
4230 rangeInterval = heiRange[1] - heiRange[0]
4381 rangeInterval = heiRange[1] - heiRange[0]
4231 rangeLimit = multDet_rangeLimit/rangeInterval
4382 rangeLimit = multDet_rangeLimit/rangeInterval
4232 timeLimit = multDet_timeLimit/dataOut.timeInterval
4383 timeLimit = multDet_timeLimit/dataOut.timeInterval
4233 #Multiple detection removals
4384 #Multiple detection removals
4234 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
4385 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
4235 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
4386 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
4236
4387
4237 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
4388 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
4238 #Parameters
4389 #Parameters
4239 phaseThresh = phaseThresh*numpy.pi/180
4390 phaseThresh = phaseThresh*numpy.pi/180
4240 thresh = [phaseThresh, noise_multiple, SNRThresh]
4391 thresh = [phaseThresh, noise_multiple, SNRThresh]
4241 #Meteor reestimation (Errors N 1, 6, 12, 17)
4392 #Meteor reestimation (Errors N 1, 6, 12, 17)
4242 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
4393 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
4243 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
4394 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
4244 #Estimation of decay times (Errors N 7, 8, 11)
4395 #Estimation of decay times (Errors N 7, 8, 11)
4245 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
4396 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
4246 #******************* END OF METEOR REESTIMATION *******************
4397 #******************* END OF METEOR REESTIMATION *******************
4247
4398
4248 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
4399 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
4249 #Calculating Radial Velocity (Error N 15)
4400 #Calculating Radial Velocity (Error N 15)
4250 radialStdThresh = 10
4401 radialStdThresh = 10
4251 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
4402 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
4252
4403
4253 if len(listMeteors4) > 0:
4404 if len(listMeteors4) > 0:
4254 #Setting New Array
4405 #Setting New Array
4255 date = dataOut.utctime
4406 date = dataOut.utctime
4256 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
4407 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
4257
4408
4258 #Correcting phase offset
4409 #Correcting phase offset
4259 if phaseOffsets != None:
4410 if phaseOffsets != None:
4260 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4411 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4261 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4412 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4262
4413
4263 #Second Pairslist
4414 #Second Pairslist
4264 pairsList = []
4415 pairsList = []
4265 pairx = (0,1)
4416 pairx = (0,1)
4266 pairy = (2,3)
4417 pairy = (2,3)
4267 pairsList.append(pairx)
4418 pairsList.append(pairx)
4268 pairsList.append(pairy)
4419 pairsList.append(pairy)
4269
4420
4270 jph = numpy.array([0,0,0,0])
4421 jph = numpy.array([0,0,0,0])
4271 h = (hmin,hmax)
4422 h = (hmin,hmax)
4272 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4423 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4273
4424
4274 # #Calculate AOA (Error N 3, 4)
4425 # #Calculate AOA (Error N 3, 4)
4275 # #JONES ET AL. 1998
4426 # #JONES ET AL. 1998
4276 # error = arrayParameters[:,-1]
4427 # error = arrayParameters[:,-1]
4277 # AOAthresh = numpy.pi/8
4428 # AOAthresh = numpy.pi/8
4278 # phases = -arrayParameters[:,9:13]
4429 # phases = -arrayParameters[:,9:13]
4279 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
4430 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
4280 #
4431 #
4281 # #Calculate Heights (Error N 13 and 14)
4432 # #Calculate Heights (Error N 13 and 14)
4282 # error = arrayParameters[:,-1]
4433 # error = arrayParameters[:,-1]
4283 # Ranges = arrayParameters[:,2]
4434 # Ranges = arrayParameters[:,2]
4284 # zenith = arrayParameters[:,5]
4435 # zenith = arrayParameters[:,5]
4285 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
4436 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
4286 # error = arrayParameters[:,-1]
4437 # error = arrayParameters[:,-1]
4287 #********************* END OF PARAMETERS CALCULATION **************************
4438 #********************* END OF PARAMETERS CALCULATION **************************
4288
4439
4289 #***************************+ PASS DATA TO NEXT STEP **********************
4440 #***************************+ PASS DATA TO NEXT STEP **********************
4290 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
4441 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
4291 dataOut.data_param = arrayParameters
4442 dataOut.data_param = arrayParameters
4292
4443
4293 if arrayParameters is None:
4444 if arrayParameters is None:
4294 dataOut.flagNoData = True
4445 dataOut.flagNoData = True
4295 else:
4446 else:
4296 dataOut.flagNoData = True
4447 dataOut.flagNoData = True
4297
4448
4298 return
4449 return
4299
4450
4300 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
4451 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
4301
4452
4302 minIndex = min(newheis[0])
4453 minIndex = min(newheis[0])
4303 maxIndex = max(newheis[0])
4454 maxIndex = max(newheis[0])
4304
4455
4305 voltage = voltage0[:,:,minIndex:maxIndex+1]
4456 voltage = voltage0[:,:,minIndex:maxIndex+1]
4306 nLength = voltage.shape[1]/n
4457 nLength = voltage.shape[1]/n
4307 nMin = 0
4458 nMin = 0
4308 nMax = 0
4459 nMax = 0
4309 phaseOffset = numpy.zeros((len(pairslist),n))
4460 phaseOffset = numpy.zeros((len(pairslist),n))
4310
4461
4311 for i in range(n):
4462 for i in range(n):
4312 nMax += nLength
4463 nMax += nLength
4313 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
4464 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
4314 phaseCCF = numpy.mean(phaseCCF, axis = 2)
4465 phaseCCF = numpy.mean(phaseCCF, axis = 2)
4315 phaseOffset[:,i] = phaseCCF.transpose()
4466 phaseOffset[:,i] = phaseCCF.transpose()
4316 nMin = nMax
4467 nMin = nMax
4317 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
4468 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
4318
4469
4319 #Remove Outliers
4470 #Remove Outliers
4320 factor = 2
4471 factor = 2
4321 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
4472 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
4322 dw = numpy.std(wt,axis = 1)
4473 dw = numpy.std(wt,axis = 1)
4323 dw = dw.reshape((dw.size,1))
4474 dw = dw.reshape((dw.size,1))
4324 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
4475 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
4325 phaseOffset[ind] = numpy.nan
4476 phaseOffset[ind] = numpy.nan
4326 phaseOffset = stats.nanmean(phaseOffset, axis=1)
4477 phaseOffset = stats.nanmean(phaseOffset, axis=1)
4327
4478
4328 return phaseOffset
4479 return phaseOffset
4329
4480
4330 def __shiftPhase(self, data, phaseShift):
4481 def __shiftPhase(self, data, phaseShift):
4331 #this will shift the phase of a complex number
4482 #this will shift the phase of a complex number
4332 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
4483 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
4333 return dataShifted
4484 return dataShifted
4334
4485
4335 def __estimatePhaseDifference(self, array, pairslist):
4486 def __estimatePhaseDifference(self, array, pairslist):
4336 nChannel = array.shape[0]
4487 nChannel = array.shape[0]
4337 nHeights = array.shape[2]
4488 nHeights = array.shape[2]
4338 numPairs = len(pairslist)
4489 numPairs = len(pairslist)
4339 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
4490 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
4340 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
4491 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
4341
4492
4342 #Correct phases
4493 #Correct phases
4343 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
4494 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
4344 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4495 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4345
4496
4346 if indDer[0].shape[0] > 0:
4497 if indDer[0].shape[0] > 0:
4347 for i in range(indDer[0].shape[0]):
4498 for i in range(indDer[0].shape[0]):
4348 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
4499 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
4349 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
4500 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
4350
4501
4351 # for j in range(numSides):
4502 # for j in range(numSides):
4352 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
4503 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
4353 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
4504 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
4354 #
4505 #
4355 #Linear
4506 #Linear
4356 phaseInt = numpy.zeros((numPairs,1))
4507 phaseInt = numpy.zeros((numPairs,1))
4357 angAllCCF = phaseCCF[:,[0,1,3,4],0]
4508 angAllCCF = phaseCCF[:,[0,1,3,4],0]
4358 for j in range(numPairs):
4509 for j in range(numPairs):
4359 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
4510 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
4360 phaseInt[j] = fit[1]
4511 phaseInt[j] = fit[1]
4361 #Phase Differences
4512 #Phase Differences
4362 phaseDiff = phaseInt - phaseCCF[:,2,:]
4513 phaseDiff = phaseInt - phaseCCF[:,2,:]
4363 phaseArrival = phaseInt.reshape(phaseInt.size)
4514 phaseArrival = phaseInt.reshape(phaseInt.size)
4364
4515
4365 #Dealias
4516 #Dealias
4366 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
4517 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
4367 # indAlias = numpy.where(phaseArrival > numpy.pi)
4518 # indAlias = numpy.where(phaseArrival > numpy.pi)
4368 # phaseArrival[indAlias] -= 2*numpy.pi
4519 # phaseArrival[indAlias] -= 2*numpy.pi
4369 # indAlias = numpy.where(phaseArrival < -numpy.pi)
4520 # indAlias = numpy.where(phaseArrival < -numpy.pi)
4370 # phaseArrival[indAlias] += 2*numpy.pi
4521 # phaseArrival[indAlias] += 2*numpy.pi
4371
4522
4372 return phaseDiff, phaseArrival
4523 return phaseDiff, phaseArrival
4373
4524
4374 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
4525 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
4375 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
4526 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
4376 #find the phase shifts of each channel over 1 second intervals
4527 #find the phase shifts of each channel over 1 second intervals
4377 #only look at ranges below the beacon signal
4528 #only look at ranges below the beacon signal
4378 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4529 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4379 numBlocks = int(volts.shape[1]/numProfPerBlock)
4530 numBlocks = int(volts.shape[1]/numProfPerBlock)
4380 numHeights = volts.shape[2]
4531 numHeights = volts.shape[2]
4381 nChannel = volts.shape[0]
4532 nChannel = volts.shape[0]
4382 voltsCohDet = volts.copy()
4533 voltsCohDet = volts.copy()
4383
4534
4384 pairsarray = numpy.array(pairslist)
4535 pairsarray = numpy.array(pairslist)
4385 indSides = pairsarray[:,1]
4536 indSides = pairsarray[:,1]
4386 # indSides = numpy.array(range(nChannel))
4537 # indSides = numpy.array(range(nChannel))
4387 # indSides = numpy.delete(indSides, indCenter)
4538 # indSides = numpy.delete(indSides, indCenter)
4388 #
4539 #
4389 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
4540 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
4390 listBlocks = numpy.array_split(volts, numBlocks, 1)
4541 listBlocks = numpy.array_split(volts, numBlocks, 1)
4391
4542
4392 startInd = 0
4543 startInd = 0
4393 endInd = 0
4544 endInd = 0
4394
4545
4395 for i in range(numBlocks):
4546 for i in range(numBlocks):
4396 startInd = endInd
4547 startInd = endInd
4397 endInd = endInd + listBlocks[i].shape[1]
4548 endInd = endInd + listBlocks[i].shape[1]
4398
4549
4399 arrayBlock = listBlocks[i]
4550 arrayBlock = listBlocks[i]
4400 # arrayBlockCenter = listCenter[i]
4551 # arrayBlockCenter = listCenter[i]
4401
4552
4402 #Estimate the Phase Difference
4553 #Estimate the Phase Difference
4403 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
4554 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
4404 #Phase Difference RMS
4555 #Phase Difference RMS
4405 arrayPhaseRMS = numpy.abs(phaseDiff)
4556 arrayPhaseRMS = numpy.abs(phaseDiff)
4406 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
4557 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
4407 indPhase = numpy.where(phaseRMSaux==4)
4558 indPhase = numpy.where(phaseRMSaux==4)
4408 #Shifting
4559 #Shifting
4409 if indPhase[0].shape[0] > 0:
4560 if indPhase[0].shape[0] > 0:
4410 for j in range(indSides.size):
4561 for j in range(indSides.size):
4411 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
4562 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
4412 voltsCohDet[:,startInd:endInd,:] = arrayBlock
4563 voltsCohDet[:,startInd:endInd,:] = arrayBlock
4413
4564
4414 return voltsCohDet
4565 return voltsCohDet
4415
4566
4416 def __calculateCCF(self, volts, pairslist ,laglist):
4567 def __calculateCCF(self, volts, pairslist ,laglist):
4417
4568
4418 nHeights = volts.shape[2]
4569 nHeights = volts.shape[2]
4419 nPoints = volts.shape[1]
4570 nPoints = volts.shape[1]
4420 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
4571 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
4421
4572
4422 for i in range(len(pairslist)):
4573 for i in range(len(pairslist)):
4423 volts1 = volts[pairslist[i][0]]
4574 volts1 = volts[pairslist[i][0]]
4424 volts2 = volts[pairslist[i][1]]
4575 volts2 = volts[pairslist[i][1]]
4425
4576
4426 for t in range(len(laglist)):
4577 for t in range(len(laglist)):
4427 idxT = laglist[t]
4578 idxT = laglist[t]
4428 if idxT >= 0:
4579 if idxT >= 0:
4429 vStacked = numpy.vstack((volts2[idxT:,:],
4580 vStacked = numpy.vstack((volts2[idxT:,:],
4430 numpy.zeros((idxT, nHeights),dtype='complex')))
4581 numpy.zeros((idxT, nHeights),dtype='complex')))
4431 else:
4582 else:
4432 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
4583 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
4433 volts2[:(nPoints + idxT),:]))
4584 volts2[:(nPoints + idxT),:]))
4434 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
4585 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
4435
4586
4436 vStacked = None
4587 vStacked = None
4437 return voltsCCF
4588 return voltsCCF
4438
4589
4439 def __getNoise(self, power, timeSegment, timeInterval):
4590 def __getNoise(self, power, timeSegment, timeInterval):
4440 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4591 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4441 numBlocks = int(power.shape[0]/numProfPerBlock)
4592 numBlocks = int(power.shape[0]/numProfPerBlock)
4442 numHeights = power.shape[1]
4593 numHeights = power.shape[1]
4443
4594
4444 listPower = numpy.array_split(power, numBlocks, 0)
4595 listPower = numpy.array_split(power, numBlocks, 0)
4445 noise = numpy.zeros((power.shape[0], power.shape[1]))
4596 noise = numpy.zeros((power.shape[0], power.shape[1]))
4446 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
4597 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
4447
4598
4448 startInd = 0
4599 startInd = 0
4449 endInd = 0
4600 endInd = 0
4450
4601
4451 for i in range(numBlocks): #split por canal
4602 for i in range(numBlocks): #split por canal
4452 startInd = endInd
4603 startInd = endInd
4453 endInd = endInd + listPower[i].shape[0]
4604 endInd = endInd + listPower[i].shape[0]
4454
4605
4455 arrayBlock = listPower[i]
4606 arrayBlock = listPower[i]
4456 noiseAux = numpy.mean(arrayBlock, 0)
4607 noiseAux = numpy.mean(arrayBlock, 0)
4457 # noiseAux = numpy.median(noiseAux)
4608 # noiseAux = numpy.median(noiseAux)
4458 # noiseAux = numpy.mean(arrayBlock)
4609 # noiseAux = numpy.mean(arrayBlock)
4459 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
4610 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
4460
4611
4461 noiseAux1 = numpy.mean(arrayBlock)
4612 noiseAux1 = numpy.mean(arrayBlock)
4462 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
4613 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
4463
4614
4464 return noise, noise1
4615 return noise, noise1
4465
4616
4466 def __findMeteors(self, power, thresh):
4617 def __findMeteors(self, power, thresh):
4467 nProf = power.shape[0]
4618 nProf = power.shape[0]
4468 nHeights = power.shape[1]
4619 nHeights = power.shape[1]
4469 listMeteors = []
4620 listMeteors = []
4470
4621
4471 for i in range(nHeights):
4622 for i in range(nHeights):
4472 powerAux = power[:,i]
4623 powerAux = power[:,i]
4473 threshAux = thresh[:,i]
4624 threshAux = thresh[:,i]
4474
4625
4475 indUPthresh = numpy.where(powerAux > threshAux)[0]
4626 indUPthresh = numpy.where(powerAux > threshAux)[0]
4476 indDNthresh = numpy.where(powerAux <= threshAux)[0]
4627 indDNthresh = numpy.where(powerAux <= threshAux)[0]
4477
4628
4478 j = 0
4629 j = 0
4479
4630
4480 while (j < indUPthresh.size - 2):
4631 while (j < indUPthresh.size - 2):
4481 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
4632 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
4482 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
4633 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
4483 indDNthresh = indDNthresh[indDNAux]
4634 indDNthresh = indDNthresh[indDNAux]
4484
4635
4485 if (indDNthresh.size > 0):
4636 if (indDNthresh.size > 0):
4486 indEnd = indDNthresh[0] - 1
4637 indEnd = indDNthresh[0] - 1
4487 indInit = indUPthresh[j]
4638 indInit = indUPthresh[j]
4488
4639
4489 meteor = powerAux[indInit:indEnd + 1]
4640 meteor = powerAux[indInit:indEnd + 1]
4490 indPeak = meteor.argmax() + indInit
4641 indPeak = meteor.argmax() + indInit
4491 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
4642 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
4492
4643
4493 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
4644 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
4494 j = numpy.where(indUPthresh == indEnd)[0] + 1
4645 j = numpy.where(indUPthresh == indEnd)[0] + 1
4495 else: j+=1
4646 else: j+=1
4496 else: j+=1
4647 else: j+=1
4497
4648
4498 return listMeteors
4649 return listMeteors
4499
4650
4500 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
4651 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
4501
4652
4502 arrayMeteors = numpy.asarray(listMeteors)
4653 arrayMeteors = numpy.asarray(listMeteors)
4503 listMeteors1 = []
4654 listMeteors1 = []
4504
4655
4505 while arrayMeteors.shape[0] > 0:
4656 while arrayMeteors.shape[0] > 0:
4506 FLAs = arrayMeteors[:,4]
4657 FLAs = arrayMeteors[:,4]
4507 maxFLA = FLAs.argmax()
4658 maxFLA = FLAs.argmax()
4508 listMeteors1.append(arrayMeteors[maxFLA,:])
4659 listMeteors1.append(arrayMeteors[maxFLA,:])
4509
4660
4510 MeteorInitTime = arrayMeteors[maxFLA,1]
4661 MeteorInitTime = arrayMeteors[maxFLA,1]
4511 MeteorEndTime = arrayMeteors[maxFLA,3]
4662 MeteorEndTime = arrayMeteors[maxFLA,3]
4512 MeteorHeight = arrayMeteors[maxFLA,0]
4663 MeteorHeight = arrayMeteors[maxFLA,0]
4513
4664
4514 #Check neighborhood
4665 #Check neighborhood
4515 maxHeightIndex = MeteorHeight + rangeLimit
4666 maxHeightIndex = MeteorHeight + rangeLimit
4516 minHeightIndex = MeteorHeight - rangeLimit
4667 minHeightIndex = MeteorHeight - rangeLimit
4517 minTimeIndex = MeteorInitTime - timeLimit
4668 minTimeIndex = MeteorInitTime - timeLimit
4518 maxTimeIndex = MeteorEndTime + timeLimit
4669 maxTimeIndex = MeteorEndTime + timeLimit
4519
4670
4520 #Check Heights
4671 #Check Heights
4521 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
4672 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
4522 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
4673 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
4523 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
4674 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
4524
4675
4525 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
4676 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
4526
4677
4527 return listMeteors1
4678 return listMeteors1
4528
4679
4529 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
4680 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
4530 numHeights = volts.shape[2]
4681 numHeights = volts.shape[2]
4531 nChannel = volts.shape[0]
4682 nChannel = volts.shape[0]
4532
4683
4533 thresholdPhase = thresh[0]
4684 thresholdPhase = thresh[0]
4534 thresholdNoise = thresh[1]
4685 thresholdNoise = thresh[1]
4535 thresholdDB = float(thresh[2])
4686 thresholdDB = float(thresh[2])
4536
4687
4537 thresholdDB1 = 10**(thresholdDB/10)
4688 thresholdDB1 = 10**(thresholdDB/10)
4538 pairsarray = numpy.array(pairslist)
4689 pairsarray = numpy.array(pairslist)
4539 indSides = pairsarray[:,1]
4690 indSides = pairsarray[:,1]
4540
4691
4541 pairslist1 = list(pairslist)
4692 pairslist1 = list(pairslist)
4542 pairslist1.append((0,1))
4693 pairslist1.append((0,1))
4543 pairslist1.append((3,4))
4694 pairslist1.append((3,4))
4544
4695
4545 listMeteors1 = []
4696 listMeteors1 = []
4546 listPowerSeries = []
4697 listPowerSeries = []
4547 listVoltageSeries = []
4698 listVoltageSeries = []
4548 #volts has the war data
4699 #volts has the war data
4549
4700
4550 if frequency == 30e6:
4701 if frequency == 30e6:
4551 timeLag = 45*10**-3
4702 timeLag = 45*10**-3
4552 else:
4703 else:
4553 timeLag = 15*10**-3
4704 timeLag = 15*10**-3
4554 lag = numpy.ceil(timeLag/timeInterval)
4705 lag = numpy.ceil(timeLag/timeInterval)
4555
4706
4556 for i in range(len(listMeteors)):
4707 for i in range(len(listMeteors)):
4557
4708
4558 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
4709 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
4559 meteorAux = numpy.zeros(16)
4710 meteorAux = numpy.zeros(16)
4560
4711
4561 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
4712 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
4562 mHeight = listMeteors[i][0]
4713 mHeight = listMeteors[i][0]
4563 mStart = listMeteors[i][1]
4714 mStart = listMeteors[i][1]
4564 mPeak = listMeteors[i][2]
4715 mPeak = listMeteors[i][2]
4565 mEnd = listMeteors[i][3]
4716 mEnd = listMeteors[i][3]
4566
4717
4567 #get the volt data between the start and end times of the meteor
4718 #get the volt data between the start and end times of the meteor
4568 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
4719 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
4569 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4720 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4570
4721
4571 #3.6. Phase Difference estimation
4722 #3.6. Phase Difference estimation
4572 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
4723 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
4573
4724
4574 #3.7. Phase difference removal & meteor start, peak and end times reestimated
4725 #3.7. Phase difference removal & meteor start, peak and end times reestimated
4575 #meteorVolts0.- all Channels, all Profiles
4726 #meteorVolts0.- all Channels, all Profiles
4576 meteorVolts0 = volts[:,:,mHeight]
4727 meteorVolts0 = volts[:,:,mHeight]
4577 meteorThresh = noise[:,mHeight]*thresholdNoise
4728 meteorThresh = noise[:,mHeight]*thresholdNoise
4578 meteorNoise = noise[:,mHeight]
4729 meteorNoise = noise[:,mHeight]
4579 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
4730 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
4580 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
4731 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
4581
4732
4582 #Times reestimation
4733 #Times reestimation
4583 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
4734 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
4584 if mStart1.size > 0:
4735 if mStart1.size > 0:
4585 mStart1 = mStart1[-1] + 1
4736 mStart1 = mStart1[-1] + 1
4586
4737
4587 else:
4738 else:
4588 mStart1 = mPeak
4739 mStart1 = mPeak
4589
4740
4590 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
4741 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
4591 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
4742 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
4592 if mEndDecayTime1.size == 0:
4743 if mEndDecayTime1.size == 0:
4593 mEndDecayTime1 = powerNet0.size
4744 mEndDecayTime1 = powerNet0.size
4594 else:
4745 else:
4595 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
4746 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
4596 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
4747 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
4597
4748
4598 #meteorVolts1.- all Channels, from start to end
4749 #meteorVolts1.- all Channels, from start to end
4599 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
4750 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
4600 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
4751 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
4601 if meteorVolts2.shape[1] == 0:
4752 if meteorVolts2.shape[1] == 0:
4602 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
4753 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
4603 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
4754 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
4604 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
4755 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
4605 ##################### END PARAMETERS REESTIMATION #########################
4756 ##################### END PARAMETERS REESTIMATION #########################
4606
4757
4607 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
4758 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
4608 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
4759 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
4609 if meteorVolts2.shape[1] > 0:
4760 if meteorVolts2.shape[1] > 0:
4610 #Phase Difference re-estimation
4761 #Phase Difference re-estimation
4611 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
4762 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
4612 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
4763 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
4613 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
4764 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
4614 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
4765 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
4615 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
4766 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
4616
4767
4617 #Phase Difference RMS
4768 #Phase Difference RMS
4618 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
4769 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
4619 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
4770 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
4620 #Data from Meteor
4771 #Data from Meteor
4621 mPeak1 = powerNet1.argmax() + mStart1
4772 mPeak1 = powerNet1.argmax() + mStart1
4622 mPeakPower1 = powerNet1.max()
4773 mPeakPower1 = powerNet1.max()
4623 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
4774 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
4624 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
4775 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
4625 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
4776 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
4626 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
4777 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
4627 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
4778 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
4628 #Vectorize
4779 #Vectorize
4629 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
4780 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
4630 meteorAux[7:11] = phaseDiffint[0:4]
4781 meteorAux[7:11] = phaseDiffint[0:4]
4631
4782
4632 #Rejection Criterions
4783 #Rejection Criterions
4633 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
4784 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
4634 meteorAux[-1] = 17
4785 meteorAux[-1] = 17
4635 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
4786 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
4636 meteorAux[-1] = 1
4787 meteorAux[-1] = 1
4637
4788
4638
4789
4639 else:
4790 else:
4640 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
4791 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
4641 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
4792 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
4642 PowerSeries = 0
4793 PowerSeries = 0
4643
4794
4644 listMeteors1.append(meteorAux)
4795 listMeteors1.append(meteorAux)
4645 listPowerSeries.append(PowerSeries)
4796 listPowerSeries.append(PowerSeries)
4646 listVoltageSeries.append(meteorVolts1)
4797 listVoltageSeries.append(meteorVolts1)
4647
4798
4648 return listMeteors1, listPowerSeries, listVoltageSeries
4799 return listMeteors1, listPowerSeries, listVoltageSeries
4649
4800
4650 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
4801 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
4651
4802
4652 threshError = 10
4803 threshError = 10
4653 #Depending if it is 30 or 50 MHz
4804 #Depending if it is 30 or 50 MHz
4654 if frequency == 30e6:
4805 if frequency == 30e6:
4655 timeLag = 45*10**-3
4806 timeLag = 45*10**-3
4656 else:
4807 else:
4657 timeLag = 15*10**-3
4808 timeLag = 15*10**-3
4658 lag = numpy.ceil(timeLag/timeInterval)
4809 lag = numpy.ceil(timeLag/timeInterval)
4659
4810
4660 listMeteors1 = []
4811 listMeteors1 = []
4661
4812
4662 for i in range(len(listMeteors)):
4813 for i in range(len(listMeteors)):
4663 meteorPower = listPower[i]
4814 meteorPower = listPower[i]
4664 meteorAux = listMeteors[i]
4815 meteorAux = listMeteors[i]
4665
4816
4666 if meteorAux[-1] == 0:
4817 if meteorAux[-1] == 0:
4667
4818
4668 try:
4819 try:
4669 indmax = meteorPower.argmax()
4820 indmax = meteorPower.argmax()
4670 indlag = indmax + lag
4821 indlag = indmax + lag
4671
4822
4672 y = meteorPower[indlag:]
4823 y = meteorPower[indlag:]
4673 x = numpy.arange(0, y.size)*timeLag
4824 x = numpy.arange(0, y.size)*timeLag
4674
4825
4675 #first guess
4826 #first guess
4676 a = y[0]
4827 a = y[0]
4677 tau = timeLag
4828 tau = timeLag
4678 #exponential fit
4829 #exponential fit
4679 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
4830 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
4680 y1 = self.__exponential_function(x, *popt)
4831 y1 = self.__exponential_function(x, *popt)
4681 #error estimation
4832 #error estimation
4682 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
4833 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
4683
4834
4684 decayTime = popt[1]
4835 decayTime = popt[1]
4685 riseTime = indmax*timeInterval
4836 riseTime = indmax*timeInterval
4686 meteorAux[11:13] = [decayTime, error]
4837 meteorAux[11:13] = [decayTime, error]
4687
4838
4688 #Table items 7, 8 and 11
4839 #Table items 7, 8 and 11
4689 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
4840 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
4690 meteorAux[-1] = 7
4841 meteorAux[-1] = 7
4691 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
4842 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
4692 meteorAux[-1] = 8
4843 meteorAux[-1] = 8
4693 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
4844 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
4694 meteorAux[-1] = 11
4845 meteorAux[-1] = 11
4695
4846
4696
4847
4697 except:
4848 except:
4698 meteorAux[-1] = 11
4849 meteorAux[-1] = 11
4699
4850
4700
4851
4701 listMeteors1.append(meteorAux)
4852 listMeteors1.append(meteorAux)
4702
4853
4703 return listMeteors1
4854 return listMeteors1
4704
4855
4705 #Exponential Function
4856 #Exponential Function
4706
4857
4707 def __exponential_function(self, x, a, tau):
4858 def __exponential_function(self, x, a, tau):
4708 y = a*numpy.exp(-x/tau)
4859 y = a*numpy.exp(-x/tau)
4709 return y
4860 return y
4710
4861
4711 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
4862 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
4712
4863
4713 pairslist1 = list(pairslist)
4864 pairslist1 = list(pairslist)
4714 pairslist1.append((0,1))
4865 pairslist1.append((0,1))
4715 pairslist1.append((3,4))
4866 pairslist1.append((3,4))
4716 numPairs = len(pairslist1)
4867 numPairs = len(pairslist1)
4717 #Time Lag
4868 #Time Lag
4718 timeLag = 45*10**-3
4869 timeLag = 45*10**-3
4719 c = 3e8
4870 c = 3e8
4720 lag = numpy.ceil(timeLag/timeInterval)
4871 lag = numpy.ceil(timeLag/timeInterval)
4721 freq = 30e6
4872 freq = 30e6
4722
4873
4723 listMeteors1 = []
4874 listMeteors1 = []
4724
4875
4725 for i in range(len(listMeteors)):
4876 for i in range(len(listMeteors)):
4726 meteorAux = listMeteors[i]
4877 meteorAux = listMeteors[i]
4727 if meteorAux[-1] == 0:
4878 if meteorAux[-1] == 0:
4728 mStart = listMeteors[i][1]
4879 mStart = listMeteors[i][1]
4729 mPeak = listMeteors[i][2]
4880 mPeak = listMeteors[i][2]
4730 mLag = mPeak - mStart + lag
4881 mLag = mPeak - mStart + lag
4731
4882
4732 #get the volt data between the start and end times of the meteor
4883 #get the volt data between the start and end times of the meteor
4733 meteorVolts = listVolts[i]
4884 meteorVolts = listVolts[i]
4734 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4885 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4735
4886
4736 #Get CCF
4887 #Get CCF
4737 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
4888 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
4738
4889
4739 #Method 2
4890 #Method 2
4740 slopes = numpy.zeros(numPairs)
4891 slopes = numpy.zeros(numPairs)
4741 time = numpy.array([-2,-1,1,2])*timeInterval
4892 time = numpy.array([-2,-1,1,2])*timeInterval
4742 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
4893 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
4743
4894
4744 #Correct phases
4895 #Correct phases
4745 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
4896 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
4746 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4897 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4747
4898
4748 if indDer[0].shape[0] > 0:
4899 if indDer[0].shape[0] > 0:
4749 for i in range(indDer[0].shape[0]):
4900 for i in range(indDer[0].shape[0]):
4750 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
4901 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
4751 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
4902 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
4752
4903
4753 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
4904 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
4754 for j in range(numPairs):
4905 for j in range(numPairs):
4755 fit = stats.linregress(time, angAllCCF[j,:])
4906 fit = stats.linregress(time, angAllCCF[j,:])
4756 slopes[j] = fit[0]
4907 slopes[j] = fit[0]
4757
4908
4758 #Remove Outlier
4909 #Remove Outlier
4759 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4910 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4760 # slopes = numpy.delete(slopes,indOut)
4911 # slopes = numpy.delete(slopes,indOut)
4761 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4912 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4762 # slopes = numpy.delete(slopes,indOut)
4913 # slopes = numpy.delete(slopes,indOut)
4763
4914
4764 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
4915 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
4765 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
4916 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
4766 meteorAux[-2] = radialError
4917 meteorAux[-2] = radialError
4767 meteorAux[-3] = radialVelocity
4918 meteorAux[-3] = radialVelocity
4768
4919
4769 #Setting Error
4920 #Setting Error
4770 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
4921 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
4771 if numpy.abs(radialVelocity) > 200:
4922 if numpy.abs(radialVelocity) > 200:
4772 meteorAux[-1] = 15
4923 meteorAux[-1] = 15
4773 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
4924 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
4774 elif radialError > radialStdThresh:
4925 elif radialError > radialStdThresh:
4775 meteorAux[-1] = 12
4926 meteorAux[-1] = 12
4776
4927
4777 listMeteors1.append(meteorAux)
4928 listMeteors1.append(meteorAux)
4778 return listMeteors1
4929 return listMeteors1
4779
4930
4780 def __setNewArrays(self, listMeteors, date, heiRang):
4931 def __setNewArrays(self, listMeteors, date, heiRang):
4781
4932
4782 #New arrays
4933 #New arrays
4783 arrayMeteors = numpy.array(listMeteors)
4934 arrayMeteors = numpy.array(listMeteors)
4784 arrayParameters = numpy.zeros((len(listMeteors), 13))
4935 arrayParameters = numpy.zeros((len(listMeteors), 13))
4785
4936
4786 #Date inclusion
4937 #Date inclusion
4787 # date = re.findall(r'\((.*?)\)', date)
4938 # date = re.findall(r'\((.*?)\)', date)
4788 # date = date[0].split(',')
4939 # date = date[0].split(',')
4789 # date = map(int, date)
4940 # date = map(int, date)
4790 #
4941 #
4791 # if len(date)<6:
4942 # if len(date)<6:
4792 # date.append(0)
4943 # date.append(0)
4793 #
4944 #
4794 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
4945 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
4795 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
4946 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
4796 arrayDate = numpy.tile(date, (len(listMeteors)))
4947 arrayDate = numpy.tile(date, (len(listMeteors)))
4797
4948
4798 #Meteor array
4949 #Meteor array
4799 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
4950 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
4800 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
4951 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
4801
4952
4802 #Parameters Array
4953 #Parameters Array
4803 arrayParameters[:,0] = arrayDate #Date
4954 arrayParameters[:,0] = arrayDate #Date
4804 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
4955 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
4805 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
4956 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
4806 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
4957 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
4807 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
4958 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
4808
4959
4809
4960
4810 return arrayParameters
4961 return arrayParameters
4811
4962
4812 class CorrectSMPhases(Operation):
4963 class CorrectSMPhases(Operation):
4813
4964
4814 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
4965 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
4815
4966
4816 arrayParameters = dataOut.data_param
4967 arrayParameters = dataOut.data_param
4817 pairsList = []
4968 pairsList = []
4818 pairx = (0,1)
4969 pairx = (0,1)
4819 pairy = (2,3)
4970 pairy = (2,3)
4820 pairsList.append(pairx)
4971 pairsList.append(pairx)
4821 pairsList.append(pairy)
4972 pairsList.append(pairy)
4822 jph = numpy.zeros(4)
4973 jph = numpy.zeros(4)
4823
4974
4824 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4975 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4825 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4976 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4826 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
4977 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
4827
4978
4828 meteorOps = SMOperations()
4979 meteorOps = SMOperations()
4829 if channelPositions is None:
4980 if channelPositions is None:
4830 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4981 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4831 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4982 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4832
4983
4833 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4984 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4834 h = (hmin,hmax)
4985 h = (hmin,hmax)
4835
4986
4836 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4987 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4837
4988
4838 dataOut.data_param = arrayParameters
4989 dataOut.data_param = arrayParameters
4839 return
4990 return
4840
4991
4841 class SMPhaseCalibration(Operation):
4992 class SMPhaseCalibration(Operation):
4842
4993
4843 __buffer = None
4994 __buffer = None
4844
4995
4845 __initime = None
4996 __initime = None
4846
4997
4847 __dataReady = False
4998 __dataReady = False
4848
4999
4849 __isConfig = False
5000 __isConfig = False
4850
5001
4851 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
5002 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
4852
5003
4853 dataTime = currentTime + paramInterval
5004 dataTime = currentTime + paramInterval
4854 deltaTime = dataTime - initTime
5005 deltaTime = dataTime - initTime
4855
5006
4856 if deltaTime >= outputInterval or deltaTime < 0:
5007 if deltaTime >= outputInterval or deltaTime < 0:
4857 return True
5008 return True
4858
5009
4859 return False
5010 return False
4860
5011
4861 def __getGammas(self, pairs, d, phases):
5012 def __getGammas(self, pairs, d, phases):
4862 gammas = numpy.zeros(2)
5013 gammas = numpy.zeros(2)
4863
5014
4864 for i in range(len(pairs)):
5015 for i in range(len(pairs)):
4865
5016
4866 pairi = pairs[i]
5017 pairi = pairs[i]
4867
5018
4868 phip3 = phases[:,pairi[0]]
5019 phip3 = phases[:,pairi[0]]
4869 d3 = d[pairi[0]]
5020 d3 = d[pairi[0]]
4870 phip2 = phases[:,pairi[1]]
5021 phip2 = phases[:,pairi[1]]
4871 d2 = d[pairi[1]]
5022 d2 = d[pairi[1]]
4872 #Calculating gamma
5023 #Calculating gamma
4873 # jdcos = alp1/(k*d1)
5024 # jdcos = alp1/(k*d1)
4874 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
5025 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
4875 jgamma = -phip2*d3/d2 - phip3
5026 jgamma = -phip2*d3/d2 - phip3
4876 jgamma = numpy.angle(numpy.exp(1j*jgamma))
5027 jgamma = numpy.angle(numpy.exp(1j*jgamma))
4877 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
5028 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
4878 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
5029 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
4879
5030
4880 #Revised distribution
5031 #Revised distribution
4881 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
5032 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
4882
5033
4883 #Histogram
5034 #Histogram
4884 nBins = 64
5035 nBins = 64
4885 rmin = -0.5*numpy.pi
5036 rmin = -0.5*numpy.pi
4886 rmax = 0.5*numpy.pi
5037 rmax = 0.5*numpy.pi
4887 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
5038 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
4888
5039
4889 meteorsY = phaseHisto[0]
5040 meteorsY = phaseHisto[0]
4890 phasesX = phaseHisto[1][:-1]
5041 phasesX = phaseHisto[1][:-1]
4891 width = phasesX[1] - phasesX[0]
5042 width = phasesX[1] - phasesX[0]
4892 phasesX += width/2
5043 phasesX += width/2
4893
5044
4894 #Gaussian aproximation
5045 #Gaussian aproximation
4895 bpeak = meteorsY.argmax()
5046 bpeak = meteorsY.argmax()
4896 peak = meteorsY.max()
5047 peak = meteorsY.max()
4897 jmin = bpeak - 5
5048 jmin = bpeak - 5
4898 jmax = bpeak + 5 + 1
5049 jmax = bpeak + 5 + 1
4899
5050
4900 if jmin<0:
5051 if jmin<0:
4901 jmin = 0
5052 jmin = 0
4902 jmax = 6
5053 jmax = 6
4903 elif jmax > meteorsY.size:
5054 elif jmax > meteorsY.size:
4904 jmin = meteorsY.size - 6
5055 jmin = meteorsY.size - 6
4905 jmax = meteorsY.size
5056 jmax = meteorsY.size
4906
5057
4907 x0 = numpy.array([peak,bpeak,50])
5058 x0 = numpy.array([peak,bpeak,50])
4908 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
5059 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
4909
5060
4910 #Gammas
5061 #Gammas
4911 gammas[i] = coeff[0][1]
5062 gammas[i] = coeff[0][1]
4912
5063
4913 return gammas
5064 return gammas
4914
5065
4915 def __residualFunction(self, coeffs, y, t):
5066 def __residualFunction(self, coeffs, y, t):
4916
5067
4917 return y - self.__gauss_function(t, coeffs)
5068 return y - self.__gauss_function(t, coeffs)
4918
5069
4919 def __gauss_function(self, t, coeffs):
5070 def __gauss_function(self, t, coeffs):
4920
5071
4921 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
5072 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
4922
5073
4923 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
5074 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
4924 meteorOps = SMOperations()
5075 meteorOps = SMOperations()
4925 nchan = 4
5076 nchan = 4
4926 pairx = pairsList[0] #x es 0
5077 pairx = pairsList[0] #x es 0
4927 pairy = pairsList[1] #y es 1
5078 pairy = pairsList[1] #y es 1
4928 center_xangle = 0
5079 center_xangle = 0
4929 center_yangle = 0
5080 center_yangle = 0
4930 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
5081 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
4931 ntimes = len(range_angle)
5082 ntimes = len(range_angle)
4932
5083
4933 nstepsx = 20
5084 nstepsx = 20
4934 nstepsy = 20
5085 nstepsy = 20
4935
5086
4936 for iz in range(ntimes):
5087 for iz in range(ntimes):
4937 min_xangle = -range_angle[iz]/2 + center_xangle
5088 min_xangle = -range_angle[iz]/2 + center_xangle
4938 max_xangle = range_angle[iz]/2 + center_xangle
5089 max_xangle = range_angle[iz]/2 + center_xangle
4939 min_yangle = -range_angle[iz]/2 + center_yangle
5090 min_yangle = -range_angle[iz]/2 + center_yangle
4940 max_yangle = range_angle[iz]/2 + center_yangle
5091 max_yangle = range_angle[iz]/2 + center_yangle
4941
5092
4942 inc_x = (max_xangle-min_xangle)/nstepsx
5093 inc_x = (max_xangle-min_xangle)/nstepsx
4943 inc_y = (max_yangle-min_yangle)/nstepsy
5094 inc_y = (max_yangle-min_yangle)/nstepsy
4944
5095
4945 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
5096 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
4946 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
5097 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
4947 penalty = numpy.zeros((nstepsx,nstepsy))
5098 penalty = numpy.zeros((nstepsx,nstepsy))
4948 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
5099 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
4949 jph = numpy.zeros(nchan)
5100 jph = numpy.zeros(nchan)
4950
5101
4951 # Iterations looking for the offset
5102 # Iterations looking for the offset
4952 for iy in range(int(nstepsy)):
5103 for iy in range(int(nstepsy)):
4953 for ix in range(int(nstepsx)):
5104 for ix in range(int(nstepsx)):
4954 d3 = d[pairsList[1][0]]
5105 d3 = d[pairsList[1][0]]
4955 d2 = d[pairsList[1][1]]
5106 d2 = d[pairsList[1][1]]
4956 d5 = d[pairsList[0][0]]
5107 d5 = d[pairsList[0][0]]
4957 d4 = d[pairsList[0][1]]
5108 d4 = d[pairsList[0][1]]
4958
5109
4959 alp2 = alpha_y[iy] #gamma 1
5110 alp2 = alpha_y[iy] #gamma 1
4960 alp4 = alpha_x[ix] #gamma 0
5111 alp4 = alpha_x[ix] #gamma 0
4961
5112
4962 alp3 = -alp2*d3/d2 - gammas[1]
5113 alp3 = -alp2*d3/d2 - gammas[1]
4963 alp5 = -alp4*d5/d4 - gammas[0]
5114 alp5 = -alp4*d5/d4 - gammas[0]
4964 # jph[pairy[1]] = alpha_y[iy]
5115 # jph[pairy[1]] = alpha_y[iy]
4965 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
5116 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
4966
5117
4967 # jph[pairx[1]] = alpha_x[ix]
5118 # jph[pairx[1]] = alpha_x[ix]
4968 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
5119 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
4969 jph[pairsList[0][1]] = alp4
5120 jph[pairsList[0][1]] = alp4
4970 jph[pairsList[0][0]] = alp5
5121 jph[pairsList[0][0]] = alp5
4971 jph[pairsList[1][0]] = alp3
5122 jph[pairsList[1][0]] = alp3
4972 jph[pairsList[1][1]] = alp2
5123 jph[pairsList[1][1]] = alp2
4973 jph_array[:,ix,iy] = jph
5124 jph_array[:,ix,iy] = jph
4974 # d = [2.0,2.5,2.5,2.0]
5125 # d = [2.0,2.5,2.5,2.0]
4975 #falta chequear si va a leer bien los meteoros
5126 #falta chequear si va a leer bien los meteoros
4976 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
5127 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
4977 error = meteorsArray1[:,-1]
5128 error = meteorsArray1[:,-1]
4978 ind1 = numpy.where(error==0)[0]
5129 ind1 = numpy.where(error==0)[0]
4979 penalty[ix,iy] = ind1.size
5130 penalty[ix,iy] = ind1.size
4980
5131
4981 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
5132 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
4982 phOffset = jph_array[:,i,j]
5133 phOffset = jph_array[:,i,j]
4983
5134
4984 center_xangle = phOffset[pairx[1]]
5135 center_xangle = phOffset[pairx[1]]
4985 center_yangle = phOffset[pairy[1]]
5136 center_yangle = phOffset[pairy[1]]
4986
5137
4987 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
5138 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
4988 phOffset = phOffset*180/numpy.pi
5139 phOffset = phOffset*180/numpy.pi
4989 return phOffset
5140 return phOffset
4990
5141
4991
5142
4992 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
5143 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
4993
5144
4994 dataOut.flagNoData = True
5145 dataOut.flagNoData = True
4995 self.__dataReady = False
5146 self.__dataReady = False
4996 dataOut.outputInterval = nHours*3600
5147 dataOut.outputInterval = nHours*3600
4997
5148
4998 if self.__isConfig == False:
5149 if self.__isConfig == False:
4999 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
5150 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
5000 #Get Initial LTC time
5151 #Get Initial LTC time
5001 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
5152 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
5002 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
5153 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
5003
5154
5004 self.__isConfig = True
5155 self.__isConfig = True
5005
5156
5006 if self.__buffer is None:
5157 if self.__buffer is None:
5007 self.__buffer = dataOut.data_param.copy()
5158 self.__buffer = dataOut.data_param.copy()
5008
5159
5009 else:
5160 else:
5010 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5161 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5011
5162
5012 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5163 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5013
5164
5014 if self.__dataReady:
5165 if self.__dataReady:
5015 dataOut.utctimeInit = self.__initime
5166 dataOut.utctimeInit = self.__initime
5016 self.__initime += dataOut.outputInterval #to erase time offset
5167 self.__initime += dataOut.outputInterval #to erase time offset
5017
5168
5018 freq = dataOut.frequency
5169 freq = dataOut.frequency
5019 c = dataOut.C #m/s
5170 c = dataOut.C #m/s
5020 lamb = c/freq
5171 lamb = c/freq
5021 k = 2*numpy.pi/lamb
5172 k = 2*numpy.pi/lamb
5022 azimuth = 0
5173 azimuth = 0
5023 h = (hmin, hmax)
5174 h = (hmin, hmax)
5024 # pairs = ((0,1),(2,3)) #Estrella
5175 # pairs = ((0,1),(2,3)) #Estrella
5025 # pairs = ((1,0),(2,3)) #T
5176 # pairs = ((1,0),(2,3)) #T
5026
5177
5027 if channelPositions is None:
5178 if channelPositions is None:
5028 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5179 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5029 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5180 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5030 meteorOps = SMOperations()
5181 meteorOps = SMOperations()
5031 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5182 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5032
5183
5033 #Checking correct order of pairs
5184 #Checking correct order of pairs
5034 pairs = []
5185 pairs = []
5035 if distances[1] > distances[0]:
5186 if distances[1] > distances[0]:
5036 pairs.append((1,0))
5187 pairs.append((1,0))
5037 else:
5188 else:
5038 pairs.append((0,1))
5189 pairs.append((0,1))
5039
5190
5040 if distances[3] > distances[2]:
5191 if distances[3] > distances[2]:
5041 pairs.append((3,2))
5192 pairs.append((3,2))
5042 else:
5193 else:
5043 pairs.append((2,3))
5194 pairs.append((2,3))
5044 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
5195 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
5045
5196
5046 meteorsArray = self.__buffer
5197 meteorsArray = self.__buffer
5047 error = meteorsArray[:,-1]
5198 error = meteorsArray[:,-1]
5048 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5199 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5049 ind1 = numpy.where(boolError)[0]
5200 ind1 = numpy.where(boolError)[0]
5050 meteorsArray = meteorsArray[ind1,:]
5201 meteorsArray = meteorsArray[ind1,:]
5051 meteorsArray[:,-1] = 0
5202 meteorsArray[:,-1] = 0
5052 phases = meteorsArray[:,8:12]
5203 phases = meteorsArray[:,8:12]
5053
5204
5054 #Calculate Gammas
5205 #Calculate Gammas
5055 gammas = self.__getGammas(pairs, distances, phases)
5206 gammas = self.__getGammas(pairs, distances, phases)
5056 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
5207 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
5057 #Calculate Phases
5208 #Calculate Phases
5058 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5209 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5059 phasesOff = phasesOff.reshape((1,phasesOff.size))
5210 phasesOff = phasesOff.reshape((1,phasesOff.size))
5060 dataOut.data_output = -phasesOff
5211 dataOut.data_output = -phasesOff
5061 dataOut.flagNoData = False
5212 dataOut.flagNoData = False
5062 self.__buffer = None
5213 self.__buffer = None
5063
5214
5064
5215
5065 return
5216 return
5066
5217
5067 class SMOperations():
5218 class SMOperations():
5068
5219
5069 def __init__(self):
5220 def __init__(self):
5070
5221
5071 return
5222 return
5072
5223
5073 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5224 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5074
5225
5075 arrayParameters = arrayParameters0.copy()
5226 arrayParameters = arrayParameters0.copy()
5076 hmin = h[0]
5227 hmin = h[0]
5077 hmax = h[1]
5228 hmax = h[1]
5078
5229
5079 #Calculate AOA (Error N 3, 4)
5230 #Calculate AOA (Error N 3, 4)
5080 #JONES ET AL. 1998
5231 #JONES ET AL. 1998
5081 AOAthresh = numpy.pi/8
5232 AOAthresh = numpy.pi/8
5082 error = arrayParameters[:,-1]
5233 error = arrayParameters[:,-1]
5083 phases = -arrayParameters[:,8:12] + jph
5234 phases = -arrayParameters[:,8:12] + jph
5084 # phases = numpy.unwrap(phases)
5235 # phases = numpy.unwrap(phases)
5085 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5236 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5086
5237
5087 #Calculate Heights (Error N 13 and 14)
5238 #Calculate Heights (Error N 13 and 14)
5088 error = arrayParameters[:,-1]
5239 error = arrayParameters[:,-1]
5089 Ranges = arrayParameters[:,1]
5240 Ranges = arrayParameters[:,1]
5090 zenith = arrayParameters[:,4]
5241 zenith = arrayParameters[:,4]
5091 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5242 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5092
5243
5093 #----------------------- Get Final data ------------------------------------
5244 #----------------------- Get Final data ------------------------------------
5094 # error = arrayParameters[:,-1]
5245 # error = arrayParameters[:,-1]
5095 # ind1 = numpy.where(error==0)[0]
5246 # ind1 = numpy.where(error==0)[0]
5096 # arrayParameters = arrayParameters[ind1,:]
5247 # arrayParameters = arrayParameters[ind1,:]
5097
5248
5098 return arrayParameters
5249 return arrayParameters
5099
5250
5100 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5251 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5101
5252
5102 arrayAOA = numpy.zeros((phases.shape[0],3))
5253 arrayAOA = numpy.zeros((phases.shape[0],3))
5103 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5254 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5104
5255
5105 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5256 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5106 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5257 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5107 arrayAOA[:,2] = cosDirError
5258 arrayAOA[:,2] = cosDirError
5108
5259
5109 azimuthAngle = arrayAOA[:,0]
5260 azimuthAngle = arrayAOA[:,0]
5110 zenithAngle = arrayAOA[:,1]
5261 zenithAngle = arrayAOA[:,1]
5111
5262
5112 #Setting Error
5263 #Setting Error
5113 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5264 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5114 error[indError] = 0
5265 error[indError] = 0
5115 #Number 3: AOA not fesible
5266 #Number 3: AOA not fesible
5116 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5267 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5117 error[indInvalid] = 3
5268 error[indInvalid] = 3
5118 #Number 4: Large difference in AOAs obtained from different antenna baselines
5269 #Number 4: Large difference in AOAs obtained from different antenna baselines
5119 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5270 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5120 error[indInvalid] = 4
5271 error[indInvalid] = 4
5121 return arrayAOA, error
5272 return arrayAOA, error
5122
5273
5123 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5274 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5124
5275
5125 #Initializing some variables
5276 #Initializing some variables
5126 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5277 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5127 ang_aux = ang_aux.reshape(1,ang_aux.size)
5278 ang_aux = ang_aux.reshape(1,ang_aux.size)
5128
5279
5129 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5280 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5130 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5281 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5131
5282
5132
5283
5133 for i in range(2):
5284 for i in range(2):
5134 ph0 = arrayPhase[:,pairsList[i][0]]
5285 ph0 = arrayPhase[:,pairsList[i][0]]
5135 ph1 = arrayPhase[:,pairsList[i][1]]
5286 ph1 = arrayPhase[:,pairsList[i][1]]
5136 d0 = distances[pairsList[i][0]]
5287 d0 = distances[pairsList[i][0]]
5137 d1 = distances[pairsList[i][1]]
5288 d1 = distances[pairsList[i][1]]
5138
5289
5139 ph0_aux = ph0 + ph1
5290 ph0_aux = ph0 + ph1
5140 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5291 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5141 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
5292 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
5142 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
5293 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
5143 #First Estimation
5294 #First Estimation
5144 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5295 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5145
5296
5146 #Most-Accurate Second Estimation
5297 #Most-Accurate Second Estimation
5147 phi1_aux = ph0 - ph1
5298 phi1_aux = ph0 - ph1
5148 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5299 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5149 #Direction Cosine 1
5300 #Direction Cosine 1
5150 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5301 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5151
5302
5152 #Searching the correct Direction Cosine
5303 #Searching the correct Direction Cosine
5153 cosdir0_aux = cosdir0[:,i]
5304 cosdir0_aux = cosdir0[:,i]
5154 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5305 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5155 #Minimum Distance
5306 #Minimum Distance
5156 cosDiff = (cosdir1 - cosdir0_aux)**2
5307 cosDiff = (cosdir1 - cosdir0_aux)**2
5157 indcos = cosDiff.argmin(axis = 1)
5308 indcos = cosDiff.argmin(axis = 1)
5158 #Saving Value obtained
5309 #Saving Value obtained
5159 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5310 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5160
5311
5161 return cosdir0, cosdir
5312 return cosdir0, cosdir
5162
5313
5163 def __calculateAOA(self, cosdir, azimuth):
5314 def __calculateAOA(self, cosdir, azimuth):
5164 cosdirX = cosdir[:,0]
5315 cosdirX = cosdir[:,0]
5165 cosdirY = cosdir[:,1]
5316 cosdirY = cosdir[:,1]
5166
5317
5167 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5318 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5168 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5319 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5169 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5320 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5170
5321
5171 return angles
5322 return angles
5172
5323
5173 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5324 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5174
5325
5175 Ramb = 375 #Ramb = c/(2*PRF)
5326 Ramb = 375 #Ramb = c/(2*PRF)
5176 Re = 6371 #Earth Radius
5327 Re = 6371 #Earth Radius
5177 heights = numpy.zeros(Ranges.shape)
5328 heights = numpy.zeros(Ranges.shape)
5178
5329
5179 R_aux = numpy.array([0,1,2])*Ramb
5330 R_aux = numpy.array([0,1,2])*Ramb
5180 R_aux = R_aux.reshape(1,R_aux.size)
5331 R_aux = R_aux.reshape(1,R_aux.size)
5181
5332
5182 Ranges = Ranges.reshape(Ranges.size,1)
5333 Ranges = Ranges.reshape(Ranges.size,1)
5183
5334
5184 Ri = Ranges + R_aux
5335 Ri = Ranges + R_aux
5185 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5336 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5186
5337
5187 #Check if there is a height between 70 and 110 km
5338 #Check if there is a height between 70 and 110 km
5188 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5339 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5189 ind_h = numpy.where(h_bool == 1)[0]
5340 ind_h = numpy.where(h_bool == 1)[0]
5190
5341
5191 hCorr = hi[ind_h, :]
5342 hCorr = hi[ind_h, :]
5192 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5343 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5193
5344
5194 hCorr = hi[ind_hCorr][:len(ind_h)]
5345 hCorr = hi[ind_hCorr][:len(ind_h)]
5195 heights[ind_h] = hCorr
5346 heights[ind_h] = hCorr
5196
5347
5197 #Setting Error
5348 #Setting Error
5198 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5349 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5199 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5350 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5200 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5351 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5201 error[indError] = 0
5352 error[indError] = 0
5202 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5353 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5203 error[indInvalid2] = 14
5354 error[indInvalid2] = 14
5204 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5355 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5205 error[indInvalid1] = 13
5356 error[indInvalid1] = 13
5206
5357
5207 return heights, error
5358 return heights, error
5208
5359
5209 def getPhasePairs(self, channelPositions):
5360 def getPhasePairs(self, channelPositions):
5210 chanPos = numpy.array(channelPositions)
5361 chanPos = numpy.array(channelPositions)
5211 listOper = list(itertools.combinations(list(range(5)),2))
5362 listOper = list(itertools.combinations(list(range(5)),2))
5212
5363
5213 distances = numpy.zeros(4)
5364 distances = numpy.zeros(4)
5214 axisX = []
5365 axisX = []
5215 axisY = []
5366 axisY = []
5216 distX = numpy.zeros(3)
5367 distX = numpy.zeros(3)
5217 distY = numpy.zeros(3)
5368 distY = numpy.zeros(3)
5218 ix = 0
5369 ix = 0
5219 iy = 0
5370 iy = 0
5220
5371
5221 pairX = numpy.zeros((2,2))
5372 pairX = numpy.zeros((2,2))
5222 pairY = numpy.zeros((2,2))
5373 pairY = numpy.zeros((2,2))
5223
5374
5224 for i in range(len(listOper)):
5375 for i in range(len(listOper)):
5225 pairi = listOper[i]
5376 pairi = listOper[i]
5226
5377
5227 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
5378 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
5228
5379
5229 if posDif[0] == 0:
5380 if posDif[0] == 0:
5230 axisY.append(pairi)
5381 axisY.append(pairi)
5231 distY[iy] = posDif[1]
5382 distY[iy] = posDif[1]
5232 iy += 1
5383 iy += 1
5233 elif posDif[1] == 0:
5384 elif posDif[1] == 0:
5234 axisX.append(pairi)
5385 axisX.append(pairi)
5235 distX[ix] = posDif[0]
5386 distX[ix] = posDif[0]
5236 ix += 1
5387 ix += 1
5237
5388
5238 for i in range(2):
5389 for i in range(2):
5239 if i==0:
5390 if i==0:
5240 dist0 = distX
5391 dist0 = distX
5241 axis0 = axisX
5392 axis0 = axisX
5242 else:
5393 else:
5243 dist0 = distY
5394 dist0 = distY
5244 axis0 = axisY
5395 axis0 = axisY
5245
5396
5246 side = numpy.argsort(dist0)[:-1]
5397 side = numpy.argsort(dist0)[:-1]
5247 axis0 = numpy.array(axis0)[side,:]
5398 axis0 = numpy.array(axis0)[side,:]
5248 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
5399 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
5249 axis1 = numpy.unique(numpy.reshape(axis0,4))
5400 axis1 = numpy.unique(numpy.reshape(axis0,4))
5250 side = axis1[axis1 != chanC]
5401 side = axis1[axis1 != chanC]
5251 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
5402 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
5252 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
5403 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
5253 if diff1<0:
5404 if diff1<0:
5254 chan2 = side[0]
5405 chan2 = side[0]
5255 d2 = numpy.abs(diff1)
5406 d2 = numpy.abs(diff1)
5256 chan1 = side[1]
5407 chan1 = side[1]
5257 d1 = numpy.abs(diff2)
5408 d1 = numpy.abs(diff2)
5258 else:
5409 else:
5259 chan2 = side[1]
5410 chan2 = side[1]
5260 d2 = numpy.abs(diff2)
5411 d2 = numpy.abs(diff2)
5261 chan1 = side[0]
5412 chan1 = side[0]
5262 d1 = numpy.abs(diff1)
5413 d1 = numpy.abs(diff1)
5263
5414
5264 if i==0:
5415 if i==0:
5265 chanCX = chanC
5416 chanCX = chanC
5266 chan1X = chan1
5417 chan1X = chan1
5267 chan2X = chan2
5418 chan2X = chan2
5268 distances[0:2] = numpy.array([d1,d2])
5419 distances[0:2] = numpy.array([d1,d2])
5269 else:
5420 else:
5270 chanCY = chanC
5421 chanCY = chanC
5271 chan1Y = chan1
5422 chan1Y = chan1
5272 chan2Y = chan2
5423 chan2Y = chan2
5273 distances[2:4] = numpy.array([d1,d2])
5424 distances[2:4] = numpy.array([d1,d2])
5274 # axisXsides = numpy.reshape(axisX[ix,:],4)
5425 # axisXsides = numpy.reshape(axisX[ix,:],4)
5275 #
5426 #
5276 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
5427 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
5277 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
5428 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
5278 #
5429 #
5279 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
5430 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
5280 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
5431 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
5281 # channel25X = int(pairX[0,ind25X])
5432 # channel25X = int(pairX[0,ind25X])
5282 # channel20X = int(pairX[1,ind20X])
5433 # channel20X = int(pairX[1,ind20X])
5283 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
5434 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
5284 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
5435 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
5285 # channel25Y = int(pairY[0,ind25Y])
5436 # channel25Y = int(pairY[0,ind25Y])
5286 # channel20Y = int(pairY[1,ind20Y])
5437 # channel20Y = int(pairY[1,ind20Y])
5287
5438
5288 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
5439 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
5289 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
5440 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
5290
5441
5291 return pairslist, distances
5442 return pairslist, distances
5292 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
5443 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
5293 #
5444 #
5294 # arrayAOA = numpy.zeros((phases.shape[0],3))
5445 # arrayAOA = numpy.zeros((phases.shape[0],3))
5295 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
5446 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
5296 #
5447 #
5297 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5448 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5298 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5449 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5299 # arrayAOA[:,2] = cosDirError
5450 # arrayAOA[:,2] = cosDirError
5300 #
5451 #
5301 # azimuthAngle = arrayAOA[:,0]
5452 # azimuthAngle = arrayAOA[:,0]
5302 # zenithAngle = arrayAOA[:,1]
5453 # zenithAngle = arrayAOA[:,1]
5303 #
5454 #
5304 # #Setting Error
5455 # #Setting Error
5305 # #Number 3: AOA not fesible
5456 # #Number 3: AOA not fesible
5306 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5457 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5307 # error[indInvalid] = 3
5458 # error[indInvalid] = 3
5308 # #Number 4: Large difference in AOAs obtained from different antenna baselines
5459 # #Number 4: Large difference in AOAs obtained from different antenna baselines
5309 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5460 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5310 # error[indInvalid] = 4
5461 # error[indInvalid] = 4
5311 # return arrayAOA, error
5462 # return arrayAOA, error
5312 #
5463 #
5313 # def __getDirectionCosines(self, arrayPhase, pairsList):
5464 # def __getDirectionCosines(self, arrayPhase, pairsList):
5314 #
5465 #
5315 # #Initializing some variables
5466 # #Initializing some variables
5316 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5467 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5317 # ang_aux = ang_aux.reshape(1,ang_aux.size)
5468 # ang_aux = ang_aux.reshape(1,ang_aux.size)
5318 #
5469 #
5319 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
5470 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
5320 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5471 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5321 #
5472 #
5322 #
5473 #
5323 # for i in range(2):
5474 # for i in range(2):
5324 # #First Estimation
5475 # #First Estimation
5325 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
5476 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
5326 # #Dealias
5477 # #Dealias
5327 # indcsi = numpy.where(phi0_aux > numpy.pi)
5478 # indcsi = numpy.where(phi0_aux > numpy.pi)
5328 # phi0_aux[indcsi] -= 2*numpy.pi
5479 # phi0_aux[indcsi] -= 2*numpy.pi
5329 # indcsi = numpy.where(phi0_aux < -numpy.pi)
5480 # indcsi = numpy.where(phi0_aux < -numpy.pi)
5330 # phi0_aux[indcsi] += 2*numpy.pi
5481 # phi0_aux[indcsi] += 2*numpy.pi
5331 # #Direction Cosine 0
5482 # #Direction Cosine 0
5332 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
5483 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
5333 #
5484 #
5334 # #Most-Accurate Second Estimation
5485 # #Most-Accurate Second Estimation
5335 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
5486 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
5336 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5487 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5337 # #Direction Cosine 1
5488 # #Direction Cosine 1
5338 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
5489 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
5339 #
5490 #
5340 # #Searching the correct Direction Cosine
5491 # #Searching the correct Direction Cosine
5341 # cosdir0_aux = cosdir0[:,i]
5492 # cosdir0_aux = cosdir0[:,i]
5342 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5493 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5343 # #Minimum Distance
5494 # #Minimum Distance
5344 # cosDiff = (cosdir1 - cosdir0_aux)**2
5495 # cosDiff = (cosdir1 - cosdir0_aux)**2
5345 # indcos = cosDiff.argmin(axis = 1)
5496 # indcos = cosDiff.argmin(axis = 1)
5346 # #Saving Value obtained
5497 # #Saving Value obtained
5347 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5498 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5348 #
5499 #
5349 # return cosdir0, cosdir
5500 # return cosdir0, cosdir
5350 #
5501 #
5351 # def __calculateAOA(self, cosdir, azimuth):
5502 # def __calculateAOA(self, cosdir, azimuth):
5352 # cosdirX = cosdir[:,0]
5503 # cosdirX = cosdir[:,0]
5353 # cosdirY = cosdir[:,1]
5504 # cosdirY = cosdir[:,1]
5354 #
5505 #
5355 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5506 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5356 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
5507 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
5357 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5508 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5358 #
5509 #
5359 # return angles
5510 # return angles
5360 #
5511 #
5361 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5512 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5362 #
5513 #
5363 # Ramb = 375 #Ramb = c/(2*PRF)
5514 # Ramb = 375 #Ramb = c/(2*PRF)
5364 # Re = 6371 #Earth Radius
5515 # Re = 6371 #Earth Radius
5365 # heights = numpy.zeros(Ranges.shape)
5516 # heights = numpy.zeros(Ranges.shape)
5366 #
5517 #
5367 # R_aux = numpy.array([0,1,2])*Ramb
5518 # R_aux = numpy.array([0,1,2])*Ramb
5368 # R_aux = R_aux.reshape(1,R_aux.size)
5519 # R_aux = R_aux.reshape(1,R_aux.size)
5369 #
5520 #
5370 # Ranges = Ranges.reshape(Ranges.size,1)
5521 # Ranges = Ranges.reshape(Ranges.size,1)
5371 #
5522 #
5372 # Ri = Ranges + R_aux
5523 # Ri = Ranges + R_aux
5373 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5524 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5374 #
5525 #
5375 # #Check if there is a height between 70 and 110 km
5526 # #Check if there is a height between 70 and 110 km
5376 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5527 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5377 # ind_h = numpy.where(h_bool == 1)[0]
5528 # ind_h = numpy.where(h_bool == 1)[0]
5378 #
5529 #
5379 # hCorr = hi[ind_h, :]
5530 # hCorr = hi[ind_h, :]
5380 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5531 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5381 #
5532 #
5382 # hCorr = hi[ind_hCorr]
5533 # hCorr = hi[ind_hCorr]
5383 # heights[ind_h] = hCorr
5534 # heights[ind_h] = hCorr
5384 #
5535 #
5385 # #Setting Error
5536 # #Setting Error
5386 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5537 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5387 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5538 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5388 #
5539 #
5389 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5540 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5390 # error[indInvalid2] = 14
5541 # error[indInvalid2] = 14
5391 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5542 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5392 # error[indInvalid1] = 13
5543 # error[indInvalid1] = 13
5393 #
5544 #
5394 # return heights, error
5545 # return heights, error
5395
5546
5396
5547
5397
5548
5398 class IGRFModel(Operation):
5549 class IGRFModel(Operation):
5399 """Operation to calculate Geomagnetic parameters.
5550 """Operation to calculate Geomagnetic parameters.
5400
5551
5401 Parameters:
5552 Parameters:
5402 -----------
5553 -----------
5403 None
5554 None
5404
5555
5405 Example
5556 Example
5406 --------
5557 --------
5407
5558
5408 op = proc_unit.addOperation(name='IGRFModel', optype='other')
5559 op = proc_unit.addOperation(name='IGRFModel', optype='other')
5409
5560
5410 """
5561 """
5411
5562
5412 def __init__(self, **kwargs):
5563 def __init__(self, **kwargs):
5413
5564
5414 Operation.__init__(self, **kwargs)
5565 Operation.__init__(self, **kwargs)
5415
5566
5416 self.aux=1
5567 self.aux=1
5417
5568
5418 def run(self,dataOut):
5569 def run(self,dataOut):
5419
5570
5420 try:
5571 try:
5421 from schainpy.model.proc import mkfact_short_2020
5572 from schainpy.model.proc import mkfact_short_2020
5422 except:
5573 except:
5423 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
5574 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
5424
5575
5425 if self.aux==1:
5576 if self.aux==1:
5426
5577
5427 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
5578 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
5428 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
5579 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
5429 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
5580 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
5430 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
5581 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
5431 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
5582 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
5432 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
5583 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
5433
5584
5434 self.aux=0
5585 self.aux=0
5435
5586
5436 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
5587 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
5437 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5588 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5438 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
5589 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
5439 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5590 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5440 dataOut.thb=numpy.array(dataOut.thb,order='F')
5591 dataOut.thb=numpy.array(dataOut.thb,order='F')
5441 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5592 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5442 dataOut.bki=numpy.array(dataOut.bki,order='F')
5593 dataOut.bki=numpy.array(dataOut.bki,order='F')
5443
5594
5444 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
5595 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
5445
5596
5446 return dataOut
5597 return dataOut
General Comments 0
You need to be logged in to leave comments. Login now