##// END OF EJS Templates
classes for ESF and 150kM Processing
imanay -
r1765:827e92f42420
parent child
Show More
This diff has been collapsed as it changes many lines, (828 lines changed) Show them Hide them
@@ -1,5672 +1,6214
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 import matplotlib.pyplot as plt
16 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
17 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
17 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
18 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
18 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
19 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
19 from scipy import asarray as ar,exp
20 from scipy import asarray as ar,exp
20 from scipy.optimize import fmin, curve_fit
21 from scipy.optimize import fmin, curve_fit
21 from schainpy.utils import log
22 from schainpy.utils import log
22 import warnings
23 import warnings
23 from numpy import NaN
24 from numpy import NaN
24 from scipy.optimize.optimize import OptimizeWarning
25 from scipy.optimize.optimize import OptimizeWarning
25 warnings.filterwarnings('ignore')
26 warnings.filterwarnings('ignore')
26
27
27
28
28 SPEED_OF_LIGHT = 299792458
29 SPEED_OF_LIGHT = 299792458
29
30
30 '''solving pickling issue'''
31 '''solving pickling issue'''
31
32
32 def _pickle_method(method):
33 def _pickle_method(method):
33 func_name = method.__func__.__name__
34 func_name = method.__func__.__name__
34 obj = method.__self__
35 obj = method.__self__
35 cls = method.__self__.__class__
36 cls = method.__self__.__class__
36 return _unpickle_method, (func_name, obj, cls)
37 return _unpickle_method, (func_name, obj, cls)
37
38
38 def _unpickle_method(func_name, obj, cls):
39 def _unpickle_method(func_name, obj, cls):
39 for cls in cls.mro():
40 for cls in cls.mro():
40 try:
41 try:
41 func = cls.__dict__[func_name]
42 func = cls.__dict__[func_name]
42 except KeyError:
43 except KeyError:
43 pass
44 pass
44 else:
45 else:
45 break
46 break
46 return func.__get__(obj, cls)
47 return func.__get__(obj, cls)
47
48
48 # @MPDecorator
49 # @MPDecorator
49 class ParametersProc(ProcessingUnit):
50 class ParametersProc(ProcessingUnit):
50
51
51 METHODS = {}
52 METHODS = {}
52 nSeconds = None
53 nSeconds = None
53
54
54 def __init__(self):
55 def __init__(self):
55 ProcessingUnit.__init__(self)
56 ProcessingUnit.__init__(self)
56
57
57 self.buffer = None
58 self.buffer = None
58 self.firstdatatime = None
59 self.firstdatatime = None
59 self.profIndex = 0
60 self.profIndex = 0
60 self.dataOut = Parameters()
61 self.dataOut = Parameters()
61 self.setupReq = False #Agregar a todas las unidades de proc
62 self.setupReq = False #Agregar a todas las unidades de proc
62
63
63 def __updateObjFromInput(self):
64 def __updateObjFromInput(self):
64
65
65 self.dataOut.inputUnit = self.dataIn.type
66 self.dataOut.inputUnit = self.dataIn.type
66
67
67 self.dataOut.timeZone = self.dataIn.timeZone
68 self.dataOut.timeZone = self.dataIn.timeZone
68 self.dataOut.dstFlag = self.dataIn.dstFlag
69 self.dataOut.dstFlag = self.dataIn.dstFlag
69 self.dataOut.errorCount = self.dataIn.errorCount
70 self.dataOut.errorCount = self.dataIn.errorCount
70 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71
72
72 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 self.dataOut.channelList = self.dataIn.channelList
75 self.dataOut.channelList = self.dataIn.channelList
75 self.dataOut.heightList = self.dataIn.heightList
76 self.dataOut.heightList = self.dataIn.heightList
76 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 # self.dataOut.nHeights = self.dataIn.nHeights
78 # self.dataOut.nHeights = self.dataIn.nHeights
78 # self.dataOut.nChannels = self.dataIn.nChannels
79 # self.dataOut.nChannels = self.dataIn.nChannels
79 # self.dataOut.nBaud = self.dataIn.nBaud
80 # self.dataOut.nBaud = self.dataIn.nBaud
80 # self.dataOut.nCode = self.dataIn.nCode
81 # self.dataOut.nCode = self.dataIn.nCode
81 # self.dataOut.code = self.dataIn.code
82 # self.dataOut.code = self.dataIn.code
82 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
83 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
83 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
84 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
84 # self.dataOut.utctime = self.firstdatatime
85 # self.dataOut.utctime = self.firstdatatime
85 self.dataOut.utctime = self.dataIn.utctime
86 self.dataOut.utctime = self.dataIn.utctime
86 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
87 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
88 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
88 self.dataOut.nCohInt = self.dataIn.nCohInt
89 self.dataOut.nCohInt = self.dataIn.nCohInt
89 # self.dataOut.nIncohInt = 1
90 # self.dataOut.nIncohInt = 1
90 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
91 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
91 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
92 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
92 self.dataOut.timeInterval1 = self.dataIn.timeInterval
93 self.dataOut.timeInterval1 = self.dataIn.timeInterval
93 self.dataOut.heightList = self.dataIn.heightList
94 self.dataOut.heightList = self.dataIn.heightList
94 self.dataOut.frequency = self.dataIn.frequency
95 self.dataOut.frequency = self.dataIn.frequency
95 #self.dataOut.noise = self.dataIn.noise
96 #self.dataOut.noise = self.dataIn.noise
96
97
97 def run(self):
98 def run(self):
98
99
99 #---------------------- Voltage Data ---------------------------
100 #---------------------- Voltage Data ---------------------------
100
101
101 if self.dataIn.type == "Voltage":
102 if self.dataIn.type == "Voltage":
102
103
103 self.__updateObjFromInput()
104 self.__updateObjFromInput()
104 self.dataOut.data_pre = self.dataIn.data.copy()
105 self.dataOut.data_pre = self.dataIn.data.copy()
105 self.dataOut.flagNoData = False
106 self.dataOut.flagNoData = False
106 self.dataOut.utctimeInit = self.dataIn.utctime
107 self.dataOut.utctimeInit = self.dataIn.utctime
107 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
108 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
108 if hasattr(self.dataIn, 'dataPP_POW'):
109 if hasattr(self.dataIn, 'dataPP_POW'):
109 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
110 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
110
111
111 if hasattr(self.dataIn, 'dataPP_POWER'):
112 if hasattr(self.dataIn, 'dataPP_POWER'):
112 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
113 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
113
114
114 if hasattr(self.dataIn, 'dataPP_DOP'):
115 if hasattr(self.dataIn, 'dataPP_DOP'):
115 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
116 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
116
117
117 if hasattr(self.dataIn, 'dataPP_SNR'):
118 if hasattr(self.dataIn, 'dataPP_SNR'):
118 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
119 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
119
120
120 if hasattr(self.dataIn, 'dataPP_WIDTH'):
121 if hasattr(self.dataIn, 'dataPP_WIDTH'):
121 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
122 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
122 return
123 return
123
124
124 #---------------------- Spectra Data ---------------------------
125 #---------------------- Spectra Data ---------------------------
125
126
126 if self.dataIn.type == "Spectra":
127 if self.dataIn.type == "Spectra":
127
128
128 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
129 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
129 self.dataOut.data_spc = self.dataIn.data_spc
130 self.dataOut.data_spc = self.dataIn.data_spc
130 self.dataOut.data_cspc = self.dataIn.data_cspc
131 self.dataOut.data_cspc = self.dataIn.data_cspc
132 # for JULIA processing
133 self.dataOut.data_diffcspc = self.dataIn.data_diffcspc
134 self.dataOut.nDiffIncohInt = self.dataIn.nDiffIncohInt
135 # for JULIA processing
131 self.dataOut.nProfiles = self.dataIn.nProfiles
136 self.dataOut.nProfiles = self.dataIn.nProfiles
132 self.dataOut.nIncohInt = self.dataIn.nIncohInt
137 self.dataOut.nIncohInt = self.dataIn.nIncohInt
133 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
138 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
134 self.dataOut.ippFactor = self.dataIn.ippFactor
139 self.dataOut.ippFactor = self.dataIn.ippFactor
135 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
140 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
136 self.dataOut.spc_noise = self.dataIn.getNoise()
141 self.dataOut.spc_noise = self.dataIn.getNoise()
137 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
142 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
138 # self.dataOut.normFactor = self.dataIn.normFactor
143 # self.dataOut.normFactor = self.dataIn.normFactor
139 self.dataOut.pairsList = self.dataIn.pairsList
144 self.dataOut.pairsList = self.dataIn.pairsList
140 self.dataOut.groupList = self.dataIn.pairsList
145 self.dataOut.groupList = self.dataIn.pairsList
141 self.dataOut.flagNoData = False
146 self.dataOut.flagNoData = False
142
147
143 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
148 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
144 self.dataOut.ChanDist = self.dataIn.ChanDist
149 self.dataOut.ChanDist = self.dataIn.ChanDist
145 else: self.dataOut.ChanDist = None
150 else: self.dataOut.ChanDist = None
146
151
147 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
152 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
148 # self.dataOut.VelRange = self.dataIn.VelRange
153 # self.dataOut.VelRange = self.dataIn.VelRange
149 #else: self.dataOut.VelRange = None
154 #else: self.dataOut.VelRange = None
150
155
151 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
156 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
152 self.dataOut.RadarConst = self.dataIn.RadarConst
157 self.dataOut.RadarConst = self.dataIn.RadarConst
153
158
154 if hasattr(self.dataIn, 'NPW'): #NPW
159 if hasattr(self.dataIn, 'NPW'): #NPW
155 self.dataOut.NPW = self.dataIn.NPW
160 self.dataOut.NPW = self.dataIn.NPW
156
161
157 if hasattr(self.dataIn, 'COFA'): #COFA
162 if hasattr(self.dataIn, 'COFA'): #COFA
158 self.dataOut.COFA = self.dataIn.COFA
163 self.dataOut.COFA = self.dataIn.COFA
159
164
160
165
161
166
162 #---------------------- Correlation Data ---------------------------
167 #---------------------- Correlation Data ---------------------------
163
168
164 if self.dataIn.type == "Correlation":
169 if self.dataIn.type == "Correlation":
165 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
170 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
166
171
167 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
172 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,:])
173 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
169 self.dataOut.groupList = (acf_pairs, ccf_pairs)
174 self.dataOut.groupList = (acf_pairs, ccf_pairs)
170
175
171 self.dataOut.abscissaList = self.dataIn.lagRange
176 self.dataOut.abscissaList = self.dataIn.lagRange
172 self.dataOut.noise = self.dataIn.noise
177 self.dataOut.noise = self.dataIn.noise
173 self.dataOut.data_snr = self.dataIn.SNR
178 self.dataOut.data_snr = self.dataIn.SNR
174 self.dataOut.flagNoData = False
179 self.dataOut.flagNoData = False
175 self.dataOut.nAvg = self.dataIn.nAvg
180 self.dataOut.nAvg = self.dataIn.nAvg
176
181
177 #---------------------- Parameters Data ---------------------------
182 #---------------------- Parameters Data ---------------------------
178
183
179 if self.dataIn.type == "Parameters":
184 if self.dataIn.type == "Parameters":
180 self.dataOut.copy(self.dataIn)
185 self.dataOut.copy(self.dataIn)
181 self.dataOut.flagNoData = False
186 self.dataOut.flagNoData = False
182
187
183 return True
188 return True
184
189
185 self.__updateObjFromInput()
190 self.__updateObjFromInput()
186 self.dataOut.utctimeInit = self.dataIn.utctime
191 self.dataOut.utctimeInit = self.dataIn.utctime
187 self.dataOut.paramInterval = self.dataIn.timeInterval
192 self.dataOut.paramInterval = self.dataIn.timeInterval
188
193
189 return
194 return
190
195
191
196
192 def target(tups):
197 def target(tups):
193
198
194 obj, args = tups
199 obj, args = tups
195
200
196 return obj.FitGau(args)
201 return obj.FitGau(args)
197
202
198 class RemoveWideGC(Operation):
203 class RemoveWideGC(Operation):
199 ''' This class remove the wide clutter and replace it with a simple interpolation points
204 ''' This class remove the wide clutter and replace it with a simple interpolation points
200 This mainly applies to CLAIRE radar
205 This mainly applies to CLAIRE radar
201
206
202 ClutterWidth : Width to look for the clutter peak
207 ClutterWidth : Width to look for the clutter peak
203
208
204 Input:
209 Input:
205
210
206 self.dataOut.data_pre : SPC and CSPC
211 self.dataOut.data_pre : SPC and CSPC
207 self.dataOut.spc_range : To select wind and rainfall velocities
212 self.dataOut.spc_range : To select wind and rainfall velocities
208
213
209 Affected:
214 Affected:
210
215
211 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
216 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
212
217
213 Written by D. ScipiΓ³n 25.02.2021
218 Written by D. ScipiΓ³n 25.02.2021
214 '''
219 '''
215 def __init__(self):
220 def __init__(self):
216 Operation.__init__(self)
221 Operation.__init__(self)
217 self.i = 0
222 self.i = 0
218 self.ich = 0
223 self.ich = 0
219 self.ir = 0
224 self.ir = 0
220
225
221 def run(self, dataOut, ClutterWidth=2.5):
226 def run(self, dataOut, ClutterWidth=2.5):
222
227
223 self.spc = dataOut.data_pre[0].copy()
228 self.spc = dataOut.data_pre[0].copy()
224 self.spc_out = dataOut.data_pre[0].copy()
229 self.spc_out = dataOut.data_pre[0].copy()
225 self.Num_Chn = self.spc.shape[0]
230 self.Num_Chn = self.spc.shape[0]
226 self.Num_Hei = self.spc.shape[2]
231 self.Num_Hei = self.spc.shape[2]
227 VelRange = dataOut.spc_range[2][:-1]
232 VelRange = dataOut.spc_range[2][:-1]
228 dv = VelRange[1]-VelRange[0]
233 dv = VelRange[1]-VelRange[0]
229
234
230 # Find the velocities that corresponds to zero
235 # Find the velocities that corresponds to zero
231 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
236 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
232
237
233 # Removing novalid data from the spectra
238 # Removing novalid data from the spectra
234 for ich in range(self.Num_Chn) :
239 for ich in range(self.Num_Chn) :
235 for ir in range(self.Num_Hei) :
240 for ir in range(self.Num_Hei) :
236 # Estimate the noise at each range
241 # Estimate the noise at each range
237 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
242 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
238
243
239 # Removing the noise floor at each range
244 # Removing the noise floor at each range
240 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
245 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
241 self.spc[ich,novalid,ir] = HSn
246 self.spc[ich,novalid,ir] = HSn
242
247
243 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
248 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))
249 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
245 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
250 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
246 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
251 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
247 continue
252 continue
248 junk3 = numpy.squeeze(numpy.diff(j1index))
253 junk3 = numpy.squeeze(numpy.diff(j1index))
249 junk4 = numpy.squeeze(numpy.diff(j2index))
254 junk4 = numpy.squeeze(numpy.diff(j2index))
250
255
251 valleyindex = j2index[numpy.where(junk4>1)]
256 valleyindex = j2index[numpy.where(junk4>1)]
252 peakindex = j1index[numpy.where(junk3>1)]
257 peakindex = j1index[numpy.where(junk3>1)]
253
258
254 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
259 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
255 if numpy.size(isvalid) == 0 :
260 if numpy.size(isvalid) == 0 :
256 continue
261 continue
257 if numpy.size(isvalid) >1 :
262 if numpy.size(isvalid) >1 :
258 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
263 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
259 isvalid = isvalid[vindex]
264 isvalid = isvalid[vindex]
260
265
261 # clutter peak
266 # clutter peak
262 gcpeak = peakindex[isvalid]
267 gcpeak = peakindex[isvalid]
263 vl = numpy.where(valleyindex < gcpeak)
268 vl = numpy.where(valleyindex < gcpeak)
264 if numpy.size(vl) == 0:
269 if numpy.size(vl) == 0:
265 continue
270 continue
266 gcvl = valleyindex[vl[0][-1]]
271 gcvl = valleyindex[vl[0][-1]]
267 vr = numpy.where(valleyindex > gcpeak)
272 vr = numpy.where(valleyindex > gcpeak)
268 if numpy.size(vr) == 0:
273 if numpy.size(vr) == 0:
269 continue
274 continue
270 gcvr = valleyindex[vr[0][0]]
275 gcvr = valleyindex[vr[0][0]]
271
276
272 # Removing the clutter
277 # Removing the clutter
273 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
278 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
274 gcindex = gc_values[gcvl+1:gcvr-1]
279 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])
280 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
276
281
277 dataOut.data_pre[0] = self.spc_out
282 dataOut.data_pre[0] = self.spc_out
278
283
279 return dataOut
284 return dataOut
280
285
281 class SpectralFilters(Operation):
286 class SpectralFilters(Operation):
282 ''' This class allows to replace the novalid values with noise for each channel
287 ''' This class allows to replace the novalid values with noise for each channel
283 This applies to CLAIRE RADAR
288 This applies to CLAIRE RADAR
284
289
285 PositiveLimit : RightLimit of novalid data
290 PositiveLimit : RightLimit of novalid data
286 NegativeLimit : LeftLimit of novalid data
291 NegativeLimit : LeftLimit of novalid data
287
292
288 Input:
293 Input:
289
294
290 self.dataOut.data_pre : SPC and CSPC
295 self.dataOut.data_pre : SPC and CSPC
291 self.dataOut.spc_range : To select wind and rainfall velocities
296 self.dataOut.spc_range : To select wind and rainfall velocities
292
297
293 Affected:
298 Affected:
294
299
295 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
300 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
296
301
297 Written by D. ScipiΓ³n 29.01.2021
302 Written by D. ScipiΓ³n 29.01.2021
298 '''
303 '''
299 def __init__(self):
304 def __init__(self):
300 Operation.__init__(self)
305 Operation.__init__(self)
301 self.i = 0
306 self.i = 0
302
307
303 def run(self, dataOut, ):
308 def run(self, dataOut, ):
304
309
305 self.spc = dataOut.data_pre[0].copy()
310 self.spc = dataOut.data_pre[0].copy()
306 self.Num_Chn = self.spc.shape[0]
311 self.Num_Chn = self.spc.shape[0]
307 VelRange = dataOut.spc_range[2]
312 VelRange = dataOut.spc_range[2]
308
313
309 # novalid corresponds to data within the Negative and PositiveLimit
314 # novalid corresponds to data within the Negative and PositiveLimit
310
315
311
316
312 # Removing novalid data from the spectra
317 # Removing novalid data from the spectra
313 for i in range(self.Num_Chn):
318 for i in range(self.Num_Chn):
314 self.spc[i,novalid,:] = dataOut.noise[i]
319 self.spc[i,novalid,:] = dataOut.noise[i]
315 dataOut.data_pre[0] = self.spc
320 dataOut.data_pre[0] = self.spc
316 return dataOut
321 return dataOut
317
322
318
323
319
324
320 class GaussianFit(Operation):
325 class GaussianFit(Operation):
321
326
322 '''
327 '''
323 Function that fit of one and two generalized gaussians (gg) based
328 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
329 on the PSD shape across an "power band" identified from a cumsum of
325 the measured spectrum - noise.
330 the measured spectrum - noise.
326
331
327 Input:
332 Input:
328 self.dataOut.data_pre : SelfSpectra
333 self.dataOut.data_pre : SelfSpectra
329
334
330 Output:
335 Output:
331 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
336 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
332
337
333 '''
338 '''
334 def __init__(self):
339 def __init__(self):
335 Operation.__init__(self)
340 Operation.__init__(self)
336 self.i=0
341 self.i=0
337
342
338
343
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
344 # 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'):
345 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
341 """This routine will find a couple of generalized Gaussians to a power spectrum
346 """This routine will find a couple of generalized Gaussians to a power spectrum
342 methods: generalized, squared
347 methods: generalized, squared
343 input: spc
348 input: spc
344 output:
349 output:
345 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
350 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
346 """
351 """
347 print ('Entering ',method,' double Gaussian fit')
352 print ('Entering ',method,' double Gaussian fit')
348 self.spc = dataOut.data_pre[0].copy()
353 self.spc = dataOut.data_pre[0].copy()
349 self.Num_Hei = self.spc.shape[2]
354 self.Num_Hei = self.spc.shape[2]
350 self.Num_Bin = self.spc.shape[1]
355 self.Num_Bin = self.spc.shape[1]
351 self.Num_Chn = self.spc.shape[0]
356 self.Num_Chn = self.spc.shape[0]
352
357
353 start_time = time.time()
358 start_time = time.time()
354
359
355 pool = Pool(processes=self.Num_Chn)
360 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)]
361 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)]
362 objs = [self for __ in range(self.Num_Chn)]
358 attrs = list(zip(objs, args))
363 attrs = list(zip(objs, args))
359 DGauFitParam = pool.map(target, attrs)
364 DGauFitParam = pool.map(target, attrs)
360 # Parameters:
365 # Parameters:
361 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
366 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
362 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
367 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
363
368
364 # Double Gaussian Curves
369 # Double Gaussian Curves
365 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
370 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
366 gau0[:] = numpy.NaN
371 gau0[:] = numpy.NaN
367 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
372 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
368 gau1[:] = numpy.NaN
373 gau1[:] = numpy.NaN
369 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
374 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
370 for iCh in range(self.Num_Chn):
375 for iCh in range(self.Num_Chn):
371 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
376 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))
377 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))
378 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))
379 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))
380 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))
381 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))
382 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))
383 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
379 if method == 'generalized':
384 if method == 'generalized':
380 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
385 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))
386 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
382 elif method == 'squared':
387 elif method == 'squared':
383 p0 = 2.
388 p0 = 2.
384 p1 = 2.
389 p1 = 2.
385 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
390 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
391 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
387 dataOut.GaussFit0 = gau0
392 dataOut.GaussFit0 = gau0
388 dataOut.GaussFit1 = gau1
393 dataOut.GaussFit1 = gau1
389
394
390 print('Leaving ',method ,' double Gaussian fit')
395 print('Leaving ',method ,' double Gaussian fit')
391 return dataOut
396 return dataOut
392
397
393 def FitGau(self, X):
398 def FitGau(self, X):
394 # print('Entering FitGau')
399 # print('Entering FitGau')
395 # Assigning the variables
400 # Assigning the variables
396 Vrange, ch, wnoise, num_intg, SNRlimit = X
401 Vrange, ch, wnoise, num_intg, SNRlimit = X
397 # Noise Limits
402 # Noise Limits
398 noisebl = wnoise * 0.9
403 noisebl = wnoise * 0.9
399 noisebh = wnoise * 1.1
404 noisebh = wnoise * 1.1
400 # Radar Velocity
405 # Radar Velocity
401 Va = max(Vrange)
406 Va = max(Vrange)
402 deltav = Vrange[1] - Vrange[0]
407 deltav = Vrange[1] - Vrange[0]
403 x = numpy.arange(self.Num_Bin)
408 x = numpy.arange(self.Num_Bin)
404
409
405 # print ('stop 0')
410 # print ('stop 0')
406
411
407 # 5 parameters, 2 Gaussians
412 # 5 parameters, 2 Gaussians
408 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
413 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
409 DGauFitParam[:] = numpy.NaN
414 DGauFitParam[:] = numpy.NaN
410
415
411 # SPCparam = []
416 # SPCparam = []
412 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
417 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
413 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
418 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
414 # SPC_ch1[:] = 0 #numpy.NaN
419 # SPC_ch1[:] = 0 #numpy.NaN
415 # SPC_ch2[:] = 0 #numpy.NaN
420 # SPC_ch2[:] = 0 #numpy.NaN
416 # print ('stop 1')
421 # print ('stop 1')
417 for ht in range(self.Num_Hei):
422 for ht in range(self.Num_Hei):
418 # print (ht)
423 # print (ht)
419 # print ('stop 2')
424 # print ('stop 2')
420 # Spectra at each range
425 # Spectra at each range
421 spc = numpy.asarray(self.spc)[ch,:,ht]
426 spc = numpy.asarray(self.spc)[ch,:,ht]
422 snr = ( spc.mean() - wnoise ) / wnoise
427 snr = ( spc.mean() - wnoise ) / wnoise
423 snrdB = 10.*numpy.log10(snr)
428 snrdB = 10.*numpy.log10(snr)
424
429
425 #print ('stop 3')
430 #print ('stop 3')
426 if snrdB < SNRlimit :
431 if snrdB < SNRlimit :
427 # snr = numpy.NaN
432 # snr = numpy.NaN
428 # SPC_ch1[:,ht] = 0#numpy.NaN
433 # SPC_ch1[:,ht] = 0#numpy.NaN
429 # SPC_ch1[:,ht] = 0#numpy.NaN
434 # SPC_ch1[:,ht] = 0#numpy.NaN
430 # SPCparam = (SPC_ch1,SPC_ch2)
435 # SPCparam = (SPC_ch1,SPC_ch2)
431 # print ('SNR less than SNRth')
436 # print ('SNR less than SNRth')
432 continue
437 continue
433 # wnoise = hildebrand_sekhon(spc,num_intg)
438 # wnoise = hildebrand_sekhon(spc,num_intg)
434 # print ('stop 2.01')
439 # print ('stop 2.01')
435 #############################################
440 #############################################
436 # normalizing spc and noise
441 # normalizing spc and noise
437 # This part differs from gg1
442 # This part differs from gg1
438 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
443 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
439 #spc = spc / spc_norm_max
444 #spc = spc / spc_norm_max
440 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
445 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
441 #############################################
446 #############################################
442
447
443 # print ('stop 2.1')
448 # print ('stop 2.1')
444 fatspectra=1.0
449 fatspectra=1.0
445 # noise per channel.... we might want to use the noise at each range
450 # noise per channel.... we might want to use the noise at each range
446
451
447 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
452 # 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
453 #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
454 #if wnoise>1.1*pnoise: # to be tested later
450 # wnoise=pnoise
455 # wnoise=pnoise
451 # noisebl = wnoise*0.9
456 # noisebl = wnoise*0.9
452 # noisebh = wnoise*1.1
457 # noisebh = wnoise*1.1
453 spc = spc - wnoise # signal
458 spc = spc - wnoise # signal
454
459
455 # print ('stop 2.2')
460 # print ('stop 2.2')
456 minx = numpy.argmin(spc)
461 minx = numpy.argmin(spc)
457 #spcs=spc.copy()
462 #spcs=spc.copy()
458 spcs = numpy.roll(spc,-minx)
463 spcs = numpy.roll(spc,-minx)
459 cum = numpy.cumsum(spcs)
464 cum = numpy.cumsum(spcs)
460 # tot_noise = wnoise * self.Num_Bin #64;
465 # tot_noise = wnoise * self.Num_Bin #64;
461
466
462 # print ('stop 2.3')
467 # print ('stop 2.3')
463 # snr = sum(spcs) / tot_noise
468 # snr = sum(spcs) / tot_noise
464 # snrdB = 10.*numpy.log10(snr)
469 # snrdB = 10.*numpy.log10(snr)
465 #print ('stop 3')
470 #print ('stop 3')
466 # if snrdB < SNRlimit :
471 # if snrdB < SNRlimit :
467 # snr = numpy.NaN
472 # snr = numpy.NaN
468 # SPC_ch1[:,ht] = 0#numpy.NaN
473 # SPC_ch1[:,ht] = 0#numpy.NaN
469 # SPC_ch1[:,ht] = 0#numpy.NaN
474 # SPC_ch1[:,ht] = 0#numpy.NaN
470 # SPCparam = (SPC_ch1,SPC_ch2)
475 # SPCparam = (SPC_ch1,SPC_ch2)
471 # print ('SNR less than SNRth')
476 # print ('SNR less than SNRth')
472 # continue
477 # continue
473
478
474
479
475 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
480 #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
481 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
477 # print ('stop 4')
482 # print ('stop 4')
478 cummax = max(cum)
483 cummax = max(cum)
479 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
484 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
480 cumlo = cummax * epsi
485 cumlo = cummax * epsi
481 cumhi = cummax * (1-epsi)
486 cumhi = cummax * (1-epsi)
482 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
487 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
483
488
484 # print ('stop 5')
489 # print ('stop 5')
485 if len(powerindex) < 1:# case for powerindex 0
490 if len(powerindex) < 1:# case for powerindex 0
486 # print ('powerindex < 1')
491 # print ('powerindex < 1')
487 continue
492 continue
488 powerlo = powerindex[0]
493 powerlo = powerindex[0]
489 powerhi = powerindex[-1]
494 powerhi = powerindex[-1]
490 powerwidth = powerhi-powerlo
495 powerwidth = powerhi-powerlo
491 if powerwidth <= 1:
496 if powerwidth <= 1:
492 # print('powerwidth <= 1')
497 # print('powerwidth <= 1')
493 continue
498 continue
494
499
495 # print ('stop 6')
500 # print ('stop 6')
496 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
501 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
497 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
502 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
498 midpeak = (firstpeak + secondpeak)/2.
503 midpeak = (firstpeak + secondpeak)/2.
499 firstamp = spcs[int(firstpeak)]
504 firstamp = spcs[int(firstpeak)]
500 secondamp = spcs[int(secondpeak)]
505 secondamp = spcs[int(secondpeak)]
501 midamp = spcs[int(midpeak)]
506 midamp = spcs[int(midpeak)]
502
507
503 y_data = spc + wnoise
508 y_data = spc + wnoise
504
509
505 ''' single Gaussian '''
510 ''' single Gaussian '''
506 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
511 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
507 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
512 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
508 power0 = 2.
513 power0 = 2.
509 amplitude0 = midamp
514 amplitude0 = midamp
510 state0 = [shift0,width0,amplitude0,power0,wnoise]
515 state0 = [shift0,width0,amplitude0,power0,wnoise]
511 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
516 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)
517 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
513 # print ('stop 7.1')
518 # print ('stop 7.1')
514 # print (bnds)
519 # print (bnds)
515
520
516 chiSq1=lsq1[1]
521 chiSq1=lsq1[1]
517
522
518 # print ('stop 8')
523 # print ('stop 8')
519 if fatspectra<1.0 and powerwidth<4:
524 if fatspectra<1.0 and powerwidth<4:
520 choice=0
525 choice=0
521 Amplitude0=lsq1[0][2]
526 Amplitude0=lsq1[0][2]
522 shift0=lsq1[0][0]
527 shift0=lsq1[0][0]
523 width0=lsq1[0][1]
528 width0=lsq1[0][1]
524 p0=lsq1[0][3]
529 p0=lsq1[0][3]
525 Amplitude1=0.
530 Amplitude1=0.
526 shift1=0.
531 shift1=0.
527 width1=0.
532 width1=0.
528 p1=0.
533 p1=0.
529 noise=lsq1[0][4]
534 noise=lsq1[0][4]
530 #return (numpy.array([shift0,width0,Amplitude0,p0]),
535 #return (numpy.array([shift0,width0,Amplitude0,p0]),
531 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
536 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
532 # print ('stop 9')
537 # print ('stop 9')
533 ''' two Gaussians '''
538 ''' two Gaussians '''
534 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
539 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
535 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
540 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
536 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
541 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
537 width0 = powerwidth/6.
542 width0 = powerwidth/6.
538 width1 = width0
543 width1 = width0
539 power0 = 2.
544 power0 = 2.
540 power1 = power0
545 power1 = power0
541 amplitude0 = firstamp
546 amplitude0 = firstamp
542 amplitude1 = secondamp
547 amplitude1 = secondamp
543 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
548 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))
549 #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))
550 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))
551 #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
552
548 # print ('stop 10')
553 # print ('stop 10')
549 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
554 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
550
555
551 # print ('stop 11')
556 # print ('stop 11')
552 chiSq2 = lsq2[1]
557 chiSq2 = lsq2[1]
553
558
554 # print ('stop 12')
559 # print ('stop 12')
555
560
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)
561 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
562
558 # print ('stop 13')
563 # print ('stop 13')
559 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
564 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
560 if oneG:
565 if oneG:
561 choice = 0
566 choice = 0
562 else:
567 else:
563 w1 = lsq2[0][1]; w2 = lsq2[0][5]
568 w1 = lsq2[0][1]; w2 = lsq2[0][5]
564 a1 = lsq2[0][2]; a2 = lsq2[0][6]
569 a1 = lsq2[0][2]; a2 = lsq2[0][6]
565 p1 = lsq2[0][3]; p2 = lsq2[0][7]
570 p1 = lsq2[0][3]; p2 = lsq2[0][7]
566 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
571 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
567 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
572 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
573 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
569
574
570 if gp1>gp2:
575 if gp1>gp2:
571 if a1>0.7*a2:
576 if a1>0.7*a2:
572 choice = 1
577 choice = 1
573 else:
578 else:
574 choice = 2
579 choice = 2
575 elif gp2>gp1:
580 elif gp2>gp1:
576 if a2>0.7*a1:
581 if a2>0.7*a1:
577 choice = 2
582 choice = 2
578 else:
583 else:
579 choice = 1
584 choice = 1
580 else:
585 else:
581 choice = numpy.argmax([a1,a2])+1
586 choice = numpy.argmax([a1,a2])+1
582 #else:
587 #else:
583 #choice=argmin([std2a,std2b])+1
588 #choice=argmin([std2a,std2b])+1
584
589
585 else: # with low SNR go to the most energetic peak
590 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]])
591 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
587
592
588 # print ('stop 14')
593 # print ('stop 14')
589 shift0 = lsq2[0][0]
594 shift0 = lsq2[0][0]
590 vel0 = Vrange[0] + shift0 * deltav
595 vel0 = Vrange[0] + shift0 * deltav
591 shift1 = lsq2[0][4]
596 shift1 = lsq2[0][4]
592 # vel1=Vrange[0] + shift1 * deltav
597 # vel1=Vrange[0] + shift1 * deltav
593
598
594 # max_vel = 1.0
599 # max_vel = 1.0
595 # Va = max(Vrange)
600 # Va = max(Vrange)
596 # deltav = Vrange[1]-Vrange[0]
601 # deltav = Vrange[1]-Vrange[0]
597 # print ('stop 15')
602 # print ('stop 15')
598 #first peak will be 0, second peak will be 1
603 #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
604 # 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
605 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
601 shift0 = lsq2[0][0]
606 shift0 = lsq2[0][0]
602 width0 = lsq2[0][1]
607 width0 = lsq2[0][1]
603 Amplitude0 = lsq2[0][2]
608 Amplitude0 = lsq2[0][2]
604 p0 = lsq2[0][3]
609 p0 = lsq2[0][3]
605
610
606 shift1 = lsq2[0][4]
611 shift1 = lsq2[0][4]
607 width1 = lsq2[0][5]
612 width1 = lsq2[0][5]
608 Amplitude1 = lsq2[0][6]
613 Amplitude1 = lsq2[0][6]
609 p1 = lsq2[0][7]
614 p1 = lsq2[0][7]
610 noise = lsq2[0][8]
615 noise = lsq2[0][8]
611 else:
616 else:
612 shift1 = lsq2[0][0]
617 shift1 = lsq2[0][0]
613 width1 = lsq2[0][1]
618 width1 = lsq2[0][1]
614 Amplitude1 = lsq2[0][2]
619 Amplitude1 = lsq2[0][2]
615 p1 = lsq2[0][3]
620 p1 = lsq2[0][3]
616
621
617 shift0 = lsq2[0][4]
622 shift0 = lsq2[0][4]
618 width0 = lsq2[0][5]
623 width0 = lsq2[0][5]
619 Amplitude0 = lsq2[0][6]
624 Amplitude0 = lsq2[0][6]
620 p0 = lsq2[0][7]
625 p0 = lsq2[0][7]
621 noise = lsq2[0][8]
626 noise = lsq2[0][8]
622
627
623 if Amplitude0<0.05: # in case the peak is noise
628 if Amplitude0<0.05: # in case the peak is noise
624 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
629 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
625 if Amplitude1<0.05:
630 if Amplitude1<0.05:
626 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
631 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
627
632
628 # print ('stop 16 ')
633 # print ('stop 16 ')
629 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
634 # 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)
635 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
631 # SPCparam = (SPC_ch1,SPC_ch2)
636 # SPCparam = (SPC_ch1,SPC_ch2)
632
637
633 DGauFitParam[0,ht,0] = noise
638 DGauFitParam[0,ht,0] = noise
634 DGauFitParam[0,ht,1] = noise
639 DGauFitParam[0,ht,1] = noise
635 DGauFitParam[1,ht,0] = Amplitude0
640 DGauFitParam[1,ht,0] = Amplitude0
636 DGauFitParam[1,ht,1] = Amplitude1
641 DGauFitParam[1,ht,1] = Amplitude1
637 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
642 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
638 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
643 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
639 DGauFitParam[3,ht,0] = width0 * deltav
644 DGauFitParam[3,ht,0] = width0 * deltav
640 DGauFitParam[3,ht,1] = width1 * deltav
645 DGauFitParam[3,ht,1] = width1 * deltav
641 DGauFitParam[4,ht,0] = p0
646 DGauFitParam[4,ht,0] = p0
642 DGauFitParam[4,ht,1] = p1
647 DGauFitParam[4,ht,1] = p1
643
648
644 return DGauFitParam
649 return DGauFitParam
645
650
646 def y_model1(self,x,state):
651 def y_model1(self,x,state):
647 shift0, width0, amplitude0, power0, noise = state
652 shift0, width0, amplitude0, power0, noise = state
648 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
653 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)
654 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)
655 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
651 return model0 + model0u + model0d + noise
656 return model0 + model0u + model0d + noise
652
657
653 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
658 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
654 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
659 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
655 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
660 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)
661 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)
662 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
658
663
659 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
664 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)
665 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)
666 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
662 return model0 + model0u + model0d + model1 + model1u + model1d + noise
667 return model0 + model0u + model0d + model1 + model1u + model1d + noise
663
668
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.
669 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
670
666 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
671 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
667
672
668 def misfit2(self,state,y_data,x,num_intg):
673 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.)
674 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
670
675
671 class Oblique_Gauss_Fit(Operation):
676 class Oblique_Gauss_Fit(Operation):
672
677
673 def __init__(self):
678 def __init__(self):
674 Operation.__init__(self)
679 Operation.__init__(self)
675
680
676 def Gauss_fit(self,spc,x,nGauss):
681 def Gauss_fit(self,spc,x,nGauss):
677
682
678
683
679 def gaussian(x, a, b, c, d):
684 def gaussian(x, a, b, c, d):
680 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
685 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
681 return val
686 return val
682
687
683 if nGauss == 'first':
688 if nGauss == 'first':
684 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
689 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
685 spc_2_aux = numpy.flip(spc_1_aux)
690 spc_2_aux = numpy.flip(spc_1_aux)
686 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
691 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
687
692
688 len_dif = len(x)-len(spc_3_aux)
693 len_dif = len(x)-len(spc_3_aux)
689
694
690 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
695 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
691
696
692 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
697 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
693
698
694 y = spc_new
699 y = spc_new
695
700
696 elif nGauss == 'second':
701 elif nGauss == 'second':
697 y = spc
702 y = spc
698
703
699
704
700 # estimate starting values from the data
705 # estimate starting values from the data
701 a = y.max()
706 a = y.max()
702 b = x[numpy.argmax(y)]
707 b = x[numpy.argmax(y)]
703 if nGauss == 'first':
708 if nGauss == 'first':
704 c = 1.#b#b#numpy.std(spc)
709 c = 1.#b#b#numpy.std(spc)
705 elif nGauss == 'second':
710 elif nGauss == 'second':
706 c = b
711 c = b
707 else:
712 else:
708 print("ERROR")
713 print("ERROR")
709
714
710 d = numpy.mean(y[-100:])
715 d = numpy.mean(y[-100:])
711
716
712 # define a least squares function to optimize
717 # define a least squares function to optimize
713 def minfunc(params):
718 def minfunc(params):
714 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
719 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
715
720
716 # fit
721 # fit
717 popt = fmin(minfunc,[a,b,c,d],disp=False)
722 popt = fmin(minfunc,[a,b,c,d],disp=False)
718 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
723 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
719
724
720
725
721 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
726 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
722
727
723
728
724 def Gauss_fit_2(self,spc,x,nGauss):
729 def Gauss_fit_2(self,spc,x,nGauss):
725
730
726
731
727 def gaussian(x, a, b, c, d):
732 def gaussian(x, a, b, c, d):
728 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
733 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
729 return val
734 return val
730
735
731 if nGauss == 'first':
736 if nGauss == 'first':
732 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
737 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
733 spc_2_aux = numpy.flip(spc_1_aux)
738 spc_2_aux = numpy.flip(spc_1_aux)
734 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
739 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
735
740
736 len_dif = len(x)-len(spc_3_aux)
741 len_dif = len(x)-len(spc_3_aux)
737
742
738 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
743 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
739
744
740 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
745 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
741
746
742 y = spc_new
747 y = spc_new
743
748
744 elif nGauss == 'second':
749 elif nGauss == 'second':
745 y = spc
750 y = spc
746
751
747
752
748 # estimate starting values from the data
753 # estimate starting values from the data
749 a = y.max()
754 a = y.max()
750 b = x[numpy.argmax(y)]
755 b = x[numpy.argmax(y)]
751 if nGauss == 'first':
756 if nGauss == 'first':
752 c = 1.#b#b#numpy.std(spc)
757 c = 1.#b#b#numpy.std(spc)
753 elif nGauss == 'second':
758 elif nGauss == 'second':
754 c = b
759 c = b
755 else:
760 else:
756 print("ERROR")
761 print("ERROR")
757
762
758 d = numpy.mean(y[-100:])
763 d = numpy.mean(y[-100:])
759
764
760 # define a least squares function to optimize
765 # define a least squares function to optimize
761 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
766 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
762 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
767 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
763
768
764
769
765 #return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
770 #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]
771 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
767
772
768 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
773 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
769
774
770 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
775 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
776 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
772 return val
777 return val
773
778
774
779
775 y = spc
780 y = spc
776
781
777 # estimate starting values from the data
782 # estimate starting values from the data
778 a1 = A1
783 a1 = A1
779 b1 = B1
784 b1 = B1
780 c1 = C1#numpy.std(spc)
785 c1 = C1#numpy.std(spc)
781
786
782 a2 = A2#y.max()
787 a2 = A2#y.max()
783 b2 = B2#x[numpy.argmax(y)]
788 b2 = B2#x[numpy.argmax(y)]
784 c2 = C2#numpy.std(spc)
789 c2 = C2#numpy.std(spc)
785 d = D
790 d = D
786
791
787 # define a least squares function to optimize
792 # define a least squares function to optimize
788 def minfunc(params):
793 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)
794 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
790
795
791 # fit
796 # fit
792 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
797 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
793
798
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]
799 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
800
796 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
801 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
797
802
798 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
803 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
804 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
800 return val
805 return val
801
806
802
807
803 y = spc
808 y = spc
804
809
805 # estimate starting values from the data
810 # estimate starting values from the data
806 a1 = A1
811 a1 = A1
807 b1 = B1
812 b1 = B1
808 c1 = C1#numpy.std(spc)
813 c1 = C1#numpy.std(spc)
809
814
810 a2 = A2#y.max()
815 a2 = A2#y.max()
811 b2 = B2#x[numpy.argmax(y)]
816 b2 = B2#x[numpy.argmax(y)]
812 c2 = C2#numpy.std(spc)
817 c2 = C2#numpy.std(spc)
813 d = D
818 d = D
814
819
815 # fit
820 # fit
816
821
817 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
822 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
818
823
819 error = numpy.sqrt(numpy.diag(pcov))
824 error = numpy.sqrt(numpy.diag(pcov))
820
825
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]
826 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
827
823 def run(self, dataOut):
828 def run(self, dataOut):
824
829
825 pwcode = 1
830 pwcode = 1
826
831
827 if dataOut.flagDecodeData:
832 if dataOut.flagDecodeData:
828 pwcode = numpy.sum(dataOut.code[0]**2)
833 pwcode = numpy.sum(dataOut.code[0]**2)
829 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
834 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
830 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
835 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
831 factor = normFactor
836 factor = normFactor
832 z = dataOut.data_spc / factor
837 z = dataOut.data_spc / factor
833 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
838 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
834 dataOut.power = numpy.average(z, axis=1)
839 dataOut.power = numpy.average(z, axis=1)
835 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
840 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
836
841
837
842
838 x = dataOut.getVelRange(0)
843 x = dataOut.getVelRange(0)
839
844
840 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
845 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
841 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
846 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
842
847
843 dataOut.VelRange = x
848 dataOut.VelRange = x
844
849
845
850
846 l1=range(22,36)
851 l1=range(22,36)
847 l2=range(58,99)
852 l2=range(58,99)
848
853
849 for hei in itertools.chain(l1, l2):
854 for hei in itertools.chain(l1, l2):
850
855
851 try:
856 try:
852 spc = dataOut.data_spc[0,:,hei]
857 spc = dataOut.data_spc[0,:,hei]
853
858
854 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
859 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
855
860
856 spc_diff = spc - spc_fit
861 spc_diff = spc - spc_fit
857 spc_diff[spc_diff < 0] = 0
862 spc_diff[spc_diff < 0] = 0
858
863
859 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
864 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
860
865
861 D = (D1+D2)
866 D = (D1+D2)
862
867
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)
868 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)
869 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
865
870
866 except:
871 except:
867 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
872 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
868 pass
873 pass
869
874
870 return dataOut
875 return dataOut
871
876
872 class PrecipitationProc(Operation):
877 class PrecipitationProc(Operation):
873
878
874 '''
879 '''
875 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
880 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
876
881
877 Input:
882 Input:
878 self.dataOut.data_pre : SelfSpectra
883 self.dataOut.data_pre : SelfSpectra
879
884
880 Output:
885 Output:
881
886
882 self.dataOut.data_output : Reflectivity factor, rainfall Rate
887 self.dataOut.data_output : Reflectivity factor, rainfall Rate
883
888
884
889
885 Parameters affected:
890 Parameters affected:
886 '''
891 '''
887
892
888 def __init__(self):
893 def __init__(self):
889 Operation.__init__(self)
894 Operation.__init__(self)
890 self.i=0
895 self.i=0
891
896
892 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
897 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,
898 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350, SNRdBlimit=-30,
894 channel=None):
899 channel=None):
895
900
896 # print ('Entering PrecepitationProc ... ')
901 # print ('Entering PrecepitationProc ... ')
897
902
898 if radar == "MIRA35C" :
903 if radar == "MIRA35C" :
899
904
900 self.spc = dataOut.data_pre[0].copy()
905 self.spc = dataOut.data_pre[0].copy()
901 self.Num_Hei = self.spc.shape[2]
906 self.Num_Hei = self.spc.shape[2]
902 self.Num_Bin = self.spc.shape[1]
907 self.Num_Bin = self.spc.shape[1]
903 self.Num_Chn = self.spc.shape[0]
908 self.Num_Chn = self.spc.shape[0]
904 Ze = self.dBZeMODE2(dataOut)
909 Ze = self.dBZeMODE2(dataOut)
905
910
906 else:
911 else:
907
912
908 self.spc = dataOut.data_pre[0].copy()
913 self.spc = dataOut.data_pre[0].copy()
909
914
910 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
915 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
911 self.spc[:,:,0:7]= numpy.NaN
916 self.spc[:,:,0:7]= numpy.NaN
912
917
913 self.Num_Hei = self.spc.shape[2]
918 self.Num_Hei = self.spc.shape[2]
914 self.Num_Bin = self.spc.shape[1]
919 self.Num_Bin = self.spc.shape[1]
915 self.Num_Chn = self.spc.shape[0]
920 self.Num_Chn = self.spc.shape[0]
916
921
917 VelRange = dataOut.spc_range[2]
922 VelRange = dataOut.spc_range[2]
918
923
919 ''' Se obtiene la constante del RADAR '''
924 ''' Se obtiene la constante del RADAR '''
920
925
921 self.Pt = Pt
926 self.Pt = Pt
922 self.Gt = Gt
927 self.Gt = Gt
923 self.Gr = Gr
928 self.Gr = Gr
924 self.Lambda = Lambda
929 self.Lambda = Lambda
925 self.aL = aL
930 self.aL = aL
926 self.tauW = tauW
931 self.tauW = tauW
927 self.ThetaT = ThetaT
932 self.ThetaT = ThetaT
928 self.ThetaR = ThetaR
933 self.ThetaR = ThetaR
929 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
934 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
935 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
936 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
932
937
933 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
938 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)
939 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
935 RadarConstant = 10e-26 * Numerator / Denominator #
940 RadarConstant = 10e-26 * Numerator / Denominator #
936 ExpConstant = 10**(40/10) #Constante Experimental
941 ExpConstant = 10**(40/10) #Constante Experimental
937
942
938 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
943 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
939 for i in range(self.Num_Chn):
944 for i in range(self.Num_Chn):
940 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
945 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
941 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
946 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
942
947
943 if channel is None:
948 if channel is None:
944 SPCmean = numpy.mean(SignalPower, 0)
949 SPCmean = numpy.mean(SignalPower, 0)
945 else:
950 else:
946 SPCmean = SignalPower[channel]
951 SPCmean = SignalPower[channel]
947 Pr = SPCmean[:,:]/dataOut.normFactor
952 Pr = SPCmean[:,:]/dataOut.normFactor
948
953
949 # Declaring auxiliary variables
954 # Declaring auxiliary variables
950 Range = dataOut.heightList*1000. #Range in m
955 Range = dataOut.heightList*1000. #Range in m
951 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
956 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
952 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
957 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
953 zMtrx = rMtrx+Altitude
958 zMtrx = rMtrx+Altitude
954 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
959 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
955 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
960 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
956
961
957 # height dependence to air density Foote and Du Toit (1969)
962 # height dependence to air density Foote and Du Toit (1969)
958 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
963 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
959 VMtrx = VelMtrx / delv_z #Normalized velocity
964 VMtrx = VelMtrx / delv_z #Normalized velocity
960 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
965 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
961 # Diameter is related to the fall speed of falling drops
966 # 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]
967 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
963 # Only valid for D>= 0.16 mm
968 # Only valid for D>= 0.16 mm
964 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
969 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
965
970
966 #Calculate Radar Reflectivity ETAn
971 #Calculate Radar Reflectivity ETAn
967 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
972 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
968 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
973 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
969 # Radar Cross Section
974 # Radar Cross Section
970 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
975 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
971 # Drop Size Distribution
976 # Drop Size Distribution
972 DSD = ETAn / sigmaD
977 DSD = ETAn / sigmaD
973 # Equivalente Reflectivy
978 # Equivalente Reflectivy
974 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
979 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]
980 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
976 # RainFall Rate
981 # RainFall Rate
977 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
982 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
978
983
979 # Censoring the data
984 # Censoring the data
980 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
985 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
981 SNRth = 10**(SNRdBlimit/10) #-30dB
986 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
987 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)
988 W = numpy.nanmean(dataOut.data_dop,0)
984 W[novalid] = numpy.NaN
989 W[novalid] = numpy.NaN
985 Ze_org[novalid] = numpy.NaN
990 Ze_org[novalid] = numpy.NaN
986 RR[novalid] = numpy.NaN
991 RR[novalid] = numpy.NaN
987
992
988 dataOut.data_output = RR[8]
993 dataOut.data_output = RR[8]
989 dataOut.data_param = numpy.ones([3,self.Num_Hei])
994 dataOut.data_param = numpy.ones([3,self.Num_Hei])
990 dataOut.channelList = [0,1,2]
995 dataOut.channelList = [0,1,2]
991
996
992 dataOut.data_param[0]=10*numpy.log10(Ze_org)
997 dataOut.data_param[0]=10*numpy.log10(Ze_org)
993 dataOut.data_param[1]=-W
998 dataOut.data_param[1]=-W
994 dataOut.data_param[2]=RR
999 dataOut.data_param[2]=RR
995
1000
996 # print ('Leaving PrecepitationProc ... ')
1001 # print ('Leaving PrecepitationProc ... ')
997 return dataOut
1002 return dataOut
998
1003
999 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
1004 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
1000
1005
1001 NPW = dataOut.NPW
1006 NPW = dataOut.NPW
1002 COFA = dataOut.COFA
1007 COFA = dataOut.COFA
1003
1008
1004 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
1009 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
1005 RadarConst = dataOut.RadarConst
1010 RadarConst = dataOut.RadarConst
1006 #frequency = 34.85*10**9
1011 #frequency = 34.85*10**9
1007
1012
1008 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1013 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1009 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
1014 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
1010
1015
1011 ETA = numpy.sum(SNR,1)
1016 ETA = numpy.sum(SNR,1)
1012
1017
1013 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
1018 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
1014
1019
1015 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
1020 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
1016
1021
1017 for r in range(self.Num_Hei):
1022 for r in range(self.Num_Hei):
1018
1023
1019 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
1024 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)
1025 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
1021
1026
1022 return Ze
1027 return Ze
1023
1028
1024 # def GetRadarConstant(self):
1029 # def GetRadarConstant(self):
1025 #
1030 #
1026 # """
1031 # """
1027 # Constants:
1032 # Constants:
1028 #
1033 #
1029 # Pt: Transmission Power dB 5kW 5000
1034 # Pt: Transmission Power dB 5kW 5000
1030 # Gt: Transmission Gain dB 24.7 dB 295.1209
1035 # Gt: Transmission Gain dB 24.7 dB 295.1209
1031 # Gr: Reception Gain dB 18.5 dB 70.7945
1036 # Gr: Reception Gain dB 18.5 dB 70.7945
1032 # Lambda: Wavelenght m 0.6741 m 0.6741
1037 # Lambda: Wavelenght m 0.6741 m 0.6741
1033 # aL: Attenuation loses dB 4dB 2.5118
1038 # aL: Attenuation loses dB 4dB 2.5118
1034 # tauW: Width of transmission pulse s 4us 4e-6
1039 # tauW: Width of transmission pulse s 4us 4e-6
1035 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
1040 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
1036 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
1041 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
1037 #
1042 #
1038 # """
1043 # """
1039 #
1044 #
1040 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1045 # 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)
1046 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1042 # RadarConstant = Numerator / Denominator
1047 # RadarConstant = Numerator / Denominator
1043 #
1048 #
1044 # return RadarConstant
1049 # return RadarConstant
1045
1050
1046
1051
1047 class FullSpectralAnalysis(Operation):
1052 class FullSpectralAnalysis(Operation):
1048
1053
1049 """
1054 """
1050 Function that implements Full Spectral Analysis technique.
1055 Function that implements Full Spectral Analysis technique.
1051
1056
1052 Input:
1057 Input:
1053 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
1058 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
1054 self.dataOut.groupList : Pairlist of channels
1059 self.dataOut.groupList : Pairlist of channels
1055 self.dataOut.ChanDist : Physical distance between receivers
1060 self.dataOut.ChanDist : Physical distance between receivers
1056
1061
1057
1062
1058 Output:
1063 Output:
1059
1064
1060 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
1065 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
1061
1066
1062
1067
1063 Parameters affected: Winds, height range, SNR
1068 Parameters affected: Winds, height range, SNR
1064
1069
1065 """
1070 """
1066 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
1071 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):
1072 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
1068
1073
1069 spc = dataOut.data_pre[0].copy()
1074 spc = dataOut.data_pre[0].copy()
1070 cspc = dataOut.data_pre[1]
1075 cspc = dataOut.data_pre[1]
1071 nHeights = spc.shape[2]
1076 nHeights = spc.shape[2]
1072
1077
1073 # first_height = 0.75 #km (ref: data header 20170822)
1078 # first_height = 0.75 #km (ref: data header 20170822)
1074 # resolution_height = 0.075 #km
1079 # resolution_height = 0.075 #km
1075 '''
1080 '''
1076 finding height range. check this when radar parameters are changed!
1081 finding height range. check this when radar parameters are changed!
1077 '''
1082 '''
1078 if maxheight is not None:
1083 if maxheight is not None:
1079 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
1084 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
1080 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
1085 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
1081 else:
1086 else:
1082 range_max = nHeights
1087 range_max = nHeights
1083 if minheight is not None:
1088 if minheight is not None:
1084 # range_min = int((minheight - first_height) / resolution_height) # theoretical
1089 # range_min = int((minheight - first_height) / resolution_height) # theoretical
1085 range_min = int(13.26 * minheight - 5) # empirical, works better
1090 range_min = int(13.26 * minheight - 5) # empirical, works better
1086 if range_min < 0:
1091 if range_min < 0:
1087 range_min = 0
1092 range_min = 0
1088 else:
1093 else:
1089 range_min = 0
1094 range_min = 0
1090
1095
1091 pairsList = dataOut.groupList
1096 pairsList = dataOut.groupList
1092 if dataOut.ChanDist is not None :
1097 if dataOut.ChanDist is not None :
1093 ChanDist = dataOut.ChanDist
1098 ChanDist = dataOut.ChanDist
1094 else:
1099 else:
1095 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
1100 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
1096
1101
1097 # 4 variables: zonal, meridional, vertical, and average SNR
1102 # 4 variables: zonal, meridional, vertical, and average SNR
1098 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
1103 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
1099 velocityX = numpy.zeros([nHeights]) * numpy.NaN
1104 velocityX = numpy.zeros([nHeights]) * numpy.NaN
1100 velocityY = numpy.zeros([nHeights]) * numpy.NaN
1105 velocityY = numpy.zeros([nHeights]) * numpy.NaN
1101 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
1106 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
1102
1107
1103 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
1108 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
1104
1109
1105 '''***********************************************WIND ESTIMATION**************************************'''
1110 '''***********************************************WIND ESTIMATION**************************************'''
1106 for Height in range(nHeights):
1111 for Height in range(nHeights):
1107
1112
1108 if Height >= range_min and Height < range_max:
1113 if Height >= range_min and Height < range_max:
1109 # error_code will be useful in future analysis
1114 # error_code will be useful in future analysis
1110 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
1115 [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)
1116 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
1112
1117
1113 if abs(Vzon) < 100. and abs(Vmer) < 100.:
1118 if abs(Vzon) < 100. and abs(Vmer) < 100.:
1114 velocityX[Height] = Vzon
1119 velocityX[Height] = Vzon
1115 velocityY[Height] = -Vmer
1120 velocityY[Height] = -Vmer
1116 velocityZ[Height] = Vver
1121 velocityZ[Height] = Vver
1117
1122
1118 # Censoring data with SNR threshold
1123 # Censoring data with SNR threshold
1119 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
1124 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
1120
1125
1121 data_param[0] = velocityX
1126 data_param[0] = velocityX
1122 data_param[1] = velocityY
1127 data_param[1] = velocityY
1123 data_param[2] = velocityZ
1128 data_param[2] = velocityZ
1124 data_param[3] = dbSNR
1129 data_param[3] = dbSNR
1125 dataOut.data_param = data_param
1130 dataOut.data_param = data_param
1126 return dataOut
1131 return dataOut
1127
1132
1128 def moving_average(self,x, N=2):
1133 def moving_average(self,x, N=2):
1129 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
1134 """ 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):]
1135 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1131
1136
1132 def gaus(self,xSamples,Amp,Mu,Sigma):
1137 def gaus(self,xSamples,Amp,Mu,Sigma):
1133 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
1138 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
1134
1139
1135 def Moments(self, ySamples, xSamples):
1140 def Moments(self, ySamples, xSamples):
1136 Power = numpy.nanmean(ySamples) # Power, 0th Moment
1141 Power = numpy.nanmean(ySamples) # Power, 0th Moment
1137 yNorm = ySamples / numpy.nansum(ySamples)
1142 yNorm = ySamples / numpy.nansum(ySamples)
1138 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
1143 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
1139 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
1144 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
1140 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
1145 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
1141 return numpy.array([Power,RadVel,StdDev])
1146 return numpy.array([Power,RadVel,StdDev])
1142
1147
1143 def StopWindEstimation(self, error_code):
1148 def StopWindEstimation(self, error_code):
1144 Vzon = numpy.NaN
1149 Vzon = numpy.NaN
1145 Vmer = numpy.NaN
1150 Vmer = numpy.NaN
1146 Vver = numpy.NaN
1151 Vver = numpy.NaN
1147 return Vzon, Vmer, Vver, error_code
1152 return Vzon, Vmer, Vver, error_code
1148
1153
1149 def AntiAliasing(self, interval, maxstep):
1154 def AntiAliasing(self, interval, maxstep):
1150 """
1155 """
1151 function to prevent errors from aliased values when computing phaseslope
1156 function to prevent errors from aliased values when computing phaseslope
1152 """
1157 """
1153 antialiased = numpy.zeros(len(interval))
1158 antialiased = numpy.zeros(len(interval))
1154 copyinterval = interval.copy()
1159 copyinterval = interval.copy()
1155
1160
1156 antialiased[0] = copyinterval[0]
1161 antialiased[0] = copyinterval[0]
1157
1162
1158 for i in range(1,len(antialiased)):
1163 for i in range(1,len(antialiased)):
1159 step = interval[i] - interval[i-1]
1164 step = interval[i] - interval[i-1]
1160 if step > maxstep:
1165 if step > maxstep:
1161 copyinterval -= 2*numpy.pi
1166 copyinterval -= 2*numpy.pi
1162 antialiased[i] = copyinterval[i]
1167 antialiased[i] = copyinterval[i]
1163 elif step < maxstep*(-1):
1168 elif step < maxstep*(-1):
1164 copyinterval += 2*numpy.pi
1169 copyinterval += 2*numpy.pi
1165 antialiased[i] = copyinterval[i]
1170 antialiased[i] = copyinterval[i]
1166 else:
1171 else:
1167 antialiased[i] = copyinterval[i].copy()
1172 antialiased[i] = copyinterval[i].copy()
1168
1173
1169 return antialiased
1174 return antialiased
1170
1175
1171 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1176 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1172 """
1177 """
1173 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1178 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1174 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1179 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1175
1180
1176 Input:
1181 Input:
1177 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1182 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
1183 pairsList : Pairlist of channels
1179 ChanDist : array of xi_ij and eta_ij
1184 ChanDist : array of xi_ij and eta_ij
1180 Height : height at which data is processed
1185 Height : height at which data is processed
1181 noise : noise in [channels] format for specific height
1186 noise : noise in [channels] format for specific height
1182 Abbsisarange : range of the frequencies or velocities
1187 Abbsisarange : range of the frequencies or velocities
1183 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1188 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1184
1189
1185 Output:
1190 Output:
1186 Vzon, Vmer, Vver : wind velocities
1191 Vzon, Vmer, Vver : wind velocities
1187 error_code : int that states where code is terminated
1192 error_code : int that states where code is terminated
1188
1193
1189 0 : no error detected
1194 0 : no error detected
1190 1 : Gaussian of mean spc exceeds widthlimit
1195 1 : Gaussian of mean spc exceeds widthlimit
1191 2 : no Gaussian of mean spc found
1196 2 : no Gaussian of mean spc found
1192 3 : SNR to low or velocity to high -> prec. e.g.
1197 3 : SNR to low or velocity to high -> prec. e.g.
1193 4 : at least one Gaussian of cspc exceeds widthlimit
1198 4 : at least one Gaussian of cspc exceeds widthlimit
1194 5 : zero out of three cspc Gaussian fits converged
1199 5 : zero out of three cspc Gaussian fits converged
1195 6 : phase slope fit could not be found
1200 6 : phase slope fit could not be found
1196 7 : arrays used to fit phase have different length
1201 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)
1202 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1198
1203
1199 """
1204 """
1200
1205
1201 error_code = 0
1206 error_code = 0
1202
1207
1203 nChan = spc.shape[0]
1208 nChan = spc.shape[0]
1204 nProf = spc.shape[1]
1209 nProf = spc.shape[1]
1205 nPair = cspc.shape[0]
1210 nPair = cspc.shape[0]
1206
1211
1207 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1212 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
1213 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1209 phase = numpy.zeros([nPair, nProf]) # phase between channels
1214 phase = numpy.zeros([nPair, nProf]) # phase between channels
1210 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1215 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1211 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1216 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1212 xFrec = AbbsisaRange[0][:-1] # frequency range
1217 xFrec = AbbsisaRange[0][:-1] # frequency range
1213 xVel = AbbsisaRange[2][:-1] # velocity range
1218 xVel = AbbsisaRange[2][:-1] # velocity range
1214 xSamples = xFrec # the frequency range is taken
1219 xSamples = xFrec # the frequency range is taken
1215 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1220 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1216
1221
1217 # only consider velocities with in NegativeLimit and PositiveLimit
1222 # only consider velocities with in NegativeLimit and PositiveLimit
1218 if (NegativeLimit is None):
1223 if (NegativeLimit is None):
1219 NegativeLimit = numpy.min(xVel)
1224 NegativeLimit = numpy.min(xVel)
1220 if (PositiveLimit is None):
1225 if (PositiveLimit is None):
1221 PositiveLimit = numpy.max(xVel)
1226 PositiveLimit = numpy.max(xVel)
1222 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1227 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1223 xSamples_zoom = xSamples[xvalid]
1228 xSamples_zoom = xSamples[xvalid]
1224
1229
1225 '''Getting Eij and Nij'''
1230 '''Getting Eij and Nij'''
1226 Xi01, Xi02, Xi12 = ChanDist[:,0]
1231 Xi01, Xi02, Xi12 = ChanDist[:,0]
1227 Eta01, Eta02, Eta12 = ChanDist[:,1]
1232 Eta01, Eta02, Eta12 = ChanDist[:,1]
1228
1233
1229 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1234 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1230 widthlimit = 10
1235 widthlimit = 10
1231 '''************************* SPC is normalized ********************************'''
1236 '''************************* SPC is normalized ********************************'''
1232 spc_norm = spc.copy()
1237 spc_norm = spc.copy()
1233 # For each channel
1238 # For each channel
1234 for i in range(nChan):
1239 for i in range(nChan):
1235 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1240 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1236 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1241 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1237
1242
1238 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1243 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1239
1244
1240 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1245 """ 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,
1246 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,
1247 only for estimation of width. for normalization of cross spectra, you need initial,
1243 unnormalized self-spectra With noise.
1248 unnormalized self-spectra With noise.
1244
1249
1245 Technically, you don't even need to normalize the self-spectra, as you only need the
1250 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:
1251 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
1252 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)
1253 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1249 """
1254 """
1250 # initial conditions
1255 # initial conditions
1251 popt = [1e-10,0,1e-10]
1256 popt = [1e-10,0,1e-10]
1252 # Spectra average
1257 # Spectra average
1253 SPCMean = numpy.average(SPC_Samples,0)
1258 SPCMean = numpy.average(SPC_Samples,0)
1254 # Moments in frequency
1259 # Moments in frequency
1255 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1260 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1256
1261
1257 # Gauss Fit SPC in frequency domain
1262 # Gauss Fit SPC in frequency domain
1258 if dbSNR > SNRlimit: # only if SNR > SNRth
1263 if dbSNR > SNRlimit: # only if SNR > SNRth
1259 try:
1264 try:
1260 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1265 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1261 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1266 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1262 return self.StopWindEstimation(error_code = 1)
1267 return self.StopWindEstimation(error_code = 1)
1263 FitGauss = self.gaus(xSamples_zoom,*popt)
1268 FitGauss = self.gaus(xSamples_zoom,*popt)
1264 except :#RuntimeError:
1269 except :#RuntimeError:
1265 return self.StopWindEstimation(error_code = 2)
1270 return self.StopWindEstimation(error_code = 2)
1266 else:
1271 else:
1267 return self.StopWindEstimation(error_code = 3)
1272 return self.StopWindEstimation(error_code = 3)
1268
1273
1269 '''***************************** CSPC Normalization *************************
1274 '''***************************** CSPC Normalization *************************
1270 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1275 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
1276 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
1277 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
1278 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)
1279 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1275
1280
1276 The sums are then added and multiplied by range/datapoints, because you need
1281 The sums are then added and multiplied by range/datapoints, because you need
1277 an integral and not a sum for normalization.
1282 an integral and not a sum for normalization.
1278
1283
1279 A norm is found according to Briggs 92.
1284 A norm is found according to Briggs 92.
1280 '''
1285 '''
1281 # for each pair
1286 # for each pair
1282 for i in range(nPair):
1287 for i in range(nPair):
1283 cspc_norm = cspc[i,:].copy()
1288 cspc_norm = cspc[i,:].copy()
1284 chan_index0 = pairsList[i][0]
1289 chan_index0 = pairsList[i][0]
1285 chan_index1 = pairsList[i][1]
1290 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)
1291 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)
1292 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1288
1293
1289 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1294 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1290 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1295 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1291 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1296 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1292
1297
1293 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1298 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))
1299 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1295
1300
1296 '''*******************************FIT GAUSS CSPC************************************'''
1301 '''*******************************FIT GAUSS CSPC************************************'''
1297 try:
1302 try:
1298 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1303 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1299 if popt01[2] > widthlimit: # CONDITION
1304 if popt01[2] > widthlimit: # CONDITION
1300 return self.StopWindEstimation(error_code = 4)
1305 return self.StopWindEstimation(error_code = 4)
1301 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1306 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1302 if popt02[2] > widthlimit: # CONDITION
1307 if popt02[2] > widthlimit: # CONDITION
1303 return self.StopWindEstimation(error_code = 4)
1308 return self.StopWindEstimation(error_code = 4)
1304 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1309 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1305 if popt12[2] > widthlimit: # CONDITION
1310 if popt12[2] > widthlimit: # CONDITION
1306 return self.StopWindEstimation(error_code = 4)
1311 return self.StopWindEstimation(error_code = 4)
1307
1312
1308 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1313 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1309 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1314 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1310 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1315 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1311 except:
1316 except:
1312 return self.StopWindEstimation(error_code = 5)
1317 return self.StopWindEstimation(error_code = 5)
1313
1318
1314
1319
1315 '''************* Getting Fij ***************'''
1320 '''************* Getting Fij ***************'''
1316 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1321 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1317 GaussCenter = popt[1]
1322 GaussCenter = popt[1]
1318 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1323 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1319 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1324 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1320
1325
1321 # Point where e^-1 is located in the gaussian
1326 # Point where e^-1 is located in the gaussian
1322 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1327 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1323 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1328 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1324 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1329 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1325 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1330 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1326
1331
1327 '''********** Taking frequency ranges from mean SPCs **********'''
1332 '''********** Taking frequency ranges from mean SPCs **********'''
1328 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1333 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1329 Range = numpy.empty(2)
1334 Range = numpy.empty(2)
1330 Range[0] = GaussCenter - GauWidth
1335 Range[0] = GaussCenter - GauWidth
1331 Range[1] = GaussCenter + GauWidth
1336 Range[1] = GaussCenter + GauWidth
1332 # Point in x-axis where the bandwidth is located (min:max)
1337 # Point in x-axis where the bandwidth is located (min:max)
1333 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1338 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1334 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1339 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1335 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1340 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1336 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1341 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1337 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1342 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1338 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1343 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1339
1344
1340 '''************************** Getting Phase Slope ***************************'''
1345 '''************************** Getting Phase Slope ***************************'''
1341 for i in range(nPair):
1346 for i in range(nPair):
1342 if len(FrecRange) > 5:
1347 if len(FrecRange) > 5:
1343 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1348 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1344 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1349 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1345 if len(FrecRange) == len(PhaseRange):
1350 if len(FrecRange) == len(PhaseRange):
1346 try:
1351 try:
1347 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1352 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1348 PhaseSlope[i] = slope
1353 PhaseSlope[i] = slope
1349 PhaseInter[i] = intercept
1354 PhaseInter[i] = intercept
1350 except:
1355 except:
1351 return self.StopWindEstimation(error_code = 6)
1356 return self.StopWindEstimation(error_code = 6)
1352 else:
1357 else:
1353 return self.StopWindEstimation(error_code = 7)
1358 return self.StopWindEstimation(error_code = 7)
1354 else:
1359 else:
1355 return self.StopWindEstimation(error_code = 8)
1360 return self.StopWindEstimation(error_code = 8)
1356
1361
1357 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1362 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1358
1363
1359 '''Getting constant C'''
1364 '''Getting constant C'''
1360 cC=(Fij*numpy.pi)**2
1365 cC=(Fij*numpy.pi)**2
1361
1366
1362 '''****** Getting constants F and G ******'''
1367 '''****** Getting constants F and G ******'''
1363 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1368 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1364 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1369 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1365 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1370 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1366 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1371 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1367 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1372 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1368 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1373 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1369 MijResults = numpy.array([MijResult1, MijResult2])
1374 MijResults = numpy.array([MijResult1, MijResult2])
1370 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1375 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1371
1376
1372 '''****** Getting constants A, B and H ******'''
1377 '''****** Getting constants A, B and H ******'''
1373 W01 = numpy.nanmax( FitGauss01 )
1378 W01 = numpy.nanmax( FitGauss01 )
1374 W02 = numpy.nanmax( FitGauss02 )
1379 W02 = numpy.nanmax( FitGauss02 )
1375 W12 = numpy.nanmax( FitGauss12 )
1380 W12 = numpy.nanmax( FitGauss12 )
1376
1381
1377 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1382 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))
1383 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))
1384 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1380 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1385 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1381
1386
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] ])
1387 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)
1388 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1384
1389
1385 VxVy = numpy.array([[cA,cH],[cH,cB]])
1390 VxVy = numpy.array([[cA,cH],[cH,cB]])
1386 VxVyResults = numpy.array([-cF,-cG])
1391 VxVyResults = numpy.array([-cF,-cG])
1387 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1392 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1388 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1393 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1389 error_code = 0
1394 error_code = 0
1390
1395
1391 return Vzon, Vmer, Vver, error_code
1396 return Vzon, Vmer, Vver, error_code
1392
1397
1393 class SpectralMoments(Operation):
1398 class SpectralMoments(Operation):
1394
1399
1395 '''
1400 '''
1396 Function SpectralMoments()
1401 Function SpectralMoments()
1397
1402
1398 Calculates moments (power, mean, standard deviation) and SNR of the signal
1403 Calculates moments (power, mean, standard deviation) and SNR of the signal
1399
1404
1400 Type of dataIn: Spectra
1405 Type of dataIn: Spectra
1401
1406
1402 Configuration Parameters:
1407 Configuration Parameters:
1403
1408
1404 proc_type : (0) First spectral moments routine (Default),
1409 proc_type : (0) First spectral moments routine (Default),
1405 (1) Spectral moment routine similar to JULIA.
1410 (1) Spectral moment routine similar to JULIA.
1406 mode_fit : (0) No gaussian fit
1411 mode_fit : (0) No gaussian fit
1407 (1) One gaussian fit for 150Km processing.
1412 (1) One gaussian fit for 150Km processing.
1408
1413
1409 exp : '150EEJ' To select 128 points window
1414 exp : '150EEJ' To select 128 points window
1410 'ESF_EW' To select full window.
1415 'ESF_EW' To select full window.
1411
1416
1412 Input:
1417 Input:
1413 channelList : simple channel list to select e.g. [2,3,7]
1418 channelList : simple channel list to select e.g. [2,3,7]
1414 self.dataOut.data_pre : Spectral data
1419 self.dataOut.data_pre : Spectral data
1415 self.dataOut.abscissaList : List of frequencies
1420 self.dataOut.abscissaList : List of frequencies
1416 self.dataOut.noise : Noise level per channel
1421 self.dataOut.noise : Noise level per channel
1417
1422
1418 Affected:
1423 Affected:
1419 self.dataOut.moments : Parameters per channel
1424 self.dataOut.moments : Parameters per channel
1420 self.dataOut.data_snr : SNR per channel
1425 self.dataOut.data_snr : SNR per channel
1421
1426
1422 '''
1427 '''
1423
1428
1424 def run(self, dataOut, proc_type=0, mode_fit=0, exp='150EEJ'):
1425
1426 absc = dataOut.abscissaList[:-1]
1427 #noise = dataOut.noise
1428 nChannel = dataOut.data_pre[0].shape[0]
1429 nHei = dataOut.data_pre[0].shape[2]
1430 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
1431
1432 if proc_type == 1:
1433 type1 = mode_fit
1434 fwindow = numpy.zeros(absc.size) + 1
1435 if exp == '150EEJ':
1436 b=64
1437 fwindow[0:absc.size//2 - b] = 0
1438 fwindow[absc.size//2 + b:] = 0
1439 vers = 1 # new
1440 nProfiles = dataOut.nProfiles
1441 nCohInt = dataOut.nCohInt
1442 nIncohInt = dataOut.nIncohInt
1443 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
1444 N = numpy.array(M / nIncohInt,dtype='float32')
1445 data = dataOut.data_pre[0] * N
1446 #noise = dataOut.noise * N
1447 noise = numpy.zeros(nChannel)
1448 for ind in range(nChannel):
1449 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
1450 smooth=3
1451 else:
1452 data = dataOut.data_pre[0]
1453 noise = dataOut.noise
1454 fwindow = None
1455 vers = 0 # old
1456 nIncohInt = None
1457 smooth=None
1458
1459 for ind in range(nChannel):
1460 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, vers=vers)
1461 #print('snr:',data_param[:,0])
1462
1463 if proc_type == 1:
1464 dataOut.moments = data_param[:,1:,:]
1465 #dataOut.data_dop = data_param[:,0]
1466 dataOut.data_dop = data_param[:,2]
1467 dataOut.data_width = data_param[:,1]
1468 # dataOut.data_snr = data_param[:,2]
1469 dataOut.data_snr = data_param[:,0]
1470 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
1471 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
1472
1473 else:
1474 dataOut.moments = data_param[:,1:,:]
1475 dataOut.data_snr = data_param[:,0]
1476 dataOut.data_pow = data_param[:,1]
1477 dataOut.data_dop = data_param[:,2]
1478 dataOut.data_width = data_param[:,3]
1479 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
1480
1481 return dataOut
1482
1483 def __calculateMoments(self, oldspec, oldfreq, n0,
1429 def __calculateMoments(self, oldspec, oldfreq, n0,
1484 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None, vers= None):
1430 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, \
1431 snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None, \
1432 vers= None, Hei= None, debug=False, dbg_hei=None, ymax=0.1, curr_ch=0, sel_ch=[0,1]):
1485
1433
1486 def __GAUSSWINFIT1(A, flagPDER=0):
1434 def __GAUSSWINFIT1(A, flagPDER=0):
1487 nonlocal truex, xvalid
1435 nonlocal truex, xvalid
1488 nparams = 4
1436 nparams = 4
1489 M=truex.size
1437 M=truex.size
1490 mm=numpy.arange(M,dtype='f4')
1438 mm=numpy.arange(M,dtype='f4')
1491 delta = numpy.zeros(M,dtype='f4')
1439 delta = numpy.zeros(M,dtype='f4')
1492 delta[0] = 1.0
1440 delta[0] = 1.0
1493 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
1441 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
1494 jj = -1j
1442 jj = -1j
1495 #if self.winauto is None: self.winauto = (1.0 - mm/M)
1443 #if self.winauto is None: self.winauto = (1.0 - mm/M)
1496 winauto = (1.0 - mm/M)
1444 winauto = (1.0 - mm/M)
1497 winauto = winauto/winauto.max() # Normalized to 1
1445 winauto = winauto/winauto.max() # Normalized to 1
1498 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
1446 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
1499 A[0] = numpy.abs(A[0])
1447 A[0] = numpy.abs(A[0])
1500 A[2] = numpy.abs(A[2])
1448 A[2] = numpy.abs(A[2])
1501 A[3] = numpy.abs(A[3])
1449 A[3] = numpy.abs(A[3])
1502 pi=numpy.array([numpy.pi],dtype='f4')[0]
1450 pi=numpy.array([numpy.pi],dtype='f4')[0]
1503 if A[2] != 0:
1451 if A[2] != 0:
1504 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
1452 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
1505 else:
1453 else:
1506 Z = mm*0.0
1454 Z = mm*0.0
1507 A[0] = 0.0
1455 A[0] = 0.0
1508 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
1456 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
1509 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
1457 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
1510 F = junkF[xvalid]
1458 F = junkF[xvalid]
1511 if flagPDER == 0: #NEED PARTIAL?
1459 if flagPDER == 0: #NEED PARTIAL?
1512 return F
1460 return F
1513 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
1461 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
1514 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
1462 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
1515 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
1463 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
1516 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
1464 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
1517 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
1465 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
1518 PDER = PDER[xvalid,:]
1466 PDER = PDER[xvalid,:]
1519 return F, PDER
1467 return F, PDER
1520
1468
1521 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
1469 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
1522 itmax=20, tol=None):
1470 itmax=20, tol=None):
1523 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
1471 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
1524 if tol == None:
1472 if tol == None:
1525 tol = numpy.array([1.e-3],dtype='f4')[0]
1473 tol = numpy.array([1.e-3],dtype='f4')[0]
1526 typ=a.dtype
1474 typ=a.dtype
1527 double = 1 if typ == numpy.float64 else 0
1475 double = 1 if typ == numpy.float64 else 0
1528 if typ != numpy.float32:
1476 if typ != numpy.float32:
1529 a=a.astype(numpy.float32) #Make params floating
1477 a=a.astype(numpy.float32) #Make params floating
1530 # if we will be estimating partial derivates then compute machine precision
1478 # if we will be estimating partial derivates then compute machine precision
1531 if FlagNoDerivative == 1:
1479 if FlagNoDerivative == 1:
1532 res=numpy.MachAr(float_conv=numpy.float32)
1480 res=numpy.MachAr(float_conv=numpy.float32)
1533 eps=numpy.sqrt(res.eps)
1481 eps=numpy.sqrt(res.eps)
1534
1482
1535 nterms = a.size # Number of parameters
1483 nterms = a.size # Number of parameters
1536 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
1484 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
1537 if nfree <= 0: print('Curvefit - not enough data points.')
1485 if nfree <= 0: print('Curvefit - not enough data points.')
1538 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
1486 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
1539 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
1487 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
1540 # Use diag method in python
1488 # Use diag method in python
1541 converge=1
1489 converge=1
1542
1490
1543 #Define the partial derivative array
1491 #Define the partial derivative array
1544 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
1492 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
1545
1493
1546 for Niter in range(itmax): #Iteration loop
1494 for Niter in range(itmax): #Iteration loop
1547
1495
1548 if FlagNoDerivative == 1:
1496 if FlagNoDerivative == 1:
1549 #Evaluate function and estimate partial derivatives
1497 #Evaluate function and estimate partial derivatives
1550 yfit = __GAUSSWINFIT1(a)
1498 yfit = __GAUSSWINFIT1(a)
1551 for term in range(nterms):
1499 for term in range(nterms):
1552 p=a.copy() # Copy current parameters
1500 p=a.copy() # Copy current parameters
1553 #Increment size for forward difference derivative
1501 #Increment size for forward difference derivative
1554 inc = eps * abs(p[term])
1502 inc = eps * abs(p[term])
1555 if inc == 0: inc = eps
1503 if inc == 0: inc = eps
1556 p[term] = p[term] + inc
1504 p[term] = p[term] + inc
1557 yfit1 = __GAUSSWINFIT1(p)
1505 yfit1 = __GAUSSWINFIT1(p)
1558 PDER[term,:] = (yfit1-yfit)/inc
1506 PDER[term,:] = (yfit1-yfit)/inc
1559 else:
1507 else:
1560 #The user's procedure will return partial derivatives
1508 #The user's procedure will return partial derivatives
1561 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
1509 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
1562
1510
1563 beta = numpy.dot(PDER,(y-yfit)*Weights)
1511 beta = numpy.dot(PDER,(y-yfit)*Weights)
1564 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
1512 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
1565 # save current values of return parameters
1513 # save current values of return parameters
1566 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
1514 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
1567 sigma = sigma1
1515 sigma = sigma1
1568
1516
1569 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
1517 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
1570 chisq = chisq1
1518 chisq = chisq1
1571 yfit1 = yfit
1519 yfit1 = yfit
1572 elev7=numpy.array([1.0e7],dtype='f4')[0]
1520 elev7=numpy.array([1.0e7],dtype='f4')[0]
1573 compara =numpy.sum(abs(y))/elev7/nfree
1521 compara =numpy.sum(abs(y))/elev7/nfree
1574 done_early = chisq1 < compara
1522 done_early = chisq1 < compara
1575
1523
1576 if done_early:
1524 if done_early:
1577 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1525 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1578 if done_early: Niter -= 1
1526 if done_early: Niter -= 1
1579 #save_tp(chisq,Niter,yfit)
1527 #save_tp(chisq,Niter,yfit)
1580 return yfit, a, converge, sigma, chisq # return result
1528 return yfit, a, converge, sigma, chisq # return result
1581 #c = numpy.dot(c, c) # this operator implemented at the next lines
1529 #c = numpy.dot(c, c) # this operator implemented at the next lines
1582 c_tmp = numpy.sqrt(numpy.diag(alpha))
1530 c_tmp = numpy.sqrt(numpy.diag(alpha))
1583 siz=len(c_tmp)
1531 siz=len(c_tmp)
1584 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
1532 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
1585 lambdaCount = 0
1533 lambdaCount = 0
1586 while True:
1534 while True:
1587 lambdaCount += 1
1535 lambdaCount += 1
1588 # Normalize alpha to have unit diagonal.
1536 # Normalize alpha to have unit diagonal.
1589 array = alpha / c
1537 array = alpha / c
1590 # Augment the diagonal.
1538 # Augment the diagonal.
1591 one=numpy.array([1.],dtype='f4')[0]
1539 one=numpy.array([1.],dtype='f4')[0]
1592 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
1540 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
1593 # Invert modified curvature matrix to find new parameters.
1541 # Invert modified curvature matrix to find new parameters.
1594
1542
1595 try:
1543 try:
1596 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
1544 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
1597 except Exception as e:
1545 except Exception as e:
1598 print(e)
1546 print(e)
1599 array[:]=numpy.NaN
1547 array[:]=numpy.NaN
1600
1548
1601 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
1549 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
1602 yfit = __GAUSSWINFIT1(b) # Evaluate function
1550 yfit = __GAUSSWINFIT1(b) # Evaluate function
1603 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
1551 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
1604 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
1552 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
1605 if (numpy.isfinite(chisq) == 0) or \
1553 if (numpy.isfinite(chisq) == 0) or \
1606 (lambdaCount > 30 and chisq >= chisq1):
1554 (lambdaCount > 30 and chisq >= chisq1):
1607 # Reject changes made this iteration, use old values.
1555 # Reject changes made this iteration, use old values.
1608 yfit = yfit1
1556 yfit = yfit1
1609 sigma = sigma1
1557 sigma = sigma1
1610 chisq = chisq1
1558 chisq = chisq1
1611 converge = 0
1559 converge = 0
1612 #print('Failed to converge.')
1560 #print('Failed to converge.')
1613 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1561 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1614 if done_early: Niter -= 1
1562 if done_early: Niter -= 1
1615 #save_tp(chisq,Niter,yfit)
1616 return yfit, a, converge, sigma, chisq, chi2 # return result
1563 return yfit, a, converge, sigma, chisq, chi2 # return result
1617 ten=numpy.array([10.0],dtype='f4')[0]
1564 ten=numpy.array([10.0],dtype='f4')[0]
1618 flambda *= ten # Assume fit got worse
1565 flambda *= ten # Assume fit got worse
1619 if chisq <= chisq1:
1566 if chisq <= chisq1:
1620 break
1567 break
1621 hundred=numpy.array([100.0],dtype='f4')[0]
1568 hundred=numpy.array([100.0],dtype='f4')[0]
1622 flambda /= hundred
1569 flambda /= hundred
1623
1570
1624 a=b # Save new parameter estimate.
1571 a=b # Save new parameter estimate.
1625 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
1572 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
1626 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1573 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1627 if done_early: Niter -= 1
1574 if done_early: Niter -= 1
1628 #save_tp(chisq,Niter,yfit)
1629 return yfit, a, converge, sigma, chisq, chi2 # return result
1575 return yfit, a, converge, sigma, chisq, chi2 # return result
1630 converge = 0
1576 converge = 0
1631 chi2 = chisq
1577 chi2 = chisq
1632 #print('Failed to converge.')
1578 #print('Failed to converge.')
1633 #save_tp(chisq,Niter,yfit)
1634 return yfit, a, converge, sigma, chisq, chi2
1579 return yfit, a, converge, sigma, chisq, chi2
1635
1580
1581
1582 def spectral_cut(Hei, ind, dbg_hei, freq, fd, snr, n1, w, ymax, spec, spec2, n0, max_spec, ss1, m, bb0, curr_ch, sel_ch):
1583 if Hei[ind] > dbg_hei[0] and Hei[ind] < dbg_hei[1] and (curr_ch in sel_ch):
1584 nsa=len(freq)
1585 aux='H=%iKm, dop: %4.1f, snr: %4.1f, noise: %4.1f, sw: %4.1f'%(Hei[ind],fd, 10*numpy.log10(snr),10*numpy.log10(n1), w)
1586 plt.subplots()
1587 plt.ylim(0,ymax)
1588 plt.plot(freq,spec,'b-',freq,spec2,'b--', freq,numpy.repeat(n1, nsa),'k--', freq,numpy.repeat(n0, nsa),'k-', freq,numpy.repeat(max_spec, nsa),'y.-', numpy.repeat(fd, nsa),numpy.linspace(0,ymax,nsa),'r--', numpy.repeat(freq[ss1], nsa),numpy.linspace(0,ymax,nsa),'g-.', numpy.repeat(freq[m + bb0], nsa),numpy.linspace(0,ymax,nsa),'g-.')
1589 plt.title(aux)
1590 plt.show()
1591
1592
1636 if (nicoh is None): nicoh = 1
1593 if (nicoh is None): nicoh = 1
1637 if (smooth is None): smooth = 0
1594 if (smooth is None): smooth = 0
1638 if (type1 is None): type1 = 0
1595 if (type1 is None): type1 = 0
1639 if (vers is None): vers = 0
1596 if (vers is None): vers = 0
1640 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1597 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1641 if (snrth is None): snrth = -20.0
1598 if (snrth is None): snrth = -20.0
1642 #if (snrth is None): snrth = -21.0 # abs test
1643 if (dc is None): dc = 0
1599 if (dc is None): dc = 0
1644 if (aliasing is None): aliasing = 0
1600 if (aliasing is None): aliasing = 0
1645 if (oldfd is None): oldfd = 0
1601 if (oldfd is None): oldfd = 0
1646 if (wwauto is None): wwauto = 0
1602 if (wwauto is None): wwauto = 0
1647
1603
1648 if (n0 < 1.e-20): n0 = 1.e-20
1604 if (n0 < 1.e-20): n0 = 1.e-20
1649
1605
1650 xvalid = numpy.where(fwindow == 1)[0]
1606 xvalid = numpy.where(fwindow == 1)[0]
1651 freq = oldfreq
1607 freq = oldfreq
1652 truex = oldfreq
1608 truex = oldfreq
1653 vec_power = numpy.zeros(oldspec.shape[1])
1609 vec_power = numpy.zeros(oldspec.shape[1])
1654 vec_fd = numpy.zeros(oldspec.shape[1])
1610 vec_fd = numpy.zeros(oldspec.shape[1])
1655 vec_w = numpy.zeros(oldspec.shape[1])
1611 vec_w = numpy.zeros(oldspec.shape[1])
1656 vec_snr = numpy.zeros(oldspec.shape[1])
1612 vec_snr = numpy.zeros(oldspec.shape[1])
1657 vec_n1 = numpy.empty(oldspec.shape[1])
1613 vec_n1 = numpy.empty(oldspec.shape[1])
1658 vec_fp = numpy.empty(oldspec.shape[1])
1614 vec_fp = numpy.empty(oldspec.shape[1])
1659 vec_sigma_fd = numpy.empty(oldspec.shape[1])
1615 vec_sigma_fd = numpy.empty(oldspec.shape[1])
1660
1616
1661 for ind in range(oldspec.shape[1]):
1617 for ind in range(oldspec.shape[1]):
1662
1663 spec = oldspec[:,ind]
1618 spec = oldspec[:,ind]
1664 if (smooth == 0):
1619 if (smooth == 0):
1665 spec2 = spec
1620 spec2 = spec
1666 else:
1621 else:
1667 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1622 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1668
1623
1669 aux = spec2*fwindow
1624 aux = spec2*fwindow
1670 max_spec = aux.max()
1625 max_spec = aux.max()
1671 m = aux.tolist().index(max_spec)
1626 m = aux.tolist().index(max_spec)
1672
1627
1673 if m > 2 and m < oldfreq.size - 3:
1628 if m > 2 and m < oldfreq.size - 3:
1674 newindex = m + numpy.array([-2,-1,0,1,2])
1629 newindex = m + numpy.array([-2,-1,0,1,2])
1675 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
1630 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
1676 #peakspec = SPLINE(,)
1677 tck = interpolate.splrep(freq[newindex], spec2[newindex])
1631 tck = interpolate.splrep(freq[newindex], spec2[newindex])
1678 peakspec = interpolate.splev(newfreq, tck)
1632 peakspec = interpolate.splev(newfreq, tck)
1679 # max_spec = MAX(peakspec,)
1680 max_spec = numpy.max(peakspec)
1633 max_spec = numpy.max(peakspec)
1681 mnew = numpy.argmax(peakspec)
1634 mnew = numpy.argmax(peakspec)
1682 #fp = newfreq(mnew)
1683 fp = newfreq[mnew]
1635 fp = newfreq[mnew]
1684 else:
1636 else:
1685 fp = freq[m]
1637 fp = freq[m]
1686
1638
1687 if vers ==0:
1639 if vers ==0:
1688
1640
1689 # Moments Estimation
1641 # Moments Estimation
1690 bb = spec2[numpy.arange(m,spec2.size)]
1642 bb = spec2[numpy.arange(m,spec2.size)]
1691 bb = (bb<n0).nonzero()
1643 bb = (bb<n0).nonzero()
1692 bb = bb[0]
1644 bb = bb[0]
1693
1645
1694 ss = spec2[numpy.arange(0,m + 1)]
1646 ss = spec2[numpy.arange(0,m + 1)]
1695 ss = (ss<n0).nonzero()
1647 ss = (ss<n0).nonzero()
1696 ss = ss[0]
1648 ss = ss[0]
1697
1649
1698 if (bb.size == 0):
1650 if (bb.size == 0):
1699 bb0 = spec.size - 1 - m
1651 bb0 = spec.size - 1 - m
1700 else:
1652 else:
1701 bb0 = bb[0] - 1
1653 bb0 = bb[0] - 1
1702 if (bb0 < 0):
1654 if (bb0 < 0):
1703 bb0 = 0
1655 bb0 = 0
1704
1656
1705 if (ss.size == 0):
1657 if (ss.size == 0):
1706 ss1 = 1
1658 ss1 = 1
1707 else:
1659 else:
1708 ss1 = max(ss) + 1
1660 ss1 = max(ss) + 1
1709
1661
1710 if (ss1 > m):
1662 if (ss1 > m):
1711 ss1 = m
1663 ss1 = m
1712
1664
1713 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1665 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1714
1666
1715 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1667 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1716 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1668 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1717 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1669 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1718 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1670 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1719 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1671 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1720 snr = (spec2.mean()-n0)/n0
1672 snr = (spec2.mean()-n0)/n0
1721 if (snr < 1.e-20): snr = 1.e-20
1673 if (snr < 1.e-20): snr = 1.e-20
1722
1674
1723 vec_power[ind] = total_power
1675 vec_power[ind] = total_power
1724 vec_fd[ind] = fd
1676 vec_fd[ind] = fd
1725 vec_w[ind] = w
1677 vec_w[ind] = w
1726 vec_snr[ind] = snr
1678 vec_snr[ind] = snr
1727 else:
1679 else:
1728 # Noise by heights
1680 # Noise by heights
1729 n1, stdv = self.__get_noise2(spec, nicoh)
1681 n1, stdv = self.__get_noise2(spec, nicoh)
1730 # Moments Estimation
1682 # Moments Estimation
1731 bb = spec2[numpy.arange(m,spec2.size)]
1683 bb = spec2[numpy.arange(m,spec2.size)]
1732 bb = (bb<n1).nonzero()
1684 bb = (bb<n1).nonzero()
1733 bb = bb[0]
1685 bb = bb[0]
1734
1686
1735 ss = spec2[numpy.arange(0,m + 1)]
1687 ss = spec2[numpy.arange(0,m + 1)]
1736 ss = (ss<n1).nonzero()
1688 ss = (ss<n1).nonzero()
1737 ss = ss[0]
1689 ss = ss[0]
1738
1690
1739 if (bb.size == 0):
1691 if (bb.size == 0):
1740 bb0 = spec.size - 1 - m
1692 bb0 = spec.size - 1 - m
1741 else:
1693 else:
1742 bb0 = bb[0] - 1
1694 bb0 = bb[0] - 1
1743 if (bb0 < 0):
1695 if (bb0 < 0):
1744 bb0 = 0
1696 bb0 = 0
1745
1697
1746 if (ss.size == 0):
1698 if (ss.size == 0):
1747 ss1 = 1
1699 ss1 = 1
1748 else:
1700 else:
1749 ss1 = max(ss) + 1
1701 ss1 = max(ss) + 1
1750
1702
1751 if (ss1 > m):
1703 if (ss1 > m):
1752 ss1 = m
1704 ss1 = m
1753
1705
1754 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1706 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1755
1707
1756 power = ((spec[valid] - n1)*fwindow[valid]).sum()
1708 power = ((spec[valid] - n1)*fwindow[valid]).sum()
1757 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
1709 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
1758 try:
1710 try:
1759 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1711 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1760 except:
1712 except:
1761 w = float("NaN")
1713 w = float("NaN")
1762 snr = power/(n0*fwindow.sum())
1714 snr = power/(n0*fwindow.sum())
1715
1716 if debug:
1717 spectral_cut(Hei, ind, dbg_hei, freq, fd, snr, n1, w, ymax, spec, spec2, n0, max_spec, ss1, m, bb0, curr_ch, sel_ch)
1718
1763 if snr < 1.e-20: snr = 1.e-20
1719 if snr < 1.e-20: snr = 1.e-20
1764
1720
1765 # Here start gaussean adjustment
1721 # Here start gaussean adjustment
1766
1722
1767 if type1 == 1 and snr > numpy.power(10,0.1*snrth):
1723 if type1 == 1 and snr > numpy.power(10,0.1*snrth):
1768
1724
1769 a = numpy.zeros(4,dtype='f4')
1725 a = numpy.zeros(4,dtype='f4')
1770 a[0] = snr * n0
1726 a[0] = snr * n0
1771 a[1] = fd
1727 a[1] = fd
1772 a[2] = w
1728 a[2] = w
1773 a[3] = n0
1729 a[3] = n0
1774
1730
1775 np = spec.size
1731 np = spec.size
1776 aold = a.copy()
1732 aold = a.copy()
1777 spec2 = spec.copy()
1733 spec2 = spec.copy()
1778 oldxvalid = xvalid.copy()
1734 oldxvalid = xvalid.copy()
1779
1735
1780 for i in range(2):
1736 for i in range(2):
1781
1737
1782 ww = 1.0/(numpy.power(spec2,2)/nicoh)
1738 ww = 1.0/(numpy.power(spec2,2)/nicoh)
1783 ww[np//2] = 0.0
1739 ww[np//2] = 0.0
1784
1740
1785 a = aold.copy()
1741 a = aold.copy()
1786 xvalid = oldxvalid.copy()
1742 xvalid = oldxvalid.copy()
1787 #self.show_var(xvalid)
1743 #self.show_var(xvalid)
1788
1744
1789 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
1745 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
1790 a = gaussfn[1]
1746 a = gaussfn[1]
1791 converge = gaussfn[2]
1747 converge = gaussfn[2]
1792
1748
1793 xvalid = numpy.arange(np)
1749 xvalid = numpy.arange(np)
1794 spec2 = __GAUSSWINFIT1(a)
1750 spec2 = __GAUSSWINFIT1(a)
1795
1751
1796 xvalid = oldxvalid.copy()
1752 xvalid = oldxvalid.copy()
1797 power = a[0] * np
1753 power = a[0] * np
1798 fd = a[1]
1754 fd = a[1]
1799 sigma_fd = gaussfn[3][1]
1755 sigma_fd = gaussfn[3][1]
1800 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
1756 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
1801 w = numpy.abs(a[2])
1757 w = numpy.abs(a[2])
1802 n1 = max(a[3], n0)
1758 n1 = max(a[3], n0)
1803
1759
1804 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
1760 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
1805 else:
1761 else:
1806 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
1762 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
1807
1763
1808 vec_fd[ind] = fd
1764 vec_fd[ind] = fd
1809 vec_w[ind] = w
1765 vec_w[ind] = w
1810 vec_snr[ind] = snr
1766 vec_snr[ind] = snr
1811 vec_n1[ind] = n1
1767 vec_n1[ind] = n1
1812 vec_fp[ind] = fp
1768 vec_fp[ind] = fp
1813 vec_sigma_fd[ind] = sigma_fd
1769 vec_sigma_fd[ind] = sigma_fd
1814 vec_power[ind] = power # to compare with type 0 proccessing
1770 vec_power[ind] = power # to compare with type 0 proccessing
1815
1771
1816 if vers==1:
1772 if vers==1:
1817 #return numpy.vstack((vec_fd, vec_w, vec_snr, vec_n1, vec_fp, vec_sigma_fd, vec_power))
1773 return numpy.vstack((vec_snr, vec_w, vec_fd, vec_n1, vec_fp, vec_sigma_fd, vec_power))
1818 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
1819 else:
1774 else:
1820 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1775 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1821
1776
1822 def __get_noise2(self,POWER, fft_avg, TALK=0):
1777 def __get_noise2(self,POWER, fft_avg, TALK=0):
1823 '''
1778 '''
1824 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
1779 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
1825 '''
1780 '''
1826 SPECT_PTS = len(POWER)
1781 SPECT_PTS = len(POWER)
1827 fft_avg = fft_avg*1.0
1782 fft_avg = fft_avg*1.0
1828 NOMIT = 0
1783 NOMIT = 0
1829 NN = SPECT_PTS - NOMIT
1784 NN = SPECT_PTS - NOMIT
1830 N = NN//2
1785 N = NN//2
1831 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
1786 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
1832 ARR = numpy.sort(ARR)
1787 ARR = numpy.sort(ARR)
1833 NUMS_MIN = (SPECT_PTS+7)//8
1788 NUMS_MIN = (SPECT_PTS+7)//8
1834 RTEST = (1.0+1.0/fft_avg)
1789 RTEST = (1.0+1.0/fft_avg)
1835 SUM = 0.0
1790 SUM = 0.0
1836 SUMSQ = 0.0
1791 SUMSQ = 0.0
1837 J = 0
1792 J = 0
1838 for I in range(NN):
1793 for I in range(NN):
1839 J = J + 1
1794 J = J + 1
1840 SUM = SUM + ARR[I]
1795 SUM = SUM + ARR[I]
1841 SUMSQ = SUMSQ + ARR[I]*ARR[I]
1796 SUMSQ = SUMSQ + ARR[I]*ARR[I]
1842 AVE = SUM*1.0/J
1797 AVE = SUM*1.0/J
1843 if J > NUMS_MIN:
1798 if J > NUMS_MIN:
1844 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
1799 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
1845 else:
1800 else:
1846 if J == NUMS_MIN: RNOISE = AVE
1801 if J == NUMS_MIN: RNOISE = AVE
1847 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
1802 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
1848 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1803 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1849 return RNOISE, stdv
1804 return RNOISE, stdv
1850
1805
1851 def __get_noise1(self, power, fft_avg, TALK=0):
1806 def __get_noise1(self, power, fft_avg, TALK=0):
1852 '''
1807 '''
1853 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
1808 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
1854 '''
1809 '''
1855 num_pts = numpy.size(power)
1810 num_pts = numpy.size(power)
1856 #print('num_pts',num_pts)
1857 #print('power',power.shape)
1858 #print(power[256:267,0:2])
1859 fft_avg = fft_avg*1.0
1811 fft_avg = fft_avg*1.0
1860
1861 ind = numpy.argsort(power, axis=None, kind='stable')
1812 ind = numpy.argsort(power, axis=None, kind='stable')
1862 #ind = numpy.argsort(numpy.reshape(power,-1))
1863 #print(ind.shape)
1864 #print(ind[0:11])
1865 #print(numpy.reshape(power,-1)[ind[0:11]])
1866 ARR = numpy.reshape(power,-1)[ind]
1813 ARR = numpy.reshape(power,-1)[ind]
1867 #print('ARR',len(ARR))
1868 #print('ARR',ARR.shape)
1869 NUMS_MIN = num_pts//10
1814 NUMS_MIN = num_pts//10
1870 RTEST = (1.0+1.0/fft_avg)
1815 RTEST = (1.0+1.0/fft_avg)
1871 SUM = 0.0
1816 SUM = 0.0
1872 SUMSQ = 0.0
1817 SUMSQ = 0.0
1873 J = 0
1818 J = 0
1874 cont = 1
1819 cont = 1
1875 while cont == 1 and J < num_pts:
1820 while cont == 1 and J < num_pts:
1876
1821
1877 SUM = SUM + ARR[J]
1822 SUM = SUM + ARR[J]
1878 SUMSQ = SUMSQ + ARR[J]*ARR[J]
1823 SUMSQ = SUMSQ + ARR[J]*ARR[J]
1879 J = J + 1
1824 J = J + 1
1880
1825
1881 if J > NUMS_MIN:
1826 if J > NUMS_MIN:
1882 if (SUMSQ*J <= RTEST*SUM*SUM):
1827 if (SUMSQ*J <= RTEST*SUM*SUM):
1883 LNOISE = SUM*1.0/J
1828 LNOISE = SUM*1.0/J
1884 else:
1829 else:
1885 J = J - 1
1830 J = J - 1
1886 SUM = SUM - ARR[J]
1831 SUM = SUM - ARR[J]
1887 SUMSQ = SUMSQ - ARR[J]*ARR[J]
1832 SUMSQ = SUMSQ - ARR[J]*ARR[J]
1888 cont = 0
1833 cont = 0
1889 else:
1834 else:
1890 if J == NUMS_MIN: LNOISE = SUM*1.0/J
1835 if J == NUMS_MIN: LNOISE = SUM*1.0/J
1891 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
1836 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
1892 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1837 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1893 return LNOISE, stdv
1838 return LNOISE, stdv
1894
1839
1895 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
1840 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
1896
1841
1897 val_frq = numpy.arange(num_prof-2)+1
1842 val_frq = numpy.arange(num_prof-2)+1
1898 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
1843 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
1899 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
1844 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
1900 junkid = numpy.argsort(junkspc)
1845 junkid = numpy.argsort(junkspc)
1901 noisezone = val_frq[junkid[0:num_prof//2]]
1846 noisezone = val_frq[junkid[0:num_prof//2]]
1902 specnoise = spectra[noisezone,:]
1847 specnoise = spectra[noisezone,:]
1903 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
1848 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
1904
1849
1905 if talk:
1850 if talk:
1906 print('noise =', noise)
1851 print('noise =', noise)
1907 return noise
1852 return noise, stdvnoise
1853
1854 def run(self, dataOut, proc_type=0, mode_fit=0, exp='150EEJ', debug=False, dbg_hei=None, ymax=1, sel_ch=[0,1]):
1855
1856 absc = dataOut.abscissaList[:-1]
1857 nChannel = dataOut.data_pre[0].shape[0]
1858 nHei = dataOut.data_pre[0].shape[2]
1859 Hei=dataOut.heightList
1860 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
1861 nProfiles = dataOut.nProfiles
1862 nCohInt = dataOut.nCohInt
1863 nIncohInt = dataOut.nIncohInt
1864 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
1865 N = numpy.array(M / nIncohInt,dtype='float32')
1866
1867 if proc_type == 1:
1868 type1 = mode_fit
1869 fwindow = numpy.zeros(absc.size) + 1
1870 if exp == '150EEJ':
1871 b=64
1872 fwindow[0:absc.size//2 - b] = 0
1873 fwindow[absc.size//2 + b:] = 0
1874 vers = 1 # new
1875
1876 data = dataOut.data_pre[0] * N
1877
1878 noise = numpy.zeros(nChannel)
1879 stdvnoise = numpy.zeros(nChannel)
1880 for ind in range(nChannel):
1881 noise[ind], stdvnoise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
1882 smooth=3
1883 else:
1884 data = dataOut.data_pre[0]
1885 noise = dataOut.noise
1886 fwindow = None
1887 type1 = None
1888 vers = 0 # old
1889 nIncohInt = None
1890 smooth=None
1891
1892 for ind in range(nChannel):
1893 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, vers=vers, Hei=Hei, debug=debug, dbg_hei=dbg_hei, ymax=ymax, curr_ch=ind, sel_ch=sel_ch)
1894 #data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, vers=vers, Hei=Hei, debug=debug)
1895 if exp == 'ESF_EW':
1896 data_param[ind,0,:]*=(noise[ind]/stdvnoise[ind])
1897 data_param[ind,3,:]*=(1.0/M)
1898
1899 if proc_type == 1:
1900 dataOut.moments = data_param[:,1:,:]
1901 dataOut.data_dop = data_param[:,2]
1902 dataOut.data_width = data_param[:,1]
1903 dataOut.data_snr = data_param[:,0]
1904 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
1905 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
1906
1907 if exp == 'ESF_EW':
1908 spc=dataOut.data_pre[0]* N
1909 cspc=dataOut.data_pre[1]* N
1910 nHei=dataOut.data_pre[1].shape[2]
1911 cross_pairs=dataOut.pairsList
1912 nDiffIncohInt = dataOut.nDiffIncohInt
1913 N2=numpy.array(1 / nDiffIncohInt,dtype='float32')
1914 diffcspectra=dataOut.data_diffcspc.copy()* N2 * M * M
1915 num_pairs=len(dataOut.pairsList)
1916
1917 if num_pairs >= 0:
1918 fbinv=numpy.where(absc != 0)[0]
1919 ccf=numpy.sum(cspc[:,fbinv,:], axis=1)
1920 jvpower=numpy.sum(spc[:,fbinv,:], axis=1)
1921 coh=ccf/numpy.sqrt(jvpower[cross_pairs[0][0],:]*jvpower[cross_pairs[0][1],:])
1922 dccf=numpy.sum(diffcspectra[:,fbinv,:], axis=1)
1923 dataOut.ccfpar = numpy.zeros((num_pairs,nHei,3))
1924 dataOut.ccfpar[:,:,0]=numpy.abs(coh)
1925 dataOut.ccfpar[:,:,1]=numpy.arctan(numpy.imag(coh)/numpy.real(coh))
1926 dataOut.ccfpar[:,:,2]=numpy.arctan(numpy.imag(dccf)/numpy.real(dccf))
1927 else:
1928 dataOut.moments = data_param[:,1:,:]
1929 dataOut.data_snr = data_param[:,0]
1930 dataOut.data_pow = data_param[:,1]
1931 dataOut.data_dop = data_param[:,2]
1932 dataOut.data_width = data_param[:,3]
1933 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
1934
1935 return dataOut
1908
1936
1909 class JULIADriftsEstimation(Operation):
1910
1937
1911 def __init__(self):
1938 class JULIA_DayVelocities(Operation):
1912 Operation.__init__(self)
1939 '''
1940 Function SpectralMoments()
1941
1942 From espectral parameters calculates:
1943
1944 1. Signal to noise level (SNL)
1945 2. Vertical velocity
1946 3. Zonal velocity
1947 4. Vertical velocity error
1948 5. Zonal velocity error.
1949
1950 Type of dataIn: SpectralMoments
1913
1951
1952 Configuration Parameters:
1953
1954 zenith : Pairs of angles corresponding to the two beams related to the perpendicular to B from the center of the antenna.
1955 zenithCorrection : Adjustment angle for the zenith. Default 0.
1956 heights : Range to process 150kM echoes. By default [125,185].
1957 nchan : To process 2 or 1 channel. 2 by default.
1958 chan : If nchan = 1, chan indicates which of the 2 channels to process.
1959 clean : 2nd cleaning processing (Graphical). Default False
1960 driftstdv_th : Diferencia mΓ‘xima entre valores promedio consecutivos de vertical.
1961 zonalstdv_th : Diferencia mΓ‘xima entre valores promedio consecutivos de zonal.
1914
1962
1963 Input:
1964
1965 Affected:
1966
1967 '''
1968
1969 def __init__(self):
1970 Operation.__init__(self)
1971 self.old_drift=None
1972 self.old_zonal=None
1973 self.count_drift=0
1974 self.count_zonal=0
1975 self.oldTime_drift=None
1976 self.oldTime_zonal=None
1977
1915 def newtotal(self, data):
1978 def newtotal(self, data):
1916 return numpy.nansum(data)
1979 return numpy.nansum(data)
1917
1980
1918 #def data_filter(self, parm, snrth=-19.5, swth=20, wErrth=500):
1919 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
1981 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
1920 #def data_filter(self, parm, snrth=-21, swth=20, wErrth=500): # abs test
1921
1982
1922 Sz0 = parm.shape # Sz0: h,p
1983 Sz0 = parm.shape # Sz0: h,p
1923 drift = parm[:,0]
1984 drift = parm[:,0]
1924 sw = 2*parm[:,1]
1985 sw = 2*parm[:,1]
1925 snr = 10*numpy.log10(parm[:,2])
1986 snr = 10*numpy.log10(parm[:,2])
1926 Sz = drift.shape # Sz: h
1987 Sz = drift.shape # Sz: h
1927 mask = numpy.ones((Sz[0]))
1988 mask = numpy.ones((Sz[0]))
1928 th=0
1989 th=0
1929 valid=numpy.where(numpy.isfinite(snr))
1990 valid=numpy.where(numpy.isfinite(snr))
1930 cvalid = len(valid[0])
1991 cvalid = len(valid[0])
1931 if cvalid >= 1:
1992 if cvalid >= 1:
1932 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
1993 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
1933 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
1994 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
1934 h = numpy.histogram(snr,bins=nbins)
1995 h = numpy.histogram(snr,bins=nbins)
1935 hist = h[0]
1996 hist = h[0]
1936 values = numpy.round_(h[1])
1997 values = numpy.round_(h[1])
1937 moda = values[numpy.where(hist == numpy.max(hist))]
1998 moda = values[numpy.where(hist == numpy.max(hist))]
1938 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
1999 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
1939
2000
1940 noise = snr[indNoise]
2001 noise = snr[indNoise]
1941 noise_mean = numpy.sum(noise)/len(noise)
2002 noise_mean = numpy.sum(noise)/len(noise)
1942 # CΓ‘lculo de media de snr
2003 # CΓ‘lculo de media de snr
1943 med = numpy.median(snr)
2004 med = numpy.median(snr)
1944 # Establece el umbral de snr
2005 # Establece el umbral de snr
1945 if noise_mean > med + 3:
2006 if noise_mean > med + 3:
1946 th = med
2007 th = med
1947 else:
2008 else:
1948 th = noise_mean + 3
2009 th = noise_mean + 3
1949 # Establece mΓ‘scara
2010 # Establece mΓ‘scara
1950 novalid = numpy.where(snr <= th)[0]
2011 novalid = numpy.where(snr <= th)[0]
1951 mask[novalid] = numpy.nan
2012 mask[novalid] = numpy.nan
1952 # Elimina datos que no sobrepasen el umbral: PARAMETRO
2013 # Elimina datos que no sobrepasen el umbral: PARAMETRO
1953 novalid = numpy.where(snr <= snrth)
2014 novalid = numpy.where(snr <= snrth)
1954 cnovalid = len(novalid[0])
2015 cnovalid = len(novalid[0])
1955 if cnovalid > 0:
2016 if cnovalid > 0:
1956 mask[novalid] = numpy.nan
2017 mask[novalid] = numpy.nan
1957 novalid = numpy.where(numpy.isnan(snr))
2018 novalid = numpy.where(numpy.isnan(snr))
1958 cnovalid = len(novalid[0])
2019 cnovalid = len(novalid[0])
1959 if cnovalid > 0:
2020 if cnovalid > 0:
1960 mask[novalid] = numpy.nan
2021 mask[novalid] = numpy.nan
2022
1961 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
2023 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
1962 for h in range(Sz0[0]):
2024 for i in range(Sz0[1]):
1963 for p in range(Sz0[1]):
2025 new_parm[:,i] = parm[:,i] * mask
1964 if numpy.isnan(mask[h]):
1965 new_parm[h,p]=numpy.nan
1966 else:
1967 new_parm[h,p]=parm[h,p]
1968
2026
1969 return new_parm, th
2027 return new_parm, th
1970
2028
1971 def statistics150km(self, veloc , sigma , threshold , currTime=None, \
1972 amountdata=2, clearAll = None, timeFactor=None):
1973
2029
1974 step = threshold/2
2030 def statistics150km(self, veloc , sigma , threshold , old_veloc=None, count=0, \
2031 currTime=None, oldTime=None, amountdata=2, clearAll = None, timeFactor=1800, debug = False):
2032
2033 if oldTime == None:
2034 oldTime = currTime
2035
2036 step = (threshold/2)*(numpy.abs(currTime - oldTime)//timeFactor + 1)
1975 factor = 2
2037 factor = 2
1976 avg_threshold = 100
2038 avg_threshold = 100
1977
1978 # Calcula la mediana en todas las alturas por tiempo
2039 # Calcula la mediana en todas las alturas por tiempo
1979 val1=numpy.nanmedian(veloc)
2040 val1=numpy.nanmedian(veloc)
1980
2041
1981 # Calcula la media ponderada en todas las alturas por tiempo
2042 # Calcula la media ponderada en todas las alturas por tiempo
1982 val2 = self.newtotal(veloc/numpy.power(sigma,2))/self.newtotal(1/numpy.power(sigma,2))
2043 val2 = self.newtotal(veloc/numpy.power(sigma,2))/self.newtotal(1/numpy.power(sigma,2))
1983
1984
2044
1985 # Verifica la cercanΓ­a de los valores calculados de mediana y media, si son cercanos escoge la media ponderada
2045 # Verifica la cercanΓ­a de los valores calculados de mediana y media, si son cercanos escoge la media ponderada
1986 op1=numpy.abs(val2-val1)
2046 op1=numpy.abs(val2-val1)
1987 op2=threshold/factor
2047 op2=threshold/factor
1988 cond = op1 < op2
2048 cond = op1 < op2
1989
2049
1990 veloc_prof = val2 if cond else val1
2050 veloc_prof = val2 if cond else val1
1991 sigma_prof = numpy.nan
2051 sigma_prof = numpy.nan
1992 sets=numpy.array([-1])
2052 sets=numpy.array([-1])
1993
2053
1994 if op1 > avg_threshold: #Si son muy lejanos no toma en cuenta estos datos
2054 if op1 > avg_threshold: #Si son muy lejanos no toma en cuenta estos datos
1995 veloc_prof = numpy.nan
2055 veloc_prof = numpy.nan
1996
2056
1997 # Se calcula nuevamente media ponderada, en base a estimado inicial de la media
2057 # Se calcula nuevamente media ponderada, en base a estimado inicial de la media
1998 # a fin de eliminar valores que estΓ‘n muy lejanos a dicho valor
2058 # a fin de eliminar valores que estΓ‘n muy lejanos a dicho valor
1999 junk = numpy.where(numpy.abs(veloc-veloc_prof) < threshold/factor)[0]
2000
2059
2001 return junk
2060 if debug:
2061 print('veloc_prof:', veloc_prof)
2062 print('veloc:',veloc)
2063 print('threshold:',threshold)
2064 print('factor:',factor)
2065 print('threshold/factor:',threshold/factor)
2066 print('numpy.abs(veloc-veloc_prof):', numpy.abs(veloc-veloc_prof))
2067 print('numpy.where(numpy.abs(veloc-veloc_prof) < threshold/factor)[0]:', numpy.where(numpy.abs(veloc-veloc_prof) < threshold/factor)[0])
2068
2069 junk = numpy.where(numpy.abs(veloc-veloc_prof) < threshold/factor)[0]
2070 if junk.size > 2:
2071 veloc_prof = self.newtotal(veloc[junk]/numpy.power(sigma[junk],2))/self.newtotal(1/numpy.power(sigma[junk],2))
2072 sigma_prof1 = numpy.sqrt(1/self.newtotal(1/numpy.power(sigma[junk],2)))
2073 sigma_prof2 = numpy.sqrt(self.newtotal(numpy.power(veloc[junk]-veloc_prof,2)/numpy.power(sigma[junk],2)))*sigma_prof1
2074 sigma_prof = numpy.sqrt(numpy.power(sigma_prof1,2)+numpy.power(sigma_prof2,2))
2075 sets = junk
2076
2077 # Compara con valor anterior para evitar presencia de "outliers"
2078 if debug:
2079 print('old_veloc:',old_veloc)
2080 print('step:', step)
2081
2082 if old_veloc == None:
2083 valid=numpy.isfinite(veloc_prof)
2084 else:
2085 valid=numpy.abs(veloc_prof-old_veloc) < step
2086
2087 if debug:
2088 print('valid:', valid)
2089
2090 if not valid:
2091 aver_veloc=numpy.nan
2092 aver_sigma=numpy.nan
2093 sets=numpy.array([-1])
2094 else:
2095 aver_veloc=veloc_prof
2096 aver_sigma=sigma_prof
2097 clearAll=0
2098 if old_veloc != None and count < 5:
2099 if numpy.abs(veloc_prof-old_veloc) > step:
2100 clearAll=1
2101 count=0
2102 old_veloc=None
2103 if numpy.isfinite(aver_veloc):
2104
2105 count+=1
2106 if old_veloc != None:
2107 old_veloc = (old_veloc + aver_veloc) * 0.5
2108 else:
2109 old_veloc=aver_veloc
2110 oldTime=currTime
2111 if debug:
2112 print('count:',count)
2113 print('sets:',sets)
2114 return sets, old_veloc, count, oldTime, aver_veloc, aver_sigma, clearAll
2002
2115
2003 def run(self, dataOut, zenith, zenithCorrection,heights=None, otype=0, nchan=2, chan=0):
2004
2116
2117 def run(self, dataOut, zenith, zenithCorrection=0.0, heights=[125, 185], nchan=2, chan=0, clean=False, driftstdv_th=100, zonalstdv_th=200):
2005
2118
2006 dataOut.lat=-11.95
2119 dataOut.lat=-11.95
2007 dataOut.lon=-76.87
2120 dataOut.lon=-76.87
2008
2121
2009 nCh=dataOut.spcpar.shape[0]
2122 nCh=dataOut.spcpar.shape[0]
2010 nHei=dataOut.spcpar.shape[1]
2123 nHei=dataOut.spcpar.shape[1]
2011 nParam=dataOut.spcpar.shape[2]
2124 nParam=dataOut.spcpar.shape[2]
2012 # SelecciΓ³n de alturas
2013
2125
2014 if not heights:
2126 # SelecciΓ³n de alturas
2015 parm = numpy.zeros((nCh,nHei,nParam))
2127 hei=dataOut.heightList
2016 parm[:] = dataOut.spcpar[:]
2128 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
2017 else:
2129 nhvalid=len(hvalid)
2018 hei=dataOut.heightList
2130 dataOut.heightList = hei[hvalid]
2019 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
2131 parm=numpy.empty((nCh,nhvalid,nParam)); parm[:]=numpy.nan
2020 nhvalid=len(hvalid)
2132 parm[:] = dataOut.spcpar[:,hvalid,:]
2021 dataOut.heightList = hei[hvalid]
2022 parm = numpy.zeros((nCh,nhvalid,nParam))
2023 parm[:] = dataOut.spcpar[:,hvalid,:]
2024 print('parm:',parm.shape)
2025
2026
2027 # Primer filtrado: Umbral de SNR
2133 # Primer filtrado: Umbral de SNR
2028 for i in range(nCh):
2134 for i in range(nCh):
2029 parm[i,:,:] = self.data_filter(parm[i,:,:])[0]
2135 parm[i,:,:] = self.data_filter(parm[i,:,:])[0]
2030
2136
2031 zenith = numpy.array(zenith)
2137 zenith = numpy.array(zenith)
2032 zenith -= zenithCorrection
2138 zenith -= zenithCorrection
2033 zenith *= numpy.pi/180
2139 zenith *= numpy.pi/180
2034 alpha = zenith[0]
2140 alpha = zenith[0]
2035 beta = zenith[1]
2141 beta = zenith[1]
2036 dopplerCH0 = parm[0,:,0]
2142 dopplerCH0 = parm[0,:,0]
2037 dopplerCH1 = parm[1,:,0]
2143 dopplerCH1 = parm[1,:,0]
2038 swCH0 = parm[0,:,1]
2144 swCH0 = parm[0,:,1]
2039 swCH1 = parm[1,:,1]
2145 swCH1 = parm[1,:,1]
2040 snrCH0 = 10*numpy.log10(parm[0,:,2])
2146 snrCH0 = 10*numpy.log10(parm[0,:,2])
2041 snrCH1 = 10*numpy.log10(parm[1,:,2])
2147 snrCH1 = 10*numpy.log10(parm[1,:,2])
2042 noiseCH0 = parm[0,:,3]
2148 noiseCH0 = parm[0,:,3]
2043 noiseCH1 = parm[1,:,3]
2149 noiseCH1 = parm[1,:,3]
2044 wErrCH0 = parm[0,:,5]
2150 wErrCH0 = parm[0,:,5]
2045 wErrCH1 = parm[1,:,5]
2151 wErrCH1 = parm[1,:,5]
2046
2152
2047 # Vertical and zonal calculation: nchan=2 by default
2153 # Vertical and zonal calculation: nchan=2 by default
2048 # Only vertical calculation, for offline processing with only one channel with good signal
2154 # Only vertical calculation, for offline processing with only one channel with good signal
2049 if nchan == 1:
2155 if nchan == 1:
2050 if chan == 1:
2156 if chan == 1:
2051 drift = - dopplerCH1
2157 drift = - dopplerCH1
2052 snr = snrCH1
2158 snr = snrCH1
2053 noise = noiseCH1
2159 noise = noiseCH1
2054 sw = swCH1
2160 sw = swCH1
2055 w_w_err = wErrCH1
2161 w_w_err = wErrCH1
2056 elif chan == 0:
2162 elif chan == 0:
2057 drift = - dopplerCH0
2163 drift = - dopplerCH0
2058 snr = snrCH0
2164 snr = snrCH0
2059 noise = noiseCH0
2165 noise = noiseCH0
2060 sw = swCH0
2166 sw = swCH0
2061 w_w_err = wErrCH0
2167 w_w_err = wErrCH0
2062
2168
2063 elif nchan == 2:
2169 elif nchan == 2:
2064 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
2170 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
2065 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
2171 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
2066 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
2172 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
2067 snr = (snrCH0 + snrCH1)/2
2173 snr = (snrCH0 + snrCH1)/2
2068 noise = (noiseCH0 + noiseCH1)/2
2174 noise = (noiseCH0 + noiseCH1)/2
2069 sw = (swCH0 + swCH1)/2
2175 sw = (swCH0 + swCH1)/2
2070 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))
2176 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))
2071 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))
2177 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))
2072
2178
2073 # 150Km statistics to clean data
2179 # 150Km statistics to clean data
2074
2075 clean_drift = drift.copy()
2180 clean_drift = drift.copy()
2076
2077 clean_drift[:] = numpy.nan
2181 clean_drift[:] = numpy.nan
2078 if nchan == 2:
2182 if nchan == 2:
2079 clean_zonal = zonal.copy()
2183 clean_zonal = zonal.copy()
2080 clean_zonal[:] = numpy.nan
2184 clean_zonal[:] = numpy.nan
2081
2185
2082 # Drifts
2186 # Vertical
2083 driftstdv_th = 20*2
2187 sets1, self.old_drift, self.count_drift, self.oldTime_drift, aver_veloc, aver_sigma, clearAll = self.statistics150km(drift, w_w_err, driftstdv_th, \
2084
2188 old_veloc=self.old_drift, count=self.count_drift, currTime=dataOut.utctime, \
2085 sets1 = self.statistics150km(drift, w_w_err, driftstdv_th)
2189 oldTime=self.oldTime_drift, timeFactor=120)
2086
2190 if clearAll == 1:
2191 mean_zonal = numpy.nan
2192 sigma_zonal = numpy.nan
2193 mean_drift = aver_veloc
2194 sigma_drift = aver_sigma
2195
2087 if sets1.size != 1:
2196 if sets1.size != 1:
2088 clean_drift[sets1] = drift[sets1]
2197 clean_drift[sets1] = drift[sets1]
2089
2198
2090 novalid=numpy.where(numpy.isnan(clean_drift))[0]; cnovalid=novalid.size
2199 novalid=numpy.where(numpy.isnan(clean_drift))[0]; cnovalid=novalid.size
2091 if cnovalid > 0: drift[novalid] = numpy.nan
2200 if cnovalid > 0: drift[novalid] = numpy.nan
2092 if cnovalid > 0: snr[novalid] = numpy.nan
2201 if cnovalid > 0: snr[novalid] = numpy.nan
2093
2202
2094 # Zonal
2203 # Zonal
2095 if nchan == 2:
2204 if nchan == 2:
2096 zonalstdv_th = 30*2
2205 sets2, self.old_zonal, self.count_zonal, self.oldTime_zonal, aver_veloc, aver_sigma, clearAll = self.statistics150km(zonal, w_e_err, zonalstdv_th, \
2097 sets2 = self.statistics150km(zonal, w_e_err, zonalstdv_th)
2206 old_veloc=self.old_zonal, count=self.count_zonal, currTime=dataOut.utctime, \
2098
2207 oldTime=self.oldTime_zonal, timeFactor=600)
2208 if clearAll == 1:
2209 mean_zonal = numpy.nan
2210 sigma_zonal = numpy.nan
2211 mean_zonal = aver_veloc
2212 sigma_zonal = aver_sigma
2099 if sets2.size != 1:
2213 if sets2.size != 1:
2100 clean_zonal[sets2] = zonal[sets2]
2214 clean_zonal[sets2] = zonal[sets2]
2101
2215
2102 novalid=numpy.where(numpy.isnan(clean_zonal))[0]; cnovalid=novalid.size
2216 novalid=numpy.where(numpy.isnan(clean_zonal))[0]; cnovalid=novalid.size
2103 if cnovalid > 0: zonal[novalid] = numpy.nan
2217 if cnovalid > 0: zonal[novalid] = numpy.nan
2104 if cnovalid > 0: snr[novalid] = numpy.nan
2218 if cnovalid > 0: snr[novalid] = numpy.nan
2219
2220 n_avg_par=4
2221 avg_par=numpy.empty((n_avg_par,)); avg_par[:] = numpy.nan
2222 avg_par[0,]=mean_drift
2223 avg_par[1,]=mean_zonal
2224 avg_par[2,]=sigma_drift
2225 avg_par[3,]=sigma_zonal
2226
2227 set1 = 1.0
2228 navg = set1
2229 nci = dataOut.nCohInt
2230 # ----------------------------------
2231 ipp = 252.0
2232 nincoh = dataOut.nIncohInt
2233 nptsfft = dataOut.nProfiles
2234 hardcoded=False # if True, similar to IDL processing
2235 if hardcoded:
2236 ipp=200.1
2237 nincoh=22
2238 nptsfft=128
2239 # ----------------------------------
2240 nipp = ipp * nci
2241 height = dataOut.heightList
2242 nHei = len(height)
2243 kd = 213.6
2244 nint = nptsfft * nincoh
2245 drift1D = drift.copy()
2246 if nchan == 2:
2247 zonal1D=zonal.copy()
2248 snr1D = snr.copy()
2249 snr1D = 10*numpy.power(10, 0.1*snr1D)
2250 noise1D = noise.copy()
2251 noise0 = numpy.nanmedian(noise1D)
2252 noise = noise0 + noise0
2253 sw1D = sw.copy()
2254 pow0 = snr1D * noise0 + noise0
2255 acf0 = snr1D * noise0 * numpy.exp((-drift1D*nipp*numpy.pi/(1.5e5*1.5))*1j) * (1-0.5*numpy.power(sw1D*nipp*numpy.pi/(1.5e5*1.5),2))
2256 acf0 /= pow0
2257 acf1 = acf0
2258 dt= nint * nipp /1.5e5
2259
2260 if nchan == 2:
2261 dccf = pow0 * pow0 * numpy.exp((zonal1D*kd*dt/(height*1e3))*(1j))
2262 else:
2263 dccf = numpy.empty(nHei); dccf[:]=numpy.nan # complex?
2264 dccf /= pow0 * pow0
2265 sno=(pow0+pow0-noise)/noise
2266
2267 # First parameter: Signal to noise ratio and its error
2268 sno = numpy.log10(sno)
2269 sno10 = 10 * sno
2270 dsno = 1.0/numpy.sqrt(nint*navg)*(1+1/sno10)
2271
2272 # Second parameter: Vertical Drifts
2273 s=numpy.sqrt(numpy.abs(acf0)*numpy.abs(acf1))
2274 sp = s*(1.0 + 1.0/sno10)
2275 vzo = -numpy.arctan2(numpy.imag(acf0+acf1),numpy.real(acf0+acf1))* \
2276 1.5e5*1.5/(nipp*numpy.pi)
2277 dvzo = numpy.sqrt(1-sp*sp)*0.338*1.5e5/(numpy.sqrt(nint*navg)*sp*nipp)
2278
2279 # Third parameter: Zonal Drifts
2280 dt = nint*nipp/1.5e5
2281 ss = numpy.sqrt(numpy.abs(dccf))
2282 vxo = numpy.arctan2(numpy.imag(dccf),numpy.real(dccf))*height*1e3/(kd*dt)
2283 dvxo = numpy.sqrt(1.0-ss*ss)*height*1e3/(numpy.sqrt(nint*navg)*ss*kd*dt)
2105
2284
2285 npar = 5
2286 par = numpy.empty((npar, nHei)); par[:] = numpy.nan
2106
2287
2107 if otype == 0:
2288 par[0,:] = sno
2108 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
2289 par[1,:] = vzo
2109 elif otype == 2:
2290 par[2,:] = vxo
2110 winds = numpy.vstack((snr, drift)) # one channel good signal: 2 RTI's
2291 par[3,:] = dvzo
2111 elif otype == 3:
2292 par[4,:] = dvxo
2112 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
2293
2113 elif otype == 4:
2294 # Segundo filtrado:
2114 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
2295 # RemociΓ³n por altura: Menos de dos datos finitos no son considerados como eco 150Km.
2115
2296 clean_par=numpy.empty((npar,nHei)); clean_par[:]=numpy.nan
2116 snr1 = numpy.vstack((snrCH0, snrCH1))
2297 if clean:
2117 print('winds:',winds.shape)
2298
2118 print('snrCH0:',snrCH0.shape)
2299 for p in range(npar):
2119 dataOut.data_output = winds
2300 ih=0
2120 dataOut.data_snr = snr1
2301 while ih < nHei-1:
2302 j=ih
2303 if numpy.isfinite(snr1D[ih]):
2304 while numpy.isfinite(snr1D[j]):
2305 j+=1
2306 if j >= nHei:
2307 break
2308 if j > ih + 1:
2309 for k in range(ih,j):
2310 clean_par[p][k] = par[p][k]
2311 ih = j - 1
2312 ih+=1
2313 else:
2314 clean_par[:] = par[:]
2121
2315
2316 winds = numpy.vstack((clean_par[0,:], clean_par[1,:], clean_par[2,:], clean_par[3,:], clean_par[4,:]))
2317 dataOut.data_output = winds
2318 dataOut.avg_output = avg_par
2122 dataOut.utctimeInit = dataOut.utctime
2319 dataOut.utctimeInit = dataOut.utctime
2123 dataOut.outputInterval = dataOut.timeInterval
2320 dataOut.outputInterval = dataOut.timeInterval
2124
2321
2125 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.data_output[0])) # NAN vectors are not written
2322 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.data_output[0])) # NAN vectors are not written
2126
2323
2127 return dataOut
2324 return dataOut
2325
2326
2327 class JULIA_NightVelocities(Operation):
2328 '''
2329 Function SpreadFVelocities()
2330
2331 Calculates SNL and drifts
2332
2333 Type of dataIn: Parameters
2334
2335 Configuration Parameters:
2336
2337 mymode : (0) Interferometry,
2338 (1) Doppler beam swinging.
2339 myproc : (0) JULIA_V,
2340 (1) JULIA_EW.
2341 myantenna : (0) 1/4 antenna,
2342 (1) 1/2 antenna.
2343 jset : Number of Incoherent integrations.
2344
2345
2346 Input:
2347 channelList : simple channel list to select e.g. [2,3,7]
2348 self.dataOut.data_pre : Spectral data
2349 self.dataOut.abscissaList : List of frequencies
2350 self.dataOut.noise : Noise level per channel
2351
2352 Affected:
2353 self.dataOut.moments : Parameters per channel
2354 self.dataOut.data_snr : SNR per channel
2355
2356 '''
2357 def __init__(self):
2358 Operation.__init__(self)
2359
2360 def newtotal(self, data):
2361 return numpy.nansum(data)
2362
2363 def data_filter(self, parm, snrth=-17, swth=20, dopth=500.0, debug=False):
2364
2365 Sz0 = parm.shape # Sz0: h,p
2366 drift = parm[:,0]
2367 sw = 2*parm[:,1]
2368 snr = 10*numpy.log10(parm[:,2])
2369 Sz = drift.shape # Sz: h
2370 mask = numpy.ones((Sz[0]))
2371 th=0
2372 valid=numpy.where(numpy.isfinite(snr))
2373 cvalid = len(valid[0])
2374 if cvalid >= 1:
2375 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
2376 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
2377 h = numpy.histogram(snr,bins=nbins)
2378 hist = h[0]
2379 values = numpy.round_(h[1])
2380 moda = values[numpy.where(hist == numpy.max(hist))]
2381 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
2382
2383 noise = snr[indNoise]
2384 noise_mean = numpy.sum(noise)/len(noise)
2385 # CΓ‘lculo de media de snr
2386 med = numpy.median(snr)
2387 # Establece el umbral de snr
2388 if noise_mean > med + 3:
2389 th = med
2390 else:
2391 th = noise_mean + 3
2392 # Establece mΓ‘scara
2393 novalid = numpy.where(snr <= th)[0]
2394 mask[novalid] = numpy.nan
2395 # Elimina datos que no sobrepasen el umbral: PARAMETRO
2396 novalid = numpy.where(snr <= snrth)
2397 cnovalid = len(novalid[0])
2398 if cnovalid > 0:
2399 mask[novalid] = numpy.nan
2400 novalid = numpy.where(numpy.isnan(snr))
2401 cnovalid = len(novalid[0])
2402 if cnovalid > 0:
2403 mask[novalid] = numpy.nan
2404 # umbral de velocidad
2405 if dopth != None:
2406 novalid = numpy.where(numpy.logical_or(drift< dopth*(-1), drift > dopth))
2407 cnovalid = len(novalid[0])
2408 if cnovalid > 0:
2409 mask[novalid] = numpy.nan
2410 if debug:
2411 print('Descartados:%i de %i:' %(cnovalid, len(drift)))
2412 print('Porcentaje:%3.1f' %(100.0*cnovalid/len(drift)))
2413
2414 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
2415 for i in range(Sz0[1]):
2416 new_parm[:,i] = parm[:,i] * mask
2417
2418 return new_parm, mask
2419
2420
2421 def run(self, dataOut, zenith, zenithCorrection, mymode=1, dbs_sel=0, myproc=0, myantenna=0, jset=None, clean=False):
2422
2423
2424 dataOut.lat=-11.95
2425 dataOut.lon=-76.87
2426 mode=mymode
2427 proc=myproc
2428 antenna=myantenna
2429 nci=dataOut.nCohInt
2430 nptsfft=dataOut.nProfiles
2431 navg= 3 if jset is None else jset
2432 nint=dataOut.nIncohInt//navg
2433 navg1=dataOut.nProfiles * nint * navg
2434 tau1=dataOut.ippSeconds
2435 nipp=dataOut.radarControllerHeaderObj.ipp
2436 jlambda=6
2437 kd=213.6
2438 hei=dataOut.heightList.copy()
2128
2439
2440 nCh=dataOut.spcpar.shape[0]
2441 nHei=dataOut.spcpar.shape[1]
2442 nParam=dataOut.spcpar.shape[2]
2443
2444 parm = numpy.zeros((nCh,nHei,nParam))
2445 parm[:] = dataOut.spcpar[:]
2446 mask=numpy.ones(nHei)
2447 mask0=mask.copy()
2448 # Primer filtrado: Umbral de SNR
2449 for i in range(nCh):
2450 parm[i,:,:], mask = self.data_filter(parm[i,:,:], snrth = 0.1) # umbral 0.1 filtra seΓ±al que no corresponde a ESF, para interferometrΓ­a usar -17dB
2451 mask0 *= mask
2452
2453 ccf_results=numpy.transpose(dataOut.ccfpar,(2,1,0))
2454
2455 for i in range(3):
2456 ccf_results[i,:,0] *= mask0
2457
2458 zenith = numpy.array(zenith)
2459 zenith -= zenithCorrection
2460 zenith *= numpy.pi/180
2461 alpha = zenith[0]
2462 beta = zenith[1]
2463
2464 w_w = parm[0,:,0]
2465 w_e = parm[1,:,0]
2466
2467 if mode==1:
2468 # Vertical and zonal calculation
2469 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
2470 w = -(w_w * numpy.sin(beta) - w_e * numpy.sin(alpha))/ sinB_A
2471 u = (w_w * numpy.cos(beta) - w_e * numpy.cos(alpha))/ sinB_A
2472
2473 #Noise
2474 n0 = parm[0,:,3]
2475 n1 = parm[1,:,3]
2476 jn0_1 = numpy.nanmedian(n0)
2477 jn0_2 = numpy.nanmean(n0)
2478 jn1_1 = numpy.nanmedian(n1)
2479 jn1_2 = numpy.nanmean(n1)
2480 noise0 = jn0_2 if numpy.abs(jn0_1-jn0_2)/(jn0_1+jn0_2) <= 0.1 else jn0_1
2481 noise1 = jn1_2 if numpy.abs(jn1_1-jn1_2)/(jn1_1+jn1_2) <= 0.1 else jn1_1
2482
2483 noise = noise0 + noise0 if mode == 1 else noise0 + noise1
2484
2485 #Power
2486 apow1 = (parm[0,:,2]/numpy.sqrt(nint))*noise0 + n0
2487 apow2 = (parm[1,:,2]/numpy.sqrt(nint))*noise1 + n1
2488
2489 #SNR SNR=Detectability/ SQRT(nint) or (Pow-Noise)/Noise
2490 s_n0 = (apow1 - noise0)/noise0
2491 s_n1 = (apow2 - noise1)/noise1
2492
2493 swCH0 = parm[0,:,1]
2494 swCH1 = parm[1,:,1]
2495
2496 if mode == 1:
2497 aacf1=(1-numpy.square(tau1)*numpy.square(4*numpy.pi/jlambda*swCH0)/2)* \
2498 numpy.exp(-4*numpy.pi/jlambda*w*tau1*1j)* \
2499 apow1
2500 aacf2=(1-numpy.square(tau1)*numpy.square(4*numpy.pi/jlambda*swCH1)/2)* \
2501 numpy.exp(-4*numpy.pi/jlambda*w*tau1*1j)* \
2502 apow2
2503 dccf_0=numpy.zeros(nHei, dtype=complex)
2504
2505 else:
2506 aacf1=(1-numpy.square(tau1)*numpy.square(4*numpy.pi/jlambda*swCH0)/2)* \
2507 numpy.exp(4*numpy.pi/jlambda*w_w*tau1*1j)* \
2508 apow1
2509 aacf2=(1-numpy.square(tau1)*numpy.square(4*numpy.pi/jlambda*swCH1)/2)* \
2510 numpy.exp(4*numpy.pi/jlambda*w_e*tau1*1j)* \
2511 apow2
2512 dccf_0=numpy.power(ccf_results[0,:,0],2)*apow1*apow2* \
2513 numpy.exp( \
2514 ( \
2515 (1+1*(antenna==1))* \
2516 (-1+2*(proc == 1))* \
2517 ccf_results[2,:,0] \
2518 )*1j)
2519
2520 nsamp=len(hei)
2521 pow0 = numpy.empty(nsamp); pow0[:] = numpy.nan
2522 pow1 = numpy.empty(nsamp); pow1[:] = numpy.nan
2523 acf0 = numpy.empty(nsamp, dtype=complex); acf0[:] = numpy.nan
2524 acf1 = numpy.empty(nsamp, dtype=complex); acf1[:] = numpy.nan
2525 dccf = numpy.empty(nsamp, dtype=complex); dccf[:] = numpy.nan
2526 dop0 = numpy.empty(nsamp); dop0[:] = numpy.nan
2527 dop1 = numpy.empty(nsamp); dop1[:] = numpy.nan
2528 p_w = numpy.empty(nsamp); p_w[:] = numpy.nan
2529 p_u = numpy.empty(nsamp); p_u[:] = numpy.nan
2530
2531 if mode == 0 or (mode == 1 and dbs_sel == 0):
2532 ih=0
2533 while ih < nsamp-10:
2534 j=ih
2535 if numpy.isfinite(s_n0[ih]) and numpy.isfinite(s_n1[ih]):
2536 while numpy.isfinite(s_n0[j]) and numpy.isfinite(s_n1[j]):
2537 j+=1
2538 if j > ih + 2:
2539 for k in range(ih,j):
2540 pow0[k] = apow1[k]
2541 pow1[k] = apow2[k]
2542 acf0[k] = aacf1[k]
2543 acf1[k] = aacf2[k]
2544 dccf[k] = dccf_0[k]
2545 ih = j - 1
2546 ih+=1
2547 else:
2548 ih=0
2549 while ih < nsamp-10:
2550 j=ih
2551 if numpy.isfinite(s_n0[ih]):
2552 while numpy.isfinite(s_n0[j]) and j < nsamp-10:
2553 j+=1
2554 #if j > ih + 6:
2555 if j > ih + 2:
2556 #if j > ih + 3:
2557 for k in range(ih,j):
2558 pow0[k] = apow1[k]
2559 #acf0[k] = aacf1[k]
2560 #dccf[k] = dccf_0[k]
2561 p_w[k] = w[k]
2562 dop0[k] = w_w[k]
2563 ih = j - 1
2564 ih+=1
2565 ih=0
2566 while ih < nsamp-10:
2567 j=ih
2568 if numpy.isfinite(s_n1[ih]):
2569 while numpy.isfinite(s_n1[j]) and j < nsamp-10:
2570 j+=1
2571 #if j > ih + 6:
2572 if j > ih + 2:
2573 #if j > ih + 3:
2574 for k in range(ih,j):
2575 pow1[k] = apow2[k]
2576 #acf1[k] = aacf2[k]
2577 p_u[k] = u[k]
2578 dop1[k] = w_e[k]
2579 ih = j - 1
2580 ih+=1
2581
2582 acf0 = numpy.zeros(nsamp, dtype=complex)
2583 acf1 = numpy.zeros(nsamp, dtype=complex)
2584 dccf = numpy.zeros(nsamp, dtype=complex)
2585
2586 acf0 /= pow0
2587 acf1 /= pow1
2588 dccf /= pow0 * pow1
2589
2590 if mode == 0 or (mode == 1 and dbs_sel == 0):
2591 sno=(pow0+pow1-noise)/noise
2592 # First parameter: Signal to noise ratio and its error
2593 sno=numpy.log10(sno)
2594 dsno=1.0/numpy.sqrt(nint*navg)*(1+1/sno)
2595 # Second parameter: Vertical Drifts
2596 s=numpy.sqrt(numpy.abs(acf0)*numpy.abs(acf1))
2597 ind=numpy.where(numpy.abs(s)>=1.0)
2598 if numpy.size(ind)>0:
2599 s[ind]=numpy.sqrt(0.9999)
2600 sp=s*(1.0 + 1.0/sno)
2601 vzo=-numpy.arctan2(numpy.imag(acf0+acf1),numpy.real(acf0+acf1))* \
2602 1.5e5*1.5/(nipp*numpy.pi)
2603 dvzo=numpy.sqrt(1-sp*sp)*0.338*1.5e5/(numpy.sqrt(nint*navg)*sp*nipp)
2604 ind=numpy.where(dvzo<=0.1)
2605 if numpy.size(ind)>0:
2606 dvzo[ind]=0.1
2607 # Third parameter: Zonal Drifts
2608 dt=nint*nipp/1.5e5
2609 ss=numpy.sqrt(numpy.abs(dccf))
2610 ind=numpy.where(ss>=1.0)
2611 if numpy.size(ind)>0:
2612 ss[ind]=numpy.sqrt(0.99999)
2613 ind=numpy.where(ss<=0.1)
2614 if numpy.size(ind)>0:
2615 ss[ind]=numpy.sqrt(0.1)
2616 vxo=numpy.arctan2(numpy.imag(dccf),numpy.real(dccf))*hei*1e3/(kd*dt)
2617 dvxo=numpy.sqrt(1.0-ss*ss)*hei*1e3/(numpy.sqrt(nint*navg)*ss*kd*dt)
2618 ind=numpy.where(dvxo<=0.1)
2619 if numpy.size(ind)>0:
2620 dvxo[ind]=0.1
2621 else:
2622 sno0=(pow0-noise0)/noise0
2623 sno1=(pow1-noise1)/noise1
2624
2625 # First parameter: Signal to noise ratio and its error
2626 sno0=numpy.log10(sno0)
2627 dsno0=1.0/numpy.sqrt(nint*navg)*(1+1/sno0)
2628 sno1=numpy.log10(sno1)
2629 dsno1=1.0/numpy.sqrt(nint*navg)*(1+1/sno1)
2630
2631 npar=6
2632 par = numpy.empty((npar, nHei)); par[:] = numpy.nan
2633
2634 if mode == 0:
2635 par[0,:] = sno
2636 par[1,:] = vxo
2637 par[2,:] = dvxo
2638 par[3,:] = vzo
2639 par[4,:] = dvzo
2640
2641 elif mode == 1 and dbs_sel == 0:
2642 par[0,:] = sno
2643 par[1,:] = vzo
2644 else:
2645 par[0,:] = sno0
2646 par[1,:] = sno1
2647 par[2,:] = dop0
2648 par[3,:] = dop1
2649 #par[4,:] = p_w
2650 #par[5,:] = p_u
2651
2652 if mode == 0:
2653 winds = numpy.vstack((par[0,:], par[1,:], par[2,:], par[3,:], par[4,:]))
2654 elif mode == 1 and dbs_sel == 0:
2655 winds = numpy.vstack((par[0,:], par[1,:]))
2656 else:
2657 winds = numpy.vstack((par[0,:], par[1,:], par[2,:], par[3,:]))
2658
2659 dataOut.data_output = winds
2660 dataOut.data_snr = par[0,:]
2661
2662 dataOut.utctimeInit = dataOut.utctime
2663 dataOut.outputInterval = dataOut.timeInterval
2664
2665 aux1= numpy.all(numpy.isnan(dataOut.data_output[0])) # NAN vectors are not written
2666 aux2= numpy.all(numpy.isnan(dataOut.data_output[1])) # NAN vectors are not written
2667 dataOut.flagNoData = aux1 or aux2
2668
2669 return dataOut
2670
2129 class SALags(Operation):
2671 class SALags(Operation):
2130 '''
2672 '''
2131 Function GetMoments()
2673 Function GetMoments()
2132
2674
2133 Input:
2675 Input:
2134 self.dataOut.data_pre
2676 self.dataOut.data_pre
2135 self.dataOut.abscissaList
2677 self.dataOut.abscissaList
2136 self.dataOut.noise
2678 self.dataOut.noise
2137 self.dataOut.normFactor
2679 self.dataOut.normFactor
2138 self.dataOut.data_snr
2680 self.dataOut.data_snr
2139 self.dataOut.groupList
2681 self.dataOut.groupList
2140 self.dataOut.nChannels
2682 self.dataOut.nChannels
2141
2683
2142 Affected:
2684 Affected:
2143 self.dataOut.data_param
2685 self.dataOut.data_param
2144
2686
2145 '''
2687 '''
2146 def run(self, dataOut):
2688 def run(self, dataOut):
2147 data_acf = dataOut.data_pre[0]
2689 data_acf = dataOut.data_pre[0]
2148 data_ccf = dataOut.data_pre[1]
2690 data_ccf = dataOut.data_pre[1]
2149 normFactor_acf = dataOut.normFactor[0]
2691 normFactor_acf = dataOut.normFactor[0]
2150 normFactor_ccf = dataOut.normFactor[1]
2692 normFactor_ccf = dataOut.normFactor[1]
2151 pairs_acf = dataOut.groupList[0]
2693 pairs_acf = dataOut.groupList[0]
2152 pairs_ccf = dataOut.groupList[1]
2694 pairs_ccf = dataOut.groupList[1]
2153
2695
2154 nHeights = dataOut.nHeights
2696 nHeights = dataOut.nHeights
2155 absc = dataOut.abscissaList
2697 absc = dataOut.abscissaList
2156 noise = dataOut.noise
2698 noise = dataOut.noise
2157 SNR = dataOut.data_snr
2699 SNR = dataOut.data_snr
2158 nChannels = dataOut.nChannels
2700 nChannels = dataOut.nChannels
2159 # pairsList = dataOut.groupList
2701 # pairsList = dataOut.groupList
2160 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
2702 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
2161
2703
2162 for l in range(len(pairs_acf)):
2704 for l in range(len(pairs_acf)):
2163 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
2705 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
2164
2706
2165 for l in range(len(pairs_ccf)):
2707 for l in range(len(pairs_ccf)):
2166 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
2708 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
2167
2709
2168 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
2710 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
2169 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
2711 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
2170 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
2712 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
2171 return
2713 return
2172
2714
2173 # def __getPairsAutoCorr(self, pairsList, nChannels):
2715 # def __getPairsAutoCorr(self, pairsList, nChannels):
2174 #
2716 #
2175 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
2717 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
2176 #
2718 #
2177 # for l in range(len(pairsList)):
2719 # for l in range(len(pairsList)):
2178 # firstChannel = pairsList[l][0]
2720 # firstChannel = pairsList[l][0]
2179 # secondChannel = pairsList[l][1]
2721 # secondChannel = pairsList[l][1]
2180 #
2722 #
2181 # #Obteniendo pares de Autocorrelacion
2723 # #Obteniendo pares de Autocorrelacion
2182 # if firstChannel == secondChannel:
2724 # if firstChannel == secondChannel:
2183 # pairsAutoCorr[firstChannel] = int(l)
2725 # pairsAutoCorr[firstChannel] = int(l)
2184 #
2726 #
2185 # pairsAutoCorr = pairsAutoCorr.astype(int)
2727 # pairsAutoCorr = pairsAutoCorr.astype(int)
2186 #
2728 #
2187 # pairsCrossCorr = range(len(pairsList))
2729 # pairsCrossCorr = range(len(pairsList))
2188 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
2730 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
2189 #
2731 #
2190 # return pairsAutoCorr, pairsCrossCorr
2732 # return pairsAutoCorr, pairsCrossCorr
2191
2733
2192 def __calculateTaus(self, data_acf, data_ccf, lagRange):
2734 def __calculateTaus(self, data_acf, data_ccf, lagRange):
2193
2735
2194 lag0 = data_acf.shape[1]/2
2736 lag0 = data_acf.shape[1]/2
2195 #Funcion de Autocorrelacion
2737 #Funcion de Autocorrelacion
2196 mean_acf = stats.nanmean(data_acf, axis = 0)
2738 mean_acf = stats.nanmean(data_acf, axis = 0)
2197
2739
2198 #Obtencion Indice de TauCross
2740 #Obtencion Indice de TauCross
2199 ind_ccf = data_ccf.argmax(axis = 1)
2741 ind_ccf = data_ccf.argmax(axis = 1)
2200 #Obtencion Indice de TauAuto
2742 #Obtencion Indice de TauAuto
2201 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
2743 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
2202 ccf_lag0 = data_ccf[:,lag0,:]
2744 ccf_lag0 = data_ccf[:,lag0,:]
2203
2745
2204 for i in range(ccf_lag0.shape[0]):
2746 for i in range(ccf_lag0.shape[0]):
2205 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
2747 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
2206
2748
2207 #Obtencion de TauCross y TauAuto
2749 #Obtencion de TauCross y TauAuto
2208 tau_ccf = lagRange[ind_ccf]
2750 tau_ccf = lagRange[ind_ccf]
2209 tau_acf = lagRange[ind_acf]
2751 tau_acf = lagRange[ind_acf]
2210
2752
2211 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
2753 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
2212
2754
2213 tau_ccf[Nan1,Nan2] = numpy.nan
2755 tau_ccf[Nan1,Nan2] = numpy.nan
2214 tau_acf[Nan1,Nan2] = numpy.nan
2756 tau_acf[Nan1,Nan2] = numpy.nan
2215 tau = numpy.vstack((tau_ccf,tau_acf))
2757 tau = numpy.vstack((tau_ccf,tau_acf))
2216
2758
2217 return tau
2759 return tau
2218
2760
2219 def __calculateLag1Phase(self, data, lagTRange):
2761 def __calculateLag1Phase(self, data, lagTRange):
2220 data1 = stats.nanmean(data, axis = 0)
2762 data1 = stats.nanmean(data, axis = 0)
2221 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
2763 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
2222
2764
2223 phase = numpy.angle(data1[lag1,:])
2765 phase = numpy.angle(data1[lag1,:])
2224
2766
2225 return phase
2767 return phase
2226
2768
2227 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
2769 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
2228 z = (x - a1) / a2
2770 z = (x - a1) / a2
2229 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
2771 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
2230 return y
2772 return y
2231
2773
2232
2774
2233 class SpectralFitting(Operation):
2775 class SpectralFitting(Operation):
2234 '''
2776 '''
2235 Function GetMoments()
2777 Function GetMoments()
2236
2778
2237 Input:
2779 Input:
2238 Output:
2780 Output:
2239 Variables modified:
2781 Variables modified:
2240 '''
2782 '''
2241 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):
2783 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):
2242
2784
2243 if (nicoh is None): nicoh = 1
2785 if (nicoh is None): nicoh = 1
2244 if (graph is None): graph = 0
2786 if (graph is None): graph = 0
2245 if (smooth is None): smooth = 0
2787 if (smooth is None): smooth = 0
2246 elif (self.smooth < 3): smooth = 0
2788 elif (self.smooth < 3): smooth = 0
2247
2789
2248 if (type1 is None): type1 = 0
2790 if (type1 is None): type1 = 0
2249 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2791 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2250 if (snrth is None): snrth = -3
2792 if (snrth is None): snrth = -3
2251 if (dc is None): dc = 0
2793 if (dc is None): dc = 0
2252 if (aliasing is None): aliasing = 0
2794 if (aliasing is None): aliasing = 0
2253 if (oldfd is None): oldfd = 0
2795 if (oldfd is None): oldfd = 0
2254 if (wwauto is None): wwauto = 0
2796 if (wwauto is None): wwauto = 0
2255
2797
2256 if (n0 < 1.e-20): n0 = 1.e-20
2798 if (n0 < 1.e-20): n0 = 1.e-20
2257
2799
2258 freq = oldfreq
2800 freq = oldfreq
2259 vec_power = numpy.zeros(oldspec.shape[1])
2801 vec_power = numpy.zeros(oldspec.shape[1])
2260 vec_fd = numpy.zeros(oldspec.shape[1])
2802 vec_fd = numpy.zeros(oldspec.shape[1])
2261 vec_w = numpy.zeros(oldspec.shape[1])
2803 vec_w = numpy.zeros(oldspec.shape[1])
2262 vec_snr = numpy.zeros(oldspec.shape[1])
2804 vec_snr = numpy.zeros(oldspec.shape[1])
2263
2805
2264 oldspec = numpy.ma.masked_invalid(oldspec)
2806 oldspec = numpy.ma.masked_invalid(oldspec)
2265
2807
2266 for ind in range(oldspec.shape[1]):
2808 for ind in range(oldspec.shape[1]):
2267
2809
2268 spec = oldspec[:,ind]
2810 spec = oldspec[:,ind]
2269 aux = spec*fwindow
2811 aux = spec*fwindow
2270 max_spec = aux.max()
2812 max_spec = aux.max()
2271 m = list(aux).index(max_spec)
2813 m = list(aux).index(max_spec)
2272
2814
2273 #Smooth
2815 #Smooth
2274 if (smooth == 0): spec2 = spec
2816 if (smooth == 0): spec2 = spec
2275 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2817 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2276
2818
2277 # Calculo de Momentos
2819 # Calculo de Momentos
2278 bb = spec2[list(range(m,spec2.size))]
2820 bb = spec2[list(range(m,spec2.size))]
2279 bb = (bb<n0).nonzero()
2821 bb = (bb<n0).nonzero()
2280 bb = bb[0]
2822 bb = bb[0]
2281
2823
2282 ss = spec2[list(range(0,m + 1))]
2824 ss = spec2[list(range(0,m + 1))]
2283 ss = (ss<n0).nonzero()
2825 ss = (ss<n0).nonzero()
2284 ss = ss[0]
2826 ss = ss[0]
2285
2827
2286 if (bb.size == 0):
2828 if (bb.size == 0):
2287 bb0 = spec.size - 1 - m
2829 bb0 = spec.size - 1 - m
2288 else:
2830 else:
2289 bb0 = bb[0] - 1
2831 bb0 = bb[0] - 1
2290 if (bb0 < 0):
2832 if (bb0 < 0):
2291 bb0 = 0
2833 bb0 = 0
2292
2834
2293 if (ss.size == 0): ss1 = 1
2835 if (ss.size == 0): ss1 = 1
2294 else: ss1 = max(ss) + 1
2836 else: ss1 = max(ss) + 1
2295
2837
2296 if (ss1 > m): ss1 = m
2838 if (ss1 > m): ss1 = m
2297
2839
2298 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
2840 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
2299 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
2841 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
2300 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
2842 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
2301 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2843 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2302 snr = (spec2.mean()-n0)/n0
2844 snr = (spec2.mean()-n0)/n0
2303
2845
2304 if (snr < 1.e-20) :
2846 if (snr < 1.e-20) :
2305 snr = 1.e-20
2847 snr = 1.e-20
2306
2848
2307 vec_power[ind] = power
2849 vec_power[ind] = power
2308 vec_fd[ind] = fd
2850 vec_fd[ind] = fd
2309 vec_w[ind] = w
2851 vec_w[ind] = w
2310 vec_snr[ind] = snr
2852 vec_snr[ind] = snr
2311
2853
2312 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2854 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2313 return moments
2855 return moments
2314
2856
2315 #def __DiffCoherent(self,snrth, spectra, cspectra, nProf, heights,nChan, nHei, nPairs, channels, noise, crosspairs):
2857 #def __DiffCoherent(self,snrth, spectra, cspectra, nProf, heights,nChan, nHei, nPairs, channels, noise, crosspairs):
2316 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
2858 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
2317
2859
2318 import matplotlib.pyplot as plt
2860 import matplotlib.pyplot as plt
2319 nProf = dataOut.nProfiles
2861 nProf = dataOut.nProfiles
2320 heights = dataOut.heightList
2862 heights = dataOut.heightList
2321 nHei = len(heights)
2863 nHei = len(heights)
2322 channels = dataOut.channelList
2864 channels = dataOut.channelList
2323 nChan = len(channels)
2865 nChan = len(channels)
2324 crosspairs = dataOut.groupList
2866 crosspairs = dataOut.groupList
2325 nPairs = len(crosspairs)
2867 nPairs = len(crosspairs)
2326 #Separar espectros incoherentes de coherentes snr > 20 dB'
2868 #Separar espectros incoherentes de coherentes snr > 20 dB'
2327 snr_th = 10**(snrth/10.0)
2869 snr_th = 10**(snrth/10.0)
2328 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
2870 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
2329 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
2871 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
2330 my_incoh_aver = numpy.zeros([nChan, nHei])
2872 my_incoh_aver = numpy.zeros([nChan, nHei])
2331 my_coh_aver = numpy.zeros([nChan, nHei])
2873 my_coh_aver = numpy.zeros([nChan, nHei])
2332
2874
2333 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2875 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2334 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2876 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2335 coh_aver = numpy.zeros([nChan, nHei])
2877 coh_aver = numpy.zeros([nChan, nHei])
2336
2878
2337 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2879 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2338 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2880 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2339 incoh_aver = numpy.zeros([nChan, nHei])
2881 incoh_aver = numpy.zeros([nChan, nHei])
2340 power = numpy.sum(spectra, axis=1)
2882 power = numpy.sum(spectra, axis=1)
2341
2883
2342 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
2884 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
2343 if hei_th == None : hei_th = numpy.array([60,300,650])
2885 if hei_th == None : hei_th = numpy.array([60,300,650])
2344 for ic in range(2):
2886 for ic in range(2):
2345 pair = crosspairs[ic]
2887 pair = crosspairs[ic]
2346 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
2888 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
2347 s_n0 = power[pair[0],:]/noise[pair[0]]
2889 s_n0 = power[pair[0],:]/noise[pair[0]]
2348 s_n1 = power[pair[1],:]/noise[pair[1]]
2890 s_n1 = power[pair[1],:]/noise[pair[1]]
2349
2891
2350 valid1 =(s_n0>=snr_th).nonzero()
2892 valid1 =(s_n0>=snr_th).nonzero()
2351 valid2 = (s_n1>=snr_th).nonzero()
2893 valid2 = (s_n1>=snr_th).nonzero()
2352 #valid = valid2 + valid1 #numpy.concatenate((valid1,valid2), axis=None)
2894 #valid = valid2 + valid1 #numpy.concatenate((valid1,valid2), axis=None)
2353 valid1 = numpy.array(valid1[0])
2895 valid1 = numpy.array(valid1[0])
2354 valid2 = numpy.array(valid2[0])
2896 valid2 = numpy.array(valid2[0])
2355 valid = valid1
2897 valid = valid1
2356 for iv in range(len(valid2)):
2898 for iv in range(len(valid2)):
2357 #for ivv in range(len(valid1)) :
2899 #for ivv in range(len(valid1)) :
2358 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2900 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2359 if len(indv[0]) == 0 :
2901 if len(indv[0]) == 0 :
2360 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2902 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2361 if len(valid)>0:
2903 if len(valid)>0:
2362 my_coh_aver[pair[0],valid]=1
2904 my_coh_aver[pair[0],valid]=1
2363 my_coh_aver[pair[1],valid]=1
2905 my_coh_aver[pair[1],valid]=1
2364 # si la coherencia es mayor a la coherencia threshold los datos se toman
2906 # si la coherencia es mayor a la coherencia threshold los datos se toman
2365 #print my_coh_aver[0,:]
2907 #print my_coh_aver[0,:]
2366 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)))
2908 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)))
2367 #print('coh',numpy.absolute(coh))
2909 #print('coh',numpy.absolute(coh))
2368 for ih in range(len(hei_th)):
2910 for ih in range(len(hei_th)):
2369 hvalid = (heights>hei_th[ih]).nonzero()
2911 hvalid = (heights>hei_th[ih]).nonzero()
2370 hvalid = hvalid[0]
2912 hvalid = hvalid[0]
2371 if len(hvalid)>0:
2913 if len(hvalid)>0:
2372 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
2914 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
2373 valid = valid[0]
2915 valid = valid[0]
2374 #print('hvalid:',hvalid)
2916 #print('hvalid:',hvalid)
2375 #print('valid', valid)
2917 #print('valid', valid)
2376 if len(valid)>0:
2918 if len(valid)>0:
2377 my_coh_aver[pair[0],hvalid[valid]] =1
2919 my_coh_aver[pair[0],hvalid[valid]] =1
2378 my_coh_aver[pair[1],hvalid[valid]] =1
2920 my_coh_aver[pair[1],hvalid[valid]] =1
2379
2921
2380 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
2922 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
2381 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
2923 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
2382 incoh_echoes = incoh_echoes[0]
2924 incoh_echoes = incoh_echoes[0]
2383 if len(incoh_echoes) > 0:
2925 if len(incoh_echoes) > 0:
2384 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2926 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2385 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2927 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2386 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2928 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2387 my_incoh_aver[pair[0],incoh_echoes] = 1
2929 my_incoh_aver[pair[0],incoh_echoes] = 1
2388 my_incoh_aver[pair[1],incoh_echoes] = 1
2930 my_incoh_aver[pair[1],incoh_echoes] = 1
2389
2931
2390
2932
2391 for ic in range(2):
2933 for ic in range(2):
2392 pair = crosspairs[ic]
2934 pair = crosspairs[ic]
2393
2935
2394 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
2936 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
2395 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
2937 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
2396 valid1 = numpy.array(valid1[0])
2938 valid1 = numpy.array(valid1[0])
2397 valid2 = numpy.array(valid2[0])
2939 valid2 = numpy.array(valid2[0])
2398 valid = valid1
2940 valid = valid1
2399 #print valid1 , valid2
2941 #print valid1 , valid2
2400 for iv in range(len(valid2)):
2942 for iv in range(len(valid2)):
2401 #for ivv in range(len(valid1)) :
2943 #for ivv in range(len(valid1)) :
2402 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2944 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2403 if len(indv[0]) == 0 :
2945 if len(indv[0]) == 0 :
2404 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2946 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2405 #print valid
2947 #print valid
2406 #valid = numpy.concatenate((valid1,valid2), axis=None)
2948 #valid = numpy.concatenate((valid1,valid2), axis=None)
2407 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
2949 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
2408 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
2950 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
2409 valid1 = numpy.array(valid1[0])
2951 valid1 = numpy.array(valid1[0])
2410 valid2 = numpy.array(valid2[0])
2952 valid2 = numpy.array(valid2[0])
2411 incoh_echoes = valid1
2953 incoh_echoes = valid1
2412 #print valid1, valid2
2954 #print valid1, valid2
2413 #incoh_echoes= numpy.concatenate((valid1,valid2), axis=None)
2955 #incoh_echoes= numpy.concatenate((valid1,valid2), axis=None)
2414 for iv in range(len(valid2)):
2956 for iv in range(len(valid2)):
2415 #for ivv in range(len(valid1)) :
2957 #for ivv in range(len(valid1)) :
2416 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2958 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2417 if len(indv[0]) == 0 :
2959 if len(indv[0]) == 0 :
2418 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
2960 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
2419 #print incoh_echoes
2961 #print incoh_echoes
2420 if len(valid)>0:
2962 if len(valid)>0:
2421 #print pair
2963 #print pair
2422 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
2964 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
2423 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
2965 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
2424 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
2966 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
2425 coh_aver[pair[0],valid]=1
2967 coh_aver[pair[0],valid]=1
2426 coh_aver[pair[1],valid]=1
2968 coh_aver[pair[1],valid]=1
2427 if len(incoh_echoes)>0:
2969 if len(incoh_echoes)>0:
2428 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2970 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2429 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2971 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2430 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2972 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2431 incoh_aver[pair[0],incoh_echoes]=1
2973 incoh_aver[pair[0],incoh_echoes]=1
2432 incoh_aver[pair[1],incoh_echoes]=1
2974 incoh_aver[pair[1],incoh_echoes]=1
2433 #plt.imshow(spectra[0,:,:],vmin=20000000)
2975 #plt.imshow(spectra[0,:,:],vmin=20000000)
2434 #plt.show()
2976 #plt.show()
2435 #my_incoh_aver = my_incoh_aver+1
2977 #my_incoh_aver = my_incoh_aver+1
2436
2978
2437 #spec = my_incoh_spectra.copy()
2979 #spec = my_incoh_spectra.copy()
2438 #cspec = my_incoh_cspectra.copy()
2980 #cspec = my_incoh_cspectra.copy()
2439 #print('######################', spec)
2981 #print('######################', spec)
2440 #print(self.numpy)
2982 #print(self.numpy)
2441 #return spec, cspec,coh_aver
2983 #return spec, cspec,coh_aver
2442 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
2984 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
2443
2985
2444 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
2986 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
2445
2987
2446 import matplotlib.pyplot as plt
2988 import matplotlib.pyplot as plt
2447 nProf = dataOut.nProfiles
2989 nProf = dataOut.nProfiles
2448 heights = dataOut.heightList
2990 heights = dataOut.heightList
2449 nHei = len(heights)
2991 nHei = len(heights)
2450 channels = dataOut.channelList
2992 channels = dataOut.channelList
2451 nChan = len(channels)
2993 nChan = len(channels)
2452 crosspairs = dataOut.groupList
2994 crosspairs = dataOut.groupList
2453 nPairs = len(crosspairs)
2995 nPairs = len(crosspairs)
2454
2996
2455 #data = dataOut.data_pre[0]
2997 #data = dataOut.data_pre[0]
2456 absc = dataOut.abscissaList[:-1]
2998 absc = dataOut.abscissaList[:-1]
2457 #noise = dataOut.noise
2999 #noise = dataOut.noise
2458 #nChannel = data.shape[0]
3000 #nChannel = data.shape[0]
2459 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
3001 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
2460
3002
2461
3003
2462 #plt.plot(absc)
3004 #plt.plot(absc)
2463 #plt.show()
3005 #plt.show()
2464 clean_coh_spectra = spectra.copy()
3006 clean_coh_spectra = spectra.copy()
2465 clean_coh_cspectra = cspectra.copy()
3007 clean_coh_cspectra = cspectra.copy()
2466 clean_coh_aver = coh_aver.copy()
3008 clean_coh_aver = coh_aver.copy()
2467
3009
2468 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
3010 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
2469 coh_th = 0.75
3011 coh_th = 0.75
2470
3012
2471 rtime0 = [6,18] # periodo sin ESF
3013 rtime0 = [6,18] # periodo sin ESF
2472 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
3014 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
2473
3015
2474 time = index*5./60
3016 time = index*5./60
2475 if clean_coh_echoes == 1 :
3017 if clean_coh_echoes == 1 :
2476 for ind in range(nChan):
3018 for ind in range(nChan):
2477 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
3019 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
2478 #print data_param[:,3]
3020 #print data_param[:,3]
2479 spwd = data_param[:,3]
3021 spwd = data_param[:,3]
2480 #print spwd.shape
3022 #print spwd.shape
2481 # 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
3023 # 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
2482 #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]
3024 #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]
2483 #spwd=numpy.array([spwd1,spwd1,spwd1,spwd1])
3025 #spwd=numpy.array([spwd1,spwd1,spwd1,spwd1])
2484 #print spwd.shape, heights.shape,coh_aver.shape
3026 #print spwd.shape, heights.shape,coh_aver.shape
2485 # para obtener spwd
3027 # para obtener spwd
2486 for ic in range(nPairs):
3028 for ic in range(nPairs):
2487 pair = crosspairs[ic]
3029 pair = crosspairs[ic]
2488 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)))
3030 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)))
2489 for ih in range(nHei) :
3031 for ih in range(nHei) :
2490 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
3032 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
2491 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
3033 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
2492 # Checking coherence
3034 # Checking coherence
2493 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
3035 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
2494 # Checking spectral widths
3036 # Checking spectral widths
2495 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
3037 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
2496 # satelite
3038 # satelite
2497 clean_coh_spectra[pair,ih,:] = 0.0
3039 clean_coh_spectra[pair,ih,:] = 0.0
2498 clean_coh_cspectra[ic,ih,:] = 0.0
3040 clean_coh_cspectra[ic,ih,:] = 0.0
2499 clean_coh_aver[pair,ih] = 0
3041 clean_coh_aver[pair,ih] = 0
2500 else :
3042 else :
2501 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
3043 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
2502 # Especial event like sun.
3044 # Especial event like sun.
2503 clean_coh_spectra[pair,ih,:] = 0.0
3045 clean_coh_spectra[pair,ih,:] = 0.0
2504 clean_coh_cspectra[ic,ih,:] = 0.0
3046 clean_coh_cspectra[ic,ih,:] = 0.0
2505 clean_coh_aver[pair,ih] = 0
3047 clean_coh_aver[pair,ih] = 0
2506
3048
2507 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
3049 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
2508
3050
2509 isConfig = False
3051 isConfig = False
2510 __dataReady = False
3052 __dataReady = False
2511 bloques = None
3053 bloques = None
2512 bloque0 = None
3054 bloque0 = None
2513
3055
2514 def __init__(self):
3056 def __init__(self):
2515 Operation.__init__(self)
3057 Operation.__init__(self)
2516 self.i=0
3058 self.i=0
2517 self.isConfig = False
3059 self.isConfig = False
2518
3060
2519
3061
2520 def setup(self,nChan,nProf,nHei,nBlocks):
3062 def setup(self,nChan,nProf,nHei,nBlocks):
2521 self.__dataReady = False
3063 self.__dataReady = False
2522 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
3064 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
2523 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
3065 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
2524
3066
2525 #def CleanRayleigh(self,dataOut,spectra,cspectra,out_spectra,out_cspectra,sat_spectra,sat_cspectra,crosspairs,heights, channels, nProf,nHei,nChan,nPairs,nIncohInt,nBlocks):
3067 #def CleanRayleigh(self,dataOut,spectra,cspectra,out_spectra,out_cspectra,sat_spectra,sat_cspectra,crosspairs,heights, channels, nProf,nHei,nChan,nPairs,nIncohInt,nBlocks):
2526 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
3068 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
2527 #import matplotlib.pyplot as plt
3069 #import matplotlib.pyplot as plt
2528 #for k in range(149):
3070 #for k in range(149):
2529
3071
2530 # self.bloque0[:,:,:,k] = spectra[:,:,0:nHei]
3072 # self.bloque0[:,:,:,k] = spectra[:,:,0:nHei]
2531 # self.bloques[:,:,:,k] = cspectra[:,:,0:nHei]
3073 # self.bloques[:,:,:,k] = cspectra[:,:,0:nHei]
2532 #if self.i==nBlocks:
3074 #if self.i==nBlocks:
2533 # self.i==0
3075 # self.i==0
2534 rfunc = cspectra.copy() #self.bloques
3076 rfunc = cspectra.copy() #self.bloques
2535 n_funct = len(rfunc[0,:,0,0])
3077 n_funct = len(rfunc[0,:,0,0])
2536 val_spc = spectra*0.0 #self.bloque0*0.0
3078 val_spc = spectra*0.0 #self.bloque0*0.0
2537 val_cspc = cspectra*0.0 #self.bloques*0.0
3079 val_cspc = cspectra*0.0 #self.bloques*0.0
2538 in_sat_spectra = spectra.copy() #self.bloque0
3080 in_sat_spectra = spectra.copy() #self.bloque0
2539 in_sat_cspectra = cspectra.copy() #self.bloques
3081 in_sat_cspectra = cspectra.copy() #self.bloques
2540
3082
2541 #print( rfunc.shape)
3083 #print( rfunc.shape)
2542 min_hei = 200
3084 min_hei = 200
2543 nProf = dataOut.nProfiles
3085 nProf = dataOut.nProfiles
2544 heights = dataOut.heightList
3086 heights = dataOut.heightList
2545 nHei = len(heights)
3087 nHei = len(heights)
2546 channels = dataOut.channelList
3088 channels = dataOut.channelList
2547 nChan = len(channels)
3089 nChan = len(channels)
2548 crosspairs = dataOut.groupList
3090 crosspairs = dataOut.groupList
2549 nPairs = len(crosspairs)
3091 nPairs = len(crosspairs)
2550 hval=(heights >= min_hei).nonzero()
3092 hval=(heights >= min_hei).nonzero()
2551 ih=hval[0]
3093 ih=hval[0]
2552 #print numpy.absolute(rfunc[:,0,0,14])
3094 #print numpy.absolute(rfunc[:,0,0,14])
2553 for ih in range(hval[0][0],nHei):
3095 for ih in range(hval[0][0],nHei):
2554 for ifreq in range(nProf):
3096 for ifreq in range(nProf):
2555 for ii in range(n_funct):
3097 for ii in range(n_funct):
2556
3098
2557 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
3099 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
2558 #print numpy.amin(func2clean)
3100 #print numpy.amin(func2clean)
2559 val = (numpy.isfinite(func2clean)==True).nonzero()
3101 val = (numpy.isfinite(func2clean)==True).nonzero()
2560 if len(val)>0:
3102 if len(val)>0:
2561 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
3103 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
2562 if min_val <= -40 : min_val = -40
3104 if min_val <= -40 : min_val = -40
2563 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
3105 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
2564 if max_val >= 200 : max_val = 200
3106 if max_val >= 200 : max_val = 200
2565 #print min_val, max_val
3107 #print min_val, max_val
2566 step = 1
3108 step = 1
2567 #Getting bins and the histogram
3109 #Getting bins and the histogram
2568 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
3110 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
2569 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
3111 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
2570 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
3112 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
2571 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
3113 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
2572 parg = [numpy.amax(y_dist),mean,sigma]
3114 parg = [numpy.amax(y_dist),mean,sigma]
2573 try :
3115 try :
2574 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
3116 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
2575 mode = gauss_fit[1]
3117 mode = gauss_fit[1]
2576 stdv = gauss_fit[2]
3118 stdv = gauss_fit[2]
2577 except:
3119 except:
2578 mode = mean
3120 mode = mean
2579 stdv = sigma
3121 stdv = sigma
2580 # if ih == 14 and ii == 0 and ifreq ==0 :
3122 # if ih == 14 and ii == 0 and ifreq ==0 :
2581 # print x_dist.shape, y_dist.shape
3123 # print x_dist.shape, y_dist.shape
2582 # print x_dist, y_dist
3124 # print x_dist, y_dist
2583 # print min_val, max_val, binstep
3125 # print min_val, max_val, binstep
2584 # print func2clean
3126 # print func2clean
2585 # print mean,sigma
3127 # print mean,sigma
2586 # mean1,std = norm.fit(y_dist)
3128 # mean1,std = norm.fit(y_dist)
2587 # print mean1, std, gauss_fit
3129 # print mean1, std, gauss_fit
2588 # print fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
3130 # print fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
2589 # 7.84616 53.9307 3.61863
3131 # 7.84616 53.9307 3.61863
2590 #stdv = 3.61863 # 2.99089
3132 #stdv = 3.61863 # 2.99089
2591 #mode = 53.9307 #7.79008
3133 #mode = 53.9307 #7.79008
2592
3134
2593 #Removing echoes greater than mode + 3*stdv
3135 #Removing echoes greater than mode + 3*stdv
2594 factor_stdv = 2.5
3136 factor_stdv = 2.5
2595 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
3137 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
2596
3138
2597 if len(noval[0]) > 0:
3139 if len(noval[0]) > 0:
2598 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
3140 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
2599 cross_pairs = crosspairs[ii]
3141 cross_pairs = crosspairs[ii]
2600 #Getting coherent echoes which are removed.
3142 #Getting coherent echoes which are removed.
2601 if len(novall[0]) > 0:
3143 if len(novall[0]) > 0:
2602 #val_spc[(0,1),novall[a],ih] = 1
3144 #val_spc[(0,1),novall[a],ih] = 1
2603 #val_spc[,(2,3),novall[a],ih] = 1
3145 #val_spc[,(2,3),novall[a],ih] = 1
2604 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
3146 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
2605 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
3147 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
2606 val_cspc[novall[0],ii,ifreq,ih] = 1
3148 val_cspc[novall[0],ii,ifreq,ih] = 1
2607 #print("OUT NOVALL 1")
3149 #print("OUT NOVALL 1")
2608 #Removing coherent from ISR data
3150 #Removing coherent from ISR data
2609 # if ih == 17 and ii == 0 and ifreq ==0 :
3151 # if ih == 17 and ii == 0 and ifreq ==0 :
2610 # print spectra[:,cross_pairs[0],ifreq,ih]
3152 # print spectra[:,cross_pairs[0],ifreq,ih]
2611 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
3153 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
2612 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
3154 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
2613 cspectra[noval,ii,ifreq,ih] = numpy.nan
3155 cspectra[noval,ii,ifreq,ih] = numpy.nan
2614 # if ih == 17 and ii == 0 and ifreq ==0 :
3156 # if ih == 17 and ii == 0 and ifreq ==0 :
2615 # print spectra[:,cross_pairs[0],ifreq,ih]
3157 # print spectra[:,cross_pairs[0],ifreq,ih]
2616 # print noval, len(noval[0])
3158 # print noval, len(noval[0])
2617 # print novall, len(novall[0])
3159 # print novall, len(novall[0])
2618 # print factor_stdv*stdv
3160 # print factor_stdv*stdv
2619 # print func2clean-mode
3161 # print func2clean-mode
2620 # print val_spc[:,cross_pairs[0],ifreq,ih]
3162 # print val_spc[:,cross_pairs[0],ifreq,ih]
2621 # print spectra[:,cross_pairs[0],ifreq,ih]
3163 # print spectra[:,cross_pairs[0],ifreq,ih]
2622 #no sale es para savedrifts >2
3164 #no sale es para savedrifts >2
2623 ''' channels = channels
3165 ''' channels = channels
2624 cross_pairs = cross_pairs
3166 cross_pairs = cross_pairs
2625 #print("OUT NOVALL 2")
3167 #print("OUT NOVALL 2")
2626
3168
2627 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
3169 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
2628 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
3170 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
2629 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
3171 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
2630 #print('vcros =', vcross)
3172 #print('vcros =', vcross)
2631
3173
2632 #Getting coherent echoes which are removed.
3174 #Getting coherent echoes which are removed.
2633 if len(novall) > 0:
3175 if len(novall) > 0:
2634 #val_spc[novall,ii,ifreq,ih] = 1
3176 #val_spc[novall,ii,ifreq,ih] = 1
2635 val_spc[ii,ifreq,ih,novall] = 1
3177 val_spc[ii,ifreq,ih,novall] = 1
2636 if len(vcross) > 0:
3178 if len(vcross) > 0:
2637 val_cspc[vcross,ifreq,ih,novall] = 1
3179 val_cspc[vcross,ifreq,ih,novall] = 1
2638
3180
2639 #Removing coherent from ISR data.
3181 #Removing coherent from ISR data.
2640 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
3182 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
2641 if len(vcross) > 0:
3183 if len(vcross) > 0:
2642 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
3184 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
2643 '''
3185 '''
2644 #Getting average of the spectra and cross-spectra from incoherent echoes.
3186 #Getting average of the spectra and cross-spectra from incoherent echoes.
2645 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
3187 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
2646 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
3188 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
2647 for ih in range(nHei):
3189 for ih in range(nHei):
2648 for ifreq in range(nProf):
3190 for ifreq in range(nProf):
2649 for ich in range(nChan):
3191 for ich in range(nChan):
2650 tmp = spectra[:,ich,ifreq,ih]
3192 tmp = spectra[:,ich,ifreq,ih]
2651 valid = (numpy.isfinite(tmp[:])==True).nonzero()
3193 valid = (numpy.isfinite(tmp[:])==True).nonzero()
2652 # if ich == 0 and ifreq == 0 and ih == 17 :
3194 # if ich == 0 and ifreq == 0 and ih == 17 :
2653 # print tmp
3195 # print tmp
2654 # print valid
3196 # print valid
2655 # print len(valid[0])
3197 # print len(valid[0])
2656 #print('TMP',tmp)
3198 #print('TMP',tmp)
2657 if len(valid[0]) >0 :
3199 if len(valid[0]) >0 :
2658 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3200 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2659 #for icr in range(nPairs):
3201 #for icr in range(nPairs):
2660 for icr in range(nPairs):
3202 for icr in range(nPairs):
2661 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
3203 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
2662 valid = (numpy.isfinite(tmp)==True).nonzero()
3204 valid = (numpy.isfinite(tmp)==True).nonzero()
2663 if len(valid[0]) > 0:
3205 if len(valid[0]) > 0:
2664 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3206 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2665 # print('##########################################################')
3207 # print('##########################################################')
2666 #Removing fake coherent echoes (at least 4 points around the point)
3208 #Removing fake coherent echoes (at least 4 points around the point)
2667
3209
2668 val_spectra = numpy.sum(val_spc,0)
3210 val_spectra = numpy.sum(val_spc,0)
2669 val_cspectra = numpy.sum(val_cspc,0)
3211 val_cspectra = numpy.sum(val_cspc,0)
2670
3212
2671 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
3213 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
2672 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
3214 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
2673
3215
2674 for i in range(nChan):
3216 for i in range(nChan):
2675 for j in range(nProf):
3217 for j in range(nProf):
2676 for k in range(nHei):
3218 for k in range(nHei):
2677 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
3219 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
2678 val_spc[:,i,j,k] = 0.0
3220 val_spc[:,i,j,k] = 0.0
2679 for i in range(nPairs):
3221 for i in range(nPairs):
2680 for j in range(nProf):
3222 for j in range(nProf):
2681 for k in range(nHei):
3223 for k in range(nHei):
2682 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
3224 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
2683 val_cspc[:,i,j,k] = 0.0
3225 val_cspc[:,i,j,k] = 0.0
2684 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHei*nChan))
3226 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHei*nChan))
2685 # if numpy.isfinite(val_spectra)==str(True):
3227 # if numpy.isfinite(val_spectra)==str(True):
2686 # noval = (val_spectra<1).nonzero()
3228 # noval = (val_spectra<1).nonzero()
2687 # if len(noval) > 0:
3229 # if len(noval) > 0:
2688 # val_spc[:,noval] = 0.0
3230 # val_spc[:,noval] = 0.0
2689 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHei))
3231 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHei))
2690
3232
2691 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHei*nProf))
3233 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHei*nProf))
2692 #if numpy.isfinite(val_cspectra)==str(True):
3234 #if numpy.isfinite(val_cspectra)==str(True):
2693 # noval = (val_cspectra<1).nonzero()
3235 # noval = (val_cspectra<1).nonzero()
2694 # if len(noval) > 0:
3236 # if len(noval) > 0:
2695 # val_cspc[:,noval] = 0.0
3237 # val_cspc[:,noval] = 0.0
2696 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHei))
3238 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHei))
2697
3239
2698 tmp_sat_spectra = spectra.copy()
3240 tmp_sat_spectra = spectra.copy()
2699 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
3241 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
2700 tmp_sat_cspectra = cspectra.copy()
3242 tmp_sat_cspectra = cspectra.copy()
2701 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
3243 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
2702
3244
2703 # fig = plt.figure(figsize=(6,5))
3245 # fig = plt.figure(figsize=(6,5))
2704 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
3246 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2705 # ax = fig.add_axes([left, bottom, width, height])
3247 # ax = fig.add_axes([left, bottom, width, height])
2706 # cp = ax.contour(10*numpy.log10(numpy.absolute(spectra[0,0,:,:])))
3248 # cp = ax.contour(10*numpy.log10(numpy.absolute(spectra[0,0,:,:])))
2707 # ax.clabel(cp, inline=True,fontsize=10)
3249 # ax.clabel(cp, inline=True,fontsize=10)
2708 # plt.show()
3250 # plt.show()
2709
3251
2710 val = (val_spc > 0).nonzero()
3252 val = (val_spc > 0).nonzero()
2711 if len(val[0]) > 0:
3253 if len(val[0]) > 0:
2712 tmp_sat_spectra[val] = in_sat_spectra[val]
3254 tmp_sat_spectra[val] = in_sat_spectra[val]
2713
3255
2714 val = (val_cspc > 0).nonzero()
3256 val = (val_cspc > 0).nonzero()
2715 if len(val[0]) > 0:
3257 if len(val[0]) > 0:
2716 tmp_sat_cspectra[val] = in_sat_cspectra[val]
3258 tmp_sat_cspectra[val] = in_sat_cspectra[val]
2717
3259
2718 #Getting average of the spectra and cross-spectra from incoherent echoes.
3260 #Getting average of the spectra and cross-spectra from incoherent echoes.
2719 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
3261 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
2720 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
3262 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
2721 for ih in range(nHei):
3263 for ih in range(nHei):
2722 for ifreq in range(nProf):
3264 for ifreq in range(nProf):
2723 for ich in range(nChan):
3265 for ich in range(nChan):
2724 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
3266 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
2725 valid = (numpy.isfinite(tmp)).nonzero()
3267 valid = (numpy.isfinite(tmp)).nonzero()
2726 if len(valid[0]) > 0:
3268 if len(valid[0]) > 0:
2727 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3269 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2728
3270
2729 for icr in range(nPairs):
3271 for icr in range(nPairs):
2730 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
3272 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
2731 valid = (numpy.isfinite(tmp)).nonzero()
3273 valid = (numpy.isfinite(tmp)).nonzero()
2732 if len(valid[0]) > 0:
3274 if len(valid[0]) > 0:
2733 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3275 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2734 #self.__dataReady= True
3276 #self.__dataReady= True
2735 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
3277 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
2736 #if not self.__dataReady:
3278 #if not self.__dataReady:
2737 #return None, None
3279 #return None, None
2738 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
3280 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
2739 def REM_ISOLATED_POINTS(self,array,rth):
3281 def REM_ISOLATED_POINTS(self,array,rth):
2740 # import matplotlib.pyplot as plt
3282 # import matplotlib.pyplot as plt
2741 if rth == None : rth = 4
3283 if rth == None : rth = 4
2742
3284
2743 num_prof = len(array[0,:,0])
3285 num_prof = len(array[0,:,0])
2744 num_hei = len(array[0,0,:])
3286 num_hei = len(array[0,0,:])
2745 n2d = len(array[:,0,0])
3287 n2d = len(array[:,0,0])
2746
3288
2747 for ii in range(n2d) :
3289 for ii in range(n2d) :
2748 #print ii,n2d
3290 #print ii,n2d
2749 tmp = array[ii,:,:]
3291 tmp = array[ii,:,:]
2750 #print tmp.shape, array[ii,101,:],array[ii,102,:]
3292 #print tmp.shape, array[ii,101,:],array[ii,102,:]
2751
3293
2752 # fig = plt.figure(figsize=(6,5))
3294 # fig = plt.figure(figsize=(6,5))
2753 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
3295 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2754 # ax = fig.add_axes([left, bottom, width, height])
3296 # ax = fig.add_axes([left, bottom, width, height])
2755 # x = range(num_prof)
3297 # x = range(num_prof)
2756 # y = range(num_hei)
3298 # y = range(num_hei)
2757 # cp = ax.contour(y,x,tmp)
3299 # cp = ax.contour(y,x,tmp)
2758 # ax.clabel(cp, inline=True,fontsize=10)
3300 # ax.clabel(cp, inline=True,fontsize=10)
2759 # plt.show()
3301 # plt.show()
2760
3302
2761 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
3303 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
2762 tmp = numpy.reshape(tmp,num_prof*num_hei)
3304 tmp = numpy.reshape(tmp,num_prof*num_hei)
2763 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
3305 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
2764 indxs2 = (tmp > 0).nonzero()
3306 indxs2 = (tmp > 0).nonzero()
2765
3307
2766 indxs1 = (indxs1[0])
3308 indxs1 = (indxs1[0])
2767 indxs2 = indxs2[0]
3309 indxs2 = indxs2[0]
2768 #indxs1 = numpy.array(indxs1[0])
3310 #indxs1 = numpy.array(indxs1[0])
2769 #indxs2 = numpy.array(indxs2[0])
3311 #indxs2 = numpy.array(indxs2[0])
2770 indxs = None
3312 indxs = None
2771 #print indxs1 , indxs2
3313 #print indxs1 , indxs2
2772 for iv in range(len(indxs2)):
3314 for iv in range(len(indxs2)):
2773 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
3315 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
2774 #print len(indxs2), indv
3316 #print len(indxs2), indv
2775 if len(indv[0]) > 0 :
3317 if len(indv[0]) > 0 :
2776 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
3318 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
2777 # print indxs
3319 # print indxs
2778 indxs = indxs[1:]
3320 indxs = indxs[1:]
2779 #print indxs, len(indxs)
3321 #print indxs, len(indxs)
2780 if len(indxs) < 4 :
3322 if len(indxs) < 4 :
2781 array[ii,:,:] = 0.
3323 array[ii,:,:] = 0.
2782 return
3324 return
2783
3325
2784 xpos = numpy.mod(indxs ,num_hei)
3326 xpos = numpy.mod(indxs ,num_hei)
2785 ypos = (indxs / num_hei)
3327 ypos = (indxs / num_hei)
2786 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
3328 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
2787 #print sx
3329 #print sx
2788 xpos = xpos[sx]
3330 xpos = xpos[sx]
2789 ypos = ypos[sx]
3331 ypos = ypos[sx]
2790
3332
2791 # *********************************** Cleaning isolated points **********************************
3333 # *********************************** Cleaning isolated points **********************************
2792 ic = 0
3334 ic = 0
2793 while True :
3335 while True :
2794 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
3336 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
2795 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
3337 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
2796 #plt.plot(r)
3338 #plt.plot(r)
2797 #plt.show()
3339 #plt.show()
2798 no_coh1 = (numpy.isfinite(r)==True).nonzero()
3340 no_coh1 = (numpy.isfinite(r)==True).nonzero()
2799 no_coh2 = (r <= rth).nonzero()
3341 no_coh2 = (r <= rth).nonzero()
2800 #print r, no_coh1, no_coh2
3342 #print r, no_coh1, no_coh2
2801 no_coh1 = numpy.array(no_coh1[0])
3343 no_coh1 = numpy.array(no_coh1[0])
2802 no_coh2 = numpy.array(no_coh2[0])
3344 no_coh2 = numpy.array(no_coh2[0])
2803 no_coh = None
3345 no_coh = None
2804 #print valid1 , valid2
3346 #print valid1 , valid2
2805 for iv in range(len(no_coh2)):
3347 for iv in range(len(no_coh2)):
2806 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
3348 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
2807 if len(indv[0]) > 0 :
3349 if len(indv[0]) > 0 :
2808 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
3350 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
2809 no_coh = no_coh[1:]
3351 no_coh = no_coh[1:]
2810 #print len(no_coh), no_coh
3352 #print len(no_coh), no_coh
2811 if len(no_coh) < 4 :
3353 if len(no_coh) < 4 :
2812 #print xpos[ic], ypos[ic], ic
3354 #print xpos[ic], ypos[ic], ic
2813 # plt.plot(r)
3355 # plt.plot(r)
2814 # plt.show()
3356 # plt.show()
2815 xpos[ic] = numpy.nan
3357 xpos[ic] = numpy.nan
2816 ypos[ic] = numpy.nan
3358 ypos[ic] = numpy.nan
2817
3359
2818 ic = ic + 1
3360 ic = ic + 1
2819 if (ic == len(indxs)) :
3361 if (ic == len(indxs)) :
2820 break
3362 break
2821 #print( xpos, ypos)
3363 #print( xpos, ypos)
2822
3364
2823 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
3365 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
2824 #print indxs[0]
3366 #print indxs[0]
2825 if len(indxs[0]) < 4 :
3367 if len(indxs[0]) < 4 :
2826 array[ii,:,:] = 0.
3368 array[ii,:,:] = 0.
2827 return
3369 return
2828
3370
2829 xpos = xpos[indxs[0]]
3371 xpos = xpos[indxs[0]]
2830 ypos = ypos[indxs[0]]
3372 ypos = ypos[indxs[0]]
2831 for i in range(0,len(ypos)):
3373 for i in range(0,len(ypos)):
2832 ypos[i]=int(ypos[i])
3374 ypos[i]=int(ypos[i])
2833 junk = tmp
3375 junk = tmp
2834 tmp = junk*0.0
3376 tmp = junk*0.0
2835
3377
2836 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
3378 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
2837 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
3379 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
2838
3380
2839 #print array.shape
3381 #print array.shape
2840 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
3382 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
2841 #print tmp.shape
3383 #print tmp.shape
2842
3384
2843 # fig = plt.figure(figsize=(6,5))
3385 # fig = plt.figure(figsize=(6,5))
2844 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
3386 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2845 # ax = fig.add_axes([left, bottom, width, height])
3387 # ax = fig.add_axes([left, bottom, width, height])
2846 # x = range(num_prof)
3388 # x = range(num_prof)
2847 # y = range(num_hei)
3389 # y = range(num_hei)
2848 # cp = ax.contour(y,x,array[ii,:,:])
3390 # cp = ax.contour(y,x,array[ii,:,:])
2849 # ax.clabel(cp, inline=True,fontsize=10)
3391 # ax.clabel(cp, inline=True,fontsize=10)
2850 # plt.show()
3392 # plt.show()
2851 return array
3393 return array
2852 def moments(self,doppler,yarray,npoints):
3394 def moments(self,doppler,yarray,npoints):
2853 ytemp = yarray
3395 ytemp = yarray
2854 #val = WHERE(ytemp GT 0,cval)
3396 #val = WHERE(ytemp GT 0,cval)
2855 #if cval == 0 : val = range(npoints-1)
3397 #if cval == 0 : val = range(npoints-1)
2856 val = (ytemp > 0).nonzero()
3398 val = (ytemp > 0).nonzero()
2857 val = val[0]
3399 val = val[0]
2858 #print('hvalid:',hvalid)
3400 #print('hvalid:',hvalid)
2859 #print('valid', valid)
3401 #print('valid', valid)
2860 if len(val) == 0 : val = range(npoints-1)
3402 if len(val) == 0 : val = range(npoints-1)
2861
3403
2862 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
3404 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
2863 ytemp[len(ytemp):] = [ynew]
3405 ytemp[len(ytemp):] = [ynew]
2864
3406
2865 index = 0
3407 index = 0
2866 index = numpy.argmax(ytemp)
3408 index = numpy.argmax(ytemp)
2867 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
3409 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
2868 ytemp = ytemp[0:npoints-1]
3410 ytemp = ytemp[0:npoints-1]
2869
3411
2870 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
3412 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
2871 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
3413 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
2872 return [fmom,numpy.sqrt(smom)]
3414 return [fmom,numpy.sqrt(smom)]
2873 # **********************************************************************************************
3415 # **********************************************************************************************
2874 index = 0
3416 index = 0
2875 fint = 0
3417 fint = 0
2876 buffer = 0
3418 buffer = 0
2877 buffer2 = 0
3419 buffer2 = 0
2878 buffer3 = 0
3420 buffer3 = 0
2879 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
3421 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
2880 nChannels = dataOut.nChannels
3422 nChannels = dataOut.nChannels
2881 nHeights= dataOut.heightList.size
3423 nHeights= dataOut.heightList.size
2882 nProf = dataOut.nProfiles
3424 nProf = dataOut.nProfiles
2883 tini=time.localtime(dataOut.utctime)
3425 tini=time.localtime(dataOut.utctime)
2884 if (tini.tm_min % 5) == 0 and (tini.tm_sec < 5 and self.fint==0):
3426 if (tini.tm_min % 5) == 0 and (tini.tm_sec < 5 and self.fint==0):
2885 # print tini.tm_min
3427 # print tini.tm_min
2886 self.index = 0
3428 self.index = 0
2887 jspc = self.buffer
3429 jspc = self.buffer
2888 jcspc = self.buffer2
3430 jcspc = self.buffer2
2889 jnoise = self.buffer3
3431 jnoise = self.buffer3
2890 self.buffer = dataOut.data_spc
3432 self.buffer = dataOut.data_spc
2891 self.buffer2 = dataOut.data_cspc
3433 self.buffer2 = dataOut.data_cspc
2892 self.buffer3 = dataOut.noise
3434 self.buffer3 = dataOut.noise
2893 self.fint = 1
3435 self.fint = 1
2894 if numpy.any(jspc) :
3436 if numpy.any(jspc) :
2895 jspc= numpy.reshape(jspc,(int(len(jspc)/4),nChannels,nProf,nHeights))
3437 jspc= numpy.reshape(jspc,(int(len(jspc)/4),nChannels,nProf,nHeights))
2896 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/2),2,nProf,nHeights))
3438 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/2),2,nProf,nHeights))
2897 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/4),nChannels))
3439 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/4),nChannels))
2898 else:
3440 else:
2899 dataOut.flagNoData = True
3441 dataOut.flagNoData = True
2900 return dataOut
3442 return dataOut
2901 else :
3443 else :
2902 if (tini.tm_min % 5) == 0 : self.fint = 1
3444 if (tini.tm_min % 5) == 0 : self.fint = 1
2903 else : self.fint = 0
3445 else : self.fint = 0
2904 self.index += 1
3446 self.index += 1
2905 if numpy.any(self.buffer):
3447 if numpy.any(self.buffer):
2906 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
3448 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
2907 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
3449 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
2908 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
3450 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
2909 else:
3451 else:
2910 self.buffer = dataOut.data_spc
3452 self.buffer = dataOut.data_spc
2911 self.buffer2 = dataOut.data_cspc
3453 self.buffer2 = dataOut.data_cspc
2912 self.buffer3 = dataOut.noise
3454 self.buffer3 = dataOut.noise
2913 dataOut.flagNoData = True
3455 dataOut.flagNoData = True
2914 return dataOut
3456 return dataOut
2915 if path != None:
3457 if path != None:
2916 sys.path.append(path)
3458 sys.path.append(path)
2917 self.library = importlib.import_module(file)
3459 self.library = importlib.import_module(file)
2918
3460
2919 #To be inserted as a parameter
3461 #To be inserted as a parameter
2920 groupArray = numpy.array(groupList)
3462 groupArray = numpy.array(groupList)
2921 #groupArray = numpy.array([[0,1],[2,3]])
3463 #groupArray = numpy.array([[0,1],[2,3]])
2922 dataOut.groupList = groupArray
3464 dataOut.groupList = groupArray
2923
3465
2924 nGroups = groupArray.shape[0]
3466 nGroups = groupArray.shape[0]
2925 nChannels = dataOut.nChannels
3467 nChannels = dataOut.nChannels
2926 nHeights = dataOut.heightList.size
3468 nHeights = dataOut.heightList.size
2927
3469
2928 #Parameters Array
3470 #Parameters Array
2929 dataOut.data_param = None
3471 dataOut.data_param = None
2930 dataOut.data_paramC = None
3472 dataOut.data_paramC = None
2931
3473
2932 #Set constants
3474 #Set constants
2933 constants = self.library.setConstants(dataOut)
3475 constants = self.library.setConstants(dataOut)
2934 dataOut.constants = constants
3476 dataOut.constants = constants
2935 M = dataOut.normFactor
3477 M = dataOut.normFactor
2936 N = dataOut.nFFTPoints
3478 N = dataOut.nFFTPoints
2937 ippSeconds = dataOut.ippSeconds
3479 ippSeconds = dataOut.ippSeconds
2938 K = dataOut.nIncohInt
3480 K = dataOut.nIncohInt
2939 pairsArray = numpy.array(dataOut.pairsList)
3481 pairsArray = numpy.array(dataOut.pairsList)
2940
3482
2941 snrth= 20
3483 snrth= 20
2942 spectra = dataOut.data_spc
3484 spectra = dataOut.data_spc
2943 cspectra = dataOut.data_cspc
3485 cspectra = dataOut.data_cspc
2944 nProf = dataOut.nProfiles
3486 nProf = dataOut.nProfiles
2945 heights = dataOut.heightList
3487 heights = dataOut.heightList
2946 nHei = len(heights)
3488 nHei = len(heights)
2947 channels = dataOut.channelList
3489 channels = dataOut.channelList
2948 nChan = len(channels)
3490 nChan = len(channels)
2949 nIncohInt = dataOut.nIncohInt
3491 nIncohInt = dataOut.nIncohInt
2950 crosspairs = dataOut.groupList
3492 crosspairs = dataOut.groupList
2951 noise = dataOut.noise
3493 noise = dataOut.noise
2952 jnoise = jnoise/N
3494 jnoise = jnoise/N
2953 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
3495 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
2954 power = numpy.sum(spectra, axis=1)
3496 power = numpy.sum(spectra, axis=1)
2955 nPairs = len(crosspairs)
3497 nPairs = len(crosspairs)
2956 absc = dataOut.abscissaList[:-1]
3498 absc = dataOut.abscissaList[:-1]
2957
3499
2958 if not self.isConfig:
3500 if not self.isConfig:
2959 self.isConfig = True
3501 self.isConfig = True
2960
3502
2961 index = tini.tm_hour*12+tini.tm_min/5
3503 index = tini.tm_hour*12+tini.tm_min/5
2962 jspc = jspc/N/N
3504 jspc = jspc/N/N
2963 jcspc = jcspc/N/N
3505 jcspc = jcspc/N/N
2964 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
3506 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
2965 jspectra = tmp_spectra*len(jspc[:,0,0,0])
3507 jspectra = tmp_spectra*len(jspc[:,0,0,0])
2966 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
3508 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
2967 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)
3509 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)
2968 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
3510 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
2969 dataOut.data_spc = incoh_spectra
3511 dataOut.data_spc = incoh_spectra
2970 dataOut.data_cspc = incoh_cspectra
3512 dataOut.data_cspc = incoh_cspectra
2971
3513
2972 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
3514 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
2973 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
3515 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
2974 #List of possible combinations
3516 #List of possible combinations
2975 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
3517 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
2976 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
3518 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
2977
3519
2978 if getSNR:
3520 if getSNR:
2979 listChannels = groupArray.reshape((groupArray.size))
3521 listChannels = groupArray.reshape((groupArray.size))
2980 listChannels.sort()
3522 listChannels.sort()
2981 dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
3523 dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
2982 if dataOut.data_paramC is None:
3524 if dataOut.data_paramC is None:
2983 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
3525 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
2984 for i in range(nGroups):
3526 for i in range(nGroups):
2985 coord = groupArray[i,:]
3527 coord = groupArray[i,:]
2986 #Input data array
3528 #Input data array
2987 data = dataOut.data_spc[coord,:,:]/(M*N)
3529 data = dataOut.data_spc[coord,:,:]/(M*N)
2988 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
3530 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
2989
3531
2990 #Cross Spectra data array for Covariance Matrixes
3532 #Cross Spectra data array for Covariance Matrixes
2991 ind = 0
3533 ind = 0
2992 for pairs in listComb:
3534 for pairs in listComb:
2993 pairsSel = numpy.array([coord[x],coord[y]])
3535 pairsSel = numpy.array([coord[x],coord[y]])
2994 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
3536 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
2995 ind += 1
3537 ind += 1
2996 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
3538 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
2997 dataCross = dataCross**2
3539 dataCross = dataCross**2
2998 nhei = nHeights
3540 nhei = nHeights
2999 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
3541 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
3000 if i == 0 : my_noises = numpy.zeros(4,dtype=float) #FLTARR(4)
3542 if i == 0 : my_noises = numpy.zeros(4,dtype=float) #FLTARR(4)
3001 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
3543 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
3002 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
3544 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
3003 n0 = n0i
3545 n0 = n0i
3004 n1= n1i
3546 n1= n1i
3005 my_noises[2*i+0] = n0
3547 my_noises[2*i+0] = n0
3006 my_noises[2*i+1] = n1
3548 my_noises[2*i+1] = n1
3007 snrth = -16.0
3549 snrth = -16.0
3008 snrth = 10**(snrth/10.0)
3550 snrth = 10**(snrth/10.0)
3009
3551
3010 for h in range(nHeights):
3552 for h in range(nHeights):
3011 d = data[:,h]
3553 d = data[:,h]
3012 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
3554 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
3013 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
3555 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
3014 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
3556 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
3015 signal0 = signalpn0-n0
3557 signal0 = signalpn0-n0
3016 signal1 = signalpn1-n1
3558 signal1 = signalpn1-n1
3017 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3559 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3018 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3560 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3019 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
3561 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
3020 #Covariance Matrix
3562 #Covariance Matrix
3021 D = numpy.diag(d**2)
3563 D = numpy.diag(d**2)
3022 ind = 0
3564 ind = 0
3023 for pairs in listComb:
3565 for pairs in listComb:
3024 #Coordinates in Covariance Matrix
3566 #Coordinates in Covariance Matrix
3025 x = pairs[0]
3567 x = pairs[0]
3026 y = pairs[1]
3568 y = pairs[1]
3027 #Channel Index
3569 #Channel Index
3028 S12 = dataCross[ind,:,h]
3570 S12 = dataCross[ind,:,h]
3029 D12 = numpy.diag(S12)
3571 D12 = numpy.diag(S12)
3030 #Completing Covariance Matrix with Cross Spectras
3572 #Completing Covariance Matrix with Cross Spectras
3031 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
3573 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
3032 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
3574 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
3033 ind += 1
3575 ind += 1
3034 diagD = numpy.zeros(256)
3576 diagD = numpy.zeros(256)
3035 if h == 17 :
3577 if h == 17 :
3036 for ii in range(256): diagD[ii] = D[ii,ii]
3578 for ii in range(256): diagD[ii] = D[ii,ii]
3037 #Dinv=numpy.linalg.inv(D)
3579 #Dinv=numpy.linalg.inv(D)
3038 #L=numpy.linalg.cholesky(Dinv)
3580 #L=numpy.linalg.cholesky(Dinv)
3039 try:
3581 try:
3040 Dinv=numpy.linalg.inv(D)
3582 Dinv=numpy.linalg.inv(D)
3041 L=numpy.linalg.cholesky(Dinv)
3583 L=numpy.linalg.cholesky(Dinv)
3042 except:
3584 except:
3043 Dinv = D*numpy.nan
3585 Dinv = D*numpy.nan
3044 L= D*numpy.nan
3586 L= D*numpy.nan
3045 LT=L.T
3587 LT=L.T
3046
3588
3047 dp = numpy.dot(LT,d)
3589 dp = numpy.dot(LT,d)
3048
3590
3049 #Initial values
3591 #Initial values
3050 data_spc = dataOut.data_spc[coord,:,h]
3592 data_spc = dataOut.data_spc[coord,:,h]
3051
3593
3052 if (h>0)and(error1[3]<5):
3594 if (h>0)and(error1[3]<5):
3053 p0 = dataOut.data_param[i,:,h-1]
3595 p0 = dataOut.data_param[i,:,h-1]
3054 else:
3596 else:
3055 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))# sin el i(data_spc, constants, i)
3597 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))# sin el i(data_spc, constants, i)
3056 try:
3598 try:
3057 #Least Squares
3599 #Least Squares
3058 #print (dp,LT,constants)
3600 #print (dp,LT,constants)
3059 #value =self.__residFunction(p0,dp,LT,constants)
3601 #value =self.__residFunction(p0,dp,LT,constants)
3060 #print ("valueREADY",value.shape, type(value))
3602 #print ("valueREADY",value.shape, type(value))
3061 #optimize.leastsq(value)
3603 #optimize.leastsq(value)
3062 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
3604 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
3063 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
3605 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
3064 #Chi square error
3606 #Chi square error
3065 #print(minp,covp.infodict,mesg,ier)
3607 #print(minp,covp.infodict,mesg,ier)
3066 #print("REALIZA OPTIMIZ")
3608 #print("REALIZA OPTIMIZ")
3067 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
3609 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
3068 #Error with Jacobian
3610 #Error with Jacobian
3069 error1 = self.library.errorFunction(minp,constants,LT)
3611 error1 = self.library.errorFunction(minp,constants,LT)
3070 # print self.__residFunction(p0,dp,LT, constants)
3612 # print self.__residFunction(p0,dp,LT, constants)
3071 # print infodict['fvec']
3613 # print infodict['fvec']
3072 # print self.__residFunction(minp,dp,LT,constants)
3614 # print self.__residFunction(minp,dp,LT,constants)
3073
3615
3074 except:
3616 except:
3075 minp = p0*numpy.nan
3617 minp = p0*numpy.nan
3076 error0 = numpy.nan
3618 error0 = numpy.nan
3077 error1 = p0*numpy.nan
3619 error1 = p0*numpy.nan
3078 #print ("EXCEPT 0000000000")
3620 #print ("EXCEPT 0000000000")
3079 # s_sq = (self.__residFunction(minp,dp,LT,constants)).sum()/(len(dp)-len(p0))
3621 # s_sq = (self.__residFunction(minp,dp,LT,constants)).sum()/(len(dp)-len(p0))
3080 # covp = covp*s_sq
3622 # covp = covp*s_sq
3081 # #print("TRY___________________________________________1")
3623 # #print("TRY___________________________________________1")
3082 # error = []
3624 # error = []
3083 # for ip in range(len(minp)):
3625 # for ip in range(len(minp)):
3084 # try:
3626 # try:
3085 # error.append(numpy.absolute(covp[ip][ip])**0.5)
3627 # error.append(numpy.absolute(covp[ip][ip])**0.5)
3086 # except:
3628 # except:
3087 # error.append( 0.00 )
3629 # error.append( 0.00 )
3088 else :
3630 else :
3089 data_spc = dataOut.data_spc[coord,:,h]
3631 data_spc = dataOut.data_spc[coord,:,h]
3090 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
3632 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
3091 minp = p0*numpy.nan
3633 minp = p0*numpy.nan
3092 error0 = numpy.nan
3634 error0 = numpy.nan
3093 error1 = p0*numpy.nan
3635 error1 = p0*numpy.nan
3094 #Save
3636 #Save
3095 if dataOut.data_param is None:
3637 if dataOut.data_param is None:
3096 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
3638 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
3097 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
3639 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
3098
3640
3099 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
3641 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
3100 dataOut.data_param[i,:,h] = minp
3642 dataOut.data_param[i,:,h] = minp
3101
3643
3102 for ht in range(nHeights-1) :
3644 for ht in range(nHeights-1) :
3103 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
3645 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
3104 dataOut.data_paramC[4*i,ht,1] = smooth
3646 dataOut.data_paramC[4*i,ht,1] = smooth
3105 signalpn0 = (coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
3647 signalpn0 = (coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
3106 signalpn1 = (coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
3648 signalpn1 = (coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
3107
3649
3108 #val0 = WHERE(signalpn0 > 0,cval0)
3650 #val0 = WHERE(signalpn0 > 0,cval0)
3109 val0 = (signalpn0 > 0).nonzero()
3651 val0 = (signalpn0 > 0).nonzero()
3110 val0 = val0[0]
3652 val0 = val0[0]
3111 #print('hvalid:',hvalid)
3653 #print('hvalid:',hvalid)
3112 #print('valid', valid)
3654 #print('valid', valid)
3113 if len(val0) == 0 : val0_npoints = nProf
3655 if len(val0) == 0 : val0_npoints = nProf
3114 else : val0_npoints = len(val0)
3656 else : val0_npoints = len(val0)
3115
3657
3116 #val1 = WHERE(signalpn1 > 0,cval1)
3658 #val1 = WHERE(signalpn1 > 0,cval1)
3117 val1 = (signalpn1 > 0).nonzero()
3659 val1 = (signalpn1 > 0).nonzero()
3118 val1 = val1[0]
3660 val1 = val1[0]
3119 if len(val1) == 0 : val1_npoints = nProf
3661 if len(val1) == 0 : val1_npoints = nProf
3120 else : val1_npoints = len(val1)
3662 else : val1_npoints = len(val1)
3121
3663
3122 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
3664 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
3123 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
3665 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
3124
3666
3125 signal0 = (signalpn0-n0) # > 0
3667 signal0 = (signalpn0-n0) # > 0
3126 vali = (signal0 < 0).nonzero()
3668 vali = (signal0 < 0).nonzero()
3127 vali = vali[0]
3669 vali = vali[0]
3128 if len(vali) > 0 : signal0[vali] = 0
3670 if len(vali) > 0 : signal0[vali] = 0
3129 signal1 = (signalpn1-n1) #> 0
3671 signal1 = (signalpn1-n1) #> 0
3130 vali = (signal1 < 0).nonzero()
3672 vali = (signal1 < 0).nonzero()
3131 vali = vali[0]
3673 vali = vali[0]
3132 if len(vali) > 0 : signal1[vali] = 0
3674 if len(vali) > 0 : signal1[vali] = 0
3133 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3675 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3134 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3676 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3135 doppler = absc[1:]
3677 doppler = absc[1:]
3136 if snr0 >= snrth and snr1 >= snrth and smooth :
3678 if snr0 >= snrth and snr1 >= snrth and smooth :
3137 signalpn0_n0 = signalpn0
3679 signalpn0_n0 = signalpn0
3138 signalpn0_n0[val0] = signalpn0[val0] - n0
3680 signalpn0_n0[val0] = signalpn0[val0] - n0
3139 mom0 = self.moments(doppler,signalpn0-n0,nProf)
3681 mom0 = self.moments(doppler,signalpn0-n0,nProf)
3140 # sigtmp= numpy.transpose(numpy.tile(signalpn0, [4,1]))
3682 # sigtmp= numpy.transpose(numpy.tile(signalpn0, [4,1]))
3141 # momt= self.__calculateMoments( sigtmp, doppler , n0 )
3683 # momt= self.__calculateMoments( sigtmp, doppler , n0 )
3142 signalpn1_n1 = signalpn1
3684 signalpn1_n1 = signalpn1
3143 signalpn1_n1[val1] = signalpn1[val1] - n1
3685 signalpn1_n1[val1] = signalpn1[val1] - n1
3144 mom1 = self.moments(doppler,signalpn1_n1,nProf)
3686 mom1 = self.moments(doppler,signalpn1_n1,nProf)
3145 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
3687 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
3146 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
3688 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
3147 # if graph == 1 :
3689 # if graph == 1 :
3148 # window, 13
3690 # window, 13
3149 # plot,doppler,signalpn0
3691 # plot,doppler,signalpn0
3150 # oplot,doppler,signalpn1,linest=1
3692 # oplot,doppler,signalpn1,linest=1
3151 # oplot,mom0(0)*doppler/doppler,signalpn0
3693 # oplot,mom0(0)*doppler/doppler,signalpn0
3152 # oplot,mom1(0)*doppler/doppler,signalpn1
3694 # oplot,mom1(0)*doppler/doppler,signalpn1
3153 # print,interval/12.,beam,45+ht*15,snr0,snr1,mom0(0),mom1(0),mom0(1),mom1(1)
3695 # print,interval/12.,beam,45+ht*15,snr0,snr1,mom0(0),mom1(0),mom0(1),mom1(1)
3154 #ENDIF
3696 #ENDIF
3155 #ENDIF
3697 #ENDIF
3156 #ENDFOR End height
3698 #ENDFOR End height
3157
3699
3158 dataOut.data_spc = jspectra
3700 dataOut.data_spc = jspectra
3159 if getSNR:
3701 if getSNR:
3160 listChannels = groupArray.reshape((groupArray.size))
3702 listChannels = groupArray.reshape((groupArray.size))
3161 listChannels.sort()
3703 listChannels.sort()
3162
3704
3163 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels])
3705 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels])
3164 return dataOut
3706 return dataOut
3165
3707
3166 def __residFunction(self, p, dp, LT, constants):
3708 def __residFunction(self, p, dp, LT, constants):
3167
3709
3168 fm = self.library.modelFunction(p, constants)
3710 fm = self.library.modelFunction(p, constants)
3169 fmp=numpy.dot(LT,fm)
3711 fmp=numpy.dot(LT,fm)
3170 return dp-fmp
3712 return dp-fmp
3171
3713
3172 def __getSNR(self, z, noise):
3714 def __getSNR(self, z, noise):
3173
3715
3174 avg = numpy.average(z, axis=1)
3716 avg = numpy.average(z, axis=1)
3175 SNR = (avg.T-noise)/noise
3717 SNR = (avg.T-noise)/noise
3176 SNR = SNR.T
3718 SNR = SNR.T
3177 return SNR
3719 return SNR
3178
3720
3179 def __chisq(self, p, chindex, hindex):
3721 def __chisq(self, p, chindex, hindex):
3180 #similar to Resid but calculates CHI**2
3722 #similar to Resid but calculates CHI**2
3181 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
3723 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
3182 dp=numpy.dot(LT,d)
3724 dp=numpy.dot(LT,d)
3183 fmp=numpy.dot(LT,fm)
3725 fmp=numpy.dot(LT,fm)
3184 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
3726 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
3185 return chisq
3727 return chisq
3186
3728
3187 class WindProfiler(Operation):
3729 class WindProfiler(Operation):
3188
3730
3189 __isConfig = False
3731 __isConfig = False
3190
3732
3191 __initime = None
3733 __initime = None
3192 __lastdatatime = None
3734 __lastdatatime = None
3193 __integrationtime = None
3735 __integrationtime = None
3194
3736
3195 __buffer = None
3737 __buffer = None
3196
3738
3197 __dataReady = False
3739 __dataReady = False
3198
3740
3199 __firstdata = None
3741 __firstdata = None
3200
3742
3201 n = None
3743 n = None
3202
3744
3203 def __init__(self):
3745 def __init__(self):
3204 Operation.__init__(self)
3746 Operation.__init__(self)
3205
3747
3206 def __calculateCosDir(self, elev, azim):
3748 def __calculateCosDir(self, elev, azim):
3207 zen = (90 - elev)*numpy.pi/180
3749 zen = (90 - elev)*numpy.pi/180
3208 azim = azim*numpy.pi/180
3750 azim = azim*numpy.pi/180
3209 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
3751 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
3210 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
3752 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
3211
3753
3212 signX = numpy.sign(numpy.cos(azim))
3754 signX = numpy.sign(numpy.cos(azim))
3213 signY = numpy.sign(numpy.sin(azim))
3755 signY = numpy.sign(numpy.sin(azim))
3214
3756
3215 cosDirX = numpy.copysign(cosDirX, signX)
3757 cosDirX = numpy.copysign(cosDirX, signX)
3216 cosDirY = numpy.copysign(cosDirY, signY)
3758 cosDirY = numpy.copysign(cosDirY, signY)
3217 return cosDirX, cosDirY
3759 return cosDirX, cosDirY
3218
3760
3219 def __calculateAngles(self, theta_x, theta_y, azimuth):
3761 def __calculateAngles(self, theta_x, theta_y, azimuth):
3220
3762
3221 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
3763 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
3222 zenith_arr = numpy.arccos(dir_cosw)
3764 zenith_arr = numpy.arccos(dir_cosw)
3223 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
3765 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
3224
3766
3225 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
3767 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
3226 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
3768 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
3227
3769
3228 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
3770 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
3229
3771
3230 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
3772 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
3231
3773
3232 if horOnly:
3774 if horOnly:
3233 A = numpy.c_[dir_cosu,dir_cosv]
3775 A = numpy.c_[dir_cosu,dir_cosv]
3234 else:
3776 else:
3235 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
3777 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
3236 A = numpy.asmatrix(A)
3778 A = numpy.asmatrix(A)
3237 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
3779 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
3238
3780
3239 return A1
3781 return A1
3240
3782
3241 def __correctValues(self, heiRang, phi, velRadial, SNR):
3783 def __correctValues(self, heiRang, phi, velRadial, SNR):
3242 listPhi = phi.tolist()
3784 listPhi = phi.tolist()
3243 maxid = listPhi.index(max(listPhi))
3785 maxid = listPhi.index(max(listPhi))
3244 minid = listPhi.index(min(listPhi))
3786 minid = listPhi.index(min(listPhi))
3245
3787
3246 rango = list(range(len(phi)))
3788 rango = list(range(len(phi)))
3247 # rango = numpy.delete(rango,maxid)
3789 # rango = numpy.delete(rango,maxid)
3248
3790
3249 heiRang1 = heiRang*math.cos(phi[maxid])
3791 heiRang1 = heiRang*math.cos(phi[maxid])
3250 heiRangAux = heiRang*math.cos(phi[minid])
3792 heiRangAux = heiRang*math.cos(phi[minid])
3251 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3793 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3252 heiRang1 = numpy.delete(heiRang1,indOut)
3794 heiRang1 = numpy.delete(heiRang1,indOut)
3253
3795
3254 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3796 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3255 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3797 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3256
3798
3257 for i in rango:
3799 for i in rango:
3258 x = heiRang*math.cos(phi[i])
3800 x = heiRang*math.cos(phi[i])
3259 y1 = velRadial[i,:]
3801 y1 = velRadial[i,:]
3260 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
3802 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
3261
3803
3262 x1 = heiRang1
3804 x1 = heiRang1
3263 y11 = f1(x1)
3805 y11 = f1(x1)
3264
3806
3265 y2 = SNR[i,:]
3807 y2 = SNR[i,:]
3266 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
3808 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
3267 y21 = f2(x1)
3809 y21 = f2(x1)
3268
3810
3269 velRadial1[i,:] = y11
3811 velRadial1[i,:] = y11
3270 SNR1[i,:] = y21
3812 SNR1[i,:] = y21
3271
3813
3272 return heiRang1, velRadial1, SNR1
3814 return heiRang1, velRadial1, SNR1
3273
3815
3274 def __calculateVelUVW(self, A, velRadial):
3816 def __calculateVelUVW(self, A, velRadial):
3275
3817
3276 #Operacion Matricial
3818 #Operacion Matricial
3277 # velUVW = numpy.zeros((velRadial.shape[1],3))
3819 # velUVW = numpy.zeros((velRadial.shape[1],3))
3278 # for ind in range(velRadial.shape[1]):
3820 # for ind in range(velRadial.shape[1]):
3279 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
3821 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
3280 # velUVW = velUVW.transpose()
3822 # velUVW = velUVW.transpose()
3281 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
3823 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
3282 velUVW[:,:] = numpy.dot(A,velRadial)
3824 velUVW[:,:] = numpy.dot(A,velRadial)
3283
3825
3284
3826
3285 return velUVW
3827 return velUVW
3286
3828
3287 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
3829 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
3288
3830
3289 def techniqueDBS(self, kwargs):
3831 def techniqueDBS(self, kwargs):
3290 """
3832 """
3291 Function that implements Doppler Beam Swinging (DBS) technique.
3833 Function that implements Doppler Beam Swinging (DBS) technique.
3292
3834
3293 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3835 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3294 Direction correction (if necessary), Ranges and SNR
3836 Direction correction (if necessary), Ranges and SNR
3295
3837
3296 Output: Winds estimation (Zonal, Meridional and Vertical)
3838 Output: Winds estimation (Zonal, Meridional and Vertical)
3297
3839
3298 Parameters affected: Winds, height range, SNR
3840 Parameters affected: Winds, height range, SNR
3299 """
3841 """
3300 velRadial0 = kwargs['velRadial']
3842 velRadial0 = kwargs['velRadial']
3301 heiRang = kwargs['heightList']
3843 heiRang = kwargs['heightList']
3302 SNR0 = kwargs['SNR']
3844 SNR0 = kwargs['SNR']
3303
3845
3304 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
3846 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
3305 theta_x = numpy.array(kwargs['dirCosx'])
3847 theta_x = numpy.array(kwargs['dirCosx'])
3306 theta_y = numpy.array(kwargs['dirCosy'])
3848 theta_y = numpy.array(kwargs['dirCosy'])
3307 else:
3849 else:
3308 elev = numpy.array(kwargs['elevation'])
3850 elev = numpy.array(kwargs['elevation'])
3309 azim = numpy.array(kwargs['azimuth'])
3851 azim = numpy.array(kwargs['azimuth'])
3310 theta_x, theta_y = self.__calculateCosDir(elev, azim)
3852 theta_x, theta_y = self.__calculateCosDir(elev, azim)
3311 azimuth = kwargs['correctAzimuth']
3853 azimuth = kwargs['correctAzimuth']
3312 if 'horizontalOnly' in kwargs:
3854 if 'horizontalOnly' in kwargs:
3313 horizontalOnly = kwargs['horizontalOnly']
3855 horizontalOnly = kwargs['horizontalOnly']
3314 else: horizontalOnly = False
3856 else: horizontalOnly = False
3315 if 'correctFactor' in kwargs:
3857 if 'correctFactor' in kwargs:
3316 correctFactor = kwargs['correctFactor']
3858 correctFactor = kwargs['correctFactor']
3317 else: correctFactor = 1
3859 else: correctFactor = 1
3318 if 'channelList' in kwargs:
3860 if 'channelList' in kwargs:
3319 channelList = kwargs['channelList']
3861 channelList = kwargs['channelList']
3320 if len(channelList) == 2:
3862 if len(channelList) == 2:
3321 horizontalOnly = True
3863 horizontalOnly = True
3322 arrayChannel = numpy.array(channelList)
3864 arrayChannel = numpy.array(channelList)
3323 param = param[arrayChannel,:,:]
3865 param = param[arrayChannel,:,:]
3324 theta_x = theta_x[arrayChannel]
3866 theta_x = theta_x[arrayChannel]
3325 theta_y = theta_y[arrayChannel]
3867 theta_y = theta_y[arrayChannel]
3326
3868
3327 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3869 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3328 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
3870 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
3329 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
3871 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
3330
3872
3331 #Calculo de Componentes de la velocidad con DBS
3873 #Calculo de Componentes de la velocidad con DBS
3332 winds = self.__calculateVelUVW(A,velRadial1)
3874 winds = self.__calculateVelUVW(A,velRadial1)
3333
3875
3334 return winds, heiRang1, SNR1
3876 return winds, heiRang1, SNR1
3335
3877
3336 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
3878 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
3337
3879
3338 nPairs = len(pairs_ccf)
3880 nPairs = len(pairs_ccf)
3339 posx = numpy.asarray(posx)
3881 posx = numpy.asarray(posx)
3340 posy = numpy.asarray(posy)
3882 posy = numpy.asarray(posy)
3341
3883
3342 #Rotacion Inversa para alinear con el azimuth
3884 #Rotacion Inversa para alinear con el azimuth
3343 if azimuth!= None:
3885 if azimuth!= None:
3344 azimuth = azimuth*math.pi/180
3886 azimuth = azimuth*math.pi/180
3345 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
3887 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
3346 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
3888 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
3347 else:
3889 else:
3348 posx1 = posx
3890 posx1 = posx
3349 posy1 = posy
3891 posy1 = posy
3350
3892
3351 #Calculo de Distancias
3893 #Calculo de Distancias
3352 distx = numpy.zeros(nPairs)
3894 distx = numpy.zeros(nPairs)
3353 disty = numpy.zeros(nPairs)
3895 disty = numpy.zeros(nPairs)
3354 dist = numpy.zeros(nPairs)
3896 dist = numpy.zeros(nPairs)
3355 ang = numpy.zeros(nPairs)
3897 ang = numpy.zeros(nPairs)
3356
3898
3357 for i in range(nPairs):
3899 for i in range(nPairs):
3358 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
3900 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
3359 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
3901 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
3360 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
3902 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
3361 ang[i] = numpy.arctan2(disty[i],distx[i])
3903 ang[i] = numpy.arctan2(disty[i],distx[i])
3362
3904
3363 return distx, disty, dist, ang
3905 return distx, disty, dist, ang
3364 #Calculo de Matrices
3906 #Calculo de Matrices
3365 # nPairs = len(pairs)
3907 # nPairs = len(pairs)
3366 # ang1 = numpy.zeros((nPairs, 2, 1))
3908 # ang1 = numpy.zeros((nPairs, 2, 1))
3367 # dist1 = numpy.zeros((nPairs, 2, 1))
3909 # dist1 = numpy.zeros((nPairs, 2, 1))
3368 #
3910 #
3369 # for j in range(nPairs):
3911 # for j in range(nPairs):
3370 # dist1[j,0,0] = dist[pairs[j][0]]
3912 # dist1[j,0,0] = dist[pairs[j][0]]
3371 # dist1[j,1,0] = dist[pairs[j][1]]
3913 # dist1[j,1,0] = dist[pairs[j][1]]
3372 # ang1[j,0,0] = ang[pairs[j][0]]
3914 # ang1[j,0,0] = ang[pairs[j][0]]
3373 # ang1[j,1,0] = ang[pairs[j][1]]
3915 # ang1[j,1,0] = ang[pairs[j][1]]
3374 #
3916 #
3375 # return distx,disty, dist1,ang1
3917 # return distx,disty, dist1,ang1
3376
3918
3377
3919
3378 def __calculateVelVer(self, phase, lagTRange, _lambda):
3920 def __calculateVelVer(self, phase, lagTRange, _lambda):
3379
3921
3380 Ts = lagTRange[1] - lagTRange[0]
3922 Ts = lagTRange[1] - lagTRange[0]
3381 velW = -_lambda*phase/(4*math.pi*Ts)
3923 velW = -_lambda*phase/(4*math.pi*Ts)
3382
3924
3383 return velW
3925 return velW
3384
3926
3385 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
3927 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
3386 nPairs = tau1.shape[0]
3928 nPairs = tau1.shape[0]
3387 nHeights = tau1.shape[1]
3929 nHeights = tau1.shape[1]
3388 vel = numpy.zeros((nPairs,3,nHeights))
3930 vel = numpy.zeros((nPairs,3,nHeights))
3389 dist1 = numpy.reshape(dist, (dist.size,1))
3931 dist1 = numpy.reshape(dist, (dist.size,1))
3390
3932
3391 angCos = numpy.cos(ang)
3933 angCos = numpy.cos(ang)
3392 angSin = numpy.sin(ang)
3934 angSin = numpy.sin(ang)
3393
3935
3394 vel0 = dist1*tau1/(2*tau2**2)
3936 vel0 = dist1*tau1/(2*tau2**2)
3395 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
3937 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
3396 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
3938 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
3397
3939
3398 ind = numpy.where(numpy.isinf(vel))
3940 ind = numpy.where(numpy.isinf(vel))
3399 vel[ind] = numpy.nan
3941 vel[ind] = numpy.nan
3400
3942
3401 return vel
3943 return vel
3402
3944
3403 # def __getPairsAutoCorr(self, pairsList, nChannels):
3945 # def __getPairsAutoCorr(self, pairsList, nChannels):
3404 #
3946 #
3405 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
3947 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
3406 #
3948 #
3407 # for l in range(len(pairsList)):
3949 # for l in range(len(pairsList)):
3408 # firstChannel = pairsList[l][0]
3950 # firstChannel = pairsList[l][0]
3409 # secondChannel = pairsList[l][1]
3951 # secondChannel = pairsList[l][1]
3410 #
3952 #
3411 # #Obteniendo pares de Autocorrelacion
3953 # #Obteniendo pares de Autocorrelacion
3412 # if firstChannel == secondChannel:
3954 # if firstChannel == secondChannel:
3413 # pairsAutoCorr[firstChannel] = int(l)
3955 # pairsAutoCorr[firstChannel] = int(l)
3414 #
3956 #
3415 # pairsAutoCorr = pairsAutoCorr.astype(int)
3957 # pairsAutoCorr = pairsAutoCorr.astype(int)
3416 #
3958 #
3417 # pairsCrossCorr = range(len(pairsList))
3959 # pairsCrossCorr = range(len(pairsList))
3418 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
3960 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
3419 #
3961 #
3420 # return pairsAutoCorr, pairsCrossCorr
3962 # return pairsAutoCorr, pairsCrossCorr
3421
3963
3422 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
3964 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
3423 def techniqueSA(self, kwargs):
3965 def techniqueSA(self, kwargs):
3424
3966
3425 """
3967 """
3426 Function that implements Spaced Antenna (SA) technique.
3968 Function that implements Spaced Antenna (SA) technique.
3427
3969
3428 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3970 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3429 Direction correction (if necessary), Ranges and SNR
3971 Direction correction (if necessary), Ranges and SNR
3430
3972
3431 Output: Winds estimation (Zonal, Meridional and Vertical)
3973 Output: Winds estimation (Zonal, Meridional and Vertical)
3432
3974
3433 Parameters affected: Winds
3975 Parameters affected: Winds
3434 """
3976 """
3435 position_x = kwargs['positionX']
3977 position_x = kwargs['positionX']
3436 position_y = kwargs['positionY']
3978 position_y = kwargs['positionY']
3437 azimuth = kwargs['azimuth']
3979 azimuth = kwargs['azimuth']
3438
3980
3439 if 'correctFactor' in kwargs:
3981 if 'correctFactor' in kwargs:
3440 correctFactor = kwargs['correctFactor']
3982 correctFactor = kwargs['correctFactor']
3441 else:
3983 else:
3442 correctFactor = 1
3984 correctFactor = 1
3443
3985
3444 groupList = kwargs['groupList']
3986 groupList = kwargs['groupList']
3445 pairs_ccf = groupList[1]
3987 pairs_ccf = groupList[1]
3446 tau = kwargs['tau']
3988 tau = kwargs['tau']
3447 _lambda = kwargs['_lambda']
3989 _lambda = kwargs['_lambda']
3448
3990
3449 #Cross Correlation pairs obtained
3991 #Cross Correlation pairs obtained
3450 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
3992 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
3451 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
3993 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
3452 # pairsSelArray = numpy.array(pairsSelected)
3994 # pairsSelArray = numpy.array(pairsSelected)
3453 # pairs = []
3995 # pairs = []
3454 #
3996 #
3455 # #Wind estimation pairs obtained
3997 # #Wind estimation pairs obtained
3456 # for i in range(pairsSelArray.shape[0]/2):
3998 # for i in range(pairsSelArray.shape[0]/2):
3457 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
3999 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
3458 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
4000 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
3459 # pairs.append((ind1,ind2))
4001 # pairs.append((ind1,ind2))
3460
4002
3461 indtau = tau.shape[0]/2
4003 indtau = tau.shape[0]/2
3462 tau1 = tau[:indtau,:]
4004 tau1 = tau[:indtau,:]
3463 tau2 = tau[indtau:-1,:]
4005 tau2 = tau[indtau:-1,:]
3464 # tau1 = tau1[pairs,:]
4006 # tau1 = tau1[pairs,:]
3465 # tau2 = tau2[pairs,:]
4007 # tau2 = tau2[pairs,:]
3466 phase1 = tau[-1,:]
4008 phase1 = tau[-1,:]
3467
4009
3468 #---------------------------------------------------------------------
4010 #---------------------------------------------------------------------
3469 #Metodo Directo
4011 #Metodo Directo
3470 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
4012 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
3471 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
4013 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
3472 winds = stats.nanmean(winds, axis=0)
4014 winds = stats.nanmean(winds, axis=0)
3473 #---------------------------------------------------------------------
4015 #---------------------------------------------------------------------
3474 #Metodo General
4016 #Metodo General
3475 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
4017 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
3476 # #Calculo Coeficientes de Funcion de Correlacion
4018 # #Calculo Coeficientes de Funcion de Correlacion
3477 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
4019 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
3478 # #Calculo de Velocidades
4020 # #Calculo de Velocidades
3479 # winds = self.calculateVelUV(F,G,A,B,H)
4021 # winds = self.calculateVelUV(F,G,A,B,H)
3480
4022
3481 #---------------------------------------------------------------------
4023 #---------------------------------------------------------------------
3482 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
4024 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
3483 winds = correctFactor*winds
4025 winds = correctFactor*winds
3484 return winds
4026 return winds
3485
4027
3486 def __checkTime(self, currentTime, paramInterval, outputInterval):
4028 def __checkTime(self, currentTime, paramInterval, outputInterval):
3487
4029
3488 dataTime = currentTime + paramInterval
4030 dataTime = currentTime + paramInterval
3489 deltaTime = dataTime - self.__initime
4031 deltaTime = dataTime - self.__initime
3490
4032
3491 if deltaTime >= outputInterval or deltaTime < 0:
4033 if deltaTime >= outputInterval or deltaTime < 0:
3492 self.__dataReady = True
4034 self.__dataReady = True
3493 return
4035 return
3494
4036
3495 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
4037 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
3496 '''
4038 '''
3497 Function that implements winds estimation technique with detected meteors.
4039 Function that implements winds estimation technique with detected meteors.
3498
4040
3499 Input: Detected meteors, Minimum meteor quantity to wind estimation
4041 Input: Detected meteors, Minimum meteor quantity to wind estimation
3500
4042
3501 Output: Winds estimation (Zonal and Meridional)
4043 Output: Winds estimation (Zonal and Meridional)
3502
4044
3503 Parameters affected: Winds
4045 Parameters affected: Winds
3504 '''
4046 '''
3505 #Settings
4047 #Settings
3506 nInt = (heightMax - heightMin)/2
4048 nInt = (heightMax - heightMin)/2
3507 nInt = int(nInt)
4049 nInt = int(nInt)
3508 winds = numpy.zeros((2,nInt))*numpy.nan
4050 winds = numpy.zeros((2,nInt))*numpy.nan
3509
4051
3510 #Filter errors
4052 #Filter errors
3511 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
4053 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
3512 finalMeteor = arrayMeteor[error,:]
4054 finalMeteor = arrayMeteor[error,:]
3513
4055
3514 #Meteor Histogram
4056 #Meteor Histogram
3515 finalHeights = finalMeteor[:,2]
4057 finalHeights = finalMeteor[:,2]
3516 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
4058 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
3517 nMeteorsPerI = hist[0]
4059 nMeteorsPerI = hist[0]
3518 heightPerI = hist[1]
4060 heightPerI = hist[1]
3519
4061
3520 #Sort of meteors
4062 #Sort of meteors
3521 indSort = finalHeights.argsort()
4063 indSort = finalHeights.argsort()
3522 finalMeteor2 = finalMeteor[indSort,:]
4064 finalMeteor2 = finalMeteor[indSort,:]
3523
4065
3524 # Calculating winds
4066 # Calculating winds
3525 ind1 = 0
4067 ind1 = 0
3526 ind2 = 0
4068 ind2 = 0
3527
4069
3528 for i in range(nInt):
4070 for i in range(nInt):
3529 nMet = nMeteorsPerI[i]
4071 nMet = nMeteorsPerI[i]
3530 ind1 = ind2
4072 ind1 = ind2
3531 ind2 = ind1 + nMet
4073 ind2 = ind1 + nMet
3532
4074
3533 meteorAux = finalMeteor2[ind1:ind2,:]
4075 meteorAux = finalMeteor2[ind1:ind2,:]
3534
4076
3535 if meteorAux.shape[0] >= meteorThresh:
4077 if meteorAux.shape[0] >= meteorThresh:
3536 vel = meteorAux[:, 6]
4078 vel = meteorAux[:, 6]
3537 zen = meteorAux[:, 4]*numpy.pi/180
4079 zen = meteorAux[:, 4]*numpy.pi/180
3538 azim = meteorAux[:, 3]*numpy.pi/180
4080 azim = meteorAux[:, 3]*numpy.pi/180
3539
4081
3540 n = numpy.cos(zen)
4082 n = numpy.cos(zen)
3541 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
4083 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
3542 # l = m*numpy.tan(azim)
4084 # l = m*numpy.tan(azim)
3543 l = numpy.sin(zen)*numpy.sin(azim)
4085 l = numpy.sin(zen)*numpy.sin(azim)
3544 m = numpy.sin(zen)*numpy.cos(azim)
4086 m = numpy.sin(zen)*numpy.cos(azim)
3545
4087
3546 A = numpy.vstack((l, m)).transpose()
4088 A = numpy.vstack((l, m)).transpose()
3547 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
4089 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
3548 windsAux = numpy.dot(A1, vel)
4090 windsAux = numpy.dot(A1, vel)
3549
4091
3550 winds[0,i] = windsAux[0]
4092 winds[0,i] = windsAux[0]
3551 winds[1,i] = windsAux[1]
4093 winds[1,i] = windsAux[1]
3552
4094
3553 return winds, heightPerI[:-1]
4095 return winds, heightPerI[:-1]
3554
4096
3555 def techniqueNSM_SA(self, **kwargs):
4097 def techniqueNSM_SA(self, **kwargs):
3556 metArray = kwargs['metArray']
4098 metArray = kwargs['metArray']
3557 heightList = kwargs['heightList']
4099 heightList = kwargs['heightList']
3558 timeList = kwargs['timeList']
4100 timeList = kwargs['timeList']
3559
4101
3560 rx_location = kwargs['rx_location']
4102 rx_location = kwargs['rx_location']
3561 groupList = kwargs['groupList']
4103 groupList = kwargs['groupList']
3562 azimuth = kwargs['azimuth']
4104 azimuth = kwargs['azimuth']
3563 dfactor = kwargs['dfactor']
4105 dfactor = kwargs['dfactor']
3564 k = kwargs['k']
4106 k = kwargs['k']
3565
4107
3566 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
4108 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
3567 d = dist*dfactor
4109 d = dist*dfactor
3568 #Phase calculation
4110 #Phase calculation
3569 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
4111 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
3570
4112
3571 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
4113 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
3572
4114
3573 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4115 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3574 azimuth1 = azimuth1*numpy.pi/180
4116 azimuth1 = azimuth1*numpy.pi/180
3575
4117
3576 for i in range(heightList.size):
4118 for i in range(heightList.size):
3577 h = heightList[i]
4119 h = heightList[i]
3578 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
4120 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
3579 metHeight = metArray1[indH,:]
4121 metHeight = metArray1[indH,:]
3580 if metHeight.shape[0] >= 2:
4122 if metHeight.shape[0] >= 2:
3581 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
4123 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
3582 iazim = metHeight[:,1].astype(int)
4124 iazim = metHeight[:,1].astype(int)
3583 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
4125 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
3584 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
4126 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
3585 A = numpy.asmatrix(A)
4127 A = numpy.asmatrix(A)
3586 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
4128 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
3587 velHor = numpy.dot(A1,velAux)
4129 velHor = numpy.dot(A1,velAux)
3588
4130
3589 velEst[i,:] = numpy.squeeze(velHor)
4131 velEst[i,:] = numpy.squeeze(velHor)
3590 return velEst
4132 return velEst
3591
4133
3592 def __getPhaseSlope(self, metArray, heightList, timeList):
4134 def __getPhaseSlope(self, metArray, heightList, timeList):
3593 meteorList = []
4135 meteorList = []
3594 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
4136 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
3595 #Putting back together the meteor matrix
4137 #Putting back together the meteor matrix
3596 utctime = metArray[:,0]
4138 utctime = metArray[:,0]
3597 uniqueTime = numpy.unique(utctime)
4139 uniqueTime = numpy.unique(utctime)
3598
4140
3599 phaseDerThresh = 0.5
4141 phaseDerThresh = 0.5
3600 ippSeconds = timeList[1] - timeList[0]
4142 ippSeconds = timeList[1] - timeList[0]
3601 sec = numpy.where(timeList>1)[0][0]
4143 sec = numpy.where(timeList>1)[0][0]
3602 nPairs = metArray.shape[1] - 6
4144 nPairs = metArray.shape[1] - 6
3603 nHeights = len(heightList)
4145 nHeights = len(heightList)
3604
4146
3605 for t in uniqueTime:
4147 for t in uniqueTime:
3606 metArray1 = metArray[utctime==t,:]
4148 metArray1 = metArray[utctime==t,:]
3607 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
4149 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
3608 tmet = metArray1[:,1].astype(int)
4150 tmet = metArray1[:,1].astype(int)
3609 hmet = metArray1[:,2].astype(int)
4151 hmet = metArray1[:,2].astype(int)
3610
4152
3611 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
4153 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
3612 metPhase[:,:] = numpy.nan
4154 metPhase[:,:] = numpy.nan
3613 metPhase[:,hmet,tmet] = metArray1[:,6:].T
4155 metPhase[:,hmet,tmet] = metArray1[:,6:].T
3614
4156
3615 #Delete short trails
4157 #Delete short trails
3616 metBool = ~numpy.isnan(metPhase[0,:,:])
4158 metBool = ~numpy.isnan(metPhase[0,:,:])
3617 heightVect = numpy.sum(metBool, axis = 1)
4159 heightVect = numpy.sum(metBool, axis = 1)
3618 metBool[heightVect<sec,:] = False
4160 metBool[heightVect<sec,:] = False
3619 metPhase[:,heightVect<sec,:] = numpy.nan
4161 metPhase[:,heightVect<sec,:] = numpy.nan
3620
4162
3621 #Derivative
4163 #Derivative
3622 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
4164 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
3623 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
4165 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
3624 metPhase[phDerAux] = numpy.nan
4166 metPhase[phDerAux] = numpy.nan
3625
4167
3626 #--------------------------METEOR DETECTION -----------------------------------------
4168 #--------------------------METEOR DETECTION -----------------------------------------
3627 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
4169 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
3628
4170
3629 for p in numpy.arange(nPairs):
4171 for p in numpy.arange(nPairs):
3630 phase = metPhase[p,:,:]
4172 phase = metPhase[p,:,:]
3631 phDer = metDer[p,:,:]
4173 phDer = metDer[p,:,:]
3632
4174
3633 for h in indMet:
4175 for h in indMet:
3634 height = heightList[h]
4176 height = heightList[h]
3635 phase1 = phase[h,:] #82
4177 phase1 = phase[h,:] #82
3636 phDer1 = phDer[h,:]
4178 phDer1 = phDer[h,:]
3637
4179
3638 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
4180 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
3639
4181
3640 indValid = numpy.where(~numpy.isnan(phase1))[0]
4182 indValid = numpy.where(~numpy.isnan(phase1))[0]
3641 initMet = indValid[0]
4183 initMet = indValid[0]
3642 endMet = 0
4184 endMet = 0
3643
4185
3644 for i in range(len(indValid)-1):
4186 for i in range(len(indValid)-1):
3645
4187
3646 #Time difference
4188 #Time difference
3647 inow = indValid[i]
4189 inow = indValid[i]
3648 inext = indValid[i+1]
4190 inext = indValid[i+1]
3649 idiff = inext - inow
4191 idiff = inext - inow
3650 #Phase difference
4192 #Phase difference
3651 phDiff = numpy.abs(phase1[inext] - phase1[inow])
4193 phDiff = numpy.abs(phase1[inext] - phase1[inow])
3652
4194
3653 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
4195 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
3654 sizeTrail = inow - initMet + 1
4196 sizeTrail = inow - initMet + 1
3655 if sizeTrail>3*sec: #Too short meteors
4197 if sizeTrail>3*sec: #Too short meteors
3656 x = numpy.arange(initMet,inow+1)*ippSeconds
4198 x = numpy.arange(initMet,inow+1)*ippSeconds
3657 y = phase1[initMet:inow+1]
4199 y = phase1[initMet:inow+1]
3658 ynnan = ~numpy.isnan(y)
4200 ynnan = ~numpy.isnan(y)
3659 x = x[ynnan]
4201 x = x[ynnan]
3660 y = y[ynnan]
4202 y = y[ynnan]
3661 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
4203 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
3662 ylin = x*slope + intercept
4204 ylin = x*slope + intercept
3663 rsq = r_value**2
4205 rsq = r_value**2
3664 if rsq > 0.5:
4206 if rsq > 0.5:
3665 vel = slope#*height*1000/(k*d)
4207 vel = slope#*height*1000/(k*d)
3666 estAux = numpy.array([utctime,p,height, vel, rsq])
4208 estAux = numpy.array([utctime,p,height, vel, rsq])
3667 meteorList.append(estAux)
4209 meteorList.append(estAux)
3668 initMet = inext
4210 initMet = inext
3669 metArray2 = numpy.array(meteorList)
4211 metArray2 = numpy.array(meteorList)
3670
4212
3671 return metArray2
4213 return metArray2
3672
4214
3673 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
4215 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
3674
4216
3675 azimuth1 = numpy.zeros(len(pairslist))
4217 azimuth1 = numpy.zeros(len(pairslist))
3676 dist = numpy.zeros(len(pairslist))
4218 dist = numpy.zeros(len(pairslist))
3677
4219
3678 for i in range(len(rx_location)):
4220 for i in range(len(rx_location)):
3679 ch0 = pairslist[i][0]
4221 ch0 = pairslist[i][0]
3680 ch1 = pairslist[i][1]
4222 ch1 = pairslist[i][1]
3681
4223
3682 diffX = rx_location[ch0][0] - rx_location[ch1][0]
4224 diffX = rx_location[ch0][0] - rx_location[ch1][0]
3683 diffY = rx_location[ch0][1] - rx_location[ch1][1]
4225 diffY = rx_location[ch0][1] - rx_location[ch1][1]
3684 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
4226 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
3685 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
4227 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
3686
4228
3687 azimuth1 -= azimuth0
4229 azimuth1 -= azimuth0
3688 return azimuth1, dist
4230 return azimuth1, dist
3689
4231
3690 def techniqueNSM_DBS(self, **kwargs):
4232 def techniqueNSM_DBS(self, **kwargs):
3691 metArray = kwargs['metArray']
4233 metArray = kwargs['metArray']
3692 heightList = kwargs['heightList']
4234 heightList = kwargs['heightList']
3693 timeList = kwargs['timeList']
4235 timeList = kwargs['timeList']
3694 azimuth = kwargs['azimuth']
4236 azimuth = kwargs['azimuth']
3695 theta_x = numpy.array(kwargs['theta_x'])
4237 theta_x = numpy.array(kwargs['theta_x'])
3696 theta_y = numpy.array(kwargs['theta_y'])
4238 theta_y = numpy.array(kwargs['theta_y'])
3697
4239
3698 utctime = metArray[:,0]
4240 utctime = metArray[:,0]
3699 cmet = metArray[:,1].astype(int)
4241 cmet = metArray[:,1].astype(int)
3700 hmet = metArray[:,3].astype(int)
4242 hmet = metArray[:,3].astype(int)
3701 SNRmet = metArray[:,4]
4243 SNRmet = metArray[:,4]
3702 vmet = metArray[:,5]
4244 vmet = metArray[:,5]
3703 spcmet = metArray[:,6]
4245 spcmet = metArray[:,6]
3704
4246
3705 nChan = numpy.max(cmet) + 1
4247 nChan = numpy.max(cmet) + 1
3706 nHeights = len(heightList)
4248 nHeights = len(heightList)
3707
4249
3708 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4250 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3709 hmet = heightList[hmet]
4251 hmet = heightList[hmet]
3710 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
4252 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
3711
4253
3712 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4254 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3713
4255
3714 for i in range(nHeights - 1):
4256 for i in range(nHeights - 1):
3715 hmin = heightList[i]
4257 hmin = heightList[i]
3716 hmax = heightList[i + 1]
4258 hmax = heightList[i + 1]
3717
4259
3718 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
4260 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
3719 indthisH = numpy.where(thisH)
4261 indthisH = numpy.where(thisH)
3720
4262
3721 if numpy.size(indthisH) > 3:
4263 if numpy.size(indthisH) > 3:
3722
4264
3723 vel_aux = vmet[thisH]
4265 vel_aux = vmet[thisH]
3724 chan_aux = cmet[thisH]
4266 chan_aux = cmet[thisH]
3725 cosu_aux = dir_cosu[chan_aux]
4267 cosu_aux = dir_cosu[chan_aux]
3726 cosv_aux = dir_cosv[chan_aux]
4268 cosv_aux = dir_cosv[chan_aux]
3727 cosw_aux = dir_cosw[chan_aux]
4269 cosw_aux = dir_cosw[chan_aux]
3728
4270
3729 nch = numpy.size(numpy.unique(chan_aux))
4271 nch = numpy.size(numpy.unique(chan_aux))
3730 if nch > 1:
4272 if nch > 1:
3731 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
4273 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
3732 velEst[i,:] = numpy.dot(A,vel_aux)
4274 velEst[i,:] = numpy.dot(A,vel_aux)
3733
4275
3734 return velEst
4276 return velEst
3735
4277
3736 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
4278 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
3737
4279
3738 param = dataOut.data_param
4280 param = dataOut.data_param
3739 if dataOut.abscissaList != None:
4281 if dataOut.abscissaList != None:
3740 absc = dataOut.abscissaList[:-1]
4282 absc = dataOut.abscissaList[:-1]
3741 # noise = dataOut.noise
4283 # noise = dataOut.noise
3742 heightList = dataOut.heightList
4284 heightList = dataOut.heightList
3743 SNR = dataOut.data_snr
4285 SNR = dataOut.data_snr
3744
4286
3745 if technique == 'DBS':
4287 if technique == 'DBS':
3746
4288
3747 kwargs['velRadial'] = param[:,1,:] #Radial velocity
4289 kwargs['velRadial'] = param[:,1,:] #Radial velocity
3748 kwargs['heightList'] = heightList
4290 kwargs['heightList'] = heightList
3749 kwargs['SNR'] = SNR
4291 kwargs['SNR'] = SNR
3750
4292
3751 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
4293 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
3752 dataOut.utctimeInit = dataOut.utctime
4294 dataOut.utctimeInit = dataOut.utctime
3753 dataOut.outputInterval = dataOut.paramInterval
4295 dataOut.outputInterval = dataOut.paramInterval
3754
4296
3755 elif technique == 'SA':
4297 elif technique == 'SA':
3756
4298
3757 #Parameters
4299 #Parameters
3758 # position_x = kwargs['positionX']
4300 # position_x = kwargs['positionX']
3759 # position_y = kwargs['positionY']
4301 # position_y = kwargs['positionY']
3760 # azimuth = kwargs['azimuth']
4302 # azimuth = kwargs['azimuth']
3761 #
4303 #
3762 # if kwargs.has_key('crosspairsList'):
4304 # if kwargs.has_key('crosspairsList'):
3763 # pairs = kwargs['crosspairsList']
4305 # pairs = kwargs['crosspairsList']
3764 # else:
4306 # else:
3765 # pairs = None
4307 # pairs = None
3766 #
4308 #
3767 # if kwargs.has_key('correctFactor'):
4309 # if kwargs.has_key('correctFactor'):
3768 # correctFactor = kwargs['correctFactor']
4310 # correctFactor = kwargs['correctFactor']
3769 # else:
4311 # else:
3770 # correctFactor = 1
4312 # correctFactor = 1
3771
4313
3772 # tau = dataOut.data_param
4314 # tau = dataOut.data_param
3773 # _lambda = dataOut.C/dataOut.frequency
4315 # _lambda = dataOut.C/dataOut.frequency
3774 # pairsList = dataOut.groupList
4316 # pairsList = dataOut.groupList
3775 # nChannels = dataOut.nChannels
4317 # nChannels = dataOut.nChannels
3776
4318
3777 kwargs['groupList'] = dataOut.groupList
4319 kwargs['groupList'] = dataOut.groupList
3778 kwargs['tau'] = dataOut.data_param
4320 kwargs['tau'] = dataOut.data_param
3779 kwargs['_lambda'] = dataOut.C/dataOut.frequency
4321 kwargs['_lambda'] = dataOut.C/dataOut.frequency
3780 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
4322 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
3781 dataOut.data_output = self.techniqueSA(kwargs)
4323 dataOut.data_output = self.techniqueSA(kwargs)
3782 dataOut.utctimeInit = dataOut.utctime
4324 dataOut.utctimeInit = dataOut.utctime
3783 dataOut.outputInterval = dataOut.timeInterval
4325 dataOut.outputInterval = dataOut.timeInterval
3784
4326
3785 elif technique == 'Meteors':
4327 elif technique == 'Meteors':
3786 dataOut.flagNoData = True
4328 dataOut.flagNoData = True
3787 self.__dataReady = False
4329 self.__dataReady = False
3788
4330
3789 if 'nHours' in kwargs:
4331 if 'nHours' in kwargs:
3790 nHours = kwargs['nHours']
4332 nHours = kwargs['nHours']
3791 else:
4333 else:
3792 nHours = 1
4334 nHours = 1
3793
4335
3794 if 'meteorsPerBin' in kwargs:
4336 if 'meteorsPerBin' in kwargs:
3795 meteorThresh = kwargs['meteorsPerBin']
4337 meteorThresh = kwargs['meteorsPerBin']
3796 else:
4338 else:
3797 meteorThresh = 6
4339 meteorThresh = 6
3798
4340
3799 if 'hmin' in kwargs:
4341 if 'hmin' in kwargs:
3800 hmin = kwargs['hmin']
4342 hmin = kwargs['hmin']
3801 else: hmin = 70
4343 else: hmin = 70
3802 if 'hmax' in kwargs:
4344 if 'hmax' in kwargs:
3803 hmax = kwargs['hmax']
4345 hmax = kwargs['hmax']
3804 else: hmax = 110
4346 else: hmax = 110
3805
4347
3806 dataOut.outputInterval = nHours*3600
4348 dataOut.outputInterval = nHours*3600
3807
4349
3808 if self.__isConfig == False:
4350 if self.__isConfig == False:
3809 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
4351 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3810 #Get Initial LTC time
4352 #Get Initial LTC time
3811 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4353 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3812 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4354 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3813
4355
3814 self.__isConfig = True
4356 self.__isConfig = True
3815
4357
3816 if self.__buffer is None:
4358 if self.__buffer is None:
3817 self.__buffer = dataOut.data_param
4359 self.__buffer = dataOut.data_param
3818 self.__firstdata = copy.copy(dataOut)
4360 self.__firstdata = copy.copy(dataOut)
3819
4361
3820 else:
4362 else:
3821 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4363 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3822
4364
3823 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4365 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3824
4366
3825 if self.__dataReady:
4367 if self.__dataReady:
3826 dataOut.utctimeInit = self.__initime
4368 dataOut.utctimeInit = self.__initime
3827
4369
3828 self.__initime += dataOut.outputInterval #to erase time offset
4370 self.__initime += dataOut.outputInterval #to erase time offset
3829
4371
3830 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
4372 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
3831 dataOut.flagNoData = False
4373 dataOut.flagNoData = False
3832 self.__buffer = None
4374 self.__buffer = None
3833
4375
3834 elif technique == 'Meteors1':
4376 elif technique == 'Meteors1':
3835 dataOut.flagNoData = True
4377 dataOut.flagNoData = True
3836 self.__dataReady = False
4378 self.__dataReady = False
3837
4379
3838 if 'nMins' in kwargs:
4380 if 'nMins' in kwargs:
3839 nMins = kwargs['nMins']
4381 nMins = kwargs['nMins']
3840 else: nMins = 20
4382 else: nMins = 20
3841 if 'rx_location' in kwargs:
4383 if 'rx_location' in kwargs:
3842 rx_location = kwargs['rx_location']
4384 rx_location = kwargs['rx_location']
3843 else: rx_location = [(0,1),(1,1),(1,0)]
4385 else: rx_location = [(0,1),(1,1),(1,0)]
3844 if 'azimuth' in kwargs:
4386 if 'azimuth' in kwargs:
3845 azimuth = kwargs['azimuth']
4387 azimuth = kwargs['azimuth']
3846 else: azimuth = 51.06
4388 else: azimuth = 51.06
3847 if 'dfactor' in kwargs:
4389 if 'dfactor' in kwargs:
3848 dfactor = kwargs['dfactor']
4390 dfactor = kwargs['dfactor']
3849 if 'mode' in kwargs:
4391 if 'mode' in kwargs:
3850 mode = kwargs['mode']
4392 mode = kwargs['mode']
3851 if 'theta_x' in kwargs:
4393 if 'theta_x' in kwargs:
3852 theta_x = kwargs['theta_x']
4394 theta_x = kwargs['theta_x']
3853 if 'theta_y' in kwargs:
4395 if 'theta_y' in kwargs:
3854 theta_y = kwargs['theta_y']
4396 theta_y = kwargs['theta_y']
3855 else: mode = 'SA'
4397 else: mode = 'SA'
3856
4398
3857 #Borrar luego esto
4399 #Borrar luego esto
3858 if dataOut.groupList is None:
4400 if dataOut.groupList is None:
3859 dataOut.groupList = [(0,1),(0,2),(1,2)]
4401 dataOut.groupList = [(0,1),(0,2),(1,2)]
3860 groupList = dataOut.groupList
4402 groupList = dataOut.groupList
3861 C = 3e8
4403 C = 3e8
3862 freq = 50e6
4404 freq = 50e6
3863 lamb = C/freq
4405 lamb = C/freq
3864 k = 2*numpy.pi/lamb
4406 k = 2*numpy.pi/lamb
3865
4407
3866 timeList = dataOut.abscissaList
4408 timeList = dataOut.abscissaList
3867 heightList = dataOut.heightList
4409 heightList = dataOut.heightList
3868
4410
3869 if self.__isConfig == False:
4411 if self.__isConfig == False:
3870 dataOut.outputInterval = nMins*60
4412 dataOut.outputInterval = nMins*60
3871 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
4413 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3872 #Get Initial LTC time
4414 #Get Initial LTC time
3873 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4415 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3874 minuteAux = initime.minute
4416 minuteAux = initime.minute
3875 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
4417 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
3876 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4418 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3877
4419
3878 self.__isConfig = True
4420 self.__isConfig = True
3879
4421
3880 if self.__buffer is None:
4422 if self.__buffer is None:
3881 self.__buffer = dataOut.data_param
4423 self.__buffer = dataOut.data_param
3882 self.__firstdata = copy.copy(dataOut)
4424 self.__firstdata = copy.copy(dataOut)
3883
4425
3884 else:
4426 else:
3885 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4427 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3886
4428
3887 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4429 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3888
4430
3889 if self.__dataReady:
4431 if self.__dataReady:
3890 dataOut.utctimeInit = self.__initime
4432 dataOut.utctimeInit = self.__initime
3891 self.__initime += dataOut.outputInterval #to erase time offset
4433 self.__initime += dataOut.outputInterval #to erase time offset
3892
4434
3893 metArray = self.__buffer
4435 metArray = self.__buffer
3894 if mode == 'SA':
4436 if mode == 'SA':
3895 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
4437 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
3896 elif mode == 'DBS':
4438 elif mode == 'DBS':
3897 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
4439 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
3898 dataOut.data_output = dataOut.data_output.T
4440 dataOut.data_output = dataOut.data_output.T
3899 dataOut.flagNoData = False
4441 dataOut.flagNoData = False
3900 self.__buffer = None
4442 self.__buffer = None
3901
4443
3902 return
4444 return
3903
4445
3904 class EWDriftsEstimation(Operation):
4446 class EWDriftsEstimation(Operation):
3905
4447
3906 def __init__(self):
4448 def __init__(self):
3907 Operation.__init__(self)
4449 Operation.__init__(self)
3908
4450
3909 def __correctValues(self, heiRang, phi, velRadial, SNR):
4451 def __correctValues(self, heiRang, phi, velRadial, SNR):
3910 listPhi = phi.tolist()
4452 listPhi = phi.tolist()
3911 maxid = listPhi.index(max(listPhi))
4453 maxid = listPhi.index(max(listPhi))
3912 minid = listPhi.index(min(listPhi))
4454 minid = listPhi.index(min(listPhi))
3913
4455
3914 rango = list(range(len(phi)))
4456 rango = list(range(len(phi)))
3915 # rango = numpy.delete(rango,maxid)
4457 # rango = numpy.delete(rango,maxid)
3916
4458
3917 heiRang1 = heiRang*math.cos(phi[maxid])
4459 heiRang1 = heiRang*math.cos(phi[maxid])
3918 heiRangAux = heiRang*math.cos(phi[minid])
4460 heiRangAux = heiRang*math.cos(phi[minid])
3919 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4461 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3920 heiRang1 = numpy.delete(heiRang1,indOut)
4462 heiRang1 = numpy.delete(heiRang1,indOut)
3921
4463
3922 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4464 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3923 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4465 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3924
4466
3925 for i in rango:
4467 for i in rango:
3926 x = heiRang*math.cos(phi[i])
4468 x = heiRang*math.cos(phi[i])
3927 y1 = velRadial[i,:]
4469 y1 = velRadial[i,:]
3928 vali= (numpy.isfinite(y1)==True).nonzero()
4470 vali= (numpy.isfinite(y1)==True).nonzero()
3929 y1=y1[vali]
4471 y1=y1[vali]
3930 x = x[vali]
4472 x = x[vali]
3931 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
4473 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
3932
4474
3933 #heiRang1 = x*math.cos(phi[maxid])
4475 #heiRang1 = x*math.cos(phi[maxid])
3934 x1 = heiRang1
4476 x1 = heiRang1
3935 y11 = f1(x1)
4477 y11 = f1(x1)
3936
4478
3937 y2 = SNR[i,:]
4479 y2 = SNR[i,:]
3938 #print 'snr ', y2
4480 #print 'snr ', y2
3939 x = heiRang*math.cos(phi[i])
4481 x = heiRang*math.cos(phi[i])
3940 vali= (y2 != -1).nonzero()
4482 vali= (y2 != -1).nonzero()
3941 y2 = y2[vali]
4483 y2 = y2[vali]
3942 x = x[vali]
4484 x = x[vali]
3943 #print 'snr ',y2
4485 #print 'snr ',y2
3944 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
4486 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
3945 y21 = f2(x1)
4487 y21 = f2(x1)
3946
4488
3947 velRadial1[i,:] = y11
4489 velRadial1[i,:] = y11
3948 SNR1[i,:] = y21
4490 SNR1[i,:] = y21
3949
4491
3950 return heiRang1, velRadial1, SNR1
4492 return heiRang1, velRadial1, SNR1
3951
4493
3952
4494
3953
4495
3954 def run(self, dataOut, zenith, zenithCorrection):
4496 def run(self, dataOut, zenith, zenithCorrection):
3955
4497
3956 heiRang = dataOut.heightList
4498 heiRang = dataOut.heightList
3957 velRadial = dataOut.data_param[:,3,:]
4499 velRadial = dataOut.data_param[:,3,:]
3958 velRadialm = dataOut.data_param[:,2:4,:]*-1
4500 velRadialm = dataOut.data_param[:,2:4,:]*-1
3959
4501
3960 rbufc=dataOut.data_paramC[:,:,0]
4502 rbufc=dataOut.data_paramC[:,:,0]
3961 ebufc=dataOut.data_paramC[:,:,1]
4503 ebufc=dataOut.data_paramC[:,:,1]
3962 SNR = dataOut.data_snr
4504 SNR = dataOut.data_snr
3963 velRerr = dataOut.data_error[:,4,:]
4505 velRerr = dataOut.data_error[:,4,:]
3964 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
4506 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
3965 dataOut.moments=moments
4507 dataOut.moments=moments
3966 # Coherent
4508 # Coherent
3967 smooth_wC = ebufc[0,:]
4509 smooth_wC = ebufc[0,:]
3968 p_w0C = rbufc[0,:]
4510 p_w0C = rbufc[0,:]
3969 p_w1C = rbufc[1,:]
4511 p_w1C = rbufc[1,:]
3970 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
4512 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
3971 t_wC = rbufc[3,:]
4513 t_wC = rbufc[3,:]
3972 my_nbeams = 2
4514 my_nbeams = 2
3973
4515
3974 zenith = numpy.array(zenith)
4516 zenith = numpy.array(zenith)
3975 zenith -= zenithCorrection
4517 zenith -= zenithCorrection
3976 zenith *= numpy.pi/180
4518 zenith *= numpy.pi/180
3977 if zenithCorrection != 0 :
4519 if zenithCorrection != 0 :
3978 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
4520 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
3979 else :
4521 else :
3980 heiRang1 = heiRang
4522 heiRang1 = heiRang
3981 velRadial1 = velRadial
4523 velRadial1 = velRadial
3982 SNR1 = SNR
4524 SNR1 = SNR
3983
4525
3984 alp = zenith[0]
4526 alp = zenith[0]
3985 bet = zenith[1]
4527 bet = zenith[1]
3986
4528
3987 w_w = velRadial1[0,:]
4529 w_w = velRadial1[0,:]
3988 w_e = velRadial1[1,:]
4530 w_e = velRadial1[1,:]
3989 w_w_err = velRerr[0,:]
4531 w_w_err = velRerr[0,:]
3990 w_e_err = velRerr[1,:]
4532 w_e_err = velRerr[1,:]
3991
4533
3992 val = (numpy.isfinite(w_w)==False).nonzero()
4534 val = (numpy.isfinite(w_w)==False).nonzero()
3993 val = val[0]
4535 val = val[0]
3994 bad = val
4536 bad = val
3995 if len(bad) > 0 :
4537 if len(bad) > 0 :
3996 w_w[bad] = w_wC[bad]
4538 w_w[bad] = w_wC[bad]
3997 w_w_err[bad]= numpy.nan
4539 w_w_err[bad]= numpy.nan
3998 if my_nbeams == 2:
4540 if my_nbeams == 2:
3999 smooth_eC=ebufc[4,:]
4541 smooth_eC=ebufc[4,:]
4000 p_e0C = rbufc[4,:]
4542 p_e0C = rbufc[4,:]
4001 p_e1C = rbufc[5,:]
4543 p_e1C = rbufc[5,:]
4002 w_eC = rbufc[6,:]*-1
4544 w_eC = rbufc[6,:]*-1
4003 t_eC = rbufc[7,:]
4545 t_eC = rbufc[7,:]
4004 val = (numpy.isfinite(w_e)==False).nonzero()
4546 val = (numpy.isfinite(w_e)==False).nonzero()
4005 val = val[0]
4547 val = val[0]
4006 bad = val
4548 bad = val
4007 if len(bad) > 0 :
4549 if len(bad) > 0 :
4008 w_e[bad] = w_eC[bad]
4550 w_e[bad] = w_eC[bad]
4009 w_e_err[bad]= numpy.nan
4551 w_e_err[bad]= numpy.nan
4010
4552
4011 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
4553 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
4012 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
4554 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
4013
4555
4014 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))
4556 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))
4015 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))
4557 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))
4016
4558
4017 winds = numpy.vstack((w,u))
4559 winds = numpy.vstack((w,u))
4018
4560
4019 dataOut.heightList = heiRang1
4561 dataOut.heightList = heiRang1
4020 dataOut.data_output = winds
4562 dataOut.data_output = winds
4021
4563
4022 snr1 = 10*numpy.log10(SNR1[0])
4564 snr1 = 10*numpy.log10(SNR1[0])
4023 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
4565 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
4024 dataOut.utctimeInit = dataOut.utctime
4566 dataOut.utctimeInit = dataOut.utctime
4025 dataOut.outputInterval = dataOut.timeInterval
4567 dataOut.outputInterval = dataOut.timeInterval
4026
4568
4027 hei_aver0 = 218
4569 hei_aver0 = 218
4028 jrange = 450 #900 para HA drifts
4570 jrange = 450 #900 para HA drifts
4029 deltah = 15.0 #dataOut.spacing(0)
4571 deltah = 15.0 #dataOut.spacing(0)
4030 h0 = 0.0 #dataOut.first_height(0)
4572 h0 = 0.0 #dataOut.first_height(0)
4031 heights = dataOut.heightList
4573 heights = dataOut.heightList
4032 nhei = len(heights)
4574 nhei = len(heights)
4033
4575
4034 range1 = numpy.arange(nhei) * deltah + h0
4576 range1 = numpy.arange(nhei) * deltah + h0
4035
4577
4036 #jhei = WHERE(range1 GE hei_aver0 , jcount)
4578 #jhei = WHERE(range1 GE hei_aver0 , jcount)
4037 jhei = (range1 >= hei_aver0).nonzero()
4579 jhei = (range1 >= hei_aver0).nonzero()
4038 if len(jhei[0]) > 0 :
4580 if len(jhei[0]) > 0 :
4039 h0_index = jhei[0][0] # Initial height for getting averages 218km
4581 h0_index = jhei[0][0] # Initial height for getting averages 218km
4040
4582
4041 mynhei = 7
4583 mynhei = 7
4042 nhei_avg = int(jrange/deltah)
4584 nhei_avg = int(jrange/deltah)
4043 h_avgs = int(nhei_avg/mynhei)
4585 h_avgs = int(nhei_avg/mynhei)
4044 nhei_avg = h_avgs*(mynhei-1)+mynhei
4586 nhei_avg = h_avgs*(mynhei-1)+mynhei
4045
4587
4046 navgs = numpy.zeros(mynhei,dtype='float')
4588 navgs = numpy.zeros(mynhei,dtype='float')
4047 delta_h = numpy.zeros(mynhei,dtype='float')
4589 delta_h = numpy.zeros(mynhei,dtype='float')
4048 range_aver = numpy.zeros(mynhei,dtype='float')
4590 range_aver = numpy.zeros(mynhei,dtype='float')
4049 for ih in range( mynhei-1 ):
4591 for ih in range( mynhei-1 ):
4050 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
4592 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
4051 navgs[ih] = h_avgs
4593 navgs[ih] = h_avgs
4052 delta_h[ih] = deltah*h_avgs
4594 delta_h[ih] = deltah*h_avgs
4053
4595
4054 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
4596 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
4055 navgs[mynhei-1] = 6*h_avgs
4597 navgs[mynhei-1] = 6*h_avgs
4056 delta_h[mynhei-1] = deltah*6*h_avgs
4598 delta_h[mynhei-1] = deltah*6*h_avgs
4057
4599
4058 wA = w[h0_index:h0_index+nhei_avg-0]
4600 wA = w[h0_index:h0_index+nhei_avg-0]
4059 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
4601 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
4060
4602
4061 for i in range(5) :
4603 for i in range(5) :
4062 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
4604 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
4063 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
4605 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
4064 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4606 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4065 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4607 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4066 wA[6*h_avgs+i] = avg
4608 wA[6*h_avgs+i] = avg
4067 wA_err[6*h_avgs+i] = sigma
4609 wA_err[6*h_avgs+i] = sigma
4068
4610
4069
4611
4070 vals = wA[0:6*h_avgs-0]
4612 vals = wA[0:6*h_avgs-0]
4071 errs=wA_err[0:6*h_avgs-0]
4613 errs=wA_err[0:6*h_avgs-0]
4072 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
4614 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
4073 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4615 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4074 wA[nhei_avg-1] = avg
4616 wA[nhei_avg-1] = avg
4075 wA_err[nhei_avg-1] = sigma
4617 wA_err[nhei_avg-1] = sigma
4076
4618
4077 wA = wA[6*h_avgs:nhei_avg-0]
4619 wA = wA[6*h_avgs:nhei_avg-0]
4078 wA_err=wA_err[6*h_avgs:nhei_avg-0]
4620 wA_err=wA_err[6*h_avgs:nhei_avg-0]
4079 if my_nbeams == 2 :
4621 if my_nbeams == 2 :
4080
4622
4081 uA = u[h0_index:h0_index+nhei_avg]
4623 uA = u[h0_index:h0_index+nhei_avg]
4082 uA_err=u_err[h0_index:h0_index+nhei_avg]
4624 uA_err=u_err[h0_index:h0_index+nhei_avg]
4083
4625
4084 for i in range(5) :
4626 for i in range(5) :
4085 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
4627 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
4086 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
4628 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
4087 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4629 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4088 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4630 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4089 uA[6*h_avgs+i] = avg
4631 uA[6*h_avgs+i] = avg
4090 uA_err[6*h_avgs+i]=sigma
4632 uA_err[6*h_avgs+i]=sigma
4091
4633
4092 vals = uA[0:6*h_avgs-0]
4634 vals = uA[0:6*h_avgs-0]
4093 errs = uA_err[0:6*h_avgs-0]
4635 errs = uA_err[0:6*h_avgs-0]
4094 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4636 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4095 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4637 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4096 uA[nhei_avg-1] = avg
4638 uA[nhei_avg-1] = avg
4097 uA_err[nhei_avg-1] = sigma
4639 uA_err[nhei_avg-1] = sigma
4098 uA = uA[6*h_avgs:nhei_avg-0]
4640 uA = uA[6*h_avgs:nhei_avg-0]
4099 uA_err = uA_err[6*h_avgs:nhei_avg-0]
4641 uA_err = uA_err[6*h_avgs:nhei_avg-0]
4100
4642
4101 dataOut.drifts_avg = numpy.vstack((wA,uA))
4643 dataOut.drifts_avg = numpy.vstack((wA,uA))
4102
4644
4103 tini=time.localtime(dataOut.utctime)
4645 tini=time.localtime(dataOut.utctime)
4104 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
4646 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
4105 nfile = '/home/pcondor/Database/ewdriftsschain2019/jro'+datefile+'drifts_sch3.txt'
4647 nfile = '/home/pcondor/Database/ewdriftsschain2019/jro'+datefile+'drifts_sch3.txt'
4106
4648
4107 f1 = open(nfile,'a')
4649 f1 = open(nfile,'a')
4108
4650
4109 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
4651 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
4110 driftavgstr=str(dataOut.drifts_avg)
4652 driftavgstr=str(dataOut.drifts_avg)
4111
4653
4112 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
4654 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
4113 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
4655 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
4114 f1.close()
4656 f1.close()
4115
4657
4116 return dataOut
4658 return dataOut
4117
4659
4118 #--------------- Non Specular Meteor ----------------
4660 #--------------- Non Specular Meteor ----------------
4119
4661
4120 class NonSpecularMeteorDetection(Operation):
4662 class NonSpecularMeteorDetection(Operation):
4121
4663
4122 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
4664 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
4123 data_acf = dataOut.data_pre[0]
4665 data_acf = dataOut.data_pre[0]
4124 data_ccf = dataOut.data_pre[1]
4666 data_ccf = dataOut.data_pre[1]
4125 pairsList = dataOut.groupList[1]
4667 pairsList = dataOut.groupList[1]
4126
4668
4127 lamb = dataOut.C/dataOut.frequency
4669 lamb = dataOut.C/dataOut.frequency
4128 tSamp = dataOut.ippSeconds*dataOut.nCohInt
4670 tSamp = dataOut.ippSeconds*dataOut.nCohInt
4129 paramInterval = dataOut.paramInterval
4671 paramInterval = dataOut.paramInterval
4130
4672
4131 nChannels = data_acf.shape[0]
4673 nChannels = data_acf.shape[0]
4132 nLags = data_acf.shape[1]
4674 nLags = data_acf.shape[1]
4133 nProfiles = data_acf.shape[2]
4675 nProfiles = data_acf.shape[2]
4134 nHeights = dataOut.nHeights
4676 nHeights = dataOut.nHeights
4135 nCohInt = dataOut.nCohInt
4677 nCohInt = dataOut.nCohInt
4136 sec = numpy.round(nProfiles/dataOut.paramInterval)
4678 sec = numpy.round(nProfiles/dataOut.paramInterval)
4137 heightList = dataOut.heightList
4679 heightList = dataOut.heightList
4138 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
4680 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
4139 utctime = dataOut.utctime
4681 utctime = dataOut.utctime
4140
4682
4141 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
4683 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
4142
4684
4143 #------------------------ SNR --------------------------------------
4685 #------------------------ SNR --------------------------------------
4144 power = data_acf[:,0,:,:].real
4686 power = data_acf[:,0,:,:].real
4145 noise = numpy.zeros(nChannels)
4687 noise = numpy.zeros(nChannels)
4146 SNR = numpy.zeros(power.shape)
4688 SNR = numpy.zeros(power.shape)
4147 for i in range(nChannels):
4689 for i in range(nChannels):
4148 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
4690 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
4149 SNR[i] = (power[i]-noise[i])/noise[i]
4691 SNR[i] = (power[i]-noise[i])/noise[i]
4150 SNRm = numpy.nanmean(SNR, axis = 0)
4692 SNRm = numpy.nanmean(SNR, axis = 0)
4151 SNRdB = 10*numpy.log10(SNR)
4693 SNRdB = 10*numpy.log10(SNR)
4152
4694
4153 if mode == 'SA':
4695 if mode == 'SA':
4154 dataOut.groupList = dataOut.groupList[1]
4696 dataOut.groupList = dataOut.groupList[1]
4155 nPairs = data_ccf.shape[0]
4697 nPairs = data_ccf.shape[0]
4156 #---------------------- Coherence and Phase --------------------------
4698 #---------------------- Coherence and Phase --------------------------
4157 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
4699 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
4158 # phase1 = numpy.copy(phase)
4700 # phase1 = numpy.copy(phase)
4159 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
4701 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
4160
4702
4161 for p in range(nPairs):
4703 for p in range(nPairs):
4162 ch0 = pairsList[p][0]
4704 ch0 = pairsList[p][0]
4163 ch1 = pairsList[p][1]
4705 ch1 = pairsList[p][1]
4164 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
4706 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
4165 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
4707 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
4166 # phase1[p,:,:] = numpy.angle(ccf) #median filter
4708 # phase1[p,:,:] = numpy.angle(ccf) #median filter
4167 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
4709 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
4168 # coh1[p,:,:] = numpy.abs(ccf) #median filter
4710 # coh1[p,:,:] = numpy.abs(ccf) #median filter
4169 coh = numpy.nanmax(coh1, axis = 0)
4711 coh = numpy.nanmax(coh1, axis = 0)
4170 # struc = numpy.ones((5,1))
4712 # struc = numpy.ones((5,1))
4171 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
4713 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
4172 #---------------------- Radial Velocity ----------------------------
4714 #---------------------- Radial Velocity ----------------------------
4173 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
4715 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
4174 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
4716 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
4175
4717
4176 if allData:
4718 if allData:
4177 boolMetFin = ~numpy.isnan(SNRm)
4719 boolMetFin = ~numpy.isnan(SNRm)
4178 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4720 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4179 else:
4721 else:
4180 #------------------------ Meteor mask ---------------------------------
4722 #------------------------ Meteor mask ---------------------------------
4181 # #SNR mask
4723 # #SNR mask
4182 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
4724 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
4183 #
4725 #
4184 # #Erase small objects
4726 # #Erase small objects
4185 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
4727 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
4186 #
4728 #
4187 # auxEEJ = numpy.sum(boolMet1,axis=0)
4729 # auxEEJ = numpy.sum(boolMet1,axis=0)
4188 # indOver = auxEEJ>nProfiles*0.8 #Use this later
4730 # indOver = auxEEJ>nProfiles*0.8 #Use this later
4189 # indEEJ = numpy.where(indOver)[0]
4731 # indEEJ = numpy.where(indOver)[0]
4190 # indNEEJ = numpy.where(~indOver)[0]
4732 # indNEEJ = numpy.where(~indOver)[0]
4191 #
4733 #
4192 # boolMetFin = boolMet1
4734 # boolMetFin = boolMet1
4193 #
4735 #
4194 # if indEEJ.size > 0:
4736 # if indEEJ.size > 0:
4195 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
4737 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
4196 #
4738 #
4197 # boolMet2 = coh > cohThresh
4739 # boolMet2 = coh > cohThresh
4198 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
4740 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
4199 #
4741 #
4200 # #Final Meteor mask
4742 # #Final Meteor mask
4201 # boolMetFin = boolMet1|boolMet2
4743 # boolMetFin = boolMet1|boolMet2
4202
4744
4203 #Coherence mask
4745 #Coherence mask
4204 boolMet1 = coh > 0.75
4746 boolMet1 = coh > 0.75
4205 struc = numpy.ones((30,1))
4747 struc = numpy.ones((30,1))
4206 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
4748 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
4207
4749
4208 #Derivative mask
4750 #Derivative mask
4209 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4751 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4210 boolMet2 = derPhase < 0.2
4752 boolMet2 = derPhase < 0.2
4211 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
4753 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
4212 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
4754 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
4213 boolMet2 = ndimage.median_filter(boolMet2,size=5)
4755 boolMet2 = ndimage.median_filter(boolMet2,size=5)
4214 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
4756 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
4215 # #Final mask
4757 # #Final mask
4216 # boolMetFin = boolMet2
4758 # boolMetFin = boolMet2
4217 boolMetFin = boolMet1&boolMet2
4759 boolMetFin = boolMet1&boolMet2
4218 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
4760 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
4219 #Creating data_param
4761 #Creating data_param
4220 coordMet = numpy.where(boolMetFin)
4762 coordMet = numpy.where(boolMetFin)
4221
4763
4222 tmet = coordMet[0]
4764 tmet = coordMet[0]
4223 hmet = coordMet[1]
4765 hmet = coordMet[1]
4224
4766
4225 data_param = numpy.zeros((tmet.size, 6 + nPairs))
4767 data_param = numpy.zeros((tmet.size, 6 + nPairs))
4226 data_param[:,0] = utctime
4768 data_param[:,0] = utctime
4227 data_param[:,1] = tmet
4769 data_param[:,1] = tmet
4228 data_param[:,2] = hmet
4770 data_param[:,2] = hmet
4229 data_param[:,3] = SNRm[tmet,hmet]
4771 data_param[:,3] = SNRm[tmet,hmet]
4230 data_param[:,4] = velRad[tmet,hmet]
4772 data_param[:,4] = velRad[tmet,hmet]
4231 data_param[:,5] = coh[tmet,hmet]
4773 data_param[:,5] = coh[tmet,hmet]
4232 data_param[:,6:] = phase[:,tmet,hmet].T
4774 data_param[:,6:] = phase[:,tmet,hmet].T
4233
4775
4234 elif mode == 'DBS':
4776 elif mode == 'DBS':
4235 dataOut.groupList = numpy.arange(nChannels)
4777 dataOut.groupList = numpy.arange(nChannels)
4236
4778
4237 #Radial Velocities
4779 #Radial Velocities
4238 phase = numpy.angle(data_acf[:,1,:,:])
4780 phase = numpy.angle(data_acf[:,1,:,:])
4239 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
4781 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
4240 velRad = phase*lamb/(4*numpy.pi*tSamp)
4782 velRad = phase*lamb/(4*numpy.pi*tSamp)
4241
4783
4242 #Spectral width
4784 #Spectral width
4243 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
4785 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
4244 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
4786 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
4245 acf1 = data_acf[:,1,:,:]
4787 acf1 = data_acf[:,1,:,:]
4246 acf2 = data_acf[:,2,:,:]
4788 acf2 = data_acf[:,2,:,:]
4247
4789
4248 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4790 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4249 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
4791 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
4250 if allData:
4792 if allData:
4251 boolMetFin = ~numpy.isnan(SNRdB)
4793 boolMetFin = ~numpy.isnan(SNRdB)
4252 else:
4794 else:
4253 #SNR
4795 #SNR
4254 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4796 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4255 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4797 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4256
4798
4257 #Radial velocity
4799 #Radial velocity
4258 boolMet2 = numpy.abs(velRad) < 20
4800 boolMet2 = numpy.abs(velRad) < 20
4259 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4801 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4260
4802
4261 #Spectral Width
4803 #Spectral Width
4262 boolMet3 = spcWidth < 30
4804 boolMet3 = spcWidth < 30
4263 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4805 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4264 # boolMetFin = self.__erase_small(boolMet1, 10,5)
4806 # boolMetFin = self.__erase_small(boolMet1, 10,5)
4265 boolMetFin = boolMet1&boolMet2&boolMet3
4807 boolMetFin = boolMet1&boolMet2&boolMet3
4266
4808
4267 #Creating data_param
4809 #Creating data_param
4268 coordMet = numpy.where(boolMetFin)
4810 coordMet = numpy.where(boolMetFin)
4269
4811
4270 cmet = coordMet[0]
4812 cmet = coordMet[0]
4271 tmet = coordMet[1]
4813 tmet = coordMet[1]
4272 hmet = coordMet[2]
4814 hmet = coordMet[2]
4273
4815
4274 data_param = numpy.zeros((tmet.size, 7))
4816 data_param = numpy.zeros((tmet.size, 7))
4275 data_param[:,0] = utctime
4817 data_param[:,0] = utctime
4276 data_param[:,1] = cmet
4818 data_param[:,1] = cmet
4277 data_param[:,2] = tmet
4819 data_param[:,2] = tmet
4278 data_param[:,3] = hmet
4820 data_param[:,3] = hmet
4279 data_param[:,4] = SNR[cmet,tmet,hmet].T
4821 data_param[:,4] = SNR[cmet,tmet,hmet].T
4280 data_param[:,5] = velRad[cmet,tmet,hmet].T
4822 data_param[:,5] = velRad[cmet,tmet,hmet].T
4281 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4823 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4282
4824
4283 # self.dataOut.data_param = data_int
4825 # self.dataOut.data_param = data_int
4284 if len(data_param) == 0:
4826 if len(data_param) == 0:
4285 dataOut.flagNoData = True
4827 dataOut.flagNoData = True
4286 else:
4828 else:
4287 dataOut.data_param = data_param
4829 dataOut.data_param = data_param
4288
4830
4289 def __erase_small(self, binArray, threshX, threshY):
4831 def __erase_small(self, binArray, threshX, threshY):
4290 labarray, numfeat = ndimage.measurements.label(binArray)
4832 labarray, numfeat = ndimage.measurements.label(binArray)
4291 binArray1 = numpy.copy(binArray)
4833 binArray1 = numpy.copy(binArray)
4292
4834
4293 for i in range(1,numfeat + 1):
4835 for i in range(1,numfeat + 1):
4294 auxBin = (labarray==i)
4836 auxBin = (labarray==i)
4295 auxSize = auxBin.sum()
4837 auxSize = auxBin.sum()
4296
4838
4297 x,y = numpy.where(auxBin)
4839 x,y = numpy.where(auxBin)
4298 widthX = x.max() - x.min()
4840 widthX = x.max() - x.min()
4299 widthY = y.max() - y.min()
4841 widthY = y.max() - y.min()
4300
4842
4301 #width X: 3 seg -> 12.5*3
4843 #width X: 3 seg -> 12.5*3
4302 #width Y:
4844 #width Y:
4303
4845
4304 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
4846 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
4305 binArray1[auxBin] = False
4847 binArray1[auxBin] = False
4306
4848
4307 return binArray1
4849 return binArray1
4308
4850
4309 #--------------- Specular Meteor ----------------
4851 #--------------- Specular Meteor ----------------
4310
4852
4311 class SMDetection(Operation):
4853 class SMDetection(Operation):
4312 '''
4854 '''
4313 Function DetectMeteors()
4855 Function DetectMeteors()
4314 Project developed with paper:
4856 Project developed with paper:
4315 HOLDSWORTH ET AL. 2004
4857 HOLDSWORTH ET AL. 2004
4316
4858
4317 Input:
4859 Input:
4318 self.dataOut.data_pre
4860 self.dataOut.data_pre
4319
4861
4320 centerReceiverIndex: From the channels, which is the center receiver
4862 centerReceiverIndex: From the channels, which is the center receiver
4321
4863
4322 hei_ref: Height reference for the Beacon signal extraction
4864 hei_ref: Height reference for the Beacon signal extraction
4323 tauindex:
4865 tauindex:
4324 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4866 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4325
4867
4326 cohDetection: Whether to user Coherent detection or not
4868 cohDetection: Whether to user Coherent detection or not
4327 cohDet_timeStep: Coherent Detection calculation time step
4869 cohDet_timeStep: Coherent Detection calculation time step
4328 cohDet_thresh: Coherent Detection phase threshold to correct phases
4870 cohDet_thresh: Coherent Detection phase threshold to correct phases
4329
4871
4330 noise_timeStep: Noise calculation time step
4872 noise_timeStep: Noise calculation time step
4331 noise_multiple: Noise multiple to define signal threshold
4873 noise_multiple: Noise multiple to define signal threshold
4332
4874
4333 multDet_timeLimit: Multiple Detection Removal time limit in seconds
4875 multDet_timeLimit: Multiple Detection Removal time limit in seconds
4334 multDet_rangeLimit: Multiple Detection Removal range limit in km
4876 multDet_rangeLimit: Multiple Detection Removal range limit in km
4335
4877
4336 phaseThresh: Maximum phase difference between receiver to be consider a meteor
4878 phaseThresh: Maximum phase difference between receiver to be consider a meteor
4337 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
4879 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
4338
4880
4339 hmin: Minimum Height of the meteor to use it in the further wind estimations
4881 hmin: Minimum Height of the meteor to use it in the further wind estimations
4340 hmax: Maximum Height of the meteor to use it in the further wind estimations
4882 hmax: Maximum Height of the meteor to use it in the further wind estimations
4341 azimuth: Azimuth angle correction
4883 azimuth: Azimuth angle correction
4342
4884
4343 Affected:
4885 Affected:
4344 self.dataOut.data_param
4886 self.dataOut.data_param
4345
4887
4346 Rejection Criteria (Errors):
4888 Rejection Criteria (Errors):
4347 0: No error; analysis OK
4889 0: No error; analysis OK
4348 1: SNR < SNR threshold
4890 1: SNR < SNR threshold
4349 2: angle of arrival (AOA) ambiguously determined
4891 2: angle of arrival (AOA) ambiguously determined
4350 3: AOA estimate not feasible
4892 3: AOA estimate not feasible
4351 4: Large difference in AOAs obtained from different antenna baselines
4893 4: Large difference in AOAs obtained from different antenna baselines
4352 5: echo at start or end of time series
4894 5: echo at start or end of time series
4353 6: echo less than 5 examples long; too short for analysis
4895 6: echo less than 5 examples long; too short for analysis
4354 7: echo rise exceeds 0.3s
4896 7: echo rise exceeds 0.3s
4355 8: echo decay time less than twice rise time
4897 8: echo decay time less than twice rise time
4356 9: large power level before echo
4898 9: large power level before echo
4357 10: large power level after echo
4899 10: large power level after echo
4358 11: poor fit to amplitude for estimation of decay time
4900 11: poor fit to amplitude for estimation of decay time
4359 12: poor fit to CCF phase variation for estimation of radial drift velocity
4901 12: poor fit to CCF phase variation for estimation of radial drift velocity
4360 13: height unresolvable echo: not valid height within 70 to 110 km
4902 13: height unresolvable echo: not valid height within 70 to 110 km
4361 14: height ambiguous echo: more then one possible height within 70 to 110 km
4903 14: height ambiguous echo: more then one possible height within 70 to 110 km
4362 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
4904 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
4363 16: oscilatory echo, indicating event most likely not an underdense echo
4905 16: oscilatory echo, indicating event most likely not an underdense echo
4364
4906
4365 17: phase difference in meteor Reestimation
4907 17: phase difference in meteor Reestimation
4366
4908
4367 Data Storage:
4909 Data Storage:
4368 Meteors for Wind Estimation (8):
4910 Meteors for Wind Estimation (8):
4369 Utc Time | Range Height
4911 Utc Time | Range Height
4370 Azimuth Zenith errorCosDir
4912 Azimuth Zenith errorCosDir
4371 VelRad errorVelRad
4913 VelRad errorVelRad
4372 Phase0 Phase1 Phase2 Phase3
4914 Phase0 Phase1 Phase2 Phase3
4373 TypeError
4915 TypeError
4374
4916
4375 '''
4917 '''
4376
4918
4377 def run(self, dataOut, hei_ref = None, tauindex = 0,
4919 def run(self, dataOut, hei_ref = None, tauindex = 0,
4378 phaseOffsets = None,
4920 phaseOffsets = None,
4379 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
4921 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
4380 noise_timeStep = 4, noise_multiple = 4,
4922 noise_timeStep = 4, noise_multiple = 4,
4381 multDet_timeLimit = 1, multDet_rangeLimit = 3,
4923 multDet_timeLimit = 1, multDet_rangeLimit = 3,
4382 phaseThresh = 20, SNRThresh = 5,
4924 phaseThresh = 20, SNRThresh = 5,
4383 hmin = 50, hmax=150, azimuth = 0,
4925 hmin = 50, hmax=150, azimuth = 0,
4384 channelPositions = None) :
4926 channelPositions = None) :
4385
4927
4386
4928
4387 #Getting Pairslist
4929 #Getting Pairslist
4388 if channelPositions is None:
4930 if channelPositions is None:
4389 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4931 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4390 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4932 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4391 meteorOps = SMOperations()
4933 meteorOps = SMOperations()
4392 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4934 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4393 heiRang = dataOut.heightList
4935 heiRang = dataOut.heightList
4394 #Get Beacon signal - No Beacon signal anymore
4936 #Get Beacon signal - No Beacon signal anymore
4395 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
4937 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
4396 #
4938 #
4397 # if hei_ref != None:
4939 # if hei_ref != None:
4398 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
4940 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
4399 #
4941 #
4400
4942
4401
4943
4402 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
4944 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
4403 # see if the user put in pre defined phase shifts
4945 # see if the user put in pre defined phase shifts
4404 voltsPShift = dataOut.data_pre.copy()
4946 voltsPShift = dataOut.data_pre.copy()
4405
4947
4406 # if predefinedPhaseShifts != None:
4948 # if predefinedPhaseShifts != None:
4407 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
4949 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
4408 #
4950 #
4409 # # elif beaconPhaseShifts:
4951 # # elif beaconPhaseShifts:
4410 # # #get hardware phase shifts using beacon signal
4952 # # #get hardware phase shifts using beacon signal
4411 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
4953 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
4412 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
4954 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
4413 #
4955 #
4414 # else:
4956 # else:
4415 # hardwarePhaseShifts = numpy.zeros(5)
4957 # hardwarePhaseShifts = numpy.zeros(5)
4416 #
4958 #
4417 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
4959 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
4418 # for i in range(self.dataOut.data_pre.shape[0]):
4960 # for i in range(self.dataOut.data_pre.shape[0]):
4419 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
4961 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
4420
4962
4421 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
4963 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
4422
4964
4423 #Remove DC
4965 #Remove DC
4424 voltsDC = numpy.mean(voltsPShift,1)
4966 voltsDC = numpy.mean(voltsPShift,1)
4425 voltsDC = numpy.mean(voltsDC,1)
4967 voltsDC = numpy.mean(voltsDC,1)
4426 for i in range(voltsDC.shape[0]):
4968 for i in range(voltsDC.shape[0]):
4427 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
4969 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
4428
4970
4429 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
4971 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
4430 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
4972 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
4431
4973
4432 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
4974 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
4433 #Coherent Detection
4975 #Coherent Detection
4434 if cohDetection:
4976 if cohDetection:
4435 #use coherent detection to get the net power
4977 #use coherent detection to get the net power
4436 cohDet_thresh = cohDet_thresh*numpy.pi/180
4978 cohDet_thresh = cohDet_thresh*numpy.pi/180
4437 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
4979 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
4438
4980
4439 #Non-coherent detection!
4981 #Non-coherent detection!
4440 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
4982 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
4441 #********** END OF COH/NON-COH POWER CALCULATION**********************
4983 #********** END OF COH/NON-COH POWER CALCULATION**********************
4442
4984
4443 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
4985 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
4444 #Get noise
4986 #Get noise
4445 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
4987 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
4446 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
4988 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
4447 #Get signal threshold
4989 #Get signal threshold
4448 signalThresh = noise_multiple*noise
4990 signalThresh = noise_multiple*noise
4449 #Meteor echoes detection
4991 #Meteor echoes detection
4450 listMeteors = self.__findMeteors(powerNet, signalThresh)
4992 listMeteors = self.__findMeteors(powerNet, signalThresh)
4451 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
4993 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
4452
4994
4453 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
4995 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
4454 #Parameters
4996 #Parameters
4455 heiRange = dataOut.heightList
4997 heiRange = dataOut.heightList
4456 rangeInterval = heiRange[1] - heiRange[0]
4998 rangeInterval = heiRange[1] - heiRange[0]
4457 rangeLimit = multDet_rangeLimit/rangeInterval
4999 rangeLimit = multDet_rangeLimit/rangeInterval
4458 timeLimit = multDet_timeLimit/dataOut.timeInterval
5000 timeLimit = multDet_timeLimit/dataOut.timeInterval
4459 #Multiple detection removals
5001 #Multiple detection removals
4460 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
5002 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
4461 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
5003 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
4462
5004
4463 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
5005 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
4464 #Parameters
5006 #Parameters
4465 phaseThresh = phaseThresh*numpy.pi/180
5007 phaseThresh = phaseThresh*numpy.pi/180
4466 thresh = [phaseThresh, noise_multiple, SNRThresh]
5008 thresh = [phaseThresh, noise_multiple, SNRThresh]
4467 #Meteor reestimation (Errors N 1, 6, 12, 17)
5009 #Meteor reestimation (Errors N 1, 6, 12, 17)
4468 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
5010 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
4469 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
5011 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
4470 #Estimation of decay times (Errors N 7, 8, 11)
5012 #Estimation of decay times (Errors N 7, 8, 11)
4471 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
5013 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
4472 #******************* END OF METEOR REESTIMATION *******************
5014 #******************* END OF METEOR REESTIMATION *******************
4473
5015
4474 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
5016 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
4475 #Calculating Radial Velocity (Error N 15)
5017 #Calculating Radial Velocity (Error N 15)
4476 radialStdThresh = 10
5018 radialStdThresh = 10
4477 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
5019 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
4478
5020
4479 if len(listMeteors4) > 0:
5021 if len(listMeteors4) > 0:
4480 #Setting New Array
5022 #Setting New Array
4481 date = dataOut.utctime
5023 date = dataOut.utctime
4482 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
5024 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
4483
5025
4484 #Correcting phase offset
5026 #Correcting phase offset
4485 if phaseOffsets != None:
5027 if phaseOffsets != None:
4486 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5028 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4487 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5029 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4488
5030
4489 #Second Pairslist
5031 #Second Pairslist
4490 pairsList = []
5032 pairsList = []
4491 pairx = (0,1)
5033 pairx = (0,1)
4492 pairy = (2,3)
5034 pairy = (2,3)
4493 pairsList.append(pairx)
5035 pairsList.append(pairx)
4494 pairsList.append(pairy)
5036 pairsList.append(pairy)
4495
5037
4496 jph = numpy.array([0,0,0,0])
5038 jph = numpy.array([0,0,0,0])
4497 h = (hmin,hmax)
5039 h = (hmin,hmax)
4498 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5040 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4499
5041
4500 # #Calculate AOA (Error N 3, 4)
5042 # #Calculate AOA (Error N 3, 4)
4501 # #JONES ET AL. 1998
5043 # #JONES ET AL. 1998
4502 # error = arrayParameters[:,-1]
5044 # error = arrayParameters[:,-1]
4503 # AOAthresh = numpy.pi/8
5045 # AOAthresh = numpy.pi/8
4504 # phases = -arrayParameters[:,9:13]
5046 # phases = -arrayParameters[:,9:13]
4505 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
5047 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
4506 #
5048 #
4507 # #Calculate Heights (Error N 13 and 14)
5049 # #Calculate Heights (Error N 13 and 14)
4508 # error = arrayParameters[:,-1]
5050 # error = arrayParameters[:,-1]
4509 # Ranges = arrayParameters[:,2]
5051 # Ranges = arrayParameters[:,2]
4510 # zenith = arrayParameters[:,5]
5052 # zenith = arrayParameters[:,5]
4511 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
5053 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
4512 # error = arrayParameters[:,-1]
5054 # error = arrayParameters[:,-1]
4513 #********************* END OF PARAMETERS CALCULATION **************************
5055 #********************* END OF PARAMETERS CALCULATION **************************
4514
5056
4515 #***************************+ PASS DATA TO NEXT STEP **********************
5057 #***************************+ PASS DATA TO NEXT STEP **********************
4516 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
5058 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
4517 dataOut.data_param = arrayParameters
5059 dataOut.data_param = arrayParameters
4518
5060
4519 if arrayParameters is None:
5061 if arrayParameters is None:
4520 dataOut.flagNoData = True
5062 dataOut.flagNoData = True
4521 else:
5063 else:
4522 dataOut.flagNoData = True
5064 dataOut.flagNoData = True
4523
5065
4524 return
5066 return
4525
5067
4526 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
5068 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
4527
5069
4528 minIndex = min(newheis[0])
5070 minIndex = min(newheis[0])
4529 maxIndex = max(newheis[0])
5071 maxIndex = max(newheis[0])
4530
5072
4531 voltage = voltage0[:,:,minIndex:maxIndex+1]
5073 voltage = voltage0[:,:,minIndex:maxIndex+1]
4532 nLength = voltage.shape[1]/n
5074 nLength = voltage.shape[1]/n
4533 nMin = 0
5075 nMin = 0
4534 nMax = 0
5076 nMax = 0
4535 phaseOffset = numpy.zeros((len(pairslist),n))
5077 phaseOffset = numpy.zeros((len(pairslist),n))
4536
5078
4537 for i in range(n):
5079 for i in range(n):
4538 nMax += nLength
5080 nMax += nLength
4539 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
5081 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
4540 phaseCCF = numpy.mean(phaseCCF, axis = 2)
5082 phaseCCF = numpy.mean(phaseCCF, axis = 2)
4541 phaseOffset[:,i] = phaseCCF.transpose()
5083 phaseOffset[:,i] = phaseCCF.transpose()
4542 nMin = nMax
5084 nMin = nMax
4543 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
5085 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
4544
5086
4545 #Remove Outliers
5087 #Remove Outliers
4546 factor = 2
5088 factor = 2
4547 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
5089 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
4548 dw = numpy.std(wt,axis = 1)
5090 dw = numpy.std(wt,axis = 1)
4549 dw = dw.reshape((dw.size,1))
5091 dw = dw.reshape((dw.size,1))
4550 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
5092 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
4551 phaseOffset[ind] = numpy.nan
5093 phaseOffset[ind] = numpy.nan
4552 phaseOffset = stats.nanmean(phaseOffset, axis=1)
5094 phaseOffset = stats.nanmean(phaseOffset, axis=1)
4553
5095
4554 return phaseOffset
5096 return phaseOffset
4555
5097
4556 def __shiftPhase(self, data, phaseShift):
5098 def __shiftPhase(self, data, phaseShift):
4557 #this will shift the phase of a complex number
5099 #this will shift the phase of a complex number
4558 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
5100 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
4559 return dataShifted
5101 return dataShifted
4560
5102
4561 def __estimatePhaseDifference(self, array, pairslist):
5103 def __estimatePhaseDifference(self, array, pairslist):
4562 nChannel = array.shape[0]
5104 nChannel = array.shape[0]
4563 nHeights = array.shape[2]
5105 nHeights = array.shape[2]
4564 numPairs = len(pairslist)
5106 numPairs = len(pairslist)
4565 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
5107 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
4566 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
5108 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
4567
5109
4568 #Correct phases
5110 #Correct phases
4569 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
5111 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
4570 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5112 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4571
5113
4572 if indDer[0].shape[0] > 0:
5114 if indDer[0].shape[0] > 0:
4573 for i in range(indDer[0].shape[0]):
5115 for i in range(indDer[0].shape[0]):
4574 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
5116 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
4575 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
5117 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
4576
5118
4577 # for j in range(numSides):
5119 # for j in range(numSides):
4578 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
5120 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
4579 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
5121 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
4580 #
5122 #
4581 #Linear
5123 #Linear
4582 phaseInt = numpy.zeros((numPairs,1))
5124 phaseInt = numpy.zeros((numPairs,1))
4583 angAllCCF = phaseCCF[:,[0,1,3,4],0]
5125 angAllCCF = phaseCCF[:,[0,1,3,4],0]
4584 for j in range(numPairs):
5126 for j in range(numPairs):
4585 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
5127 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
4586 phaseInt[j] = fit[1]
5128 phaseInt[j] = fit[1]
4587 #Phase Differences
5129 #Phase Differences
4588 phaseDiff = phaseInt - phaseCCF[:,2,:]
5130 phaseDiff = phaseInt - phaseCCF[:,2,:]
4589 phaseArrival = phaseInt.reshape(phaseInt.size)
5131 phaseArrival = phaseInt.reshape(phaseInt.size)
4590
5132
4591 #Dealias
5133 #Dealias
4592 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
5134 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
4593 # indAlias = numpy.where(phaseArrival > numpy.pi)
5135 # indAlias = numpy.where(phaseArrival > numpy.pi)
4594 # phaseArrival[indAlias] -= 2*numpy.pi
5136 # phaseArrival[indAlias] -= 2*numpy.pi
4595 # indAlias = numpy.where(phaseArrival < -numpy.pi)
5137 # indAlias = numpy.where(phaseArrival < -numpy.pi)
4596 # phaseArrival[indAlias] += 2*numpy.pi
5138 # phaseArrival[indAlias] += 2*numpy.pi
4597
5139
4598 return phaseDiff, phaseArrival
5140 return phaseDiff, phaseArrival
4599
5141
4600 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
5142 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
4601 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
5143 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
4602 #find the phase shifts of each channel over 1 second intervals
5144 #find the phase shifts of each channel over 1 second intervals
4603 #only look at ranges below the beacon signal
5145 #only look at ranges below the beacon signal
4604 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5146 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4605 numBlocks = int(volts.shape[1]/numProfPerBlock)
5147 numBlocks = int(volts.shape[1]/numProfPerBlock)
4606 numHeights = volts.shape[2]
5148 numHeights = volts.shape[2]
4607 nChannel = volts.shape[0]
5149 nChannel = volts.shape[0]
4608 voltsCohDet = volts.copy()
5150 voltsCohDet = volts.copy()
4609
5151
4610 pairsarray = numpy.array(pairslist)
5152 pairsarray = numpy.array(pairslist)
4611 indSides = pairsarray[:,1]
5153 indSides = pairsarray[:,1]
4612 # indSides = numpy.array(range(nChannel))
5154 # indSides = numpy.array(range(nChannel))
4613 # indSides = numpy.delete(indSides, indCenter)
5155 # indSides = numpy.delete(indSides, indCenter)
4614 #
5156 #
4615 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
5157 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
4616 listBlocks = numpy.array_split(volts, numBlocks, 1)
5158 listBlocks = numpy.array_split(volts, numBlocks, 1)
4617
5159
4618 startInd = 0
5160 startInd = 0
4619 endInd = 0
5161 endInd = 0
4620
5162
4621 for i in range(numBlocks):
5163 for i in range(numBlocks):
4622 startInd = endInd
5164 startInd = endInd
4623 endInd = endInd + listBlocks[i].shape[1]
5165 endInd = endInd + listBlocks[i].shape[1]
4624
5166
4625 arrayBlock = listBlocks[i]
5167 arrayBlock = listBlocks[i]
4626 # arrayBlockCenter = listCenter[i]
5168 # arrayBlockCenter = listCenter[i]
4627
5169
4628 #Estimate the Phase Difference
5170 #Estimate the Phase Difference
4629 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
5171 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
4630 #Phase Difference RMS
5172 #Phase Difference RMS
4631 arrayPhaseRMS = numpy.abs(phaseDiff)
5173 arrayPhaseRMS = numpy.abs(phaseDiff)
4632 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
5174 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
4633 indPhase = numpy.where(phaseRMSaux==4)
5175 indPhase = numpy.where(phaseRMSaux==4)
4634 #Shifting
5176 #Shifting
4635 if indPhase[0].shape[0] > 0:
5177 if indPhase[0].shape[0] > 0:
4636 for j in range(indSides.size):
5178 for j in range(indSides.size):
4637 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
5179 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
4638 voltsCohDet[:,startInd:endInd,:] = arrayBlock
5180 voltsCohDet[:,startInd:endInd,:] = arrayBlock
4639
5181
4640 return voltsCohDet
5182 return voltsCohDet
4641
5183
4642 def __calculateCCF(self, volts, pairslist ,laglist):
5184 def __calculateCCF(self, volts, pairslist ,laglist):
4643
5185
4644 nHeights = volts.shape[2]
5186 nHeights = volts.shape[2]
4645 nPoints = volts.shape[1]
5187 nPoints = volts.shape[1]
4646 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
5188 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
4647
5189
4648 for i in range(len(pairslist)):
5190 for i in range(len(pairslist)):
4649 volts1 = volts[pairslist[i][0]]
5191 volts1 = volts[pairslist[i][0]]
4650 volts2 = volts[pairslist[i][1]]
5192 volts2 = volts[pairslist[i][1]]
4651
5193
4652 for t in range(len(laglist)):
5194 for t in range(len(laglist)):
4653 idxT = laglist[t]
5195 idxT = laglist[t]
4654 if idxT >= 0:
5196 if idxT >= 0:
4655 vStacked = numpy.vstack((volts2[idxT:,:],
5197 vStacked = numpy.vstack((volts2[idxT:,:],
4656 numpy.zeros((idxT, nHeights),dtype='complex')))
5198 numpy.zeros((idxT, nHeights),dtype='complex')))
4657 else:
5199 else:
4658 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
5200 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
4659 volts2[:(nPoints + idxT),:]))
5201 volts2[:(nPoints + idxT),:]))
4660 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
5202 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
4661
5203
4662 vStacked = None
5204 vStacked = None
4663 return voltsCCF
5205 return voltsCCF
4664
5206
4665 def __getNoise(self, power, timeSegment, timeInterval):
5207 def __getNoise(self, power, timeSegment, timeInterval):
4666 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5208 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4667 numBlocks = int(power.shape[0]/numProfPerBlock)
5209 numBlocks = int(power.shape[0]/numProfPerBlock)
4668 numHeights = power.shape[1]
5210 numHeights = power.shape[1]
4669
5211
4670 listPower = numpy.array_split(power, numBlocks, 0)
5212 listPower = numpy.array_split(power, numBlocks, 0)
4671 noise = numpy.zeros((power.shape[0], power.shape[1]))
5213 noise = numpy.zeros((power.shape[0], power.shape[1]))
4672 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
5214 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
4673
5215
4674 startInd = 0
5216 startInd = 0
4675 endInd = 0
5217 endInd = 0
4676
5218
4677 for i in range(numBlocks): #split por canal
5219 for i in range(numBlocks): #split por canal
4678 startInd = endInd
5220 startInd = endInd
4679 endInd = endInd + listPower[i].shape[0]
5221 endInd = endInd + listPower[i].shape[0]
4680
5222
4681 arrayBlock = listPower[i]
5223 arrayBlock = listPower[i]
4682 noiseAux = numpy.mean(arrayBlock, 0)
5224 noiseAux = numpy.mean(arrayBlock, 0)
4683 # noiseAux = numpy.median(noiseAux)
5225 # noiseAux = numpy.median(noiseAux)
4684 # noiseAux = numpy.mean(arrayBlock)
5226 # noiseAux = numpy.mean(arrayBlock)
4685 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
5227 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
4686
5228
4687 noiseAux1 = numpy.mean(arrayBlock)
5229 noiseAux1 = numpy.mean(arrayBlock)
4688 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
5230 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
4689
5231
4690 return noise, noise1
5232 return noise, noise1
4691
5233
4692 def __findMeteors(self, power, thresh):
5234 def __findMeteors(self, power, thresh):
4693 nProf = power.shape[0]
5235 nProf = power.shape[0]
4694 nHeights = power.shape[1]
5236 nHeights = power.shape[1]
4695 listMeteors = []
5237 listMeteors = []
4696
5238
4697 for i in range(nHeights):
5239 for i in range(nHeights):
4698 powerAux = power[:,i]
5240 powerAux = power[:,i]
4699 threshAux = thresh[:,i]
5241 threshAux = thresh[:,i]
4700
5242
4701 indUPthresh = numpy.where(powerAux > threshAux)[0]
5243 indUPthresh = numpy.where(powerAux > threshAux)[0]
4702 indDNthresh = numpy.where(powerAux <= threshAux)[0]
5244 indDNthresh = numpy.where(powerAux <= threshAux)[0]
4703
5245
4704 j = 0
5246 j = 0
4705
5247
4706 while (j < indUPthresh.size - 2):
5248 while (j < indUPthresh.size - 2):
4707 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
5249 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
4708 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
5250 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
4709 indDNthresh = indDNthresh[indDNAux]
5251 indDNthresh = indDNthresh[indDNAux]
4710
5252
4711 if (indDNthresh.size > 0):
5253 if (indDNthresh.size > 0):
4712 indEnd = indDNthresh[0] - 1
5254 indEnd = indDNthresh[0] - 1
4713 indInit = indUPthresh[j]
5255 indInit = indUPthresh[j]
4714
5256
4715 meteor = powerAux[indInit:indEnd + 1]
5257 meteor = powerAux[indInit:indEnd + 1]
4716 indPeak = meteor.argmax() + indInit
5258 indPeak = meteor.argmax() + indInit
4717 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
5259 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
4718
5260
4719 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
5261 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
4720 j = numpy.where(indUPthresh == indEnd)[0] + 1
5262 j = numpy.where(indUPthresh == indEnd)[0] + 1
4721 else: j+=1
5263 else: j+=1
4722 else: j+=1
5264 else: j+=1
4723
5265
4724 return listMeteors
5266 return listMeteors
4725
5267
4726 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
5268 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
4727
5269
4728 arrayMeteors = numpy.asarray(listMeteors)
5270 arrayMeteors = numpy.asarray(listMeteors)
4729 listMeteors1 = []
5271 listMeteors1 = []
4730
5272
4731 while arrayMeteors.shape[0] > 0:
5273 while arrayMeteors.shape[0] > 0:
4732 FLAs = arrayMeteors[:,4]
5274 FLAs = arrayMeteors[:,4]
4733 maxFLA = FLAs.argmax()
5275 maxFLA = FLAs.argmax()
4734 listMeteors1.append(arrayMeteors[maxFLA,:])
5276 listMeteors1.append(arrayMeteors[maxFLA,:])
4735
5277
4736 MeteorInitTime = arrayMeteors[maxFLA,1]
5278 MeteorInitTime = arrayMeteors[maxFLA,1]
4737 MeteorEndTime = arrayMeteors[maxFLA,3]
5279 MeteorEndTime = arrayMeteors[maxFLA,3]
4738 MeteorHeight = arrayMeteors[maxFLA,0]
5280 MeteorHeight = arrayMeteors[maxFLA,0]
4739
5281
4740 #Check neighborhood
5282 #Check neighborhood
4741 maxHeightIndex = MeteorHeight + rangeLimit
5283 maxHeightIndex = MeteorHeight + rangeLimit
4742 minHeightIndex = MeteorHeight - rangeLimit
5284 minHeightIndex = MeteorHeight - rangeLimit
4743 minTimeIndex = MeteorInitTime - timeLimit
5285 minTimeIndex = MeteorInitTime - timeLimit
4744 maxTimeIndex = MeteorEndTime + timeLimit
5286 maxTimeIndex = MeteorEndTime + timeLimit
4745
5287
4746 #Check Heights
5288 #Check Heights
4747 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
5289 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
4748 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
5290 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
4749 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
5291 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
4750
5292
4751 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
5293 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
4752
5294
4753 return listMeteors1
5295 return listMeteors1
4754
5296
4755 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
5297 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
4756 numHeights = volts.shape[2]
5298 numHeights = volts.shape[2]
4757 nChannel = volts.shape[0]
5299 nChannel = volts.shape[0]
4758
5300
4759 thresholdPhase = thresh[0]
5301 thresholdPhase = thresh[0]
4760 thresholdNoise = thresh[1]
5302 thresholdNoise = thresh[1]
4761 thresholdDB = float(thresh[2])
5303 thresholdDB = float(thresh[2])
4762
5304
4763 thresholdDB1 = 10**(thresholdDB/10)
5305 thresholdDB1 = 10**(thresholdDB/10)
4764 pairsarray = numpy.array(pairslist)
5306 pairsarray = numpy.array(pairslist)
4765 indSides = pairsarray[:,1]
5307 indSides = pairsarray[:,1]
4766
5308
4767 pairslist1 = list(pairslist)
5309 pairslist1 = list(pairslist)
4768 pairslist1.append((0,1))
5310 pairslist1.append((0,1))
4769 pairslist1.append((3,4))
5311 pairslist1.append((3,4))
4770
5312
4771 listMeteors1 = []
5313 listMeteors1 = []
4772 listPowerSeries = []
5314 listPowerSeries = []
4773 listVoltageSeries = []
5315 listVoltageSeries = []
4774 #volts has the war data
5316 #volts has the war data
4775
5317
4776 if frequency == 30e6:
5318 if frequency == 30e6:
4777 timeLag = 45*10**-3
5319 timeLag = 45*10**-3
4778 else:
5320 else:
4779 timeLag = 15*10**-3
5321 timeLag = 15*10**-3
4780 lag = numpy.ceil(timeLag/timeInterval)
5322 lag = numpy.ceil(timeLag/timeInterval)
4781
5323
4782 for i in range(len(listMeteors)):
5324 for i in range(len(listMeteors)):
4783
5325
4784 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
5326 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
4785 meteorAux = numpy.zeros(16)
5327 meteorAux = numpy.zeros(16)
4786
5328
4787 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
5329 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
4788 mHeight = listMeteors[i][0]
5330 mHeight = listMeteors[i][0]
4789 mStart = listMeteors[i][1]
5331 mStart = listMeteors[i][1]
4790 mPeak = listMeteors[i][2]
5332 mPeak = listMeteors[i][2]
4791 mEnd = listMeteors[i][3]
5333 mEnd = listMeteors[i][3]
4792
5334
4793 #get the volt data between the start and end times of the meteor
5335 #get the volt data between the start and end times of the meteor
4794 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
5336 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
4795 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5337 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4796
5338
4797 #3.6. Phase Difference estimation
5339 #3.6. Phase Difference estimation
4798 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
5340 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
4799
5341
4800 #3.7. Phase difference removal & meteor start, peak and end times reestimated
5342 #3.7. Phase difference removal & meteor start, peak and end times reestimated
4801 #meteorVolts0.- all Channels, all Profiles
5343 #meteorVolts0.- all Channels, all Profiles
4802 meteorVolts0 = volts[:,:,mHeight]
5344 meteorVolts0 = volts[:,:,mHeight]
4803 meteorThresh = noise[:,mHeight]*thresholdNoise
5345 meteorThresh = noise[:,mHeight]*thresholdNoise
4804 meteorNoise = noise[:,mHeight]
5346 meteorNoise = noise[:,mHeight]
4805 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
5347 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
4806 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
5348 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
4807
5349
4808 #Times reestimation
5350 #Times reestimation
4809 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
5351 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
4810 if mStart1.size > 0:
5352 if mStart1.size > 0:
4811 mStart1 = mStart1[-1] + 1
5353 mStart1 = mStart1[-1] + 1
4812
5354
4813 else:
5355 else:
4814 mStart1 = mPeak
5356 mStart1 = mPeak
4815
5357
4816 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
5358 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
4817 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
5359 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
4818 if mEndDecayTime1.size == 0:
5360 if mEndDecayTime1.size == 0:
4819 mEndDecayTime1 = powerNet0.size
5361 mEndDecayTime1 = powerNet0.size
4820 else:
5362 else:
4821 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
5363 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
4822 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
5364 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
4823
5365
4824 #meteorVolts1.- all Channels, from start to end
5366 #meteorVolts1.- all Channels, from start to end
4825 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
5367 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
4826 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
5368 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
4827 if meteorVolts2.shape[1] == 0:
5369 if meteorVolts2.shape[1] == 0:
4828 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
5370 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
4829 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
5371 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
4830 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
5372 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
4831 ##################### END PARAMETERS REESTIMATION #########################
5373 ##################### END PARAMETERS REESTIMATION #########################
4832
5374
4833 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
5375 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
4834 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
5376 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
4835 if meteorVolts2.shape[1] > 0:
5377 if meteorVolts2.shape[1] > 0:
4836 #Phase Difference re-estimation
5378 #Phase Difference re-estimation
4837 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
5379 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
4838 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
5380 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
4839 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
5381 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
4840 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
5382 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
4841 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
5383 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
4842
5384
4843 #Phase Difference RMS
5385 #Phase Difference RMS
4844 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
5386 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
4845 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
5387 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
4846 #Data from Meteor
5388 #Data from Meteor
4847 mPeak1 = powerNet1.argmax() + mStart1
5389 mPeak1 = powerNet1.argmax() + mStart1
4848 mPeakPower1 = powerNet1.max()
5390 mPeakPower1 = powerNet1.max()
4849 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
5391 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
4850 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
5392 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
4851 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
5393 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
4852 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
5394 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
4853 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
5395 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
4854 #Vectorize
5396 #Vectorize
4855 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
5397 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
4856 meteorAux[7:11] = phaseDiffint[0:4]
5398 meteorAux[7:11] = phaseDiffint[0:4]
4857
5399
4858 #Rejection Criterions
5400 #Rejection Criterions
4859 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
5401 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
4860 meteorAux[-1] = 17
5402 meteorAux[-1] = 17
4861 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
5403 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
4862 meteorAux[-1] = 1
5404 meteorAux[-1] = 1
4863
5405
4864
5406
4865 else:
5407 else:
4866 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
5408 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
4867 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
5409 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
4868 PowerSeries = 0
5410 PowerSeries = 0
4869
5411
4870 listMeteors1.append(meteorAux)
5412 listMeteors1.append(meteorAux)
4871 listPowerSeries.append(PowerSeries)
5413 listPowerSeries.append(PowerSeries)
4872 listVoltageSeries.append(meteorVolts1)
5414 listVoltageSeries.append(meteorVolts1)
4873
5415
4874 return listMeteors1, listPowerSeries, listVoltageSeries
5416 return listMeteors1, listPowerSeries, listVoltageSeries
4875
5417
4876 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
5418 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
4877
5419
4878 threshError = 10
5420 threshError = 10
4879 #Depending if it is 30 or 50 MHz
5421 #Depending if it is 30 or 50 MHz
4880 if frequency == 30e6:
5422 if frequency == 30e6:
4881 timeLag = 45*10**-3
5423 timeLag = 45*10**-3
4882 else:
5424 else:
4883 timeLag = 15*10**-3
5425 timeLag = 15*10**-3
4884 lag = numpy.ceil(timeLag/timeInterval)
5426 lag = numpy.ceil(timeLag/timeInterval)
4885
5427
4886 listMeteors1 = []
5428 listMeteors1 = []
4887
5429
4888 for i in range(len(listMeteors)):
5430 for i in range(len(listMeteors)):
4889 meteorPower = listPower[i]
5431 meteorPower = listPower[i]
4890 meteorAux = listMeteors[i]
5432 meteorAux = listMeteors[i]
4891
5433
4892 if meteorAux[-1] == 0:
5434 if meteorAux[-1] == 0:
4893
5435
4894 try:
5436 try:
4895 indmax = meteorPower.argmax()
5437 indmax = meteorPower.argmax()
4896 indlag = indmax + lag
5438 indlag = indmax + lag
4897
5439
4898 y = meteorPower[indlag:]
5440 y = meteorPower[indlag:]
4899 x = numpy.arange(0, y.size)*timeLag
5441 x = numpy.arange(0, y.size)*timeLag
4900
5442
4901 #first guess
5443 #first guess
4902 a = y[0]
5444 a = y[0]
4903 tau = timeLag
5445 tau = timeLag
4904 #exponential fit
5446 #exponential fit
4905 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
5447 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
4906 y1 = self.__exponential_function(x, *popt)
5448 y1 = self.__exponential_function(x, *popt)
4907 #error estimation
5449 #error estimation
4908 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
5450 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
4909
5451
4910 decayTime = popt[1]
5452 decayTime = popt[1]
4911 riseTime = indmax*timeInterval
5453 riseTime = indmax*timeInterval
4912 meteorAux[11:13] = [decayTime, error]
5454 meteorAux[11:13] = [decayTime, error]
4913
5455
4914 #Table items 7, 8 and 11
5456 #Table items 7, 8 and 11
4915 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
5457 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
4916 meteorAux[-1] = 7
5458 meteorAux[-1] = 7
4917 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
5459 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
4918 meteorAux[-1] = 8
5460 meteorAux[-1] = 8
4919 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
5461 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
4920 meteorAux[-1] = 11
5462 meteorAux[-1] = 11
4921
5463
4922
5464
4923 except:
5465 except:
4924 meteorAux[-1] = 11
5466 meteorAux[-1] = 11
4925
5467
4926
5468
4927 listMeteors1.append(meteorAux)
5469 listMeteors1.append(meteorAux)
4928
5470
4929 return listMeteors1
5471 return listMeteors1
4930
5472
4931 #Exponential Function
5473 #Exponential Function
4932
5474
4933 def __exponential_function(self, x, a, tau):
5475 def __exponential_function(self, x, a, tau):
4934 y = a*numpy.exp(-x/tau)
5476 y = a*numpy.exp(-x/tau)
4935 return y
5477 return y
4936
5478
4937 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
5479 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
4938
5480
4939 pairslist1 = list(pairslist)
5481 pairslist1 = list(pairslist)
4940 pairslist1.append((0,1))
5482 pairslist1.append((0,1))
4941 pairslist1.append((3,4))
5483 pairslist1.append((3,4))
4942 numPairs = len(pairslist1)
5484 numPairs = len(pairslist1)
4943 #Time Lag
5485 #Time Lag
4944 timeLag = 45*10**-3
5486 timeLag = 45*10**-3
4945 c = 3e8
5487 c = 3e8
4946 lag = numpy.ceil(timeLag/timeInterval)
5488 lag = numpy.ceil(timeLag/timeInterval)
4947 freq = 30e6
5489 freq = 30e6
4948
5490
4949 listMeteors1 = []
5491 listMeteors1 = []
4950
5492
4951 for i in range(len(listMeteors)):
5493 for i in range(len(listMeteors)):
4952 meteorAux = listMeteors[i]
5494 meteorAux = listMeteors[i]
4953 if meteorAux[-1] == 0:
5495 if meteorAux[-1] == 0:
4954 mStart = listMeteors[i][1]
5496 mStart = listMeteors[i][1]
4955 mPeak = listMeteors[i][2]
5497 mPeak = listMeteors[i][2]
4956 mLag = mPeak - mStart + lag
5498 mLag = mPeak - mStart + lag
4957
5499
4958 #get the volt data between the start and end times of the meteor
5500 #get the volt data between the start and end times of the meteor
4959 meteorVolts = listVolts[i]
5501 meteorVolts = listVolts[i]
4960 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5502 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4961
5503
4962 #Get CCF
5504 #Get CCF
4963 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
5505 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
4964
5506
4965 #Method 2
5507 #Method 2
4966 slopes = numpy.zeros(numPairs)
5508 slopes = numpy.zeros(numPairs)
4967 time = numpy.array([-2,-1,1,2])*timeInterval
5509 time = numpy.array([-2,-1,1,2])*timeInterval
4968 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
5510 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
4969
5511
4970 #Correct phases
5512 #Correct phases
4971 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
5513 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
4972 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5514 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4973
5515
4974 if indDer[0].shape[0] > 0:
5516 if indDer[0].shape[0] > 0:
4975 for i in range(indDer[0].shape[0]):
5517 for i in range(indDer[0].shape[0]):
4976 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
5518 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
4977 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
5519 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
4978
5520
4979 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
5521 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
4980 for j in range(numPairs):
5522 for j in range(numPairs):
4981 fit = stats.linregress(time, angAllCCF[j,:])
5523 fit = stats.linregress(time, angAllCCF[j,:])
4982 slopes[j] = fit[0]
5524 slopes[j] = fit[0]
4983
5525
4984 #Remove Outlier
5526 #Remove Outlier
4985 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
5527 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4986 # slopes = numpy.delete(slopes,indOut)
5528 # slopes = numpy.delete(slopes,indOut)
4987 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
5529 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4988 # slopes = numpy.delete(slopes,indOut)
5530 # slopes = numpy.delete(slopes,indOut)
4989
5531
4990 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
5532 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
4991 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
5533 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
4992 meteorAux[-2] = radialError
5534 meteorAux[-2] = radialError
4993 meteorAux[-3] = radialVelocity
5535 meteorAux[-3] = radialVelocity
4994
5536
4995 #Setting Error
5537 #Setting Error
4996 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
5538 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
4997 if numpy.abs(radialVelocity) > 200:
5539 if numpy.abs(radialVelocity) > 200:
4998 meteorAux[-1] = 15
5540 meteorAux[-1] = 15
4999 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
5541 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
5000 elif radialError > radialStdThresh:
5542 elif radialError > radialStdThresh:
5001 meteorAux[-1] = 12
5543 meteorAux[-1] = 12
5002
5544
5003 listMeteors1.append(meteorAux)
5545 listMeteors1.append(meteorAux)
5004 return listMeteors1
5546 return listMeteors1
5005
5547
5006 def __setNewArrays(self, listMeteors, date, heiRang):
5548 def __setNewArrays(self, listMeteors, date, heiRang):
5007
5549
5008 #New arrays
5550 #New arrays
5009 arrayMeteors = numpy.array(listMeteors)
5551 arrayMeteors = numpy.array(listMeteors)
5010 arrayParameters = numpy.zeros((len(listMeteors), 13))
5552 arrayParameters = numpy.zeros((len(listMeteors), 13))
5011
5553
5012 #Date inclusion
5554 #Date inclusion
5013 # date = re.findall(r'\((.*?)\)', date)
5555 # date = re.findall(r'\((.*?)\)', date)
5014 # date = date[0].split(',')
5556 # date = date[0].split(',')
5015 # date = map(int, date)
5557 # date = map(int, date)
5016 #
5558 #
5017 # if len(date)<6:
5559 # if len(date)<6:
5018 # date.append(0)
5560 # date.append(0)
5019 #
5561 #
5020 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
5562 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
5021 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
5563 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
5022 arrayDate = numpy.tile(date, (len(listMeteors)))
5564 arrayDate = numpy.tile(date, (len(listMeteors)))
5023
5565
5024 #Meteor array
5566 #Meteor array
5025 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
5567 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
5026 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
5568 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
5027
5569
5028 #Parameters Array
5570 #Parameters Array
5029 arrayParameters[:,0] = arrayDate #Date
5571 arrayParameters[:,0] = arrayDate #Date
5030 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
5572 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
5031 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
5573 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
5032 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
5574 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
5033 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
5575 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
5034
5576
5035
5577
5036 return arrayParameters
5578 return arrayParameters
5037
5579
5038 class CorrectSMPhases(Operation):
5580 class CorrectSMPhases(Operation):
5039
5581
5040 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
5582 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
5041
5583
5042 arrayParameters = dataOut.data_param
5584 arrayParameters = dataOut.data_param
5043 pairsList = []
5585 pairsList = []
5044 pairx = (0,1)
5586 pairx = (0,1)
5045 pairy = (2,3)
5587 pairy = (2,3)
5046 pairsList.append(pairx)
5588 pairsList.append(pairx)
5047 pairsList.append(pairy)
5589 pairsList.append(pairy)
5048 jph = numpy.zeros(4)
5590 jph = numpy.zeros(4)
5049
5591
5050 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5592 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5051 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5593 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5052 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
5594 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
5053
5595
5054 meteorOps = SMOperations()
5596 meteorOps = SMOperations()
5055 if channelPositions is None:
5597 if channelPositions is None:
5056 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5598 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5057 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5599 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5058
5600
5059 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5601 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5060 h = (hmin,hmax)
5602 h = (hmin,hmax)
5061
5603
5062 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5604 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5063
5605
5064 dataOut.data_param = arrayParameters
5606 dataOut.data_param = arrayParameters
5065 return
5607 return
5066
5608
5067 class SMPhaseCalibration(Operation):
5609 class SMPhaseCalibration(Operation):
5068
5610
5069 __buffer = None
5611 __buffer = None
5070
5612
5071 __initime = None
5613 __initime = None
5072
5614
5073 __dataReady = False
5615 __dataReady = False
5074
5616
5075 __isConfig = False
5617 __isConfig = False
5076
5618
5077 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
5619 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
5078
5620
5079 dataTime = currentTime + paramInterval
5621 dataTime = currentTime + paramInterval
5080 deltaTime = dataTime - initTime
5622 deltaTime = dataTime - initTime
5081
5623
5082 if deltaTime >= outputInterval or deltaTime < 0:
5624 if deltaTime >= outputInterval or deltaTime < 0:
5083 return True
5625 return True
5084
5626
5085 return False
5627 return False
5086
5628
5087 def __getGammas(self, pairs, d, phases):
5629 def __getGammas(self, pairs, d, phases):
5088 gammas = numpy.zeros(2)
5630 gammas = numpy.zeros(2)
5089
5631
5090 for i in range(len(pairs)):
5632 for i in range(len(pairs)):
5091
5633
5092 pairi = pairs[i]
5634 pairi = pairs[i]
5093
5635
5094 phip3 = phases[:,pairi[0]]
5636 phip3 = phases[:,pairi[0]]
5095 d3 = d[pairi[0]]
5637 d3 = d[pairi[0]]
5096 phip2 = phases[:,pairi[1]]
5638 phip2 = phases[:,pairi[1]]
5097 d2 = d[pairi[1]]
5639 d2 = d[pairi[1]]
5098 #Calculating gamma
5640 #Calculating gamma
5099 # jdcos = alp1/(k*d1)
5641 # jdcos = alp1/(k*d1)
5100 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
5642 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
5101 jgamma = -phip2*d3/d2 - phip3
5643 jgamma = -phip2*d3/d2 - phip3
5102 jgamma = numpy.angle(numpy.exp(1j*jgamma))
5644 jgamma = numpy.angle(numpy.exp(1j*jgamma))
5103 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
5645 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
5104 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
5646 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
5105
5647
5106 #Revised distribution
5648 #Revised distribution
5107 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
5649 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
5108
5650
5109 #Histogram
5651 #Histogram
5110 nBins = 64
5652 nBins = 64
5111 rmin = -0.5*numpy.pi
5653 rmin = -0.5*numpy.pi
5112 rmax = 0.5*numpy.pi
5654 rmax = 0.5*numpy.pi
5113 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
5655 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
5114
5656
5115 meteorsY = phaseHisto[0]
5657 meteorsY = phaseHisto[0]
5116 phasesX = phaseHisto[1][:-1]
5658 phasesX = phaseHisto[1][:-1]
5117 width = phasesX[1] - phasesX[0]
5659 width = phasesX[1] - phasesX[0]
5118 phasesX += width/2
5660 phasesX += width/2
5119
5661
5120 #Gaussian aproximation
5662 #Gaussian aproximation
5121 bpeak = meteorsY.argmax()
5663 bpeak = meteorsY.argmax()
5122 peak = meteorsY.max()
5664 peak = meteorsY.max()
5123 jmin = bpeak - 5
5665 jmin = bpeak - 5
5124 jmax = bpeak + 5 + 1
5666 jmax = bpeak + 5 + 1
5125
5667
5126 if jmin<0:
5668 if jmin<0:
5127 jmin = 0
5669 jmin = 0
5128 jmax = 6
5670 jmax = 6
5129 elif jmax > meteorsY.size:
5671 elif jmax > meteorsY.size:
5130 jmin = meteorsY.size - 6
5672 jmin = meteorsY.size - 6
5131 jmax = meteorsY.size
5673 jmax = meteorsY.size
5132
5674
5133 x0 = numpy.array([peak,bpeak,50])
5675 x0 = numpy.array([peak,bpeak,50])
5134 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
5676 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
5135
5677
5136 #Gammas
5678 #Gammas
5137 gammas[i] = coeff[0][1]
5679 gammas[i] = coeff[0][1]
5138
5680
5139 return gammas
5681 return gammas
5140
5682
5141 def __residualFunction(self, coeffs, y, t):
5683 def __residualFunction(self, coeffs, y, t):
5142
5684
5143 return y - self.__gauss_function(t, coeffs)
5685 return y - self.__gauss_function(t, coeffs)
5144
5686
5145 def __gauss_function(self, t, coeffs):
5687 def __gauss_function(self, t, coeffs):
5146
5688
5147 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
5689 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
5148
5690
5149 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
5691 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
5150 meteorOps = SMOperations()
5692 meteorOps = SMOperations()
5151 nchan = 4
5693 nchan = 4
5152 pairx = pairsList[0] #x es 0
5694 pairx = pairsList[0] #x es 0
5153 pairy = pairsList[1] #y es 1
5695 pairy = pairsList[1] #y es 1
5154 center_xangle = 0
5696 center_xangle = 0
5155 center_yangle = 0
5697 center_yangle = 0
5156 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
5698 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
5157 ntimes = len(range_angle)
5699 ntimes = len(range_angle)
5158
5700
5159 nstepsx = 20
5701 nstepsx = 20
5160 nstepsy = 20
5702 nstepsy = 20
5161
5703
5162 for iz in range(ntimes):
5704 for iz in range(ntimes):
5163 min_xangle = -range_angle[iz]/2 + center_xangle
5705 min_xangle = -range_angle[iz]/2 + center_xangle
5164 max_xangle = range_angle[iz]/2 + center_xangle
5706 max_xangle = range_angle[iz]/2 + center_xangle
5165 min_yangle = -range_angle[iz]/2 + center_yangle
5707 min_yangle = -range_angle[iz]/2 + center_yangle
5166 max_yangle = range_angle[iz]/2 + center_yangle
5708 max_yangle = range_angle[iz]/2 + center_yangle
5167
5709
5168 inc_x = (max_xangle-min_xangle)/nstepsx
5710 inc_x = (max_xangle-min_xangle)/nstepsx
5169 inc_y = (max_yangle-min_yangle)/nstepsy
5711 inc_y = (max_yangle-min_yangle)/nstepsy
5170
5712
5171 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
5713 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
5172 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
5714 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
5173 penalty = numpy.zeros((nstepsx,nstepsy))
5715 penalty = numpy.zeros((nstepsx,nstepsy))
5174 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
5716 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
5175 jph = numpy.zeros(nchan)
5717 jph = numpy.zeros(nchan)
5176
5718
5177 # Iterations looking for the offset
5719 # Iterations looking for the offset
5178 for iy in range(int(nstepsy)):
5720 for iy in range(int(nstepsy)):
5179 for ix in range(int(nstepsx)):
5721 for ix in range(int(nstepsx)):
5180 d3 = d[pairsList[1][0]]
5722 d3 = d[pairsList[1][0]]
5181 d2 = d[pairsList[1][1]]
5723 d2 = d[pairsList[1][1]]
5182 d5 = d[pairsList[0][0]]
5724 d5 = d[pairsList[0][0]]
5183 d4 = d[pairsList[0][1]]
5725 d4 = d[pairsList[0][1]]
5184
5726
5185 alp2 = alpha_y[iy] #gamma 1
5727 alp2 = alpha_y[iy] #gamma 1
5186 alp4 = alpha_x[ix] #gamma 0
5728 alp4 = alpha_x[ix] #gamma 0
5187
5729
5188 alp3 = -alp2*d3/d2 - gammas[1]
5730 alp3 = -alp2*d3/d2 - gammas[1]
5189 alp5 = -alp4*d5/d4 - gammas[0]
5731 alp5 = -alp4*d5/d4 - gammas[0]
5190 # jph[pairy[1]] = alpha_y[iy]
5732 # jph[pairy[1]] = alpha_y[iy]
5191 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
5733 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
5192
5734
5193 # jph[pairx[1]] = alpha_x[ix]
5735 # jph[pairx[1]] = alpha_x[ix]
5194 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
5736 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
5195 jph[pairsList[0][1]] = alp4
5737 jph[pairsList[0][1]] = alp4
5196 jph[pairsList[0][0]] = alp5
5738 jph[pairsList[0][0]] = alp5
5197 jph[pairsList[1][0]] = alp3
5739 jph[pairsList[1][0]] = alp3
5198 jph[pairsList[1][1]] = alp2
5740 jph[pairsList[1][1]] = alp2
5199 jph_array[:,ix,iy] = jph
5741 jph_array[:,ix,iy] = jph
5200 # d = [2.0,2.5,2.5,2.0]
5742 # d = [2.0,2.5,2.5,2.0]
5201 #falta chequear si va a leer bien los meteoros
5743 #falta chequear si va a leer bien los meteoros
5202 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
5744 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
5203 error = meteorsArray1[:,-1]
5745 error = meteorsArray1[:,-1]
5204 ind1 = numpy.where(error==0)[0]
5746 ind1 = numpy.where(error==0)[0]
5205 penalty[ix,iy] = ind1.size
5747 penalty[ix,iy] = ind1.size
5206
5748
5207 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
5749 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
5208 phOffset = jph_array[:,i,j]
5750 phOffset = jph_array[:,i,j]
5209
5751
5210 center_xangle = phOffset[pairx[1]]
5752 center_xangle = phOffset[pairx[1]]
5211 center_yangle = phOffset[pairy[1]]
5753 center_yangle = phOffset[pairy[1]]
5212
5754
5213 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
5755 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
5214 phOffset = phOffset*180/numpy.pi
5756 phOffset = phOffset*180/numpy.pi
5215 return phOffset
5757 return phOffset
5216
5758
5217
5759
5218 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
5760 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
5219
5761
5220 dataOut.flagNoData = True
5762 dataOut.flagNoData = True
5221 self.__dataReady = False
5763 self.__dataReady = False
5222 dataOut.outputInterval = nHours*3600
5764 dataOut.outputInterval = nHours*3600
5223
5765
5224 if self.__isConfig == False:
5766 if self.__isConfig == False:
5225 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
5767 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
5226 #Get Initial LTC time
5768 #Get Initial LTC time
5227 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
5769 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
5228 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
5770 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
5229
5771
5230 self.__isConfig = True
5772 self.__isConfig = True
5231
5773
5232 if self.__buffer is None:
5774 if self.__buffer is None:
5233 self.__buffer = dataOut.data_param.copy()
5775 self.__buffer = dataOut.data_param.copy()
5234
5776
5235 else:
5777 else:
5236 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5778 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5237
5779
5238 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5780 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5239
5781
5240 if self.__dataReady:
5782 if self.__dataReady:
5241 dataOut.utctimeInit = self.__initime
5783 dataOut.utctimeInit = self.__initime
5242 self.__initime += dataOut.outputInterval #to erase time offset
5784 self.__initime += dataOut.outputInterval #to erase time offset
5243
5785
5244 freq = dataOut.frequency
5786 freq = dataOut.frequency
5245 c = dataOut.C #m/s
5787 c = dataOut.C #m/s
5246 lamb = c/freq
5788 lamb = c/freq
5247 k = 2*numpy.pi/lamb
5789 k = 2*numpy.pi/lamb
5248 azimuth = 0
5790 azimuth = 0
5249 h = (hmin, hmax)
5791 h = (hmin, hmax)
5250 # pairs = ((0,1),(2,3)) #Estrella
5792 # pairs = ((0,1),(2,3)) #Estrella
5251 # pairs = ((1,0),(2,3)) #T
5793 # pairs = ((1,0),(2,3)) #T
5252
5794
5253 if channelPositions is None:
5795 if channelPositions is None:
5254 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5796 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5255 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5797 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5256 meteorOps = SMOperations()
5798 meteorOps = SMOperations()
5257 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5799 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5258
5800
5259 #Checking correct order of pairs
5801 #Checking correct order of pairs
5260 pairs = []
5802 pairs = []
5261 if distances[1] > distances[0]:
5803 if distances[1] > distances[0]:
5262 pairs.append((1,0))
5804 pairs.append((1,0))
5263 else:
5805 else:
5264 pairs.append((0,1))
5806 pairs.append((0,1))
5265
5807
5266 if distances[3] > distances[2]:
5808 if distances[3] > distances[2]:
5267 pairs.append((3,2))
5809 pairs.append((3,2))
5268 else:
5810 else:
5269 pairs.append((2,3))
5811 pairs.append((2,3))
5270 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
5812 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
5271
5813
5272 meteorsArray = self.__buffer
5814 meteorsArray = self.__buffer
5273 error = meteorsArray[:,-1]
5815 error = meteorsArray[:,-1]
5274 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5816 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5275 ind1 = numpy.where(boolError)[0]
5817 ind1 = numpy.where(boolError)[0]
5276 meteorsArray = meteorsArray[ind1,:]
5818 meteorsArray = meteorsArray[ind1,:]
5277 meteorsArray[:,-1] = 0
5819 meteorsArray[:,-1] = 0
5278 phases = meteorsArray[:,8:12]
5820 phases = meteorsArray[:,8:12]
5279
5821
5280 #Calculate Gammas
5822 #Calculate Gammas
5281 gammas = self.__getGammas(pairs, distances, phases)
5823 gammas = self.__getGammas(pairs, distances, phases)
5282 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
5824 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
5283 #Calculate Phases
5825 #Calculate Phases
5284 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5826 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5285 phasesOff = phasesOff.reshape((1,phasesOff.size))
5827 phasesOff = phasesOff.reshape((1,phasesOff.size))
5286 dataOut.data_output = -phasesOff
5828 dataOut.data_output = -phasesOff
5287 dataOut.flagNoData = False
5829 dataOut.flagNoData = False
5288 self.__buffer = None
5830 self.__buffer = None
5289
5831
5290
5832
5291 return
5833 return
5292
5834
5293 class SMOperations():
5835 class SMOperations():
5294
5836
5295 def __init__(self):
5837 def __init__(self):
5296
5838
5297 return
5839 return
5298
5840
5299 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5841 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5300
5842
5301 arrayParameters = arrayParameters0.copy()
5843 arrayParameters = arrayParameters0.copy()
5302 hmin = h[0]
5844 hmin = h[0]
5303 hmax = h[1]
5845 hmax = h[1]
5304
5846
5305 #Calculate AOA (Error N 3, 4)
5847 #Calculate AOA (Error N 3, 4)
5306 #JONES ET AL. 1998
5848 #JONES ET AL. 1998
5307 AOAthresh = numpy.pi/8
5849 AOAthresh = numpy.pi/8
5308 error = arrayParameters[:,-1]
5850 error = arrayParameters[:,-1]
5309 phases = -arrayParameters[:,8:12] + jph
5851 phases = -arrayParameters[:,8:12] + jph
5310 # phases = numpy.unwrap(phases)
5852 # phases = numpy.unwrap(phases)
5311 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5853 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5312
5854
5313 #Calculate Heights (Error N 13 and 14)
5855 #Calculate Heights (Error N 13 and 14)
5314 error = arrayParameters[:,-1]
5856 error = arrayParameters[:,-1]
5315 Ranges = arrayParameters[:,1]
5857 Ranges = arrayParameters[:,1]
5316 zenith = arrayParameters[:,4]
5858 zenith = arrayParameters[:,4]
5317 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5859 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5318
5860
5319 #----------------------- Get Final data ------------------------------------
5861 #----------------------- Get Final data ------------------------------------
5320 # error = arrayParameters[:,-1]
5862 # error = arrayParameters[:,-1]
5321 # ind1 = numpy.where(error==0)[0]
5863 # ind1 = numpy.where(error==0)[0]
5322 # arrayParameters = arrayParameters[ind1,:]
5864 # arrayParameters = arrayParameters[ind1,:]
5323
5865
5324 return arrayParameters
5866 return arrayParameters
5325
5867
5326 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5868 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5327
5869
5328 arrayAOA = numpy.zeros((phases.shape[0],3))
5870 arrayAOA = numpy.zeros((phases.shape[0],3))
5329 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5871 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5330
5872
5331 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5873 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5332 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5874 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5333 arrayAOA[:,2] = cosDirError
5875 arrayAOA[:,2] = cosDirError
5334
5876
5335 azimuthAngle = arrayAOA[:,0]
5877 azimuthAngle = arrayAOA[:,0]
5336 zenithAngle = arrayAOA[:,1]
5878 zenithAngle = arrayAOA[:,1]
5337
5879
5338 #Setting Error
5880 #Setting Error
5339 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5881 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5340 error[indError] = 0
5882 error[indError] = 0
5341 #Number 3: AOA not fesible
5883 #Number 3: AOA not fesible
5342 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5884 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5343 error[indInvalid] = 3
5885 error[indInvalid] = 3
5344 #Number 4: Large difference in AOAs obtained from different antenna baselines
5886 #Number 4: Large difference in AOAs obtained from different antenna baselines
5345 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5887 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5346 error[indInvalid] = 4
5888 error[indInvalid] = 4
5347 return arrayAOA, error
5889 return arrayAOA, error
5348
5890
5349 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5891 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5350
5892
5351 #Initializing some variables
5893 #Initializing some variables
5352 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5894 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5353 ang_aux = ang_aux.reshape(1,ang_aux.size)
5895 ang_aux = ang_aux.reshape(1,ang_aux.size)
5354
5896
5355 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5897 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5356 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5898 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5357
5899
5358
5900
5359 for i in range(2):
5901 for i in range(2):
5360 ph0 = arrayPhase[:,pairsList[i][0]]
5902 ph0 = arrayPhase[:,pairsList[i][0]]
5361 ph1 = arrayPhase[:,pairsList[i][1]]
5903 ph1 = arrayPhase[:,pairsList[i][1]]
5362 d0 = distances[pairsList[i][0]]
5904 d0 = distances[pairsList[i][0]]
5363 d1 = distances[pairsList[i][1]]
5905 d1 = distances[pairsList[i][1]]
5364
5906
5365 ph0_aux = ph0 + ph1
5907 ph0_aux = ph0 + ph1
5366 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5908 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5367 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
5909 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
5368 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
5910 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
5369 #First Estimation
5911 #First Estimation
5370 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5912 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5371
5913
5372 #Most-Accurate Second Estimation
5914 #Most-Accurate Second Estimation
5373 phi1_aux = ph0 - ph1
5915 phi1_aux = ph0 - ph1
5374 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5916 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5375 #Direction Cosine 1
5917 #Direction Cosine 1
5376 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5918 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5377
5919
5378 #Searching the correct Direction Cosine
5920 #Searching the correct Direction Cosine
5379 cosdir0_aux = cosdir0[:,i]
5921 cosdir0_aux = cosdir0[:,i]
5380 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5922 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5381 #Minimum Distance
5923 #Minimum Distance
5382 cosDiff = (cosdir1 - cosdir0_aux)**2
5924 cosDiff = (cosdir1 - cosdir0_aux)**2
5383 indcos = cosDiff.argmin(axis = 1)
5925 indcos = cosDiff.argmin(axis = 1)
5384 #Saving Value obtained
5926 #Saving Value obtained
5385 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5927 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5386
5928
5387 return cosdir0, cosdir
5929 return cosdir0, cosdir
5388
5930
5389 def __calculateAOA(self, cosdir, azimuth):
5931 def __calculateAOA(self, cosdir, azimuth):
5390 cosdirX = cosdir[:,0]
5932 cosdirX = cosdir[:,0]
5391 cosdirY = cosdir[:,1]
5933 cosdirY = cosdir[:,1]
5392
5934
5393 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5935 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5394 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5936 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5395 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5937 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5396
5938
5397 return angles
5939 return angles
5398
5940
5399 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5941 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5400
5942
5401 Ramb = 375 #Ramb = c/(2*PRF)
5943 Ramb = 375 #Ramb = c/(2*PRF)
5402 Re = 6371 #Earth Radius
5944 Re = 6371 #Earth Radius
5403 heights = numpy.zeros(Ranges.shape)
5945 heights = numpy.zeros(Ranges.shape)
5404
5946
5405 R_aux = numpy.array([0,1,2])*Ramb
5947 R_aux = numpy.array([0,1,2])*Ramb
5406 R_aux = R_aux.reshape(1,R_aux.size)
5948 R_aux = R_aux.reshape(1,R_aux.size)
5407
5949
5408 Ranges = Ranges.reshape(Ranges.size,1)
5950 Ranges = Ranges.reshape(Ranges.size,1)
5409
5951
5410 Ri = Ranges + R_aux
5952 Ri = Ranges + R_aux
5411 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5953 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5412
5954
5413 #Check if there is a height between 70 and 110 km
5955 #Check if there is a height between 70 and 110 km
5414 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5956 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5415 ind_h = numpy.where(h_bool == 1)[0]
5957 ind_h = numpy.where(h_bool == 1)[0]
5416
5958
5417 hCorr = hi[ind_h, :]
5959 hCorr = hi[ind_h, :]
5418 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5960 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5419
5961
5420 hCorr = hi[ind_hCorr][:len(ind_h)]
5962 hCorr = hi[ind_hCorr][:len(ind_h)]
5421 heights[ind_h] = hCorr
5963 heights[ind_h] = hCorr
5422
5964
5423 #Setting Error
5965 #Setting Error
5424 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5966 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5425 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5967 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5426 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5968 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5427 error[indError] = 0
5969 error[indError] = 0
5428 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5970 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5429 error[indInvalid2] = 14
5971 error[indInvalid2] = 14
5430 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5972 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5431 error[indInvalid1] = 13
5973 error[indInvalid1] = 13
5432
5974
5433 return heights, error
5975 return heights, error
5434
5976
5435 def getPhasePairs(self, channelPositions):
5977 def getPhasePairs(self, channelPositions):
5436 chanPos = numpy.array(channelPositions)
5978 chanPos = numpy.array(channelPositions)
5437 listOper = list(itertools.combinations(list(range(5)),2))
5979 listOper = list(itertools.combinations(list(range(5)),2))
5438
5980
5439 distances = numpy.zeros(4)
5981 distances = numpy.zeros(4)
5440 axisX = []
5982 axisX = []
5441 axisY = []
5983 axisY = []
5442 distX = numpy.zeros(3)
5984 distX = numpy.zeros(3)
5443 distY = numpy.zeros(3)
5985 distY = numpy.zeros(3)
5444 ix = 0
5986 ix = 0
5445 iy = 0
5987 iy = 0
5446
5988
5447 pairX = numpy.zeros((2,2))
5989 pairX = numpy.zeros((2,2))
5448 pairY = numpy.zeros((2,2))
5990 pairY = numpy.zeros((2,2))
5449
5991
5450 for i in range(len(listOper)):
5992 for i in range(len(listOper)):
5451 pairi = listOper[i]
5993 pairi = listOper[i]
5452
5994
5453 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
5995 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
5454
5996
5455 if posDif[0] == 0:
5997 if posDif[0] == 0:
5456 axisY.append(pairi)
5998 axisY.append(pairi)
5457 distY[iy] = posDif[1]
5999 distY[iy] = posDif[1]
5458 iy += 1
6000 iy += 1
5459 elif posDif[1] == 0:
6001 elif posDif[1] == 0:
5460 axisX.append(pairi)
6002 axisX.append(pairi)
5461 distX[ix] = posDif[0]
6003 distX[ix] = posDif[0]
5462 ix += 1
6004 ix += 1
5463
6005
5464 for i in range(2):
6006 for i in range(2):
5465 if i==0:
6007 if i==0:
5466 dist0 = distX
6008 dist0 = distX
5467 axis0 = axisX
6009 axis0 = axisX
5468 else:
6010 else:
5469 dist0 = distY
6011 dist0 = distY
5470 axis0 = axisY
6012 axis0 = axisY
5471
6013
5472 side = numpy.argsort(dist0)[:-1]
6014 side = numpy.argsort(dist0)[:-1]
5473 axis0 = numpy.array(axis0)[side,:]
6015 axis0 = numpy.array(axis0)[side,:]
5474 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
6016 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
5475 axis1 = numpy.unique(numpy.reshape(axis0,4))
6017 axis1 = numpy.unique(numpy.reshape(axis0,4))
5476 side = axis1[axis1 != chanC]
6018 side = axis1[axis1 != chanC]
5477 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
6019 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
5478 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
6020 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
5479 if diff1<0:
6021 if diff1<0:
5480 chan2 = side[0]
6022 chan2 = side[0]
5481 d2 = numpy.abs(diff1)
6023 d2 = numpy.abs(diff1)
5482 chan1 = side[1]
6024 chan1 = side[1]
5483 d1 = numpy.abs(diff2)
6025 d1 = numpy.abs(diff2)
5484 else:
6026 else:
5485 chan2 = side[1]
6027 chan2 = side[1]
5486 d2 = numpy.abs(diff2)
6028 d2 = numpy.abs(diff2)
5487 chan1 = side[0]
6029 chan1 = side[0]
5488 d1 = numpy.abs(diff1)
6030 d1 = numpy.abs(diff1)
5489
6031
5490 if i==0:
6032 if i==0:
5491 chanCX = chanC
6033 chanCX = chanC
5492 chan1X = chan1
6034 chan1X = chan1
5493 chan2X = chan2
6035 chan2X = chan2
5494 distances[0:2] = numpy.array([d1,d2])
6036 distances[0:2] = numpy.array([d1,d2])
5495 else:
6037 else:
5496 chanCY = chanC
6038 chanCY = chanC
5497 chan1Y = chan1
6039 chan1Y = chan1
5498 chan2Y = chan2
6040 chan2Y = chan2
5499 distances[2:4] = numpy.array([d1,d2])
6041 distances[2:4] = numpy.array([d1,d2])
5500 # axisXsides = numpy.reshape(axisX[ix,:],4)
6042 # axisXsides = numpy.reshape(axisX[ix,:],4)
5501 #
6043 #
5502 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
6044 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
5503 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
6045 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
5504 #
6046 #
5505 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
6047 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
5506 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
6048 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
5507 # channel25X = int(pairX[0,ind25X])
6049 # channel25X = int(pairX[0,ind25X])
5508 # channel20X = int(pairX[1,ind20X])
6050 # channel20X = int(pairX[1,ind20X])
5509 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
6051 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
5510 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
6052 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
5511 # channel25Y = int(pairY[0,ind25Y])
6053 # channel25Y = int(pairY[0,ind25Y])
5512 # channel20Y = int(pairY[1,ind20Y])
6054 # channel20Y = int(pairY[1,ind20Y])
5513
6055
5514 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
6056 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
5515 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
6057 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
5516
6058
5517 return pairslist, distances
6059 return pairslist, distances
5518 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
6060 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
5519 #
6061 #
5520 # arrayAOA = numpy.zeros((phases.shape[0],3))
6062 # arrayAOA = numpy.zeros((phases.shape[0],3))
5521 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
6063 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
5522 #
6064 #
5523 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
6065 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5524 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
6066 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5525 # arrayAOA[:,2] = cosDirError
6067 # arrayAOA[:,2] = cosDirError
5526 #
6068 #
5527 # azimuthAngle = arrayAOA[:,0]
6069 # azimuthAngle = arrayAOA[:,0]
5528 # zenithAngle = arrayAOA[:,1]
6070 # zenithAngle = arrayAOA[:,1]
5529 #
6071 #
5530 # #Setting Error
6072 # #Setting Error
5531 # #Number 3: AOA not fesible
6073 # #Number 3: AOA not fesible
5532 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
6074 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5533 # error[indInvalid] = 3
6075 # error[indInvalid] = 3
5534 # #Number 4: Large difference in AOAs obtained from different antenna baselines
6076 # #Number 4: Large difference in AOAs obtained from different antenna baselines
5535 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
6077 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5536 # error[indInvalid] = 4
6078 # error[indInvalid] = 4
5537 # return arrayAOA, error
6079 # return arrayAOA, error
5538 #
6080 #
5539 # def __getDirectionCosines(self, arrayPhase, pairsList):
6081 # def __getDirectionCosines(self, arrayPhase, pairsList):
5540 #
6082 #
5541 # #Initializing some variables
6083 # #Initializing some variables
5542 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
6084 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5543 # ang_aux = ang_aux.reshape(1,ang_aux.size)
6085 # ang_aux = ang_aux.reshape(1,ang_aux.size)
5544 #
6086 #
5545 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
6087 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
5546 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
6088 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5547 #
6089 #
5548 #
6090 #
5549 # for i in range(2):
6091 # for i in range(2):
5550 # #First Estimation
6092 # #First Estimation
5551 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
6093 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
5552 # #Dealias
6094 # #Dealias
5553 # indcsi = numpy.where(phi0_aux > numpy.pi)
6095 # indcsi = numpy.where(phi0_aux > numpy.pi)
5554 # phi0_aux[indcsi] -= 2*numpy.pi
6096 # phi0_aux[indcsi] -= 2*numpy.pi
5555 # indcsi = numpy.where(phi0_aux < -numpy.pi)
6097 # indcsi = numpy.where(phi0_aux < -numpy.pi)
5556 # phi0_aux[indcsi] += 2*numpy.pi
6098 # phi0_aux[indcsi] += 2*numpy.pi
5557 # #Direction Cosine 0
6099 # #Direction Cosine 0
5558 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
6100 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
5559 #
6101 #
5560 # #Most-Accurate Second Estimation
6102 # #Most-Accurate Second Estimation
5561 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
6103 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
5562 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
6104 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5563 # #Direction Cosine 1
6105 # #Direction Cosine 1
5564 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
6106 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
5565 #
6107 #
5566 # #Searching the correct Direction Cosine
6108 # #Searching the correct Direction Cosine
5567 # cosdir0_aux = cosdir0[:,i]
6109 # cosdir0_aux = cosdir0[:,i]
5568 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
6110 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5569 # #Minimum Distance
6111 # #Minimum Distance
5570 # cosDiff = (cosdir1 - cosdir0_aux)**2
6112 # cosDiff = (cosdir1 - cosdir0_aux)**2
5571 # indcos = cosDiff.argmin(axis = 1)
6113 # indcos = cosDiff.argmin(axis = 1)
5572 # #Saving Value obtained
6114 # #Saving Value obtained
5573 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
6115 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5574 #
6116 #
5575 # return cosdir0, cosdir
6117 # return cosdir0, cosdir
5576 #
6118 #
5577 # def __calculateAOA(self, cosdir, azimuth):
6119 # def __calculateAOA(self, cosdir, azimuth):
5578 # cosdirX = cosdir[:,0]
6120 # cosdirX = cosdir[:,0]
5579 # cosdirY = cosdir[:,1]
6121 # cosdirY = cosdir[:,1]
5580 #
6122 #
5581 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
6123 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5582 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
6124 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
5583 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
6125 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5584 #
6126 #
5585 # return angles
6127 # return angles
5586 #
6128 #
5587 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
6129 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5588 #
6130 #
5589 # Ramb = 375 #Ramb = c/(2*PRF)
6131 # Ramb = 375 #Ramb = c/(2*PRF)
5590 # Re = 6371 #Earth Radius
6132 # Re = 6371 #Earth Radius
5591 # heights = numpy.zeros(Ranges.shape)
6133 # heights = numpy.zeros(Ranges.shape)
5592 #
6134 #
5593 # R_aux = numpy.array([0,1,2])*Ramb
6135 # R_aux = numpy.array([0,1,2])*Ramb
5594 # R_aux = R_aux.reshape(1,R_aux.size)
6136 # R_aux = R_aux.reshape(1,R_aux.size)
5595 #
6137 #
5596 # Ranges = Ranges.reshape(Ranges.size,1)
6138 # Ranges = Ranges.reshape(Ranges.size,1)
5597 #
6139 #
5598 # Ri = Ranges + R_aux
6140 # Ri = Ranges + R_aux
5599 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
6141 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5600 #
6142 #
5601 # #Check if there is a height between 70 and 110 km
6143 # #Check if there is a height between 70 and 110 km
5602 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
6144 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5603 # ind_h = numpy.where(h_bool == 1)[0]
6145 # ind_h = numpy.where(h_bool == 1)[0]
5604 #
6146 #
5605 # hCorr = hi[ind_h, :]
6147 # hCorr = hi[ind_h, :]
5606 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
6148 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5607 #
6149 #
5608 # hCorr = hi[ind_hCorr]
6150 # hCorr = hi[ind_hCorr]
5609 # heights[ind_h] = hCorr
6151 # heights[ind_h] = hCorr
5610 #
6152 #
5611 # #Setting Error
6153 # #Setting Error
5612 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
6154 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5613 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
6155 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5614 #
6156 #
5615 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
6157 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5616 # error[indInvalid2] = 14
6158 # error[indInvalid2] = 14
5617 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
6159 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5618 # error[indInvalid1] = 13
6160 # error[indInvalid1] = 13
5619 #
6161 #
5620 # return heights, error
6162 # return heights, error
5621
6163
5622
6164
5623
6165
5624 class IGRFModel(Operation):
6166 class IGRFModel(Operation):
5625 """Operation to calculate Geomagnetic parameters.
6167 """Operation to calculate Geomagnetic parameters.
5626
6168
5627 Parameters:
6169 Parameters:
5628 -----------
6170 -----------
5629 None
6171 None
5630
6172
5631 Example
6173 Example
5632 --------
6174 --------
5633
6175
5634 op = proc_unit.addOperation(name='IGRFModel', optype='other')
6176 op = proc_unit.addOperation(name='IGRFModel', optype='other')
5635
6177
5636 """
6178 """
5637
6179
5638 def __init__(self, **kwargs):
6180 def __init__(self, **kwargs):
5639
6181
5640 Operation.__init__(self, **kwargs)
6182 Operation.__init__(self, **kwargs)
5641
6183
5642 self.aux=1
6184 self.aux=1
5643
6185
5644 def run(self,dataOut):
6186 def run(self,dataOut):
5645
6187
5646 try:
6188 try:
5647 from schainpy.model.proc import mkfact_short_2020
6189 from schainpy.model.proc import mkfact_short_2020
5648 except:
6190 except:
5649 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
6191 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
5650
6192
5651 if self.aux==1:
6193 if self.aux==1:
5652
6194
5653 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
6195 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
5654 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
6196 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
5655 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
6197 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
5656 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
6198 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
5657 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
6199 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
5658 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
6200 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
5659
6201
5660 self.aux=0
6202 self.aux=0
5661
6203
5662 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
6204 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
5663 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6205 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5664 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
6206 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
5665 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6207 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5666 dataOut.thb=numpy.array(dataOut.thb,order='F')
6208 dataOut.thb=numpy.array(dataOut.thb,order='F')
5667 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6209 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5668 dataOut.bki=numpy.array(dataOut.bki,order='F')
6210 dataOut.bki=numpy.array(dataOut.bki,order='F')
5669
6211
5670 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
6212 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
5671
6213
5672 return dataOut
6214 return dataOut
General Comments 0
You need to be logged in to leave comments. Login now