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