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