##// END OF EJS Templates
Remove numpy.complex
Juan C. Espinoza -
r1595:fed0fad1169f
parent child
Show More
@@ -1,5437 +1,5437
1 1 import numpy
2 2 import math
3 3 from scipy import optimize, interpolate, signal, stats, ndimage
4 4 from scipy.fftpack import fft
5 5 import scipy
6 6 import re
7 7 import datetime
8 8 import copy
9 9 import sys
10 10 import importlib
11 11 import itertools
12 12 from multiprocessing import Pool, TimeoutError
13 13 from multiprocessing.pool import ThreadPool
14 14 import time
15 15
16 16 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
17 17 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
18 18 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
19 19 from scipy import asarray as ar,exp
20 20 from scipy.optimize import fmin, curve_fit
21 21 from schainpy.utils import log
22 22 import warnings
23 23 from numpy import NaN
24 24 from scipy.optimize.optimize import OptimizeWarning
25 25 warnings.filterwarnings('ignore')
26 26
27 27
28 28 SPEED_OF_LIGHT = 299792458
29 29
30 30 '''solving pickling issue'''
31 31
32 32 def _pickle_method(method):
33 33 func_name = method.__func__.__name__
34 34 obj = method.__self__
35 35 cls = method.__self__.__class__
36 36 return _unpickle_method, (func_name, obj, cls)
37 37
38 38 def _unpickle_method(func_name, obj, cls):
39 39 for cls in cls.mro():
40 40 try:
41 41 func = cls.__dict__[func_name]
42 42 except KeyError:
43 43 pass
44 44 else:
45 45 break
46 46 return func.__get__(obj, cls)
47 47
48 48 # @MPDecorator
49 49 class ParametersProc(ProcessingUnit):
50 50
51 51 METHODS = {}
52 52 nSeconds = None
53 53
54 54 def __init__(self):
55 55 ProcessingUnit.__init__(self)
56 56
57 57 self.buffer = None
58 58 self.firstdatatime = None
59 59 self.profIndex = 0
60 60 self.dataOut = Parameters()
61 61 self.setupReq = False #Agregar a todas las unidades de proc
62 62
63 63 def __updateObjFromInput(self):
64 64
65 65 self.dataOut.inputUnit = self.dataIn.type
66 66
67 67 self.dataOut.timeZone = self.dataIn.timeZone
68 68 self.dataOut.dstFlag = self.dataIn.dstFlag
69 69 self.dataOut.errorCount = self.dataIn.errorCount
70 70 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71 71
72 72 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 73 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 74 self.dataOut.channelList = self.dataIn.channelList
75 75 self.dataOut.heightList = self.dataIn.heightList
76 76 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 77 # self.dataOut.nHeights = self.dataIn.nHeights
78 78 # self.dataOut.nChannels = self.dataIn.nChannels
79 79 # self.dataOut.nBaud = self.dataIn.nBaud
80 80 # self.dataOut.nCode = self.dataIn.nCode
81 81 # self.dataOut.code = self.dataIn.code
82 82 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
83 83 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
84 84 # self.dataOut.utctime = self.firstdatatime
85 85 self.dataOut.utctime = self.dataIn.utctime
86 86 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
87 87 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
88 88 self.dataOut.nCohInt = self.dataIn.nCohInt
89 89 # self.dataOut.nIncohInt = 1
90 90 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
91 91 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
92 92 self.dataOut.timeInterval1 = self.dataIn.timeInterval
93 93 self.dataOut.heightList = self.dataIn.heightList
94 94 self.dataOut.frequency = self.dataIn.frequency
95 95 #self.dataOut.noise = self.dataIn.noise
96 96
97 97 def run(self):
98 98
99 99 #---------------------- Voltage Data ---------------------------
100 100
101 101 if self.dataIn.type == "Voltage":
102 102
103 103 self.__updateObjFromInput()
104 104 self.dataOut.data_pre = self.dataIn.data.copy()
105 105 self.dataOut.flagNoData = False
106 106 self.dataOut.utctimeInit = self.dataIn.utctime
107 107 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
108 108 if hasattr(self.dataIn, 'dataPP_POW'):
109 109 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
110 110
111 111 if hasattr(self.dataIn, 'dataPP_POWER'):
112 112 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
113 113
114 114 if hasattr(self.dataIn, 'dataPP_DOP'):
115 115 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
116 116
117 117 if hasattr(self.dataIn, 'dataPP_SNR'):
118 118 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
119 119
120 120 if hasattr(self.dataIn, 'dataPP_WIDTH'):
121 121 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
122 122 return
123 123
124 124 #---------------------- Spectra Data ---------------------------
125 125
126 126 if self.dataIn.type == "Spectra":
127 127
128 128 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
129 129 self.dataOut.data_spc = self.dataIn.data_spc
130 130 self.dataOut.data_cspc = self.dataIn.data_cspc
131 131 self.dataOut.nProfiles = self.dataIn.nProfiles
132 132 self.dataOut.nIncohInt = self.dataIn.nIncohInt
133 133 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
134 134 self.dataOut.ippFactor = self.dataIn.ippFactor
135 135 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
136 136 self.dataOut.spc_noise = self.dataIn.getNoise()
137 137 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
138 138 # self.dataOut.normFactor = self.dataIn.normFactor
139 139 self.dataOut.pairsList = self.dataIn.pairsList
140 140 self.dataOut.groupList = self.dataIn.pairsList
141 141 self.dataOut.flagNoData = False
142 142
143 143 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
144 144 self.dataOut.ChanDist = self.dataIn.ChanDist
145 145 else: self.dataOut.ChanDist = None
146 146
147 147 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
148 148 # self.dataOut.VelRange = self.dataIn.VelRange
149 149 #else: self.dataOut.VelRange = None
150 150
151 151 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
152 152 self.dataOut.RadarConst = self.dataIn.RadarConst
153 153
154 154 if hasattr(self.dataIn, 'NPW'): #NPW
155 155 self.dataOut.NPW = self.dataIn.NPW
156 156
157 157 if hasattr(self.dataIn, 'COFA'): #COFA
158 158 self.dataOut.COFA = self.dataIn.COFA
159 159
160 160
161 161
162 162 #---------------------- Correlation Data ---------------------------
163 163
164 164 if self.dataIn.type == "Correlation":
165 165 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
166 166
167 167 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
168 168 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
169 169 self.dataOut.groupList = (acf_pairs, ccf_pairs)
170 170
171 171 self.dataOut.abscissaList = self.dataIn.lagRange
172 172 self.dataOut.noise = self.dataIn.noise
173 173 self.dataOut.data_snr = self.dataIn.SNR
174 174 self.dataOut.flagNoData = False
175 175 self.dataOut.nAvg = self.dataIn.nAvg
176 176
177 177 #---------------------- Parameters Data ---------------------------
178 178
179 179 if self.dataIn.type == "Parameters":
180 180 self.dataOut.copy(self.dataIn)
181 181 self.dataOut.flagNoData = False
182 182
183 183 return True
184 184
185 185 self.__updateObjFromInput()
186 186 self.dataOut.utctimeInit = self.dataIn.utctime
187 187 self.dataOut.paramInterval = self.dataIn.timeInterval
188 188
189 189 return
190 190
191 191
192 192 def target(tups):
193 193
194 194 obj, args = tups
195 195
196 196 return obj.FitGau(args)
197 197
198 198 class RemoveWideGC(Operation):
199 199 ''' This class remove the wide clutter and replace it with a simple interpolation points
200 200 This mainly applies to CLAIRE radar
201 201
202 202 ClutterWidth : Width to look for the clutter peak
203 203
204 204 Input:
205 205
206 206 self.dataOut.data_pre : SPC and CSPC
207 207 self.dataOut.spc_range : To select wind and rainfall velocities
208 208
209 209 Affected:
210 210
211 211 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
212 212
213 213 Written by D. ScipiΓ³n 25.02.2021
214 214 '''
215 215 def __init__(self):
216 216 Operation.__init__(self)
217 217 self.i = 0
218 218 self.ich = 0
219 219 self.ir = 0
220 220
221 221 def run(self, dataOut, ClutterWidth=2.5):
222 222
223 223 self.spc = dataOut.data_pre[0].copy()
224 224 self.spc_out = dataOut.data_pre[0].copy()
225 225 self.Num_Chn = self.spc.shape[0]
226 226 self.Num_Hei = self.spc.shape[2]
227 227 VelRange = dataOut.spc_range[2][:-1]
228 228 dv = VelRange[1]-VelRange[0]
229 229
230 230 # Find the velocities that corresponds to zero
231 231 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
232 232
233 233 # Removing novalid data from the spectra
234 234 for ich in range(self.Num_Chn) :
235 235 for ir in range(self.Num_Hei) :
236 236 # Estimate the noise at each range
237 237 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
238 238
239 239 # Removing the noise floor at each range
240 240 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
241 241 self.spc[ich,novalid,ir] = HSn
242 242
243 243 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
244 244 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
245 245 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
246 246 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
247 247 continue
248 248 junk3 = numpy.squeeze(numpy.diff(j1index))
249 249 junk4 = numpy.squeeze(numpy.diff(j2index))
250 250
251 251 valleyindex = j2index[numpy.where(junk4>1)]
252 252 peakindex = j1index[numpy.where(junk3>1)]
253 253
254 254 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
255 255 if numpy.size(isvalid) == 0 :
256 256 continue
257 257 if numpy.size(isvalid) >1 :
258 258 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
259 259 isvalid = isvalid[vindex]
260 260
261 261 # clutter peak
262 262 gcpeak = peakindex[isvalid]
263 263 vl = numpy.where(valleyindex < gcpeak)
264 264 if numpy.size(vl) == 0:
265 265 continue
266 266 gcvl = valleyindex[vl[0][-1]]
267 267 vr = numpy.where(valleyindex > gcpeak)
268 268 if numpy.size(vr) == 0:
269 269 continue
270 270 gcvr = valleyindex[vr[0][0]]
271 271
272 272 # Removing the clutter
273 273 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
274 274 gcindex = gc_values[gcvl+1:gcvr-1]
275 275 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
276 276
277 277 dataOut.data_pre[0] = self.spc_out
278 278
279 279 return dataOut
280 280
281 281 class SpectralFilters(Operation):
282 282 ''' This class allows to replace the novalid values with noise for each channel
283 283 This applies to CLAIRE RADAR
284 284
285 285 PositiveLimit : RightLimit of novalid data
286 286 NegativeLimit : LeftLimit of novalid data
287 287
288 288 Input:
289 289
290 290 self.dataOut.data_pre : SPC and CSPC
291 291 self.dataOut.spc_range : To select wind and rainfall velocities
292 292
293 293 Affected:
294 294
295 295 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
296 296
297 297 Written by D. ScipiΓ³n 29.01.2021
298 298 '''
299 299 def __init__(self):
300 300 Operation.__init__(self)
301 301 self.i = 0
302 302
303 303 def run(self, dataOut, ):
304 304
305 305 self.spc = dataOut.data_pre[0].copy()
306 306 self.Num_Chn = self.spc.shape[0]
307 307 VelRange = dataOut.spc_range[2]
308 308
309 309 # novalid corresponds to data within the Negative and PositiveLimit
310 310
311 311
312 312 # Removing novalid data from the spectra
313 313 for i in range(self.Num_Chn):
314 314 self.spc[i,novalid,:] = dataOut.noise[i]
315 315 dataOut.data_pre[0] = self.spc
316 316 return dataOut
317 317
318 318
319 319
320 320 class GaussianFit(Operation):
321 321
322 322 '''
323 323 Function that fit of one and two generalized gaussians (gg) based
324 324 on the PSD shape across an "power band" identified from a cumsum of
325 325 the measured spectrum - noise.
326 326
327 327 Input:
328 328 self.dataOut.data_pre : SelfSpectra
329 329
330 330 Output:
331 331 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
332 332
333 333 '''
334 334 def __init__(self):
335 335 Operation.__init__(self)
336 336 self.i=0
337 337
338 338
339 339 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
340 340 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
341 341 """This routine will find a couple of generalized Gaussians to a power spectrum
342 342 methods: generalized, squared
343 343 input: spc
344 344 output:
345 345 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
346 346 """
347 347 print ('Entering ',method,' double Gaussian fit')
348 348 self.spc = dataOut.data_pre[0].copy()
349 349 self.Num_Hei = self.spc.shape[2]
350 350 self.Num_Bin = self.spc.shape[1]
351 351 self.Num_Chn = self.spc.shape[0]
352 352
353 353 start_time = time.time()
354 354
355 355 pool = Pool(processes=self.Num_Chn)
356 356 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
357 357 objs = [self for __ in range(self.Num_Chn)]
358 358 attrs = list(zip(objs, args))
359 359 DGauFitParam = pool.map(target, attrs)
360 360 # Parameters:
361 361 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
362 362 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
363 363
364 364 # Double Gaussian Curves
365 365 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
366 366 gau0[:] = numpy.NaN
367 367 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
368 368 gau1[:] = numpy.NaN
369 369 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
370 370 for iCh in range(self.Num_Chn):
371 371 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
372 372 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
373 373 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
374 374 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
375 375 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
376 376 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
377 377 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
378 378 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
379 379 if method == 'generalized':
380 380 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
381 381 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
382 382 elif method == 'squared':
383 383 p0 = 2.
384 384 p1 = 2.
385 385 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
386 386 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
387 387 dataOut.GaussFit0 = gau0
388 388 dataOut.GaussFit1 = gau1
389 389
390 390 print('Leaving ',method ,' double Gaussian fit')
391 391 return dataOut
392 392
393 393 def FitGau(self, X):
394 394 # print('Entering FitGau')
395 395 # Assigning the variables
396 396 Vrange, ch, wnoise, num_intg, SNRlimit = X
397 397 # Noise Limits
398 398 noisebl = wnoise * 0.9
399 399 noisebh = wnoise * 1.1
400 400 # Radar Velocity
401 401 Va = max(Vrange)
402 402 deltav = Vrange[1] - Vrange[0]
403 403 x = numpy.arange(self.Num_Bin)
404 404
405 405 # print ('stop 0')
406 406
407 407 # 5 parameters, 2 Gaussians
408 408 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
409 409 DGauFitParam[:] = numpy.NaN
410 410
411 411 # SPCparam = []
412 412 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
413 413 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
414 414 # SPC_ch1[:] = 0 #numpy.NaN
415 415 # SPC_ch2[:] = 0 #numpy.NaN
416 416 # print ('stop 1')
417 417 for ht in range(self.Num_Hei):
418 418 # print (ht)
419 419 # print ('stop 2')
420 420 # Spectra at each range
421 421 spc = numpy.asarray(self.spc)[ch,:,ht]
422 422 snr = ( spc.mean() - wnoise ) / wnoise
423 423 snrdB = 10.*numpy.log10(snr)
424 424
425 425 #print ('stop 3')
426 426 if snrdB < SNRlimit :
427 427 # snr = numpy.NaN
428 428 # SPC_ch1[:,ht] = 0#numpy.NaN
429 429 # SPC_ch1[:,ht] = 0#numpy.NaN
430 430 # SPCparam = (SPC_ch1,SPC_ch2)
431 431 # print ('SNR less than SNRth')
432 432 continue
433 433 # wnoise = hildebrand_sekhon(spc,num_intg)
434 434 # print ('stop 2.01')
435 435 #############################################
436 436 # normalizing spc and noise
437 437 # This part differs from gg1
438 438 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
439 439 #spc = spc / spc_norm_max
440 440 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
441 441 #############################################
442 442
443 443 # print ('stop 2.1')
444 444 fatspectra=1.0
445 445 # noise per channel.... we might want to use the noise at each range
446 446
447 447 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
448 448 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
449 449 #if wnoise>1.1*pnoise: # to be tested later
450 450 # wnoise=pnoise
451 451 # noisebl = wnoise*0.9
452 452 # noisebh = wnoise*1.1
453 453 spc = spc - wnoise # signal
454 454
455 455 # print ('stop 2.2')
456 456 minx = numpy.argmin(spc)
457 457 #spcs=spc.copy()
458 458 spcs = numpy.roll(spc,-minx)
459 459 cum = numpy.cumsum(spcs)
460 460 # tot_noise = wnoise * self.Num_Bin #64;
461 461
462 462 # print ('stop 2.3')
463 463 # snr = sum(spcs) / tot_noise
464 464 # snrdB = 10.*numpy.log10(snr)
465 465 #print ('stop 3')
466 466 # if snrdB < SNRlimit :
467 467 # snr = numpy.NaN
468 468 # SPC_ch1[:,ht] = 0#numpy.NaN
469 469 # SPC_ch1[:,ht] = 0#numpy.NaN
470 470 # SPCparam = (SPC_ch1,SPC_ch2)
471 471 # print ('SNR less than SNRth')
472 472 # continue
473 473
474 474
475 475 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
476 476 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
477 477 # print ('stop 4')
478 478 cummax = max(cum)
479 479 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
480 480 cumlo = cummax * epsi
481 481 cumhi = cummax * (1-epsi)
482 482 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
483 483
484 484 # print ('stop 5')
485 485 if len(powerindex) < 1:# case for powerindex 0
486 486 # print ('powerindex < 1')
487 487 continue
488 488 powerlo = powerindex[0]
489 489 powerhi = powerindex[-1]
490 490 powerwidth = powerhi-powerlo
491 491 if powerwidth <= 1:
492 492 # print('powerwidth <= 1')
493 493 continue
494 494
495 495 # print ('stop 6')
496 496 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
497 497 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
498 498 midpeak = (firstpeak + secondpeak)/2.
499 499 firstamp = spcs[int(firstpeak)]
500 500 secondamp = spcs[int(secondpeak)]
501 501 midamp = spcs[int(midpeak)]
502 502
503 503 y_data = spc + wnoise
504 504
505 505 ''' single Gaussian '''
506 506 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
507 507 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
508 508 power0 = 2.
509 509 amplitude0 = midamp
510 510 state0 = [shift0,width0,amplitude0,power0,wnoise]
511 511 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
512 512 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
513 513 # print ('stop 7.1')
514 514 # print (bnds)
515 515
516 516 chiSq1=lsq1[1]
517 517
518 518 # print ('stop 8')
519 519 if fatspectra<1.0 and powerwidth<4:
520 520 choice=0
521 521 Amplitude0=lsq1[0][2]
522 522 shift0=lsq1[0][0]
523 523 width0=lsq1[0][1]
524 524 p0=lsq1[0][3]
525 525 Amplitude1=0.
526 526 shift1=0.
527 527 width1=0.
528 528 p1=0.
529 529 noise=lsq1[0][4]
530 530 #return (numpy.array([shift0,width0,Amplitude0,p0]),
531 531 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
532 532 # print ('stop 9')
533 533 ''' two Gaussians '''
534 534 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
535 535 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
536 536 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
537 537 width0 = powerwidth/6.
538 538 width1 = width0
539 539 power0 = 2.
540 540 power1 = power0
541 541 amplitude0 = firstamp
542 542 amplitude1 = secondamp
543 543 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
544 544 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
545 545 bnds=((0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
546 546 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
547 547
548 548 # print ('stop 10')
549 549 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
550 550
551 551 # print ('stop 11')
552 552 chiSq2 = lsq2[1]
553 553
554 554 # print ('stop 12')
555 555
556 556 oneG = (chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
557 557
558 558 # print ('stop 13')
559 559 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
560 560 if oneG:
561 561 choice = 0
562 562 else:
563 563 w1 = lsq2[0][1]; w2 = lsq2[0][5]
564 564 a1 = lsq2[0][2]; a2 = lsq2[0][6]
565 565 p1 = lsq2[0][3]; p2 = lsq2[0][7]
566 566 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
567 567 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
568 568 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
569 569
570 570 if gp1>gp2:
571 571 if a1>0.7*a2:
572 572 choice = 1
573 573 else:
574 574 choice = 2
575 575 elif gp2>gp1:
576 576 if a2>0.7*a1:
577 577 choice = 2
578 578 else:
579 579 choice = 1
580 580 else:
581 581 choice = numpy.argmax([a1,a2])+1
582 582 #else:
583 583 #choice=argmin([std2a,std2b])+1
584 584
585 585 else: # with low SNR go to the most energetic peak
586 586 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
587 587
588 588 # print ('stop 14')
589 589 shift0 = lsq2[0][0]
590 590 vel0 = Vrange[0] + shift0 * deltav
591 591 shift1 = lsq2[0][4]
592 592 # vel1=Vrange[0] + shift1 * deltav
593 593
594 594 # max_vel = 1.0
595 595 # Va = max(Vrange)
596 596 # deltav = Vrange[1]-Vrange[0]
597 597 # print ('stop 15')
598 598 #first peak will be 0, second peak will be 1
599 599 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
600 600 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
601 601 shift0 = lsq2[0][0]
602 602 width0 = lsq2[0][1]
603 603 Amplitude0 = lsq2[0][2]
604 604 p0 = lsq2[0][3]
605 605
606 606 shift1 = lsq2[0][4]
607 607 width1 = lsq2[0][5]
608 608 Amplitude1 = lsq2[0][6]
609 609 p1 = lsq2[0][7]
610 610 noise = lsq2[0][8]
611 611 else:
612 612 shift1 = lsq2[0][0]
613 613 width1 = lsq2[0][1]
614 614 Amplitude1 = lsq2[0][2]
615 615 p1 = lsq2[0][3]
616 616
617 617 shift0 = lsq2[0][4]
618 618 width0 = lsq2[0][5]
619 619 Amplitude0 = lsq2[0][6]
620 620 p0 = lsq2[0][7]
621 621 noise = lsq2[0][8]
622 622
623 623 if Amplitude0<0.05: # in case the peak is noise
624 624 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
625 625 if Amplitude1<0.05:
626 626 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
627 627
628 628 # print ('stop 16 ')
629 629 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
630 630 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
631 631 # SPCparam = (SPC_ch1,SPC_ch2)
632 632
633 633 DGauFitParam[0,ht,0] = noise
634 634 DGauFitParam[0,ht,1] = noise
635 635 DGauFitParam[1,ht,0] = Amplitude0
636 636 DGauFitParam[1,ht,1] = Amplitude1
637 637 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
638 638 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
639 639 DGauFitParam[3,ht,0] = width0 * deltav
640 640 DGauFitParam[3,ht,1] = width1 * deltav
641 641 DGauFitParam[4,ht,0] = p0
642 642 DGauFitParam[4,ht,1] = p1
643 643
644 644 return DGauFitParam
645 645
646 646 def y_model1(self,x,state):
647 647 shift0, width0, amplitude0, power0, noise = state
648 648 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
649 649 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
650 650 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
651 651 return model0 + model0u + model0d + noise
652 652
653 653 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
654 654 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
655 655 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
656 656 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
657 657 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
658 658
659 659 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
660 660 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
661 661 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
662 662 return model0 + model0u + model0d + model1 + model1u + model1d + noise
663 663
664 664 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
665 665
666 666 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
667 667
668 668 def misfit2(self,state,y_data,x,num_intg):
669 669 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
670 670
671 671 class Oblique_Gauss_Fit(Operation):
672 672
673 673 def __init__(self):
674 674 Operation.__init__(self)
675 675
676 676 def Gauss_fit(self,spc,x,nGauss):
677 677
678 678
679 679 def gaussian(x, a, b, c, d):
680 680 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
681 681 return val
682 682
683 683 if nGauss == 'first':
684 684 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
685 685 spc_2_aux = numpy.flip(spc_1_aux)
686 686 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
687 687
688 688 len_dif = len(x)-len(spc_3_aux)
689 689
690 690 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
691 691
692 692 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
693 693
694 694 y = spc_new
695 695
696 696 elif nGauss == 'second':
697 697 y = spc
698 698
699 699
700 700 # estimate starting values from the data
701 701 a = y.max()
702 702 b = x[numpy.argmax(y)]
703 703 if nGauss == 'first':
704 704 c = 1.#b#b#numpy.std(spc)
705 705 elif nGauss == 'second':
706 706 c = b
707 707 else:
708 708 print("ERROR")
709 709
710 710 d = numpy.mean(y[-100:])
711 711
712 712 # define a least squares function to optimize
713 713 def minfunc(params):
714 714 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
715 715
716 716 # fit
717 717 popt = fmin(minfunc,[a,b,c,d],disp=False)
718 718 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
719 719
720 720
721 721 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
722 722
723 723
724 724 def Gauss_fit_2(self,spc,x,nGauss):
725 725
726 726
727 727 def gaussian(x, a, b, c, d):
728 728 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
729 729 return val
730 730
731 731 if nGauss == 'first':
732 732 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
733 733 spc_2_aux = numpy.flip(spc_1_aux)
734 734 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
735 735
736 736 len_dif = len(x)-len(spc_3_aux)
737 737
738 738 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
739 739
740 740 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
741 741
742 742 y = spc_new
743 743
744 744 elif nGauss == 'second':
745 745 y = spc
746 746
747 747
748 748 # estimate starting values from the data
749 749 a = y.max()
750 750 b = x[numpy.argmax(y)]
751 751 if nGauss == 'first':
752 752 c = 1.#b#b#numpy.std(spc)
753 753 elif nGauss == 'second':
754 754 c = b
755 755 else:
756 756 print("ERROR")
757 757
758 758 d = numpy.mean(y[-100:])
759 759
760 760 # define a least squares function to optimize
761 761 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
762 762 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
763 763
764 764
765 765 #return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
766 766 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
767 767
768 768 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
769 769
770 770 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
771 771 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
772 772 return val
773 773
774 774
775 775 y = spc
776 776
777 777 # estimate starting values from the data
778 778 a1 = A1
779 779 b1 = B1
780 780 c1 = C1#numpy.std(spc)
781 781
782 782 a2 = A2#y.max()
783 783 b2 = B2#x[numpy.argmax(y)]
784 784 c2 = C2#numpy.std(spc)
785 785 d = D
786 786
787 787 # define a least squares function to optimize
788 788 def minfunc(params):
789 789 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
790 790
791 791 # fit
792 792 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
793 793
794 794 return double_gaussian(x, popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
795 795
796 796 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
797 797
798 798 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
799 799 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
800 800 return val
801 801
802 802
803 803 y = spc
804 804
805 805 # estimate starting values from the data
806 806 a1 = A1
807 807 b1 = B1
808 808 c1 = C1#numpy.std(spc)
809 809
810 810 a2 = A2#y.max()
811 811 b2 = B2#x[numpy.argmax(y)]
812 812 c2 = C2#numpy.std(spc)
813 813 d = D
814 814
815 815 # fit
816 816
817 817 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
818 818
819 819 error = numpy.sqrt(numpy.diag(pcov))
820 820
821 821 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6], error[0], error[1], error[2], error[3], error[4], error[5], error[6]
822 822
823 823 def run(self, dataOut):
824 824
825 825 pwcode = 1
826 826
827 827 if dataOut.flagDecodeData:
828 828 pwcode = numpy.sum(dataOut.code[0]**2)
829 829 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
830 830 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
831 831 factor = normFactor
832 832 z = dataOut.data_spc / factor
833 833 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
834 834 dataOut.power = numpy.average(z, axis=1)
835 835 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
836 836
837 837
838 838 x = dataOut.getVelRange(0)
839 839
840 840 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
841 841 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
842 842
843 843 dataOut.VelRange = x
844 844
845 845
846 846 l1=range(22,36)
847 847 l2=range(58,99)
848 848
849 849 for hei in itertools.chain(l1, l2):
850 850
851 851 try:
852 852 spc = dataOut.data_spc[0,:,hei]
853 853
854 854 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
855 855
856 856 spc_diff = spc - spc_fit
857 857 spc_diff[spc_diff < 0] = 0
858 858
859 859 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
860 860
861 861 D = (D1+D2)
862 862
863 863 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_param_errors[0,0,hei],dataOut.Oblique_param_errors[0,1,hei],dataOut.Oblique_param_errors[0,2,hei],dataOut.Oblique_param_errors[0,3,hei],dataOut.Oblique_param_errors[0,4,hei],dataOut.Oblique_param_errors[0,5,hei],dataOut.Oblique_param_errors[0,6,hei] = self.Double_Gauss_fit_2(spc,x,A1,B1,C1,A2,B2,C2,D)
864 864 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
865 865
866 866 except:
867 867 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
868 868 pass
869 869
870 870 return dataOut
871 871
872 872 class PrecipitationProc(Operation):
873 873
874 874 '''
875 875 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
876 876
877 877 Input:
878 878 self.dataOut.data_pre : SelfSpectra
879 879
880 880 Output:
881 881
882 882 self.dataOut.data_output : Reflectivity factor, rainfall Rate
883 883
884 884
885 885 Parameters affected:
886 886 '''
887 887
888 888 def __init__(self):
889 889 Operation.__init__(self)
890 890 self.i=0
891 891
892 892 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
893 893 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
894 894
895 895 # print ('Entering PrecepitationProc ... ')
896 896
897 897 if radar == "MIRA35C" :
898 898
899 899 self.spc = dataOut.data_pre[0].copy()
900 900 self.Num_Hei = self.spc.shape[2]
901 901 self.Num_Bin = self.spc.shape[1]
902 902 self.Num_Chn = self.spc.shape[0]
903 903 Ze = self.dBZeMODE2(dataOut)
904 904
905 905 else:
906 906
907 907 self.spc = dataOut.data_pre[0].copy()
908 908
909 909 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
910 910 self.spc[:,:,0:7]= numpy.NaN
911 911
912 912 self.Num_Hei = self.spc.shape[2]
913 913 self.Num_Bin = self.spc.shape[1]
914 914 self.Num_Chn = self.spc.shape[0]
915 915
916 916 VelRange = dataOut.spc_range[2]
917 917
918 918 ''' Se obtiene la constante del RADAR '''
919 919
920 920 self.Pt = Pt
921 921 self.Gt = Gt
922 922 self.Gr = Gr
923 923 self.Lambda = Lambda
924 924 self.aL = aL
925 925 self.tauW = tauW
926 926 self.ThetaT = ThetaT
927 927 self.ThetaR = ThetaR
928 928 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
929 929 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
930 930 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
931 931
932 932 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
933 933 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
934 934 RadarConstant = 10e-26 * Numerator / Denominator #
935 935 ExpConstant = 10**(40/10) #Constante Experimental
936 936
937 937 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
938 938 for i in range(self.Num_Chn):
939 939 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
940 940 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
941 941
942 942 SPCmean = numpy.mean(SignalPower, 0)
943 943 Pr = SPCmean[:,:]/dataOut.normFactor
944 944
945 945 # Declaring auxiliary variables
946 946 Range = dataOut.heightList*1000. #Range in m
947 947 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
948 948 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
949 949 zMtrx = rMtrx+Altitude
950 950 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
951 951 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
952 952
953 953 # height dependence to air density Foote and Du Toit (1969)
954 954 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
955 955 VMtrx = VelMtrx / delv_z #Normalized velocity
956 956 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
957 957 # Diameter is related to the fall speed of falling drops
958 958 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
959 959 # Only valid for D>= 0.16 mm
960 960 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
961 961
962 962 #Calculate Radar Reflectivity ETAn
963 963 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
964 964 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
965 965 # Radar Cross Section
966 966 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
967 967 # Drop Size Distribution
968 968 DSD = ETAn / sigmaD
969 969 # Equivalente Reflectivy
970 970 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
971 971 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
972 972 # RainFall Rate
973 973 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
974 974
975 975 # Censoring the data
976 976 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
977 977 SNRth = 10**(SNRdBlimit/10) #-30dB
978 978 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
979 979 W = numpy.nanmean(dataOut.data_dop,0)
980 980 W[novalid] = numpy.NaN
981 981 Ze_org[novalid] = numpy.NaN
982 982 RR[novalid] = numpy.NaN
983 983
984 984 dataOut.data_output = RR[8]
985 985 dataOut.data_param = numpy.ones([3,self.Num_Hei])
986 986 dataOut.channelList = [0,1,2]
987 987
988 988 dataOut.data_param[0]=10*numpy.log10(Ze_org)
989 989 dataOut.data_param[1]=-W
990 990 dataOut.data_param[2]=RR
991 991
992 992 # print ('Leaving PrecepitationProc ... ')
993 993 return dataOut
994 994
995 995 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
996 996
997 997 NPW = dataOut.NPW
998 998 COFA = dataOut.COFA
999 999
1000 1000 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
1001 1001 RadarConst = dataOut.RadarConst
1002 1002 #frequency = 34.85*10**9
1003 1003
1004 1004 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
1005 1005 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
1006 1006
1007 1007 ETA = numpy.sum(SNR,1)
1008 1008
1009 1009 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
1010 1010
1011 1011 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
1012 1012
1013 1013 for r in range(self.Num_Hei):
1014 1014
1015 1015 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
1016 1016 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
1017 1017
1018 1018 return Ze
1019 1019
1020 1020 # def GetRadarConstant(self):
1021 1021 #
1022 1022 # """
1023 1023 # Constants:
1024 1024 #
1025 1025 # Pt: Transmission Power dB 5kW 5000
1026 1026 # Gt: Transmission Gain dB 24.7 dB 295.1209
1027 1027 # Gr: Reception Gain dB 18.5 dB 70.7945
1028 1028 # Lambda: Wavelenght m 0.6741 m 0.6741
1029 1029 # aL: Attenuation loses dB 4dB 2.5118
1030 1030 # tauW: Width of transmission pulse s 4us 4e-6
1031 1031 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
1032 1032 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
1033 1033 #
1034 1034 # """
1035 1035 #
1036 1036 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1037 1037 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1038 1038 # RadarConstant = Numerator / Denominator
1039 1039 #
1040 1040 # return RadarConstant
1041 1041
1042 1042
1043 1043 class FullSpectralAnalysis(Operation):
1044 1044
1045 1045 """
1046 1046 Function that implements Full Spectral Analysis technique.
1047 1047
1048 1048 Input:
1049 1049 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
1050 1050 self.dataOut.groupList : Pairlist of channels
1051 1051 self.dataOut.ChanDist : Physical distance between receivers
1052 1052
1053 1053
1054 1054 Output:
1055 1055
1056 1056 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
1057 1057
1058 1058
1059 1059 Parameters affected: Winds, height range, SNR
1060 1060
1061 1061 """
1062 1062 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
1063 1063 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
1064 1064
1065 1065 spc = dataOut.data_pre[0].copy()
1066 1066 cspc = dataOut.data_pre[1]
1067 1067 nHeights = spc.shape[2]
1068 1068
1069 1069 # first_height = 0.75 #km (ref: data header 20170822)
1070 1070 # resolution_height = 0.075 #km
1071 1071 '''
1072 1072 finding height range. check this when radar parameters are changed!
1073 1073 '''
1074 1074 if maxheight is not None:
1075 1075 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
1076 1076 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
1077 1077 else:
1078 1078 range_max = nHeights
1079 1079 if minheight is not None:
1080 1080 # range_min = int((minheight - first_height) / resolution_height) # theoretical
1081 1081 range_min = int(13.26 * minheight - 5) # empirical, works better
1082 1082 if range_min < 0:
1083 1083 range_min = 0
1084 1084 else:
1085 1085 range_min = 0
1086 1086
1087 1087 pairsList = dataOut.groupList
1088 1088 if dataOut.ChanDist is not None :
1089 1089 ChanDist = dataOut.ChanDist
1090 1090 else:
1091 1091 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
1092 1092
1093 1093 # 4 variables: zonal, meridional, vertical, and average SNR
1094 1094 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
1095 1095 velocityX = numpy.zeros([nHeights]) * numpy.NaN
1096 1096 velocityY = numpy.zeros([nHeights]) * numpy.NaN
1097 1097 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
1098 1098
1099 1099 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
1100 1100
1101 1101 '''***********************************************WIND ESTIMATION**************************************'''
1102 1102 for Height in range(nHeights):
1103 1103
1104 1104 if Height >= range_min and Height < range_max:
1105 1105 # error_code will be useful in future analysis
1106 1106 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
1107 1107 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
1108 1108
1109 1109 if abs(Vzon) < 100. and abs(Vmer) < 100.:
1110 1110 velocityX[Height] = Vzon
1111 1111 velocityY[Height] = -Vmer
1112 1112 velocityZ[Height] = Vver
1113 1113
1114 1114 # Censoring data with SNR threshold
1115 1115 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
1116 1116
1117 1117 data_param[0] = velocityX
1118 1118 data_param[1] = velocityY
1119 1119 data_param[2] = velocityZ
1120 1120 data_param[3] = dbSNR
1121 1121 dataOut.data_param = data_param
1122 1122 return dataOut
1123 1123
1124 1124 def moving_average(self,x, N=2):
1125 1125 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
1126 1126 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1127 1127
1128 1128 def gaus(self,xSamples,Amp,Mu,Sigma):
1129 1129 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
1130 1130
1131 1131 def Moments(self, ySamples, xSamples):
1132 1132 Power = numpy.nanmean(ySamples) # Power, 0th Moment
1133 1133 yNorm = ySamples / numpy.nansum(ySamples)
1134 1134 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
1135 1135 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
1136 1136 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
1137 1137 return numpy.array([Power,RadVel,StdDev])
1138 1138
1139 1139 def StopWindEstimation(self, error_code):
1140 1140 Vzon = numpy.NaN
1141 1141 Vmer = numpy.NaN
1142 1142 Vver = numpy.NaN
1143 1143 return Vzon, Vmer, Vver, error_code
1144 1144
1145 1145 def AntiAliasing(self, interval, maxstep):
1146 1146 """
1147 1147 function to prevent errors from aliased values when computing phaseslope
1148 1148 """
1149 1149 antialiased = numpy.zeros(len(interval))
1150 1150 copyinterval = interval.copy()
1151 1151
1152 1152 antialiased[0] = copyinterval[0]
1153 1153
1154 1154 for i in range(1,len(antialiased)):
1155 1155 step = interval[i] - interval[i-1]
1156 1156 if step > maxstep:
1157 1157 copyinterval -= 2*numpy.pi
1158 1158 antialiased[i] = copyinterval[i]
1159 1159 elif step < maxstep*(-1):
1160 1160 copyinterval += 2*numpy.pi
1161 1161 antialiased[i] = copyinterval[i]
1162 1162 else:
1163 1163 antialiased[i] = copyinterval[i].copy()
1164 1164
1165 1165 return antialiased
1166 1166
1167 1167 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1168 1168 """
1169 1169 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1170 1170 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1171 1171
1172 1172 Input:
1173 1173 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1174 1174 pairsList : Pairlist of channels
1175 1175 ChanDist : array of xi_ij and eta_ij
1176 1176 Height : height at which data is processed
1177 1177 noise : noise in [channels] format for specific height
1178 1178 Abbsisarange : range of the frequencies or velocities
1179 1179 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1180 1180
1181 1181 Output:
1182 1182 Vzon, Vmer, Vver : wind velocities
1183 1183 error_code : int that states where code is terminated
1184 1184
1185 1185 0 : no error detected
1186 1186 1 : Gaussian of mean spc exceeds widthlimit
1187 1187 2 : no Gaussian of mean spc found
1188 1188 3 : SNR to low or velocity to high -> prec. e.g.
1189 1189 4 : at least one Gaussian of cspc exceeds widthlimit
1190 1190 5 : zero out of three cspc Gaussian fits converged
1191 1191 6 : phase slope fit could not be found
1192 1192 7 : arrays used to fit phase have different length
1193 1193 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1194 1194
1195 1195 """
1196 1196
1197 1197 error_code = 0
1198 1198
1199 1199 nChan = spc.shape[0]
1200 1200 nProf = spc.shape[1]
1201 1201 nPair = cspc.shape[0]
1202 1202
1203 1203 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1204 1204 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1205 1205 phase = numpy.zeros([nPair, nProf]) # phase between channels
1206 1206 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1207 1207 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1208 1208 xFrec = AbbsisaRange[0][:-1] # frequency range
1209 1209 xVel = AbbsisaRange[2][:-1] # velocity range
1210 1210 xSamples = xFrec # the frequency range is taken
1211 1211 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1212 1212
1213 1213 # only consider velocities with in NegativeLimit and PositiveLimit
1214 1214 if (NegativeLimit is None):
1215 1215 NegativeLimit = numpy.min(xVel)
1216 1216 if (PositiveLimit is None):
1217 1217 PositiveLimit = numpy.max(xVel)
1218 1218 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1219 1219 xSamples_zoom = xSamples[xvalid]
1220 1220
1221 1221 '''Getting Eij and Nij'''
1222 1222 Xi01, Xi02, Xi12 = ChanDist[:,0]
1223 1223 Eta01, Eta02, Eta12 = ChanDist[:,1]
1224 1224
1225 1225 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1226 1226 widthlimit = 10
1227 1227 '''************************* SPC is normalized ********************************'''
1228 1228 spc_norm = spc.copy()
1229 1229 # For each channel
1230 1230 for i in range(nChan):
1231 1231 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1232 1232 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1233 1233
1234 1234 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1235 1235
1236 1236 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1237 1237 you only fit the curve and don't need the absolute value of height for calculation,
1238 1238 only for estimation of width. for normalization of cross spectra, you need initial,
1239 1239 unnormalized self-spectra With noise.
1240 1240
1241 1241 Technically, you don't even need to normalize the self-spectra, as you only need the
1242 1242 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1243 1243 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1244 1244 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1245 1245 """
1246 1246 # initial conditions
1247 1247 popt = [1e-10,0,1e-10]
1248 1248 # Spectra average
1249 1249 SPCMean = numpy.average(SPC_Samples,0)
1250 1250 # Moments in frequency
1251 1251 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1252 1252
1253 1253 # Gauss Fit SPC in frequency domain
1254 1254 if dbSNR > SNRlimit: # only if SNR > SNRth
1255 1255 try:
1256 1256 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1257 1257 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1258 1258 return self.StopWindEstimation(error_code = 1)
1259 1259 FitGauss = self.gaus(xSamples_zoom,*popt)
1260 1260 except :#RuntimeError:
1261 1261 return self.StopWindEstimation(error_code = 2)
1262 1262 else:
1263 1263 return self.StopWindEstimation(error_code = 3)
1264 1264
1265 1265 '''***************************** CSPC Normalization *************************
1266 1266 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1267 1267 influence the norm which is not desired. First, a range is identified where the
1268 1268 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1269 1269 around it gets cut off and values replaced by mean determined by the boundary
1270 1270 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1271 1271
1272 1272 The sums are then added and multiplied by range/datapoints, because you need
1273 1273 an integral and not a sum for normalization.
1274 1274
1275 1275 A norm is found according to Briggs 92.
1276 1276 '''
1277 1277 # for each pair
1278 1278 for i in range(nPair):
1279 1279 cspc_norm = cspc[i,:].copy()
1280 1280 chan_index0 = pairsList[i][0]
1281 1281 chan_index1 = pairsList[i][1]
1282 1282 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1283 1283 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1284 1284
1285 1285 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1286 1286 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1287 1287 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1288 1288
1289 1289 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1290 1290 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1291 1291
1292 1292 '''*******************************FIT GAUSS CSPC************************************'''
1293 1293 try:
1294 1294 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1295 1295 if popt01[2] > widthlimit: # CONDITION
1296 1296 return self.StopWindEstimation(error_code = 4)
1297 1297 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1298 1298 if popt02[2] > widthlimit: # CONDITION
1299 1299 return self.StopWindEstimation(error_code = 4)
1300 1300 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1301 1301 if popt12[2] > widthlimit: # CONDITION
1302 1302 return self.StopWindEstimation(error_code = 4)
1303 1303
1304 1304 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1305 1305 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1306 1306 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1307 1307 except:
1308 1308 return self.StopWindEstimation(error_code = 5)
1309 1309
1310 1310
1311 1311 '''************* Getting Fij ***************'''
1312 1312 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1313 1313 GaussCenter = popt[1]
1314 1314 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1315 1315 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1316 1316
1317 1317 # Point where e^-1 is located in the gaussian
1318 1318 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1319 1319 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1320 1320 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1321 1321 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1322 1322
1323 1323 '''********** Taking frequency ranges from mean SPCs **********'''
1324 1324 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1325 1325 Range = numpy.empty(2)
1326 1326 Range[0] = GaussCenter - GauWidth
1327 1327 Range[1] = GaussCenter + GauWidth
1328 1328 # Point in x-axis where the bandwidth is located (min:max)
1329 1329 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1330 1330 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1331 1331 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1332 1332 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1333 1333 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1334 1334 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1335 1335
1336 1336 '''************************** Getting Phase Slope ***************************'''
1337 1337 for i in range(nPair):
1338 1338 if len(FrecRange) > 5:
1339 1339 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1340 1340 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1341 1341 if len(FrecRange) == len(PhaseRange):
1342 1342 try:
1343 1343 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1344 1344 PhaseSlope[i] = slope
1345 1345 PhaseInter[i] = intercept
1346 1346 except:
1347 1347 return self.StopWindEstimation(error_code = 6)
1348 1348 else:
1349 1349 return self.StopWindEstimation(error_code = 7)
1350 1350 else:
1351 1351 return self.StopWindEstimation(error_code = 8)
1352 1352
1353 1353 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1354 1354
1355 1355 '''Getting constant C'''
1356 1356 cC=(Fij*numpy.pi)**2
1357 1357
1358 1358 '''****** Getting constants F and G ******'''
1359 1359 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1360 1360 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1361 1361 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1362 1362 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1363 1363 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1364 1364 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1365 1365 MijResults = numpy.array([MijResult1, MijResult2])
1366 1366 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1367 1367
1368 1368 '''****** Getting constants A, B and H ******'''
1369 1369 W01 = numpy.nanmax( FitGauss01 )
1370 1370 W02 = numpy.nanmax( FitGauss02 )
1371 1371 W12 = numpy.nanmax( FitGauss12 )
1372 1372
1373 1373 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1374 1374 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1375 1375 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1376 1376 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1377 1377
1378 1378 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1379 1379 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1380 1380
1381 1381 VxVy = numpy.array([[cA,cH],[cH,cB]])
1382 1382 VxVyResults = numpy.array([-cF,-cG])
1383 1383 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1384 1384 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1385 1385 error_code = 0
1386 1386
1387 1387 return Vzon, Vmer, Vver, error_code
1388 1388
1389 1389 class SpectralMoments(Operation):
1390 1390
1391 1391 '''
1392 1392 Function SpectralMoments()
1393 1393
1394 1394 Calculates moments (power, mean, standard deviation) and SNR of the signal
1395 1395
1396 1396 Type of dataIn: Spectra
1397 1397
1398 1398 Configuration Parameters:
1399 1399
1400 1400 dirCosx : Cosine director in X axis
1401 1401 dirCosy : Cosine director in Y axis
1402 1402
1403 1403 elevation :
1404 1404 azimuth :
1405 1405
1406 1406 Input:
1407 1407 channelList : simple channel list to select e.g. [2,3,7]
1408 1408 self.dataOut.data_pre : Spectral data
1409 1409 self.dataOut.abscissaList : List of frequencies
1410 1410 self.dataOut.noise : Noise level per channel
1411 1411
1412 1412 Affected:
1413 1413 self.dataOut.moments : Parameters per channel
1414 1414 self.dataOut.data_snr : SNR per channel
1415 1415
1416 1416 '''
1417 1417
1418 1418 def run(self, dataOut, proc_type=0):
1419 1419
1420 1420 absc = dataOut.abscissaList[:-1]
1421 1421 noise = dataOut.noise
1422 nChannel = data.shape[0]
1423 data_param = numpy.zeros((nChannel, 8, data.shape[2]))
1422 nChannel = dataOut.data_pre[0].shape[0]
1423 data_param = numpy.zeros((nChannel, 4 + proc_type*3, dataOut.data_pre[0].shape[2]))
1424 1424
1425 1425 if proc_type == 1:
1426 1426 fwindow = numpy.zeros(absc.size) + 1
1427 1427 #b=64
1428 1428 b=16
1429 1429 fwindow[0:absc.size//2 - b] = 0
1430 1430 fwindow[absc.size//2 + b:] = 0
1431 1431 type1 = 1 # moments calculation
1432 1432 nProfiles = dataOut.nProfiles
1433 1433 nCohInt = dataOut.nCohInt
1434 1434 nIncohInt = dataOut.nIncohInt
1435 1435 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
1436 1436 N = numpy.array(M / nIncohInt,dtype='float32')
1437 1437 data = dataOut.data_pre[0] * N
1438 1438 #noise = dataOut.noise * N
1439 1439 noise = numpy.zeros(nChannel)
1440 1440 for ind in range(nChannel):
1441 1441 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
1442 1442 smooth=3
1443 1443 else:
1444 1444 data = dataOut.data_pre[0]
1445 1445 noise = dataOut.noise
1446 1446 fwindow = None
1447 1447 type1 = 0
1448 1448 nIncohInt = None
1449 1449 smooth=None
1450 1450
1451 1451 for ind in range(nChannel):
1452 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, id_ch=ind)
1452 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow)
1453 1453
1454 1454 if proc_type == 1:
1455 1455 dataOut.moments = data_param[:,1:,:]
1456 1456 dataOut.data_dop = data_param[:,0]
1457 1457 dataOut.data_width = data_param[:,1]
1458 1458 dataOut.data_snr = data_param[:,2]
1459 1459 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
1460 1460 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
1461 1461
1462 1462 else:
1463 1463 dataOut.moments = data_param[:,1:,:]
1464 1464 dataOut.data_snr = data_param[:,0]
1465 1465 dataOut.data_pow = data_param[:,1]
1466 1466 dataOut.data_dop = data_param[:,2]
1467 1467 dataOut.data_width = data_param[:,3]
1468 1468 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
1469 1469
1470 1470 return dataOut
1471 1471
1472 1472 def __calculateMoments(self, oldspec, oldfreq, n0,
1473 1473 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1474 1474
1475 1475 def __GAUSSWINFIT1(A, flagPDER=0):
1476 1476 nonlocal truex, xvalid
1477 1477 nparams = 4
1478 1478 M=truex.size
1479 1479 mm=numpy.arange(M,dtype='f4')
1480 1480 delta = numpy.zeros(M,dtype='f4')
1481 1481 delta[0] = 1.0
1482 1482 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
1483 1483 jj = -1j
1484 1484 #if self.winauto is None: self.winauto = (1.0 - mm/M)
1485 1485 winauto = (1.0 - mm/M)
1486 1486 winauto = winauto/winauto.max() # Normalized to 1
1487 1487 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
1488 1488 A[0] = numpy.abs(A[0])
1489 1489 A[2] = numpy.abs(A[2])
1490 1490 A[3] = numpy.abs(A[3])
1491 1491 pi=numpy.array([numpy.pi],dtype='f4')[0]
1492 1492 if A[2] != 0:
1493 1493 Z = numpy.exp(-2*numpy.power((pi*A[2]*mm*Ts),2,dtype='f4')+jj*2*pi*A[1]*mm*Ts, dtype='c8') # Get Z
1494 1494 else:
1495 1495 Z = mm*0.0
1496 1496 A[0] = 0.0
1497 1497 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
1498 1498 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
1499 1499 F = junkF[xvalid]
1500 1500 if flagPDER == 0: #NEED PARTIAL?
1501 1501 return F
1502 1502 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
1503 1503 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
1504 1504 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
1505 1505 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
1506 1506 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
1507 1507 PDER = PDER[xvalid,:]
1508 1508 return F, PDER
1509 1509
1510 1510 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
1511 1511 itmax=20, tol=None):
1512 1512 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
1513 1513 if tol == None:
1514 1514 tol = numpy.array([1.e-3],dtype='f4')[0]
1515 1515 typ=a.dtype
1516 1516 double = 1 if typ == numpy.float64 else 0
1517 1517 if typ != numpy.float32:
1518 1518 a=a.astype(numpy.float32) #Make params floating
1519 1519 # if we will be estimating partial derivates then compute machine precision
1520 1520 if FlagNoDerivative == 1:
1521 1521 res=numpy.MachAr(float_conv=numpy.float32)
1522 1522 eps=numpy.sqrt(res.eps)
1523 1523
1524 1524 nterms = a.size # Number of parameters
1525 1525 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
1526 1526 if nfree <= 0: print('Curvefit - not enough data points.')
1527 1527 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
1528 1528 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
1529 1529 # Use diag method in python
1530 1530 converge=1
1531 1531
1532 1532 #Define the partial derivative array
1533 1533 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
1534 1534
1535 1535 for Niter in range(itmax): #Iteration loop
1536 1536
1537 1537 if FlagNoDerivative == 1:
1538 1538 #Evaluate function and estimate partial derivatives
1539 1539 yfit = __GAUSSWINFIT1(a)
1540 1540 for term in range(nterms):
1541 1541 p=a.copy() # Copy current parameters
1542 1542 #Increment size for forward difference derivative
1543 1543 inc = eps * abs(p[term])
1544 1544 if inc == 0: inc = eps
1545 1545 p[term] = p[term] + inc
1546 1546 yfit1 = __GAUSSWINFIT1(p)
1547 1547 PDER[term,:] = (yfit1-yfit)/inc
1548 1548 else:
1549 1549 #The user's procedure will return partial derivatives
1550 1550 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
1551 1551
1552 1552 beta = numpy.dot(PDER,(y-yfit)*Weights)
1553 1553 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
1554 1554 # save current values of return parameters
1555 1555 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
1556 1556 sigma = sigma1
1557 1557
1558 1558 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
1559 1559 chisq = chisq1
1560 1560 yfit1 = yfit
1561 1561 elev7=numpy.array([1.0e7],dtype='f4')[0]
1562 1562 compara =numpy.sum(abs(y))/elev7/nfree
1563 1563 done_early = chisq1 < compara
1564 1564
1565 1565 if done_early:
1566 1566 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1567 1567 if done_early: Niter -= 1
1568 1568 #save_tp(chisq,Niter,yfit)
1569 1569 return yfit, a, converge, sigma, chisq # return result
1570 1570 #c = numpy.dot(c, c) # this operator implemented at the next lines
1571 1571 c_tmp = numpy.sqrt(numpy.diag(alpha))
1572 1572 siz=len(c_tmp)
1573 1573 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
1574 1574 lambdaCount = 0
1575 1575 while True:
1576 1576 lambdaCount += 1
1577 1577 # Normalize alpha to have unit diagonal.
1578 1578 array = alpha / c
1579 1579 # Augment the diagonal.
1580 1580 one=numpy.array([1.],dtype='f4')[0]
1581 1581 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
1582 1582 # Invert modified curvature matrix to find new parameters.
1583 1583
1584 1584 try:
1585 1585 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
1586 1586 except Exception as e:
1587 1587 print(e)
1588 1588 array[:]=numpy.NaN
1589 1589
1590 1590 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
1591 1591 yfit = __GAUSSWINFIT1(b) # Evaluate function
1592 1592 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
1593 1593 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
1594 1594 if (numpy.isfinite(chisq) == 0) or \
1595 1595 (lambdaCount > 30 and chisq >= chisq1):
1596 1596 # Reject changes made this iteration, use old values.
1597 1597 yfit = yfit1
1598 1598 sigma = sigma1
1599 1599 chisq = chisq1
1600 1600 converge = 0
1601 1601 #print('Failed to converge.')
1602 1602 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1603 1603 if done_early: Niter -= 1
1604 1604 #save_tp(chisq,Niter,yfit)
1605 1605 return yfit, a, converge, sigma, chisq, chi2 # return result
1606 1606 ten=numpy.array([10.0],dtype='f4')[0]
1607 1607 flambda *= ten # Assume fit got worse
1608 1608 if chisq <= chisq1:
1609 1609 break
1610 1610 hundred=numpy.array([100.0],dtype='f4')[0]
1611 1611 flambda /= hundred
1612 1612
1613 1613 a=b # Save new parameter estimate.
1614 1614 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
1615 1615 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
1616 1616 if done_early: Niter -= 1
1617 1617 #save_tp(chisq,Niter,yfit)
1618 1618 return yfit, a, converge, sigma, chisq, chi2 # return result
1619 1619 converge = 0
1620 1620 chi2 = chisq
1621 1621 #print('Failed to converge.')
1622 1622 #save_tp(chisq,Niter,yfit)
1623 1623 return yfit, a, converge, sigma, chisq, chi2
1624 1624
1625 1625 if (nicoh is None): nicoh = 1
1626 1626 if (smooth is None): smooth = 0
1627 1627 if (type1 is None): type1 = 0
1628 1628 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1629 1629 if (snrth is None): snrth = -3
1630 1630 if (dc is None): dc = 0
1631 1631 if (aliasing is None): aliasing = 0
1632 1632 if (oldfd is None): oldfd = 0
1633 1633 if (wwauto is None): wwauto = 0
1634 1634
1635 1635 if (n0 < 1.e-20): n0 = 1.e-20
1636 1636
1637 1637 xvalid = numpy.where(fwindow == 1)[0]
1638 1638 freq = oldfreq
1639 1639 truex = oldfreq
1640 1640 vec_power = numpy.zeros(oldspec.shape[1])
1641 1641 vec_fd = numpy.zeros(oldspec.shape[1])
1642 1642 vec_w = numpy.zeros(oldspec.shape[1])
1643 1643 vec_snr = numpy.zeros(oldspec.shape[1])
1644 1644 vec_n1 = numpy.empty(oldspec.shape[1])
1645 1645 vec_fp = numpy.empty(oldspec.shape[1])
1646 1646 vec_sigma_fd = numpy.empty(oldspec.shape[1])
1647 1647
1648 1648 for ind in range(oldspec.shape[1]):
1649 1649
1650 1650 spec = oldspec[:,ind]
1651 1651 if (smooth == 0):
1652 1652 spec2 = spec
1653 1653 else:
1654 1654 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1655 1655
1656 1656 aux = spec2*fwindow
1657 1657 max_spec = aux.max()
1658 1658 m = aux.tolist().index(max_spec)
1659 1659
1660 1660 if m > 2 and m < oldfreq.size - 3:
1661 1661 newindex = m + numpy.array([-2,-1,0,1,2])
1662 1662 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
1663 1663 #peakspec = SPLINE(,)
1664 1664 tck = interpolate.splrep(freq[newindex], spec2[newindex])
1665 1665 peakspec = interpolate.splev(newfreq, tck)
1666 1666 # max_spec = MAX(peakspec,)
1667 1667 max_spec = numpy.max(peakspec)
1668 1668 mnew = numpy.argmax(peakspec)
1669 1669 #fp = newfreq(mnew)
1670 1670 fp = newfreq[mnew]
1671 1671 else:
1672 1672 fp = freq[m]
1673 1673
1674 1674 if type1==0:
1675 1675
1676 1676 # Moments Estimation
1677 1677 bb = spec2[numpy.arange(m,spec2.size)]
1678 1678 bb = (bb<n0).nonzero()
1679 1679 bb = bb[0]
1680 1680
1681 1681 ss = spec2[numpy.arange(0,m + 1)]
1682 1682 ss = (ss<n0).nonzero()
1683 1683 ss = ss[0]
1684 1684
1685 1685 if (bb.size == 0):
1686 1686 bb0 = spec.size - 1 - m
1687 1687 else:
1688 1688 bb0 = bb[0] - 1
1689 1689 if (bb0 < 0):
1690 1690 bb0 = 0
1691 1691
1692 1692 if (ss.size == 0):
1693 1693 ss1 = 1
1694 1694 else:
1695 1695 ss1 = max(ss) + 1
1696 1696
1697 1697 if (ss1 > m):
1698 1698 ss1 = m
1699 1699
1700 1700 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1701 1701
1702 1702 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1703 1703 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1704 1704 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1705 1705 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1706 1706 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1707 1707 snr = (spec2.mean()-n0)/n0
1708 1708 if (snr < 1.e-20): snr = 1.e-20
1709 1709
1710 1710 vec_power[ind] = total_power
1711 1711 vec_fd[ind] = fd
1712 1712 vec_w[ind] = w
1713 1713 vec_snr[ind] = snr
1714 1714 else:
1715 1715 # Noise by heights
1716 1716 n1, stdv = self.__get_noise2(spec, nicoh)
1717 1717 # Moments Estimation
1718 1718 bb = spec2[numpy.arange(m,spec2.size)]
1719 1719 bb = (bb<n1).nonzero()
1720 1720 bb = bb[0]
1721 1721
1722 1722 ss = spec2[numpy.arange(0,m + 1)]
1723 1723 ss = (ss<n1).nonzero()
1724 1724 ss = ss[0]
1725 1725
1726 1726 if (bb.size == 0):
1727 1727 bb0 = spec.size - 1 - m
1728 1728 else:
1729 1729 bb0 = bb[0] - 1
1730 1730 if (bb0 < 0):
1731 1731 bb0 = 0
1732 1732
1733 1733 if (ss.size == 0):
1734 1734 ss1 = 1
1735 1735 else:
1736 1736 ss1 = max(ss) + 1
1737 1737
1738 1738 if (ss1 > m):
1739 1739 ss1 = m
1740 1740
1741 1741 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1742 1742
1743 1743 power = ((spec[valid] - n1)*fwindow[valid]).sum()
1744 1744 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
1745 1745 try:
1746 1746 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1747 1747 except:
1748 1748 w = float("NaN")
1749 1749 snr = power/(n0*fwindow.sum())
1750 1750 if snr < 1.e-20: snr = 1.e-20
1751 1751
1752 1752 # Here start gaussean adjustment
1753 1753
1754 1754 if snr > numpy.power(10,0.1*snrth):
1755 1755
1756 1756 a = numpy.zeros(4,dtype='f4')
1757 1757 a[0] = snr * n0
1758 1758 a[1] = fd
1759 1759 a[2] = w
1760 1760 a[3] = n0
1761 1761
1762 1762 np = spec.size
1763 1763 aold = a.copy()
1764 1764 spec2 = spec.copy()
1765 1765 oldxvalid = xvalid.copy()
1766 1766
1767 1767 for i in range(2):
1768 1768
1769 1769 ww = 1.0/(numpy.power(spec2,2)/nicoh)
1770 1770 ww[np//2] = 0.0
1771 1771
1772 1772 a = aold.copy()
1773 1773 xvalid = oldxvalid.copy()
1774 1774 #self.show_var(xvalid)
1775 1775
1776 1776 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
1777 1777 a = gaussfn[1]
1778 1778
1779 1779 xvalid = numpy.arange(np)
1780 1780 spec2 = __GAUSSWINFIT1(a)
1781 1781
1782 1782 xvalid = oldxvalid.copy()
1783 1783 power = a[0] * np
1784 1784 fd = a[1]
1785 1785 sigma_fd = gaussfn[3][1]
1786 1786 snr = max(power/ (max(a[3],n0) * len(oldxvalid)), 1e-20)
1787 1787 w = numpy.abs(a[2])
1788 1788 n1 = max(a[3], n0)
1789 1789
1790 1790 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
1791 1791 else:
1792 1792 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
1793 1793
1794 1794 vec_fd[ind] = fd
1795 1795 vec_w[ind] = w
1796 1796 vec_snr[ind] = snr
1797 1797 vec_n1[ind] = n1
1798 1798 vec_fp[ind] = fp
1799 1799 vec_sigma_fd[ind] = sigma_fd
1800 1800 vec_power[ind] = power # to compare with type 0 proccessing
1801 1801
1802 1802 if type1==1:
1803 1803 return numpy.vstack((vec_fd, vec_w, vec_snr, vec_n1, vec_fp, vec_sigma_fd, vec_power))
1804 1804 else:
1805 1805 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1806 1806
1807 1807 def __get_noise2(self,POWER, fft_avg, TALK=0):
1808 1808 '''
1809 1809 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
1810 1810 '''
1811 1811 SPECT_PTS = len(POWER)
1812 1812 fft_avg = fft_avg*1.0
1813 1813 NOMIT = 0
1814 1814 NN = SPECT_PTS - NOMIT
1815 1815 N = NN//2
1816 1816 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
1817 1817 ARR = numpy.sort(ARR)
1818 1818 NUMS_MIN = (SPECT_PTS+7)//8
1819 1819 RTEST = (1.0+1.0/fft_avg)
1820 1820 SUM = 0.0
1821 1821 SUMSQ = 0.0
1822 1822 J = 0
1823 1823 for I in range(NN):
1824 1824 J = J + 1
1825 1825 SUM = SUM + ARR[I]
1826 1826 SUMSQ = SUMSQ + ARR[I]*ARR[I]
1827 1827 AVE = SUM*1.0/J
1828 1828 if J > NUMS_MIN:
1829 1829 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
1830 1830 else:
1831 1831 if J == NUMS_MIN: RNOISE = AVE
1832 1832 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
1833 1833 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1834 1834 return RNOISE, stdv
1835 1835
1836 1836 def __get_noise1(self, power, fft_avg, TALK=1):
1837 1837 '''
1838 1838 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
1839 1839 '''
1840 1840 num_pts = numpy.size(power)
1841 1841 #print('num_pts',num_pts)
1842 1842 #print('power',power.shape)
1843 1843 #print(power[256:267,0:2])
1844 1844 fft_avg = fft_avg*1.0
1845 1845
1846 1846 ind = numpy.argsort(power, axis=None, kind='stable')
1847 1847 #ind = numpy.argsort(numpy.reshape(power,-1))
1848 1848 #print(ind.shape)
1849 1849 #print(ind[0:11])
1850 1850 #print(numpy.reshape(power,-1)[ind[0:11]])
1851 1851 ARR = numpy.reshape(power,-1)[ind]
1852 1852 #print('ARR',len(ARR))
1853 1853 #print('ARR',ARR.shape)
1854 1854 NUMS_MIN = num_pts//10
1855 1855 RTEST = (1.0+1.0/fft_avg)
1856 1856 SUM = 0.0
1857 1857 SUMSQ = 0.0
1858 1858 J = 0
1859 1859 cont = 1
1860 1860 while cont == 1 and J < num_pts:
1861 1861
1862 1862 SUM = SUM + ARR[J]
1863 1863 SUMSQ = SUMSQ + ARR[J]*ARR[J]
1864 1864 J = J + 1
1865 1865
1866 1866 if J > NUMS_MIN:
1867 1867 if (SUMSQ*J <= RTEST*SUM*SUM):
1868 1868 LNOISE = SUM*1.0/J
1869 1869 else:
1870 1870 J = J - 1
1871 1871 SUM = SUM - ARR[J]
1872 1872 SUMSQ = SUMSQ - ARR[J]*ARR[J]
1873 1873 cont = 0
1874 1874 else:
1875 1875 if J == NUMS_MIN: LNOISE = SUM*1.0/J
1876 1876 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
1877 1877 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
1878 1878 return LNOISE, stdv
1879 1879
1880 1880 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
1881 1881
1882 1882 val_frq = numpy.arange(num_prof-2)+1
1883 1883 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
1884 1884 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
1885 1885 junkid = numpy.argsort(junkspc)
1886 1886 noisezone = val_frq[junkid[0:num_prof//2]]
1887 1887 specnoise = spectra[noisezone,:]
1888 1888 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
1889 1889
1890 1890 if talk:
1891 1891 print('noise =', noise)
1892 1892 return noise
1893 1893
1894 1894 class SALags(Operation):
1895 1895 '''
1896 1896 Function GetMoments()
1897 1897
1898 1898 Input:
1899 1899 self.dataOut.data_pre
1900 1900 self.dataOut.abscissaList
1901 1901 self.dataOut.noise
1902 1902 self.dataOut.normFactor
1903 1903 self.dataOut.data_snr
1904 1904 self.dataOut.groupList
1905 1905 self.dataOut.nChannels
1906 1906
1907 1907 Affected:
1908 1908 self.dataOut.data_param
1909 1909
1910 1910 '''
1911 1911 def run(self, dataOut):
1912 1912 data_acf = dataOut.data_pre[0]
1913 1913 data_ccf = dataOut.data_pre[1]
1914 1914 normFactor_acf = dataOut.normFactor[0]
1915 1915 normFactor_ccf = dataOut.normFactor[1]
1916 1916 pairs_acf = dataOut.groupList[0]
1917 1917 pairs_ccf = dataOut.groupList[1]
1918 1918
1919 1919 nHeights = dataOut.nHeights
1920 1920 absc = dataOut.abscissaList
1921 1921 noise = dataOut.noise
1922 1922 SNR = dataOut.data_snr
1923 1923 nChannels = dataOut.nChannels
1924 1924 # pairsList = dataOut.groupList
1925 1925 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1926 1926
1927 1927 for l in range(len(pairs_acf)):
1928 1928 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1929 1929
1930 1930 for l in range(len(pairs_ccf)):
1931 1931 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1932 1932
1933 1933 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1934 1934 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1935 1935 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1936 1936 return
1937 1937
1938 1938 # def __getPairsAutoCorr(self, pairsList, nChannels):
1939 1939 #
1940 1940 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1941 1941 #
1942 1942 # for l in range(len(pairsList)):
1943 1943 # firstChannel = pairsList[l][0]
1944 1944 # secondChannel = pairsList[l][1]
1945 1945 #
1946 1946 # #Obteniendo pares de Autocorrelacion
1947 1947 # if firstChannel == secondChannel:
1948 1948 # pairsAutoCorr[firstChannel] = int(l)
1949 1949 #
1950 1950 # pairsAutoCorr = pairsAutoCorr.astype(int)
1951 1951 #
1952 1952 # pairsCrossCorr = range(len(pairsList))
1953 1953 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1954 1954 #
1955 1955 # return pairsAutoCorr, pairsCrossCorr
1956 1956
1957 1957 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1958 1958
1959 1959 lag0 = data_acf.shape[1]/2
1960 1960 #Funcion de Autocorrelacion
1961 1961 mean_acf = stats.nanmean(data_acf, axis = 0)
1962 1962
1963 1963 #Obtencion Indice de TauCross
1964 1964 ind_ccf = data_ccf.argmax(axis = 1)
1965 1965 #Obtencion Indice de TauAuto
1966 1966 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1967 1967 ccf_lag0 = data_ccf[:,lag0,:]
1968 1968
1969 1969 for i in range(ccf_lag0.shape[0]):
1970 1970 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1971 1971
1972 1972 #Obtencion de TauCross y TauAuto
1973 1973 tau_ccf = lagRange[ind_ccf]
1974 1974 tau_acf = lagRange[ind_acf]
1975 1975
1976 1976 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1977 1977
1978 1978 tau_ccf[Nan1,Nan2] = numpy.nan
1979 1979 tau_acf[Nan1,Nan2] = numpy.nan
1980 1980 tau = numpy.vstack((tau_ccf,tau_acf))
1981 1981
1982 1982 return tau
1983 1983
1984 1984 def __calculateLag1Phase(self, data, lagTRange):
1985 1985 data1 = stats.nanmean(data, axis = 0)
1986 1986 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1987 1987
1988 1988 phase = numpy.angle(data1[lag1,:])
1989 1989
1990 1990 return phase
1991 1991
1992 1992 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
1993 1993 z = (x - a1) / a2
1994 1994 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
1995 1995 return y
1996 1996
1997 1997
1998 1998 class SpectralFitting(Operation):
1999 1999 '''
2000 2000 Function GetMoments()
2001 2001
2002 2002 Input:
2003 2003 Output:
2004 2004 Variables modified:
2005 2005 '''
2006 2006 def __calculateMoments(self,oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
2007 2007
2008 2008 if (nicoh is None): nicoh = 1
2009 2009 if (graph is None): graph = 0
2010 2010 if (smooth is None): smooth = 0
2011 2011 elif (self.smooth < 3): smooth = 0
2012 2012
2013 2013 if (type1 is None): type1 = 0
2014 2014 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2015 2015 if (snrth is None): snrth = -3
2016 2016 if (dc is None): dc = 0
2017 2017 if (aliasing is None): aliasing = 0
2018 2018 if (oldfd is None): oldfd = 0
2019 2019 if (wwauto is None): wwauto = 0
2020 2020
2021 2021 if (n0 < 1.e-20): n0 = 1.e-20
2022 2022
2023 2023 freq = oldfreq
2024 2024 vec_power = numpy.zeros(oldspec.shape[1])
2025 2025 vec_fd = numpy.zeros(oldspec.shape[1])
2026 2026 vec_w = numpy.zeros(oldspec.shape[1])
2027 2027 vec_snr = numpy.zeros(oldspec.shape[1])
2028 2028
2029 2029 oldspec = numpy.ma.masked_invalid(oldspec)
2030 2030
2031 2031 for ind in range(oldspec.shape[1]):
2032 2032
2033 2033 spec = oldspec[:,ind]
2034 2034 aux = spec*fwindow
2035 2035 max_spec = aux.max()
2036 2036 m = list(aux).index(max_spec)
2037 2037
2038 2038 #Smooth
2039 2039 if (smooth == 0): spec2 = spec
2040 2040 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2041 2041
2042 2042 # Calculo de Momentos
2043 2043 bb = spec2[list(range(m,spec2.size))]
2044 2044 bb = (bb<n0).nonzero()
2045 2045 bb = bb[0]
2046 2046
2047 2047 ss = spec2[list(range(0,m + 1))]
2048 2048 ss = (ss<n0).nonzero()
2049 2049 ss = ss[0]
2050 2050
2051 2051 if (bb.size == 0):
2052 2052 bb0 = spec.size - 1 - m
2053 2053 else:
2054 2054 bb0 = bb[0] - 1
2055 2055 if (bb0 < 0):
2056 2056 bb0 = 0
2057 2057
2058 2058 if (ss.size == 0): ss1 = 1
2059 2059 else: ss1 = max(ss) + 1
2060 2060
2061 2061 if (ss1 > m): ss1 = m
2062 2062
2063 2063 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
2064 2064 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
2065 2065 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
2066 2066 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2067 2067 snr = (spec2.mean()-n0)/n0
2068 2068
2069 2069 if (snr < 1.e-20) :
2070 2070 snr = 1.e-20
2071 2071
2072 2072 vec_power[ind] = power
2073 2073 vec_fd[ind] = fd
2074 2074 vec_w[ind] = w
2075 2075 vec_snr[ind] = snr
2076 2076
2077 2077 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2078 2078 return moments
2079 2079
2080 2080 #def __DiffCoherent(self,snrth, spectra, cspectra, nProf, heights,nChan, nHei, nPairs, channels, noise, crosspairs):
2081 2081 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
2082 2082
2083 2083 import matplotlib.pyplot as plt
2084 2084 nProf = dataOut.nProfiles
2085 2085 heights = dataOut.heightList
2086 2086 nHei = len(heights)
2087 2087 channels = dataOut.channelList
2088 2088 nChan = len(channels)
2089 2089 crosspairs = dataOut.groupList
2090 2090 nPairs = len(crosspairs)
2091 2091 #Separar espectros incoherentes de coherentes snr > 20 dB'
2092 2092 snr_th = 10**(snrth/10.0)
2093 2093 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
2094 2094 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
2095 2095 my_incoh_aver = numpy.zeros([nChan, nHei])
2096 2096 my_coh_aver = numpy.zeros([nChan, nHei])
2097 2097
2098 2098 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2099 2099 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2100 2100 coh_aver = numpy.zeros([nChan, nHei])
2101 2101
2102 2102 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
2103 2103 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
2104 2104 incoh_aver = numpy.zeros([nChan, nHei])
2105 2105 power = numpy.sum(spectra, axis=1)
2106 2106
2107 2107 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
2108 2108 if hei_th == None : hei_th = numpy.array([60,300,650])
2109 2109 for ic in range(2):
2110 2110 pair = crosspairs[ic]
2111 2111 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
2112 2112 s_n0 = power[pair[0],:]/noise[pair[0]]
2113 2113 s_n1 = power[pair[1],:]/noise[pair[1]]
2114 2114
2115 2115 valid1 =(s_n0>=snr_th).nonzero()
2116 2116 valid2 = (s_n1>=snr_th).nonzero()
2117 2117 #valid = valid2 + valid1 #numpy.concatenate((valid1,valid2), axis=None)
2118 2118 valid1 = numpy.array(valid1[0])
2119 2119 valid2 = numpy.array(valid2[0])
2120 2120 valid = valid1
2121 2121 for iv in range(len(valid2)):
2122 2122 #for ivv in range(len(valid1)) :
2123 2123 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2124 2124 if len(indv[0]) == 0 :
2125 2125 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2126 2126 if len(valid)>0:
2127 2127 my_coh_aver[pair[0],valid]=1
2128 2128 my_coh_aver[pair[1],valid]=1
2129 2129 # si la coherencia es mayor a la coherencia threshold los datos se toman
2130 2130 #print my_coh_aver[0,:]
2131 2131 coh = numpy.squeeze(numpy.nansum(cspectra[ic,:,:], axis=0)/numpy.sqrt(numpy.nansum(spectra[pair[0],:,:], axis=0)*numpy.nansum(spectra[pair[1],:,:], axis=0)))
2132 2132 #print('coh',numpy.absolute(coh))
2133 2133 for ih in range(len(hei_th)):
2134 2134 hvalid = (heights>hei_th[ih]).nonzero()
2135 2135 hvalid = hvalid[0]
2136 2136 if len(hvalid)>0:
2137 2137 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
2138 2138 valid = valid[0]
2139 2139 #print('hvalid:',hvalid)
2140 2140 #print('valid', valid)
2141 2141 if len(valid)>0:
2142 2142 my_coh_aver[pair[0],hvalid[valid]] =1
2143 2143 my_coh_aver[pair[1],hvalid[valid]] =1
2144 2144
2145 2145 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
2146 2146 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
2147 2147 incoh_echoes = incoh_echoes[0]
2148 2148 if len(incoh_echoes) > 0:
2149 2149 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2150 2150 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2151 2151 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2152 2152 my_incoh_aver[pair[0],incoh_echoes] = 1
2153 2153 my_incoh_aver[pair[1],incoh_echoes] = 1
2154 2154
2155 2155
2156 2156 for ic in range(2):
2157 2157 pair = crosspairs[ic]
2158 2158
2159 2159 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
2160 2160 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
2161 2161 valid1 = numpy.array(valid1[0])
2162 2162 valid2 = numpy.array(valid2[0])
2163 2163 valid = valid1
2164 2164 #print valid1 , valid2
2165 2165 for iv in range(len(valid2)):
2166 2166 #for ivv in range(len(valid1)) :
2167 2167 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2168 2168 if len(indv[0]) == 0 :
2169 2169 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
2170 2170 #print valid
2171 2171 #valid = numpy.concatenate((valid1,valid2), axis=None)
2172 2172 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
2173 2173 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
2174 2174 valid1 = numpy.array(valid1[0])
2175 2175 valid2 = numpy.array(valid2[0])
2176 2176 incoh_echoes = valid1
2177 2177 #print valid1, valid2
2178 2178 #incoh_echoes= numpy.concatenate((valid1,valid2), axis=None)
2179 2179 for iv in range(len(valid2)):
2180 2180 #for ivv in range(len(valid1)) :
2181 2181 indv = numpy.array((valid1 == valid2[iv]).nonzero())
2182 2182 if len(indv[0]) == 0 :
2183 2183 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
2184 2184 #print incoh_echoes
2185 2185 if len(valid)>0:
2186 2186 #print pair
2187 2187 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
2188 2188 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
2189 2189 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
2190 2190 coh_aver[pair[0],valid]=1
2191 2191 coh_aver[pair[1],valid]=1
2192 2192 if len(incoh_echoes)>0:
2193 2193 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
2194 2194 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
2195 2195 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
2196 2196 incoh_aver[pair[0],incoh_echoes]=1
2197 2197 incoh_aver[pair[1],incoh_echoes]=1
2198 2198 #plt.imshow(spectra[0,:,:],vmin=20000000)
2199 2199 #plt.show()
2200 2200 #my_incoh_aver = my_incoh_aver+1
2201 2201
2202 2202 #spec = my_incoh_spectra.copy()
2203 2203 #cspec = my_incoh_cspectra.copy()
2204 2204 #print('######################', spec)
2205 2205 #print(self.numpy)
2206 2206 #return spec, cspec,coh_aver
2207 2207 return my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver
2208 2208
2209 2209 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
2210 2210
2211 2211 import matplotlib.pyplot as plt
2212 2212 nProf = dataOut.nProfiles
2213 2213 heights = dataOut.heightList
2214 2214 nHei = len(heights)
2215 2215 channels = dataOut.channelList
2216 2216 nChan = len(channels)
2217 2217 crosspairs = dataOut.groupList
2218 2218 nPairs = len(crosspairs)
2219 2219
2220 2220 #data = dataOut.data_pre[0]
2221 2221 absc = dataOut.abscissaList[:-1]
2222 2222 #noise = dataOut.noise
2223 2223 #nChannel = data.shape[0]
2224 2224 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
2225 2225
2226 2226
2227 2227 #plt.plot(absc)
2228 2228 #plt.show()
2229 2229 clean_coh_spectra = spectra.copy()
2230 2230 clean_coh_cspectra = cspectra.copy()
2231 2231 clean_coh_aver = coh_aver.copy()
2232 2232
2233 2233 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
2234 2234 coh_th = 0.75
2235 2235
2236 2236 rtime0 = [6,18] # periodo sin ESF
2237 2237 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
2238 2238
2239 2239 time = index*5./60
2240 2240 if clean_coh_echoes == 1 :
2241 2241 for ind in range(nChan):
2242 2242 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
2243 2243 #print data_param[:,3]
2244 2244 spwd = data_param[:,3]
2245 2245 #print spwd.shape
2246 2246 # SPECB_JULIA,header=anal_header,jspectra=spectra,vel=velocities,hei=heights, num_aver=1, mode_fit=0,smoothing=smoothing,jvelr=velr,jspwd=spwd,jsnr=snr,jnoise=noise,jstdvnoise=stdvnoise
2247 2247 #spwd1=[ 1.65607, 1.43416, 0.500373, 0.208361, 0.000000, 26.7767, 22.5936, 26.7530, 20.6962, 29.1098, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 28.0300, 27.0511, 27.8810, 26.3126, 27.8445, 24.6181, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000]
2248 2248 #spwd=numpy.array([spwd1,spwd1,spwd1,spwd1])
2249 2249 #print spwd.shape, heights.shape,coh_aver.shape
2250 2250 # para obtener spwd
2251 2251 for ic in range(nPairs):
2252 2252 pair = crosspairs[ic]
2253 2253 coh = numpy.squeeze(numpy.sum(cspectra[ic,:,:], axis=1)/numpy.sqrt(numpy.sum(spectra[pair[0],:,:], axis=1)*numpy.sum(spectra[pair[1],:,:], axis=1)))
2254 2254 for ih in range(nHei) :
2255 2255 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
2256 2256 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
2257 2257 # Checking coherence
2258 2258 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
2259 2259 # Checking spectral widths
2260 2260 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
2261 2261 # satelite
2262 2262 clean_coh_spectra[pair,ih,:] = 0.0
2263 2263 clean_coh_cspectra[ic,ih,:] = 0.0
2264 2264 clean_coh_aver[pair,ih] = 0
2265 2265 else :
2266 2266 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
2267 2267 # Especial event like sun.
2268 2268 clean_coh_spectra[pair,ih,:] = 0.0
2269 2269 clean_coh_cspectra[ic,ih,:] = 0.0
2270 2270 clean_coh_aver[pair,ih] = 0
2271 2271
2272 2272 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
2273 2273
2274 2274 isConfig = False
2275 2275 __dataReady = False
2276 2276 bloques = None
2277 2277 bloque0 = None
2278 2278
2279 2279 def __init__(self):
2280 2280 Operation.__init__(self)
2281 2281 self.i=0
2282 2282 self.isConfig = False
2283 2283
2284 2284
2285 2285 def setup(self,nChan,nProf,nHei,nBlocks):
2286 2286 self.__dataReady = False
2287 2287 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
2288 2288 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
2289 2289
2290 2290 #def CleanRayleigh(self,dataOut,spectra,cspectra,out_spectra,out_cspectra,sat_spectra,sat_cspectra,crosspairs,heights, channels, nProf,nHei,nChan,nPairs,nIncohInt,nBlocks):
2291 2291 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
2292 2292 #import matplotlib.pyplot as plt
2293 2293 #for k in range(149):
2294 2294
2295 2295 # self.bloque0[:,:,:,k] = spectra[:,:,0:nHei]
2296 2296 # self.bloques[:,:,:,k] = cspectra[:,:,0:nHei]
2297 2297 #if self.i==nBlocks:
2298 2298 # self.i==0
2299 2299 rfunc = cspectra.copy() #self.bloques
2300 2300 n_funct = len(rfunc[0,:,0,0])
2301 2301 val_spc = spectra*0.0 #self.bloque0*0.0
2302 2302 val_cspc = cspectra*0.0 #self.bloques*0.0
2303 2303 in_sat_spectra = spectra.copy() #self.bloque0
2304 2304 in_sat_cspectra = cspectra.copy() #self.bloques
2305 2305
2306 2306 #print( rfunc.shape)
2307 2307 min_hei = 200
2308 2308 nProf = dataOut.nProfiles
2309 2309 heights = dataOut.heightList
2310 2310 nHei = len(heights)
2311 2311 channels = dataOut.channelList
2312 2312 nChan = len(channels)
2313 2313 crosspairs = dataOut.groupList
2314 2314 nPairs = len(crosspairs)
2315 2315 hval=(heights >= min_hei).nonzero()
2316 2316 ih=hval[0]
2317 2317 #print numpy.absolute(rfunc[:,0,0,14])
2318 2318 for ih in range(hval[0][0],nHei):
2319 2319 for ifreq in range(nProf):
2320 2320 for ii in range(n_funct):
2321 2321
2322 2322 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
2323 2323 #print numpy.amin(func2clean)
2324 2324 val = (numpy.isfinite(func2clean)==True).nonzero()
2325 2325 if len(val)>0:
2326 2326 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
2327 2327 if min_val <= -40 : min_val = -40
2328 2328 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
2329 2329 if max_val >= 200 : max_val = 200
2330 2330 #print min_val, max_val
2331 2331 step = 1
2332 2332 #Getting bins and the histogram
2333 2333 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
2334 2334 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
2335 2335 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
2336 2336 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
2337 2337 parg = [numpy.amax(y_dist),mean,sigma]
2338 2338 try :
2339 2339 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
2340 2340 mode = gauss_fit[1]
2341 2341 stdv = gauss_fit[2]
2342 2342 except:
2343 2343 mode = mean
2344 2344 stdv = sigma
2345 2345 # if ih == 14 and ii == 0 and ifreq ==0 :
2346 2346 # print x_dist.shape, y_dist.shape
2347 2347 # print x_dist, y_dist
2348 2348 # print min_val, max_val, binstep
2349 2349 # print func2clean
2350 2350 # print mean,sigma
2351 2351 # mean1,std = norm.fit(y_dist)
2352 2352 # print mean1, std, gauss_fit
2353 2353 # print fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
2354 2354 # 7.84616 53.9307 3.61863
2355 2355 #stdv = 3.61863 # 2.99089
2356 2356 #mode = 53.9307 #7.79008
2357 2357
2358 2358 #Removing echoes greater than mode + 3*stdv
2359 2359 factor_stdv = 2.5
2360 2360 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
2361 2361
2362 2362 if len(noval[0]) > 0:
2363 2363 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
2364 2364 cross_pairs = crosspairs[ii]
2365 2365 #Getting coherent echoes which are removed.
2366 2366 if len(novall[0]) > 0:
2367 2367 #val_spc[(0,1),novall[a],ih] = 1
2368 2368 #val_spc[,(2,3),novall[a],ih] = 1
2369 2369 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
2370 2370 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
2371 2371 val_cspc[novall[0],ii,ifreq,ih] = 1
2372 2372 #print("OUT NOVALL 1")
2373 2373 #Removing coherent from ISR data
2374 2374 # if ih == 17 and ii == 0 and ifreq ==0 :
2375 2375 # print spectra[:,cross_pairs[0],ifreq,ih]
2376 2376 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
2377 2377 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
2378 2378 cspectra[noval,ii,ifreq,ih] = numpy.nan
2379 2379 # if ih == 17 and ii == 0 and ifreq ==0 :
2380 2380 # print spectra[:,cross_pairs[0],ifreq,ih]
2381 2381 # print noval, len(noval[0])
2382 2382 # print novall, len(novall[0])
2383 2383 # print factor_stdv*stdv
2384 2384 # print func2clean-mode
2385 2385 # print val_spc[:,cross_pairs[0],ifreq,ih]
2386 2386 # print spectra[:,cross_pairs[0],ifreq,ih]
2387 2387 #no sale es para savedrifts >2
2388 2388 ''' channels = channels
2389 2389 cross_pairs = cross_pairs
2390 2390 #print("OUT NOVALL 2")
2391 2391
2392 2392 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
2393 2393 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
2394 2394 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
2395 2395 #print('vcros =', vcross)
2396 2396
2397 2397 #Getting coherent echoes which are removed.
2398 2398 if len(novall) > 0:
2399 2399 #val_spc[novall,ii,ifreq,ih] = 1
2400 2400 val_spc[ii,ifreq,ih,novall] = 1
2401 2401 if len(vcross) > 0:
2402 2402 val_cspc[vcross,ifreq,ih,novall] = 1
2403 2403
2404 2404 #Removing coherent from ISR data.
2405 2405 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
2406 2406 if len(vcross) > 0:
2407 2407 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
2408 2408 '''
2409 2409 #Getting average of the spectra and cross-spectra from incoherent echoes.
2410 2410 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
2411 2411 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
2412 2412 for ih in range(nHei):
2413 2413 for ifreq in range(nProf):
2414 2414 for ich in range(nChan):
2415 2415 tmp = spectra[:,ich,ifreq,ih]
2416 2416 valid = (numpy.isfinite(tmp[:])==True).nonzero()
2417 2417 # if ich == 0 and ifreq == 0 and ih == 17 :
2418 2418 # print tmp
2419 2419 # print valid
2420 2420 # print len(valid[0])
2421 2421 #print('TMP',tmp)
2422 2422 if len(valid[0]) >0 :
2423 2423 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2424 2424 #for icr in range(nPairs):
2425 2425 for icr in range(nPairs):
2426 2426 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
2427 2427 valid = (numpy.isfinite(tmp)==True).nonzero()
2428 2428 if len(valid[0]) > 0:
2429 2429 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2430 2430 # print('##########################################################')
2431 2431 #Removing fake coherent echoes (at least 4 points around the point)
2432 2432
2433 2433 val_spectra = numpy.sum(val_spc,0)
2434 2434 val_cspectra = numpy.sum(val_cspc,0)
2435 2435
2436 2436 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
2437 2437 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
2438 2438
2439 2439 for i in range(nChan):
2440 2440 for j in range(nProf):
2441 2441 for k in range(nHei):
2442 2442 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
2443 2443 val_spc[:,i,j,k] = 0.0
2444 2444 for i in range(nPairs):
2445 2445 for j in range(nProf):
2446 2446 for k in range(nHei):
2447 2447 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
2448 2448 val_cspc[:,i,j,k] = 0.0
2449 2449 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHei*nChan))
2450 2450 # if numpy.isfinite(val_spectra)==str(True):
2451 2451 # noval = (val_spectra<1).nonzero()
2452 2452 # if len(noval) > 0:
2453 2453 # val_spc[:,noval] = 0.0
2454 2454 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHei))
2455 2455
2456 2456 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHei*nProf))
2457 2457 #if numpy.isfinite(val_cspectra)==str(True):
2458 2458 # noval = (val_cspectra<1).nonzero()
2459 2459 # if len(noval) > 0:
2460 2460 # val_cspc[:,noval] = 0.0
2461 2461 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHei))
2462 2462
2463 2463 tmp_sat_spectra = spectra.copy()
2464 2464 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
2465 2465 tmp_sat_cspectra = cspectra.copy()
2466 2466 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
2467 2467
2468 2468 # fig = plt.figure(figsize=(6,5))
2469 2469 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2470 2470 # ax = fig.add_axes([left, bottom, width, height])
2471 2471 # cp = ax.contour(10*numpy.log10(numpy.absolute(spectra[0,0,:,:])))
2472 2472 # ax.clabel(cp, inline=True,fontsize=10)
2473 2473 # plt.show()
2474 2474
2475 2475 val = (val_spc > 0).nonzero()
2476 2476 if len(val[0]) > 0:
2477 2477 tmp_sat_spectra[val] = in_sat_spectra[val]
2478 2478
2479 2479 val = (val_cspc > 0).nonzero()
2480 2480 if len(val[0]) > 0:
2481 2481 tmp_sat_cspectra[val] = in_sat_cspectra[val]
2482 2482
2483 2483 #Getting average of the spectra and cross-spectra from incoherent echoes.
2484 2484 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
2485 2485 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
2486 2486 for ih in range(nHei):
2487 2487 for ifreq in range(nProf):
2488 2488 for ich in range(nChan):
2489 2489 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
2490 2490 valid = (numpy.isfinite(tmp)).nonzero()
2491 2491 if len(valid[0]) > 0:
2492 2492 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2493 2493
2494 2494 for icr in range(nPairs):
2495 2495 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
2496 2496 valid = (numpy.isfinite(tmp)).nonzero()
2497 2497 if len(valid[0]) > 0:
2498 2498 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
2499 2499 #self.__dataReady= True
2500 2500 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
2501 2501 #if not self.__dataReady:
2502 2502 #return None, None
2503 2503 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
2504 2504 def REM_ISOLATED_POINTS(self,array,rth):
2505 2505 # import matplotlib.pyplot as plt
2506 2506 if rth == None : rth = 4
2507 2507
2508 2508 num_prof = len(array[0,:,0])
2509 2509 num_hei = len(array[0,0,:])
2510 2510 n2d = len(array[:,0,0])
2511 2511
2512 2512 for ii in range(n2d) :
2513 2513 #print ii,n2d
2514 2514 tmp = array[ii,:,:]
2515 2515 #print tmp.shape, array[ii,101,:],array[ii,102,:]
2516 2516
2517 2517 # fig = plt.figure(figsize=(6,5))
2518 2518 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2519 2519 # ax = fig.add_axes([left, bottom, width, height])
2520 2520 # x = range(num_prof)
2521 2521 # y = range(num_hei)
2522 2522 # cp = ax.contour(y,x,tmp)
2523 2523 # ax.clabel(cp, inline=True,fontsize=10)
2524 2524 # plt.show()
2525 2525
2526 2526 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
2527 2527 tmp = numpy.reshape(tmp,num_prof*num_hei)
2528 2528 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
2529 2529 indxs2 = (tmp > 0).nonzero()
2530 2530
2531 2531 indxs1 = (indxs1[0])
2532 2532 indxs2 = indxs2[0]
2533 2533 #indxs1 = numpy.array(indxs1[0])
2534 2534 #indxs2 = numpy.array(indxs2[0])
2535 2535 indxs = None
2536 2536 #print indxs1 , indxs2
2537 2537 for iv in range(len(indxs2)):
2538 2538 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
2539 2539 #print len(indxs2), indv
2540 2540 if len(indv[0]) > 0 :
2541 2541 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
2542 2542 # print indxs
2543 2543 indxs = indxs[1:]
2544 2544 #print indxs, len(indxs)
2545 2545 if len(indxs) < 4 :
2546 2546 array[ii,:,:] = 0.
2547 2547 return
2548 2548
2549 2549 xpos = numpy.mod(indxs ,num_hei)
2550 2550 ypos = (indxs / num_hei)
2551 2551 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
2552 2552 #print sx
2553 2553 xpos = xpos[sx]
2554 2554 ypos = ypos[sx]
2555 2555
2556 2556 # *********************************** Cleaning isolated points **********************************
2557 2557 ic = 0
2558 2558 while True :
2559 2559 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
2560 2560 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
2561 2561 #plt.plot(r)
2562 2562 #plt.show()
2563 2563 no_coh1 = (numpy.isfinite(r)==True).nonzero()
2564 2564 no_coh2 = (r <= rth).nonzero()
2565 2565 #print r, no_coh1, no_coh2
2566 2566 no_coh1 = numpy.array(no_coh1[0])
2567 2567 no_coh2 = numpy.array(no_coh2[0])
2568 2568 no_coh = None
2569 2569 #print valid1 , valid2
2570 2570 for iv in range(len(no_coh2)):
2571 2571 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
2572 2572 if len(indv[0]) > 0 :
2573 2573 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
2574 2574 no_coh = no_coh[1:]
2575 2575 #print len(no_coh), no_coh
2576 2576 if len(no_coh) < 4 :
2577 2577 #print xpos[ic], ypos[ic], ic
2578 2578 # plt.plot(r)
2579 2579 # plt.show()
2580 2580 xpos[ic] = numpy.nan
2581 2581 ypos[ic] = numpy.nan
2582 2582
2583 2583 ic = ic + 1
2584 2584 if (ic == len(indxs)) :
2585 2585 break
2586 2586 #print( xpos, ypos)
2587 2587
2588 2588 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
2589 2589 #print indxs[0]
2590 2590 if len(indxs[0]) < 4 :
2591 2591 array[ii,:,:] = 0.
2592 2592 return
2593 2593
2594 2594 xpos = xpos[indxs[0]]
2595 2595 ypos = ypos[indxs[0]]
2596 2596 for i in range(0,len(ypos)):
2597 2597 ypos[i]=int(ypos[i])
2598 2598 junk = tmp
2599 2599 tmp = junk*0.0
2600 2600
2601 2601 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
2602 2602 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
2603 2603
2604 2604 #print array.shape
2605 2605 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
2606 2606 #print tmp.shape
2607 2607
2608 2608 # fig = plt.figure(figsize=(6,5))
2609 2609 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
2610 2610 # ax = fig.add_axes([left, bottom, width, height])
2611 2611 # x = range(num_prof)
2612 2612 # y = range(num_hei)
2613 2613 # cp = ax.contour(y,x,array[ii,:,:])
2614 2614 # ax.clabel(cp, inline=True,fontsize=10)
2615 2615 # plt.show()
2616 2616 return array
2617 2617 def moments(self,doppler,yarray,npoints):
2618 2618 ytemp = yarray
2619 2619 #val = WHERE(ytemp GT 0,cval)
2620 2620 #if cval == 0 : val = range(npoints-1)
2621 2621 val = (ytemp > 0).nonzero()
2622 2622 val = val[0]
2623 2623 #print('hvalid:',hvalid)
2624 2624 #print('valid', valid)
2625 2625 if len(val) == 0 : val = range(npoints-1)
2626 2626
2627 2627 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
2628 2628 ytemp[len(ytemp):] = [ynew]
2629 2629
2630 2630 index = 0
2631 2631 index = numpy.argmax(ytemp)
2632 2632 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
2633 2633 ytemp = ytemp[0:npoints-1]
2634 2634
2635 2635 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
2636 2636 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
2637 2637 return [fmom,numpy.sqrt(smom)]
2638 2638 # **********************************************************************************************
2639 2639 index = 0
2640 2640 fint = 0
2641 2641 buffer = 0
2642 2642 buffer2 = 0
2643 2643 buffer3 = 0
2644 2644 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
2645 2645 nChannels = dataOut.nChannels
2646 2646 nHeights= dataOut.heightList.size
2647 2647 nProf = dataOut.nProfiles
2648 2648 tini=time.localtime(dataOut.utctime)
2649 2649 if (tini.tm_min % 5) == 0 and (tini.tm_sec < 5 and self.fint==0):
2650 2650 # print tini.tm_min
2651 2651 self.index = 0
2652 2652 jspc = self.buffer
2653 2653 jcspc = self.buffer2
2654 2654 jnoise = self.buffer3
2655 2655 self.buffer = dataOut.data_spc
2656 2656 self.buffer2 = dataOut.data_cspc
2657 2657 self.buffer3 = dataOut.noise
2658 2658 self.fint = 1
2659 2659 if numpy.any(jspc) :
2660 2660 jspc= numpy.reshape(jspc,(int(len(jspc)/4),nChannels,nProf,nHeights))
2661 2661 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/2),2,nProf,nHeights))
2662 2662 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/4),nChannels))
2663 2663 else:
2664 2664 dataOut.flagNoData = True
2665 2665 return dataOut
2666 2666 else :
2667 2667 if (tini.tm_min % 5) == 0 : self.fint = 1
2668 2668 else : self.fint = 0
2669 2669 self.index += 1
2670 2670 if numpy.any(self.buffer):
2671 2671 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
2672 2672 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
2673 2673 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
2674 2674 else:
2675 2675 self.buffer = dataOut.data_spc
2676 2676 self.buffer2 = dataOut.data_cspc
2677 2677 self.buffer3 = dataOut.noise
2678 2678 dataOut.flagNoData = True
2679 2679 return dataOut
2680 2680 if path != None:
2681 2681 sys.path.append(path)
2682 2682 self.library = importlib.import_module(file)
2683 2683
2684 2684 #To be inserted as a parameter
2685 2685 groupArray = numpy.array(groupList)
2686 2686 #groupArray = numpy.array([[0,1],[2,3]])
2687 2687 dataOut.groupList = groupArray
2688 2688
2689 2689 nGroups = groupArray.shape[0]
2690 2690 nChannels = dataOut.nChannels
2691 2691 nHeights = dataOut.heightList.size
2692 2692
2693 2693 #Parameters Array
2694 2694 dataOut.data_param = None
2695 2695 dataOut.data_paramC = None
2696 2696
2697 2697 #Set constants
2698 2698 constants = self.library.setConstants(dataOut)
2699 2699 dataOut.constants = constants
2700 2700 M = dataOut.normFactor
2701 2701 N = dataOut.nFFTPoints
2702 2702 ippSeconds = dataOut.ippSeconds
2703 2703 K = dataOut.nIncohInt
2704 2704 pairsArray = numpy.array(dataOut.pairsList)
2705 2705
2706 2706 snrth= 20
2707 2707 spectra = dataOut.data_spc
2708 2708 cspectra = dataOut.data_cspc
2709 2709 nProf = dataOut.nProfiles
2710 2710 heights = dataOut.heightList
2711 2711 nHei = len(heights)
2712 2712 channels = dataOut.channelList
2713 2713 nChan = len(channels)
2714 2714 nIncohInt = dataOut.nIncohInt
2715 2715 crosspairs = dataOut.groupList
2716 2716 noise = dataOut.noise
2717 2717 jnoise = jnoise/N
2718 2718 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
2719 2719 power = numpy.sum(spectra, axis=1)
2720 2720 nPairs = len(crosspairs)
2721 2721 absc = dataOut.abscissaList[:-1]
2722 2722
2723 2723 if not self.isConfig:
2724 2724 self.isConfig = True
2725 2725
2726 2726 index = tini.tm_hour*12+tini.tm_min/5
2727 2727 jspc = jspc/N/N
2728 2728 jcspc = jcspc/N/N
2729 2729 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
2730 2730 jspectra = tmp_spectra*len(jspc[:,0,0,0])
2731 2731 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
2732 2732 my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver = self.__DiffCoherent(jspectra, jcspectra, dataOut, noise, snrth, None, None)
2733 2733 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
2734 2734 dataOut.data_spc = incoh_spectra
2735 2735 dataOut.data_cspc = incoh_cspectra
2736 2736
2737 2737 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
2738 2738 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
2739 2739 #List of possible combinations
2740 2740 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
2741 2741 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
2742 2742
2743 2743 if getSNR:
2744 2744 listChannels = groupArray.reshape((groupArray.size))
2745 2745 listChannels.sort()
2746 2746 dataOut.data_SNR = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels])
2747 2747 if dataOut.data_paramC is None:
2748 2748 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
2749 2749 for i in range(nGroups):
2750 2750 coord = groupArray[i,:]
2751 2751 #Input data array
2752 2752 data = dataOut.data_spc[coord,:,:]/(M*N)
2753 2753 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
2754 2754
2755 2755 #Cross Spectra data array for Covariance Matrixes
2756 2756 ind = 0
2757 2757 for pairs in listComb:
2758 2758 pairsSel = numpy.array([coord[x],coord[y]])
2759 2759 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
2760 2760 ind += 1
2761 2761 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
2762 2762 dataCross = dataCross**2
2763 2763 nhei = nHeights
2764 2764 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
2765 2765 if i == 0 : my_noises = numpy.zeros(4,dtype=float) #FLTARR(4)
2766 2766 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
2767 2767 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
2768 2768 n0 = n0i
2769 2769 n1= n1i
2770 2770 my_noises[2*i+0] = n0
2771 2771 my_noises[2*i+1] = n1
2772 2772 snrth = -16.0
2773 2773 snrth = 10**(snrth/10.0)
2774 2774
2775 2775 for h in range(nHeights):
2776 2776 d = data[:,h]
2777 2777 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
2778 2778 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
2779 2779 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
2780 2780 signal0 = signalpn0-n0
2781 2781 signal1 = signalpn1-n1
2782 2782 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2783 2783 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2784 2784 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
2785 2785 #Covariance Matrix
2786 2786 D = numpy.diag(d**2)
2787 2787 ind = 0
2788 2788 for pairs in listComb:
2789 2789 #Coordinates in Covariance Matrix
2790 2790 x = pairs[0]
2791 2791 y = pairs[1]
2792 2792 #Channel Index
2793 2793 S12 = dataCross[ind,:,h]
2794 2794 D12 = numpy.diag(S12)
2795 2795 #Completing Covariance Matrix with Cross Spectras
2796 2796 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
2797 2797 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
2798 2798 ind += 1
2799 2799 diagD = numpy.zeros(256)
2800 2800 if h == 17 :
2801 2801 for ii in range(256): diagD[ii] = D[ii,ii]
2802 2802 #Dinv=numpy.linalg.inv(D)
2803 2803 #L=numpy.linalg.cholesky(Dinv)
2804 2804 try:
2805 2805 Dinv=numpy.linalg.inv(D)
2806 2806 L=numpy.linalg.cholesky(Dinv)
2807 2807 except:
2808 2808 Dinv = D*numpy.nan
2809 2809 L= D*numpy.nan
2810 2810 LT=L.T
2811 2811
2812 2812 dp = numpy.dot(LT,d)
2813 2813
2814 2814 #Initial values
2815 2815 data_spc = dataOut.data_spc[coord,:,h]
2816 2816
2817 2817 if (h>0)and(error1[3]<5):
2818 2818 p0 = dataOut.data_param[i,:,h-1]
2819 2819 else:
2820 2820 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))# sin el i(data_spc, constants, i)
2821 2821 try:
2822 2822 #Least Squares
2823 2823 #print (dp,LT,constants)
2824 2824 #value =self.__residFunction(p0,dp,LT,constants)
2825 2825 #print ("valueREADY",value.shape, type(value))
2826 2826 #optimize.leastsq(value)
2827 2827 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
2828 2828 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
2829 2829 #Chi square error
2830 2830 #print(minp,covp.infodict,mesg,ier)
2831 2831 #print("REALIZA OPTIMIZ")
2832 2832 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
2833 2833 #Error with Jacobian
2834 2834 error1 = self.library.errorFunction(minp,constants,LT)
2835 2835 # print self.__residFunction(p0,dp,LT, constants)
2836 2836 # print infodict['fvec']
2837 2837 # print self.__residFunction(minp,dp,LT,constants)
2838 2838
2839 2839 except:
2840 2840 minp = p0*numpy.nan
2841 2841 error0 = numpy.nan
2842 2842 error1 = p0*numpy.nan
2843 2843 #print ("EXCEPT 0000000000")
2844 2844 # s_sq = (self.__residFunction(minp,dp,LT,constants)).sum()/(len(dp)-len(p0))
2845 2845 # covp = covp*s_sq
2846 2846 # #print("TRY___________________________________________1")
2847 2847 # error = []
2848 2848 # for ip in range(len(minp)):
2849 2849 # try:
2850 2850 # error.append(numpy.absolute(covp[ip][ip])**0.5)
2851 2851 # except:
2852 2852 # error.append( 0.00 )
2853 2853 else :
2854 2854 data_spc = dataOut.data_spc[coord,:,h]
2855 2855 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
2856 2856 minp = p0*numpy.nan
2857 2857 error0 = numpy.nan
2858 2858 error1 = p0*numpy.nan
2859 2859 #Save
2860 2860 if dataOut.data_param is None:
2861 2861 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
2862 2862 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
2863 2863
2864 2864 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
2865 2865 dataOut.data_param[i,:,h] = minp
2866 2866
2867 2867 for ht in range(nHeights-1) :
2868 2868 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
2869 2869 dataOut.data_paramC[4*i,ht,1] = smooth
2870 2870 signalpn0 = (coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
2871 2871 signalpn1 = (coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
2872 2872
2873 2873 #val0 = WHERE(signalpn0 > 0,cval0)
2874 2874 val0 = (signalpn0 > 0).nonzero()
2875 2875 val0 = val0[0]
2876 2876 #print('hvalid:',hvalid)
2877 2877 #print('valid', valid)
2878 2878 if len(val0) == 0 : val0_npoints = nProf
2879 2879 else : val0_npoints = len(val0)
2880 2880
2881 2881 #val1 = WHERE(signalpn1 > 0,cval1)
2882 2882 val1 = (signalpn1 > 0).nonzero()
2883 2883 val1 = val1[0]
2884 2884 if len(val1) == 0 : val1_npoints = nProf
2885 2885 else : val1_npoints = len(val1)
2886 2886
2887 2887 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
2888 2888 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
2889 2889
2890 2890 signal0 = (signalpn0-n0) # > 0
2891 2891 vali = (signal0 < 0).nonzero()
2892 2892 vali = vali[0]
2893 2893 if len(vali) > 0 : signal0[vali] = 0
2894 2894 signal1 = (signalpn1-n1) #> 0
2895 2895 vali = (signal1 < 0).nonzero()
2896 2896 vali = vali[0]
2897 2897 if len(vali) > 0 : signal1[vali] = 0
2898 2898 snr0 = numpy.sum(signal0/n0)/(nProf-1)
2899 2899 snr1 = numpy.sum(signal1/n1)/(nProf-1)
2900 2900 doppler = absc[1:]
2901 2901 if snr0 >= snrth and snr1 >= snrth and smooth :
2902 2902 signalpn0_n0 = signalpn0
2903 2903 signalpn0_n0[val0] = signalpn0[val0] - n0
2904 2904 mom0 = self.moments(doppler,signalpn0-n0,nProf)
2905 2905 # sigtmp= numpy.transpose(numpy.tile(signalpn0, [4,1]))
2906 2906 # momt= self.__calculateMoments( sigtmp, doppler , n0 )
2907 2907 signalpn1_n1 = signalpn1
2908 2908 signalpn1_n1[val1] = signalpn1[val1] - n1
2909 2909 mom1 = self.moments(doppler,signalpn1_n1,nProf)
2910 2910 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
2911 2911 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
2912 2912 # if graph == 1 :
2913 2913 # window, 13
2914 2914 # plot,doppler,signalpn0
2915 2915 # oplot,doppler,signalpn1,linest=1
2916 2916 # oplot,mom0(0)*doppler/doppler,signalpn0
2917 2917 # oplot,mom1(0)*doppler/doppler,signalpn1
2918 2918 # print,interval/12.,beam,45+ht*15,snr0,snr1,mom0(0),mom1(0),mom0(1),mom1(1)
2919 2919 #ENDIF
2920 2920 #ENDIF
2921 2921 #ENDFOR End height
2922 2922
2923 2923 dataOut.data_spc = jspectra
2924 2924 if getSNR:
2925 2925 listChannels = groupArray.reshape((groupArray.size))
2926 2926 listChannels.sort()
2927 2927
2928 2928 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels])
2929 2929 return dataOut
2930 2930
2931 2931 def __residFunction(self, p, dp, LT, constants):
2932 2932
2933 2933 fm = self.library.modelFunction(p, constants)
2934 2934 fmp=numpy.dot(LT,fm)
2935 2935 return dp-fmp
2936 2936
2937 2937 def __getSNR(self, z, noise):
2938 2938
2939 2939 avg = numpy.average(z, axis=1)
2940 2940 SNR = (avg.T-noise)/noise
2941 2941 SNR = SNR.T
2942 2942 return SNR
2943 2943
2944 2944 def __chisq(self, p, chindex, hindex):
2945 2945 #similar to Resid but calculates CHI**2
2946 2946 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
2947 2947 dp=numpy.dot(LT,d)
2948 2948 fmp=numpy.dot(LT,fm)
2949 2949 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
2950 2950 return chisq
2951 2951
2952 2952 class WindProfiler(Operation):
2953 2953
2954 2954 __isConfig = False
2955 2955
2956 2956 __initime = None
2957 2957 __lastdatatime = None
2958 2958 __integrationtime = None
2959 2959
2960 2960 __buffer = None
2961 2961
2962 2962 __dataReady = False
2963 2963
2964 2964 __firstdata = None
2965 2965
2966 2966 n = None
2967 2967
2968 2968 def __init__(self):
2969 2969 Operation.__init__(self)
2970 2970
2971 2971 def __calculateCosDir(self, elev, azim):
2972 2972 zen = (90 - elev)*numpy.pi/180
2973 2973 azim = azim*numpy.pi/180
2974 2974 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
2975 2975 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
2976 2976
2977 2977 signX = numpy.sign(numpy.cos(azim))
2978 2978 signY = numpy.sign(numpy.sin(azim))
2979 2979
2980 2980 cosDirX = numpy.copysign(cosDirX, signX)
2981 2981 cosDirY = numpy.copysign(cosDirY, signY)
2982 2982 return cosDirX, cosDirY
2983 2983
2984 2984 def __calculateAngles(self, theta_x, theta_y, azimuth):
2985 2985
2986 2986 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
2987 2987 zenith_arr = numpy.arccos(dir_cosw)
2988 2988 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
2989 2989
2990 2990 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
2991 2991 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
2992 2992
2993 2993 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
2994 2994
2995 2995 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
2996 2996
2997 2997 if horOnly:
2998 2998 A = numpy.c_[dir_cosu,dir_cosv]
2999 2999 else:
3000 3000 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
3001 3001 A = numpy.asmatrix(A)
3002 3002 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
3003 3003
3004 3004 return A1
3005 3005
3006 3006 def __correctValues(self, heiRang, phi, velRadial, SNR):
3007 3007 listPhi = phi.tolist()
3008 3008 maxid = listPhi.index(max(listPhi))
3009 3009 minid = listPhi.index(min(listPhi))
3010 3010
3011 3011 rango = list(range(len(phi)))
3012 3012 # rango = numpy.delete(rango,maxid)
3013 3013
3014 3014 heiRang1 = heiRang*math.cos(phi[maxid])
3015 3015 heiRangAux = heiRang*math.cos(phi[minid])
3016 3016 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3017 3017 heiRang1 = numpy.delete(heiRang1,indOut)
3018 3018
3019 3019 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3020 3020 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3021 3021
3022 3022 for i in rango:
3023 3023 x = heiRang*math.cos(phi[i])
3024 3024 y1 = velRadial[i,:]
3025 3025 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
3026 3026
3027 3027 x1 = heiRang1
3028 3028 y11 = f1(x1)
3029 3029
3030 3030 y2 = SNR[i,:]
3031 3031 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
3032 3032 y21 = f2(x1)
3033 3033
3034 3034 velRadial1[i,:] = y11
3035 3035 SNR1[i,:] = y21
3036 3036
3037 3037 return heiRang1, velRadial1, SNR1
3038 3038
3039 3039 def __calculateVelUVW(self, A, velRadial):
3040 3040
3041 3041 #Operacion Matricial
3042 3042 # velUVW = numpy.zeros((velRadial.shape[1],3))
3043 3043 # for ind in range(velRadial.shape[1]):
3044 3044 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
3045 3045 # velUVW = velUVW.transpose()
3046 3046 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
3047 3047 velUVW[:,:] = numpy.dot(A,velRadial)
3048 3048
3049 3049
3050 3050 return velUVW
3051 3051
3052 3052 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
3053 3053
3054 3054 def techniqueDBS(self, kwargs):
3055 3055 """
3056 3056 Function that implements Doppler Beam Swinging (DBS) technique.
3057 3057
3058 3058 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3059 3059 Direction correction (if necessary), Ranges and SNR
3060 3060
3061 3061 Output: Winds estimation (Zonal, Meridional and Vertical)
3062 3062
3063 3063 Parameters affected: Winds, height range, SNR
3064 3064 """
3065 3065 velRadial0 = kwargs['velRadial']
3066 3066 heiRang = kwargs['heightList']
3067 3067 SNR0 = kwargs['SNR']
3068 3068
3069 3069 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
3070 3070 theta_x = numpy.array(kwargs['dirCosx'])
3071 3071 theta_y = numpy.array(kwargs['dirCosy'])
3072 3072 else:
3073 3073 elev = numpy.array(kwargs['elevation'])
3074 3074 azim = numpy.array(kwargs['azimuth'])
3075 3075 theta_x, theta_y = self.__calculateCosDir(elev, azim)
3076 3076 azimuth = kwargs['correctAzimuth']
3077 3077 if 'horizontalOnly' in kwargs:
3078 3078 horizontalOnly = kwargs['horizontalOnly']
3079 3079 else: horizontalOnly = False
3080 3080 if 'correctFactor' in kwargs:
3081 3081 correctFactor = kwargs['correctFactor']
3082 3082 else: correctFactor = 1
3083 3083 if 'channelList' in kwargs:
3084 3084 channelList = kwargs['channelList']
3085 3085 if len(channelList) == 2:
3086 3086 horizontalOnly = True
3087 3087 arrayChannel = numpy.array(channelList)
3088 3088 param = param[arrayChannel,:,:]
3089 3089 theta_x = theta_x[arrayChannel]
3090 3090 theta_y = theta_y[arrayChannel]
3091 3091
3092 3092 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3093 3093 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
3094 3094 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
3095 3095
3096 3096 #Calculo de Componentes de la velocidad con DBS
3097 3097 winds = self.__calculateVelUVW(A,velRadial1)
3098 3098
3099 3099 return winds, heiRang1, SNR1
3100 3100
3101 3101 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
3102 3102
3103 3103 nPairs = len(pairs_ccf)
3104 3104 posx = numpy.asarray(posx)
3105 3105 posy = numpy.asarray(posy)
3106 3106
3107 3107 #Rotacion Inversa para alinear con el azimuth
3108 3108 if azimuth!= None:
3109 3109 azimuth = azimuth*math.pi/180
3110 3110 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
3111 3111 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
3112 3112 else:
3113 3113 posx1 = posx
3114 3114 posy1 = posy
3115 3115
3116 3116 #Calculo de Distancias
3117 3117 distx = numpy.zeros(nPairs)
3118 3118 disty = numpy.zeros(nPairs)
3119 3119 dist = numpy.zeros(nPairs)
3120 3120 ang = numpy.zeros(nPairs)
3121 3121
3122 3122 for i in range(nPairs):
3123 3123 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
3124 3124 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
3125 3125 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
3126 3126 ang[i] = numpy.arctan2(disty[i],distx[i])
3127 3127
3128 3128 return distx, disty, dist, ang
3129 3129 #Calculo de Matrices
3130 3130 # nPairs = len(pairs)
3131 3131 # ang1 = numpy.zeros((nPairs, 2, 1))
3132 3132 # dist1 = numpy.zeros((nPairs, 2, 1))
3133 3133 #
3134 3134 # for j in range(nPairs):
3135 3135 # dist1[j,0,0] = dist[pairs[j][0]]
3136 3136 # dist1[j,1,0] = dist[pairs[j][1]]
3137 3137 # ang1[j,0,0] = ang[pairs[j][0]]
3138 3138 # ang1[j,1,0] = ang[pairs[j][1]]
3139 3139 #
3140 3140 # return distx,disty, dist1,ang1
3141 3141
3142 3142
3143 3143 def __calculateVelVer(self, phase, lagTRange, _lambda):
3144 3144
3145 3145 Ts = lagTRange[1] - lagTRange[0]
3146 3146 velW = -_lambda*phase/(4*math.pi*Ts)
3147 3147
3148 3148 return velW
3149 3149
3150 3150 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
3151 3151 nPairs = tau1.shape[0]
3152 3152 nHeights = tau1.shape[1]
3153 3153 vel = numpy.zeros((nPairs,3,nHeights))
3154 3154 dist1 = numpy.reshape(dist, (dist.size,1))
3155 3155
3156 3156 angCos = numpy.cos(ang)
3157 3157 angSin = numpy.sin(ang)
3158 3158
3159 3159 vel0 = dist1*tau1/(2*tau2**2)
3160 3160 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
3161 3161 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
3162 3162
3163 3163 ind = numpy.where(numpy.isinf(vel))
3164 3164 vel[ind] = numpy.nan
3165 3165
3166 3166 return vel
3167 3167
3168 3168 # def __getPairsAutoCorr(self, pairsList, nChannels):
3169 3169 #
3170 3170 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
3171 3171 #
3172 3172 # for l in range(len(pairsList)):
3173 3173 # firstChannel = pairsList[l][0]
3174 3174 # secondChannel = pairsList[l][1]
3175 3175 #
3176 3176 # #Obteniendo pares de Autocorrelacion
3177 3177 # if firstChannel == secondChannel:
3178 3178 # pairsAutoCorr[firstChannel] = int(l)
3179 3179 #
3180 3180 # pairsAutoCorr = pairsAutoCorr.astype(int)
3181 3181 #
3182 3182 # pairsCrossCorr = range(len(pairsList))
3183 3183 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
3184 3184 #
3185 3185 # return pairsAutoCorr, pairsCrossCorr
3186 3186
3187 3187 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
3188 3188 def techniqueSA(self, kwargs):
3189 3189
3190 3190 """
3191 3191 Function that implements Spaced Antenna (SA) technique.
3192 3192
3193 3193 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
3194 3194 Direction correction (if necessary), Ranges and SNR
3195 3195
3196 3196 Output: Winds estimation (Zonal, Meridional and Vertical)
3197 3197
3198 3198 Parameters affected: Winds
3199 3199 """
3200 3200 position_x = kwargs['positionX']
3201 3201 position_y = kwargs['positionY']
3202 3202 azimuth = kwargs['azimuth']
3203 3203
3204 3204 if 'correctFactor' in kwargs:
3205 3205 correctFactor = kwargs['correctFactor']
3206 3206 else:
3207 3207 correctFactor = 1
3208 3208
3209 3209 groupList = kwargs['groupList']
3210 3210 pairs_ccf = groupList[1]
3211 3211 tau = kwargs['tau']
3212 3212 _lambda = kwargs['_lambda']
3213 3213
3214 3214 #Cross Correlation pairs obtained
3215 3215 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
3216 3216 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
3217 3217 # pairsSelArray = numpy.array(pairsSelected)
3218 3218 # pairs = []
3219 3219 #
3220 3220 # #Wind estimation pairs obtained
3221 3221 # for i in range(pairsSelArray.shape[0]/2):
3222 3222 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
3223 3223 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
3224 3224 # pairs.append((ind1,ind2))
3225 3225
3226 3226 indtau = tau.shape[0]/2
3227 3227 tau1 = tau[:indtau,:]
3228 3228 tau2 = tau[indtau:-1,:]
3229 3229 # tau1 = tau1[pairs,:]
3230 3230 # tau2 = tau2[pairs,:]
3231 3231 phase1 = tau[-1,:]
3232 3232
3233 3233 #---------------------------------------------------------------------
3234 3234 #Metodo Directo
3235 3235 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
3236 3236 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
3237 3237 winds = stats.nanmean(winds, axis=0)
3238 3238 #---------------------------------------------------------------------
3239 3239 #Metodo General
3240 3240 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
3241 3241 # #Calculo Coeficientes de Funcion de Correlacion
3242 3242 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
3243 3243 # #Calculo de Velocidades
3244 3244 # winds = self.calculateVelUV(F,G,A,B,H)
3245 3245
3246 3246 #---------------------------------------------------------------------
3247 3247 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
3248 3248 winds = correctFactor*winds
3249 3249 return winds
3250 3250
3251 3251 def __checkTime(self, currentTime, paramInterval, outputInterval):
3252 3252
3253 3253 dataTime = currentTime + paramInterval
3254 3254 deltaTime = dataTime - self.__initime
3255 3255
3256 3256 if deltaTime >= outputInterval or deltaTime < 0:
3257 3257 self.__dataReady = True
3258 3258 return
3259 3259
3260 3260 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
3261 3261 '''
3262 3262 Function that implements winds estimation technique with detected meteors.
3263 3263
3264 3264 Input: Detected meteors, Minimum meteor quantity to wind estimation
3265 3265
3266 3266 Output: Winds estimation (Zonal and Meridional)
3267 3267
3268 3268 Parameters affected: Winds
3269 3269 '''
3270 3270 #Settings
3271 3271 nInt = (heightMax - heightMin)/2
3272 3272 nInt = int(nInt)
3273 3273 winds = numpy.zeros((2,nInt))*numpy.nan
3274 3274
3275 3275 #Filter errors
3276 3276 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
3277 3277 finalMeteor = arrayMeteor[error,:]
3278 3278
3279 3279 #Meteor Histogram
3280 3280 finalHeights = finalMeteor[:,2]
3281 3281 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
3282 3282 nMeteorsPerI = hist[0]
3283 3283 heightPerI = hist[1]
3284 3284
3285 3285 #Sort of meteors
3286 3286 indSort = finalHeights.argsort()
3287 3287 finalMeteor2 = finalMeteor[indSort,:]
3288 3288
3289 3289 # Calculating winds
3290 3290 ind1 = 0
3291 3291 ind2 = 0
3292 3292
3293 3293 for i in range(nInt):
3294 3294 nMet = nMeteorsPerI[i]
3295 3295 ind1 = ind2
3296 3296 ind2 = ind1 + nMet
3297 3297
3298 3298 meteorAux = finalMeteor2[ind1:ind2,:]
3299 3299
3300 3300 if meteorAux.shape[0] >= meteorThresh:
3301 3301 vel = meteorAux[:, 6]
3302 3302 zen = meteorAux[:, 4]*numpy.pi/180
3303 3303 azim = meteorAux[:, 3]*numpy.pi/180
3304 3304
3305 3305 n = numpy.cos(zen)
3306 3306 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
3307 3307 # l = m*numpy.tan(azim)
3308 3308 l = numpy.sin(zen)*numpy.sin(azim)
3309 3309 m = numpy.sin(zen)*numpy.cos(azim)
3310 3310
3311 3311 A = numpy.vstack((l, m)).transpose()
3312 3312 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
3313 3313 windsAux = numpy.dot(A1, vel)
3314 3314
3315 3315 winds[0,i] = windsAux[0]
3316 3316 winds[1,i] = windsAux[1]
3317 3317
3318 3318 return winds, heightPerI[:-1]
3319 3319
3320 3320 def techniqueNSM_SA(self, **kwargs):
3321 3321 metArray = kwargs['metArray']
3322 3322 heightList = kwargs['heightList']
3323 3323 timeList = kwargs['timeList']
3324 3324
3325 3325 rx_location = kwargs['rx_location']
3326 3326 groupList = kwargs['groupList']
3327 3327 azimuth = kwargs['azimuth']
3328 3328 dfactor = kwargs['dfactor']
3329 3329 k = kwargs['k']
3330 3330
3331 3331 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
3332 3332 d = dist*dfactor
3333 3333 #Phase calculation
3334 3334 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
3335 3335
3336 3336 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
3337 3337
3338 3338 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3339 3339 azimuth1 = azimuth1*numpy.pi/180
3340 3340
3341 3341 for i in range(heightList.size):
3342 3342 h = heightList[i]
3343 3343 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
3344 3344 metHeight = metArray1[indH,:]
3345 3345 if metHeight.shape[0] >= 2:
3346 3346 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
3347 3347 iazim = metHeight[:,1].astype(int)
3348 3348 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
3349 3349 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
3350 3350 A = numpy.asmatrix(A)
3351 3351 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
3352 3352 velHor = numpy.dot(A1,velAux)
3353 3353
3354 3354 velEst[i,:] = numpy.squeeze(velHor)
3355 3355 return velEst
3356 3356
3357 3357 def __getPhaseSlope(self, metArray, heightList, timeList):
3358 3358 meteorList = []
3359 3359 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
3360 3360 #Putting back together the meteor matrix
3361 3361 utctime = metArray[:,0]
3362 3362 uniqueTime = numpy.unique(utctime)
3363 3363
3364 3364 phaseDerThresh = 0.5
3365 3365 ippSeconds = timeList[1] - timeList[0]
3366 3366 sec = numpy.where(timeList>1)[0][0]
3367 3367 nPairs = metArray.shape[1] - 6
3368 3368 nHeights = len(heightList)
3369 3369
3370 3370 for t in uniqueTime:
3371 3371 metArray1 = metArray[utctime==t,:]
3372 3372 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
3373 3373 tmet = metArray1[:,1].astype(int)
3374 3374 hmet = metArray1[:,2].astype(int)
3375 3375
3376 3376 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
3377 3377 metPhase[:,:] = numpy.nan
3378 3378 metPhase[:,hmet,tmet] = metArray1[:,6:].T
3379 3379
3380 3380 #Delete short trails
3381 3381 metBool = ~numpy.isnan(metPhase[0,:,:])
3382 3382 heightVect = numpy.sum(metBool, axis = 1)
3383 3383 metBool[heightVect<sec,:] = False
3384 3384 metPhase[:,heightVect<sec,:] = numpy.nan
3385 3385
3386 3386 #Derivative
3387 3387 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
3388 3388 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
3389 3389 metPhase[phDerAux] = numpy.nan
3390 3390
3391 3391 #--------------------------METEOR DETECTION -----------------------------------------
3392 3392 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
3393 3393
3394 3394 for p in numpy.arange(nPairs):
3395 3395 phase = metPhase[p,:,:]
3396 3396 phDer = metDer[p,:,:]
3397 3397
3398 3398 for h in indMet:
3399 3399 height = heightList[h]
3400 3400 phase1 = phase[h,:] #82
3401 3401 phDer1 = phDer[h,:]
3402 3402
3403 3403 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
3404 3404
3405 3405 indValid = numpy.where(~numpy.isnan(phase1))[0]
3406 3406 initMet = indValid[0]
3407 3407 endMet = 0
3408 3408
3409 3409 for i in range(len(indValid)-1):
3410 3410
3411 3411 #Time difference
3412 3412 inow = indValid[i]
3413 3413 inext = indValid[i+1]
3414 3414 idiff = inext - inow
3415 3415 #Phase difference
3416 3416 phDiff = numpy.abs(phase1[inext] - phase1[inow])
3417 3417
3418 3418 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
3419 3419 sizeTrail = inow - initMet + 1
3420 3420 if sizeTrail>3*sec: #Too short meteors
3421 3421 x = numpy.arange(initMet,inow+1)*ippSeconds
3422 3422 y = phase1[initMet:inow+1]
3423 3423 ynnan = ~numpy.isnan(y)
3424 3424 x = x[ynnan]
3425 3425 y = y[ynnan]
3426 3426 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
3427 3427 ylin = x*slope + intercept
3428 3428 rsq = r_value**2
3429 3429 if rsq > 0.5:
3430 3430 vel = slope#*height*1000/(k*d)
3431 3431 estAux = numpy.array([utctime,p,height, vel, rsq])
3432 3432 meteorList.append(estAux)
3433 3433 initMet = inext
3434 3434 metArray2 = numpy.array(meteorList)
3435 3435
3436 3436 return metArray2
3437 3437
3438 3438 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
3439 3439
3440 3440 azimuth1 = numpy.zeros(len(pairslist))
3441 3441 dist = numpy.zeros(len(pairslist))
3442 3442
3443 3443 for i in range(len(rx_location)):
3444 3444 ch0 = pairslist[i][0]
3445 3445 ch1 = pairslist[i][1]
3446 3446
3447 3447 diffX = rx_location[ch0][0] - rx_location[ch1][0]
3448 3448 diffY = rx_location[ch0][1] - rx_location[ch1][1]
3449 3449 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
3450 3450 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
3451 3451
3452 3452 azimuth1 -= azimuth0
3453 3453 return azimuth1, dist
3454 3454
3455 3455 def techniqueNSM_DBS(self, **kwargs):
3456 3456 metArray = kwargs['metArray']
3457 3457 heightList = kwargs['heightList']
3458 3458 timeList = kwargs['timeList']
3459 3459 azimuth = kwargs['azimuth']
3460 3460 theta_x = numpy.array(kwargs['theta_x'])
3461 3461 theta_y = numpy.array(kwargs['theta_y'])
3462 3462
3463 3463 utctime = metArray[:,0]
3464 3464 cmet = metArray[:,1].astype(int)
3465 3465 hmet = metArray[:,3].astype(int)
3466 3466 SNRmet = metArray[:,4]
3467 3467 vmet = metArray[:,5]
3468 3468 spcmet = metArray[:,6]
3469 3469
3470 3470 nChan = numpy.max(cmet) + 1
3471 3471 nHeights = len(heightList)
3472 3472
3473 3473 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
3474 3474 hmet = heightList[hmet]
3475 3475 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
3476 3476
3477 3477 velEst = numpy.zeros((heightList.size,2))*numpy.nan
3478 3478
3479 3479 for i in range(nHeights - 1):
3480 3480 hmin = heightList[i]
3481 3481 hmax = heightList[i + 1]
3482 3482
3483 3483 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
3484 3484 indthisH = numpy.where(thisH)
3485 3485
3486 3486 if numpy.size(indthisH) > 3:
3487 3487
3488 3488 vel_aux = vmet[thisH]
3489 3489 chan_aux = cmet[thisH]
3490 3490 cosu_aux = dir_cosu[chan_aux]
3491 3491 cosv_aux = dir_cosv[chan_aux]
3492 3492 cosw_aux = dir_cosw[chan_aux]
3493 3493
3494 3494 nch = numpy.size(numpy.unique(chan_aux))
3495 3495 if nch > 1:
3496 3496 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
3497 3497 velEst[i,:] = numpy.dot(A,vel_aux)
3498 3498
3499 3499 return velEst
3500 3500
3501 3501 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
3502 3502
3503 3503 param = dataOut.data_param
3504 3504 if dataOut.abscissaList != None:
3505 3505 absc = dataOut.abscissaList[:-1]
3506 3506 # noise = dataOut.noise
3507 3507 heightList = dataOut.heightList
3508 3508 SNR = dataOut.data_snr
3509 3509
3510 3510 if technique == 'DBS':
3511 3511
3512 3512 kwargs['velRadial'] = param[:,1,:] #Radial velocity
3513 3513 kwargs['heightList'] = heightList
3514 3514 kwargs['SNR'] = SNR
3515 3515
3516 3516 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
3517 3517 dataOut.utctimeInit = dataOut.utctime
3518 3518 dataOut.outputInterval = dataOut.paramInterval
3519 3519
3520 3520 elif technique == 'SA':
3521 3521
3522 3522 #Parameters
3523 3523 # position_x = kwargs['positionX']
3524 3524 # position_y = kwargs['positionY']
3525 3525 # azimuth = kwargs['azimuth']
3526 3526 #
3527 3527 # if kwargs.has_key('crosspairsList'):
3528 3528 # pairs = kwargs['crosspairsList']
3529 3529 # else:
3530 3530 # pairs = None
3531 3531 #
3532 3532 # if kwargs.has_key('correctFactor'):
3533 3533 # correctFactor = kwargs['correctFactor']
3534 3534 # else:
3535 3535 # correctFactor = 1
3536 3536
3537 3537 # tau = dataOut.data_param
3538 3538 # _lambda = dataOut.C/dataOut.frequency
3539 3539 # pairsList = dataOut.groupList
3540 3540 # nChannels = dataOut.nChannels
3541 3541
3542 3542 kwargs['groupList'] = dataOut.groupList
3543 3543 kwargs['tau'] = dataOut.data_param
3544 3544 kwargs['_lambda'] = dataOut.C/dataOut.frequency
3545 3545 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
3546 3546 dataOut.data_output = self.techniqueSA(kwargs)
3547 3547 dataOut.utctimeInit = dataOut.utctime
3548 3548 dataOut.outputInterval = dataOut.timeInterval
3549 3549
3550 3550 elif technique == 'Meteors':
3551 3551 dataOut.flagNoData = True
3552 3552 self.__dataReady = False
3553 3553
3554 3554 if 'nHours' in kwargs:
3555 3555 nHours = kwargs['nHours']
3556 3556 else:
3557 3557 nHours = 1
3558 3558
3559 3559 if 'meteorsPerBin' in kwargs:
3560 3560 meteorThresh = kwargs['meteorsPerBin']
3561 3561 else:
3562 3562 meteorThresh = 6
3563 3563
3564 3564 if 'hmin' in kwargs:
3565 3565 hmin = kwargs['hmin']
3566 3566 else: hmin = 70
3567 3567 if 'hmax' in kwargs:
3568 3568 hmax = kwargs['hmax']
3569 3569 else: hmax = 110
3570 3570
3571 3571 dataOut.outputInterval = nHours*3600
3572 3572
3573 3573 if self.__isConfig == False:
3574 3574 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3575 3575 #Get Initial LTC time
3576 3576 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3577 3577 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3578 3578
3579 3579 self.__isConfig = True
3580 3580
3581 3581 if self.__buffer is None:
3582 3582 self.__buffer = dataOut.data_param
3583 3583 self.__firstdata = copy.copy(dataOut)
3584 3584
3585 3585 else:
3586 3586 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3587 3587
3588 3588 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3589 3589
3590 3590 if self.__dataReady:
3591 3591 dataOut.utctimeInit = self.__initime
3592 3592
3593 3593 self.__initime += dataOut.outputInterval #to erase time offset
3594 3594
3595 3595 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
3596 3596 dataOut.flagNoData = False
3597 3597 self.__buffer = None
3598 3598
3599 3599 elif technique == 'Meteors1':
3600 3600 dataOut.flagNoData = True
3601 3601 self.__dataReady = False
3602 3602
3603 3603 if 'nMins' in kwargs:
3604 3604 nMins = kwargs['nMins']
3605 3605 else: nMins = 20
3606 3606 if 'rx_location' in kwargs:
3607 3607 rx_location = kwargs['rx_location']
3608 3608 else: rx_location = [(0,1),(1,1),(1,0)]
3609 3609 if 'azimuth' in kwargs:
3610 3610 azimuth = kwargs['azimuth']
3611 3611 else: azimuth = 51.06
3612 3612 if 'dfactor' in kwargs:
3613 3613 dfactor = kwargs['dfactor']
3614 3614 if 'mode' in kwargs:
3615 3615 mode = kwargs['mode']
3616 3616 if 'theta_x' in kwargs:
3617 3617 theta_x = kwargs['theta_x']
3618 3618 if 'theta_y' in kwargs:
3619 3619 theta_y = kwargs['theta_y']
3620 3620 else: mode = 'SA'
3621 3621
3622 3622 #Borrar luego esto
3623 3623 if dataOut.groupList is None:
3624 3624 dataOut.groupList = [(0,1),(0,2),(1,2)]
3625 3625 groupList = dataOut.groupList
3626 3626 C = 3e8
3627 3627 freq = 50e6
3628 3628 lamb = C/freq
3629 3629 k = 2*numpy.pi/lamb
3630 3630
3631 3631 timeList = dataOut.abscissaList
3632 3632 heightList = dataOut.heightList
3633 3633
3634 3634 if self.__isConfig == False:
3635 3635 dataOut.outputInterval = nMins*60
3636 3636 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3637 3637 #Get Initial LTC time
3638 3638 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3639 3639 minuteAux = initime.minute
3640 3640 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
3641 3641 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3642 3642
3643 3643 self.__isConfig = True
3644 3644
3645 3645 if self.__buffer is None:
3646 3646 self.__buffer = dataOut.data_param
3647 3647 self.__firstdata = copy.copy(dataOut)
3648 3648
3649 3649 else:
3650 3650 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3651 3651
3652 3652 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3653 3653
3654 3654 if self.__dataReady:
3655 3655 dataOut.utctimeInit = self.__initime
3656 3656 self.__initime += dataOut.outputInterval #to erase time offset
3657 3657
3658 3658 metArray = self.__buffer
3659 3659 if mode == 'SA':
3660 3660 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
3661 3661 elif mode == 'DBS':
3662 3662 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
3663 3663 dataOut.data_output = dataOut.data_output.T
3664 3664 dataOut.flagNoData = False
3665 3665 self.__buffer = None
3666 3666
3667 3667 return
3668 3668
3669 3669 class EWDriftsEstimation(Operation):
3670 3670
3671 3671 def __init__(self):
3672 3672 Operation.__init__(self)
3673 3673
3674 3674 def __correctValues(self, heiRang, phi, velRadial, SNR):
3675 3675 listPhi = phi.tolist()
3676 3676 maxid = listPhi.index(max(listPhi))
3677 3677 minid = listPhi.index(min(listPhi))
3678 3678
3679 3679 rango = list(range(len(phi)))
3680 3680 # rango = numpy.delete(rango,maxid)
3681 3681
3682 3682 heiRang1 = heiRang*math.cos(phi[maxid])
3683 3683 heiRangAux = heiRang*math.cos(phi[minid])
3684 3684 indOut = (heiRang1 < heiRangAux[0]).nonzero()
3685 3685 heiRang1 = numpy.delete(heiRang1,indOut)
3686 3686
3687 3687 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
3688 3688 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
3689 3689
3690 3690 for i in rango:
3691 3691 x = heiRang*math.cos(phi[i])
3692 3692 y1 = velRadial[i,:]
3693 3693 vali= (numpy.isfinite(y1)==True).nonzero()
3694 3694 y1=y1[vali]
3695 3695 x = x[vali]
3696 3696 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
3697 3697
3698 3698 #heiRang1 = x*math.cos(phi[maxid])
3699 3699 x1 = heiRang1
3700 3700 y11 = f1(x1)
3701 3701
3702 3702 y2 = SNR[i,:]
3703 3703 #print 'snr ', y2
3704 3704 x = heiRang*math.cos(phi[i])
3705 3705 vali= (y2 != -1).nonzero()
3706 3706 y2 = y2[vali]
3707 3707 x = x[vali]
3708 3708 #print 'snr ',y2
3709 3709 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
3710 3710 y21 = f2(x1)
3711 3711
3712 3712 velRadial1[i,:] = y11
3713 3713 SNR1[i,:] = y21
3714 3714
3715 3715 return heiRang1, velRadial1, SNR1
3716 3716
3717 3717
3718 3718
3719 3719 def run(self, dataOut, zenith, zenithCorrection):
3720 3720
3721 3721 heiRang = dataOut.heightList
3722 3722 velRadial = dataOut.data_param[:,3,:]
3723 3723 velRadialm = dataOut.data_param[:,2:4,:]*-1
3724 3724
3725 3725 rbufc=dataOut.data_paramC[:,:,0]
3726 3726 ebufc=dataOut.data_paramC[:,:,1]
3727 3727 SNR = dataOut.data_snr
3728 3728 velRerr = dataOut.data_error[:,4,:]
3729 3729 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
3730 3730 dataOut.moments=moments
3731 3731 # Coherent
3732 3732 smooth_wC = ebufc[0,:]
3733 3733 p_w0C = rbufc[0,:]
3734 3734 p_w1C = rbufc[1,:]
3735 3735 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
3736 3736 t_wC = rbufc[3,:]
3737 3737 my_nbeams = 2
3738 3738
3739 3739 zenith = numpy.array(zenith)
3740 3740 zenith -= zenithCorrection
3741 3741 zenith *= numpy.pi/180
3742 3742 if zenithCorrection != 0 :
3743 3743 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
3744 3744 else :
3745 3745 heiRang1 = heiRang
3746 3746 velRadial1 = velRadial
3747 3747 SNR1 = SNR
3748 3748
3749 3749 alp = zenith[0]
3750 3750 bet = zenith[1]
3751 3751
3752 3752 w_w = velRadial1[0,:]
3753 3753 w_e = velRadial1[1,:]
3754 3754 w_w_err = velRerr[0,:]
3755 3755 w_e_err = velRerr[1,:]
3756 3756
3757 3757 val = (numpy.isfinite(w_w)==False).nonzero()
3758 3758 val = val[0]
3759 3759 bad = val
3760 3760 if len(bad) > 0 :
3761 3761 w_w[bad] = w_wC[bad]
3762 3762 w_w_err[bad]= numpy.nan
3763 3763 if my_nbeams == 2:
3764 3764 smooth_eC=ebufc[4,:]
3765 3765 p_e0C = rbufc[4,:]
3766 3766 p_e1C = rbufc[5,:]
3767 3767 w_eC = rbufc[6,:]*-1
3768 3768 t_eC = rbufc[7,:]
3769 3769 val = (numpy.isfinite(w_e)==False).nonzero()
3770 3770 val = val[0]
3771 3771 bad = val
3772 3772 if len(bad) > 0 :
3773 3773 w_e[bad] = w_eC[bad]
3774 3774 w_e_err[bad]= numpy.nan
3775 3775
3776 3776 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
3777 3777 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
3778 3778
3779 3779 w_err = numpy.sqrt((w_w_err*numpy.sin(bet))**2.+(w_e_err*numpy.sin(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
3780 3780 u_err = numpy.sqrt((w_w_err*numpy.cos(bet))**2.+(w_e_err*numpy.cos(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
3781 3781
3782 3782 winds = numpy.vstack((w,u))
3783 3783
3784 3784 dataOut.heightList = heiRang1
3785 3785 dataOut.data_output = winds
3786 3786
3787 3787 snr1 = 10*numpy.log10(SNR1[0])
3788 3788 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
3789 3789 dataOut.utctimeInit = dataOut.utctime
3790 3790 dataOut.outputInterval = dataOut.timeInterval
3791 3791
3792 3792 hei_aver0 = 218
3793 3793 jrange = 450 #900 para HA drifts
3794 3794 deltah = 15.0 #dataOut.spacing(0)
3795 3795 h0 = 0.0 #dataOut.first_height(0)
3796 3796 heights = dataOut.heightList
3797 3797 nhei = len(heights)
3798 3798
3799 3799 range1 = numpy.arange(nhei) * deltah + h0
3800 3800
3801 3801 #jhei = WHERE(range1 GE hei_aver0 , jcount)
3802 3802 jhei = (range1 >= hei_aver0).nonzero()
3803 3803 if len(jhei[0]) > 0 :
3804 3804 h0_index = jhei[0][0] # Initial height for getting averages 218km
3805 3805
3806 3806 mynhei = 7
3807 3807 nhei_avg = int(jrange/deltah)
3808 3808 h_avgs = int(nhei_avg/mynhei)
3809 3809 nhei_avg = h_avgs*(mynhei-1)+mynhei
3810 3810
3811 3811 navgs = numpy.zeros(mynhei,dtype='float')
3812 3812 delta_h = numpy.zeros(mynhei,dtype='float')
3813 3813 range_aver = numpy.zeros(mynhei,dtype='float')
3814 3814 for ih in range( mynhei-1 ):
3815 3815 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
3816 3816 navgs[ih] = h_avgs
3817 3817 delta_h[ih] = deltah*h_avgs
3818 3818
3819 3819 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
3820 3820 navgs[mynhei-1] = 6*h_avgs
3821 3821 delta_h[mynhei-1] = deltah*6*h_avgs
3822 3822
3823 3823 wA = w[h0_index:h0_index+nhei_avg-0]
3824 3824 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
3825 3825
3826 3826 for i in range(5) :
3827 3827 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
3828 3828 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
3829 3829 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3830 3830 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3831 3831 wA[6*h_avgs+i] = avg
3832 3832 wA_err[6*h_avgs+i] = sigma
3833 3833
3834 3834
3835 3835 vals = wA[0:6*h_avgs-0]
3836 3836 errs=wA_err[0:6*h_avgs-0]
3837 3837 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
3838 3838 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3839 3839 wA[nhei_avg-1] = avg
3840 3840 wA_err[nhei_avg-1] = sigma
3841 3841
3842 3842 wA = wA[6*h_avgs:nhei_avg-0]
3843 3843 wA_err=wA_err[6*h_avgs:nhei_avg-0]
3844 3844 if my_nbeams == 2 :
3845 3845
3846 3846 uA = u[h0_index:h0_index+nhei_avg]
3847 3847 uA_err=u_err[h0_index:h0_index+nhei_avg]
3848 3848
3849 3849 for i in range(5) :
3850 3850 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
3851 3851 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
3852 3852 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3853 3853 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3854 3854 uA[6*h_avgs+i] = avg
3855 3855 uA_err[6*h_avgs+i]=sigma
3856 3856
3857 3857 vals = uA[0:6*h_avgs-0]
3858 3858 errs = uA_err[0:6*h_avgs-0]
3859 3859 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
3860 3860 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
3861 3861 uA[nhei_avg-1] = avg
3862 3862 uA_err[nhei_avg-1] = sigma
3863 3863 uA = uA[6*h_avgs:nhei_avg-0]
3864 3864 uA_err = uA_err[6*h_avgs:nhei_avg-0]
3865 3865
3866 3866 dataOut.drifts_avg = numpy.vstack((wA,uA))
3867 3867
3868 3868 tini=time.localtime(dataOut.utctime)
3869 3869 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
3870 3870 nfile = '/home/pcondor/Database/ewdriftsschain2019/jro'+datefile+'drifts_sch3.txt'
3871 3871
3872 3872 f1 = open(nfile,'a')
3873 3873
3874 3874 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
3875 3875 driftavgstr=str(dataOut.drifts_avg)
3876 3876
3877 3877 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
3878 3878 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
3879 3879 f1.close()
3880 3880
3881 3881 return dataOut
3882 3882
3883 3883 #--------------- Non Specular Meteor ----------------
3884 3884
3885 3885 class NonSpecularMeteorDetection(Operation):
3886 3886
3887 3887 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
3888 3888 data_acf = dataOut.data_pre[0]
3889 3889 data_ccf = dataOut.data_pre[1]
3890 3890 pairsList = dataOut.groupList[1]
3891 3891
3892 3892 lamb = dataOut.C/dataOut.frequency
3893 3893 tSamp = dataOut.ippSeconds*dataOut.nCohInt
3894 3894 paramInterval = dataOut.paramInterval
3895 3895
3896 3896 nChannels = data_acf.shape[0]
3897 3897 nLags = data_acf.shape[1]
3898 3898 nProfiles = data_acf.shape[2]
3899 3899 nHeights = dataOut.nHeights
3900 3900 nCohInt = dataOut.nCohInt
3901 3901 sec = numpy.round(nProfiles/dataOut.paramInterval)
3902 3902 heightList = dataOut.heightList
3903 3903 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
3904 3904 utctime = dataOut.utctime
3905 3905
3906 3906 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
3907 3907
3908 3908 #------------------------ SNR --------------------------------------
3909 3909 power = data_acf[:,0,:,:].real
3910 3910 noise = numpy.zeros(nChannels)
3911 3911 SNR = numpy.zeros(power.shape)
3912 3912 for i in range(nChannels):
3913 3913 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
3914 3914 SNR[i] = (power[i]-noise[i])/noise[i]
3915 3915 SNRm = numpy.nanmean(SNR, axis = 0)
3916 3916 SNRdB = 10*numpy.log10(SNR)
3917 3917
3918 3918 if mode == 'SA':
3919 3919 dataOut.groupList = dataOut.groupList[1]
3920 3920 nPairs = data_ccf.shape[0]
3921 3921 #---------------------- Coherence and Phase --------------------------
3922 3922 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
3923 3923 # phase1 = numpy.copy(phase)
3924 3924 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
3925 3925
3926 3926 for p in range(nPairs):
3927 3927 ch0 = pairsList[p][0]
3928 3928 ch1 = pairsList[p][1]
3929 3929 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
3930 3930 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
3931 3931 # phase1[p,:,:] = numpy.angle(ccf) #median filter
3932 3932 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
3933 3933 # coh1[p,:,:] = numpy.abs(ccf) #median filter
3934 3934 coh = numpy.nanmax(coh1, axis = 0)
3935 3935 # struc = numpy.ones((5,1))
3936 3936 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
3937 3937 #---------------------- Radial Velocity ----------------------------
3938 3938 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
3939 3939 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
3940 3940
3941 3941 if allData:
3942 3942 boolMetFin = ~numpy.isnan(SNRm)
3943 3943 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
3944 3944 else:
3945 3945 #------------------------ Meteor mask ---------------------------------
3946 3946 # #SNR mask
3947 3947 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
3948 3948 #
3949 3949 # #Erase small objects
3950 3950 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
3951 3951 #
3952 3952 # auxEEJ = numpy.sum(boolMet1,axis=0)
3953 3953 # indOver = auxEEJ>nProfiles*0.8 #Use this later
3954 3954 # indEEJ = numpy.where(indOver)[0]
3955 3955 # indNEEJ = numpy.where(~indOver)[0]
3956 3956 #
3957 3957 # boolMetFin = boolMet1
3958 3958 #
3959 3959 # if indEEJ.size > 0:
3960 3960 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
3961 3961 #
3962 3962 # boolMet2 = coh > cohThresh
3963 3963 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
3964 3964 #
3965 3965 # #Final Meteor mask
3966 3966 # boolMetFin = boolMet1|boolMet2
3967 3967
3968 3968 #Coherence mask
3969 3969 boolMet1 = coh > 0.75
3970 3970 struc = numpy.ones((30,1))
3971 3971 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
3972 3972
3973 3973 #Derivative mask
3974 3974 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
3975 3975 boolMet2 = derPhase < 0.2
3976 3976 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
3977 3977 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
3978 3978 boolMet2 = ndimage.median_filter(boolMet2,size=5)
3979 3979 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
3980 3980 # #Final mask
3981 3981 # boolMetFin = boolMet2
3982 3982 boolMetFin = boolMet1&boolMet2
3983 3983 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
3984 3984 #Creating data_param
3985 3985 coordMet = numpy.where(boolMetFin)
3986 3986
3987 3987 tmet = coordMet[0]
3988 3988 hmet = coordMet[1]
3989 3989
3990 3990 data_param = numpy.zeros((tmet.size, 6 + nPairs))
3991 3991 data_param[:,0] = utctime
3992 3992 data_param[:,1] = tmet
3993 3993 data_param[:,2] = hmet
3994 3994 data_param[:,3] = SNRm[tmet,hmet]
3995 3995 data_param[:,4] = velRad[tmet,hmet]
3996 3996 data_param[:,5] = coh[tmet,hmet]
3997 3997 data_param[:,6:] = phase[:,tmet,hmet].T
3998 3998
3999 3999 elif mode == 'DBS':
4000 4000 dataOut.groupList = numpy.arange(nChannels)
4001 4001
4002 4002 #Radial Velocities
4003 4003 phase = numpy.angle(data_acf[:,1,:,:])
4004 4004 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
4005 4005 velRad = phase*lamb/(4*numpy.pi*tSamp)
4006 4006
4007 4007 #Spectral width
4008 4008 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
4009 4009 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
4010 4010 acf1 = data_acf[:,1,:,:]
4011 4011 acf2 = data_acf[:,2,:,:]
4012 4012
4013 4013 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4014 4014 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
4015 4015 if allData:
4016 4016 boolMetFin = ~numpy.isnan(SNRdB)
4017 4017 else:
4018 4018 #SNR
4019 4019 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4020 4020 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4021 4021
4022 4022 #Radial velocity
4023 4023 boolMet2 = numpy.abs(velRad) < 20
4024 4024 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4025 4025
4026 4026 #Spectral Width
4027 4027 boolMet3 = spcWidth < 30
4028 4028 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4029 4029 # boolMetFin = self.__erase_small(boolMet1, 10,5)
4030 4030 boolMetFin = boolMet1&boolMet2&boolMet3
4031 4031
4032 4032 #Creating data_param
4033 4033 coordMet = numpy.where(boolMetFin)
4034 4034
4035 4035 cmet = coordMet[0]
4036 4036 tmet = coordMet[1]
4037 4037 hmet = coordMet[2]
4038 4038
4039 4039 data_param = numpy.zeros((tmet.size, 7))
4040 4040 data_param[:,0] = utctime
4041 4041 data_param[:,1] = cmet
4042 4042 data_param[:,2] = tmet
4043 4043 data_param[:,3] = hmet
4044 4044 data_param[:,4] = SNR[cmet,tmet,hmet].T
4045 4045 data_param[:,5] = velRad[cmet,tmet,hmet].T
4046 4046 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4047 4047
4048 4048 # self.dataOut.data_param = data_int
4049 4049 if len(data_param) == 0:
4050 4050 dataOut.flagNoData = True
4051 4051 else:
4052 4052 dataOut.data_param = data_param
4053 4053
4054 4054 def __erase_small(self, binArray, threshX, threshY):
4055 4055 labarray, numfeat = ndimage.measurements.label(binArray)
4056 4056 binArray1 = numpy.copy(binArray)
4057 4057
4058 4058 for i in range(1,numfeat + 1):
4059 4059 auxBin = (labarray==i)
4060 4060 auxSize = auxBin.sum()
4061 4061
4062 4062 x,y = numpy.where(auxBin)
4063 4063 widthX = x.max() - x.min()
4064 4064 widthY = y.max() - y.min()
4065 4065
4066 4066 #width X: 3 seg -> 12.5*3
4067 4067 #width Y:
4068 4068
4069 4069 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
4070 4070 binArray1[auxBin] = False
4071 4071
4072 4072 return binArray1
4073 4073
4074 4074 #--------------- Specular Meteor ----------------
4075 4075
4076 4076 class SMDetection(Operation):
4077 4077 '''
4078 4078 Function DetectMeteors()
4079 4079 Project developed with paper:
4080 4080 HOLDSWORTH ET AL. 2004
4081 4081
4082 4082 Input:
4083 4083 self.dataOut.data_pre
4084 4084
4085 4085 centerReceiverIndex: From the channels, which is the center receiver
4086 4086
4087 4087 hei_ref: Height reference for the Beacon signal extraction
4088 4088 tauindex:
4089 4089 predefinedPhaseShifts: Predefined phase offset for the voltge signals
4090 4090
4091 4091 cohDetection: Whether to user Coherent detection or not
4092 4092 cohDet_timeStep: Coherent Detection calculation time step
4093 4093 cohDet_thresh: Coherent Detection phase threshold to correct phases
4094 4094
4095 4095 noise_timeStep: Noise calculation time step
4096 4096 noise_multiple: Noise multiple to define signal threshold
4097 4097
4098 4098 multDet_timeLimit: Multiple Detection Removal time limit in seconds
4099 4099 multDet_rangeLimit: Multiple Detection Removal range limit in km
4100 4100
4101 4101 phaseThresh: Maximum phase difference between receiver to be consider a meteor
4102 4102 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
4103 4103
4104 4104 hmin: Minimum Height of the meteor to use it in the further wind estimations
4105 4105 hmax: Maximum Height of the meteor to use it in the further wind estimations
4106 4106 azimuth: Azimuth angle correction
4107 4107
4108 4108 Affected:
4109 4109 self.dataOut.data_param
4110 4110
4111 4111 Rejection Criteria (Errors):
4112 4112 0: No error; analysis OK
4113 4113 1: SNR < SNR threshold
4114 4114 2: angle of arrival (AOA) ambiguously determined
4115 4115 3: AOA estimate not feasible
4116 4116 4: Large difference in AOAs obtained from different antenna baselines
4117 4117 5: echo at start or end of time series
4118 4118 6: echo less than 5 examples long; too short for analysis
4119 4119 7: echo rise exceeds 0.3s
4120 4120 8: echo decay time less than twice rise time
4121 4121 9: large power level before echo
4122 4122 10: large power level after echo
4123 4123 11: poor fit to amplitude for estimation of decay time
4124 4124 12: poor fit to CCF phase variation for estimation of radial drift velocity
4125 4125 13: height unresolvable echo: not valid height within 70 to 110 km
4126 4126 14: height ambiguous echo: more then one possible height within 70 to 110 km
4127 4127 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
4128 4128 16: oscilatory echo, indicating event most likely not an underdense echo
4129 4129
4130 4130 17: phase difference in meteor Reestimation
4131 4131
4132 4132 Data Storage:
4133 4133 Meteors for Wind Estimation (8):
4134 4134 Utc Time | Range Height
4135 4135 Azimuth Zenith errorCosDir
4136 4136 VelRad errorVelRad
4137 4137 Phase0 Phase1 Phase2 Phase3
4138 4138 TypeError
4139 4139
4140 4140 '''
4141 4141
4142 4142 def run(self, dataOut, hei_ref = None, tauindex = 0,
4143 4143 phaseOffsets = None,
4144 4144 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
4145 4145 noise_timeStep = 4, noise_multiple = 4,
4146 4146 multDet_timeLimit = 1, multDet_rangeLimit = 3,
4147 4147 phaseThresh = 20, SNRThresh = 5,
4148 4148 hmin = 50, hmax=150, azimuth = 0,
4149 4149 channelPositions = None) :
4150 4150
4151 4151
4152 4152 #Getting Pairslist
4153 4153 if channelPositions is None:
4154 4154 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4155 4155 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4156 4156 meteorOps = SMOperations()
4157 4157 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4158 4158 heiRang = dataOut.heightList
4159 4159 #Get Beacon signal - No Beacon signal anymore
4160 4160 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
4161 4161 #
4162 4162 # if hei_ref != None:
4163 4163 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
4164 4164 #
4165 4165
4166 4166
4167 4167 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
4168 4168 # see if the user put in pre defined phase shifts
4169 4169 voltsPShift = dataOut.data_pre.copy()
4170 4170
4171 4171 # if predefinedPhaseShifts != None:
4172 4172 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
4173 4173 #
4174 4174 # # elif beaconPhaseShifts:
4175 4175 # # #get hardware phase shifts using beacon signal
4176 4176 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
4177 4177 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
4178 4178 #
4179 4179 # else:
4180 4180 # hardwarePhaseShifts = numpy.zeros(5)
4181 4181 #
4182 4182 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
4183 4183 # for i in range(self.dataOut.data_pre.shape[0]):
4184 4184 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
4185 4185
4186 4186 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
4187 4187
4188 4188 #Remove DC
4189 4189 voltsDC = numpy.mean(voltsPShift,1)
4190 4190 voltsDC = numpy.mean(voltsDC,1)
4191 4191 for i in range(voltsDC.shape[0]):
4192 4192 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
4193 4193
4194 4194 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
4195 4195 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
4196 4196
4197 4197 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
4198 4198 #Coherent Detection
4199 4199 if cohDetection:
4200 4200 #use coherent detection to get the net power
4201 4201 cohDet_thresh = cohDet_thresh*numpy.pi/180
4202 4202 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
4203 4203
4204 4204 #Non-coherent detection!
4205 4205 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
4206 4206 #********** END OF COH/NON-COH POWER CALCULATION**********************
4207 4207
4208 4208 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
4209 4209 #Get noise
4210 4210 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
4211 4211 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
4212 4212 #Get signal threshold
4213 4213 signalThresh = noise_multiple*noise
4214 4214 #Meteor echoes detection
4215 4215 listMeteors = self.__findMeteors(powerNet, signalThresh)
4216 4216 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
4217 4217
4218 4218 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
4219 4219 #Parameters
4220 4220 heiRange = dataOut.heightList
4221 4221 rangeInterval = heiRange[1] - heiRange[0]
4222 4222 rangeLimit = multDet_rangeLimit/rangeInterval
4223 4223 timeLimit = multDet_timeLimit/dataOut.timeInterval
4224 4224 #Multiple detection removals
4225 4225 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
4226 4226 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
4227 4227
4228 4228 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
4229 4229 #Parameters
4230 4230 phaseThresh = phaseThresh*numpy.pi/180
4231 4231 thresh = [phaseThresh, noise_multiple, SNRThresh]
4232 4232 #Meteor reestimation (Errors N 1, 6, 12, 17)
4233 4233 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
4234 4234 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
4235 4235 #Estimation of decay times (Errors N 7, 8, 11)
4236 4236 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
4237 4237 #******************* END OF METEOR REESTIMATION *******************
4238 4238
4239 4239 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
4240 4240 #Calculating Radial Velocity (Error N 15)
4241 4241 radialStdThresh = 10
4242 4242 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
4243 4243
4244 4244 if len(listMeteors4) > 0:
4245 4245 #Setting New Array
4246 4246 date = dataOut.utctime
4247 4247 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
4248 4248
4249 4249 #Correcting phase offset
4250 4250 if phaseOffsets != None:
4251 4251 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4252 4252 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4253 4253
4254 4254 #Second Pairslist
4255 4255 pairsList = []
4256 4256 pairx = (0,1)
4257 4257 pairy = (2,3)
4258 4258 pairsList.append(pairx)
4259 4259 pairsList.append(pairy)
4260 4260
4261 4261 jph = numpy.array([0,0,0,0])
4262 4262 h = (hmin,hmax)
4263 4263 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4264 4264
4265 4265 # #Calculate AOA (Error N 3, 4)
4266 4266 # #JONES ET AL. 1998
4267 4267 # error = arrayParameters[:,-1]
4268 4268 # AOAthresh = numpy.pi/8
4269 4269 # phases = -arrayParameters[:,9:13]
4270 4270 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
4271 4271 #
4272 4272 # #Calculate Heights (Error N 13 and 14)
4273 4273 # error = arrayParameters[:,-1]
4274 4274 # Ranges = arrayParameters[:,2]
4275 4275 # zenith = arrayParameters[:,5]
4276 4276 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
4277 4277 # error = arrayParameters[:,-1]
4278 4278 #********************* END OF PARAMETERS CALCULATION **************************
4279 4279
4280 4280 #***************************+ PASS DATA TO NEXT STEP **********************
4281 4281 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
4282 4282 dataOut.data_param = arrayParameters
4283 4283
4284 4284 if arrayParameters is None:
4285 4285 dataOut.flagNoData = True
4286 4286 else:
4287 4287 dataOut.flagNoData = True
4288 4288
4289 4289 return
4290 4290
4291 4291 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
4292 4292
4293 4293 minIndex = min(newheis[0])
4294 4294 maxIndex = max(newheis[0])
4295 4295
4296 4296 voltage = voltage0[:,:,minIndex:maxIndex+1]
4297 4297 nLength = voltage.shape[1]/n
4298 4298 nMin = 0
4299 4299 nMax = 0
4300 4300 phaseOffset = numpy.zeros((len(pairslist),n))
4301 4301
4302 4302 for i in range(n):
4303 4303 nMax += nLength
4304 4304 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
4305 4305 phaseCCF = numpy.mean(phaseCCF, axis = 2)
4306 4306 phaseOffset[:,i] = phaseCCF.transpose()
4307 4307 nMin = nMax
4308 4308 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
4309 4309
4310 4310 #Remove Outliers
4311 4311 factor = 2
4312 4312 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
4313 4313 dw = numpy.std(wt,axis = 1)
4314 4314 dw = dw.reshape((dw.size,1))
4315 4315 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
4316 4316 phaseOffset[ind] = numpy.nan
4317 4317 phaseOffset = stats.nanmean(phaseOffset, axis=1)
4318 4318
4319 4319 return phaseOffset
4320 4320
4321 4321 def __shiftPhase(self, data, phaseShift):
4322 4322 #this will shift the phase of a complex number
4323 4323 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
4324 4324 return dataShifted
4325 4325
4326 4326 def __estimatePhaseDifference(self, array, pairslist):
4327 4327 nChannel = array.shape[0]
4328 4328 nHeights = array.shape[2]
4329 4329 numPairs = len(pairslist)
4330 4330 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
4331 4331 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
4332 4332
4333 4333 #Correct phases
4334 4334 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
4335 4335 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4336 4336
4337 4337 if indDer[0].shape[0] > 0:
4338 4338 for i in range(indDer[0].shape[0]):
4339 4339 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
4340 4340 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
4341 4341
4342 4342 # for j in range(numSides):
4343 4343 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
4344 4344 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
4345 4345 #
4346 4346 #Linear
4347 4347 phaseInt = numpy.zeros((numPairs,1))
4348 4348 angAllCCF = phaseCCF[:,[0,1,3,4],0]
4349 4349 for j in range(numPairs):
4350 4350 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
4351 4351 phaseInt[j] = fit[1]
4352 4352 #Phase Differences
4353 4353 phaseDiff = phaseInt - phaseCCF[:,2,:]
4354 4354 phaseArrival = phaseInt.reshape(phaseInt.size)
4355 4355
4356 4356 #Dealias
4357 4357 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
4358 4358 # indAlias = numpy.where(phaseArrival > numpy.pi)
4359 4359 # phaseArrival[indAlias] -= 2*numpy.pi
4360 4360 # indAlias = numpy.where(phaseArrival < -numpy.pi)
4361 4361 # phaseArrival[indAlias] += 2*numpy.pi
4362 4362
4363 4363 return phaseDiff, phaseArrival
4364 4364
4365 4365 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
4366 4366 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
4367 4367 #find the phase shifts of each channel over 1 second intervals
4368 4368 #only look at ranges below the beacon signal
4369 4369 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4370 4370 numBlocks = int(volts.shape[1]/numProfPerBlock)
4371 4371 numHeights = volts.shape[2]
4372 4372 nChannel = volts.shape[0]
4373 4373 voltsCohDet = volts.copy()
4374 4374
4375 4375 pairsarray = numpy.array(pairslist)
4376 4376 indSides = pairsarray[:,1]
4377 4377 # indSides = numpy.array(range(nChannel))
4378 4378 # indSides = numpy.delete(indSides, indCenter)
4379 4379 #
4380 4380 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
4381 4381 listBlocks = numpy.array_split(volts, numBlocks, 1)
4382 4382
4383 4383 startInd = 0
4384 4384 endInd = 0
4385 4385
4386 4386 for i in range(numBlocks):
4387 4387 startInd = endInd
4388 4388 endInd = endInd + listBlocks[i].shape[1]
4389 4389
4390 4390 arrayBlock = listBlocks[i]
4391 4391 # arrayBlockCenter = listCenter[i]
4392 4392
4393 4393 #Estimate the Phase Difference
4394 4394 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
4395 4395 #Phase Difference RMS
4396 4396 arrayPhaseRMS = numpy.abs(phaseDiff)
4397 4397 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
4398 4398 indPhase = numpy.where(phaseRMSaux==4)
4399 4399 #Shifting
4400 4400 if indPhase[0].shape[0] > 0:
4401 4401 for j in range(indSides.size):
4402 4402 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
4403 4403 voltsCohDet[:,startInd:endInd,:] = arrayBlock
4404 4404
4405 4405 return voltsCohDet
4406 4406
4407 4407 def __calculateCCF(self, volts, pairslist ,laglist):
4408 4408
4409 4409 nHeights = volts.shape[2]
4410 4410 nPoints = volts.shape[1]
4411 4411 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
4412 4412
4413 4413 for i in range(len(pairslist)):
4414 4414 volts1 = volts[pairslist[i][0]]
4415 4415 volts2 = volts[pairslist[i][1]]
4416 4416
4417 4417 for t in range(len(laglist)):
4418 4418 idxT = laglist[t]
4419 4419 if idxT >= 0:
4420 4420 vStacked = numpy.vstack((volts2[idxT:,:],
4421 4421 numpy.zeros((idxT, nHeights),dtype='complex')))
4422 4422 else:
4423 4423 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
4424 4424 volts2[:(nPoints + idxT),:]))
4425 4425 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
4426 4426
4427 4427 vStacked = None
4428 4428 return voltsCCF
4429 4429
4430 4430 def __getNoise(self, power, timeSegment, timeInterval):
4431 4431 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
4432 4432 numBlocks = int(power.shape[0]/numProfPerBlock)
4433 4433 numHeights = power.shape[1]
4434 4434
4435 4435 listPower = numpy.array_split(power, numBlocks, 0)
4436 4436 noise = numpy.zeros((power.shape[0], power.shape[1]))
4437 4437 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
4438 4438
4439 4439 startInd = 0
4440 4440 endInd = 0
4441 4441
4442 4442 for i in range(numBlocks): #split por canal
4443 4443 startInd = endInd
4444 4444 endInd = endInd + listPower[i].shape[0]
4445 4445
4446 4446 arrayBlock = listPower[i]
4447 4447 noiseAux = numpy.mean(arrayBlock, 0)
4448 4448 # noiseAux = numpy.median(noiseAux)
4449 4449 # noiseAux = numpy.mean(arrayBlock)
4450 4450 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
4451 4451
4452 4452 noiseAux1 = numpy.mean(arrayBlock)
4453 4453 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
4454 4454
4455 4455 return noise, noise1
4456 4456
4457 4457 def __findMeteors(self, power, thresh):
4458 4458 nProf = power.shape[0]
4459 4459 nHeights = power.shape[1]
4460 4460 listMeteors = []
4461 4461
4462 4462 for i in range(nHeights):
4463 4463 powerAux = power[:,i]
4464 4464 threshAux = thresh[:,i]
4465 4465
4466 4466 indUPthresh = numpy.where(powerAux > threshAux)[0]
4467 4467 indDNthresh = numpy.where(powerAux <= threshAux)[0]
4468 4468
4469 4469 j = 0
4470 4470
4471 4471 while (j < indUPthresh.size - 2):
4472 4472 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
4473 4473 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
4474 4474 indDNthresh = indDNthresh[indDNAux]
4475 4475
4476 4476 if (indDNthresh.size > 0):
4477 4477 indEnd = indDNthresh[0] - 1
4478 4478 indInit = indUPthresh[j]
4479 4479
4480 4480 meteor = powerAux[indInit:indEnd + 1]
4481 4481 indPeak = meteor.argmax() + indInit
4482 4482 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
4483 4483
4484 4484 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
4485 4485 j = numpy.where(indUPthresh == indEnd)[0] + 1
4486 4486 else: j+=1
4487 4487 else: j+=1
4488 4488
4489 4489 return listMeteors
4490 4490
4491 4491 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
4492 4492
4493 4493 arrayMeteors = numpy.asarray(listMeteors)
4494 4494 listMeteors1 = []
4495 4495
4496 4496 while arrayMeteors.shape[0] > 0:
4497 4497 FLAs = arrayMeteors[:,4]
4498 4498 maxFLA = FLAs.argmax()
4499 4499 listMeteors1.append(arrayMeteors[maxFLA,:])
4500 4500
4501 4501 MeteorInitTime = arrayMeteors[maxFLA,1]
4502 4502 MeteorEndTime = arrayMeteors[maxFLA,3]
4503 4503 MeteorHeight = arrayMeteors[maxFLA,0]
4504 4504
4505 4505 #Check neighborhood
4506 4506 maxHeightIndex = MeteorHeight + rangeLimit
4507 4507 minHeightIndex = MeteorHeight - rangeLimit
4508 4508 minTimeIndex = MeteorInitTime - timeLimit
4509 4509 maxTimeIndex = MeteorEndTime + timeLimit
4510 4510
4511 4511 #Check Heights
4512 4512 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
4513 4513 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
4514 4514 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
4515 4515
4516 4516 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
4517 4517
4518 4518 return listMeteors1
4519 4519
4520 4520 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
4521 4521 numHeights = volts.shape[2]
4522 4522 nChannel = volts.shape[0]
4523 4523
4524 4524 thresholdPhase = thresh[0]
4525 4525 thresholdNoise = thresh[1]
4526 4526 thresholdDB = float(thresh[2])
4527 4527
4528 4528 thresholdDB1 = 10**(thresholdDB/10)
4529 4529 pairsarray = numpy.array(pairslist)
4530 4530 indSides = pairsarray[:,1]
4531 4531
4532 4532 pairslist1 = list(pairslist)
4533 4533 pairslist1.append((0,1))
4534 4534 pairslist1.append((3,4))
4535 4535
4536 4536 listMeteors1 = []
4537 4537 listPowerSeries = []
4538 4538 listVoltageSeries = []
4539 4539 #volts has the war data
4540 4540
4541 4541 if frequency == 30e6:
4542 4542 timeLag = 45*10**-3
4543 4543 else:
4544 4544 timeLag = 15*10**-3
4545 4545 lag = numpy.ceil(timeLag/timeInterval)
4546 4546
4547 4547 for i in range(len(listMeteors)):
4548 4548
4549 4549 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
4550 4550 meteorAux = numpy.zeros(16)
4551 4551
4552 4552 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
4553 4553 mHeight = listMeteors[i][0]
4554 4554 mStart = listMeteors[i][1]
4555 4555 mPeak = listMeteors[i][2]
4556 4556 mEnd = listMeteors[i][3]
4557 4557
4558 4558 #get the volt data between the start and end times of the meteor
4559 4559 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
4560 4560 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4561 4561
4562 4562 #3.6. Phase Difference estimation
4563 4563 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
4564 4564
4565 4565 #3.7. Phase difference removal & meteor start, peak and end times reestimated
4566 4566 #meteorVolts0.- all Channels, all Profiles
4567 4567 meteorVolts0 = volts[:,:,mHeight]
4568 4568 meteorThresh = noise[:,mHeight]*thresholdNoise
4569 4569 meteorNoise = noise[:,mHeight]
4570 4570 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
4571 4571 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
4572 4572
4573 4573 #Times reestimation
4574 4574 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
4575 4575 if mStart1.size > 0:
4576 4576 mStart1 = mStart1[-1] + 1
4577 4577
4578 4578 else:
4579 4579 mStart1 = mPeak
4580 4580
4581 4581 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
4582 4582 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
4583 4583 if mEndDecayTime1.size == 0:
4584 4584 mEndDecayTime1 = powerNet0.size
4585 4585 else:
4586 4586 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
4587 4587 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
4588 4588
4589 4589 #meteorVolts1.- all Channels, from start to end
4590 4590 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
4591 4591 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
4592 4592 if meteorVolts2.shape[1] == 0:
4593 4593 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
4594 4594 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
4595 4595 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
4596 4596 ##################### END PARAMETERS REESTIMATION #########################
4597 4597
4598 4598 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
4599 4599 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
4600 4600 if meteorVolts2.shape[1] > 0:
4601 4601 #Phase Difference re-estimation
4602 4602 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
4603 4603 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
4604 4604 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
4605 4605 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
4606 4606 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
4607 4607
4608 4608 #Phase Difference RMS
4609 4609 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
4610 4610 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
4611 4611 #Data from Meteor
4612 4612 mPeak1 = powerNet1.argmax() + mStart1
4613 4613 mPeakPower1 = powerNet1.max()
4614 4614 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
4615 4615 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
4616 4616 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
4617 4617 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
4618 4618 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
4619 4619 #Vectorize
4620 4620 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
4621 4621 meteorAux[7:11] = phaseDiffint[0:4]
4622 4622
4623 4623 #Rejection Criterions
4624 4624 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
4625 4625 meteorAux[-1] = 17
4626 4626 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
4627 4627 meteorAux[-1] = 1
4628 4628
4629 4629
4630 4630 else:
4631 4631 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
4632 4632 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
4633 4633 PowerSeries = 0
4634 4634
4635 4635 listMeteors1.append(meteorAux)
4636 4636 listPowerSeries.append(PowerSeries)
4637 4637 listVoltageSeries.append(meteorVolts1)
4638 4638
4639 4639 return listMeteors1, listPowerSeries, listVoltageSeries
4640 4640
4641 4641 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
4642 4642
4643 4643 threshError = 10
4644 4644 #Depending if it is 30 or 50 MHz
4645 4645 if frequency == 30e6:
4646 4646 timeLag = 45*10**-3
4647 4647 else:
4648 4648 timeLag = 15*10**-3
4649 4649 lag = numpy.ceil(timeLag/timeInterval)
4650 4650
4651 4651 listMeteors1 = []
4652 4652
4653 4653 for i in range(len(listMeteors)):
4654 4654 meteorPower = listPower[i]
4655 4655 meteorAux = listMeteors[i]
4656 4656
4657 4657 if meteorAux[-1] == 0:
4658 4658
4659 4659 try:
4660 4660 indmax = meteorPower.argmax()
4661 4661 indlag = indmax + lag
4662 4662
4663 4663 y = meteorPower[indlag:]
4664 4664 x = numpy.arange(0, y.size)*timeLag
4665 4665
4666 4666 #first guess
4667 4667 a = y[0]
4668 4668 tau = timeLag
4669 4669 #exponential fit
4670 4670 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
4671 4671 y1 = self.__exponential_function(x, *popt)
4672 4672 #error estimation
4673 4673 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
4674 4674
4675 4675 decayTime = popt[1]
4676 4676 riseTime = indmax*timeInterval
4677 4677 meteorAux[11:13] = [decayTime, error]
4678 4678
4679 4679 #Table items 7, 8 and 11
4680 4680 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
4681 4681 meteorAux[-1] = 7
4682 4682 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
4683 4683 meteorAux[-1] = 8
4684 4684 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
4685 4685 meteorAux[-1] = 11
4686 4686
4687 4687
4688 4688 except:
4689 4689 meteorAux[-1] = 11
4690 4690
4691 4691
4692 4692 listMeteors1.append(meteorAux)
4693 4693
4694 4694 return listMeteors1
4695 4695
4696 4696 #Exponential Function
4697 4697
4698 4698 def __exponential_function(self, x, a, tau):
4699 4699 y = a*numpy.exp(-x/tau)
4700 4700 return y
4701 4701
4702 4702 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
4703 4703
4704 4704 pairslist1 = list(pairslist)
4705 4705 pairslist1.append((0,1))
4706 4706 pairslist1.append((3,4))
4707 4707 numPairs = len(pairslist1)
4708 4708 #Time Lag
4709 4709 timeLag = 45*10**-3
4710 4710 c = 3e8
4711 4711 lag = numpy.ceil(timeLag/timeInterval)
4712 4712 freq = 30e6
4713 4713
4714 4714 listMeteors1 = []
4715 4715
4716 4716 for i in range(len(listMeteors)):
4717 4717 meteorAux = listMeteors[i]
4718 4718 if meteorAux[-1] == 0:
4719 4719 mStart = listMeteors[i][1]
4720 4720 mPeak = listMeteors[i][2]
4721 4721 mLag = mPeak - mStart + lag
4722 4722
4723 4723 #get the volt data between the start and end times of the meteor
4724 4724 meteorVolts = listVolts[i]
4725 4725 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
4726 4726
4727 4727 #Get CCF
4728 4728 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
4729 4729
4730 4730 #Method 2
4731 4731 slopes = numpy.zeros(numPairs)
4732 4732 time = numpy.array([-2,-1,1,2])*timeInterval
4733 4733 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
4734 4734
4735 4735 #Correct phases
4736 4736 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
4737 4737 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
4738 4738
4739 4739 if indDer[0].shape[0] > 0:
4740 4740 for i in range(indDer[0].shape[0]):
4741 4741 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
4742 4742 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
4743 4743
4744 4744 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
4745 4745 for j in range(numPairs):
4746 4746 fit = stats.linregress(time, angAllCCF[j,:])
4747 4747 slopes[j] = fit[0]
4748 4748
4749 4749 #Remove Outlier
4750 4750 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4751 4751 # slopes = numpy.delete(slopes,indOut)
4752 4752 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
4753 4753 # slopes = numpy.delete(slopes,indOut)
4754 4754
4755 4755 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
4756 4756 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
4757 4757 meteorAux[-2] = radialError
4758 4758 meteorAux[-3] = radialVelocity
4759 4759
4760 4760 #Setting Error
4761 4761 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
4762 4762 if numpy.abs(radialVelocity) > 200:
4763 4763 meteorAux[-1] = 15
4764 4764 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
4765 4765 elif radialError > radialStdThresh:
4766 4766 meteorAux[-1] = 12
4767 4767
4768 4768 listMeteors1.append(meteorAux)
4769 4769 return listMeteors1
4770 4770
4771 4771 def __setNewArrays(self, listMeteors, date, heiRang):
4772 4772
4773 4773 #New arrays
4774 4774 arrayMeteors = numpy.array(listMeteors)
4775 4775 arrayParameters = numpy.zeros((len(listMeteors), 13))
4776 4776
4777 4777 #Date inclusion
4778 4778 # date = re.findall(r'\((.*?)\)', date)
4779 4779 # date = date[0].split(',')
4780 4780 # date = map(int, date)
4781 4781 #
4782 4782 # if len(date)<6:
4783 4783 # date.append(0)
4784 4784 #
4785 4785 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
4786 4786 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
4787 4787 arrayDate = numpy.tile(date, (len(listMeteors)))
4788 4788
4789 4789 #Meteor array
4790 4790 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
4791 4791 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
4792 4792
4793 4793 #Parameters Array
4794 4794 arrayParameters[:,0] = arrayDate #Date
4795 4795 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
4796 4796 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
4797 4797 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
4798 4798 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
4799 4799
4800 4800
4801 4801 return arrayParameters
4802 4802
4803 4803 class CorrectSMPhases(Operation):
4804 4804
4805 4805 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
4806 4806
4807 4807 arrayParameters = dataOut.data_param
4808 4808 pairsList = []
4809 4809 pairx = (0,1)
4810 4810 pairy = (2,3)
4811 4811 pairsList.append(pairx)
4812 4812 pairsList.append(pairy)
4813 4813 jph = numpy.zeros(4)
4814 4814
4815 4815 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
4816 4816 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
4817 4817 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
4818 4818
4819 4819 meteorOps = SMOperations()
4820 4820 if channelPositions is None:
4821 4821 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
4822 4822 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
4823 4823
4824 4824 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
4825 4825 h = (hmin,hmax)
4826 4826
4827 4827 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
4828 4828
4829 4829 dataOut.data_param = arrayParameters
4830 4830 return
4831 4831
4832 4832 class SMPhaseCalibration(Operation):
4833 4833
4834 4834 __buffer = None
4835 4835
4836 4836 __initime = None
4837 4837
4838 4838 __dataReady = False
4839 4839
4840 4840 __isConfig = False
4841 4841
4842 4842 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
4843 4843
4844 4844 dataTime = currentTime + paramInterval
4845 4845 deltaTime = dataTime - initTime
4846 4846
4847 4847 if deltaTime >= outputInterval or deltaTime < 0:
4848 4848 return True
4849 4849
4850 4850 return False
4851 4851
4852 4852 def __getGammas(self, pairs, d, phases):
4853 4853 gammas = numpy.zeros(2)
4854 4854
4855 4855 for i in range(len(pairs)):
4856 4856
4857 4857 pairi = pairs[i]
4858 4858
4859 4859 phip3 = phases[:,pairi[0]]
4860 4860 d3 = d[pairi[0]]
4861 4861 phip2 = phases[:,pairi[1]]
4862 4862 d2 = d[pairi[1]]
4863 4863 #Calculating gamma
4864 4864 # jdcos = alp1/(k*d1)
4865 4865 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
4866 4866 jgamma = -phip2*d3/d2 - phip3
4867 4867 jgamma = numpy.angle(numpy.exp(1j*jgamma))
4868 4868 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
4869 4869 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
4870 4870
4871 4871 #Revised distribution
4872 4872 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
4873 4873
4874 4874 #Histogram
4875 4875 nBins = 64
4876 4876 rmin = -0.5*numpy.pi
4877 4877 rmax = 0.5*numpy.pi
4878 4878 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
4879 4879
4880 4880 meteorsY = phaseHisto[0]
4881 4881 phasesX = phaseHisto[1][:-1]
4882 4882 width = phasesX[1] - phasesX[0]
4883 4883 phasesX += width/2
4884 4884
4885 4885 #Gaussian aproximation
4886 4886 bpeak = meteorsY.argmax()
4887 4887 peak = meteorsY.max()
4888 4888 jmin = bpeak - 5
4889 4889 jmax = bpeak + 5 + 1
4890 4890
4891 4891 if jmin<0:
4892 4892 jmin = 0
4893 4893 jmax = 6
4894 4894 elif jmax > meteorsY.size:
4895 4895 jmin = meteorsY.size - 6
4896 4896 jmax = meteorsY.size
4897 4897
4898 4898 x0 = numpy.array([peak,bpeak,50])
4899 4899 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
4900 4900
4901 4901 #Gammas
4902 4902 gammas[i] = coeff[0][1]
4903 4903
4904 4904 return gammas
4905 4905
4906 4906 def __residualFunction(self, coeffs, y, t):
4907 4907
4908 4908 return y - self.__gauss_function(t, coeffs)
4909 4909
4910 4910 def __gauss_function(self, t, coeffs):
4911 4911
4912 4912 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
4913 4913
4914 4914 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
4915 4915 meteorOps = SMOperations()
4916 4916 nchan = 4
4917 4917 pairx = pairsList[0] #x es 0
4918 4918 pairy = pairsList[1] #y es 1
4919 4919 center_xangle = 0
4920 4920 center_yangle = 0
4921 4921 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
4922 4922 ntimes = len(range_angle)
4923 4923
4924 4924 nstepsx = 20
4925 4925 nstepsy = 20
4926 4926
4927 4927 for iz in range(ntimes):
4928 4928 min_xangle = -range_angle[iz]/2 + center_xangle
4929 4929 max_xangle = range_angle[iz]/2 + center_xangle
4930 4930 min_yangle = -range_angle[iz]/2 + center_yangle
4931 4931 max_yangle = range_angle[iz]/2 + center_yangle
4932 4932
4933 4933 inc_x = (max_xangle-min_xangle)/nstepsx
4934 4934 inc_y = (max_yangle-min_yangle)/nstepsy
4935 4935
4936 4936 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
4937 4937 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
4938 4938 penalty = numpy.zeros((nstepsx,nstepsy))
4939 4939 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
4940 4940 jph = numpy.zeros(nchan)
4941 4941
4942 4942 # Iterations looking for the offset
4943 4943 for iy in range(int(nstepsy)):
4944 4944 for ix in range(int(nstepsx)):
4945 4945 d3 = d[pairsList[1][0]]
4946 4946 d2 = d[pairsList[1][1]]
4947 4947 d5 = d[pairsList[0][0]]
4948 4948 d4 = d[pairsList[0][1]]
4949 4949
4950 4950 alp2 = alpha_y[iy] #gamma 1
4951 4951 alp4 = alpha_x[ix] #gamma 0
4952 4952
4953 4953 alp3 = -alp2*d3/d2 - gammas[1]
4954 4954 alp5 = -alp4*d5/d4 - gammas[0]
4955 4955 # jph[pairy[1]] = alpha_y[iy]
4956 4956 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
4957 4957
4958 4958 # jph[pairx[1]] = alpha_x[ix]
4959 4959 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
4960 4960 jph[pairsList[0][1]] = alp4
4961 4961 jph[pairsList[0][0]] = alp5
4962 4962 jph[pairsList[1][0]] = alp3
4963 4963 jph[pairsList[1][1]] = alp2
4964 4964 jph_array[:,ix,iy] = jph
4965 4965 # d = [2.0,2.5,2.5,2.0]
4966 4966 #falta chequear si va a leer bien los meteoros
4967 4967 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
4968 4968 error = meteorsArray1[:,-1]
4969 4969 ind1 = numpy.where(error==0)[0]
4970 4970 penalty[ix,iy] = ind1.size
4971 4971
4972 4972 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
4973 4973 phOffset = jph_array[:,i,j]
4974 4974
4975 4975 center_xangle = phOffset[pairx[1]]
4976 4976 center_yangle = phOffset[pairy[1]]
4977 4977
4978 4978 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
4979 4979 phOffset = phOffset*180/numpy.pi
4980 4980 return phOffset
4981 4981
4982 4982
4983 4983 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
4984 4984
4985 4985 dataOut.flagNoData = True
4986 4986 self.__dataReady = False
4987 4987 dataOut.outputInterval = nHours*3600
4988 4988
4989 4989 if self.__isConfig == False:
4990 4990 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
4991 4991 #Get Initial LTC time
4992 4992 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4993 4993 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4994 4994
4995 4995 self.__isConfig = True
4996 4996
4997 4997 if self.__buffer is None:
4998 4998 self.__buffer = dataOut.data_param.copy()
4999 4999
5000 5000 else:
5001 5001 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5002 5002
5003 5003 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5004 5004
5005 5005 if self.__dataReady:
5006 5006 dataOut.utctimeInit = self.__initime
5007 5007 self.__initime += dataOut.outputInterval #to erase time offset
5008 5008
5009 5009 freq = dataOut.frequency
5010 5010 c = dataOut.C #m/s
5011 5011 lamb = c/freq
5012 5012 k = 2*numpy.pi/lamb
5013 5013 azimuth = 0
5014 5014 h = (hmin, hmax)
5015 5015 # pairs = ((0,1),(2,3)) #Estrella
5016 5016 # pairs = ((1,0),(2,3)) #T
5017 5017
5018 5018 if channelPositions is None:
5019 5019 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5020 5020 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5021 5021 meteorOps = SMOperations()
5022 5022 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5023 5023
5024 5024 #Checking correct order of pairs
5025 5025 pairs = []
5026 5026 if distances[1] > distances[0]:
5027 5027 pairs.append((1,0))
5028 5028 else:
5029 5029 pairs.append((0,1))
5030 5030
5031 5031 if distances[3] > distances[2]:
5032 5032 pairs.append((3,2))
5033 5033 else:
5034 5034 pairs.append((2,3))
5035 5035 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
5036 5036
5037 5037 meteorsArray = self.__buffer
5038 5038 error = meteorsArray[:,-1]
5039 5039 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5040 5040 ind1 = numpy.where(boolError)[0]
5041 5041 meteorsArray = meteorsArray[ind1,:]
5042 5042 meteorsArray[:,-1] = 0
5043 5043 phases = meteorsArray[:,8:12]
5044 5044
5045 5045 #Calculate Gammas
5046 5046 gammas = self.__getGammas(pairs, distances, phases)
5047 5047 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
5048 5048 #Calculate Phases
5049 5049 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5050 5050 phasesOff = phasesOff.reshape((1,phasesOff.size))
5051 5051 dataOut.data_output = -phasesOff
5052 5052 dataOut.flagNoData = False
5053 5053 self.__buffer = None
5054 5054
5055 5055
5056 5056 return
5057 5057
5058 5058 class SMOperations():
5059 5059
5060 5060 def __init__(self):
5061 5061
5062 5062 return
5063 5063
5064 5064 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5065 5065
5066 5066 arrayParameters = arrayParameters0.copy()
5067 5067 hmin = h[0]
5068 5068 hmax = h[1]
5069 5069
5070 5070 #Calculate AOA (Error N 3, 4)
5071 5071 #JONES ET AL. 1998
5072 5072 AOAthresh = numpy.pi/8
5073 5073 error = arrayParameters[:,-1]
5074 5074 phases = -arrayParameters[:,8:12] + jph
5075 5075 # phases = numpy.unwrap(phases)
5076 5076 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5077 5077
5078 5078 #Calculate Heights (Error N 13 and 14)
5079 5079 error = arrayParameters[:,-1]
5080 5080 Ranges = arrayParameters[:,1]
5081 5081 zenith = arrayParameters[:,4]
5082 5082 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5083 5083
5084 5084 #----------------------- Get Final data ------------------------------------
5085 5085 # error = arrayParameters[:,-1]
5086 5086 # ind1 = numpy.where(error==0)[0]
5087 5087 # arrayParameters = arrayParameters[ind1,:]
5088 5088
5089 5089 return arrayParameters
5090 5090
5091 5091 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5092 5092
5093 5093 arrayAOA = numpy.zeros((phases.shape[0],3))
5094 5094 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5095 5095
5096 5096 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5097 5097 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5098 5098 arrayAOA[:,2] = cosDirError
5099 5099
5100 5100 azimuthAngle = arrayAOA[:,0]
5101 5101 zenithAngle = arrayAOA[:,1]
5102 5102
5103 5103 #Setting Error
5104 5104 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5105 5105 error[indError] = 0
5106 5106 #Number 3: AOA not fesible
5107 5107 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5108 5108 error[indInvalid] = 3
5109 5109 #Number 4: Large difference in AOAs obtained from different antenna baselines
5110 5110 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5111 5111 error[indInvalid] = 4
5112 5112 return arrayAOA, error
5113 5113
5114 5114 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5115 5115
5116 5116 #Initializing some variables
5117 5117 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5118 5118 ang_aux = ang_aux.reshape(1,ang_aux.size)
5119 5119
5120 5120 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5121 5121 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5122 5122
5123 5123
5124 5124 for i in range(2):
5125 5125 ph0 = arrayPhase[:,pairsList[i][0]]
5126 5126 ph1 = arrayPhase[:,pairsList[i][1]]
5127 5127 d0 = distances[pairsList[i][0]]
5128 5128 d1 = distances[pairsList[i][1]]
5129 5129
5130 5130 ph0_aux = ph0 + ph1
5131 5131 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5132 5132 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
5133 5133 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
5134 5134 #First Estimation
5135 5135 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5136 5136
5137 5137 #Most-Accurate Second Estimation
5138 5138 phi1_aux = ph0 - ph1
5139 5139 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5140 5140 #Direction Cosine 1
5141 5141 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5142 5142
5143 5143 #Searching the correct Direction Cosine
5144 5144 cosdir0_aux = cosdir0[:,i]
5145 5145 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5146 5146 #Minimum Distance
5147 5147 cosDiff = (cosdir1 - cosdir0_aux)**2
5148 5148 indcos = cosDiff.argmin(axis = 1)
5149 5149 #Saving Value obtained
5150 5150 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5151 5151
5152 5152 return cosdir0, cosdir
5153 5153
5154 5154 def __calculateAOA(self, cosdir, azimuth):
5155 5155 cosdirX = cosdir[:,0]
5156 5156 cosdirY = cosdir[:,1]
5157 5157
5158 5158 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5159 5159 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5160 5160 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5161 5161
5162 5162 return angles
5163 5163
5164 5164 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5165 5165
5166 5166 Ramb = 375 #Ramb = c/(2*PRF)
5167 5167 Re = 6371 #Earth Radius
5168 5168 heights = numpy.zeros(Ranges.shape)
5169 5169
5170 5170 R_aux = numpy.array([0,1,2])*Ramb
5171 5171 R_aux = R_aux.reshape(1,R_aux.size)
5172 5172
5173 5173 Ranges = Ranges.reshape(Ranges.size,1)
5174 5174
5175 5175 Ri = Ranges + R_aux
5176 5176 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5177 5177
5178 5178 #Check if there is a height between 70 and 110 km
5179 5179 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5180 5180 ind_h = numpy.where(h_bool == 1)[0]
5181 5181
5182 5182 hCorr = hi[ind_h, :]
5183 5183 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5184 5184
5185 5185 hCorr = hi[ind_hCorr][:len(ind_h)]
5186 5186 heights[ind_h] = hCorr
5187 5187
5188 5188 #Setting Error
5189 5189 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5190 5190 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5191 5191 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
5192 5192 error[indError] = 0
5193 5193 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5194 5194 error[indInvalid2] = 14
5195 5195 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5196 5196 error[indInvalid1] = 13
5197 5197
5198 5198 return heights, error
5199 5199
5200 5200 def getPhasePairs(self, channelPositions):
5201 5201 chanPos = numpy.array(channelPositions)
5202 5202 listOper = list(itertools.combinations(list(range(5)),2))
5203 5203
5204 5204 distances = numpy.zeros(4)
5205 5205 axisX = []
5206 5206 axisY = []
5207 5207 distX = numpy.zeros(3)
5208 5208 distY = numpy.zeros(3)
5209 5209 ix = 0
5210 5210 iy = 0
5211 5211
5212 5212 pairX = numpy.zeros((2,2))
5213 5213 pairY = numpy.zeros((2,2))
5214 5214
5215 5215 for i in range(len(listOper)):
5216 5216 pairi = listOper[i]
5217 5217
5218 5218 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
5219 5219
5220 5220 if posDif[0] == 0:
5221 5221 axisY.append(pairi)
5222 5222 distY[iy] = posDif[1]
5223 5223 iy += 1
5224 5224 elif posDif[1] == 0:
5225 5225 axisX.append(pairi)
5226 5226 distX[ix] = posDif[0]
5227 5227 ix += 1
5228 5228
5229 5229 for i in range(2):
5230 5230 if i==0:
5231 5231 dist0 = distX
5232 5232 axis0 = axisX
5233 5233 else:
5234 5234 dist0 = distY
5235 5235 axis0 = axisY
5236 5236
5237 5237 side = numpy.argsort(dist0)[:-1]
5238 5238 axis0 = numpy.array(axis0)[side,:]
5239 5239 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
5240 5240 axis1 = numpy.unique(numpy.reshape(axis0,4))
5241 5241 side = axis1[axis1 != chanC]
5242 5242 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
5243 5243 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
5244 5244 if diff1<0:
5245 5245 chan2 = side[0]
5246 5246 d2 = numpy.abs(diff1)
5247 5247 chan1 = side[1]
5248 5248 d1 = numpy.abs(diff2)
5249 5249 else:
5250 5250 chan2 = side[1]
5251 5251 d2 = numpy.abs(diff2)
5252 5252 chan1 = side[0]
5253 5253 d1 = numpy.abs(diff1)
5254 5254
5255 5255 if i==0:
5256 5256 chanCX = chanC
5257 5257 chan1X = chan1
5258 5258 chan2X = chan2
5259 5259 distances[0:2] = numpy.array([d1,d2])
5260 5260 else:
5261 5261 chanCY = chanC
5262 5262 chan1Y = chan1
5263 5263 chan2Y = chan2
5264 5264 distances[2:4] = numpy.array([d1,d2])
5265 5265 # axisXsides = numpy.reshape(axisX[ix,:],4)
5266 5266 #
5267 5267 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
5268 5268 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
5269 5269 #
5270 5270 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
5271 5271 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
5272 5272 # channel25X = int(pairX[0,ind25X])
5273 5273 # channel20X = int(pairX[1,ind20X])
5274 5274 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
5275 5275 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
5276 5276 # channel25Y = int(pairY[0,ind25Y])
5277 5277 # channel20Y = int(pairY[1,ind20Y])
5278 5278
5279 5279 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
5280 5280 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
5281 5281
5282 5282 return pairslist, distances
5283 5283 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
5284 5284 #
5285 5285 # arrayAOA = numpy.zeros((phases.shape[0],3))
5286 5286 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
5287 5287 #
5288 5288 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5289 5289 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5290 5290 # arrayAOA[:,2] = cosDirError
5291 5291 #
5292 5292 # azimuthAngle = arrayAOA[:,0]
5293 5293 # zenithAngle = arrayAOA[:,1]
5294 5294 #
5295 5295 # #Setting Error
5296 5296 # #Number 3: AOA not fesible
5297 5297 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5298 5298 # error[indInvalid] = 3
5299 5299 # #Number 4: Large difference in AOAs obtained from different antenna baselines
5300 5300 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5301 5301 # error[indInvalid] = 4
5302 5302 # return arrayAOA, error
5303 5303 #
5304 5304 # def __getDirectionCosines(self, arrayPhase, pairsList):
5305 5305 #
5306 5306 # #Initializing some variables
5307 5307 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5308 5308 # ang_aux = ang_aux.reshape(1,ang_aux.size)
5309 5309 #
5310 5310 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
5311 5311 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5312 5312 #
5313 5313 #
5314 5314 # for i in range(2):
5315 5315 # #First Estimation
5316 5316 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
5317 5317 # #Dealias
5318 5318 # indcsi = numpy.where(phi0_aux > numpy.pi)
5319 5319 # phi0_aux[indcsi] -= 2*numpy.pi
5320 5320 # indcsi = numpy.where(phi0_aux < -numpy.pi)
5321 5321 # phi0_aux[indcsi] += 2*numpy.pi
5322 5322 # #Direction Cosine 0
5323 5323 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
5324 5324 #
5325 5325 # #Most-Accurate Second Estimation
5326 5326 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
5327 5327 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5328 5328 # #Direction Cosine 1
5329 5329 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
5330 5330 #
5331 5331 # #Searching the correct Direction Cosine
5332 5332 # cosdir0_aux = cosdir0[:,i]
5333 5333 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5334 5334 # #Minimum Distance
5335 5335 # cosDiff = (cosdir1 - cosdir0_aux)**2
5336 5336 # indcos = cosDiff.argmin(axis = 1)
5337 5337 # #Saving Value obtained
5338 5338 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5339 5339 #
5340 5340 # return cosdir0, cosdir
5341 5341 #
5342 5342 # def __calculateAOA(self, cosdir, azimuth):
5343 5343 # cosdirX = cosdir[:,0]
5344 5344 # cosdirY = cosdir[:,1]
5345 5345 #
5346 5346 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5347 5347 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
5348 5348 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5349 5349 #
5350 5350 # return angles
5351 5351 #
5352 5352 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5353 5353 #
5354 5354 # Ramb = 375 #Ramb = c/(2*PRF)
5355 5355 # Re = 6371 #Earth Radius
5356 5356 # heights = numpy.zeros(Ranges.shape)
5357 5357 #
5358 5358 # R_aux = numpy.array([0,1,2])*Ramb
5359 5359 # R_aux = R_aux.reshape(1,R_aux.size)
5360 5360 #
5361 5361 # Ranges = Ranges.reshape(Ranges.size,1)
5362 5362 #
5363 5363 # Ri = Ranges + R_aux
5364 5364 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
5365 5365 #
5366 5366 # #Check if there is a height between 70 and 110 km
5367 5367 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
5368 5368 # ind_h = numpy.where(h_bool == 1)[0]
5369 5369 #
5370 5370 # hCorr = hi[ind_h, :]
5371 5371 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
5372 5372 #
5373 5373 # hCorr = hi[ind_hCorr]
5374 5374 # heights[ind_h] = hCorr
5375 5375 #
5376 5376 # #Setting Error
5377 5377 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
5378 5378 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
5379 5379 #
5380 5380 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
5381 5381 # error[indInvalid2] = 14
5382 5382 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
5383 5383 # error[indInvalid1] = 13
5384 5384 #
5385 5385 # return heights, error
5386 5386
5387 5387
5388 5388
5389 5389 class IGRFModel(Operation):
5390 5390 """Operation to calculate Geomagnetic parameters.
5391 5391
5392 5392 Parameters:
5393 5393 -----------
5394 5394 None
5395 5395
5396 5396 Example
5397 5397 --------
5398 5398
5399 5399 op = proc_unit.addOperation(name='IGRFModel', optype='other')
5400 5400
5401 5401 """
5402 5402
5403 5403 def __init__(self, **kwargs):
5404 5404
5405 5405 Operation.__init__(self, **kwargs)
5406 5406
5407 5407 self.aux=1
5408 5408
5409 5409 def run(self,dataOut):
5410 5410
5411 5411 try:
5412 5412 from schainpy.model.proc import mkfact_short_2020
5413 5413 except:
5414 5414 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
5415 5415
5416 5416 if self.aux==1:
5417 5417
5418 5418 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
5419 5419 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
5420 5420 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
5421 5421 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
5422 5422 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
5423 5423 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
5424 5424
5425 5425 self.aux=0
5426 5426
5427 5427 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
5428 5428 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5429 5429 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
5430 5430 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5431 5431 dataOut.thb=numpy.array(dataOut.thb,order='F')
5432 5432 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
5433 5433 dataOut.bki=numpy.array(dataOut.bki,order='F')
5434 5434
5435 5435 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
5436 5436
5437 5437 return dataOut
@@ -1,935 +1,935
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Spectra processing Unit and operations
6 6
7 7 Here you will find the processing unit `SpectraProc` and several operations
8 8 to work with Spectra data type
9 9 """
10 10
11 11 import time
12 12 import itertools
13 13
14 14 import numpy
15 15
16 16 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
17 17 from schainpy.model.data.jrodata import Spectra
18 18 from schainpy.model.data.jrodata import hildebrand_sekhon
19 19 from schainpy.utils import log
20 20
21 21
22 22 class SpectraProc(ProcessingUnit):
23 23
24 24 def __init__(self):
25 25
26 26 ProcessingUnit.__init__(self)
27 27
28 28 self.buffer = None
29 29 self.firstdatatime = None
30 30 self.profIndex = 0
31 31 self.dataOut = Spectra()
32 32 self.id_min = None
33 33 self.id_max = None
34 34 self.setupReq = False # Agregar a todas las unidades de proc
35 35
36 36 def __updateSpecFromVoltage(self):
37 37
38 38 self.dataOut.timeZone = self.dataIn.timeZone
39 39 self.dataOut.dstFlag = self.dataIn.dstFlag
40 40 self.dataOut.errorCount = self.dataIn.errorCount
41 41 self.dataOut.useLocalTime = self.dataIn.useLocalTime
42 42 try:
43 43 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
44 44 except:
45 45 pass
46 46 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
47 47 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
48 48 self.dataOut.channelList = self.dataIn.channelList
49 49 self.dataOut.heightList = self.dataIn.heightList
50 50 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
51 51 self.dataOut.nProfiles = self.dataOut.nFFTPoints
52 52 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
53 53 self.dataOut.utctime = self.firstdatatime
54 54 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
55 55 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
56 56 self.dataOut.flagShiftFFT = False
57 57 self.dataOut.nCohInt = self.dataIn.nCohInt
58 58 self.dataOut.nIncohInt = 1
59 59 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
60 60 self.dataOut.frequency = self.dataIn.frequency
61 61 self.dataOut.realtime = self.dataIn.realtime
62 62 self.dataOut.azimuth = self.dataIn.azimuth
63 63 self.dataOut.zenith = self.dataIn.zenith
64 64 self.dataOut.beam.codeList = self.dataIn.beam.codeList
65 65 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
66 66 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
67 67
68 68 def __getFft(self):
69 69 """
70 70 Convierte valores de Voltaje a Spectra
71 71
72 72 Affected:
73 73 self.dataOut.data_spc
74 74 self.dataOut.data_cspc
75 75 self.dataOut.data_dc
76 76 self.dataOut.heightList
77 77 self.profIndex
78 78 self.buffer
79 79 self.dataOut.flagNoData
80 80 """
81 81 fft_volt = numpy.fft.fft(
82 82 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
83 83 fft_volt = fft_volt.astype(numpy.dtype('complex'))
84 84 dc = fft_volt[:, 0, :]
85 85
86 86 # calculo de self-spectra
87 87 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
88 88 spc = fft_volt * numpy.conjugate(fft_volt)
89 89 spc = spc.real
90 90
91 91 blocksize = 0
92 92 blocksize += dc.size
93 93 blocksize += spc.size
94 94
95 95 cspc = None
96 96 pairIndex = 0
97 97 if self.dataOut.pairsList != None:
98 98 # calculo de cross-spectra
99 99 cspc = numpy.zeros(
100 100 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
101 101 for pair in self.dataOut.pairsList:
102 102 if pair[0] not in self.dataOut.channelList:
103 103 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
104 104 str(pair), str(self.dataOut.channelList)))
105 105 if pair[1] not in self.dataOut.channelList:
106 106 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
107 107 str(pair), str(self.dataOut.channelList)))
108 108
109 109 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
110 110 numpy.conjugate(fft_volt[pair[1], :, :])
111 111 pairIndex += 1
112 112 blocksize += cspc.size
113 113
114 114 self.dataOut.data_spc = spc
115 115 self.dataOut.data_cspc = cspc
116 116 self.dataOut.data_dc = dc
117 117 self.dataOut.blockSize = blocksize
118 118 self.dataOut.flagShiftFFT = False
119 119
120 120 def run(self, nProfiles=None, nFFTPoints=None, pairsList=None, ippFactor=None, shift_fft=False):
121 121
122 122 if self.dataIn.type == "Spectra":
123 123 self.dataOut.copy(self.dataIn)
124 124 if shift_fft:
125 125 # desplaza a la derecha en el eje 2 determinadas posiciones
126 126 shift = int(self.dataOut.nFFTPoints / 2)
127 127 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
128 128
129 129 if self.dataOut.data_cspc is not None:
130 130 # desplaza a la derecha en el eje 2 determinadas posiciones
131 131 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
132 132 if pairsList:
133 133 self.__selectPairs(pairsList)
134 134
135 135 elif self.dataIn.type == "Voltage":
136 136
137 137 self.dataOut.flagNoData = True
138 138
139 139 if nFFTPoints == None:
140 140 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
141 141
142 142 if nProfiles == None:
143 143 nProfiles = nFFTPoints
144 144
145 145 if ippFactor == None:
146 146 self.dataOut.ippFactor = 1
147 147
148 148 self.dataOut.nFFTPoints = nFFTPoints
149 149
150 150 if self.buffer is None:
151 151 self.buffer = numpy.zeros((self.dataIn.nChannels,
152 152 nProfiles,
153 153 self.dataIn.nHeights),
154 154 dtype='complex')
155 155
156 156 if self.dataIn.flagDataAsBlock:
157 157 nVoltProfiles = self.dataIn.data.shape[1]
158 158 if nVoltProfiles == nProfiles:
159 159 self.buffer = self.dataIn.data.copy()
160 160 self.profIndex = nVoltProfiles
161 161
162 162 elif nVoltProfiles < nProfiles:
163 163
164 164 if self.profIndex == 0:
165 165 self.id_min = 0
166 166 self.id_max = nVoltProfiles
167 167
168 168 self.buffer[:, self.id_min:self.id_max,
169 169 :] = self.dataIn.data
170 170 self.profIndex += nVoltProfiles
171 171 self.id_min += nVoltProfiles
172 172 self.id_max += nVoltProfiles
173 173 elif nVoltProfiles > nProfiles:
174 174 self.reader.bypass = True
175 175 if self.profIndex == 0:
176 176 self.id_min = 0
177 177 self.id_max = nProfiles
178 178
179 179 self.buffer = self.dataIn.data[:, self.id_min:self.id_max,:]
180 180 self.profIndex += nProfiles
181 181 self.id_min += nProfiles
182 182 self.id_max += nProfiles
183 183 if self.id_max == nVoltProfiles:
184 184 self.reader.bypass = False
185 185
186 186 else:
187 187 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
188 188 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
189 189 self.dataOut.flagNoData = True
190 190 else:
191 191 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
192 192 self.profIndex += 1
193 193
194 194 if self.firstdatatime == None:
195 195 self.firstdatatime = self.dataIn.utctime
196 196
197 197 if self.profIndex % nProfiles == 0:
198 198 self.__updateSpecFromVoltage()
199 199 if pairsList == None:
200 200 self.dataOut.pairsList = [pair for pair in itertools.combinations(self.dataOut.channelList, 2)]
201 201 else:
202 202 self.dataOut.pairsList = pairsList
203 203 self.__getFft()
204 204 self.dataOut.flagNoData = False
205 205 self.firstdatatime = None
206 206 if not self.reader.bypass:
207 207 self.profIndex = 0
208 208 else:
209 209 raise ValueError("The type of input object '%s' is not valid".format(
210 210 self.dataIn.type))
211 211
212 212 def __selectPairs(self, pairsList):
213 213
214 214 if not pairsList:
215 215 return
216 216
217 217 pairs = []
218 218 pairsIndex = []
219 219
220 220 for pair in pairsList:
221 221 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
222 222 continue
223 223 pairs.append(pair)
224 224 pairsIndex.append(pairs.index(pair))
225 225
226 226 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
227 227 self.dataOut.pairsList = pairs
228 228
229 229 return
230 230
231 231 def selectFFTs(self, minFFT, maxFFT):
232 232 """
233 233 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
234 234 minFFT<= FFT <= maxFFT
235 235 """
236 236
237 237 if (minFFT > maxFFT):
238 238 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
239 239
240 240 if (minFFT < self.dataOut.getFreqRange()[0]):
241 241 minFFT = self.dataOut.getFreqRange()[0]
242 242
243 243 if (maxFFT > self.dataOut.getFreqRange()[-1]):
244 244 maxFFT = self.dataOut.getFreqRange()[-1]
245 245
246 246 minIndex = 0
247 247 maxIndex = 0
248 248 FFTs = self.dataOut.getFreqRange()
249 249
250 250 inda = numpy.where(FFTs >= minFFT)
251 251 indb = numpy.where(FFTs <= maxFFT)
252 252
253 253 try:
254 254 minIndex = inda[0][0]
255 255 except:
256 256 minIndex = 0
257 257
258 258 try:
259 259 maxIndex = indb[0][-1]
260 260 except:
261 261 maxIndex = len(FFTs)
262 262
263 263 self.selectFFTsByIndex(minIndex, maxIndex)
264 264
265 265 return 1
266 266
267 267 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
268 268 newheis = numpy.where(
269 269 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
270 270
271 271 if hei_ref != None:
272 272 newheis = numpy.where(self.dataOut.heightList > hei_ref)
273 273
274 274 minIndex = min(newheis[0])
275 275 maxIndex = max(newheis[0])
276 276 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
277 277 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
278 278
279 279 # determina indices
280 280 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
281 281 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
282 282 avg_dB = 10 * \
283 283 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
284 284 beacon_dB = numpy.sort(avg_dB)[-nheis:]
285 285 beacon_heiIndexList = []
286 286 for val in avg_dB.tolist():
287 287 if val >= beacon_dB[0]:
288 288 beacon_heiIndexList.append(avg_dB.tolist().index(val))
289 289
290 290 # data_spc = data_spc[:,:,beacon_heiIndexList]
291 291 data_cspc = None
292 292 if self.dataOut.data_cspc is not None:
293 293 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
294 294 # data_cspc = data_cspc[:,:,beacon_heiIndexList]
295 295
296 296 data_dc = None
297 297 if self.dataOut.data_dc is not None:
298 298 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
299 299 # data_dc = data_dc[:,beacon_heiIndexList]
300 300
301 301 self.dataOut.data_spc = data_spc
302 302 self.dataOut.data_cspc = data_cspc
303 303 self.dataOut.data_dc = data_dc
304 304 self.dataOut.heightList = heightList
305 305 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
306 306
307 307 return 1
308 308
309 309 def selectFFTsByIndex(self, minIndex, maxIndex):
310 310 """
311 311
312 312 """
313 313
314 314 if (minIndex < 0) or (minIndex > maxIndex):
315 315 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
316 316
317 317 if (maxIndex >= self.dataOut.nProfiles):
318 318 maxIndex = self.dataOut.nProfiles - 1
319 319
320 320 # Spectra
321 321 data_spc = self.dataOut.data_spc[:, minIndex:maxIndex + 1, :]
322 322
323 323 data_cspc = None
324 324 if self.dataOut.data_cspc is not None:
325 325 data_cspc = self.dataOut.data_cspc[:, minIndex:maxIndex + 1, :]
326 326
327 327 data_dc = None
328 328 if self.dataOut.data_dc is not None:
329 329 data_dc = self.dataOut.data_dc[minIndex:maxIndex + 1, :]
330 330
331 331 self.dataOut.data_spc = data_spc
332 332 self.dataOut.data_cspc = data_cspc
333 333 self.dataOut.data_dc = data_dc
334 334
335 335 self.dataOut.ippSeconds = self.dataOut.ippSeconds * (self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
336 336 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
337 337 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
338 338
339 339 return 1
340 340
341 341 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
342 342 # validacion de rango
343 343 if minHei == None:
344 344 minHei = self.dataOut.heightList[0]
345 345
346 346 if maxHei == None:
347 347 maxHei = self.dataOut.heightList[-1]
348 348
349 349 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
350 350 print('minHei: %.2f is out of the heights range' % (minHei))
351 351 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
352 352 minHei = self.dataOut.heightList[0]
353 353
354 354 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
355 355 print('maxHei: %.2f is out of the heights range' % (maxHei))
356 356 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
357 357 maxHei = self.dataOut.heightList[-1]
358 358
359 359 # validacion de velocidades
360 360 velrange = self.dataOut.getVelRange(1)
361 361
362 362 if minVel == None:
363 363 minVel = velrange[0]
364 364
365 365 if maxVel == None:
366 366 maxVel = velrange[-1]
367 367
368 368 if (minVel < velrange[0]) or (minVel > maxVel):
369 369 print('minVel: %.2f is out of the velocity range' % (minVel))
370 370 print('minVel is setting to %.2f' % (velrange[0]))
371 371 minVel = velrange[0]
372 372
373 373 if (maxVel > velrange[-1]) or (maxVel < minVel):
374 374 print('maxVel: %.2f is out of the velocity range' % (maxVel))
375 375 print('maxVel is setting to %.2f' % (velrange[-1]))
376 376 maxVel = velrange[-1]
377 377
378 378 # seleccion de indices para rango
379 379 minIndex = 0
380 380 maxIndex = 0
381 381 heights = self.dataOut.heightList
382 382
383 383 inda = numpy.where(heights >= minHei)
384 384 indb = numpy.where(heights <= maxHei)
385 385
386 386 try:
387 387 minIndex = inda[0][0]
388 388 except:
389 389 minIndex = 0
390 390
391 391 try:
392 392 maxIndex = indb[0][-1]
393 393 except:
394 394 maxIndex = len(heights)
395 395
396 396 if (minIndex < 0) or (minIndex > maxIndex):
397 397 raise ValueError("some value in (%d,%d) is not valid" % (
398 398 minIndex, maxIndex))
399 399
400 400 if (maxIndex >= self.dataOut.nHeights):
401 401 maxIndex = self.dataOut.nHeights - 1
402 402
403 403 # seleccion de indices para velocidades
404 404 indminvel = numpy.where(velrange >= minVel)
405 405 indmaxvel = numpy.where(velrange <= maxVel)
406 406 try:
407 407 minIndexVel = indminvel[0][0]
408 408 except:
409 409 minIndexVel = 0
410 410
411 411 try:
412 412 maxIndexVel = indmaxvel[0][-1]
413 413 except:
414 414 maxIndexVel = len(velrange)
415 415
416 416 # seleccion del espectro
417 417 data_spc = self.dataOut.data_spc[:,
418 418 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
419 419 # estimacion de ruido
420 420 noise = numpy.zeros(self.dataOut.nChannels)
421 421
422 422 for channel in range(self.dataOut.nChannels):
423 423 daux = data_spc[channel, :, :]
424 424 sortdata = numpy.sort(daux, axis=None)
425 425 noise[channel] = hildebrand_sekhon(sortdata, self.dataOut.nIncohInt)
426 426
427 427 self.dataOut.noise_estimation = noise.copy()
428 428
429 429 return 1
430 430
431 431 class removeDC(Operation):
432 432
433 433 def run(self, dataOut, mode=2):
434 434 self.dataOut = dataOut
435 435 jspectra = self.dataOut.data_spc
436 436 jcspectra = self.dataOut.data_cspc
437 437
438 438 num_chan = jspectra.shape[0]
439 439 num_hei = jspectra.shape[2]
440 440
441 441 if jcspectra is not None:
442 442 jcspectraExist = True
443 443 num_pairs = jcspectra.shape[0]
444 444 else:
445 445 jcspectraExist = False
446 446
447 447 freq_dc = int(jspectra.shape[1] / 2)
448 448 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
449 449 ind_vel = ind_vel.astype(int)
450 450
451 451 if ind_vel[0] < 0:
452 452 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
453 453
454 454 if mode == 1:
455 455 jspectra[:, freq_dc, :] = (
456 456 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
457 457
458 458 if jcspectraExist:
459 459 jcspectra[:, freq_dc, :] = (
460 460 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
461 461
462 462 if mode == 2:
463 463
464 464 vel = numpy.array([-2, -1, 1, 2])
465 465 xx = numpy.zeros([4, 4])
466 466
467 467 for fil in range(4):
468 468 xx[fil, :] = vel[fil] ** numpy.asarray(list(range(4)))
469 469
470 470 xx_inv = numpy.linalg.inv(xx)
471 471 xx_aux = xx_inv[0, :]
472 472
473 473 for ich in range(num_chan):
474 474 yy = jspectra[ich, ind_vel, :]
475 475 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
476 476
477 477 junkid = jspectra[ich, freq_dc, :] <= 0
478 478 cjunkid = sum(junkid)
479 479
480 480 if cjunkid.any():
481 481 jspectra[ich, freq_dc, junkid.nonzero()] = (
482 482 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
483 483
484 484 if jcspectraExist:
485 485 for ip in range(num_pairs):
486 486 yy = jcspectra[ip, ind_vel, :]
487 487 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
488 488
489 489 self.dataOut.data_spc = jspectra
490 490 self.dataOut.data_cspc = jcspectra
491 491
492 492 return self.dataOut
493 493
494 494 class removeInterference(Operation):
495 495
496 496 def removeInterference2(self):
497 497
498 498 cspc = self.dataOut.data_cspc
499 499 spc = self.dataOut.data_spc
500 500 Heights = numpy.arange(cspc.shape[2])
501 501 realCspc = numpy.abs(cspc)
502 502
503 503 for i in range(cspc.shape[0]):
504 504 LinePower = numpy.sum(realCspc[i], axis=0)
505 505 Threshold = numpy.amax(LinePower) - numpy.sort(LinePower)[len(Heights) - int(len(Heights) * 0.1)]
506 506 SelectedHeights = Heights[ numpy.where(LinePower < Threshold) ]
507 507 InterferenceSum = numpy.sum(realCspc[i, :, SelectedHeights], axis=0)
508 508 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum) * 0.98)]
509 509 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum) * 0.99)]
510 510
511 511
512 512 InterferenceRange = numpy.where(([InterferenceSum > InterferenceThresholdMin])) # , InterferenceSum < InterferenceThresholdMax]) )
513 513 # InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
514 514 if len(InterferenceRange) < int(cspc.shape[1] * 0.3):
515 515 cspc[i, InterferenceRange, :] = numpy.NaN
516 516
517 517 self.dataOut.data_cspc = cspc
518 518
519 519 def removeInterference(self, interf=2, hei_interf=None, nhei_interf=None, offhei_interf=None):
520 520
521 521 jspectra = self.dataOut.data_spc
522 522 jcspectra = self.dataOut.data_cspc
523 523 jnoise = self.dataOut.getNoise()
524 524 num_incoh = self.dataOut.nIncohInt
525 525
526 526 num_channel = jspectra.shape[0]
527 527 num_prof = jspectra.shape[1]
528 528 num_hei = jspectra.shape[2]
529 529
530 530 # hei_interf
531 531 if hei_interf is None:
532 532 count_hei = int(num_hei / 2)
533 533 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
534 534 hei_interf = numpy.asarray(hei_interf)[0]
535 535 # nhei_interf
536 536 if (nhei_interf == None):
537 537 nhei_interf = 5
538 538 if (nhei_interf < 1):
539 539 nhei_interf = 1
540 540 if (nhei_interf > count_hei):
541 541 nhei_interf = count_hei
542 542 if (offhei_interf == None):
543 543 offhei_interf = 0
544 544
545 545 ind_hei = list(range(num_hei))
546 546 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
547 547 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
548 548 mask_prof = numpy.asarray(list(range(num_prof)))
549 549 num_mask_prof = mask_prof.size
550 550 comp_mask_prof = [0, num_prof / 2]
551 551
552 552 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
553 553 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
554 554 jnoise = numpy.nan
555 555 noise_exist = jnoise[0] < numpy.Inf
556 556
557 557 # Subrutina de Remocion de la Interferencia
558 558 for ich in range(num_channel):
559 559 # Se ordena los espectros segun su potencia (menor a mayor)
560 560 power = jspectra[ich, mask_prof, :]
561 561 power = power[:, hei_interf]
562 562 power = power.sum(axis=0)
563 563 psort = power.ravel().argsort()
564 564
565 565 # Se estima la interferencia promedio en los Espectros de Potencia empleando
566 566 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
567 567 offhei_interf, nhei_interf + offhei_interf))]]]
568 568
569 569 if noise_exist:
570 570 # tmp_noise = jnoise[ich] / num_prof
571 571 tmp_noise = jnoise[ich]
572 572 junkspc_interf = junkspc_interf - tmp_noise
573 573 # junkspc_interf[:,comp_mask_prof] = 0
574 574
575 575 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
576 576 jspc_interf = jspc_interf.transpose()
577 577 # Calculando el espectro de interferencia promedio
578 578 noiseid = numpy.where(
579 579 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
580 580 noiseid = noiseid[0]
581 581 cnoiseid = noiseid.size
582 582 interfid = numpy.where(
583 583 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
584 584 interfid = interfid[0]
585 585 cinterfid = interfid.size
586 586
587 587 if (cnoiseid > 0):
588 588 jspc_interf[noiseid] = 0
589 589
590 590 # Expandiendo los perfiles a limpiar
591 591 if (cinterfid > 0):
592 592 new_interfid = (
593 593 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
594 594 new_interfid = numpy.asarray(new_interfid)
595 595 new_interfid = {x for x in new_interfid}
596 596 new_interfid = numpy.array(list(new_interfid))
597 597 new_cinterfid = new_interfid.size
598 598 else:
599 599 new_cinterfid = 0
600 600
601 601 for ip in range(new_cinterfid):
602 602 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
603 603 jspc_interf[new_interfid[ip]
604 604 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
605 605
606 606 jspectra[ich, :, ind_hei] = jspectra[ich, :,
607 607 ind_hei] - jspc_interf # Corregir indices
608 608
609 609 # Removiendo la interferencia del punto de mayor interferencia
610 610 ListAux = jspc_interf[mask_prof].tolist()
611 611 maxid = ListAux.index(max(ListAux))
612 612
613 613 if cinterfid > 0:
614 614 for ip in range(cinterfid * (interf == 2) - 1):
615 615 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
616 616 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
617 617 cind = len(ind)
618 618
619 619 if (cind > 0):
620 620 jspectra[ich, interfid[ip], ind] = tmp_noise * \
621 621 (1 + (numpy.random.uniform(cind) - 0.5) /
622 622 numpy.sqrt(num_incoh))
623 623
624 624 ind = numpy.array([-2, -1, 1, 2])
625 625 xx = numpy.zeros([4, 4])
626 626
627 627 for id1 in range(4):
628 628 xx[:, id1] = ind[id1] ** numpy.asarray(list(range(4)))
629 629
630 630 xx_inv = numpy.linalg.inv(xx)
631 631 xx = xx_inv[:, 0]
632 632 ind = (ind + maxid + num_mask_prof) % num_mask_prof
633 633 yy = jspectra[ich, mask_prof[ind], :]
634 634 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
635 635 yy.transpose(), xx)
636 636
637 637 indAux = (jspectra[ich, :, :] < tmp_noise *
638 638 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
639 639 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
640 640 (1 - 1 / numpy.sqrt(num_incoh))
641 641
642 642 # Remocion de Interferencia en el Cross Spectra
643 643 if jcspectra is None:
644 644 return jspectra, jcspectra
645 645 num_pairs = int(jcspectra.size / (num_prof * num_hei))
646 646 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
647 647
648 648 for ip in range(num_pairs):
649 649
650 650 #-------------------------------------------
651 651
652 652 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
653 653 cspower = cspower[:, hei_interf]
654 654 cspower = cspower.sum(axis=0)
655 655
656 656 cspsort = cspower.ravel().argsort()
657 657 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
658 658 offhei_interf, nhei_interf + offhei_interf))]]]
659 659 junkcspc_interf = junkcspc_interf.transpose()
660 660 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
661 661
662 662 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
663 663
664 664 median_real = int(numpy.median(numpy.real(
665 665 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
666 666 median_imag = int(numpy.median(numpy.imag(
667 667 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
668 668 comp_mask_prof = [int(e) for e in comp_mask_prof]
669 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
669 junkcspc_interf[comp_mask_prof, :] = complex(
670 670 median_real, median_imag)
671 671
672 672 for iprof in range(num_prof):
673 673 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
674 674 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
675 675
676 676 # Removiendo la Interferencia
677 677 jcspectra[ip, :, ind_hei] = jcspectra[ip,
678 678 :, ind_hei] - jcspc_interf
679 679
680 680 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
681 681 maxid = ListAux.index(max(ListAux))
682 682
683 683 ind = numpy.array([-2, -1, 1, 2])
684 684 xx = numpy.zeros([4, 4])
685 685
686 686 for id1 in range(4):
687 687 xx[:, id1] = ind[id1] ** numpy.asarray(list(range(4)))
688 688
689 689 xx_inv = numpy.linalg.inv(xx)
690 690 xx = xx_inv[:, 0]
691 691
692 692 ind = (ind + maxid + num_mask_prof) % num_mask_prof
693 693 yy = jcspectra[ip, mask_prof[ind], :]
694 694 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
695 695
696 696 # Guardar Resultados
697 697 self.dataOut.data_spc = jspectra
698 698 self.dataOut.data_cspc = jcspectra
699 699
700 700 return 1
701 701
702 702 def run(self, dataOut, interf=2, hei_interf=None, nhei_interf=None, offhei_interf=None, mode=1):
703 703
704 704 self.dataOut = dataOut
705 705
706 706 if mode == 1:
707 707 self.removeInterference(interf=2, hei_interf=None, nhei_interf=None, offhei_interf=None)
708 708 elif mode == 2:
709 709 self.removeInterference2()
710 710
711 711 return self.dataOut
712 712
713 713
714 714 class deflip(Operation):
715 715
716 716 def run(self, dataOut):
717 717 # arreglo 1: (num_chan, num_profiles, num_heights)
718 718 self.dataOut = dataOut
719 719
720 720 # JULIA-oblicua, indice 2
721 721 # arreglo 2: (num_profiles, num_heights)
722 722 jspectra = self.dataOut.data_spc[2]
723 723 jspectra_tmp=numpy.zeros(jspectra.shape)
724 724 num_profiles=jspectra.shape[0]
725 725 freq_dc = int(num_profiles / 2)
726 726 # Flip con for
727 727 for j in range(num_profiles):
728 728 jspectra_tmp[num_profiles-j-1]= jspectra[j]
729 729 # Intercambio perfil de DC con perfil inmediato anterior
730 730 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
731 731 jspectra_tmp[freq_dc]= jspectra[freq_dc]
732 732 # canal modificado es re-escrito en el arreglo de canales
733 733 self.dataOut.data_spc[2] = jspectra_tmp
734 734
735 735 return self.dataOut
736 736
737 737
738 738 class IncohInt(Operation):
739 739
740 740 __profIndex = 0
741 741 __withOverapping = False
742 742
743 743 __byTime = False
744 744 __initime = None
745 745 __lastdatatime = None
746 746 __integrationtime = None
747 747
748 748 __buffer_spc = None
749 749 __buffer_cspc = None
750 750 __buffer_dc = None
751 751
752 752 __dataReady = False
753 753
754 754 __timeInterval = None
755 755
756 756 n = None
757 757
758 758 def __init__(self):
759 759
760 760 Operation.__init__(self)
761 761
762 762 def setup(self, n=None, timeInterval=None, overlapping=False):
763 763 """
764 764 Set the parameters of the integration class.
765 765
766 766 Inputs:
767 767
768 768 n : Number of coherent integrations
769 769 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
770 770 overlapping :
771 771
772 772 """
773 773
774 774 self.__initime = None
775 775 self.__lastdatatime = 0
776 776
777 777 self.__buffer_spc = 0
778 778 self.__buffer_cspc = 0
779 779 self.__buffer_dc = 0
780 780
781 781 self.__profIndex = 0
782 782 self.__dataReady = False
783 783 self.__byTime = False
784 784
785 785 if n is None and timeInterval is None:
786 786 raise ValueError("n or timeInterval should be specified ...")
787 787
788 788 if n is not None:
789 789 self.n = int(n)
790 790 else:
791 791
792 792 self.__integrationtime = int(timeInterval)
793 793 self.n = None
794 794 self.__byTime = True
795 795
796 796 def putData(self, data_spc, data_cspc, data_dc):
797 797 """
798 798 Add a profile to the __buffer_spc and increase in one the __profileIndex
799 799
800 800 """
801 801
802 802 self.__buffer_spc += data_spc
803 803
804 804 if data_cspc is None:
805 805 self.__buffer_cspc = None
806 806 else:
807 807 self.__buffer_cspc += data_cspc
808 808
809 809 if data_dc is None:
810 810 self.__buffer_dc = None
811 811 else:
812 812 self.__buffer_dc += data_dc
813 813
814 814 self.__profIndex += 1
815 815
816 816 return
817 817
818 818 def pushData(self):
819 819 """
820 820 Return the sum of the last profiles and the profiles used in the sum.
821 821
822 822 Affected:
823 823
824 824 self.__profileIndex
825 825
826 826 """
827 827
828 828 data_spc = self.__buffer_spc
829 829 data_cspc = self.__buffer_cspc
830 830 data_dc = self.__buffer_dc
831 831 n = self.__profIndex
832 832
833 833 self.__buffer_spc = 0
834 834 self.__buffer_cspc = 0
835 835 self.__buffer_dc = 0
836 836 self.__profIndex = 0
837 837
838 838 return data_spc, data_cspc, data_dc, n
839 839
840 840 def byProfiles(self, *args):
841 841
842 842 self.__dataReady = False
843 843 avgdata_spc = None
844 844 avgdata_cspc = None
845 845 avgdata_dc = None
846 846
847 847 self.putData(*args)
848 848
849 849 if self.__profIndex == self.n:
850 850
851 851 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
852 852 self.n = n
853 853 self.__dataReady = True
854 854
855 855 return avgdata_spc, avgdata_cspc, avgdata_dc
856 856
857 857 def byTime(self, datatime, *args):
858 858
859 859 self.__dataReady = False
860 860 avgdata_spc = None
861 861 avgdata_cspc = None
862 862 avgdata_dc = None
863 863
864 864 self.putData(*args)
865 865
866 866 if (datatime - self.__initime) >= self.__integrationtime:
867 867 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
868 868 self.n = n
869 869 self.__dataReady = True
870 870
871 871 return avgdata_spc, avgdata_cspc, avgdata_dc
872 872
873 873 def integrate(self, datatime, *args):
874 874
875 875 if self.__profIndex == 0:
876 876 self.__initime = datatime
877 877
878 878 if self.__byTime:
879 879 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
880 880 datatime, *args)
881 881 else:
882 882 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
883 883
884 884 if not self.__dataReady:
885 885 return None, None, None, None
886 886
887 887 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
888 888
889 889 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
890 890 if n == 1:
891 891 return dataOut
892 892
893 893 dataOut.flagNoData = True
894 894
895 895 if not self.isConfig:
896 896 self.setup(n, timeInterval, overlapping)
897 897 self.isConfig = True
898 898
899 899 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
900 900 dataOut.data_spc,
901 901 dataOut.data_cspc,
902 902 dataOut.data_dc)
903 903
904 904 if self.__dataReady:
905 905
906 906 dataOut.data_spc = avgdata_spc
907 907 dataOut.data_cspc = avgdata_cspc
908 908 dataOut.data_dc = avgdata_dc
909 909 dataOut.nIncohInt *= self.n
910 910 dataOut.utctime = avgdatatime
911 911 dataOut.flagNoData = False
912 912
913 913 return dataOut
914 914
915 915 class dopplerFlip(Operation):
916 916
917 917 def run(self, dataOut):
918 918 # arreglo 1: (num_chan, num_profiles, num_heights)
919 919 self.dataOut = dataOut
920 920 # JULIA-oblicua, indice 2
921 921 # arreglo 2: (num_profiles, num_heights)
922 922 jspectra = self.dataOut.data_spc[2]
923 923 jspectra_tmp = numpy.zeros(jspectra.shape)
924 924 num_profiles = jspectra.shape[0]
925 925 freq_dc = int(num_profiles / 2)
926 926 # Flip con for
927 927 for j in range(num_profiles):
928 928 jspectra_tmp[num_profiles - j - 1] = jspectra[j]
929 929 # Intercambio perfil de DC con perfil inmediato anterior
930 930 jspectra_tmp[freq_dc - 1] = jspectra[freq_dc - 1]
931 931 jspectra_tmp[freq_dc] = jspectra[freq_dc]
932 932 # canal modificado es re-escrito en el arreglo de canales
933 933 self.dataOut.data_spc[2] = jspectra_tmp
934 934
935 935 return self.dataOut
@@ -1,736 +1,736
1 1 import numpy
2 2
3 3 from .jroproc_base import ProcessingUnit, Operation
4 4 from schainpy.model.data.jrodata import Spectra
5 5 from schainpy.model.data.jrodata import hildebrand_sekhon
6 6
7 7 class SpectraAFCProc(ProcessingUnit):
8 8
9 9 def __init__(self, **kwargs):
10 10
11 11 ProcessingUnit.__init__(self, **kwargs)
12 12
13 13 self.buffer = None
14 14 self.firstdatatime = None
15 15 self.profIndex = 0
16 16 self.dataOut = Spectra()
17 17 self.id_min = None
18 18 self.id_max = None
19 19
20 20 def __updateSpecFromVoltage(self):
21 21
22 22 self.dataOut.plotting = "spectra_acf"
23 23
24 24 self.dataOut.timeZone = self.dataIn.timeZone
25 25 self.dataOut.dstFlag = self.dataIn.dstFlag
26 26 self.dataOut.errorCount = self.dataIn.errorCount
27 27 self.dataOut.useLocalTime = self.dataIn.useLocalTime
28 28
29 29 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
30 30 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
31 31 self.dataOut.ippSeconds = self.dataIn.getDeltaH() * (10 ** -6) / 0.15
32 32
33 33 self.dataOut.channelList = self.dataIn.channelList
34 34 self.dataOut.heightList = self.dataIn.heightList
35 35 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
36 36
37 37 self.dataOut.nBaud = self.dataIn.nBaud
38 38 self.dataOut.nCode = self.dataIn.nCode
39 39 self.dataOut.code = self.dataIn.code
40 40 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
41 41
42 42 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
43 43 self.dataOut.utctime = self.firstdatatime
44 44 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData # asumo q la data esta decodificada
45 45 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData # asumo q la data esta sin flip
46 46 self.dataOut.flagShiftFFT = False
47 47
48 48 self.dataOut.nCohInt = self.dataIn.nCohInt
49 49 self.dataOut.nIncohInt = 1
50 50
51 51 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
52 52
53 53 self.dataOut.frequency = self.dataIn.frequency
54 54 self.dataOut.realtime = self.dataIn.realtime
55 55
56 56 self.dataOut.azimuth = self.dataIn.azimuth
57 57 self.dataOut.zenith = self.dataIn.zenith
58 58
59 59 self.dataOut.beam.codeList = self.dataIn.beam.codeList
60 60 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
61 61 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
62 62
63 63 def __decodeData(self, nProfiles, code):
64 64
65 65 if code is None:
66 66 return
67 67
68 68 for i in range(nProfiles):
69 69 self.buffer[:, i, :] = self.buffer[:, i, :] * code[0][i]
70 70
71 71 def __getFft(self):
72 72 """
73 73 Convierte valores de Voltaje a Spectra
74 74
75 75 Affected:
76 76 self.dataOut.data_spc
77 77 self.dataOut.data_cspc
78 78 self.dataOut.data_dc
79 79 self.dataOut.heightList
80 80 self.profIndex
81 81 self.buffer
82 82 self.dataOut.flagNoData
83 83 """
84 84 nsegments = self.dataOut.nHeights
85 85
86 86 _fft_buffer = numpy.zeros((self.dataOut.nChannels, self.dataOut.nProfiles, nsegments), dtype='complex')
87 87
88 88 for i in range(nsegments):
89 89 try:
90 90 _fft_buffer[:, :, i] = self.buffer[:, i:i + self.dataOut.nProfiles]
91 91
92 92 if self.code is not None:
93 93 _fft_buffer[:, :, i] = _fft_buffer[:, :, i] * self.code[0]
94 94 except:
95 95 pass
96 96
97 97 fft_volt = numpy.fft.fft(_fft_buffer, n=self.dataOut.nFFTPoints, axis=1)
98 98 fft_volt = fft_volt.astype(numpy.dtype('complex'))
99 99 dc = fft_volt[:, 0, :]
100 100
101 101 # calculo de self-spectra
102 102 # fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
103 103 spc = fft_volt * numpy.conjugate(fft_volt)
104 104
105 105 data = numpy.fft.ifft(spc, axis=1)
106 106 data = numpy.fft.fftshift(data, axes=(1,))
107 107
108 108 spc = data
109 109
110 110 blocksize = 0
111 111 blocksize += dc.size
112 112 blocksize += spc.size
113 113
114 114 cspc = None
115 115 pairIndex = 0
116 116
117 117 if self.dataOut.pairsList != None:
118 118 # calculo de cross-spectra
119 119 cspc = numpy.zeros((self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
120 120 for pair in self.dataOut.pairsList:
121 121 if pair[0] not in self.dataOut.channelList:
122 122 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (str(pair), str(self.dataOut.channelList)))
123 123 if pair[1] not in self.dataOut.channelList:
124 124 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (str(pair), str(self.dataOut.channelList)))
125 125
126 126 chan_index0 = self.dataOut.channelList.index(pair[0])
127 127 chan_index1 = self.dataOut.channelList.index(pair[1])
128 128
129 129 cspc[pairIndex, :, :] = fft_volt[chan_index0, :, :] * numpy.conjugate(fft_volt[chan_index1, :, :])
130 130 pairIndex += 1
131 131 blocksize += cspc.size
132 132
133 133 self.dataOut.data_spc = spc
134 134 self.dataOut.data_cspc = cspc
135 135 self.dataOut.data_dc = dc
136 136 self.dataOut.blockSize = blocksize
137 137 self.dataOut.flagShiftFFT = True
138 138
139 139 def run(self, nProfiles=None, nFFTPoints=None, pairsList=[], code=None, nCode=1, nBaud=1):
140 140
141 141 self.dataOut.flagNoData = True
142 142
143 143 if code is not None:
144 144 self.code = numpy.array(code).reshape(nCode, nBaud)
145 145 else:
146 146 self.code = None
147 147
148 148 if self.dataIn.type == "Voltage":
149 149
150 150 if nFFTPoints == None:
151 151 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
152 152
153 153 if nProfiles == None:
154 154 nProfiles = nFFTPoints
155 155
156 156 self.dataOut.ippFactor = 1
157 157
158 158 self.dataOut.nFFTPoints = nFFTPoints
159 159 self.dataOut.nProfiles = nProfiles
160 160 self.dataOut.pairsList = pairsList
161 161
162 162 # if self.buffer is None:
163 163 # self.buffer = numpy.zeros( (self.dataIn.nChannels, nProfiles, self.dataIn.nHeights),
164 164 # dtype='complex')
165 165
166 166 if not self.dataIn.flagDataAsBlock:
167 167 self.buffer = self.dataIn.data.copy()
168 168
169 169 # for i in range(self.dataIn.nHeights):
170 170 # self.buffer[:, self.profIndex, self.profIndex:] = voltage_data[:,:self.dataIn.nHeights - self.profIndex]
171 171 #
172 172 # self.profIndex += 1
173 173
174 174 else:
175 175 raise ValueError("")
176 176
177 177 self.firstdatatime = self.dataIn.utctime
178 178
179 179 self.profIndex == nProfiles
180 180
181 181 self.__updateSpecFromVoltage()
182 182
183 183 self.__getFft()
184 184
185 185 self.dataOut.flagNoData = False
186 186
187 187 return True
188 188
189 189 raise ValueError("The type of input object '%s' is not valid" % (self.dataIn.type))
190 190
191 191 def __selectPairs(self, pairsList):
192 192
193 193 if channelList == None:
194 194 return
195 195
196 196 pairsIndexListSelected = []
197 197
198 198 for thisPair in pairsList:
199 199
200 200 if thisPair not in self.dataOut.pairsList:
201 201 continue
202 202
203 203 pairIndex = self.dataOut.pairsList.index(thisPair)
204 204
205 205 pairsIndexListSelected.append(pairIndex)
206 206
207 207 if not pairsIndexListSelected:
208 208 self.dataOut.data_cspc = None
209 209 self.dataOut.pairsList = []
210 210 return
211 211
212 212 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
213 213 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
214 214
215 215 return
216 216
217 217 def __selectPairsByChannel(self, channelList=None):
218 218
219 219 if channelList == None:
220 220 return
221 221
222 222 pairsIndexListSelected = []
223 223 for pairIndex in self.dataOut.pairsIndexList:
224 224 # First pair
225 225 if self.dataOut.pairsList[pairIndex][0] not in channelList:
226 226 continue
227 227 # Second pair
228 228 if self.dataOut.pairsList[pairIndex][1] not in channelList:
229 229 continue
230 230
231 231 pairsIndexListSelected.append(pairIndex)
232 232
233 233 if not pairsIndexListSelected:
234 234 self.dataOut.data_cspc = None
235 235 self.dataOut.pairsList = []
236 236 return
237 237
238 238 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
239 239 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
240 240
241 241 return
242 242
243 243 def selectChannels(self, channelList):
244 244
245 245 channelIndexList = []
246 246
247 247 for channel in channelList:
248 248 if channel not in self.dataOut.channelList:
249 249 raise ValueError("Error selecting channels, Channel %d is not valid.\nAvailable channels = %s" % (channel, str(self.dataOut.channelList)))
250 250
251 251 index = self.dataOut.channelList.index(channel)
252 252 channelIndexList.append(index)
253 253
254 254 self.selectChannelsByIndex(channelIndexList)
255 255
256 256 def selectChannelsByIndex(self, channelIndexList):
257 257 """
258 258 Selecciona un bloque de datos en base a canales segun el channelIndexList
259 259
260 260 Input:
261 261 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
262 262
263 263 Affected:
264 264 self.dataOut.data_spc
265 265 self.dataOut.channelIndexList
266 266 self.dataOut.nChannels
267 267
268 268 Return:
269 269 None
270 270 """
271 271
272 272 for channelIndex in channelIndexList:
273 273 if channelIndex not in self.dataOut.channelIndexList:
274 274 raise ValueError("Error selecting channels: The value %d in channelIndexList is not valid.\nAvailable channel indexes = " % (channelIndex, self.dataOut.channelIndexList))
275 275
276 276 # nChannels = len(channelIndexList)
277 277
278 278 data_spc = self.dataOut.data_spc[channelIndexList, :]
279 279 data_dc = self.dataOut.data_dc[channelIndexList, :]
280 280
281 281 self.dataOut.data_spc = data_spc
282 282 self.dataOut.data_dc = data_dc
283 283
284 284 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
285 285 # self.dataOut.nChannels = nChannels
286 286
287 287 self.__selectPairsByChannel(self.dataOut.channelList)
288 288
289 289 return 1
290 290
291 291 def selectHeights(self, minHei, maxHei):
292 292 """
293 293 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
294 294 minHei <= height <= maxHei
295 295
296 296 Input:
297 297 minHei : valor minimo de altura a considerar
298 298 maxHei : valor maximo de altura a considerar
299 299
300 300 Affected:
301 301 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
302 302
303 303 Return:
304 304 1 si el metodo se ejecuto con exito caso contrario devuelve 0
305 305 """
306 306
307 307 if (minHei > maxHei):
308 308 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei))
309 309
310 310 if (minHei < self.dataOut.heightList[0]):
311 311 minHei = self.dataOut.heightList[0]
312 312
313 313 if (maxHei > self.dataOut.heightList[-1]):
314 314 maxHei = self.dataOut.heightList[-1]
315 315
316 316 minIndex = 0
317 317 maxIndex = 0
318 318 heights = self.dataOut.heightList
319 319
320 320 inda = numpy.where(heights >= minHei)
321 321 indb = numpy.where(heights <= maxHei)
322 322
323 323 try:
324 324 minIndex = inda[0][0]
325 325 except:
326 326 minIndex = 0
327 327
328 328 try:
329 329 maxIndex = indb[0][-1]
330 330 except:
331 331 maxIndex = len(heights)
332 332
333 333 self.selectHeightsByIndex(minIndex, maxIndex)
334 334
335 335 return 1
336 336
337 337 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
338 338 newheis = numpy.where(self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
339 339
340 340 if hei_ref != None:
341 341 newheis = numpy.where(self.dataOut.heightList > hei_ref)
342 342
343 343 minIndex = min(newheis[0])
344 344 maxIndex = max(newheis[0])
345 345 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
346 346 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
347 347
348 348 # determina indices
349 349 nheis = int(self.dataOut.radarControllerHeaderObj.txB / (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
350 350 avg_dB = 10 * numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
351 351 beacon_dB = numpy.sort(avg_dB)[-nheis:]
352 352 beacon_heiIndexList = []
353 353 for val in avg_dB.tolist():
354 354 if val >= beacon_dB[0]:
355 355 beacon_heiIndexList.append(avg_dB.tolist().index(val))
356 356
357 357 # data_spc = data_spc[:,:,beacon_heiIndexList]
358 358 data_cspc = None
359 359 if self.dataOut.data_cspc is not None:
360 360 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
361 361 # data_cspc = data_cspc[:,:,beacon_heiIndexList]
362 362
363 363 data_dc = None
364 364 if self.dataOut.data_dc is not None:
365 365 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
366 366 # data_dc = data_dc[:,beacon_heiIndexList]
367 367
368 368 self.dataOut.data_spc = data_spc
369 369 self.dataOut.data_cspc = data_cspc
370 370 self.dataOut.data_dc = data_dc
371 371 self.dataOut.heightList = heightList
372 372 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
373 373
374 374 return 1
375 375
376 376
377 377 def selectHeightsByIndex(self, minIndex, maxIndex):
378 378 """
379 379 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
380 380 minIndex <= index <= maxIndex
381 381
382 382 Input:
383 383 minIndex : valor de indice minimo de altura a considerar
384 384 maxIndex : valor de indice maximo de altura a considerar
385 385
386 386 Affected:
387 387 self.dataOut.data_spc
388 388 self.dataOut.data_cspc
389 389 self.dataOut.data_dc
390 390 self.dataOut.heightList
391 391
392 392 Return:
393 393 1 si el metodo se ejecuto con exito caso contrario devuelve 0
394 394 """
395 395
396 396 if (minIndex < 0) or (minIndex > maxIndex):
397 397 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
398 398
399 399 if (maxIndex >= self.dataOut.nHeights):
400 400 maxIndex = self.dataOut.nHeights - 1
401 401
402 402 # Spectra
403 403 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
404 404
405 405 data_cspc = None
406 406 if self.dataOut.data_cspc is not None:
407 407 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
408 408
409 409 data_dc = None
410 410 if self.dataOut.data_dc is not None:
411 411 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
412 412
413 413 self.dataOut.data_spc = data_spc
414 414 self.dataOut.data_cspc = data_cspc
415 415 self.dataOut.data_dc = data_dc
416 416
417 417 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
418 418
419 419 return 1
420 420
421 421 def removeDC(self, mode=2):
422 422 jspectra = self.dataOut.data_spc
423 423 jcspectra = self.dataOut.data_cspc
424 424
425 425
426 426 num_chan = jspectra.shape[0]
427 427 num_hei = jspectra.shape[2]
428 428
429 429 if jcspectra is not None:
430 430 jcspectraExist = True
431 431 num_pairs = jcspectra.shape[0]
432 432 else: jcspectraExist = False
433 433
434 434 freq_dc = jspectra.shape[1] / 2
435 435 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
436 436
437 437 if ind_vel[0] < 0:
438 438 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
439 439
440 440 if mode == 1:
441 441 jspectra[:, freq_dc, :] = (jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
442 442
443 443 if jcspectraExist:
444 444 jcspectra[:, freq_dc, :] = (jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
445 445
446 446 if mode == 2:
447 447
448 448 vel = numpy.array([-2, -1, 1, 2])
449 449 xx = numpy.zeros([4, 4])
450 450
451 451 for fil in range(4):
452 452 xx[fil, :] = vel[fil] ** numpy.asarray(list(range(4)))
453 453
454 454 xx_inv = numpy.linalg.inv(xx)
455 455 xx_aux = xx_inv[0, :]
456 456
457 457 for ich in range(num_chan):
458 458 yy = jspectra[ich, ind_vel, :]
459 459 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
460 460
461 461 junkid = jspectra[ich, freq_dc, :] <= 0
462 462 cjunkid = sum(junkid)
463 463
464 464 if cjunkid.any():
465 465 jspectra[ich, freq_dc, junkid.nonzero()] = (jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
466 466
467 467 if jcspectraExist:
468 468 for ip in range(num_pairs):
469 469 yy = jcspectra[ip, ind_vel, :]
470 470 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
471 471
472 472
473 473 self.dataOut.data_spc = jspectra
474 474 self.dataOut.data_cspc = jcspectra
475 475
476 476 return 1
477 477
478 478 def removeInterference(self, interf=2, hei_interf=None, nhei_interf=None, offhei_interf=None):
479 479
480 480 jspectra = self.dataOut.data_spc
481 481 jcspectra = self.dataOut.data_cspc
482 482 jnoise = self.dataOut.getNoise()
483 483 num_incoh = self.dataOut.nIncohInt
484 484
485 485 num_channel = jspectra.shape[0]
486 486 num_prof = jspectra.shape[1]
487 487 num_hei = jspectra.shape[2]
488 488
489 489 # hei_interf
490 490 if hei_interf is None:
491 491 count_hei = num_hei / 2 # Como es entero no importa
492 492 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
493 493 hei_interf = numpy.asarray(hei_interf)[0]
494 494 # nhei_interf
495 495 if (nhei_interf == None):
496 496 nhei_interf = 5
497 497 if (nhei_interf < 1):
498 498 nhei_interf = 1
499 499 if (nhei_interf > count_hei):
500 500 nhei_interf = count_hei
501 501 if (offhei_interf == None):
502 502 offhei_interf = 0
503 503
504 504 ind_hei = list(range(num_hei))
505 505 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
506 506 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
507 507 mask_prof = numpy.asarray(list(range(num_prof)))
508 508 num_mask_prof = mask_prof.size
509 509 comp_mask_prof = [0, num_prof / 2]
510 510
511 511
512 512 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
513 513 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
514 514 jnoise = numpy.nan
515 515 noise_exist = jnoise[0] < numpy.Inf
516 516
517 517 # Subrutina de Remocion de la Interferencia
518 518 for ich in range(num_channel):
519 519 # Se ordena los espectros segun su potencia (menor a mayor)
520 520 power = jspectra[ich, mask_prof, :]
521 521 power = power[:, hei_interf]
522 522 power = power.sum(axis=0)
523 523 psort = power.ravel().argsort()
524 524
525 525 # Se estima la interferencia promedio en los Espectros de Potencia empleando
526 526 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(offhei_interf, nhei_interf + offhei_interf))]]]
527 527
528 528 if noise_exist:
529 529 # tmp_noise = jnoise[ich] / num_prof
530 530 tmp_noise = jnoise[ich]
531 531 junkspc_interf = junkspc_interf - tmp_noise
532 532 # junkspc_interf[:,comp_mask_prof] = 0
533 533
534 534 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
535 535 jspc_interf = jspc_interf.transpose()
536 536 # Calculando el espectro de interferencia promedio
537 537 noiseid = numpy.where(jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
538 538 noiseid = noiseid[0]
539 539 cnoiseid = noiseid.size
540 540 interfid = numpy.where(jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
541 541 interfid = interfid[0]
542 542 cinterfid = interfid.size
543 543
544 544 if (cnoiseid > 0): jspc_interf[noiseid] = 0
545 545
546 546 # Expandiendo los perfiles a limpiar
547 547 if (cinterfid > 0):
548 548 new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
549 549 new_interfid = numpy.asarray(new_interfid)
550 550 new_interfid = {x for x in new_interfid}
551 551 new_interfid = numpy.array(list(new_interfid))
552 552 new_cinterfid = new_interfid.size
553 553 else: new_cinterfid = 0
554 554
555 555 for ip in range(new_cinterfid):
556 556 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
557 557 jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf / 2], new_interfid[ip]]
558 558
559 559
560 560 jspectra[ich, :, ind_hei] = jspectra[ich, :, ind_hei] - jspc_interf # Corregir indices
561 561
562 562 # Removiendo la interferencia del punto de mayor interferencia
563 563 ListAux = jspc_interf[mask_prof].tolist()
564 564 maxid = ListAux.index(max(ListAux))
565 565
566 566
567 567 if cinterfid > 0:
568 568 for ip in range(cinterfid * (interf == 2) - 1):
569 569 ind = (jspectra[ich, interfid[ip], :] < tmp_noise * (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
570 570 cind = len(ind)
571 571
572 572 if (cind > 0):
573 573 jspectra[ich, interfid[ip], ind] = tmp_noise * (1 + (numpy.random.uniform(cind) - 0.5) / numpy.sqrt(num_incoh))
574 574
575 575 ind = numpy.array([-2, -1, 1, 2])
576 576 xx = numpy.zeros([4, 4])
577 577
578 578 for id1 in range(4):
579 579 xx[:, id1] = ind[id1] ** numpy.asarray(list(range(4)))
580 580
581 581 xx_inv = numpy.linalg.inv(xx)
582 582 xx = xx_inv[:, 0]
583 583 ind = (ind + maxid + num_mask_prof) % num_mask_prof
584 584 yy = jspectra[ich, mask_prof[ind], :]
585 585 jspectra[ich, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
586 586
587 587
588 588 indAux = (jspectra[ich, :, :] < tmp_noise * (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
589 589 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * (1 - 1 / numpy.sqrt(num_incoh))
590 590
591 591 # Remocion de Interferencia en el Cross Spectra
592 592 if jcspectra is None: return jspectra, jcspectra
593 593 num_pairs = jcspectra.size / (num_prof * num_hei)
594 594 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
595 595
596 596 for ip in range(num_pairs):
597 597
598 598 #-------------------------------------------
599 599
600 600 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
601 601 cspower = cspower[:, hei_interf]
602 602 cspower = cspower.sum(axis=0)
603 603
604 604 cspsort = cspower.ravel().argsort()
605 605 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(offhei_interf, nhei_interf + offhei_interf))]]]
606 606 junkcspc_interf = junkcspc_interf.transpose()
607 607 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
608 608
609 609 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
610 610
611 611 median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[list(range(3 * num_prof / 4))]], :]))
612 612 median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[list(range(3 * num_prof / 4))]], :]))
613 junkcspc_interf[comp_mask_prof, :] = numpy.complex(median_real, median_imag)
613 junkcspc_interf[comp_mask_prof, :] = complex(median_real, median_imag)
614 614
615 615 for iprof in range(num_prof):
616 616 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
617 617 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf / 2]]
618 618
619 619 # Removiendo la Interferencia
620 620 jcspectra[ip, :, ind_hei] = jcspectra[ip, :, ind_hei] - jcspc_interf
621 621
622 622 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
623 623 maxid = ListAux.index(max(ListAux))
624 624
625 625 ind = numpy.array([-2, -1, 1, 2])
626 626 xx = numpy.zeros([4, 4])
627 627
628 628 for id1 in range(4):
629 629 xx[:, id1] = ind[id1] ** numpy.asarray(list(range(4)))
630 630
631 631 xx_inv = numpy.linalg.inv(xx)
632 632 xx = xx_inv[:, 0]
633 633
634 634 ind = (ind + maxid + num_mask_prof) % num_mask_prof
635 635 yy = jcspectra[ip, mask_prof[ind], :]
636 636 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
637 637
638 638 # Guardar Resultados
639 639 self.dataOut.data_spc = jspectra
640 640 self.dataOut.data_cspc = jcspectra
641 641
642 642 return 1
643 643
644 644 def setRadarFrequency(self, frequency=None):
645 645
646 646 if frequency != None:
647 647 self.dataOut.frequency = frequency
648 648
649 649 return 1
650 650
651 651 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
652 652 # validacion de rango
653 653 if minHei == None:
654 654 minHei = self.dataOut.heightList[0]
655 655
656 656 if maxHei == None:
657 657 maxHei = self.dataOut.heightList[-1]
658 658
659 659 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
660 660 print('minHei: %.2f is out of the heights range' % (minHei))
661 661 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
662 662 minHei = self.dataOut.heightList[0]
663 663
664 664 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
665 665 print('maxHei: %.2f is out of the heights range' % (maxHei))
666 666 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
667 667 maxHei = self.dataOut.heightList[-1]
668 668
669 669 # validacion de velocidades
670 670 velrange = self.dataOut.getVelRange(1)
671 671
672 672 if minVel == None:
673 673 minVel = velrange[0]
674 674
675 675 if maxVel == None:
676 676 maxVel = velrange[-1]
677 677
678 678 if (minVel < velrange[0]) or (minVel > maxVel):
679 679 print('minVel: %.2f is out of the velocity range' % (minVel))
680 680 print('minVel is setting to %.2f' % (velrange[0]))
681 681 minVel = velrange[0]
682 682
683 683 if (maxVel > velrange[-1]) or (maxVel < minVel):
684 684 print('maxVel: %.2f is out of the velocity range' % (maxVel))
685 685 print('maxVel is setting to %.2f' % (velrange[-1]))
686 686 maxVel = velrange[-1]
687 687
688 688 # seleccion de indices para rango
689 689 minIndex = 0
690 690 maxIndex = 0
691 691 heights = self.dataOut.heightList
692 692
693 693 inda = numpy.where(heights >= minHei)
694 694 indb = numpy.where(heights <= maxHei)
695 695
696 696 try:
697 697 minIndex = inda[0][0]
698 698 except:
699 699 minIndex = 0
700 700
701 701 try:
702 702 maxIndex = indb[0][-1]
703 703 except:
704 704 maxIndex = len(heights)
705 705
706 706 if (minIndex < 0) or (minIndex > maxIndex):
707 707 raise ValueError("some value in (%d,%d) is not valid" % (minIndex, maxIndex))
708 708
709 709 if (maxIndex >= self.dataOut.nHeights):
710 710 maxIndex = self.dataOut.nHeights - 1
711 711
712 712 # seleccion de indices para velocidades
713 713 indminvel = numpy.where(velrange >= minVel)
714 714 indmaxvel = numpy.where(velrange <= maxVel)
715 715 try:
716 716 minIndexVel = indminvel[0][0]
717 717 except:
718 718 minIndexVel = 0
719 719
720 720 try:
721 721 maxIndexVel = indmaxvel[0][-1]
722 722 except:
723 723 maxIndexVel = len(velrange)
724 724
725 725 # seleccion del espectro
726 726 data_spc = self.dataOut.data_spc[:, minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
727 727 # estimacion de ruido
728 728 noise = numpy.zeros(self.dataOut.nChannels)
729 729
730 730 for channel in range(self.dataOut.nChannels):
731 731 daux = data_spc[channel, :, :]
732 732 noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt)
733 733
734 734 self.dataOut.noise_estimation = noise.copy()
735 735
736 736 return 1
@@ -1,739 +1,739
1 1 import numpy
2 2
3 3 from .jroproc_base import ProcessingUnit, Operation
4 4 from schainpy.model.data.jrodata import Spectra
5 5 from schainpy.model.data.jrodata import hildebrand_sekhon
6 6
7 7 class SpectraLagsProc(ProcessingUnit):
8 8
9 9 def __init__(self, **kwargs):
10 10
11 11 ProcessingUnit.__init__(self, **kwargs)
12 12
13 13 self.__input_buffer = None
14 14 self.firstdatatime = None
15 15 self.profIndex = 0
16 16 self.dataOut = Spectra()
17 17 self.id_min = None
18 18 self.id_max = None
19 19 self.__codeIndex = 0
20 20
21 21 self.__lags_buffer = None
22 22
23 23 def __updateSpecFromVoltage(self):
24 24
25 25 self.dataOut.plotting = "spectra_lags"
26 26 self.dataOut.timeZone = self.dataIn.timeZone
27 27 self.dataOut.dstFlag = self.dataIn.dstFlag
28 28 self.dataOut.errorCount = self.dataIn.errorCount
29 29 self.dataOut.useLocalTime = self.dataIn.useLocalTime
30 30
31 31 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
32 32 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
33 33 self.dataOut.ippSeconds = self.dataIn.getDeltaH() * (10 ** -6) / 0.15
34 34
35 35 self.dataOut.channelList = self.dataIn.channelList
36 36 self.dataOut.heightList = self.dataIn.heightList
37 37 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
38 38
39 39 self.dataOut.nBaud = self.dataIn.nBaud
40 40 self.dataOut.nCode = self.dataIn.nCode
41 41 self.dataOut.code = self.dataIn.code
42 42 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
43 43
44 44 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
45 45 self.dataOut.utctime = self.firstdatatime
46 46 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData # asumo q la data esta decodificada
47 47 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData # asumo q la data esta sin flip
48 48 self.dataOut.flagShiftFFT = False
49 49
50 50 self.dataOut.nCohInt = self.dataIn.nCohInt
51 51 self.dataOut.nIncohInt = 1
52 52
53 53 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
54 54
55 55 self.dataOut.frequency = self.dataIn.frequency
56 56 self.dataOut.realtime = self.dataIn.realtime
57 57
58 58 self.dataOut.azimuth = self.dataIn.azimuth
59 59 self.dataOut.zenith = self.dataIn.zenith
60 60
61 61 self.dataOut.beam.codeList = self.dataIn.beam.codeList
62 62 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
63 63 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
64 64
65 65 def __createLagsBlock(self, voltages):
66 66
67 67 if self.__lags_buffer is None:
68 68 self.__lags_buffer = numpy.zeros((self.dataOut.nChannels, self.dataOut.nProfiles, self.dataOut.nHeights), dtype='complex')
69 69
70 70 nsegments = self.dataOut.nHeights - self.dataOut.nProfiles
71 71
72 72 # codes = numpy.conjugate(self.__input_buffer[:,9:169])/10000
73 73
74 74 for i in range(nsegments):
75 75 self.__lags_buffer[:, :, i] = voltages[:, i:i + self.dataOut.nProfiles] # *codes
76 76
77 77 return self.__lags_buffer
78 78
79 79 def __decodeData(self, volt_buffer, pulseIndex=None):
80 80
81 81 if pulseIndex is None:
82 82 return volt_buffer
83 83
84 84 codes = numpy.conjugate(self.__input_buffer[:, pulseIndex[0]:pulseIndex[1]]) / 10000
85 85
86 86 nsegments = self.dataOut.nHeights - self.dataOut.nProfiles
87 87
88 88 for i in range(nsegments):
89 89 volt_buffer[:, :, i] = volt_buffer[:, :, i] * codes
90 90
91 91 return volt_buffer
92 92
93 93 def __getFft(self, datablock):
94 94 """
95 95 Convierte valores de Voltaje a Spectra
96 96
97 97 Affected:
98 98 self.dataOut.data_spc
99 99 self.dataOut.data_cspc
100 100 self.dataOut.data_dc
101 101 self.dataOut.heightList
102 102 self.profIndex
103 103 self.__input_buffer
104 104 self.dataOut.flagNoData
105 105 """
106 106
107 107 fft_volt = numpy.fft.fft(datablock, n=self.dataOut.nFFTPoints, axis=1)
108 108
109 109 dc = fft_volt[:, 0, :]
110 110
111 111 # calculo de self-spectra
112 112 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
113 113 spc = fft_volt * numpy.conjugate(fft_volt)
114 114 spc = spc.real
115 115
116 116 blocksize = 0
117 117 blocksize += dc.size
118 118 blocksize += spc.size
119 119
120 120 cspc = None
121 121 pairIndex = 0
122 122
123 123 if self.dataOut.pairsList != []:
124 124 # calculo de cross-spectra
125 125 cspc = numpy.zeros((self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
126 126 for pair in self.dataOut.pairsList:
127 127 if pair[0] not in self.dataOut.channelList:
128 128 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (str(pair), str(self.dataOut.channelList)))
129 129 if pair[1] not in self.dataOut.channelList:
130 130 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (str(pair), str(self.dataOut.channelList)))
131 131
132 132 chan_index0 = self.dataOut.channelList.index(pair[0])
133 133 chan_index1 = self.dataOut.channelList.index(pair[1])
134 134
135 135 cspc[pairIndex, :, :] = fft_volt[chan_index0, :, :] * numpy.conjugate(fft_volt[chan_index1, :, :])
136 136 pairIndex += 1
137 137 blocksize += cspc.size
138 138
139 139 self.dataOut.data_spc = spc
140 140 self.dataOut.data_cspc = cspc
141 141 self.dataOut.data_dc = dc
142 142 self.dataOut.blockSize = blocksize
143 143 self.dataOut.flagShiftFFT = True
144 144
145 145 def run(self, nProfiles=None, nFFTPoints=None, pairsList=[], code=None, nCode=None, nBaud=None, codeFromHeader=False, pulseIndex=None):
146 146
147 147 self.dataOut.flagNoData = True
148 148
149 149 self.code = None
150 150
151 151 if codeFromHeader:
152 152 if self.dataIn.code is not None:
153 153 self.code = self.dataIn.code
154 154
155 155 if code is not None:
156 156 self.code = numpy.array(code).reshape(nCode, nBaud)
157 157
158 158 if self.dataIn.type == "Voltage":
159 159
160 160 if nFFTPoints == None:
161 161 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
162 162
163 163 if nProfiles == None:
164 164 nProfiles = nFFTPoints
165 165
166 166 self.profIndex == nProfiles
167 167 self.firstdatatime = self.dataIn.utctime
168 168
169 169 self.dataOut.ippFactor = 1
170 170 self.dataOut.nFFTPoints = nFFTPoints
171 171 self.dataOut.nProfiles = nProfiles
172 172 self.dataOut.pairsList = pairsList
173 173
174 174 self.__updateSpecFromVoltage()
175 175
176 176 if not self.dataIn.flagDataAsBlock:
177 177 self.__input_buffer = self.dataIn.data.copy()
178 178
179 179 lags_block = self.__createLagsBlock(self.__input_buffer)
180 180
181 181 lags_block = self.__decodeData(lags_block, pulseIndex)
182 182
183 183 else:
184 184 self.__input_buffer = self.dataIn.data.copy()
185 185
186 186 self.__getFft(lags_block)
187 187
188 188 self.dataOut.flagNoData = False
189 189
190 190 return True
191 191
192 192 raise ValueError("The type of input object '%s' is not valid" % (self.dataIn.type))
193 193
194 194 def __selectPairs(self, pairsList):
195 195
196 196 if channelList == None:
197 197 return
198 198
199 199 pairsIndexListSelected = []
200 200
201 201 for thisPair in pairsList:
202 202
203 203 if thisPair not in self.dataOut.pairsList:
204 204 continue
205 205
206 206 pairIndex = self.dataOut.pairsList.index(thisPair)
207 207
208 208 pairsIndexListSelected.append(pairIndex)
209 209
210 210 if not pairsIndexListSelected:
211 211 self.dataOut.data_cspc = None
212 212 self.dataOut.pairsList = []
213 213 return
214 214
215 215 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
216 216 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
217 217
218 218 return
219 219
220 220 def __selectPairsByChannel(self, channelList=None):
221 221
222 222 if channelList == None:
223 223 return
224 224
225 225 pairsIndexListSelected = []
226 226 for pairIndex in self.dataOut.pairsIndexList:
227 227 # First pair
228 228 if self.dataOut.pairsList[pairIndex][0] not in channelList:
229 229 continue
230 230 # Second pair
231 231 if self.dataOut.pairsList[pairIndex][1] not in channelList:
232 232 continue
233 233
234 234 pairsIndexListSelected.append(pairIndex)
235 235
236 236 if not pairsIndexListSelected:
237 237 self.dataOut.data_cspc = None
238 238 self.dataOut.pairsList = []
239 239 return
240 240
241 241 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
242 242 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
243 243
244 244 return
245 245
246 246 def selectChannels(self, channelList):
247 247
248 248 channelIndexList = []
249 249
250 250 for channel in channelList:
251 251 if channel not in self.dataOut.channelList:
252 252 raise ValueError("Error selecting channels, Channel %d is not valid.\nAvailable channels = %s" % (channel, str(self.dataOut.channelList)))
253 253
254 254 index = self.dataOut.channelList.index(channel)
255 255 channelIndexList.append(index)
256 256
257 257 self.selectChannelsByIndex(channelIndexList)
258 258
259 259 def selectChannelsByIndex(self, channelIndexList):
260 260 """
261 261 Selecciona un bloque de datos en base a canales segun el channelIndexList
262 262
263 263 Input:
264 264 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
265 265
266 266 Affected:
267 267 self.dataOut.data_spc
268 268 self.dataOut.channelIndexList
269 269 self.dataOut.nChannels
270 270
271 271 Return:
272 272 None
273 273 """
274 274
275 275 for channelIndex in channelIndexList:
276 276 if channelIndex not in self.dataOut.channelIndexList:
277 277 raise ValueError("Error selecting channels: The value %d in channelIndexList is not valid.\nAvailable channel indexes = " % (channelIndex, self.dataOut.channelIndexList))
278 278
279 279 # nChannels = len(channelIndexList)
280 280
281 281 data_spc = self.dataOut.data_spc[channelIndexList, :]
282 282 data_dc = self.dataOut.data_dc[channelIndexList, :]
283 283
284 284 self.dataOut.data_spc = data_spc
285 285 self.dataOut.data_dc = data_dc
286 286
287 287 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
288 288 # self.dataOut.nChannels = nChannels
289 289
290 290 self.__selectPairsByChannel(self.dataOut.channelList)
291 291
292 292 return 1
293 293
294 294 def selectHeights(self, minHei, maxHei):
295 295 """
296 296 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
297 297 minHei <= height <= maxHei
298 298
299 299 Input:
300 300 minHei : valor minimo de altura a considerar
301 301 maxHei : valor maximo de altura a considerar
302 302
303 303 Affected:
304 304 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
305 305
306 306 Return:
307 307 1 si el metodo se ejecuto con exito caso contrario devuelve 0
308 308 """
309 309
310 310 if (minHei > maxHei):
311 311 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei))
312 312
313 313 if (minHei < self.dataOut.heightList[0]):
314 314 minHei = self.dataOut.heightList[0]
315 315
316 316 if (maxHei > self.dataOut.heightList[-1]):
317 317 maxHei = self.dataOut.heightList[-1]
318 318
319 319 minIndex = 0
320 320 maxIndex = 0
321 321 heights = self.dataOut.heightList
322 322
323 323 inda = numpy.where(heights >= minHei)
324 324 indb = numpy.where(heights <= maxHei)
325 325
326 326 try:
327 327 minIndex = inda[0][0]
328 328 except:
329 329 minIndex = 0
330 330
331 331 try:
332 332 maxIndex = indb[0][-1]
333 333 except:
334 334 maxIndex = len(heights)
335 335
336 336 self.selectHeightsByIndex(minIndex, maxIndex)
337 337
338 338 return 1
339 339
340 340 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
341 341 newheis = numpy.where(self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
342 342
343 343 if hei_ref != None:
344 344 newheis = numpy.where(self.dataOut.heightList > hei_ref)
345 345
346 346 minIndex = min(newheis[0])
347 347 maxIndex = max(newheis[0])
348 348 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
349 349 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
350 350
351 351 # determina indices
352 352 nheis = int(self.dataOut.radarControllerHeaderObj.txB / (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
353 353 avg_dB = 10 * numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
354 354 beacon_dB = numpy.sort(avg_dB)[-nheis:]
355 355 beacon_heiIndexList = []
356 356 for val in avg_dB.tolist():
357 357 if val >= beacon_dB[0]:
358 358 beacon_heiIndexList.append(avg_dB.tolist().index(val))
359 359
360 360 # data_spc = data_spc[:,:,beacon_heiIndexList]
361 361 data_cspc = None
362 362 if self.dataOut.data_cspc is not None:
363 363 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
364 364 # data_cspc = data_cspc[:,:,beacon_heiIndexList]
365 365
366 366 data_dc = None
367 367 if self.dataOut.data_dc is not None:
368 368 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
369 369 # data_dc = data_dc[:,beacon_heiIndexList]
370 370
371 371 self.dataOut.data_spc = data_spc
372 372 self.dataOut.data_cspc = data_cspc
373 373 self.dataOut.data_dc = data_dc
374 374 self.dataOut.heightList = heightList
375 375 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
376 376
377 377 return 1
378 378
379 379
380 380 def selectHeightsByIndex(self, minIndex, maxIndex):
381 381 """
382 382 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
383 383 minIndex <= index <= maxIndex
384 384
385 385 Input:
386 386 minIndex : valor de indice minimo de altura a considerar
387 387 maxIndex : valor de indice maximo de altura a considerar
388 388
389 389 Affected:
390 390 self.dataOut.data_spc
391 391 self.dataOut.data_cspc
392 392 self.dataOut.data_dc
393 393 self.dataOut.heightList
394 394
395 395 Return:
396 396 1 si el metodo se ejecuto con exito caso contrario devuelve 0
397 397 """
398 398
399 399 if (minIndex < 0) or (minIndex > maxIndex):
400 400 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
401 401
402 402 if (maxIndex >= self.dataOut.nHeights):
403 403 maxIndex = self.dataOut.nHeights - 1
404 404
405 405 # Spectra
406 406 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
407 407
408 408 data_cspc = None
409 409 if self.dataOut.data_cspc is not None:
410 410 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
411 411
412 412 data_dc = None
413 413 if self.dataOut.data_dc is not None:
414 414 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
415 415
416 416 self.dataOut.data_spc = data_spc
417 417 self.dataOut.data_cspc = data_cspc
418 418 self.dataOut.data_dc = data_dc
419 419
420 420 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
421 421
422 422 return 1
423 423
424 424 def removeDC(self, mode=2):
425 425 jspectra = self.dataOut.data_spc
426 426 jcspectra = self.dataOut.data_cspc
427 427
428 428
429 429 num_chan = jspectra.shape[0]
430 430 num_hei = jspectra.shape[2]
431 431
432 432 if jcspectra is not None:
433 433 jcspectraExist = True
434 434 num_pairs = jcspectra.shape[0]
435 435 else: jcspectraExist = False
436 436
437 437 freq_dc = jspectra.shape[1] / 2
438 438 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
439 439
440 440 if ind_vel[0] < 0:
441 441 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
442 442
443 443 if mode == 1:
444 444 jspectra[:, freq_dc, :] = (jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
445 445
446 446 if jcspectraExist:
447 447 jcspectra[:, freq_dc, :] = (jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
448 448
449 449 if mode == 2:
450 450
451 451 vel = numpy.array([-2, -1, 1, 2])
452 452 xx = numpy.zeros([4, 4])
453 453
454 454 for fil in range(4):
455 455 xx[fil, :] = vel[fil] ** numpy.asarray(list(range(4)))
456 456
457 457 xx_inv = numpy.linalg.inv(xx)
458 458 xx_aux = xx_inv[0, :]
459 459
460 460 for ich in range(num_chan):
461 461 yy = jspectra[ich, ind_vel, :]
462 462 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
463 463
464 464 junkid = jspectra[ich, freq_dc, :] <= 0
465 465 cjunkid = sum(junkid)
466 466
467 467 if cjunkid.any():
468 468 jspectra[ich, freq_dc, junkid.nonzero()] = (jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
469 469
470 470 if jcspectraExist:
471 471 for ip in range(num_pairs):
472 472 yy = jcspectra[ip, ind_vel, :]
473 473 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
474 474
475 475
476 476 self.dataOut.data_spc = jspectra
477 477 self.dataOut.data_cspc = jcspectra
478 478
479 479 return 1
480 480
481 481 def removeInterference(self, interf=2, hei_interf=None, nhei_interf=None, offhei_interf=None):
482 482
483 483 jspectra = self.dataOut.data_spc
484 484 jcspectra = self.dataOut.data_cspc
485 485 jnoise = self.dataOut.getNoise()
486 486 num_incoh = self.dataOut.nIncohInt
487 487
488 488 num_channel = jspectra.shape[0]
489 489 num_prof = jspectra.shape[1]
490 490 num_hei = jspectra.shape[2]
491 491
492 492 # hei_interf
493 493 if hei_interf is None:
494 494 count_hei = num_hei / 2 # Como es entero no importa
495 495 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
496 496 hei_interf = numpy.asarray(hei_interf)[0]
497 497 # nhei_interf
498 498 if (nhei_interf == None):
499 499 nhei_interf = 5
500 500 if (nhei_interf < 1):
501 501 nhei_interf = 1
502 502 if (nhei_interf > count_hei):
503 503 nhei_interf = count_hei
504 504 if (offhei_interf == None):
505 505 offhei_interf = 0
506 506
507 507 ind_hei = list(range(num_hei))
508 508 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
509 509 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
510 510 mask_prof = numpy.asarray(list(range(num_prof)))
511 511 num_mask_prof = mask_prof.size
512 512 comp_mask_prof = [0, num_prof / 2]
513 513
514 514
515 515 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
516 516 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
517 517 jnoise = numpy.nan
518 518 noise_exist = jnoise[0] < numpy.Inf
519 519
520 520 # Subrutina de Remocion de la Interferencia
521 521 for ich in range(num_channel):
522 522 # Se ordena los espectros segun su potencia (menor a mayor)
523 523 power = jspectra[ich, mask_prof, :]
524 524 power = power[:, hei_interf]
525 525 power = power.sum(axis=0)
526 526 psort = power.ravel().argsort()
527 527
528 528 # Se estima la interferencia promedio en los Espectros de Potencia empleando
529 529 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(offhei_interf, nhei_interf + offhei_interf))]]]
530 530
531 531 if noise_exist:
532 532 # tmp_noise = jnoise[ich] / num_prof
533 533 tmp_noise = jnoise[ich]
534 534 junkspc_interf = junkspc_interf - tmp_noise
535 535 # junkspc_interf[:,comp_mask_prof] = 0
536 536
537 537 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
538 538 jspc_interf = jspc_interf.transpose()
539 539 # Calculando el espectro de interferencia promedio
540 540 noiseid = numpy.where(jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
541 541 noiseid = noiseid[0]
542 542 cnoiseid = noiseid.size
543 543 interfid = numpy.where(jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
544 544 interfid = interfid[0]
545 545 cinterfid = interfid.size
546 546
547 547 if (cnoiseid > 0): jspc_interf[noiseid] = 0
548 548
549 549 # Expandiendo los perfiles a limpiar
550 550 if (cinterfid > 0):
551 551 new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
552 552 new_interfid = numpy.asarray(new_interfid)
553 553 new_interfid = {x for x in new_interfid}
554 554 new_interfid = numpy.array(list(new_interfid))
555 555 new_cinterfid = new_interfid.size
556 556 else: new_cinterfid = 0
557 557
558 558 for ip in range(new_cinterfid):
559 559 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
560 560 jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf / 2], new_interfid[ip]]
561 561
562 562
563 563 jspectra[ich, :, ind_hei] = jspectra[ich, :, ind_hei] - jspc_interf # Corregir indices
564 564
565 565 # Removiendo la interferencia del punto de mayor interferencia
566 566 ListAux = jspc_interf[mask_prof].tolist()
567 567 maxid = ListAux.index(max(ListAux))
568 568
569 569
570 570 if cinterfid > 0:
571 571 for ip in range(cinterfid * (interf == 2) - 1):
572 572 ind = (jspectra[ich, interfid[ip], :] < tmp_noise * (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
573 573 cind = len(ind)
574 574
575 575 if (cind > 0):
576 576 jspectra[ich, interfid[ip], ind] = tmp_noise * (1 + (numpy.random.uniform(cind) - 0.5) / numpy.sqrt(num_incoh))
577 577
578 578 ind = numpy.array([-2, -1, 1, 2])
579 579 xx = numpy.zeros([4, 4])
580 580
581 581 for id1 in range(4):
582 582 xx[:, id1] = ind[id1] ** numpy.asarray(list(range(4)))
583 583
584 584 xx_inv = numpy.linalg.inv(xx)
585 585 xx = xx_inv[:, 0]
586 586 ind = (ind + maxid + num_mask_prof) % num_mask_prof
587 587 yy = jspectra[ich, mask_prof[ind], :]
588 588 jspectra[ich, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
589 589
590 590
591 591 indAux = (jspectra[ich, :, :] < tmp_noise * (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
592 592 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * (1 - 1 / numpy.sqrt(num_incoh))
593 593
594 594 # Remocion de Interferencia en el Cross Spectra
595 595 if jcspectra is None: return jspectra, jcspectra
596 596 num_pairs = jcspectra.size / (num_prof * num_hei)
597 597 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
598 598
599 599 for ip in range(num_pairs):
600 600
601 601 #-------------------------------------------
602 602
603 603 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
604 604 cspower = cspower[:, hei_interf]
605 605 cspower = cspower.sum(axis=0)
606 606
607 607 cspsort = cspower.ravel().argsort()
608 608 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(offhei_interf, nhei_interf + offhei_interf))]]]
609 609 junkcspc_interf = junkcspc_interf.transpose()
610 610 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
611 611
612 612 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
613 613
614 614 median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[list(range(3 * num_prof / 4))]], :]))
615 615 median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[list(range(3 * num_prof / 4))]], :]))
616 junkcspc_interf[comp_mask_prof, :] = numpy.complex(median_real, median_imag)
616 junkcspc_interf[comp_mask_prof, :] = complex(median_real, median_imag)
617 617
618 618 for iprof in range(num_prof):
619 619 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
620 620 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf / 2]]
621 621
622 622 # Removiendo la Interferencia
623 623 jcspectra[ip, :, ind_hei] = jcspectra[ip, :, ind_hei] - jcspc_interf
624 624
625 625 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
626 626 maxid = ListAux.index(max(ListAux))
627 627
628 628 ind = numpy.array([-2, -1, 1, 2])
629 629 xx = numpy.zeros([4, 4])
630 630
631 631 for id1 in range(4):
632 632 xx[:, id1] = ind[id1] ** numpy.asarray(list(range(4)))
633 633
634 634 xx_inv = numpy.linalg.inv(xx)
635 635 xx = xx_inv[:, 0]
636 636
637 637 ind = (ind + maxid + num_mask_prof) % num_mask_prof
638 638 yy = jcspectra[ip, mask_prof[ind], :]
639 639 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
640 640
641 641 # Guardar Resultados
642 642 self.dataOut.data_spc = jspectra
643 643 self.dataOut.data_cspc = jcspectra
644 644
645 645 return 1
646 646
647 647 def setRadarFrequency(self, frequency=None):
648 648
649 649 if frequency != None:
650 650 self.dataOut.frequency = frequency
651 651
652 652 return 1
653 653
654 654 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
655 655 # validacion de rango
656 656 if minHei == None:
657 657 minHei = self.dataOut.heightList[0]
658 658
659 659 if maxHei == None:
660 660 maxHei = self.dataOut.heightList[-1]
661 661
662 662 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
663 663 print('minHei: %.2f is out of the heights range' % (minHei))
664 664 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
665 665 minHei = self.dataOut.heightList[0]
666 666
667 667 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
668 668 print('maxHei: %.2f is out of the heights range' % (maxHei))
669 669 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
670 670 maxHei = self.dataOut.heightList[-1]
671 671
672 672 # validacion de velocidades
673 673 velrange = self.dataOut.getVelRange(1)
674 674
675 675 if minVel == None:
676 676 minVel = velrange[0]
677 677
678 678 if maxVel == None:
679 679 maxVel = velrange[-1]
680 680
681 681 if (minVel < velrange[0]) or (minVel > maxVel):
682 682 print('minVel: %.2f is out of the velocity range' % (minVel))
683 683 print('minVel is setting to %.2f' % (velrange[0]))
684 684 minVel = velrange[0]
685 685
686 686 if (maxVel > velrange[-1]) or (maxVel < minVel):
687 687 print('maxVel: %.2f is out of the velocity range' % (maxVel))
688 688 print('maxVel is setting to %.2f' % (velrange[-1]))
689 689 maxVel = velrange[-1]
690 690
691 691 # seleccion de indices para rango
692 692 minIndex = 0
693 693 maxIndex = 0
694 694 heights = self.dataOut.heightList
695 695
696 696 inda = numpy.where(heights >= minHei)
697 697 indb = numpy.where(heights <= maxHei)
698 698
699 699 try:
700 700 minIndex = inda[0][0]
701 701 except:
702 702 minIndex = 0
703 703
704 704 try:
705 705 maxIndex = indb[0][-1]
706 706 except:
707 707 maxIndex = len(heights)
708 708
709 709 if (minIndex < 0) or (minIndex > maxIndex):
710 710 raise ValueError("some value in (%d,%d) is not valid" % (minIndex, maxIndex))
711 711
712 712 if (maxIndex >= self.dataOut.nHeights):
713 713 maxIndex = self.dataOut.nHeights - 1
714 714
715 715 # seleccion de indices para velocidades
716 716 indminvel = numpy.where(velrange >= minVel)
717 717 indmaxvel = numpy.where(velrange <= maxVel)
718 718 try:
719 719 minIndexVel = indminvel[0][0]
720 720 except:
721 721 minIndexVel = 0
722 722
723 723 try:
724 724 maxIndexVel = indmaxvel[0][-1]
725 725 except:
726 726 maxIndexVel = len(velrange)
727 727
728 728 # seleccion del espectro
729 729 data_spc = self.dataOut.data_spc[:, minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
730 730 # estimacion de ruido
731 731 noise = numpy.zeros(self.dataOut.nChannels)
732 732
733 733 for channel in range(self.dataOut.nChannels):
734 734 daux = data_spc[channel, :, :]
735 735 noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt)
736 736
737 737 self.dataOut.noise_estimation = noise.copy()
738 738
739 739 return 1
@@ -1,6266 +1,6266
1 1
2 2 import os
3 3 import sys
4 4 import numpy, math
5 5 from scipy import interpolate
6 6 from scipy.optimize import nnls
7 7 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
8 8 from schainpy.model.data.jrodata import Voltage, hildebrand_sekhon
9 9 from schainpy.utils import log
10 10 from time import time, mktime, strptime, gmtime, ctime
11 11
12 12 try:
13 13 from schainpy.model.proc import fitacf_guess
14 14 from schainpy.model.proc import fitacf_fit_short
15 15 from schainpy.model.proc import fitacf_acf2
16 16 from schainpy.model.proc import full_profile_profile
17 17 except:
18 18 log.warning('Missing Faraday fortran libs')
19 19
20 20 class VoltageProc(ProcessingUnit):
21 21
22 22 def __init__(self):
23 23
24 24 ProcessingUnit.__init__(self)
25 25
26 26 self.dataOut = Voltage()
27 27 self.flip = 1
28 28 self.setupReq = False
29 29 #self.dataOut.test=1
30 30
31 31
32 32 def run(self):
33 33 #import time
34 34 #time.sleep(3)
35 35
36 36 if self.dataIn.type == 'AMISR':
37 37 self.__updateObjFromAmisrInput()
38 38
39 39 if self.dataIn.type == 'Voltage':
40 40 self.dataOut.copy(self.dataIn)
41 41
42 42
43 43 #self.dataOut.flagNoData=True
44 44 #print(self.dataOut.data[-1,:])
45 45 #print(ctime(self.dataOut.utctime))
46 46 #print(self.dataOut.heightList)
47 47 #print(self.dataOut.nHeights)
48 48 #exit(1)
49 49 #print(self.dataOut.data[6,:32])
50 50 #print(self.dataOut.data[0,320-5:320+5-5])
51 51 ##print(self.dataOut.heightList[-20:])
52 52 #print(numpy.shape(self.dataOut.data))
53 53 #print(self.dataOut.code)
54 54 #print(numpy.shape(self.dataOut.code))
55 55 #exit(1)
56 56 #print(self.dataOut.CurrentBlock)
57 57 #print(self.dataOut.data[0,:,0])
58 58
59 59 #print(numpy.shape(self.dataOut.data))
60 60 #print(self.dataOut.data[0,:,1666:1666+320])
61 61 #exit(1)
62 62
63 63 #print(self.dataOut.utctime)
64 64 #self.dataOut.test+=1
65 65
66 66
67 67 def __updateObjFromAmisrInput(self):
68 68
69 69 self.dataOut.timeZone = self.dataIn.timeZone
70 70 self.dataOut.dstFlag = self.dataIn.dstFlag
71 71 self.dataOut.errorCount = self.dataIn.errorCount
72 72 self.dataOut.useLocalTime = self.dataIn.useLocalTime
73 73
74 74 self.dataOut.flagNoData = self.dataIn.flagNoData
75 75 self.dataOut.data = self.dataIn.data
76 76 self.dataOut.utctime = self.dataIn.utctime
77 77 self.dataOut.channelList = self.dataIn.channelList
78 78 # self.dataOut.timeInterval = self.dataIn.timeInterval
79 79 self.dataOut.heightList = self.dataIn.heightList
80 80 self.dataOut.nProfiles = self.dataIn.nProfiles
81 81
82 82 self.dataOut.nCohInt = self.dataIn.nCohInt
83 83 self.dataOut.ippSeconds = self.dataIn.ippSeconds
84 84 self.dataOut.frequency = self.dataIn.frequency
85 85
86 86 self.dataOut.azimuth = self.dataIn.azimuth
87 87 self.dataOut.zenith = self.dataIn.zenith
88 88
89 89 self.dataOut.beam.codeList = self.dataIn.beam.codeList
90 90 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
91 91 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
92 92
93 93 class selectChannels(Operation):
94 94
95 95 def run(self, dataOut, channelList):
96 96
97 97
98 98
99 99
100 100 channelIndexList = []
101 101 self.dataOut = dataOut
102 102 for channel in channelList:
103 103 if channel not in self.dataOut.channelList:
104 104 raise ValueError("Channel %d is not in %s" % (channel, str(self.dataOut.channelList)))
105 105
106 106 index = self.dataOut.channelList.index(channel)
107 107 channelIndexList.append(index)
108 108 self.selectChannelsByIndex(channelIndexList)
109 109
110 110 return self.dataOut
111 111
112 112
113 113 def selectChannelsByIndex(self, channelIndexList):
114 114 """
115 115 Selecciona un bloque de datos en base a canales segun el channelIndexList
116 116
117 117 Input:
118 118 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
119 119
120 120 Affected:
121 121 self.dataOut.data
122 122 self.dataOut.channelIndexList
123 123 self.dataOut.nChannels
124 124 self.dataOut.m_ProcessingHeader.totalSpectra
125 125 self.dataOut.systemHeaderObj.numChannels
126 126 self.dataOut.m_ProcessingHeader.blockSize
127 127
128 128 Return:
129 129 None
130 130 """
131 131
132 132 for channelIndex in channelIndexList:
133 133 if channelIndex not in self.dataOut.channelIndexList:
134 134 raise ValueError("The value %d in channelIndexList is not valid" % channelIndex)
135 135
136 136 if self.dataOut.type == 'Voltage':
137 137 if self.dataOut.flagDataAsBlock:
138 138 """
139 139 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
140 140 """
141 141 data = self.dataOut.data[channelIndexList, :, :]
142 142 else:
143 143 data = self.dataOut.data[channelIndexList, :]
144 144
145 145 self.dataOut.data = data
146 146 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
147 147 self.dataOut.channelList = range(len(channelIndexList))
148 148
149 149 elif self.dataOut.type == 'Spectra':
150 150 data_spc = self.dataOut.data_spc[channelIndexList, :]
151 151 data_dc = self.dataOut.data_dc[channelIndexList, :]
152 152
153 153 self.dataOut.data_spc = data_spc
154 154 self.dataOut.data_dc = data_dc
155 155
156 156 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
157 157 self.dataOut.channelList = range(len(channelIndexList))
158 158 self.__selectPairsByChannel(channelIndexList)
159 159
160 160 return 1
161 161
162 162 def __selectPairsByChannel(self, channelList=None):
163 163
164 164 if channelList == None:
165 165 return
166 166
167 167 pairsIndexListSelected = []
168 168 for pairIndex in self.dataOut.pairsIndexList:
169 169 # First pair
170 170 if self.dataOut.pairsList[pairIndex][0] not in channelList:
171 171 continue
172 172 # Second pair
173 173 if self.dataOut.pairsList[pairIndex][1] not in channelList:
174 174 continue
175 175
176 176 pairsIndexListSelected.append(pairIndex)
177 177
178 178 if not pairsIndexListSelected:
179 179 self.dataOut.data_cspc = None
180 180 self.dataOut.pairsList = []
181 181 return
182 182
183 183 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
184 184 self.dataOut.pairsList = [self.dataOut.pairsList[i]
185 185 for i in pairsIndexListSelected]
186 186
187 187 return
188 188
189 189 class selectHeights(Operation):
190 190
191 191 def run(self, dataOut, minHei=None, maxHei=None, minIndex=None, maxIndex=None):
192 192 """
193 193 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
194 194 minHei <= height <= maxHei
195 195
196 196 Input:
197 197 minHei : valor minimo de altura a considerar
198 198 maxHei : valor maximo de altura a considerar
199 199
200 200 Affected:
201 201 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
202 202
203 203 Return:
204 204 1 si el metodo se ejecuto con exito caso contrario devuelve 0
205 205 """
206 206
207 207 self.dataOut = dataOut
208 208
209 209 #if minHei and maxHei:
210 210 if 1:
211 211 if minHei == None:
212 212 minHei = self.dataOut.heightList[0]
213 213
214 214 if maxHei == None:
215 215 maxHei = self.dataOut.heightList[-1]
216 216
217 217 if (minHei < self.dataOut.heightList[0]):
218 218 minHei = self.dataOut.heightList[0]
219 219
220 220 if (maxHei > self.dataOut.heightList[-1]):
221 221 maxHei = self.dataOut.heightList[-1]
222 222
223 223 minIndex = 0
224 224 maxIndex = 0
225 225 heights = self.dataOut.heightList
226 226
227 227 inda = numpy.where(heights >= minHei)
228 228 indb = numpy.where(heights <= maxHei)
229 229
230 230 try:
231 231 minIndex = inda[0][0]
232 232 except:
233 233 minIndex = 0
234 234
235 235 try:
236 236 maxIndex = indb[0][-1]
237 237 except:
238 238 maxIndex = len(heights)
239 239
240 240 self.selectHeightsByIndex(minIndex, maxIndex)
241 241 #print(self.dataOut.nHeights)
242 242
243 243
244 244 return self.dataOut
245 245
246 246 def selectHeightsByIndex(self, minIndex, maxIndex):
247 247 """
248 248 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
249 249 minIndex <= index <= maxIndex
250 250
251 251 Input:
252 252 minIndex : valor de indice minimo de altura a considerar
253 253 maxIndex : valor de indice maximo de altura a considerar
254 254
255 255 Affected:
256 256 self.dataOut.data
257 257 self.dataOut.heightList
258 258
259 259 Return:
260 260 1 si el metodo se ejecuto con exito caso contrario devuelve 0
261 261 """
262 262
263 263 if self.dataOut.type == 'Voltage':
264 264 if (minIndex < 0) or (minIndex > maxIndex):
265 265 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
266 266
267 267 if (maxIndex >= self.dataOut.nHeights):
268 268 maxIndex = self.dataOut.nHeights
269 269
270 270 # voltage
271 271 if self.dataOut.flagDataAsBlock:
272 272 """
273 273 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
274 274 """
275 275 data = self.dataOut.data[:, :, minIndex:maxIndex]
276 276 else:
277 277 data = self.dataOut.data[:, minIndex:maxIndex]
278 278
279 279 # firstHeight = self.dataOut.heightList[minIndex]
280 280
281 281 self.dataOut.data = data
282 282 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
283 283
284 284 if self.dataOut.nHeights <= 1:
285 285 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" % (self.dataOut.nHeights))
286 286 elif self.dataOut.type == 'Spectra':
287 287 if (minIndex < 0) or (minIndex > maxIndex):
288 288 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (
289 289 minIndex, maxIndex))
290 290
291 291 if (maxIndex >= self.dataOut.nHeights):
292 292 maxIndex = self.dataOut.nHeights - 1
293 293
294 294 # Spectra
295 295 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
296 296
297 297 data_cspc = None
298 298 if self.dataOut.data_cspc is not None:
299 299 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
300 300
301 301 data_dc = None
302 302 if self.dataOut.data_dc is not None:
303 303 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
304 304
305 305 self.dataOut.data_spc = data_spc
306 306 self.dataOut.data_cspc = data_cspc
307 307 self.dataOut.data_dc = data_dc
308 308
309 309 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
310 310
311 311 return 1
312 312
313 313
314 314 class filterByHeights(Operation):
315 315
316 316 def run(self, dataOut, window):
317 317
318 318 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
319 319
320 320 if window == None:
321 321 window = (dataOut.radarControllerHeaderObj.txA / dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
322 322
323 323 newdelta = deltaHeight * window
324 324 r = dataOut.nHeights % window
325 325 newheights = (dataOut.nHeights - r) / window
326 326
327 327 if newheights <= 1:
328 328 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" % (dataOut.nHeights, window))
329 329
330 330 if dataOut.flagDataAsBlock:
331 331 """
332 332 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
333 333 """
334 334 buffer = dataOut.data[:, :, 0:int(dataOut.nHeights - r)]
335 335 buffer = buffer.reshape(dataOut.nChannels, dataOut.nProfiles, int(dataOut.nHeights / window), window)
336 336 buffer = numpy.sum(buffer, 3)
337 337
338 338 else:
339 339 buffer = dataOut.data[:, 0:int(dataOut.nHeights - r)]
340 340 buffer = buffer.reshape(dataOut.nChannels, int(dataOut.nHeights / window), int(window))
341 341 buffer = numpy.sum(buffer, 2)
342 342
343 343 dataOut.data = buffer
344 344 dataOut.heightList = dataOut.heightList[0] + numpy.arange(newheights) * newdelta
345 345 dataOut.windowOfFilter = window
346 346
347 347 return dataOut
348 348
349 349
350 350 class setH0(Operation):
351 351
352 352 def run(self, dataOut, h0, deltaHeight=None):
353 353
354 354 if not deltaHeight:
355 355 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
356 356
357 357 nHeights = dataOut.nHeights
358 358
359 359 newHeiRange = h0 + numpy.arange(nHeights) * deltaHeight
360 360
361 361 dataOut.heightList = newHeiRange
362 362
363 363 return dataOut
364 364
365 365
366 366 class deFlip(Operation):
367 367 def __init__(self):
368 368
369 369 self.flip = 1
370 370
371 371 def run(self, dataOut, channelList=[]):
372 372
373 373 data = dataOut.data.copy()
374 374 #print(dataOut.channelList)
375 375 #exit()
376 376
377 377 if channelList==1: #PARCHE
378 378 channelList=[1]
379 379
380 380
381 381 dataOut.FlipChannels=channelList
382 382 if dataOut.flagDataAsBlock:
383 383 flip = self.flip
384 384 profileList = list(range(dataOut.nProfiles))
385 385
386 386 if not channelList:
387 387 for thisProfile in profileList:
388 388 data[:, thisProfile, :] = data[:, thisProfile, :] * flip
389 389 flip *= -1.0
390 390 else:
391 391 for thisChannel in channelList:
392 392 if thisChannel not in dataOut.channelList:
393 393 continue
394 394
395 395 for thisProfile in profileList:
396 396 data[thisChannel, thisProfile, :] = data[thisChannel, thisProfile, :] * flip
397 397 flip *= -1.0
398 398
399 399 self.flip = flip
400 400
401 401
402 402
403 403
404 404 else:
405 405 if not channelList:
406 406 data[:, :] = data[:, :] * self.flip
407 407 else:
408 408 channelList=[1]
409 409 #print(self.flip)
410 410 for thisChannel in channelList:
411 411 if thisChannel not in dataOut.channelList:
412 412 continue
413 413
414 414 data[thisChannel, :] = data[thisChannel, :] * self.flip
415 415
416 416 self.flip *= -1.
417 417
418 418
419 419 dataOut.data = data
420 420
421 421 return dataOut
422 422
423 423
424 424 class setAttribute(Operation):
425 425 '''
426 426 Set an arbitrary attribute(s) to dataOut
427 427 '''
428 428
429 429 def __init__(self):
430 430
431 431 Operation.__init__(self)
432 432 self._ready = False
433 433
434 434 def run(self, dataOut, **kwargs):
435 435
436 436 for key, value in kwargs.items():
437 437 setattr(dataOut, key, value)
438 438
439 439 return dataOut
440 440
441 441
442 442 @MPDecorator
443 443 class printAttribute(Operation):
444 444 '''
445 445 Print an arbitrary attribute of dataOut
446 446 '''
447 447
448 448 def __init__(self):
449 449
450 450 Operation.__init__(self)
451 451
452 452 def run(self, dataOut, attributes):
453 453
454 454 if isinstance(attributes, str):
455 455 attributes = [attributes]
456 456 for attr in attributes:
457 457 if hasattr(dataOut, attr):
458 458 log.log(getattr(dataOut, attr), attr)
459 459
460 460
461 461 class interpolateHeights(Operation):
462 462
463 463 def run(self, dataOut, topLim, botLim):
464 464 # 69 al 72 para julia
465 465 # 82-84 para meteoros
466 466 if len(numpy.shape(dataOut.data)) == 2:
467 467 sampInterp = (dataOut.data[:, botLim - 1] + dataOut.data[:, topLim + 1]) / 2
468 468 sampInterp = numpy.transpose(numpy.tile(sampInterp, (topLim - botLim + 1, 1)))
469 469 # dataOut.data[:,botLim:limSup+1] = sampInterp
470 470 dataOut.data[:, botLim:topLim + 1] = sampInterp
471 471 else:
472 472 nHeights = dataOut.data.shape[2]
473 473 x = numpy.hstack((numpy.arange(botLim), numpy.arange(topLim + 1, nHeights)))
474 474 y = dataOut.data[:, :, list(range(botLim)) + list(range(topLim + 1, nHeights))]
475 475 f = interpolate.interp1d(x, y, axis=2)
476 476 xnew = numpy.arange(botLim, topLim + 1)
477 477 ynew = f(xnew)
478 478 dataOut.data[:, :, botLim:topLim + 1] = ynew
479 479
480 480 return dataOut
481 481
482 482
483 483 class LagsReshape(Operation):
484 484 """Operation to reshape input data into (Channels,Profiles(with same lag),Heights,Lags) and heights reconstruction.
485 485
486 486 Parameters:
487 487 -----------
488 488
489 489
490 490 Example
491 491 --------
492 492
493 493 op = proc_unit.addOperation(name='LagsReshape')
494 494
495 495
496 496 """
497 497
498 498 def __init__(self, **kwargs):
499 499
500 500 Operation.__init__(self, **kwargs)
501 501
502 502 self.buffer=None
503 503 self.buffer_HR=None
504 504 self.buffer_HRonelag=None
505 505
506 506 def LagDistribution(self,dataOut):
507 507
508 508 dataOut.datapure=numpy.copy(dataOut.data[:,0:dataOut.NSCAN,:])
509 509 self.buffer = numpy.zeros((dataOut.nChannels,
510 510 int(dataOut.NSCAN/dataOut.DPL),
511 511 dataOut.nHeights,dataOut.DPL),
512 512 dtype='complex')
513 513
514 514 for j in range(int(self.buffer.shape[1]/2)):
515 515 for i in range(dataOut.DPL):
516 516 if j+1==int(self.buffer.shape[1]/2) and i+1==dataOut.DPL:
517 517 self.buffer[:,2*j:,:,i]=dataOut.datapure[:,2*i+int(2*j*dataOut.DPL):,:]
518 518 else:
519 519 self.buffer[:,2*j:2*(j+1),:,i]=dataOut.datapure[:,2*i+int(2*j*dataOut.DPL):2*(i+1)+int(2*j*dataOut.DPL),:]
520 520
521 521 return self.buffer
522 522
523 523 def HeightReconstruction(self,dataOut):
524 524
525 525 self.buffer_HR = numpy.zeros((int(dataOut.NSCAN/dataOut.DPL),
526 526 dataOut.nHeights,dataOut.DPL),
527 527 dtype='complex')
528 528
529 529 #self.buffer_HR[0,:,:,:]=dataOut.datalags[0,:,:,:] #No Lags
530 530
531 531 for i in range(int(dataOut.DPL)): #Only channel B
532 532 if i==0:
533 533 self.buffer_HR[:,:,i]=dataOut.datalags[1,:,:,i]
534 534 else:
535 535 self.buffer_HR[:,:,i]=self.HRonelag(dataOut,i)
536 536
537 537 return self.buffer_HR
538 538
539 539
540 540 def HRonelag(self,dataOut,whichlag):
541 541 self.buffer_HRonelag = numpy.zeros((int(dataOut.NSCAN/dataOut.DPL),
542 542 dataOut.nHeights),
543 543 dtype='complex')
544 544
545 545 for i in range(self.buffer_HRonelag.shape[0]):
546 546 for j in range(dataOut.nHeights):
547 547 if j+int(2*whichlag)<dataOut.nHeights:
548 548 self.buffer_HRonelag[i,j]=dataOut.datalags[1,i,j+2*whichlag,whichlag]
549 549 else:
550 550 if whichlag!=10:
551 551 self.buffer_HRonelag[i,j]=dataOut.datalags[1,i,(j+2*whichlag)%dataOut.nHeights,whichlag+1]
552 552 else:
553 553 if i+2<self.buffer_HRonelag.shape[0]:
554 554 self.buffer_HRonelag[i,j]=dataOut.datalags[1,i+2,(j+2*whichlag)%dataOut.nHeights,0]
555 555 else: #i+1==self.buffer_HRonelag.shape[0]:
556 556 self.buffer_HRonelag[i,j]=dataOut.datalags[1,i,(j+2*whichlag)%dataOut.nHeights,whichlag]
557 557
558 558 return self.buffer_HRonelag
559 559
560 560
561 561
562 562 def run(self,dataOut,DPL=11,NSCAN=132):
563 563
564 564 dataOut.DPL=DPL
565 565 dataOut.NSCAN=NSCAN
566 566 dataOut.paramInterval=0#int(dataOut.nint*dataOut.header[7][0]*2 )
567 567 dataOut.lat=-11.95
568 568 dataOut.lon=-76.87
569 569 dataOut.datalags=None
570 570 #print(dataOut.NSCAN)
571 571
572 572 dataOut.datalags=numpy.copy(self.LagDistribution(dataOut))
573 573 dataOut.datalags[1,:,:,:]=self.HeightReconstruction(dataOut)
574 574
575 575 return dataOut
576 576
577 577
578 578
579 579
580 580 class CrossProdDP(Operation):
581 581 """Operation to calculate cross products of the Double Pulse Experiment.
582 582
583 583 Parameters:
584 584 -----------
585 585 NLAG : int
586 586 Number of lags Long Pulse.
587 587 NRANGE : int
588 588 Number of samples for Long Pulse.
589 589 NCAL : int
590 590 .*
591 591 DPL : int
592 592 Number of lags Double Pulse.
593 593 NDN : int
594 594 .*
595 595 NDT : int
596 596 Number of heights for Double Pulse.*
597 597 NDP : int
598 598 Number of heights for Double Pulse.*
599 599 NSCAN : int
600 600 Number of profiles when the transmitter is on.
601 601 flags_array : intlist
602 602 .*
603 603 NAVG : int
604 604 Number of blocks to be "averaged".
605 605 nkill : int
606 606 Number of blocks not to be considered when averaging.
607 607
608 608 Example
609 609 --------
610 610
611 611 op = proc_unit.addOperation(name='CrossProdDP', optype='other')
612 612 op.addParameter(name='NLAG', value='16', format='int')
613 613 op.addParameter(name='NRANGE', value='0', format='int')
614 614 op.addParameter(name='NCAL', value='0', format='int')
615 615 op.addParameter(name='DPL', value='11', format='int')
616 616 op.addParameter(name='NDN', value='0', format='int')
617 617 op.addParameter(name='NDT', value='66', format='int')
618 618 op.addParameter(name='NDP', value='66', format='int')
619 619 op.addParameter(name='NSCAN', value='132', format='int')
620 620 op.addParameter(name='flags_array', value='(0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300)', format='intlist')
621 621 op.addParameter(name='NAVG', value='16', format='int')
622 622 op.addParameter(name='nkill', value='6', format='int')
623 623
624 624 """
625 625
626 626 def __init__(self, **kwargs):
627 627
628 628 Operation.__init__(self, **kwargs)
629 629 self.bcounter=0
630 630 self.aux=1
631 631 self.lag_products_LP_median_estimates_aux=0
632 632
633 633 def set_header_output(self,dataOut):
634 634
635 635 dataOut.read_samples=len(dataOut.heightList)#int(dataOut.systemHeaderObj.nSamples/dataOut.windowOfFilter)
636 636 padding=numpy.zeros(1,'int32')
637 637 hsize=numpy.zeros(1,'int32')
638 638 bufsize=numpy.zeros(1,'int32')
639 639 nr=numpy.zeros(1,'int32')
640 640 ngates=numpy.zeros(1,'int32') ### ### ### 2
641 641 time1=numpy.zeros(1,'uint64') # pos 3
642 642 time2=numpy.zeros(1,'uint64') # pos 4
643 643 lcounter=numpy.zeros(1,'int32')
644 644 groups=numpy.zeros(1,'int32')
645 645 system=numpy.zeros(4,'int8') # pos 7
646 646 h0=numpy.zeros(1,'float32')
647 647 dh=numpy.zeros(1,'float32')
648 648 ipp=numpy.zeros(1,'float32')
649 649 process=numpy.zeros(1,'int32')
650 650 tx=numpy.zeros(1,'int32')
651 651 ngates1=numpy.zeros(1,'int32') ### ### ### 13
652 652 time0=numpy.zeros(1,'uint64') # pos 14
653 653 nlags=numpy.zeros(1,'int32')
654 654 nlags1=numpy.zeros(1,'int32')
655 655 txb=numpy.zeros(1,'float32') ### ### ### 17
656 656 time3=numpy.zeros(1,'uint64') # pos 18
657 657 time4=numpy.zeros(1,'uint64') # pos 19
658 658 h0_=numpy.zeros(1,'float32')
659 659 dh_=numpy.zeros(1,'float32')
660 660 ipp_=numpy.zeros(1,'float32')
661 661 txa_=numpy.zeros(1,'float32')
662 662 pad=numpy.zeros(100,'int32')
663 663 nbytes=numpy.zeros(1,'int32')
664 664 limits=numpy.zeros(1,'int32')
665 665 ngroups=numpy.zeros(1,'int32') ### ### ### 27
666 666
667 667 dataOut.header=[hsize,bufsize,nr,ngates,time1,time2,
668 668 lcounter,groups,system,h0,dh,ipp,
669 669 process,tx,ngates1,padding,time0,nlags,
670 670 nlags1,padding,txb,time3,time4,h0_,dh_,
671 671 ipp_,txa_,pad,nbytes,limits,padding,ngroups]
672 672
673 673
674 674 #dataOut.header[1][0]=81864
675 675 dataOut.FirstHeight=int(dataOut.heightList[0])
676 676 dataOut.MAXNRANGENDT=max(dataOut.NRANGE,dataOut.NDT)
677 677 dataOut.header[3][0]=max(dataOut.NRANGE,dataOut.NDT)
678 678 dataOut.header[7][0]=dataOut.NAVG
679 679 dataOut.header[9][0]=int(dataOut.heightList[0])
680 680 dataOut.header[10][0]=dataOut.DH
681 681 dataOut.header[17][0]=dataOut.DPL
682 682 dataOut.header[18][0]=dataOut.NLAG
683 683 #self.header[5][0]=0
684 684 dataOut.header[15][0]=dataOut.NDP
685 685 dataOut.header[2][0]=dataOut.NR
686 686
687 687
688 688 def get_products_cabxys(self,dataOut):
689 689
690 690 if self.aux==1:
691 691 self.set_header_output(dataOut)
692 692 self.aux=0
693 693
694 694
695 695 dataOut.lags_array=[x / dataOut.DH for x in dataOut.flags_array]
696 696 self.cax=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
697 697 self.cay=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
698 698 self.cbx=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
699 699 self.cby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
700 700 self.cax2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
701 701 self.cay2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
702 702 self.cbx2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
703 703 self.cby2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
704 704 self.caxbx=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
705 705 self.caxby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
706 706 self.caybx=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
707 707 self.cayby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
708 708 self.caxay=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
709 709 self.cbxby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
710 710
711 711 for i in range(2):
712 712 for j in range(dataOut.NDP):
713 713 for k in range(int(dataOut.NSCAN/2)):
714 714 n=k%dataOut.DPL
715 715 ax=dataOut.data[0,2*k+i,j].real
716 716 ay=dataOut.data[0,2*k+i,j].imag
717 717 if j+dataOut.lags_array[n]<dataOut.NDP:
718 718 bx=dataOut.data[1,2*k+i,j+int(dataOut.lags_array[n])].real
719 719 by=dataOut.data[1,2*k+i,j+int(dataOut.lags_array[n])].imag
720 720 else:
721 721 if k+1<int(dataOut.NSCAN/2):
722 722 bx=dataOut.data[1,2*(k+1)+i,(dataOut.NRANGE+dataOut.NCAL+j+int(dataOut.lags_array[n]))%dataOut.NDP].real
723 723 by=dataOut.data[1,2*(k+1)+i,(dataOut.NRANGE+dataOut.NCAL+j+int(dataOut.lags_array[n]))%dataOut.NDP].imag
724 724
725 725 if k+1==int(dataOut.NSCAN/2):
726 726 bx=dataOut.data[1,2*k+i,(dataOut.NRANGE+dataOut.NCAL+j+int(dataOut.lags_array[n]))%dataOut.NDP].real
727 727 by=dataOut.data[1,2*k+i,(dataOut.NRANGE+dataOut.NCAL+j+int(dataOut.lags_array[n]))%dataOut.NDP].imag
728 728
729 729 if(k<dataOut.DPL):
730 730 self.cax[j][n][i]=ax
731 731 self.cay[j][n][i]=ay
732 732 self.cbx[j][n][i]=bx
733 733 self.cby[j][n][i]=by
734 734 self.cax2[j][n][i]=ax*ax
735 735 self.cay2[j][n][i]=ay*ay
736 736 self.cbx2[j][n][i]=bx*bx
737 737 self.cby2[j][n][i]=by*by
738 738 self.caxbx[j][n][i]=ax*bx
739 739 self.caxby[j][n][i]=ax*by
740 740 self.caybx[j][n][i]=ay*bx
741 741 self.cayby[j][n][i]=ay*by
742 742 self.caxay[j][n][i]=ax*ay
743 743 self.cbxby[j][n][i]=bx*by
744 744 else:
745 745 self.cax[j][n][i]+=ax
746 746 self.cay[j][n][i]+=ay
747 747 self.cbx[j][n][i]+=bx
748 748 self.cby[j][n][i]+=by
749 749 self.cax2[j][n][i]+=ax*ax
750 750 self.cay2[j][n][i]+=ay*ay
751 751 self.cbx2[j][n][i]+=bx*bx
752 752 self.cby2[j][n][i]+=by*by
753 753 self.caxbx[j][n][i]+=ax*bx
754 754 self.caxby[j][n][i]+=ax*by
755 755 self.caybx[j][n][i]+=ay*bx
756 756 self.cayby[j][n][i]+=ay*by
757 757 self.caxay[j][n][i]+=ax*ay
758 758 self.cbxby[j][n][i]+=bx*by
759 759
760 760
761 761 def medi(self,data_navg,NAVG,nkill):
762 762 sorts=sorted(data_navg)
763 763 rsorts=numpy.arange(NAVG)
764 764 result=0.0
765 765 for k in range(NAVG):
766 766 if k>=nkill/2 and k<NAVG-nkill/2:
767 767 result+=sorts[k]*float(NAVG)/(float)(NAVG-nkill)
768 768 return result
769 769
770 770
771 771 def get_dc(self,dataOut):
772 772 if self.bcounter==0:
773 773 dataOut.dc=numpy.zeros(dataOut.NR,dtype='complex64')
774 774 def cabxys_navg(self,dataOut):
775 775
776 776
777 777 #dataOut.header[5][0]=mktime(strptime(dataOut.TimeBlockDate))
778 778 dataOut.header[5][0]=dataOut.TimeBlockSeconds
779 779 #print(dataOut.TimeBlockDate)
780 780 #print(dataOut.utctime)
781 781 #print(dataOut.datatime)
782 782 #print(mktime(strptime(dataOut.TimeBlockDate)))
783 783 #print(dataOut.header[5][0])
784 784
785 785 #dataOut.LastAVGDate=mktime(strptime(dataOut.TimeBlockDate))
786 786 dataOut.LastAVGDate=dataOut.TimeBlockSeconds
787 787 #print(dataOut.TimeBlockDate)
788 788 #print(TimeBlockSeconds)
789 789 #input()
790 790 if self.bcounter==0:
791 791 #dataOut.FirstAVGDate=mktime(strptime(dataOut.TimeBlockDate))
792 792 dataOut.FirstAVGDate=dataOut.TimeBlockSeconds
793 793 dataOut.header[4][0]=dataOut.header[5][0]#firsttimeofNAVG
794 794 if dataOut.CurrentBlock==1:
795 795 #dataOut.FirstBlockDate=mktime(strptime(dataOut.TimeBlockDate))
796 796 dataOut.FirstBlockDate=dataOut.TimeBlockSeconds
797 797 dataOut.header[16][0]=dataOut.header[5][0]#FirsTimeOfTotalBlocks
798 798
799 799 self.cax_navg=[]
800 800 self.cay_navg=[]
801 801 self.cbx_navg=[]
802 802 self.cby_navg=[]
803 803 self.cax2_navg=[]
804 804 self.cay2_navg=[]
805 805 self.cbx2_navg=[]
806 806 self.cby2_navg=[]
807 807 self.caxbx_navg=[]
808 808 self.caxby_navg=[]
809 809 self.caybx_navg=[]
810 810 self.cayby_navg=[]
811 811 self.caxay_navg=[]
812 812 self.cbxby_navg=[]
813 813
814 814 dataOut.noisevector=numpy.zeros((dataOut.MAXNRANGENDT,dataOut.NR,dataOut.NAVG),'float32') #30/03/2020
815 815
816 816 dataOut.noisevector_=numpy.zeros((dataOut.read_samples,dataOut.NR,dataOut.NAVG),'float32')
817 817 #dataOut.dc=numpy.zeros(dataOut.NR,dtype=numpy.complex_) #30/03/2020
818 818 #self.dataOut.noisevector=numpy.zeros((self.dataOut.read_samples,2,self.dataOut.NAVG),'float32') #31/03/2020
819 819 #self.dataOut.noisevector_=numpy.zeros((self.dataOut.read_samples,2,self.dataOut.NAVG),'float32') #31/03/2020
820 820 #dataOut.dc=numpy.zeros(dataOut.NR,dtype='complex64')
821 821 #self.dataOut.dc=numpy.zeros(2,dtype=numpy.complex_) #31/03/2020
822 822 #self.dataOut.processingHeaderObj.profilesPerBlock
823 823
824 824 self.noisevectorizer(dataOut.NSCAN,dataOut.nProfiles,dataOut.NR,dataOut.MAXNRANGENDT,dataOut.noisevector,dataOut.data,dataOut.dc) #30/03/2020
825 825
826 826 #print(self.dataOut.noisevector[:,:,:])
827 827
828 828 self.cax_navg.append(self.cax)
829 829 self.cay_navg.append(self.cay)
830 830 self.cbx_navg.append(self.cbx)
831 831 self.cby_navg.append(self.cby)
832 832 self.cax2_navg.append(self.cax2)
833 833 self.cay2_navg.append(self.cay2)
834 834 self.cbx2_navg.append(self.cbx2)
835 835 self.cby2_navg.append(self.cby2)
836 836 self.caxbx_navg.append(self.caxbx)
837 837 self.caxby_navg.append(self.caxby)
838 838 self.caybx_navg.append(self.caybx)
839 839 self.cayby_navg.append(self.cayby)
840 840 self.caxay_navg.append(self.caxay)
841 841 self.cbxby_navg.append(self.cbxby)
842 842 self.bcounter+=1
843 843
844 844 def noise_estimation4x_DP(self,dataOut):
845 845 if self.bcounter==dataOut.NAVG:
846 846 dataOut.noise_final=numpy.zeros(dataOut.NR,'float32')
847 847 snoise=numpy.zeros((dataOut.NR,dataOut.NAVG),'float32')
848 848 nvector1=numpy.zeros((dataOut.NR,dataOut.NAVG,dataOut.MAXNRANGENDT),'float32')
849 849 for i in range(dataOut.NR):
850 850 dataOut.noise_final[i]=0.0
851 851 for k in range(dataOut.NAVG):
852 852 snoise[i][k]=0.0
853 853 for j in range(dataOut.MAXNRANGENDT):
854 854 nvector1[i][k][j]= dataOut.noisevector[j][i][k];
855 855 snoise[i][k]=self.noise_hs4x(dataOut.MAXNRANGENDT, nvector1[i][k])
856 856 #print("snoise",snoise[3,k])
857 857 dataOut.noise_final[i]=self.noise_hs4x(dataOut.NAVG, snoise[i])
858 858
859 859
860 860
861 861
862 862
863 863
864 864
865 865
866 866 def kabxys(self,dataOut):
867 867
868 868
869 869 #self.cabxys_navg(dataOut)
870 870
871 871
872 872 if self.bcounter==dataOut.NAVG:
873 873
874 874 dataOut.flagNoData = False
875 875
876 876
877 877 #dataOut.noise_final=numpy.zeros(dataOut.NR,'float32') #30/03/2020
878 878 #self.dataOut.noise_final=numpy.zeros(2,'float32') #31/03/2020
879 879
880 880
881 881 self.kax=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
882 882 self.kay=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
883 883 self.kbx=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
884 884 self.kby=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
885 885 self.kax2=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
886 886 self.kay2=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
887 887 self.kbx2=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
888 888 self.kby2=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
889 889 self.kaxbx=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
890 890 self.kaxby=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
891 891 self.kaybx=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
892 892 self.kayby=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
893 893 self.kaxay=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
894 894 self.kbxby=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
895 895
896 896 for i in range(self.cax_navg[0].shape[0]):
897 897 for j in range(self.cax_navg[0].shape[1]):
898 898 for k in range(self.cax_navg[0].shape[2]):
899 899 data_navg=[item[i,j,k] for item in self.cax_navg]
900 900 self.kax[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
901 901 data_navg=[item[i,j,k] for item in self.cay_navg]
902 902 self.kay[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
903 903 data_navg=[item[i,j,k] for item in self.cbx_navg]
904 904 self.kbx[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
905 905 data_navg=[item[i,j,k] for item in self.cby_navg]
906 906 self.kby[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
907 907 data_navg=[item[i,j,k] for item in self.cax2_navg]
908 908 self.kax2[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
909 909 data_navg=[item[i,j,k] for item in self.cay2_navg]
910 910 self.kay2[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
911 911 data_navg=[item[i,j,k] for item in self.cbx2_navg]
912 912 self.kbx2[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
913 913 data_navg=[item[i,j,k] for item in self.cby2_navg]
914 914 self.kby2[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
915 915 data_navg=[item[i,j,k] for item in self.caxbx_navg]
916 916 self.kaxbx[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
917 917 data_navg=[item[i,j,k] for item in self.caxby_navg]
918 918 self.kaxby[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
919 919 data_navg=[item[i,j,k] for item in self.caybx_navg]
920 920 self.kaybx[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
921 921 data_navg=[item[i,j,k] for item in self.cayby_navg]
922 922 self.kayby[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
923 923 data_navg=[item[i,j,k] for item in self.caxay_navg]
924 924 self.kaxay[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
925 925 data_navg=[item[i,j,k] for item in self.cbxby_navg]
926 926 self.kbxby[i,j,k]=self.medi(data_navg,dataOut.NAVG,dataOut.nkill)
927 927
928 928
929 929 dataOut.kax=self.kax
930 930 dataOut.kay=self.kay
931 931 dataOut.kbx=self.kbx
932 932 dataOut.kby=self.kby
933 933 dataOut.kax2=self.kax2
934 934 dataOut.kay2=self.kay2
935 935 dataOut.kbx2=self.kbx2
936 936 dataOut.kby2=self.kby2
937 937 dataOut.kaxbx=self.kaxbx
938 938 dataOut.kaxby=self.kaxby
939 939 dataOut.kaybx=self.kaybx
940 940 dataOut.kayby=self.kayby
941 941 dataOut.kaxay=self.kaxay
942 942 dataOut.kbxby=self.kbxby
943 943
944 944 self.bcounter=0
945 945
946 946 dataOut.crossprods=numpy.zeros((3,4,numpy.shape(dataOut.kax)[0],numpy.shape(dataOut.kax)[1],numpy.shape(dataOut.kax)[2]))
947 947
948 948 dataOut.crossprods[0]=[dataOut.kax,dataOut.kay,dataOut.kbx,dataOut.kby]
949 949 dataOut.crossprods[1]=[dataOut.kax2,dataOut.kay2,dataOut.kbx2,dataOut.kby2]
950 950 dataOut.crossprods[2]=[dataOut.kaxay,dataOut.kbxby,dataOut.kaxbx,dataOut.kaxby]
951 951 #print("before: ",self.dataOut.noise_final)
952 952 dataOut.data_for_RTI_DP=numpy.zeros((3,dataOut.NDP))
953 953 dataOut.data_for_RTI_DP[0],dataOut.data_for_RTI_DP[1],dataOut.data_for_RTI_DP[2]=self.RTI_COLUMN(dataOut.kax2,dataOut.kay2,dataOut.kbx2,dataOut.kby2,dataOut.kaxbx,dataOut.kayby,dataOut.kaybx,dataOut.kaxby, dataOut.NDP)
954 954
955 955
956 956
957 957 def RTI_COLUMN(self,kax2,kay2,kbx2,kby2,kaxbx,kayby,kaybx,kaxby, NDP):
958 958 x00=numpy.zeros(NDP,dtype='float32')
959 959 x01=numpy.zeros(NDP,dtype='float32')
960 960 x02=numpy.zeros(NDP,dtype='float32')
961 961 for j in range(2):# first couple lags
962 962 for k in range(2): #flip
963 963 for i in range(NDP): #
964 964 fx=numpy.sqrt((kaxbx[i,j,k]+kayby[i,j,k])**2+(kaybx[i,j,k]-kaxby[i,j,k])**2)
965 965 x00[i]=x00[i]+(kax2[i,j,k]+kay2[i,j,k])
966 966 x01[i]=x01[i]+(kbx2[i,j,k]+kby2[i,j,k])
967 967 x02[i]=x02[i]+fx
968 968
969 969 x00[i]=10.0*numpy.log10(x00[i]/4.)
970 970 x01[i]=10.0*numpy.log10(x01[i]/4.)
971 971 x02[i]=10.0*numpy.log10(x02[i])
972 972 return x02,x00,x01
973 973
974 974
975 975
976 976
977 977
978 978
979 979 #30/03/2020:
980 980 def noisevectorizer(self,NSCAN,nProfiles,NR,MAXNRANGENDT,noisevector,data,dc):
981 981
982 982 rnormalizer= 1./(float(nProfiles - NSCAN))
983 983 #rnormalizer= float(NSCAN)/((float(nProfiles - NSCAN))*float(MAXNRANGENDT))
984 984 for i in range(NR):
985 985 for j in range(MAXNRANGENDT):
986 986 for k in range(NSCAN,nProfiles):
987 987 #TODO:integrate just 2nd quartile gates
988 988 if k==NSCAN:
989 989 noisevector[j][i][self.bcounter]=(abs(data[i][k][j]-dc[i])**2)*rnormalizer
990 990 else:
991 991 noisevector[j][i][self.bcounter]+=(abs(data[i][k][j]-dc[i])**2)*rnormalizer
992 992
993 993
994 994
995 995
996 996 def noise_hs4x(self, ndatax, datax):
997 997 divider=10#divider was originally 10
998 998 noise=0.0
999 999 data=numpy.zeros(ndatax,'float32')
1000 1000 ndata1=int(ndatax/4)
1001 1001 ndata2=int(2.5*(ndatax/4.))
1002 1002 ndata=int(ndata2-ndata1)
1003 1003 sorts=sorted(datax)
1004 1004
1005 1005 for k in range(ndata2): # select just second quartile
1006 1006 data[k]=sorts[k+ndata1]
1007 1007 nums_min= int(ndata/divider)
1008 1008 if(int(ndata/divider)> 2):
1009 1009 nums_min= int(ndata/divider)
1010 1010 else:
1011 1011 nums_min=2
1012 1012 sump=0.0
1013 1013 sumq=0.0
1014 1014 j=0
1015 1015 cont=1
1016 1016 while ( (cont==1) and (j<ndata)):
1017 1017 sump+=data[j]
1018 1018 sumq+= data[j]*data[j]
1019 1019 j=j+1
1020 1020 if (j> nums_min):
1021 1021 rtest= float(j/(j-1)) +1.0/ndata
1022 1022 if( (sumq*j) > (rtest*sump*sump ) ):
1023 1023 j=j-1
1024 1024 sump-= data[j]
1025 1025 sumq-=data[j]*data[j]
1026 1026 cont= 0
1027 1027 noise= (sump/j)
1028 1028
1029 1029 return noise
1030 1030
1031 1031
1032 1032
1033 1033 def run(self, dataOut, NLAG=16, NRANGE=0, NCAL=0, DPL=11,
1034 1034 NDN=0, NDT=66, NDP=66, NSCAN=132,
1035 1035 flags_array=(0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300), NAVG=16, nkill=6, **kwargs):
1036 1036
1037 1037 dataOut.NLAG=NLAG
1038 1038 dataOut.NR=len(dataOut.channelList)
1039 1039 dataOut.NRANGE=NRANGE
1040 1040 dataOut.NCAL=NCAL
1041 1041 dataOut.DPL=DPL
1042 1042 dataOut.NDN=NDN
1043 1043 dataOut.NDT=NDT
1044 1044 dataOut.NDP=NDP
1045 1045 dataOut.NSCAN=NSCAN
1046 1046 dataOut.DH=dataOut.heightList[1]-dataOut.heightList[0]
1047 1047 dataOut.H0=int(dataOut.heightList[0])
1048 1048 dataOut.flags_array=flags_array
1049 1049 dataOut.NAVG=NAVG
1050 1050 dataOut.nkill=nkill
1051 1051 dataOut.flagNoData = True
1052 1052
1053 1053 self.get_dc(dataOut)
1054 1054 self.get_products_cabxys(dataOut)
1055 1055 self.cabxys_navg(dataOut)
1056 1056 self.noise_estimation4x_DP(dataOut)
1057 1057 self.kabxys(dataOut)
1058 1058
1059 1059 return dataOut
1060 1060
1061 1061
1062 1062
1063 1063 class IntegrationDP(Operation):
1064 1064 """Operation to integrate the Double Pulse data.
1065 1065
1066 1066 Parameters:
1067 1067 -----------
1068 1068 nint : int
1069 1069 Number of integrations.
1070 1070
1071 1071 Example
1072 1072 --------
1073 1073
1074 1074 op = proc_unit.addOperation(name='IntegrationDP', optype='other')
1075 1075 op.addParameter(name='nint', value='30', format='int')
1076 1076
1077 1077 """
1078 1078
1079 1079 def __init__(self, **kwargs):
1080 1080
1081 1081 Operation.__init__(self, **kwargs)
1082 1082
1083 1083 self.counter=0
1084 1084 self.aux=0
1085 1085 self.init_time=None
1086 1086
1087 1087 def integration_for_double_pulse(self,dataOut):
1088 1088 #print("inside")
1089 1089 #print(self.aux)
1090 1090 if self.aux==1:
1091 1091 #print("CurrentBlockBBBBB: ",dataOut.CurrentBlock)
1092 1092 #print(dataOut.datatime)
1093 1093
1094 1094 #dataOut.TimeBlockDate_for_dp_power=dataOut.TimeBlockDate
1095 1095 ########dataOut.TimeBlockSeconds_for_dp_power=dataOut.LastAVGDate
1096 1096 #print("Date: ",dataOut.TimeBlockDate_for_dp_power)
1097 1097
1098 1098 #dataOut.TimeBlockSeconds_for_dp_power=mktime(strptime(dataOut.TimeBlockDate_for_dp_power))
1099 1099 dataOut.TimeBlockSeconds_for_dp_power=dataOut.utctime#dataOut.TimeBlockSeconds-18000
1100 1100 #dataOut.TimeBlockSeconds_for_dp_power=dataOut.LastAVGDate
1101 1101 #print("Seconds: ",dataOut.TimeBlockSeconds_for_dp_power)
1102 1102 dataOut.bd_time=gmtime(dataOut.TimeBlockSeconds_for_dp_power)
1103 1103 #print(dataOut.bd_time)
1104 1104 #exit()
1105 1105 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
1106 1106 dataOut.ut_Faraday=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
1107 1107 #print("date: ", dataOut.TimeBlockDate)
1108 1108
1109 1109
1110 1110 self.aux=0
1111 1111
1112 1112 #print("after")
1113 1113
1114 1114 if self.counter==0:
1115 1115
1116 1116 tmpx=numpy.zeros((dataOut.NDP,dataOut.DPL,2),'float32')
1117 1117 dataOut.kabxys_integrated=[tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx]
1118 1118 self.init_time=dataOut.utctime
1119 1119
1120 1120 if self.counter < dataOut.nint:
1121 1121 #print("HERE")
1122 1122
1123 1123 dataOut.final_cross_products=[dataOut.kax,dataOut.kay,dataOut.kbx,dataOut.kby,dataOut.kax2,dataOut.kay2,dataOut.kbx2,dataOut.kby2,dataOut.kaxbx,dataOut.kaxby,dataOut.kaybx,dataOut.kayby,dataOut.kaxay,dataOut.kbxby]
1124 1124
1125 1125 for ind in range(len(dataOut.kabxys_integrated)): #final cross products
1126 1126 dataOut.kabxys_integrated[ind]=dataOut.kabxys_integrated[ind]+dataOut.final_cross_products[ind]
1127 1127
1128 1128 self.counter+=1
1129 1129
1130 1130 if self.counter==dataOut.nint-1:
1131 1131 self.aux=1
1132 1132 #dataOut.TimeBlockDate_for_dp_power=dataOut.TimeBlockDate
1133 1133 if self.counter==dataOut.nint:
1134 1134
1135 1135 dataOut.flagNoData=False
1136 1136 dataOut.utctime=self.init_time
1137 1137 self.counter=0
1138 1138
1139 1139
1140 1140 def run(self,dataOut,nint=20):
1141 1141
1142 1142 dataOut.flagNoData=True
1143 1143 dataOut.nint=nint
1144 1144 dataOut.paramInterval=0#int(dataOut.nint*dataOut.header[7][0]*2 )
1145 1145 dataOut.lat=-11.95
1146 1146 dataOut.lon=-76.87
1147 1147
1148 1148 self.integration_for_double_pulse(dataOut)
1149 1149
1150 1150 return dataOut
1151 1151
1152 1152
1153 1153 class SumFlips(Operation):
1154 1154 """Operation to sum the flip and unflip part of certain cross products of the Double Pulse.
1155 1155
1156 1156 Parameters:
1157 1157 -----------
1158 1158 None
1159 1159
1160 1160 Example
1161 1161 --------
1162 1162
1163 1163 op = proc_unit.addOperation(name='SumFlips', optype='other')
1164 1164
1165 1165 """
1166 1166
1167 1167 def __init__(self, **kwargs):
1168 1168
1169 1169 Operation.__init__(self, **kwargs)
1170 1170
1171 1171
1172 1172 def rint2DP(self,dataOut):
1173 1173
1174 1174 dataOut.rnint2=numpy.zeros(dataOut.DPL,'float32')
1175 1175
1176 1176 for l in range(dataOut.DPL):
1177 1177
1178 1178 dataOut.rnint2[l]=1.0/(dataOut.nint*dataOut.NAVG*12.0)
1179 1179
1180 1180
1181 1181 def SumLags(self,dataOut):
1182 1182
1183 1183 for l in range(dataOut.DPL):
1184 1184
1185 1185 dataOut.kabxys_integrated[4][:,l,0]=(dataOut.kabxys_integrated[4][:,l,0]+dataOut.kabxys_integrated[4][:,l,1])*dataOut.rnint2[l]
1186 1186 dataOut.kabxys_integrated[5][:,l,0]=(dataOut.kabxys_integrated[5][:,l,0]+dataOut.kabxys_integrated[5][:,l,1])*dataOut.rnint2[l]
1187 1187 dataOut.kabxys_integrated[6][:,l,0]=(dataOut.kabxys_integrated[6][:,l,0]+dataOut.kabxys_integrated[6][:,l,1])*dataOut.rnint2[l]
1188 1188 dataOut.kabxys_integrated[7][:,l,0]=(dataOut.kabxys_integrated[7][:,l,0]+dataOut.kabxys_integrated[7][:,l,1])*dataOut.rnint2[l]
1189 1189
1190 1190 dataOut.kabxys_integrated[8][:,l,0]=(dataOut.kabxys_integrated[8][:,l,0]-dataOut.kabxys_integrated[8][:,l,1])*dataOut.rnint2[l]
1191 1191 dataOut.kabxys_integrated[9][:,l,0]=(dataOut.kabxys_integrated[9][:,l,0]-dataOut.kabxys_integrated[9][:,l,1])*dataOut.rnint2[l]
1192 1192 dataOut.kabxys_integrated[10][:,l,0]=(dataOut.kabxys_integrated[10][:,l,0]-dataOut.kabxys_integrated[10][:,l,1])*dataOut.rnint2[l]
1193 1193 dataOut.kabxys_integrated[11][:,l,0]=(dataOut.kabxys_integrated[11][:,l,0]-dataOut.kabxys_integrated[11][:,l,1])*dataOut.rnint2[l]
1194 1194
1195 1195
1196 1196 def run(self,dataOut):
1197 1197
1198 1198 self.rint2DP(dataOut)
1199 1199 self.SumLags(dataOut)
1200 1200
1201 1201 return dataOut
1202 1202
1203 1203
1204 1204 class FlagBadHeights(Operation):
1205 1205 """Operation to flag bad heights (bad data) of the Double Pulse.
1206 1206
1207 1207 Parameters:
1208 1208 -----------
1209 1209 None
1210 1210
1211 1211 Example
1212 1212 --------
1213 1213
1214 1214 op = proc_unit.addOperation(name='FlagBadHeights', optype='other')
1215 1215
1216 1216 """
1217 1217
1218 1218 def __init__(self, **kwargs):
1219 1219
1220 1220 Operation.__init__(self, **kwargs)
1221 1221
1222 1222 def run(self,dataOut):
1223 1223
1224 1224 dataOut.ibad=numpy.zeros((dataOut.NDP,dataOut.DPL),'int32')
1225 1225
1226 1226 for j in range(dataOut.NDP):
1227 1227 for l in range(dataOut.DPL):
1228 1228 ip1=j+dataOut.NDP*(0+2*l)
1229 1229
1230 1230 if( (dataOut.kabxys_integrated[5][j,l,0] <= 0.) or (dataOut.kabxys_integrated[4][j,l,0] <= 0.) or (dataOut.kabxys_integrated[7][j,l,0] <= 0.) or (dataOut.kabxys_integrated[6][j,l,0] <= 0.)):
1231 1231 dataOut.ibad[j][l]=1
1232 1232 else:
1233 1233 dataOut.ibad[j][l]=0
1234 1234
1235 1235 return dataOut
1236 1236
1237 1237 class FlagBadHeightsSpectra(Operation):
1238 1238 """Operation to flag bad heights (bad data) of the Double Pulse.
1239 1239
1240 1240 Parameters:
1241 1241 -----------
1242 1242 None
1243 1243
1244 1244 Example
1245 1245 --------
1246 1246
1247 1247 op = proc_unit.addOperation(name='FlagBadHeightsSpectra', optype='other')
1248 1248
1249 1249 """
1250 1250
1251 1251 def __init__(self, **kwargs):
1252 1252
1253 1253 Operation.__init__(self, **kwargs)
1254 1254
1255 1255 def run(self,dataOut):
1256 1256
1257 1257 dataOut.ibad=numpy.zeros((dataOut.NDP,dataOut.DPL),'int32')
1258 1258
1259 1259 for j in range(dataOut.NDP):
1260 1260 for l in range(dataOut.DPL):
1261 1261 ip1=j+dataOut.NDP*(0+2*l)
1262 1262
1263 1263 if( (dataOut.kabxys_integrated[4][j,l,0] <= 0.) or (dataOut.kabxys_integrated[6][j,l,0] <= 0.)):
1264 1264 dataOut.ibad[j][l]=1
1265 1265 else:
1266 1266 dataOut.ibad[j][l]=0
1267 1267
1268 1268 return dataOut
1269 1269
1270 1270 class NoisePower(Operation):
1271 1271 """Operation to get noise power from the integrated data of the Double Pulse.
1272 1272
1273 1273 Parameters:
1274 1274 -----------
1275 1275 None
1276 1276
1277 1277 Example
1278 1278 --------
1279 1279
1280 1280 op = proc_unit.addOperation(name='NoisePower', optype='other')
1281 1281
1282 1282 """
1283 1283
1284 1284 def __init__(self, **kwargs):
1285 1285
1286 1286 Operation.__init__(self, **kwargs)
1287 1287
1288 1288 def hildebrand(self,dataOut,data):
1289 1289
1290 1290 divider=10 # divider was originally 10
1291 1291 noise=0.0
1292 1292 n1=0
1293 1293 n2=int(dataOut.NDP/2)
1294 1294 sorts= sorted(data)
1295 1295 nums_min= dataOut.NDP/divider
1296 1296 if((dataOut.NDP/divider)> 2):
1297 1297 nums_min= int(dataOut.NDP/divider)
1298 1298
1299 1299 else:
1300 1300 nums_min=2
1301 1301 sump=0.0
1302 1302 sumq=0.0
1303 1303 j=0
1304 1304 cont=1
1305 1305 while( (cont==1) and (j<n2)):
1306 1306 sump+=sorts[j+n1]
1307 1307 sumq+= sorts[j+n1]*sorts[j+n1]
1308 1308 t3= sump/(j+1)
1309 1309 j=j+1
1310 1310 if(j> nums_min):
1311 1311 rtest= float(j/(j-1)) +1.0/dataOut.NAVG
1312 1312 t1= (sumq*j)
1313 1313 t2=(rtest*sump*sump)
1314 1314 if( (t1/t2) > 0.990):
1315 1315 j=j-1
1316 1316 sump-= sorts[j+n1]
1317 1317 sumq-=sorts[j+n1]*sorts[j+n1]
1318 1318 cont= 0
1319 1319
1320 1320 noise= sump/j
1321 1321 stdv=numpy.sqrt((sumq- noise*noise)/(j-1))
1322 1322 return noise
1323 1323
1324 1324 def run(self,dataOut):
1325 1325
1326 1326 p=numpy.zeros((dataOut.NR,dataOut.NDP,dataOut.DPL),'float32')
1327 1327 av=numpy.zeros(dataOut.NDP,'float32')
1328 1328 dataOut.pnoise=numpy.zeros(dataOut.NR,'float32')
1329 1329
1330 1330 p[0,:,:]=dataOut.kabxys_integrated[4][:,:,0]+dataOut.kabxys_integrated[5][:,:,0] #total power for channel 0, just pulse with non-flip
1331 1331 p[1,:,:]=dataOut.kabxys_integrated[6][:,:,0]+dataOut.kabxys_integrated[7][:,:,0] #total power for channel 1
1332 1332
1333 1333 for i in range(dataOut.NR):
1334 1334 dataOut.pnoise[i]=0.0
1335 1335 for k in range(dataOut.DPL):
1336 1336 dataOut.pnoise[i]+= self.hildebrand(dataOut,p[i,:,k])
1337 1337
1338 1338 dataOut.pnoise[i]=dataOut.pnoise[i]/dataOut.DPL
1339 1339
1340 1340
1341 1341 dataOut.pan=1.0*dataOut.pnoise[0] # weights could change
1342 1342 dataOut.pbn=1.0*dataOut.pnoise[1] # weights could change
1343 1343
1344 1344 return dataOut
1345 1345
1346 1346
1347 1347 class DoublePulseACFs(Operation):
1348 1348 """Operation to get the ACFs of the Double Pulse.
1349 1349
1350 1350 Parameters:
1351 1351 -----------
1352 1352 None
1353 1353
1354 1354 Example
1355 1355 --------
1356 1356
1357 1357 op = proc_unit.addOperation(name='DoublePulseACFs', optype='other')
1358 1358
1359 1359 """
1360 1360
1361 1361 def __init__(self, **kwargs):
1362 1362
1363 1363 Operation.__init__(self, **kwargs)
1364 1364 self.aux=1
1365 1365
1366 1366 def run(self,dataOut):
1367 1367
1368 1368 dataOut.igcej=numpy.zeros((dataOut.NDP,dataOut.DPL),'int32')
1369 1369
1370 1370 if self.aux==1:
1371 1371 dataOut.rhor=numpy.zeros((dataOut.NDP,dataOut.DPL), dtype=float)
1372 1372 dataOut.rhoi=numpy.zeros((dataOut.NDP,dataOut.DPL), dtype=float)
1373 1373 dataOut.sdp=numpy.zeros((dataOut.NDP,dataOut.DPL), dtype=float)
1374 1374 dataOut.sd=numpy.zeros((dataOut.NDP,dataOut.DPL), dtype=float)
1375 1375 dataOut.p=numpy.zeros((dataOut.NDP,dataOut.DPL), dtype=float)
1376 1376 dataOut.alag=numpy.zeros(dataOut.NDP,'float32')
1377 1377 for l in range(dataOut.DPL):
1378 1378 dataOut.alag[l]=l*dataOut.DH*2.0/150.0
1379 1379 self.aux=0
1380 1380 sn4=dataOut.pan*dataOut.pbn
1381 1381 rhorn=0
1382 1382 rhoin=0
1383 1383 panrm=numpy.zeros((dataOut.NDP,dataOut.DPL), dtype=float)
1384 1384
1385 1385 for i in range(dataOut.NDP):
1386 1386 for j in range(dataOut.DPL):
1387 1387 ################# Total power
1388 1388 pa=numpy.abs(dataOut.kabxys_integrated[4][i,j,0]+dataOut.kabxys_integrated[5][i,j,0])
1389 1389 pb=numpy.abs(dataOut.kabxys_integrated[6][i,j,0]+dataOut.kabxys_integrated[7][i,j,0])
1390 1390 st4=pa*pb
1391 1391 dataOut.p[i,j]=pa+pb-(dataOut.pan+dataOut.pbn)
1392 1392 dataOut.sdp[i,j]=2*dataOut.rnint2[j]*((pa+pb)*(pa+pb))
1393 1393 ## ACF
1394 1394 rhorp=dataOut.kabxys_integrated[8][i,j,0]+dataOut.kabxys_integrated[11][i,j,0]
1395 1395 rhoip=dataOut.kabxys_integrated[10][i,j,0]-dataOut.kabxys_integrated[9][i,j,0]
1396 1396 if ((pa>dataOut.pan)&(pb>dataOut.pbn)):
1397 1397
1398 1398 ss4=numpy.abs((pa-dataOut.pan)*(pb-dataOut.pbn))
1399 1399 panrm[i,j]=math.sqrt(ss4)
1400 1400 rnorm=1/panrm[i,j]
1401 1401 ## ACF
1402 1402 dataOut.rhor[i,j]=rhorp*rnorm
1403 1403 dataOut.rhoi[i,j]=rhoip*rnorm
1404 1404 ############# Compute standard error for ACF
1405 1405 stoss4=st4/ss4
1406 1406 snoss4=sn4/ss4
1407 1407 rp2=((rhorp*rhorp)+(rhoip*rhoip))/st4
1408 1408 rn2=((rhorn*rhorn)+(rhoin*rhoin))/sn4
1409 1409 rs2=(dataOut.rhor[i,j]*dataOut.rhor[i,j])+(dataOut.rhoi[i,j]*dataOut.rhoi[i,j])
1410 1410 st=1.0+rs2*(stoss4-(2*math.sqrt(stoss4*snoss4)))
1411 1411 stn=1.0+rs2*(snoss4-(2*math.sqrt(stoss4*snoss4)))
1412 1412 dataOut.sd[i,j]=((stoss4*((1.0+rp2)*st+(2.0*rp2*rs2*snoss4)-4.0*math.sqrt(rs2*rp2)))+(0.25*snoss4*((1.0+rn2)*stn+(2.0*rn2*rs2*stoss4)-4.0*math.sqrt(rs2*rn2))))*dataOut.rnint2[j]
1413 1413 dataOut.sd[i,j]=numpy.abs(dataOut.sd[i,j])
1414 1414
1415 1415 else: #default values for bad points
1416 1416 rnorm=1/math.sqrt(st4)
1417 1417 dataOut.sd[i,j]=1.e30
1418 1418 dataOut.ibad[i,j]=4
1419 1419 dataOut.rhor[i,j]=rhorp*rnorm
1420 1420 dataOut.rhoi[i,j]=rhoip*rnorm
1421 1421
1422 1422 if ((pa/dataOut.pan-1.0)>2.25*(pb/dataOut.pbn-1.0)):
1423 1423 dataOut.igcej[i,j]=1
1424 1424
1425 1425 return dataOut
1426 1426
1427 1427
1428 1428 class FaradayAngleAndDPPower(Operation):
1429 1429 """Operation to calculate Faraday angle and Double Pulse power.
1430 1430
1431 1431 Parameters:
1432 1432 -----------
1433 1433 None
1434 1434
1435 1435 Example
1436 1436 --------
1437 1437
1438 1438 op = proc_unit.addOperation(name='FaradayAngleAndDPPower', optype='other')
1439 1439
1440 1440 """
1441 1441
1442 1442 def __init__(self, **kwargs):
1443 1443
1444 1444 Operation.__init__(self, **kwargs)
1445 1445 self.aux=1
1446 1446
1447 1447 def run(self,dataOut):
1448 1448
1449 1449 if self.aux==1:
1450 1450 dataOut.h2=numpy.zeros(dataOut.MAXNRANGENDT,'float32')
1451 1451 dataOut.range1=numpy.zeros(dataOut.MAXNRANGENDT,order='F',dtype='float32')
1452 1452 dataOut.sdn2=numpy.zeros(dataOut.NDP,'float32')
1453 1453 dataOut.ph2=numpy.zeros(dataOut.NDP,'float32')
1454 1454 dataOut.sdp2=numpy.zeros(dataOut.NDP,'float32')
1455 1455 dataOut.ibd=numpy.zeros(dataOut.NDP,'float32')
1456 1456 dataOut.phi=numpy.zeros(dataOut.NDP,'float32')
1457 1457
1458 1458 self.aux=0
1459 1459
1460 1460 for i in range(dataOut.MAXNRANGENDT):
1461 1461 dataOut.range1[i]=dataOut.H0 + i*dataOut.DH
1462 1462 dataOut.h2[i]=dataOut.range1[i]**2
1463 1463
1464 1464 for j in range(dataOut.NDP):
1465 1465 dataOut.ph2[j]=0.
1466 1466 dataOut.sdp2[j]=0.
1467 1467 ri=dataOut.rhoi[j][0]/dataOut.sd[j][0]
1468 1468 rr=dataOut.rhor[j][0]/dataOut.sd[j][0]
1469 1469 dataOut.sdn2[j]=1./dataOut.sd[j][0]
1470 1470
1471 1471 pt=0.# // total power
1472 1472 st=0.# // total signal
1473 1473 ibt=0# // bad lags
1474 1474 ns=0# // no. good lags
1475 1475 for l in range(dataOut.DPL):
1476 1476 #add in other lags if outside of e-jet contamination
1477 1477 if( (dataOut.igcej[j][l] == 0) and (dataOut.ibad[j][l] == 0) ):
1478 1478
1479 1479 dataOut.ph2[j]+=dataOut.p[j][l]/dataOut.sdp[j][l]
1480 1480 dataOut.sdp2[j]=dataOut.sdp2[j]+1./dataOut.sdp[j][l]
1481 1481 ns+=1
1482 1482
1483 1483
1484 1484 pt+=dataOut.p[j][l]/dataOut.sdp[j][l]
1485 1485 st+=1./dataOut.sdp[j][l]
1486 1486 ibt|=dataOut.ibad[j][l];
1487 1487 if(ns!= 0):
1488 1488 dataOut.ibd[j]=0
1489 1489 dataOut.ph2[j]=dataOut.ph2[j]/dataOut.sdp2[j]
1490 1490 dataOut.sdp2[j]=1./dataOut.sdp2[j]
1491 1491 else:
1492 1492 dataOut.ibd[j]=ibt
1493 1493 dataOut.ph2[j]=pt/st
1494 1494 dataOut.sdp2[j]=1./st
1495 1495
1496 1496 dataOut.ph2[j]=dataOut.ph2[j]*dataOut.h2[j]
1497 1497 dataOut.sdp2[j]=numpy.sqrt(dataOut.sdp2[j])*dataOut.h2[j]
1498 1498 rr=rr/dataOut.sdn2[j]
1499 1499 ri=ri/dataOut.sdn2[j]
1500 1500 #rm[j]=np.sqrt(rr*rr + ri*ri) it is not used in c program
1501 1501 dataOut.sdn2[j]=1./(dataOut.sdn2[j]*(rr*rr + ri*ri))
1502 1502 if( (ri == 0.) and (rr == 0.) ):
1503 1503 dataOut.phi[j]=0.
1504 1504 else:
1505 1505 dataOut.phi[j]=math.atan2( ri , rr )
1506 1506
1507 1507 return dataOut
1508 1508
1509 1509
1510 1510 class ElectronDensityFaraday(Operation):
1511 1511 """Operation to calculate electron density from Faraday angle.
1512 1512
1513 1513 Parameters:
1514 1514 -----------
1515 1515 NSHTS : int
1516 1516 .*
1517 1517 RATE : float
1518 1518 .*
1519 1519
1520 1520 Example
1521 1521 --------
1522 1522
1523 1523 op = proc_unit.addOperation(name='ElectronDensityFaraday', optype='other')
1524 1524 op.addParameter(name='NSHTS', value='50', format='int')
1525 1525 op.addParameter(name='RATE', value='1.8978873e-6', format='float')
1526 1526
1527 1527 """
1528 1528
1529 1529 def __init__(self, **kwargs):
1530 1530
1531 1531 Operation.__init__(self, **kwargs)
1532 1532 self.aux=1
1533 1533
1534 1534 def run(self,dataOut,NSHTS=50,RATE=1.8978873e-6):
1535 1535
1536 1536 #print(ctime(dataOut.utctime))
1537 1537 #3print("Faraday Angle",dataOut.phi)
1538 1538
1539 1539 dataOut.NSHTS=NSHTS
1540 1540 dataOut.RATE=RATE
1541 1541
1542 1542 if self.aux==1:
1543 1543 dataOut.dphi=numpy.zeros(dataOut.NDP,'float32')
1544 1544 dataOut.sdn1=numpy.zeros(dataOut.NDP,'float32')
1545 1545 self.aux=0
1546 1546 theta=numpy.zeros(dataOut.NDP,dtype=numpy.complex_)
1547 1547 thetai=numpy.zeros(dataOut.NDP,dtype=numpy.complex_)
1548 1548 # use complex numbers for phase
1549 1549 for i in range(dataOut.NSHTS):
1550 1550 theta[i]=math.cos(dataOut.phi[i])+math.sin(dataOut.phi[i])*1j
1551 1551 thetai[i]=-math.sin(dataOut.phi[i])+math.cos(dataOut.phi[i])*1j
1552 1552
1553 1553 # differentiate and convert to number density
1554 1554 ndphi=dataOut.NSHTS-4
1555 1555 for i in range(2,dataOut.NSHTS-2):
1556 1556 fact=(-0.5/(dataOut.RATE*dataOut.DH))*dataOut.bki[i]
1557 1557 #four-point derivative, no phase unwrapping necessary
1558 1558 ####dataOut.dphi[i]=((((theta[i+1]-theta[i-1])+(2.0*(theta[i+2]-theta[i-2])))/thetai[i])).real/10.0
1559 1559 dataOut.dphi[i]=((((theta[i-2]-theta[i+2])+(8.0*(theta[i+1]-theta[i-1])))/thetai[i])).real/12.0
1560 1560
1561 1561 dataOut.dphi[i]=abs(dataOut.dphi[i]*fact)
1562 1562 dataOut.sdn1[i]=(4.*(dataOut.sdn2[i-2]+dataOut.sdn2[i+2])+dataOut.sdn2[i-1]+dataOut.sdn2[i+1])
1563 1563 dataOut.sdn1[i]=numpy.sqrt(dataOut.sdn1[i])*fact
1564 1564
1565 1565 return dataOut
1566 1566
1567 1567 class ElectronDensityRobertoTestFaraday(Operation):
1568 1568 """Operation to calculate electron density from Faraday angle.
1569 1569
1570 1570 Parameters:
1571 1571 -----------
1572 1572 NSHTS : int
1573 1573 .*
1574 1574 RATE : float
1575 1575 .*
1576 1576
1577 1577 Example
1578 1578 --------
1579 1579
1580 1580 op = proc_unit.addOperation(name='ElectronDensityFaraday', optype='other')
1581 1581 op.addParameter(name='NSHTS', value='50', format='int')
1582 1582 op.addParameter(name='RATE', value='1.8978873e-6', format='float')
1583 1583
1584 1584 """
1585 1585
1586 1586 def __init__(self, **kwargs):
1587 1587
1588 1588 Operation.__init__(self, **kwargs)
1589 1589 self.aux=1
1590 1590
1591 1591 def run(self,dataOut,NSHTS=50,RATE=1.8978873e-6):
1592 1592
1593 1593 #print(ctime(dataOut.utctime))
1594 1594 #print("Faraday Angle",dataOut.phi)
1595 1595
1596 1596 dataOut.NSHTS=NSHTS
1597 1597 dataOut.RATE=RATE
1598 1598
1599 1599 if self.aux==1:
1600 1600 dataOut.dphi=numpy.zeros(dataOut.NDP,'float32')
1601 1601 dataOut.sdn1=numpy.zeros(dataOut.NDP,'float32')
1602 1602 self.aux=0
1603 1603 theta=numpy.zeros(dataOut.NDP,dtype=numpy.complex_)
1604 1604 thetai=numpy.zeros(dataOut.NDP,dtype=numpy.complex_)
1605 1605 # use complex numbers for phase
1606 1606 '''
1607 1607 for i in range(dataOut.NSHTS):
1608 1608 theta[i]=math.cos(dataOut.phi[i])+math.sin(dataOut.phi[i])*1j
1609 1609 thetai[i]=-math.sin(dataOut.phi[i])+math.cos(dataOut.phi[i])*1j
1610 1610 '''
1611 1611
1612 1612 # differentiate and convert to number density
1613 1613 ndphi=dataOut.NSHTS-4
1614 1614
1615 1615 dataOut.phi=numpy.unwrap(dataOut.phi)
1616 1616
1617 1617 for i in range(2,dataOut.NSHTS-2):
1618 1618 fact=(-0.5/(dataOut.RATE*dataOut.DH))*dataOut.bki[i]
1619 1619 #four-point derivative, no phase unwrapping necessary
1620 1620 ####dataOut.dphi[i]=((((theta[i+1]-theta[i-1])+(2.0*(theta[i+2]-theta[i-2])))/thetai[i])).real/10.0
1621 1621 ##dataOut.dphi[i]=((((theta[i-2]-theta[i+2])+(8.0*(theta[i+1]-theta[i-1])))/thetai[i])).real/12.0
1622 1622 dataOut.dphi[i]=((dataOut.phi[i+1]-dataOut.phi[i-1])+(2.0*(dataOut.phi[i+2]-dataOut.phi[i-2])))/10.0
1623 1623
1624 1624 dataOut.dphi[i]=abs(dataOut.dphi[i]*fact)
1625 1625 dataOut.sdn1[i]=(4.*(dataOut.sdn2[i-2]+dataOut.sdn2[i+2])+dataOut.sdn2[i-1]+dataOut.sdn2[i+1])
1626 1626 dataOut.sdn1[i]=numpy.sqrt(dataOut.sdn1[i])*fact
1627 1627
1628 1628 return dataOut
1629 1629
1630 1630 class ElectronDensityRobertoTest2Faraday(Operation):
1631 1631 """Operation to calculate electron density from Faraday angle.
1632 1632
1633 1633 Parameters:
1634 1634 -----------
1635 1635 NSHTS : int
1636 1636 .*
1637 1637 RATE : float
1638 1638 .*
1639 1639
1640 1640 Example
1641 1641 --------
1642 1642
1643 1643 op = proc_unit.addOperation(name='ElectronDensityFaraday', optype='other')
1644 1644 op.addParameter(name='NSHTS', value='50', format='int')
1645 1645 op.addParameter(name='RATE', value='1.8978873e-6', format='float')
1646 1646
1647 1647 """
1648 1648
1649 1649 def __init__(self, **kwargs):
1650 1650
1651 1651 Operation.__init__(self, **kwargs)
1652 1652 self.aux=1
1653 1653
1654 1654 def run(self,dataOut,NSHTS=50,RATE=1.8978873e-6):
1655 1655
1656 1656 #print(ctime(dataOut.utctime))
1657 1657 #print("Faraday Angle",dataOut.phi)
1658 1658
1659 1659 dataOut.NSHTS=NSHTS
1660 1660 dataOut.RATE=RATE
1661 1661
1662 1662 if self.aux==1:
1663 1663 dataOut.dphi=numpy.zeros(dataOut.NDP,'float32')
1664 1664 dataOut.sdn1=numpy.zeros(dataOut.NDP,'float32')
1665 1665 self.aux=0
1666 1666 theta=numpy.zeros(dataOut.NDP,dtype=numpy.complex_)
1667 1667 thetai=numpy.zeros(dataOut.NDP,dtype=numpy.complex_)
1668 1668 # use complex numbers for phase
1669 1669 '''
1670 1670 for i in range(dataOut.NSHTS):
1671 1671 theta[i]=math.cos(dataOut.phi[i])+math.sin(dataOut.phi[i])*1j
1672 1672 thetai[i]=-math.sin(dataOut.phi[i])+math.cos(dataOut.phi[i])*1j
1673 1673 '''
1674 1674
1675 1675 # differentiate and convert to number density
1676 1676 ndphi=dataOut.NSHTS-4
1677 1677
1678 1678 #dataOut.phi=numpy.unwrap(dataOut.phi)
1679 1679 f1=numpy.exp((dataOut.phi*1.j)/10)
1680 1680 f2=numpy.exp((dataOut.phi*2.j)/10)
1681 1681
1682 1682 for i in range(2,dataOut.NSHTS-2):
1683 1683 fact=(-0.5/(dataOut.RATE*dataOut.DH))*dataOut.bki[i]
1684 1684 #four-point derivative, no phase unwrapping necessary
1685 1685 ####dataOut.dphi[i]=((((theta[i+1]-theta[i-1])+(2.0*(theta[i+2]-theta[i-2])))/thetai[i])).real/10.0
1686 1686 ##dataOut.dphi[i]=((((theta[i-2]-theta[i+2])+(8.0*(theta[i+1]-theta[i-1])))/thetai[i])).real/12.0
1687 1687 ##dataOut.dphi[i]=((dataOut.phi[i+1]-dataOut.phi[i-1])+(2.0*(dataOut.phi[i+2]-dataOut.phi[i-2])))/10.0
1688 1688
1689 1689 dataOut.dphi[i]=numpy.angle(f1[i+1]*numpy.conjugate(f1[i-1])*f2[i+2]*numpy.conjugate(f2[i-2]))
1690 1690
1691 1691
1692 1692 dataOut.dphi[i]=abs(dataOut.dphi[i]*fact)
1693 1693 dataOut.sdn1[i]=(4.*(dataOut.sdn2[i-2]+dataOut.sdn2[i+2])+dataOut.sdn2[i-1]+dataOut.sdn2[i+1])
1694 1694 dataOut.sdn1[i]=numpy.sqrt(dataOut.sdn1[i])*fact
1695 1695
1696 1696 return dataOut
1697 1697
1698 1698 class NormalizeDPPower(Operation):
1699 1699 """Operation to normalize relative electron density from power with total electron density from Farday angle.
1700 1700
1701 1701 Parameters:
1702 1702 -----------
1703 1703 None
1704 1704
1705 1705 Example
1706 1706 --------
1707 1707
1708 1708 op = proc_unit.addOperation(name='NormalizeDPPower', optype='other')
1709 1709
1710 1710 """
1711 1711
1712 1712 def __init__(self, **kwargs):
1713 1713
1714 1714 Operation.__init__(self, **kwargs)
1715 1715 self.aux=1
1716 1716
1717 1717 def normal(self,a,b,n,m):
1718 1718 chmin=1.0e30
1719 1719 chisq=numpy.zeros(150,'float32')
1720 1720 temp=numpy.zeros(150,'float32')
1721 1721
1722 1722 for i in range(2*m-1):
1723 1723 an=al=be=chisq[i]=0.0
1724 1724 for j in range(int(n/m)):
1725 1725 k=int(j+i*n/(2*m))
1726 1726 if(a[k]>0.0 and b[k]>0.0):
1727 1727 al+=a[k]*b[k]
1728 1728 be+=b[k]*b[k]
1729 1729
1730 1730 if(be>0.0):
1731 1731 temp[i]=al/be
1732 1732 else:
1733 1733 temp[i]=1.0
1734 1734
1735 1735 for j in range(int(n/m)):
1736 1736 k=int(j+i*n/(2*m))
1737 1737 if(a[k]>0.0 and b[k]>0.0):
1738 1738 chisq[i]+=(numpy.log10(b[k]*temp[i]/a[k]))**2
1739 1739 an=an+1
1740 1740
1741 1741 if(chisq[i]>0.0):
1742 1742 chisq[i]/=an
1743 1743
1744 1744 for i in range(int(2*m-1)):
1745 1745 if(chisq[i]<chmin and chisq[i]>1.0e-6):
1746 1746 chmin=chisq[i]
1747 1747 cf=temp[i]
1748 1748 return cf
1749 1749
1750 1750 def normalize(self,dataOut):
1751 1751
1752 1752 if self.aux==1:
1753 1753 dataOut.cf=numpy.zeros(1,'float32')
1754 1754 dataOut.cflast=numpy.zeros(1,'float32')
1755 1755 self.aux=0
1756 1756
1757 1757 night_first=300.0
1758 1758 night_first1= 310.0
1759 1759 night_end= 450.0
1760 1760 day_first=250.0
1761 1761 day_end=400.0
1762 1762 day_first_sunrise=190.0
1763 1763 day_end_sunrise=280.0
1764 1764
1765 1765 print(dataOut.ut_Faraday)
1766 1766 if(dataOut.ut_Faraday>4.0 and dataOut.ut_Faraday<11.0): #early
1767 1767 print("EARLY")
1768 1768 i2=(night_end-dataOut.range1[0])/dataOut.DH
1769 1769 i1=(night_first -dataOut.range1[0])/dataOut.DH
1770 1770 elif (dataOut.ut_Faraday>0.0 and dataOut.ut_Faraday<4.0): #night
1771 1771 print("NIGHT")
1772 1772 i2=(night_end-dataOut.range1[0])/dataOut.DH
1773 1773 i1=(night_first1 -dataOut.range1[0])/dataOut.DH
1774 1774 elif (dataOut.ut_Faraday>=11.0 and dataOut.ut_Faraday<13.5): #sunrise
1775 1775 print("SUNRISE")
1776 1776 i2=( day_end_sunrise-dataOut.range1[0])/dataOut.DH
1777 1777 i1=(day_first_sunrise - dataOut.range1[0])/dataOut.DH
1778 1778 else:
1779 1779 print("ELSE")
1780 1780 i2=(day_end-dataOut.range1[0])/dataOut.DH
1781 1781 i1=(day_first -dataOut.range1[0])/dataOut.DH
1782 1782 #print(i1*dataOut.DH)
1783 1783 #print(i2*dataOut.DH)
1784 1784
1785 1785 i1=int(i1)
1786 1786 i2=int(i2)
1787 1787
1788 1788 try:
1789 1789 dataOut.cf=self.normal(dataOut.dphi[i1::], dataOut.ph2[i1::], i2-i1, 1)
1790 1790 except:
1791 1791 pass
1792 1792
1793 1793 #print(dataOut.ph2)
1794 1794 #input()
1795 1795 # in case of spread F, normalize much higher
1796 1796 if(dataOut.cf<dataOut.cflast[0]/10.0):
1797 1797 i1=(night_first1+100.-dataOut.range1[0])/dataOut.DH
1798 1798 i2=(night_end+100.0-dataOut.range1[0])/dataOut.DH
1799 1799 i1=int(i1)
1800 1800 i2=int(i2)
1801 1801 try:
1802 1802 dataOut.cf=self.normal(dataOut.dphi[int(i1)::], dataOut.ph2[int(i1)::], int(i2-i1), 1)
1803 1803 except:
1804 1804 pass
1805 1805
1806 1806 dataOut.cflast[0]=dataOut.cf
1807 1807
1808 1808 ## normalize double pulse power and error bars to Faraday
1809 1809 for i in range(dataOut.NSHTS):
1810 1810 dataOut.ph2[i]*=dataOut.cf
1811 1811 dataOut.sdp2[i]*=dataOut.cf
1812 1812 #print(dataOut.ph2)
1813 1813 #input()
1814 1814
1815 1815 for i in range(dataOut.NSHTS):
1816 1816 dataOut.ph2[i]=(max(1.0, dataOut.ph2[i]))
1817 1817 dataOut.dphi[i]=(max(1.0, dataOut.dphi[i]))
1818 1818
1819 1819
1820 1820 def run(self,dataOut):
1821 1821
1822 1822 self.normalize(dataOut)
1823 1823 #print(dataOut.ph2)
1824 1824 #print(dataOut.sdp2)
1825 1825 #input()
1826 1826
1827 1827
1828 1828 return dataOut
1829 1829
1830 1830 class NormalizeDPPowerRoberto(Operation):
1831 1831 """Operation to normalize relative electron density from power with total electron density from Farday angle.
1832 1832
1833 1833 Parameters:
1834 1834 -----------
1835 1835 None
1836 1836
1837 1837 Example
1838 1838 --------
1839 1839
1840 1840 op = proc_unit.addOperation(name='NormalizeDPPower', optype='other')
1841 1841
1842 1842 """
1843 1843
1844 1844 def __init__(self, **kwargs):
1845 1845
1846 1846 Operation.__init__(self, **kwargs)
1847 1847 self.aux=1
1848 1848
1849 1849 def normal(self,a,b,n,m):
1850 1850 chmin=1.0e30
1851 1851 chisq=numpy.zeros(150,'float32')
1852 1852 temp=numpy.zeros(150,'float32')
1853 1853
1854 1854 for i in range(2*m-1):
1855 1855 an=al=be=chisq[i]=0.0
1856 1856 for j in range(int(n/m)):
1857 1857 k=int(j+i*n/(2*m))
1858 1858 if(a[k]>0.0 and b[k]>0.0):
1859 1859 al+=a[k]*b[k]
1860 1860 be+=b[k]*b[k]
1861 1861
1862 1862 if(be>0.0):
1863 1863 temp[i]=al/be
1864 1864 else:
1865 1865 temp[i]=1.0
1866 1866
1867 1867 for j in range(int(n/m)):
1868 1868 k=int(j+i*n/(2*m))
1869 1869 if(a[k]>0.0 and b[k]>0.0):
1870 1870 chisq[i]+=(numpy.log10(b[k]*temp[i]/a[k]))**2
1871 1871 an=an+1
1872 1872
1873 1873 if(chisq[i]>0.0):
1874 1874 chisq[i]/=an
1875 1875
1876 1876 for i in range(int(2*m-1)):
1877 1877 if(chisq[i]<chmin and chisq[i]>1.0e-6):
1878 1878 chmin=chisq[i]
1879 1879 cf=temp[i]
1880 1880 return cf
1881 1881
1882 1882 def normalize(self,dataOut):
1883 1883
1884 1884 if self.aux==1:
1885 1885 dataOut.cf=numpy.zeros(1,'float32')
1886 1886 dataOut.cflast=numpy.zeros(1,'float32')
1887 1887 self.aux=0
1888 1888
1889 1889 night_first=300.0
1890 1890 night_first1= 310.0
1891 1891 night_end= 450.0
1892 1892 day_first=250.0
1893 1893 day_end=400.0
1894 1894 day_first_sunrise=190.0
1895 1895 day_end_sunrise=350.0
1896 1896
1897 1897 print(dataOut.ut_Faraday)
1898 1898 '''
1899 1899 if(dataOut.ut_Faraday>4.0 and dataOut.ut_Faraday<11.0): #early
1900 1900 print("EARLY")
1901 1901 i2=(night_end-dataOut.range1[0])/dataOut.DH
1902 1902 i1=(night_first -dataOut.range1[0])/dataOut.DH
1903 1903 elif (dataOut.ut_Faraday>0.0 and dataOut.ut_Faraday<4.0): #night
1904 1904 print("NIGHT")
1905 1905 i2=(night_end-dataOut.range1[0])/dataOut.DH
1906 1906 i1=(night_first1 -dataOut.range1[0])/dataOut.DH
1907 1907 elif (dataOut.ut_Faraday>=11.0 and dataOut.ut_Faraday<13.5): #sunrise
1908 1908 print("SUNRISE")
1909 1909 i2=( day_end_sunrise-dataOut.range1[0])/dataOut.DH
1910 1910 i1=(day_first_sunrise - dataOut.range1[0])/dataOut.DH
1911 1911 else:
1912 1912 print("ELSE")
1913 1913 i2=(day_end-dataOut.range1[0])/dataOut.DH
1914 1914 i1=(day_first -dataOut.range1[0])/dataOut.DH
1915 1915 '''
1916 1916 i2=(420-dataOut.range1[0])/dataOut.DH
1917 1917 i1=(200 -dataOut.range1[0])/dataOut.DH
1918 1918 print(i1*dataOut.DH)
1919 1919 print(i2*dataOut.DH)
1920 1920
1921 1921 i1=int(i1)
1922 1922 i2=int(i2)
1923 1923
1924 1924 try:
1925 1925 dataOut.cf=self.normal(dataOut.dphi[i1::], dataOut.ph2[i1::], i2-i1, 1)
1926 1926 except:
1927 1927 pass
1928 1928
1929 1929 #print(dataOut.ph2)
1930 1930 #input()
1931 1931 # in case of spread F, normalize much higher
1932 1932 if(dataOut.cf<dataOut.cflast[0]/10.0):
1933 1933 i1=(night_first1+100.-dataOut.range1[0])/dataOut.DH
1934 1934 i2=(night_end+100.0-dataOut.range1[0])/dataOut.DH
1935 1935 i1=int(i1)
1936 1936 i2=int(i2)
1937 1937 try:
1938 1938 dataOut.cf=self.normal(dataOut.dphi[int(i1)::], dataOut.ph2[int(i1)::], int(i2-i1), 1)
1939 1939 except:
1940 1940 pass
1941 1941
1942 1942 dataOut.cflast[0]=dataOut.cf
1943 1943
1944 1944 ## normalize double pulse power and error bars to Faraday
1945 1945 for i in range(dataOut.NSHTS):
1946 1946 dataOut.ph2[i]*=dataOut.cf
1947 1947 dataOut.sdp2[i]*=dataOut.cf
1948 1948 #print(dataOut.ph2)
1949 1949 #input()
1950 1950
1951 1951 for i in range(dataOut.NSHTS):
1952 1952 dataOut.ph2[i]=(max(1.0, dataOut.ph2[i]))
1953 1953 dataOut.dphi[i]=(max(1.0, dataOut.dphi[i]))
1954 1954
1955 1955
1956 1956 def run(self,dataOut):
1957 1957
1958 1958 self.normalize(dataOut)
1959 1959 #print(dataOut.ph2)
1960 1960 #print(dataOut.sdp2)
1961 1961 #input()
1962 1962
1963 1963
1964 1964 return dataOut
1965 1965
1966 1966
1967 1967 class suppress_stdout_stderr(object):
1968 1968 '''
1969 1969 A context manager for doing a "deep suppression" of stdout and stderr in
1970 1970 Python, i.e. will suppress all print, even if the print originates in a
1971 1971 compiled C/Fortran sub-function.
1972 1972 This will not suppress raised exceptions, since exceptions are printed
1973 1973 to stderr just before a script exits, and after the context manager has
1974 1974 exited (at least, I think that is why it lets exceptions through).
1975 1975
1976 1976 '''
1977 1977 def __init__(self):
1978 1978 # Open a pair of null files
1979 1979 self.null_fds = [os.open(os.devnull,os.O_RDWR) for x in range(2)]
1980 1980 # Save the actual stdout (1) and stderr (2) file descriptors.
1981 1981 self.save_fds = [os.dup(1), os.dup(2)]
1982 1982
1983 1983 def __enter__(self):
1984 1984 # Assign the null pointers to stdout and stderr.
1985 1985 os.dup2(self.null_fds[0],1)
1986 1986 os.dup2(self.null_fds[1],2)
1987 1987
1988 1988 def __exit__(self, *_):
1989 1989 # Re-assign the real stdout/stderr back to (1) and (2)
1990 1990 os.dup2(self.save_fds[0],1)
1991 1991 os.dup2(self.save_fds[1],2)
1992 1992 # Close all file descriptors
1993 1993 for fd in self.null_fds + self.save_fds:
1994 1994 os.close(fd)
1995 1995
1996 1996
1997 1997 class DPTemperaturesEstimation(Operation):
1998 1998 """Operation to estimate temperatures for Double Pulse data.
1999 1999
2000 2000 Parameters:
2001 2001 -----------
2002 2002 IBITS : int
2003 2003 .*
2004 2004
2005 2005 Example
2006 2006 --------
2007 2007
2008 2008 op = proc_unit.addOperation(name='DPTemperaturesEstimation', optype='other')
2009 2009 op.addParameter(name='IBITS', value='16', format='int')
2010 2010
2011 2011 """
2012 2012
2013 2013 def __init__(self, **kwargs):
2014 2014
2015 2015 Operation.__init__(self, **kwargs)
2016 2016
2017 2017 self.aux=1
2018 2018
2019 2019 def Estimation(self,dataOut):
2020 2020 with suppress_stdout_stderr():
2021 2021 #if True:
2022 2022
2023 2023 if self.aux==1:
2024 2024 dataOut.ifit=numpy.zeros(5,order='F',dtype='int32')
2025 2025 dataOut.m=numpy.zeros(1,order='F',dtype='int32')
2026 2026 dataOut.te2=numpy.zeros(dataOut.NSHTS,order='F',dtype='float32')
2027 2027 dataOut.ti2=numpy.zeros(dataOut.NSHTS,order='F',dtype='float32')
2028 2028 dataOut.ete2=numpy.zeros(dataOut.NSHTS,order='F',dtype='float32')
2029 2029 dataOut.eti2=numpy.zeros(dataOut.NSHTS,order='F',dtype='float32')
2030 2030
2031 2031 self.aux=0
2032 2032
2033 2033 dataOut.phy2=numpy.zeros(dataOut.NSHTS,order='F',dtype='float32')
2034 2034 dataOut.ephy2=numpy.zeros(dataOut.NSHTS,order='F',dtype='float32')
2035 2035 dataOut.info2=numpy.zeros(dataOut.NDP,order='F',dtype='float32')
2036 2036 dataOut.params=numpy.zeros(10,order='F',dtype='float32')
2037 2037 dataOut.cov=numpy.zeros(dataOut.IBITS*dataOut.IBITS,order='F',dtype='float32')
2038 2038 dataOut.covinv=numpy.zeros(dataOut.IBITS*dataOut.IBITS,order='F',dtype='float32')
2039 2039
2040 2040 #null_fd = os.open(os.devnull, os.O_RDWR)
2041 2041 #os.dup2(null_fd, 1)
2042 2042
2043 2043 for i in range(10,dataOut.NSHTS): #no point below 150 km
2044 2044
2045 2045 #some definitions
2046 2046 iflag=0 # inicializado a cero?
2047 2047 wl = 3.0
2048 2048 x=numpy.zeros(dataOut.DPL+dataOut.IBITS,order='F',dtype='float32')
2049 2049 y=numpy.zeros(dataOut.DPL+dataOut.IBITS,order='F',dtype='float32')
2050 2050 e=numpy.zeros(dataOut.DPL+dataOut.IBITS,order='F',dtype='float32')
2051 2051 eb=numpy.zeros(5,order='F',dtype='float32')
2052 2052 zero=numpy.zeros(1,order='F',dtype='float32')
2053 2053 depth=numpy.zeros(1,order='F',dtype='float32')
2054 2054 t1=numpy.zeros(1,order='F',dtype='float32')
2055 2055 t2=numpy.zeros(1,order='F',dtype='float32')
2056 2056
2057 2057 if i>10 and l1>=0:
2058 2058 if l1==0:
2059 2059 l1=1
2060 2060
2061 2061 dataOut.cov=numpy.reshape(dataOut.cov,l1*l1)
2062 2062 dataOut.cov=numpy.resize(dataOut.cov,dataOut.DPL*dataOut.DPL)
2063 2063 dataOut.covinv=numpy.reshape(dataOut.covinv,l1*l1)
2064 2064 dataOut.covinv=numpy.resize(dataOut.covinv,dataOut.DPL*dataOut.DPL)
2065 2065
2066 2066 for l in range(dataOut.DPL*dataOut.DPL):
2067 2067 dataOut.cov[l]=0.0
2068 2068 acfm= (dataOut.rhor[i][0])**2 + (dataOut.rhoi[i][0])**2
2069 2069 if acfm> 0.0:
2070 2070 cc=dataOut.rhor[i][0]/acfm
2071 2071 ss=dataOut.rhoi[i][0]/acfm
2072 2072 else:
2073 2073 cc=1.
2074 2074 ss=0.
2075 2075 # keep only uncontaminated data, don't pass zero lag to fitter
2076 2076 l1=0
2077 2077 for l in range(0+1,dataOut.DPL):
2078 2078 if dataOut.igcej[i][l]==0 and dataOut.ibad[i][l]==0:
2079 2079 y[l1]=dataOut.rhor[i][l]*cc + dataOut.rhoi[i][l]*ss
2080 2080 x[l1]=dataOut.alag[l]*1.0e-3
2081 2081 dataOut.sd[i][l]=dataOut.sd[i][l]/((acfm)**2)# important
2082 2082 e[l1]=dataOut.sd[i][l] #this is the variance, not the st. dev.
2083 2083 l1=l1+1
2084 2084
2085 2085 for l in range(l1*(l1+1)):
2086 2086 dataOut.cov[l]=0.0
2087 2087 for l in range(l1):
2088 2088 dataOut.cov[l*(1+l1)]=e[l]
2089 2089 angle=dataOut.thb[i]*0.01745
2090 2090 bm=dataOut.bfm[i]
2091 2091 dataOut.params[0]=1.0 #norm
2092 2092 dataOut.params[1]=1000.0 #te
2093 2093 dataOut.params[2]=800.0 #ti
2094 2094 dataOut.params[3]=0.00 #ph
2095 2095 dataOut.params[4]=0.00 #phe
2096 2096
2097 2097 if l1!=0:
2098 2098 x=numpy.resize(x,l1)
2099 2099 y=numpy.resize(y,l1)
2100 2100 else:
2101 2101 x=numpy.resize(x,1)
2102 2102 y=numpy.resize(y,1)
2103 2103
2104 2104 if True: #len(y)!=0:
2105 2105
2106 2106 fitacf_guess.guess(y,x,zero,depth,t1,t2,len(y))
2107 2107 t2=t1/t2
2108 2108
2109 2109
2110 2110
2111 2111
2112 2112 if (t1<5000.0 and t1> 600.0):
2113 2113 dataOut.params[1]=t1
2114 2114 dataOut.params[2]=min(t2,t1)
2115 2115 dataOut.ifit[1]=dataOut.ifit[2]=1
2116 2116 dataOut.ifit[0]=dataOut.ifit[3]=dataOut.ifit[4]=0
2117 2117 #print(dataOut.ut_Faraday)
2118 2118 if dataOut.ut_Faraday<10.0 and dataOut.ut_Faraday>=0.5:
2119 2119 dataOut.ifit[2]=0
2120 2120
2121 2121 den=dataOut.ph2[i]
2122 2122
2123 2123 if l1!=0:
2124 2124 dataOut.covinv=dataOut.covinv[0:l1*l1].reshape((l1,l1))
2125 2125 dataOut.cov=dataOut.cov[0:l1*l1].reshape((l1,l1))
2126 2126 e=numpy.resize(e,l1)
2127 2127 else:
2128 2128 dataOut.covinv=numpy.resize(dataOut.covinv,1)
2129 2129 dataOut.cov=numpy.resize(dataOut.cov,1)
2130 2130 e=numpy.resize(e,1)
2131 2131
2132 2132 eb=numpy.resize(eb,10)
2133 2133 dataOut.ifit=numpy.resize(dataOut.ifit,10)
2134 2134
2135 2135
2136 2136
2137 2137 dataOut.covinv,e,dataOut.params,eb,dataOut.m=fitacf_fit_short.fit(wl,x,y,dataOut.cov,dataOut.covinv,e,dataOut.params,bm,angle,den,dataOut.range1[i],dataOut.year,dataOut.ifit,dataOut.m,l1) #
2138 2138
2139 2139 #exit()
2140 2140
2141 2141 if dataOut.params[2]>dataOut.params[1]*1.05:
2142 2142 dataOut.ifit[2]=0
2143 2143 dataOut.params[1]=dataOut.params[2]=t1
2144 2144 dataOut.covinv,e,dataOut.params,eb,dataOut.m=fitacf_fit_short.fit(wl,x,y,dataOut.cov,dataOut.covinv,e,dataOut.params,bm,angle,den,dataOut.range1[i],dataOut.year,dataOut.ifit,dataOut.m,l1) #
2145 2145
2146 2146 if (dataOut.ifit[2]==0):
2147 2147 dataOut.params[2]=dataOut.params[1]
2148 2148 if (dataOut.ifit[3]==0 and iflag==0):
2149 2149 dataOut.params[3]=0.0
2150 2150 if (dataOut.ifit[4]==0):
2151 2151 dataOut.params[4]=0.0
2152 2152 dataOut.te2[i]=dataOut.params[1]
2153 2153 dataOut.ti2[i]=dataOut.params[2]
2154 2154 dataOut.ete2[i]=eb[1]
2155 2155 dataOut.eti2[i]=eb[2]
2156 2156
2157 2157 if dataOut.eti2[i]==0:
2158 2158 dataOut.eti2[i]=dataOut.ete2[i]
2159 2159
2160 2160 dataOut.phy2[i]=dataOut.params[3]
2161 2161 dataOut.ephy2[i]=eb[3]
2162 2162 if(iflag==1):
2163 2163 dataOut.ephy2[i]=0.0
2164 2164
2165 2165 if (dataOut.m<=3 and dataOut.m!= 0 and dataOut.te2[i]>400.0):
2166 2166 dataOut.info2[i]=1
2167 2167 else:
2168 2168 dataOut.info2[i]=0
2169 2169
2170 2170 def run(self,dataOut,IBITS=16):
2171 2171
2172 2172 dataOut.IBITS = IBITS
2173 2173
2174 2174 self.Estimation(dataOut)
2175 2175
2176 2176
2177 2177 return dataOut
2178 2178
2179 2179 class NeTeTiRecal(NormalizeDPPower,DPTemperaturesEstimation):
2180 2180
2181 2181 def __init__(self, **kwargs):
2182 2182
2183 2183 Operation.__init__(self, **kwargs)
2184 2184 self.aux=0
2185 2185
2186 2186 def run(self,dataOut):
2187 2187
2188 2188 for i in range(dataOut.NSHTS):
2189 2189 print("H: ",i*15)
2190 2190 print(1+(dataOut.te2[i]/dataOut.ti2[i]))
2191 2191 dataOut.ph2[i]*=1+(dataOut.te2[i]/dataOut.ti2[i])
2192 2192
2193 2193 self.normalize(dataOut)
2194 2194 self.Estimation(dataOut)
2195 2195
2196 2196
2197 2197 return dataOut
2198 2198
2199 2199
2200 2200 class DenCorrection(Operation):
2201 2201
2202 2202 def __init__(self, **kwargs):
2203 2203
2204 2204 Operation.__init__(self, **kwargs)
2205 2205
2206 2206
2207 2207 def run(self,dataOut):
2208 2208
2209 2209 y=numpy.zeros(dataOut.DPL,order='F',dtype='float32')
2210 2210 #y_aux = numpy.zeros(1,,dtype='float32')
2211 2211 for i in range(dataOut.NSHTS):
2212 2212 y[0]=y[1]=dataOut.range1[i]
2213 2213
2214 2214 y = y.astype(dtype='float64',order='F')
2215 2215 three=int(3)
2216 2216 wl = 3.0
2217 2217 tion=numpy.zeros(three,order='F',dtype='float32')
2218 2218 fion=numpy.zeros(three,order='F',dtype='float32')
2219 2219 nui=numpy.zeros(three,order='F',dtype='float32')
2220 2220 wion=numpy.zeros(three,order='F',dtype='int32')
2221 2221 bline=0.0
2222 2222 #bline=numpy.zeros(1,order='F',dtype='float32')
2223 2223
2224 2224
2225 2225 #print("**** ACF2 WRAPPER ***** ",fitacf_acf2.acf2.__doc__ )
2226 2226 print("BEFORE",dataOut.ph2[10:35])
2227 2227 for i in range(dataOut.NSHTS):
2228 2228 if dataOut.info2[i]==1:
2229 2229 angle=dataOut.thb[i]*0.01745
2230 2230 nue=nui[0]=nui[1]=nui[2]=0.0#nui[3]=0.0
2231 2231 wion[0]=16
2232 2232 wion[1]=1
2233 2233 wion[2]=4
2234 2234 tion[0]=tion[1]=tion[2]=dataOut.ti2[i]
2235 2235 fion[0]=1.0-dataOut.phy2[i]
2236 2236 fion[1]=dataOut.phy2[i]
2237 2237 fion[2]=0.0
2238 2238 for j in range(dataOut.DPL):
2239 2239 tau=dataOut.alag[j]*1.0e-3
2240 2240
2241 2241 '''
2242 2242 print("**** input from acf2 ***** ")
2243 2243 print("wl ",wl)
2244 2244 print("tau ",tau)
2245 2245 print("te2[i] ",dataOut.te2[i])
2246 2246 print("tion ",tion)
2247 2247 print("fion ",fion)
2248 2248 print("nue ",nue)
2249 2249 print("nui ",nui)
2250 2250 print("wion ",wion)
2251 2251 print("angle ",angle)
2252 2252 print("ph2[i] ",dataOut.ph2[i])
2253 2253 print("bfm[i] ",dataOut.bfm[i])
2254 2254 print("y[j] ",y[j])
2255 2255 '''
2256 2256 print("Before y[j] ",y[j])
2257 2257 #with suppress_stdout_stderr():
2258 2258 y[j]=fitacf_acf2.acf2(wl,tau,dataOut.te2[i],tion,fion,nue,nui,wion,angle,dataOut.ph2[i],dataOut.bfm[i],y[j],three)
2259 2259 #print("l",l)
2260 2260 print("After y[j] ",y[j])
2261 2261 '''
2262 2262 print("**** output from acf2 ***** ")
2263 2263 print("wl ",wl)
2264 2264 print("tau ",tau)
2265 2265 print("te2[i] ",dataOut.te2[i])
2266 2266 print("tion ",tion)
2267 2267 print("fion ",fion)
2268 2268 print("nue ",nue)
2269 2269 print("nui ",nui)
2270 2270 print("wion ",wion)
2271 2271 print("angle ",angle)
2272 2272 print("ph2[i] ",dataOut.ph2[i])
2273 2273 print("bfm[i] ",dataOut.bfm[i])
2274 2274 print("y[j] ",y[j])
2275 2275 print("i ",i , " j ",j , "y[j] ",y[j])
2276 2276 '''
2277 2277
2278 2278
2279 2279 #exit(1)
2280 2280 if dataOut.ut_Faraday>11.0 and dataOut.range1[i]>150.0 and dataOut.range1[i]<400.0:
2281 2281 tau=0.0
2282 2282 #with suppress_stdout_stderr():
2283 2283 bline=fitacf_acf2.acf2(wl,tau,tion,tion,fion,nue,nui,wion,angle,dataOut.ph2[i],dataOut.bfm[i],bline,three)
2284 2284 cf=min(1.2,max(1.0,bline/y[0]))
2285 2285 print("bline: ",bline)
2286 2286 if cf != 1.0:
2287 2287 print("bline: ",bline)
2288 2288 print("cf: ",cf)
2289 2289 #exit(1)
2290 2290 #print("cf: ",cf)
2291 2291 dataOut.ph2[i]=cf*dataOut.ph2[i]
2292 2292 dataOut.sdp2[i]=cf*dataOut.sdp2[i]
2293 2293 for j in range(1,dataOut.DPL):
2294 2294 y[j]=(y[j]/y[0])*dataOut.DH+dataOut.range1[i]
2295 2295 y[0]=dataOut.range1[i]+dataOut.DH
2296 2296 #exit(1)
2297 2297
2298 2298
2299 2299 #exit(1)
2300 2300 print("AFTER",dataOut.ph2[10:35])
2301 2301 #exit(1)
2302 2302
2303 2303
2304 2304
2305 2305
2306 2306
2307 2307 return dataOut
2308 2308
2309 2309 class DataPlotCleaner(Operation):
2310 2310 def __init__(self, **kwargs):
2311 2311
2312 2312 Operation.__init__(self, **kwargs)
2313 2313
2314 2314 def run(self,dataOut):
2315 2315
2316 2316
2317 2317 THRESH_MIN_POW=10000
2318 2318 THRESH_MAX_POW=10000000
2319 2319 THRESH_MIN_TEMP=500
2320 2320 THRESH_MAX_TEMP=4000
2321 2321 dataOut.DensityClean=numpy.zeros((1,dataOut.NDP))
2322 2322 dataOut.EDensityClean=numpy.zeros((1,dataOut.NDP))
2323 2323 dataOut.ElecTempClean=numpy.zeros((1,dataOut.NDP))
2324 2324 dataOut.EElecTempClean=numpy.zeros((1,dataOut.NDP))
2325 2325 dataOut.IonTempClean=numpy.zeros((1,dataOut.NDP))
2326 2326 dataOut.EIonTempClean=numpy.zeros((1,dataOut.NDP))
2327 2327
2328 2328 dataOut.DensityClean[0]=numpy.copy(dataOut.ph2)
2329 2329 dataOut.EDensityClean[0]=numpy.copy(dataOut.sdp2)
2330 2330 dataOut.ElecTempClean[0,:dataOut.NSHTS]=numpy.copy(dataOut.te2)
2331 2331 dataOut.EElecTempClean[0,:dataOut.NSHTS]=numpy.copy(dataOut.ete2)
2332 2332 dataOut.IonTempClean[0,:dataOut.NSHTS]=numpy.copy(dataOut.ti2)
2333 2333 dataOut.EIonTempClean[0,:dataOut.NSHTS]=numpy.copy(dataOut.eti2)
2334 2334
2335 2335 for i in range(dataOut.NDP):
2336 2336 if dataOut.DensityClean[0,i]<THRESH_MIN_POW:
2337 2337 dataOut.DensityClean[0,i]=THRESH_MIN_POW
2338 2338
2339 2339 for i in range(dataOut.NDP):
2340 2340 if dataOut.DensityClean[0,i]>THRESH_MAX_POW:
2341 2341 dataOut.DensityClean[0,i]=THRESH_MAX_POW
2342 2342
2343 2343 for i in range(dataOut.NSHTS):
2344 2344 dataOut.ElecTempClean[0,i]=(max(1.0, dataOut.ElecTempClean[0,i]))
2345 2345 dataOut.IonTempClean[0,i]=(max(1.0, dataOut.IonTempClean[0,i]))
2346 2346 for i in range(dataOut.NSHTS):
2347 2347 if dataOut.ElecTempClean[0,i]<THRESH_MIN_TEMP:
2348 2348 dataOut.ElecTempClean[0,i]=THRESH_MIN_TEMP
2349 2349 if dataOut.IonTempClean[0,i]<THRESH_MIN_TEMP:
2350 2350 dataOut.IonTempClean[0,i]=THRESH_MIN_TEMP
2351 2351 for i in range(dataOut.NSHTS):
2352 2352 if dataOut.ElecTempClean[0,i]>THRESH_MAX_TEMP:
2353 2353 dataOut.ElecTempClean[0,i]=THRESH_MAX_TEMP
2354 2354 if dataOut.IonTempClean[0,i]>THRESH_MAX_TEMP:
2355 2355 dataOut.IonTempClean[0,i]=THRESH_MAX_TEMP
2356 2356 for i in range(dataOut.NSHTS):
2357 2357 if dataOut.EElecTempClean[0,i]>500:#
2358 2358 dataOut.ElecTempClean[0,i]=500
2359 2359 if dataOut.EIonTempClean[0,i]>500:#
2360 2360 dataOut.IonTempClean[0,i]=500
2361 2361
2362 2362 missing=numpy.nan
2363 2363
2364 2364 for i in range(dataOut.NSHTS,dataOut.NDP):
2365 2365
2366 2366 dataOut.ElecTempClean[0,i]=missing
2367 2367 dataOut.EElecTempClean[0,i]=missing
2368 2368 dataOut.IonTempClean[0,i]=missing
2369 2369 dataOut.EIonTempClean[0,i]=missing
2370 2370
2371 2371 return dataOut
2372 2372
2373 2373
2374 2374 class DataSaveCleaner(Operation):
2375 2375 def __init__(self, **kwargs):
2376 2376
2377 2377 Operation.__init__(self, **kwargs)
2378 2378
2379 2379
2380 2380 def run(self,dataOut):
2381 2381
2382 2382 dataOut.DensityFinal=numpy.zeros((1,dataOut.NDP))
2383 2383 dataOut.EDensityFinal=numpy.zeros((1,dataOut.NDP))
2384 2384 dataOut.ElecTempFinal=numpy.zeros((1,dataOut.NDP))
2385 2385 dataOut.EElecTempFinal=numpy.zeros((1,dataOut.NDP))
2386 2386 dataOut.IonTempFinal=numpy.zeros((1,dataOut.NDP))
2387 2387 dataOut.EIonTempFinal=numpy.zeros((1,dataOut.NDP))
2388 2388 dataOut.PhyFinal=numpy.zeros((1,dataOut.NDP))
2389 2389 dataOut.EPhyFinal=numpy.zeros((1,dataOut.NDP))
2390 2390
2391 2391 dataOut.DensityFinal[0]=numpy.copy(dataOut.ph2)
2392 2392 dataOut.EDensityFinal[0]=numpy.copy(dataOut.sdp2)
2393 2393 dataOut.ElecTempFinal[0,:dataOut.NSHTS]=numpy.copy(dataOut.te2)
2394 2394 dataOut.EElecTempFinal[0,:dataOut.NSHTS]=numpy.copy(dataOut.ete2)
2395 2395 dataOut.IonTempFinal[0,:dataOut.NSHTS]=numpy.copy(dataOut.ti2)
2396 2396 dataOut.EIonTempFinal[0,:dataOut.NSHTS]=numpy.copy(dataOut.eti2)
2397 2397 dataOut.PhyFinal[0,:dataOut.NSHTS]=numpy.copy(dataOut.phy2)
2398 2398 dataOut.EPhyFinal[0,:dataOut.NSHTS]=numpy.copy(dataOut.ephy2)
2399 2399
2400 2400 missing=numpy.nan
2401 2401
2402 2402 temp_min=100.0
2403 2403 temp_max=3000.0#6000.0e
2404 2404
2405 2405 for i in range(dataOut.NSHTS):
2406 2406
2407 2407 if dataOut.info2[i]!=1:
2408 2408 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2409 2409
2410 2410 if dataOut.ElecTempFinal[0,i]<=temp_min or dataOut.ElecTempFinal[0,i]>temp_max or dataOut.EElecTempFinal[0,i]>temp_max:
2411 2411
2412 2412 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=missing
2413 2413
2414 2414
2415 2415 if dataOut.IonTempFinal[0,i]<=temp_min or dataOut.IonTempFinal[0,i]>temp_max or dataOut.EIonTempFinal[0,i]>temp_max:
2416 2416 dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2417 2417
2418 2418 if dataOut.lags_to_plot[i,:][~numpy.isnan(dataOut.lags_to_plot[i,:])].shape[0]<6:
2419 2419 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2420 2420
2421 2421 if dataOut.ut_Faraday>4 and dataOut.ut_Faraday<11:
2422 2422 if numpy.nanmax(dataOut.acfs_error_to_plot[i,:])>=10:
2423 2423 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2424 2424
2425 2425 if dataOut.EPhyFinal[0,i]<0.0 or dataOut.EPhyFinal[0,i]>1.0:
2426 2426 dataOut.PhyFinal[0,i]=dataOut.EPhyFinal[0,i]=missing
2427 2427 if dataOut.EDensityFinal[0,i]>0.0 and dataOut.DensityFinal[0,i]>0.0 and dataOut.DensityFinal[0,i]<9.9e6:
2428 2428 dataOut.EDensityFinal[0,i]=max(dataOut.EDensityFinal[0,i],1000.0)
2429 2429 else:
2430 2430 dataOut.DensityFinal[0,i]=dataOut.EDensityFinal[0,i]=missing
2431 2431 if dataOut.PhyFinal[0,i]==0 or dataOut.PhyFinal[0,i]>0.4:
2432 2432 dataOut.PhyFinal[0,i]=dataOut.EPhyFinal[0,i]=missing
2433 2433 if dataOut.ElecTempFinal[0,i]==dataOut.IonTempFinal[0,i]:
2434 2434 dataOut.EElecTempFinal[0,i]=dataOut.EIonTempFinal[0,i]
2435 2435 if numpy.isnan(dataOut.ElecTempFinal[0,i]):
2436 2436 dataOut.EElecTempFinal[0,i]=missing
2437 2437 if numpy.isnan(dataOut.IonTempFinal[0,i]):
2438 2438 dataOut.EIonTempFinal[0,i]=missing
2439 2439 if numpy.isnan(dataOut.ElecTempFinal[0,i]) or numpy.isnan(dataOut.EElecTempFinal[0,i]):
2440 2440 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2441 2441
2442 2442 for i in range(12,dataOut.NSHTS-1):
2443 2443
2444 2444 if numpy.isnan(dataOut.ElecTempFinal[0,i-1]) and numpy.isnan(dataOut.ElecTempFinal[0,i+1]):
2445 2445 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=missing
2446 2446
2447 2447 if numpy.isnan(dataOut.IonTempFinal[0,i-1]) and numpy.isnan(dataOut.IonTempFinal[0,i+1]):
2448 2448 dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2449 2449
2450 2450 if dataOut.ut_Faraday>4 and dataOut.ut_Faraday<11:
2451 2451
2452 2452 if numpy.isnan(dataOut.ElecTempFinal[0,i-1]) and numpy.isnan(dataOut.ElecTempFinal[0,i-2]) and numpy.isnan(dataOut.ElecTempFinal[0,i+2]) and numpy.isnan(dataOut.ElecTempFinal[0,i+3]): #and numpy.isnan(dataOut.ElecTempFinal[0,i-5]):
2453 2453
2454 2454 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=missing
2455 2455 if numpy.isnan(dataOut.IonTempFinal[0,i-1]) and numpy.isnan(dataOut.IonTempFinal[0,i-2]) and numpy.isnan(dataOut.IonTempFinal[0,i+2]) and numpy.isnan(dataOut.IonTempFinal[0,i+3]): #and numpy.isnan(dataOut.IonTempFinal[0,i-5]):
2456 2456
2457 2457 dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2458 2458
2459 2459
2460 2460
2461 2461 if i>25:
2462 2462 if numpy.isnan(dataOut.ElecTempFinal[0,i-1]) and numpy.isnan(dataOut.ElecTempFinal[0,i-2]) and numpy.isnan(dataOut.ElecTempFinal[0,i-3]) and numpy.isnan(dataOut.ElecTempFinal[0,i-4]): #and numpy.isnan(dataOut.ElecTempFinal[0,i-5]):
2463 2463 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=missing
2464 2464 if numpy.isnan(dataOut.IonTempFinal[0,i-1]) and numpy.isnan(dataOut.IonTempFinal[0,i-2]) and numpy.isnan(dataOut.IonTempFinal[0,i-3]) and numpy.isnan(dataOut.IonTempFinal[0,i-4]): #and numpy.isnan(dataOut.IonTempFinal[0,i-5]):
2465 2465
2466 2466 dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2467 2467
2468 2468 if numpy.isnan(dataOut.ElecTempFinal[0,i]) or numpy.isnan(dataOut.EElecTempFinal[0,i]):
2469 2469
2470 2470 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2471 2471
2472 2472 for i in range(12,dataOut.NSHTS-1):
2473 2473
2474 2474 if numpy.isnan(dataOut.ElecTempFinal[0,i-1]) and numpy.isnan(dataOut.ElecTempFinal[0,i+1]):
2475 2475 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=missing
2476 2476
2477 2477 if numpy.isnan(dataOut.IonTempFinal[0,i-1]) and numpy.isnan(dataOut.IonTempFinal[0,i+1]):
2478 2478 dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2479 2479
2480 2480
2481 2481 if numpy.isnan(dataOut.ElecTempFinal[0,i]) or numpy.isnan(dataOut.EElecTempFinal[0,i]):
2482 2482
2483 2483 dataOut.ElecTempFinal[0,i]=dataOut.EElecTempFinal[0,i]=dataOut.IonTempFinal[0,i]=dataOut.EIonTempFinal[0,i]=missing
2484 2484
2485 2485 if numpy.count_nonzero(~numpy.isnan(dataOut.ElecTempFinal[0,12:50]))<5:
2486 2486 dataOut.ElecTempFinal[0,:]=dataOut.EElecTempFinal[0,:]=missing
2487 2487 if numpy.count_nonzero(~numpy.isnan(dataOut.IonTempFinal[0,12:50]))<5:
2488 2488 dataOut.IonTempFinal[0,:]=dataOut.EIonTempFinal[0,:]=missing
2489 2489
2490 2490 for i in range(dataOut.NSHTS,dataOut.NDP):
2491 2491
2492 2492 dataOut.ElecTempFinal[0,i]=missing
2493 2493 dataOut.EElecTempFinal[0,i]=missing
2494 2494 dataOut.IonTempFinal[0,i]=missing
2495 2495 dataOut.EIonTempFinal[0,i]=missing
2496 2496 dataOut.PhyFinal[0,i]=missing
2497 2497 dataOut.EPhyFinal[0,i]=missing
2498 2498
2499 2499 return dataOut
2500 2500
2501 2501
2502 2502 class DataSaveCleanerHP(Operation):
2503 2503 def __init__(self, **kwargs):
2504 2504
2505 2505 Operation.__init__(self, **kwargs)
2506 2506
2507 2507 def run(self,dataOut):
2508 2508
2509 2509 dataOut.Density_DP=numpy.zeros(dataOut.cut)
2510 2510 dataOut.EDensity_DP=numpy.zeros(dataOut.cut)
2511 2511 dataOut.ElecTemp_DP=numpy.zeros(dataOut.cut)
2512 2512 dataOut.EElecTemp_DP=numpy.zeros(dataOut.cut)
2513 2513 dataOut.IonTemp_DP=numpy.zeros(dataOut.cut)
2514 2514 dataOut.EIonTemp_DP=numpy.zeros(dataOut.cut)
2515 2515 dataOut.Phy_DP=numpy.zeros(dataOut.cut)
2516 2516 dataOut.EPhy_DP=numpy.zeros(dataOut.cut)
2517 2517 dataOut.Phe_DP=numpy.empty(dataOut.cut)
2518 2518 dataOut.EPhe_DP=numpy.empty(dataOut.cut)
2519 2519
2520 2520 dataOut.Density_DP[:]=numpy.copy(dataOut.ph2[:dataOut.cut])
2521 2521 dataOut.EDensity_DP[:]=numpy.copy(dataOut.sdp2[:dataOut.cut])
2522 2522 dataOut.ElecTemp_DP[:]=numpy.copy(dataOut.te2[:dataOut.cut])
2523 2523 dataOut.EElecTemp_DP[:]=numpy.copy(dataOut.ete2[:dataOut.cut])
2524 2524 dataOut.IonTemp_DP[:]=numpy.copy(dataOut.ti2[:dataOut.cut])
2525 2525 dataOut.EIonTemp_DP[:]=numpy.copy(dataOut.eti2[:dataOut.cut])
2526 2526 dataOut.Phy_DP[:]=numpy.copy(dataOut.phy2[:dataOut.cut])
2527 2527 dataOut.EPhy_DP[:]=numpy.copy(dataOut.ephy2[:dataOut.cut])
2528 2528 dataOut.Phe_DP[:]=numpy.nan
2529 2529 dataOut.EPhe_DP[:]=numpy.nan
2530 2530
2531 2531 missing=numpy.nan
2532 2532 temp_min=100.0
2533 2533 temp_max_dp=3000.0
2534 2534
2535 2535 for i in range(dataOut.cut):
2536 2536 if dataOut.info2[i]!=1:
2537 2537 dataOut.ElecTemp_DP[i]=dataOut.EElecTemp_DP[i]=dataOut.IonTemp_DP[i]=dataOut.EIonTemp_DP[i]=missing
2538 2538
2539 2539 if dataOut.ElecTemp_DP[i]<=temp_min or dataOut.ElecTemp_DP[i]>temp_max_dp or dataOut.EElecTemp_DP[i]>temp_max_dp:
2540 2540
2541 2541 dataOut.ElecTemp_DP[i]=dataOut.EElecTemp_DP[i]=missing
2542 2542
2543 2543 if dataOut.IonTemp_DP[i]<=temp_min or dataOut.IonTemp_DP[i]>temp_max_dp or dataOut.EIonTemp_DP[i]>temp_max_dp:
2544 2544 dataOut.IonTemp_DP[i]=dataOut.EIonTemp_DP[i]=missing
2545 2545
2546 2546 ####################################################################################### CHECK THIS
2547 2547 if dataOut.lags_to_plot[i,:][~numpy.isnan(dataOut.lags_to_plot[i,:])].shape[0]<6:
2548 2548 dataOut.ElecTemp_DP[i]=dataOut.EElecTemp_DP[i]=dataOut.IonTemp_DP[i]=dataOut.EIonTemp_DP[i]=missing
2549 2549
2550 2550 if dataOut.ut_Faraday>4 and dataOut.ut_Faraday<11:
2551 2551 if numpy.nanmax(dataOut.acfs_error_to_plot[i,:])>=10:
2552 2552 dataOut.ElecTemp_DP[i]=dataOut.EElecTemp_DP[i]=dataOut.IonTemp_DP[i]=dataOut.EIonTemp_DP[i]=missing
2553 2553 #######################################################################################
2554 2554
2555 2555 if dataOut.EPhy_DP[i]<0.0 or dataOut.EPhy_DP[i]>1.0:
2556 2556 dataOut.Phy_DP[i]=dataOut.EPhy_DP[i]=missing
2557 2557 if dataOut.EDensity_DP[i]>0.0 and dataOut.Density_DP[i]>0.0 and dataOut.Density_DP[i]<9.9e6:
2558 2558 dataOut.EDensity_DP[i]=max(dataOut.EDensity_DP[i],1000.0)
2559 2559 else:
2560 2560 dataOut.Density_DP[i]=dataOut.EDensity_DP[i]=missing
2561 2561 if dataOut.Phy_DP[i]==0 or dataOut.Phy_DP[i]>0.4:
2562 2562 dataOut.Phy_DP[i]=dataOut.EPhy_DP[i]=missing
2563 2563 if dataOut.ElecTemp_DP[i]==dataOut.IonTemp_DP[i]:
2564 2564 dataOut.EElecTemp_DP[i]=dataOut.EIonTemp_DP[i]
2565 2565 if numpy.isnan(dataOut.ElecTemp_DP[i]):
2566 2566 dataOut.EElecTemp_DP[i]=missing
2567 2567 if numpy.isnan(dataOut.IonTemp_DP[i]):
2568 2568 dataOut.EIonTemp_DP[i]=missing
2569 2569 if numpy.isnan(dataOut.ElecTemp_DP[i]) or numpy.isnan(dataOut.EElecTemp_DP[i]):
2570 2570 dataOut.ElecTemp_DP[i]=dataOut.EElecTemp_DP[i]=dataOut.IonTemp_DP[i]=dataOut.EIonTemp_DP[i]=missing
2571 2571
2572 2572
2573 2573
2574 2574 dataOut.Density_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2575 2575 dataOut.EDensity_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2576 2576 dataOut.ElecTemp_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2577 2577 dataOut.EElecTemp_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2578 2578 dataOut.IonTemp_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2579 2579 dataOut.EIonTemp_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2580 2580 dataOut.Phy_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2581 2581 dataOut.EPhy_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2582 2582 dataOut.Phe_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2583 2583 dataOut.EPhe_LP=numpy.zeros(dataOut.NACF-dataOut.cut)
2584 2584
2585 2585 dataOut.Density_LP[:]=numpy.copy(dataOut.ne[dataOut.cut:dataOut.NACF])
2586 2586 dataOut.EDensity_LP[:]=numpy.copy(dataOut.ene[dataOut.cut:dataOut.NACF])
2587 2587 dataOut.ElecTemp_LP[:]=numpy.copy(dataOut.te[dataOut.cut:dataOut.NACF])
2588 2588 dataOut.EElecTemp_LP[:]=numpy.copy(dataOut.ete[dataOut.cut:dataOut.NACF])
2589 2589 dataOut.IonTemp_LP[:]=numpy.copy(dataOut.ti[dataOut.cut:dataOut.NACF])
2590 2590 dataOut.EIonTemp_LP[:]=numpy.copy(dataOut.eti[dataOut.cut:dataOut.NACF])
2591 2591 dataOut.Phy_LP[:]=numpy.copy(dataOut.ph[dataOut.cut:dataOut.NACF])
2592 2592 dataOut.EPhy_LP[:]=numpy.copy(dataOut.eph[dataOut.cut:dataOut.NACF])
2593 2593 dataOut.Phe_LP[:]=numpy.copy(dataOut.phe[dataOut.cut:dataOut.NACF])
2594 2594 dataOut.EPhe_LP[:]=numpy.copy(dataOut.ephe[dataOut.cut:dataOut.NACF])
2595 2595
2596 2596 temp_max_lp=6000.0
2597 2597
2598 2598 for i in range(dataOut.NACF-dataOut.cut):
2599 2599
2600 2600 if dataOut.ElecTemp_LP[i]<=temp_min or dataOut.ElecTemp_LP[i]>temp_max_lp or dataOut.EElecTemp_LP[i]>temp_max_lp:
2601 2601
2602 2602 dataOut.ElecTemp_LP[i]=dataOut.EElecTemp_LP[i]=missing
2603 2603
2604 2604 if dataOut.IonTemp_LP[i]<=temp_min or dataOut.IonTemp_LP[i]>temp_max_lp or dataOut.EIonTemp_LP[i]>temp_max_lp:
2605 2605 dataOut.IonTemp_LP[i]=dataOut.EIonTemp_LP[i]=missing
2606 2606 if dataOut.EPhy_LP[i]<0.0 or dataOut.EPhy_LP[i]>1.0:
2607 2607 dataOut.Phy_LP[i]=dataOut.EPhy_LP[i]=missing
2608 2608
2609 2609 if dataOut.EPhe_LP[i]<0.0 or dataOut.EPhe_LP[i]>1.0:
2610 2610 dataOut.Phe_LP[i]=dataOut.EPhe_LP[i]=missing
2611 2611 if dataOut.EDensity_LP[i]>0.0 and dataOut.Density_LP[i]>0.0 and dataOut.Density_LP[i]<9.9e6 and dataOut.EDensity_LP[i]*dataOut.Density_LP[i]<9.9e6:
2612 2612 dataOut.EDensity_LP[i]=max(dataOut.EDensity_LP[i],1000.0/dataOut.Density_LP[i])
2613 2613 else:
2614 2614 dataOut.Density_LP[i]=missing
2615 2615 dataOut.EDensity_LP[i]=1.0
2616 2616
2617 2617 if numpy.isnan(dataOut.Phy_LP[i]):
2618 2618 dataOut.EPhy_LP[i]=missing
2619 2619
2620 2620 if numpy.isnan(dataOut.Phe_LP[i]):
2621 2621 dataOut.EPhe_LP[i]=missing
2622 2622
2623 2623
2624 2624 if dataOut.ElecTemp_LP[i]==dataOut.IonTemp_LP[i]:
2625 2625 dataOut.EElecTemp_LP[i]=dataOut.EIonTemp_LP[i]
2626 2626 if numpy.isnan(dataOut.ElecTemp_LP[i]):
2627 2627 dataOut.EElecTemp_LP[i]=missing
2628 2628 if numpy.isnan(dataOut.IonTemp_LP[i]):
2629 2629 dataOut.EIonTemp_LP[i]=missing
2630 2630 if numpy.isnan(dataOut.ElecTemp_LP[i]) or numpy.isnan(dataOut.EElecTemp_LP[i]):
2631 2631 dataOut.ElecTemp_LP[i]=dataOut.EElecTemp_LP[i]=dataOut.IonTemp_LP[i]=dataOut.EIonTemp_LP[i]=missing
2632 2632
2633 2633
2634 2634 dataOut.DensityFinal=numpy.reshape(numpy.concatenate((dataOut.Density_DP,dataOut.Density_LP)),(1,-1))
2635 2635 dataOut.EDensityFinal=numpy.reshape(numpy.concatenate((dataOut.EDensity_DP,dataOut.EDensity_LP)),(1,-1))
2636 2636 dataOut.ElecTempFinal=numpy.reshape(numpy.concatenate((dataOut.ElecTemp_DP,dataOut.ElecTemp_LP)),(1,-1))
2637 2637 dataOut.EElecTempFinal=numpy.reshape(numpy.concatenate((dataOut.EElecTemp_DP,dataOut.EElecTemp_LP)),(1,-1))
2638 2638 dataOut.IonTempFinal=numpy.reshape(numpy.concatenate((dataOut.IonTemp_DP,dataOut.IonTemp_LP)),(1,-1))
2639 2639 dataOut.EIonTempFinal=numpy.reshape(numpy.concatenate((dataOut.EIonTemp_DP,dataOut.EIonTemp_LP)),(1,-1))
2640 2640 dataOut.PhyFinal=numpy.reshape(numpy.concatenate((dataOut.Phy_DP,dataOut.Phy_LP)),(1,-1))
2641 2641 dataOut.EPhyFinal=numpy.reshape(numpy.concatenate((dataOut.EPhy_DP,dataOut.EPhy_LP)),(1,-1))
2642 2642 dataOut.PheFinal=numpy.reshape(numpy.concatenate((dataOut.Phe_DP,dataOut.Phe_LP)),(1,-1))
2643 2643 dataOut.EPheFinal=numpy.reshape(numpy.concatenate((dataOut.EPhe_DP,dataOut.EPhe_LP)),(1,-1))
2644 2644
2645 2645 nan_array_2=numpy.empty(dataOut.NACF-dataOut.NDP)
2646 2646 nan_array_2[:]=numpy.nan
2647 2647
2648 2648 dataOut.acfs_DP=numpy.zeros((dataOut.NACF,dataOut.DPL),'float32')
2649 2649 dataOut.acfs_error_DP=numpy.zeros((dataOut.NACF,dataOut.DPL),'float32')
2650 2650 acfs_dp_aux=dataOut.acfs_to_save.transpose()
2651 2651 acfs_error_dp_aux=dataOut.acfs_error_to_save.transpose()
2652 2652 for i in range(dataOut.DPL):
2653 2653 dataOut.acfs_DP[:,i]=numpy.concatenate((acfs_dp_aux[:,i],nan_array_2))
2654 2654 dataOut.acfs_error_DP[:,i]=numpy.concatenate((acfs_error_dp_aux[:,i],nan_array_2))
2655 2655 dataOut.acfs_DP=dataOut.acfs_DP.transpose()
2656 2656 dataOut.acfs_error_DP=dataOut.acfs_error_DP.transpose()
2657 2657
2658 2658 dataOut.acfs_LP=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
2659 2659 dataOut.acfs_error_LP=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
2660 2660
2661 2661 for i in range(dataOut.NACF):
2662 2662 for j in range(dataOut.IBITS):
2663 2663 if numpy.abs(dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0])<1.0:
2664 2664 dataOut.acfs_LP[i,j]=dataOut.output_LP_integrated.real[j,i,0]/dataOut.output_LP_integrated.real[0,i,0]
2665 2665 dataOut.acfs_LP[i,j]=max(min(dataOut.acfs_LP[i,j],1.0),-1.0)
2666 2666
2667 2667 dataOut.acfs_error_LP[i,j]=dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0]
2668 2668 else:
2669 2669 dataOut.acfs_LP[i,j]=numpy.nan
2670 2670
2671 2671 dataOut.acfs_error_LP[i,j]=numpy.nan
2672 2672
2673 2673 dataOut.acfs_LP=dataOut.acfs_LP.transpose()
2674 2674 dataOut.acfs_error_LP=dataOut.acfs_error_LP.transpose()
2675 2675
2676 2676 return dataOut
2677 2677
2678 2678
2679 2679 class ACFs(Operation):
2680 2680 def __init__(self, **kwargs):
2681 2681
2682 2682 Operation.__init__(self, **kwargs)
2683 2683
2684 2684 self.aux=1
2685 2685
2686 2686 def run(self,dataOut):
2687 2687
2688 2688 if self.aux:
2689 2689 self.taup=numpy.zeros(dataOut.DPL,'float32')
2690 2690 self.pacf=numpy.zeros(dataOut.DPL,'float32')
2691 2691 self.sacf=numpy.zeros(dataOut.DPL,'float32')
2692 2692
2693 2693 self.taup_full=numpy.zeros(dataOut.DPL,'float32')
2694 2694 self.pacf_full=numpy.zeros(dataOut.DPL,'float32')
2695 2695 self.sacf_full=numpy.zeros(dataOut.DPL,'float32')
2696 2696 self.x_igcej=numpy.zeros(dataOut.DPL,'float32')
2697 2697 self.y_igcej=numpy.zeros(dataOut.DPL,'float32')
2698 2698 self.x_ibad=numpy.zeros(dataOut.DPL,'float32')
2699 2699 self.y_ibad=numpy.zeros(dataOut.DPL,'float32')
2700 2700 self.aux=0
2701 2701
2702 2702 dataOut.acfs_to_plot=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2703 2703 dataOut.acfs_to_save=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2704 2704 dataOut.acfs_error_to_plot=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2705 2705 dataOut.acfs_error_to_save=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2706 2706 dataOut.lags_to_plot=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2707 2707 dataOut.x_igcej_to_plot=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2708 2708 dataOut.x_ibad_to_plot=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2709 2709 dataOut.y_igcej_to_plot=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2710 2710 dataOut.y_ibad_to_plot=numpy.zeros((dataOut.NDP,dataOut.DPL),'float32')
2711 2711
2712 2712 for i in range(dataOut.NSHTS):
2713 2713
2714 2714 acfm=dataOut.rhor[i][0]**2+dataOut.rhoi[i][0]**2
2715 2715
2716 2716 if acfm>0:
2717 2717 cc=dataOut.rhor[i][0]/acfm
2718 2718 ss=dataOut.rhoi[i][0]/acfm
2719 2719 else:
2720 2720 cc=1.
2721 2721 ss=0.
2722 2722
2723 2723 # keep only uncontaminated data
2724 2724 for l in range(dataOut.DPL):
2725 2725 fact=dataOut.DH
2726 2726 if (dataOut.igcej[i][l]==0 and dataOut.ibad[i][l]==0):
2727 2727
2728 2728 self.pacf_full[l]=min(1.0,max(-1.0,(dataOut.rhor[i][l]*cc + dataOut.rhoi[i][l]*ss)))*fact+dataOut.range1[i]
2729 2729 self.sacf_full[l]=min(1.0,numpy.sqrt(dataOut.sd[i][l]))*fact
2730 2730 self.taup_full[l]=dataOut.alag[l]
2731 2731 self.x_igcej[l]=numpy.nan
2732 2732 self.y_igcej[l]=numpy.nan
2733 2733 self.x_ibad[l]=numpy.nan
2734 2734 self.y_ibad[l]=numpy.nan
2735 2735
2736 2736 else:
2737 2737 self.pacf_full[l]=numpy.nan
2738 2738 self.sacf_full[l]=numpy.nan
2739 2739 self.taup_full[l]=numpy.nan
2740 2740
2741 2741 if dataOut.igcej[i][l]:
2742 2742 self.x_igcej[l]=dataOut.alag[l]
2743 2743 self.y_igcej[l]=dataOut.range1[i]
2744 2744 self.x_ibad[l]=numpy.nan
2745 2745 self.y_ibad[l]=numpy.nan
2746 2746
2747 2747 if dataOut.ibad[i][l]:
2748 2748 self.x_igcej[l]=numpy.nan
2749 2749 self.y_igcej[l]=numpy.nan
2750 2750 self.x_ibad[l]=dataOut.alag[l]
2751 2751 self.y_ibad[l]=dataOut.range1[i]
2752 2752
2753 2753 pacf_new=numpy.copy((self.pacf_full-dataOut.range1[i])/dataOut.DH)
2754 2754 sacf_new=numpy.copy(self.sacf_full/dataOut.DH)
2755 2755 dataOut.acfs_to_save[i,:]=numpy.copy(pacf_new)
2756 2756 dataOut.acfs_error_to_save[i,:]=numpy.copy(sacf_new)
2757 2757 dataOut.acfs_to_plot[i,:]=numpy.copy(self.pacf_full)
2758 2758 dataOut.acfs_error_to_plot[i,:]=numpy.copy(self.sacf_full)
2759 2759 dataOut.lags_to_plot[i,:]=numpy.copy(self.taup_full)
2760 2760 dataOut.x_igcej_to_plot[i,:]=numpy.copy(self.x_igcej)
2761 2761 dataOut.x_ibad_to_plot[i,:]=numpy.copy(self.x_ibad)
2762 2762 dataOut.y_igcej_to_plot[i,:]=numpy.copy(self.y_igcej)
2763 2763 dataOut.y_ibad_to_plot[i,:]=numpy.copy(self.y_ibad)
2764 2764
2765 2765 missing=numpy.nan#-32767
2766 2766
2767 2767 for i in range(dataOut.NSHTS,dataOut.NDP):
2768 2768 for j in range(dataOut.DPL):
2769 2769 dataOut.acfs_to_save[i,j]=missing
2770 2770 dataOut.acfs_error_to_save[i,j]=missing
2771 2771 dataOut.acfs_to_plot[i,j]=missing
2772 2772 dataOut.acfs_error_to_plot[i,j]=missing
2773 2773 dataOut.lags_to_plot[i,j]=missing
2774 2774 dataOut.x_igcej_to_plot[i,j]=missing
2775 2775 dataOut.x_ibad_to_plot[i,j]=missing
2776 2776 dataOut.y_igcej_to_plot[i,j]=missing
2777 2777 dataOut.y_ibad_to_plot[i,j]=missing
2778 2778
2779 2779 dataOut.acfs_to_save=dataOut.acfs_to_save.transpose()
2780 2780 dataOut.acfs_error_to_save=dataOut.acfs_error_to_save.transpose()
2781 2781
2782 2782 return dataOut
2783 2783
2784 2784
2785 2785 class CohInt(Operation):
2786 2786
2787 2787 isConfig = False
2788 2788 __profIndex = 0
2789 2789 __byTime = False
2790 2790 __initime = None
2791 2791 __lastdatatime = None
2792 2792 __integrationtime = None
2793 2793 __buffer = None
2794 2794 __bufferStride = []
2795 2795 __dataReady = False
2796 2796 __profIndexStride = 0
2797 2797 __dataToPutStride = False
2798 2798 n = None
2799 2799
2800 2800 def __init__(self, **kwargs):
2801 2801
2802 2802 Operation.__init__(self, **kwargs)
2803 2803
2804 2804 # self.isConfig = False
2805 2805
2806 2806 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
2807 2807 """
2808 2808 Set the parameters of the integration class.
2809 2809
2810 2810 Inputs:
2811 2811
2812 2812 n : Number of coherent integrations
2813 2813 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
2814 2814 overlapping :
2815 2815 """
2816 2816
2817 2817 self.__initime = None
2818 2818 self.__lastdatatime = 0
2819 2819 self.__buffer = None
2820 2820 self.__dataReady = False
2821 2821 self.byblock = byblock
2822 2822 self.stride = stride
2823 2823
2824 2824 if n == None and timeInterval == None:
2825 2825 raise ValueError("n or timeInterval should be specified ...")
2826 2826
2827 2827 if n != None:
2828 2828 self.n = n
2829 2829 self.__byTime = False
2830 2830 else:
2831 2831 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
2832 2832 self.n = 9999
2833 2833 self.__byTime = True
2834 2834
2835 2835 if overlapping:
2836 2836 self.__withOverlapping = True
2837 2837 self.__buffer = None
2838 2838 else:
2839 2839 self.__withOverlapping = False
2840 2840 self.__buffer = 0
2841 2841
2842 2842 self.__profIndex = 0
2843 2843
2844 2844 def putData(self, data):
2845 2845
2846 2846 """
2847 2847 Add a profile to the __buffer and increase in one the __profileIndex
2848 2848
2849 2849 """
2850 2850
2851 2851 if not self.__withOverlapping:
2852 2852 self.__buffer += data.copy()
2853 2853 self.__profIndex += 1
2854 2854 return
2855 2855
2856 2856 #Overlapping data
2857 2857 nChannels, nHeis = data.shape
2858 2858 data = numpy.reshape(data, (1, nChannels, nHeis))
2859 2859
2860 2860 #If the buffer is empty then it takes the data value
2861 2861 if self.__buffer is None:
2862 2862 self.__buffer = data
2863 2863 self.__profIndex += 1
2864 2864 return
2865 2865
2866 2866 #If the buffer length is lower than n then stakcing the data value
2867 2867 if self.__profIndex < self.n:
2868 2868 self.__buffer = numpy.vstack((self.__buffer, data))
2869 2869 self.__profIndex += 1
2870 2870 return
2871 2871
2872 2872 #If the buffer length is equal to n then replacing the last buffer value with the data value
2873 2873 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
2874 2874 self.__buffer[self.n-1] = data
2875 2875 self.__profIndex = self.n
2876 2876 return
2877 2877
2878 2878
2879 2879 def pushData(self):
2880 2880 """
2881 2881 Return the sum of the last profiles and the profiles used in the sum.
2882 2882
2883 2883 Affected:
2884 2884
2885 2885 self.__profileIndex
2886 2886
2887 2887 """
2888 2888
2889 2889 if not self.__withOverlapping:
2890 2890 data = self.__buffer
2891 2891 n = self.__profIndex
2892 2892
2893 2893 self.__buffer = 0
2894 2894 self.__profIndex = 0
2895 2895
2896 2896 return data, n
2897 2897
2898 2898 #Integration with Overlapping
2899 2899 data = numpy.sum(self.__buffer, axis=0)
2900 2900 # print data
2901 2901 # raise
2902 2902 n = self.__profIndex
2903 2903
2904 2904 return data, n
2905 2905
2906 2906 def byProfiles(self, data):
2907 2907
2908 2908 self.__dataReady = False
2909 2909 avgdata = None
2910 2910 # n = None
2911 2911 # print data
2912 2912 # raise
2913 2913 self.putData(data)
2914 2914
2915 2915 if self.__profIndex == self.n:
2916 2916 avgdata, n = self.pushData()
2917 2917 self.__dataReady = True
2918 2918
2919 2919 return avgdata
2920 2920
2921 2921 def byTime(self, data, datatime):
2922 2922
2923 2923 self.__dataReady = False
2924 2924 avgdata = None
2925 2925 n = None
2926 2926
2927 2927 self.putData(data)
2928 2928
2929 2929 if (datatime - self.__initime) >= self.__integrationtime:
2930 2930 avgdata, n = self.pushData()
2931 2931 self.n = n
2932 2932 self.__dataReady = True
2933 2933
2934 2934 return avgdata
2935 2935
2936 2936 def integrateByStride(self, data, datatime):
2937 2937 # print data
2938 2938 if self.__profIndex == 0:
2939 2939 self.__buffer = [[data.copy(), datatime]]
2940 2940 else:
2941 2941 self.__buffer.append([data.copy(),datatime])
2942 2942 self.__profIndex += 1
2943 2943 self.__dataReady = False
2944 2944
2945 2945 if self.__profIndex == self.n * self.stride :
2946 2946 self.__dataToPutStride = True
2947 2947 self.__profIndexStride = 0
2948 2948 self.__profIndex = 0
2949 2949 self.__bufferStride = []
2950 2950 for i in range(self.stride):
2951 2951 current = self.__buffer[i::self.stride]
2952 2952 data = numpy.sum([t[0] for t in current], axis=0)
2953 2953 avgdatatime = numpy.average([t[1] for t in current])
2954 2954 # print data
2955 2955 self.__bufferStride.append((data, avgdatatime))
2956 2956
2957 2957 if self.__dataToPutStride:
2958 2958 self.__dataReady = True
2959 2959 self.__profIndexStride += 1
2960 2960 if self.__profIndexStride == self.stride:
2961 2961 self.__dataToPutStride = False
2962 2962 # print self.__bufferStride[self.__profIndexStride - 1]
2963 2963 # raise
2964 2964 return self.__bufferStride[self.__profIndexStride - 1]
2965 2965
2966 2966
2967 2967 return None, None
2968 2968
2969 2969 def integrate(self, data, datatime=None):
2970 2970
2971 2971 if self.__initime == None:
2972 2972 self.__initime = datatime
2973 2973
2974 2974 if self.__byTime:
2975 2975 avgdata = self.byTime(data, datatime)
2976 2976 else:
2977 2977 avgdata = self.byProfiles(data)
2978 2978
2979 2979
2980 2980 self.__lastdatatime = datatime
2981 2981
2982 2982 if avgdata is None:
2983 2983 return None, None
2984 2984
2985 2985 avgdatatime = self.__initime
2986 2986
2987 2987 deltatime = datatime - self.__lastdatatime
2988 2988
2989 2989 if not self.__withOverlapping:
2990 2990 self.__initime = datatime
2991 2991 else:
2992 2992 self.__initime += deltatime
2993 2993
2994 2994 return avgdata, avgdatatime
2995 2995
2996 2996 def integrateByBlock(self, dataOut):
2997 2997
2998 2998 times = int(dataOut.data.shape[1]/self.n)
2999 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
2999 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=complex)
3000 3000
3001 3001 id_min = 0
3002 3002 id_max = self.n
3003 3003
3004 3004 for i in range(times):
3005 3005 junk = dataOut.data[:,id_min:id_max,:]
3006 3006 avgdata[:,i,:] = junk.sum(axis=1)
3007 3007 id_min += self.n
3008 3008 id_max += self.n
3009 3009
3010 3010 timeInterval = dataOut.ippSeconds*self.n
3011 3011 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
3012 3012 self.__dataReady = True
3013 3013 return avgdata, avgdatatime
3014 3014
3015 3015 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
3016 3016
3017 3017 if not self.isConfig:
3018 3018 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
3019 3019 self.isConfig = True
3020 3020
3021 3021 if dataOut.flagDataAsBlock:
3022 3022 """
3023 3023 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
3024 3024 """
3025 3025
3026 3026 avgdata, avgdatatime = self.integrateByBlock(dataOut)
3027 3027 dataOut.nProfiles /= self.n
3028 3028 else:
3029 3029 if stride is None:
3030 3030 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
3031 3031 else:
3032 3032 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
3033 3033
3034 3034
3035 3035 # dataOut.timeInterval *= n
3036 3036 dataOut.flagNoData = True
3037 3037
3038 3038 if self.__dataReady:
3039 3039 dataOut.data = avgdata
3040 3040 if not dataOut.flagCohInt:
3041 3041 dataOut.nCohInt *= self.n
3042 3042 dataOut.flagCohInt = True
3043 3043 dataOut.utctime = avgdatatime
3044 3044 # print avgdata, avgdatatime
3045 3045 # raise
3046 3046 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
3047 3047 dataOut.flagNoData = False
3048 3048 return dataOut
3049 3049
3050 3050 class TimesCode(Operation):
3051 3051 """
3052 3052
3053 3053 """
3054 3054
3055 3055 def __init__(self, **kwargs):
3056 3056
3057 3057 Operation.__init__(self, **kwargs)
3058 3058
3059 3059
3060 3060
3061 3061 def run(self,dataOut,code):
3062 3062
3063 3063 #code = numpy.repeat(code, repeats=osamp, axis=1)
3064 3064 nCodes = numpy.shape(code)[1]
3065 3065 #nprofcode = dataOut.nProfiles//nCodes
3066 3066 code = numpy.array(code)
3067 3067 #print("nHeights",dataOut.nHeights)
3068 3068 #print("nheicode",nheicode)
3069 3069 #print("Code.Shape",numpy.shape(code))
3070 3070 #print("Code",code[0,:])
3071 3071 nheicode = dataOut.nHeights//nCodes
3072 3072 res = dataOut.nHeights%nCodes
3073 3073 '''
3074 3074 buffer = numpy.zeros((dataOut.nChannels,
3075 3075 nprofcode,
3076 3076 nCodes,
3077 3077 ndataOut.nHeights),
3078 3078 dtype='complex')
3079 3079 '''
3080 3080 #exit(1)
3081 3081 #for ipr in range(dataOut.nProfiles):
3082 3082 #print(dataOut.nHeights)
3083 3083 #print(dataOut.data[0,384-2:])
3084 3084 #print(dataOut.profileIndex)
3085 3085 #print(dataOut.data[0,:2])
3086 3086 #print(dataOut.data[0,0:64])
3087 3087 #print(dataOut.data[0,64:64+64])
3088 3088 #exit(1)
3089 3089 for ich in range(dataOut.nChannels):
3090 3090 for ihe in range(nheicode):
3091 3091 #print(ihe*nCodes)
3092 3092 #print((ihe+1)*nCodes)
3093 3093 #dataOut.data[ich,ipr,ihe*nCodes:nCodes*(ihe+1)]
3094 3094 #code[ipr,:]
3095 3095 #print("before",dataOut.data[ich,ipr,ihe*nCodes:nCodes*(ihe+1)])
3096 3096 #dataOut.data[ich,ipr,ihe*nCodes:nCodes*(ihe+1)] = numpy.prod([dataOut.data[ich,ipr,ihe*nCodes:nCodes*(ihe+1)],code[ipr,:]],axis=0)
3097 3097 dataOut.data[ich,ihe*nCodes:nCodes*(ihe+1)] = numpy.prod([dataOut.data[ich,ihe*nCodes:nCodes*(ihe+1)],code[dataOut.profileIndex,:]],axis=0)
3098 3098
3099 3099 #print("after",dataOut.data[ich,ipr,ihe*nCodes:nCodes*(ihe+1)])
3100 3100 #exit(1)
3101 3101 #print(dataOut.data[0,:2])
3102 3102 #exit(1)
3103 3103 #print(nheicode)
3104 3104 #print((nheicode)*nCodes)
3105 3105 #print(((nheicode)*nCodes)+res)
3106 3106 if res != 0:
3107 3107 for ich in range(dataOut.nChannels):
3108 3108 dataOut.data[ich,nheicode*nCodes:] = numpy.prod([dataOut.data[ich,nheicode*nCodes:],code[dataOut.profileIndex,:res]],axis=0)
3109 3109
3110 3110 #pass
3111 3111 #print(dataOut.data[0,384-2:])
3112 3112 #exit(1)
3113 3113 #dataOut.data = numpy.mean(buffer,axis=1)
3114 3114 #print(numpy.shape(dataOut.data))
3115 3115 #print(dataOut.nHeights)
3116 3116 #dataOut.heightList = dataOut.heightList[0:nheicode]
3117 3117 #print(dataOut.nHeights)
3118 3118 #dataOut.nHeights = numpy.shape(dataOut.data)[2]
3119 3119 #print(numpy.shape(dataOut.data))
3120 3120 #exit(1)
3121 3121
3122 3122 return dataOut
3123 3123
3124 3124 '''
3125 3125 class Spectrogram(Operation):
3126 3126 """
3127 3127
3128 3128 """
3129 3129
3130 3130 def __init__(self, **kwargs):
3131 3131
3132 3132 Operation.__init__(self, **kwargs)
3133 3133
3134 3134
3135 3135
3136 3136 def run(self,dataOut):
3137 3137
3138 3138 import scipy
3139 3139
3140 3140
3141 3141
3142 3142 fs = 3200*1e-6
3143 3143 fs = fs/64
3144 3144 fs = 1/fs
3145 3145
3146 3146 nperseg=64
3147 3147 noverlap=48
3148 3148
3149 3149 f, t, Sxx = signal.spectrogram(x, fs, return_onesided=False, nperseg=nperseg, noverlap=noverlap, mode='complex')
3150 3150
3151 3151
3152 3152 for ich in range(dataOut.nChannels):
3153 3153 for ihe in range(nheicode):
3154 3154
3155 3155
3156 3156 return dataOut
3157 3157 '''
3158 3158
3159 3159
3160 3160 class RemoveDcHae(Operation):
3161 3161
3162 3162 def __init__(self, **kwargs):
3163 3163
3164 3164 Operation.__init__(self, **kwargs)
3165 3165 self.DcCounter = 0
3166 3166
3167 3167 def run(self, dataOut):
3168 3168
3169 3169 if self.DcCounter == 0:
3170 3170 dataOut.DcHae = numpy.zeros((dataOut.data.shape[0],320),dtype='complex')
3171 3171 #dataOut.DcHae = []
3172 3172 self.DcCounter = 1
3173 3173
3174 3174 dataOut.dataaux = numpy.copy(dataOut.data)
3175 3175
3176 3176 #dataOut.DcHae += dataOut.dataaux[:,1666:1666+320]
3177 3177 dataOut.DcHae += dataOut.dataaux[:,0:0+320]
3178 3178 hei = 1666
3179 3179 hei = 2000
3180 3180 hei = 1000
3181 3181 hei = 0
3182 3182 #dataOut.DcHae = numpy.concatenate([dataOut.DcHae,dataOut.dataaux[0,hei]],axis = None)
3183 3183
3184 3184
3185 3185
3186 3186 return dataOut
3187 3187
3188 3188
3189 3189 class SSheightProfiles(Operation):
3190 3190
3191 3191 step = None
3192 3192 nsamples = None
3193 3193 bufferShape = None
3194 3194 profileShape = None
3195 3195 sshProfiles = None
3196 3196 profileIndex = None
3197 3197
3198 3198 def __init__(self, **kwargs):
3199 3199
3200 3200 Operation.__init__(self, **kwargs)
3201 3201 self.isConfig = False
3202 3202
3203 3203 def setup(self,dataOut ,step = None , nsamples = None):
3204 3204
3205 3205 if step == None and nsamples == None:
3206 3206 #pass
3207 3207 raise ValueError("step or nheights should be specified ...")
3208 3208
3209 3209 self.step = step
3210 3210 self.nsamples = nsamples
3211 3211 self.__nChannels = dataOut.nChannels
3212 3212 self.__nProfiles = dataOut.nProfiles
3213 3213 self.__nHeis = dataOut.nHeights
3214 3214 shape = dataOut.data.shape #nchannels, nprofiles, nsamples
3215 3215 '''
3216 3216 print "input nChannels",self.__nChannels
3217 3217 print "input nProfiles",self.__nProfiles
3218 3218 print "input nHeis",self.__nHeis
3219 3219 print "input Shape",shape
3220 3220 '''
3221 3221
3222 3222
3223 3223 residue = (shape[1] - self.nsamples) % self.step
3224 3224 if residue != 0:
3225 3225 print("The residue is %d, step=%d should be multiple of %d to avoid loss of %d samples"%(residue,step,shape[1] - self.nsamples,residue))
3226 3226
3227 3227 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3228 3228 numberProfile = self.nsamples
3229 3229 numberSamples = (shape[1] - self.nsamples)/self.step
3230 3230 '''
3231 3231 print "new numberProfile",numberProfile
3232 3232 print "new numberSamples",numberSamples
3233 3233
3234 3234 print "New number of profile: %d, number of height: %d, Resolution %f Km"%(numberProfile,numberSamples,deltaHeight*self.step)
3235 3235 '''
3236 3236 self.bufferShape = int(shape[0]), int(numberSamples), int(numberProfile) # nchannels, nsamples , nprofiles
3237 3237 self.profileShape = int(shape[0]), int(numberProfile), int(numberSamples) # nchannels, nprofiles, nsamples
3238 3238
3239 self.buffer = numpy.zeros(self.bufferShape , dtype=numpy.complex)
3240 self.sshProfiles = numpy.zeros(self.profileShape, dtype=numpy.complex)
3239 self.buffer = numpy.zeros(self.bufferShape , dtype=complex)
3240 self.sshProfiles = numpy.zeros(self.profileShape, dtype=complex)
3241 3241
3242 3242 def run(self, dataOut, step, nsamples, code = None, repeat = None):
3243 3243 #print(dataOut.profileIndex)
3244 3244 dataOut.flagNoData = True
3245 3245 dataOut.flagDataAsBlock = False
3246 3246 profileIndex = None
3247 3247
3248 3248 #code = numpy.array(code)
3249 3249 #print(dataOut.data[0,:])
3250 3250 #exit(1)
3251 3251
3252 3252
3253 3253 if not self.isConfig:
3254 3254 #print("STEP",step)
3255 3255 self.setup(dataOut, step=step , nsamples=nsamples)
3256 3256 self.isConfig = True
3257 3257 #print(code[dataOut.profileIndex,:])
3258 3258
3259 3259 #DC_Hae = numpy.array([0.398+0.588j, -0.926+0.306j, -0.536-0.682j, -0.072+0.53j, 0.368-0.356j, 0.996+0.362j])
3260 3260 DC_Hae = numpy.array([ 0.001025 +0.0516375j, 0.03485 +0.20923125j, -0.168 -0.02720625j,
3261 3261 -0.1105375 +0.0707125j, -0.20309375-0.09670625j, 0.189775 +0.02716875j])*(-3.5)
3262 3262
3263 3263 DC_Hae = numpy.array([ -32.26 +8.66j, -32.26 +8.66j])
3264 3264
3265 3265 DC_Hae = numpy.array([-2.78500000e-01 -1.39175j, -6.63237294e+02+210.4268625j])
3266 3266
3267 3267
3268 3268
3269 3269
3270 3270
3271 3271
3272 3272 #print(dataOut.data[0,13:15])
3273 3273 dataOut.data = dataOut.data - DC_Hae[:,None]
3274 3274 #print(dataOut.data[0,13:15])
3275 3275 #exit(1)
3276 3276
3277 3277
3278 3278
3279 3279 code = numpy.array(code)
3280 3280 roll = 0
3281 3281 code = numpy.roll(code,roll,axis=0)
3282 3282 code = numpy.reshape(code,(5,100,64))
3283 3283 block = dataOut.CurrentBlock%5
3284 3284 #print(block)
3285 3285
3286 3286 #code_block = code[block-1-2,:,:]
3287 3287 day_dif = 1 #day_12
3288 3288 code_block = code[block-1-0,:,:]
3289 3289
3290 3290 if repeat is not None:
3291 3291 code_block = numpy.repeat(code_block, repeats=repeat, axis=1)
3292 3292
3293 3293
3294 3294
3295 3295 #print(dataOut.data[0:2,13])
3296 3296 for i in range(self.buffer.shape[1]):
3297 3297 #self.buffer[:,i] = numpy.flip(dataOut.data[:,i*self.step:i*self.step + self.nsamples])
3298 3298 '''
3299 3299 print(dataOut.profileIndex)
3300 3300 print(code[dataOut.profileIndex,:])
3301 3301 print("before",dataOut.data[:,i*self.step:i*self.step + self.nsamples])
3302 3302 print("after",dataOut.data[:,i*self.step:i*self.step + self.nsamples]*code[dataOut.profileIndex,:])
3303 3303 exit(1)
3304 3304 '''
3305 3305
3306 3306 #dif = numpy.copy(code)
3307 3307 if code is not None:
3308 3308 '''
3309 3309 code = numpy.array(code)
3310 3310 #print(code[0,:])
3311 3311
3312 3312 #print("There is Code")
3313 3313 #exit(1)
3314 3314 #code = dataOut.code
3315 3315 #print(code[0,:])
3316 3316 #exit(1)
3317 3317
3318 3318 roll = 0
3319 3319 code = numpy.roll(code,roll,axis=0)
3320 3320 code = numpy.reshape(code,(5,100,64))
3321 3321 block = dataOut.CurrentBlock%5
3322 3322 #print(block)
3323 3323
3324 3324 #code_block = code[block-1-2,:,:]
3325 3325 day_dif = 1 #day_12
3326 3326 code_block = code[block-1-0,:,:]
3327 3327
3328 3328
3329 3329
3330 3330 if repeat is not None:
3331 3331 code_block = numpy.repeat(code_block, repeats=repeat, axis=1)
3332 3332 '''
3333 3333
3334 3334
3335 3335
3336 3336 #code_block = code[0,:,:]
3337 3337
3338 3338 #print(code_block[2,:])
3339 3339 #for l in range(dataOut.data.shape[1]):
3340 3340 #dataOut.data[:,l] = dataOut.data[:,l] - numpy.array([0.398+0.588j, -0.926+0.306j, -0.536-0.682j, -0.072+0.53j, 0.368-0.356j, 0.996+0.362j])
3341 3341
3342 3342 ##DC_Hae = numpy.array([0.398+0.588j, -0.926+0.306j, -0.536-0.682j, -0.072+0.53j, 0.368-0.356j, 0.996+0.362j])
3343 3343
3344 3344 #print(dataOut.data[0:2,13])
3345 3345 ##dataOut.data = dataOut.data - DC_Hae[:,None]
3346 3346 #print(dataOut.data[0:2,13])
3347 3347 #exit(1)
3348 3348 #print(dataOut.data[0,i*self.step:i*self.step + self.nsamples])
3349 3349 #print(dataOut.data[1,i*self.step:i*self.step + self.nsamples])
3350 3350 #print(code_block[dataOut.profileIndex,:])
3351 3351 #print(numpy.shape(code_block[dataOut.profileIndex,:]))
3352 3352 #exit(1)
3353 3353 ###aux = numpy.mean(dataOut.data[:,i*self.step:i*self.step + self.nsamples],axis=1)
3354 3354 ###self.buffer[:,i] = (dataOut.data[:,i*self.step:i*self.step + self.nsamples]-aux[:,None])*code_block[dataOut.profileIndex,:]
3355 3355 '''
3356 3356 if i == 18:
3357 3357 buffer = dataOut.data[0,i*self.step:i*self.step + self.nsamples]
3358 3358 import matplotlib.pyplot as plt
3359 3359 fig, axes = plt.subplots(figsize=(14, 10))
3360 3360 x = numpy.linspace(0,20,numpy.shape(buffer)[0])
3361 3361 x = numpy.fft.fftfreq(numpy.shape(buffer)[0],0.00005)
3362 3362 x = numpy.fft.fftshift(x)
3363 3363
3364 3364 plt.plot(x,buffer)
3365 3365 plt.show()
3366 3366 import time
3367 3367 time.sleep(50)
3368 3368 '''
3369 3369 #for k in range(dataOut.nChannels):
3370 3370 self.buffer[:,i] = dataOut.data[:,i*self.step:i*self.step + self.nsamples]*code_block[dataOut.profileIndex,:]
3371 3371 #print(dataOut.data[0,:])
3372 3372 #print(code_block[0,:])
3373 3373 #print(self.buffer[1,i])
3374 3374 #exit(1)
3375 3375 else:
3376 3376 #print("There is no Code")
3377 3377 #exit(1)
3378 3378 self.buffer[:,i] = dataOut.data[:,i*self.step:i*self.step + self.nsamples]#*code[dataOut.profileIndex,:]
3379 3379
3380 3380 #self.buffer[:,j,self.__nHeis-j*self.step - self.nheights:self.__nHeis-j*self.step] = numpy.flip(dataOut.data[:,j*self.step:j*self.step + self.nheights])
3381 3381
3382 3382 for j in range(self.buffer.shape[0]):
3383 3383 self.sshProfiles[j] = numpy.transpose(self.buffer[j])
3384 3384
3385 3385 profileIndex = self.nsamples
3386 3386 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3387 3387 ippSeconds = (deltaHeight*1.0e-6)/(0.15)
3388 3388 #print "ippSeconds",ippSeconds
3389 3389 try:
3390 3390 if dataOut.concat_m is not None:
3391 3391 ippSeconds= ippSeconds/float(dataOut.concat_m)
3392 3392 #print "Profile concat %d"%dataOut.concat_m
3393 3393 except:
3394 3394 pass
3395 3395
3396 3396
3397 3397
3398 3398 dataOut.data = self.sshProfiles
3399 3399 dataOut.flagNoData = False
3400 3400 dataOut.heightList = numpy.arange(self.buffer.shape[1]) *self.step*deltaHeight + dataOut.heightList[0]
3401 3401 dataOut.nProfiles = int(dataOut.nProfiles*self.nsamples)
3402 3402
3403 3403 '''
3404 3404 print(dataOut.profileIndex)
3405 3405 if dataOut.profileIndex == 0:
3406 3406 dataOut.data = dataOut.data*1.e5
3407 3407
3408 3408 buffer_prom =
3409 3409 '''
3410 3410 #dataOut.utctime = dataOut.utctime - dataOut.profileIndex
3411 3411 #print(dataOut.profileIndex)
3412 3412 #print(dataOut.data[0,0,0])
3413 3413 '''
3414 3414 if dataOut.profileIndex == 0:
3415 3415 self.buffer_prom = numpy.copy(dataOut.data)
3416 3416
3417 3417 else:
3418 3418 self.buffer_prom = dataOut.data+self.buffer_prom
3419 3419 if dataOut.profileIndex == 99:
3420 3420 dataOut.data = self.buffer_prom/100
3421 3421 '''
3422 3422
3423 3423 #print(dataOut.data[0,0,0])
3424 3424 #print(dataOut.profileIndex)
3425 3425 dataOut.profileIndex = profileIndex
3426 3426 dataOut.flagDataAsBlock = True
3427 3427 dataOut.ippSeconds = ippSeconds
3428 3428 dataOut.step = self.step
3429 3429 #print(dataOut.profileIndex)
3430 3430 #print(dataOut.heightList)
3431 3431 #exit(1)
3432 3432
3433 3433 #print(dataOut.times)
3434 3434
3435 3435 return dataOut
3436 3436
3437 3437 class Decoder(Operation):
3438 3438
3439 3439 isConfig = False
3440 3440 __profIndex = 0
3441 3441
3442 3442 code = None
3443 3443
3444 3444 nCode = None
3445 3445 nBaud = None
3446 3446
3447 3447 def __init__(self, **kwargs):
3448 3448
3449 3449 Operation.__init__(self, **kwargs)
3450 3450
3451 3451 self.times = None
3452 3452 self.osamp = None
3453 3453 # self.__setValues = False
3454 3454 self.isConfig = False
3455 3455 self.setupReq = False
3456 3456 def setup(self, code, osamp, dataOut):
3457 3457
3458 3458 self.__profIndex = 0
3459 3459
3460 3460 self.code = code
3461 3461
3462 3462 self.nCode = len(code)
3463 3463 self.nBaud = len(code[0])
3464 3464
3465 3465 if (osamp != None) and (osamp >1):
3466 3466 self.osamp = osamp
3467 3467 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
3468 3468 self.nBaud = self.nBaud*self.osamp
3469 3469
3470 3470 self.__nChannels = dataOut.nChannels
3471 3471 self.__nProfiles = dataOut.nProfiles
3472 3472 self.__nHeis = dataOut.nHeights
3473 3473
3474 3474 if self.__nHeis < self.nBaud:
3475 3475 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
3476 3476
3477 3477 #Frequency
3478 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
3478 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=complex)
3479 3479
3480 3480 __codeBuffer[:,0:self.nBaud] = self.code
3481 3481
3482 3482 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
3483 3483
3484 3484 if dataOut.flagDataAsBlock:
3485 3485
3486 3486 self.ndatadec = self.__nHeis #- self.nBaud + 1
3487 3487
3488 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
3488 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=complex)
3489 3489
3490 3490 else:
3491 3491
3492 3492 #Time
3493 3493 self.ndatadec = self.__nHeis #- self.nBaud + 1
3494 3494
3495 3495
3496 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
3496 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=complex)
3497 3497
3498 3498 def __convolutionInFreq(self, data):
3499 3499
3500 3500 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
3501 3501
3502 3502 fft_data = numpy.fft.fft(data, axis=1)
3503 3503
3504 3504 conv = fft_data*fft_code
3505 3505
3506 3506 data = numpy.fft.ifft(conv,axis=1)
3507 3507
3508 3508 return data
3509 3509
3510 3510 def __convolutionInFreqOpt(self, data):
3511 3511
3512 3512 raise NotImplementedError
3513 3513
3514 3514 def __convolutionInTime(self, data):
3515 3515
3516 3516 code = self.code[self.__profIndex]
3517 3517 for i in range(self.__nChannels):
3518 3518 #aux=numpy.correlate(data[i,:], code, mode='full')
3519 3519 #print(numpy.shape(aux))
3520 3520 #print(numpy.shape(data[i,:]))
3521 3521 #print(numpy.shape(code))
3522 3522 #exit(1)
3523 3523 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
3524 3524
3525 3525 return self.datadecTime
3526 3526
3527 3527 def __convolutionByBlockInTime(self, data):
3528 3528
3529 3529 repetitions = int(self.__nProfiles / self.nCode)
3530 3530 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
3531 3531 junk = junk.flatten()
3532 3532 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
3533 3533 profilesList = range(self.__nProfiles)
3534 3534 #print(numpy.shape(self.datadecTime))
3535 3535 #print(numpy.shape(data))
3536 3536 for i in range(self.__nChannels):
3537 3537 for j in profilesList:
3538 3538 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
3539 3539 return self.datadecTime
3540 3540
3541 3541 def __convolutionByBlockInFreq(self, data):
3542 3542
3543 3543 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
3544 3544
3545 3545
3546 3546 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
3547 3547
3548 3548 fft_data = numpy.fft.fft(data, axis=2)
3549 3549
3550 3550 conv = fft_data*fft_code
3551 3551
3552 3552 data = numpy.fft.ifft(conv,axis=2)
3553 3553
3554 3554 return data
3555 3555
3556 3556
3557 3557 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
3558 3558
3559 3559 if dataOut.flagDecodeData:
3560 3560 print("This data is already decoded, recoding again ...")
3561 3561
3562 3562 if not self.isConfig:
3563 3563
3564 3564 if code is None:
3565 3565 if dataOut.code is None:
3566 3566 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
3567 3567
3568 3568 code = dataOut.code
3569 3569 else:
3570 3570 code = numpy.array(code).reshape(nCode,nBaud)
3571 3571 self.setup(code, osamp, dataOut)
3572 3572
3573 3573 self.isConfig = True
3574 3574
3575 3575 if mode == 3:
3576 3576 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
3577 3577
3578 3578 if times != None:
3579 3579 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
3580 3580
3581 3581 if self.code is None:
3582 3582 print("Fail decoding: Code is not defined.")
3583 3583 return
3584 3584
3585 3585 self.__nProfiles = dataOut.nProfiles
3586 3586 datadec = None
3587 3587
3588 3588 if mode == 3:
3589 3589 mode = 0
3590 3590
3591 3591 if dataOut.flagDataAsBlock:
3592 3592 """
3593 3593 Decoding when data have been read as block,
3594 3594 """
3595 3595
3596 3596 if mode == 0:
3597 3597 datadec = self.__convolutionByBlockInTime(dataOut.data)
3598 3598 if mode == 1:
3599 3599 datadec = self.__convolutionByBlockInFreq(dataOut.data)
3600 3600 else:
3601 3601 """
3602 3602 Decoding when data have been read profile by profile
3603 3603 """
3604 3604 if mode == 0:
3605 3605 datadec = self.__convolutionInTime(dataOut.data)
3606 3606
3607 3607 if mode == 1:
3608 3608 datadec = self.__convolutionInFreq(dataOut.data)
3609 3609
3610 3610 if mode == 2:
3611 3611 datadec = self.__convolutionInFreqOpt(dataOut.data)
3612 3612
3613 3613 if datadec is None:
3614 3614 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
3615 3615
3616 3616 dataOut.code = self.code
3617 3617 dataOut.nCode = self.nCode
3618 3618 dataOut.nBaud = self.nBaud
3619 3619
3620 3620 dataOut.data = datadec
3621 3621 #print("before",dataOut.heightList)
3622 3622 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
3623 3623 #print("after",dataOut.heightList)
3624 3624
3625 3625 dataOut.flagDecodeData = True #asumo q la data esta decodificada
3626 3626
3627 3627 if self.__profIndex == self.nCode-1:
3628 3628 self.__profIndex = 0
3629 3629 return dataOut
3630 3630
3631 3631 self.__profIndex += 1
3632 3632
3633 3633 #print("SHAPE",numpy.shape(dataOut.data))
3634 3634
3635 3635 return dataOut
3636 3636 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
3637 3637
3638 3638 class DecoderRoll(Operation):
3639 3639
3640 3640 isConfig = False
3641 3641 __profIndex = 0
3642 3642
3643 3643 code = None
3644 3644
3645 3645 nCode = None
3646 3646 nBaud = None
3647 3647
3648 3648 def __init__(self, **kwargs):
3649 3649
3650 3650 Operation.__init__(self, **kwargs)
3651 3651
3652 3652 self.times = None
3653 3653 self.osamp = None
3654 3654 # self.__setValues = False
3655 3655 self.isConfig = False
3656 3656 self.setupReq = False
3657 3657 def setup(self, code, osamp, dataOut):
3658 3658
3659 3659 self.__profIndex = 0
3660 3660
3661 3661
3662 3662 self.code = code
3663 3663
3664 3664 self.nCode = len(code)
3665 3665 self.nBaud = len(code[0])
3666 3666
3667 3667 if (osamp != None) and (osamp >1):
3668 3668 self.osamp = osamp
3669 3669 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
3670 3670 self.nBaud = self.nBaud*self.osamp
3671 3671
3672 3672 self.__nChannels = dataOut.nChannels
3673 3673 self.__nProfiles = dataOut.nProfiles
3674 3674 self.__nHeis = dataOut.nHeights
3675 3675
3676 3676 if self.__nHeis < self.nBaud:
3677 3677 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
3678 3678
3679 3679 #Frequency
3680 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
3680 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=complex)
3681 3681
3682 3682 __codeBuffer[:,0:self.nBaud] = self.code
3683 3683
3684 3684 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
3685 3685
3686 3686 if dataOut.flagDataAsBlock:
3687 3687
3688 3688 self.ndatadec = self.__nHeis #- self.nBaud + 1
3689 3689
3690 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
3690 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=complex)
3691 3691
3692 3692 else:
3693 3693
3694 3694 #Time
3695 3695 self.ndatadec = self.__nHeis #- self.nBaud + 1
3696 3696
3697 3697
3698 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
3698 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=complex)
3699 3699
3700 3700 def __convolutionInFreq(self, data):
3701 3701
3702 3702 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
3703 3703
3704 3704 fft_data = numpy.fft.fft(data, axis=1)
3705 3705
3706 3706 conv = fft_data*fft_code
3707 3707
3708 3708 data = numpy.fft.ifft(conv,axis=1)
3709 3709
3710 3710 return data
3711 3711
3712 3712 def __convolutionInFreqOpt(self, data):
3713 3713
3714 3714 raise NotImplementedError
3715 3715
3716 3716 def __convolutionInTime(self, data):
3717 3717
3718 3718 code = self.code[self.__profIndex]
3719 3719 #print("code",code[0,0])
3720 3720 for i in range(self.__nChannels):
3721 3721 #aux=numpy.correlate(data[i,:], code, mode='full')
3722 3722 #print(numpy.shape(aux))
3723 3723 #print(numpy.shape(data[i,:]))
3724 3724 #print(numpy.shape(code))
3725 3725 #exit(1)
3726 3726 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
3727 3727
3728 3728 return self.datadecTime
3729 3729
3730 3730 def __convolutionByBlockInTime(self, data):
3731 3731
3732 3732 repetitions = int(self.__nProfiles / self.nCode)
3733 3733 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
3734 3734 junk = junk.flatten()
3735 3735 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
3736 3736 profilesList = range(self.__nProfiles)
3737 3737 #print(numpy.shape(self.datadecTime))
3738 3738 #print(numpy.shape(data))
3739 3739 for i in range(self.__nChannels):
3740 3740 for j in profilesList:
3741 3741 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
3742 3742 return self.datadecTime
3743 3743
3744 3744 def __convolutionByBlockInFreq(self, data):
3745 3745
3746 3746 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
3747 3747
3748 3748
3749 3749 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
3750 3750
3751 3751 fft_data = numpy.fft.fft(data, axis=2)
3752 3752
3753 3753 conv = fft_data*fft_code
3754 3754
3755 3755 data = numpy.fft.ifft(conv,axis=2)
3756 3756
3757 3757 return data
3758 3758
3759 3759
3760 3760 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
3761 3761
3762 3762 if dataOut.flagDecodeData:
3763 3763 print("This data is already decoded, recoding again ...")
3764 3764
3765 3765
3766 3766
3767 3767 #print(dataOut.ippSeconds)
3768 3768 #exit(1)
3769 3769 roll = 0
3770 3770
3771 3771 if self.isConfig:
3772 3772 code = numpy.array(code)
3773 3773
3774 3774 #roll = 29
3775 3775 code = numpy.roll(code,roll,axis=0)
3776 3776 code = numpy.reshape(code,(5,100,64))
3777 3777 block = dataOut.CurrentBlock%5
3778 3778 #code = code[block-1,:,:] #NormalizeDPPower
3779 3779 code = code[block-1-1,:,:] #Next Day
3780 3780 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
3781 3781
3782 3782
3783 3783 if not self.isConfig:
3784 3784
3785 3785 if code is None:
3786 3786 if dataOut.code is None:
3787 3787 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
3788 3788
3789 3789 code = dataOut.code
3790 3790 else:
3791 3791 code = numpy.array(code)
3792 3792
3793 3793 #roll = 29
3794 3794 code = numpy.roll(code,roll,axis=0)
3795 3795 code = numpy.reshape(code,(5,100,64))
3796 3796 block = dataOut.CurrentBlock%5
3797 3797 code = code[block-1-1,:,:]
3798 3798 #print(code.shape())
3799 3799 #exit(1)
3800 3800
3801 3801 code = numpy.array(code).reshape(nCode,nBaud)
3802 3802 self.setup(code, osamp, dataOut)
3803 3803
3804 3804 self.isConfig = True
3805 3805
3806 3806 if mode == 3:
3807 3807 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
3808 3808
3809 3809 if times != None:
3810 3810 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
3811 3811
3812 3812 if self.code is None:
3813 3813 print("Fail decoding: Code is not defined.")
3814 3814 return
3815 3815
3816 3816 self.__nProfiles = dataOut.nProfiles
3817 3817 datadec = None
3818 3818
3819 3819 if mode == 3:
3820 3820 mode = 0
3821 3821
3822 3822 if dataOut.flagDataAsBlock:
3823 3823 """
3824 3824 Decoding when data have been read as block,
3825 3825 """
3826 3826
3827 3827 if mode == 0:
3828 3828 datadec = self.__convolutionByBlockInTime(dataOut.data)
3829 3829 if mode == 1:
3830 3830 datadec = self.__convolutionByBlockInFreq(dataOut.data)
3831 3831 else:
3832 3832 """
3833 3833 Decoding when data have been read profile by profile
3834 3834 """
3835 3835 if mode == 0:
3836 3836 datadec = self.__convolutionInTime(dataOut.data)
3837 3837
3838 3838 if mode == 1:
3839 3839 datadec = self.__convolutionInFreq(dataOut.data)
3840 3840
3841 3841 if mode == 2:
3842 3842 datadec = self.__convolutionInFreqOpt(dataOut.data)
3843 3843
3844 3844 if datadec is None:
3845 3845 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
3846 3846
3847 3847 dataOut.code = self.code
3848 3848 dataOut.nCode = self.nCode
3849 3849 dataOut.nBaud = self.nBaud
3850 3850
3851 3851 dataOut.data = datadec
3852 3852 #print("before",dataOut.heightList)
3853 3853 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
3854 3854 #print("after",dataOut.heightList)
3855 3855
3856 3856 dataOut.flagDecodeData = True #asumo q la data esta decodificada
3857 3857
3858 3858 if self.__profIndex == self.nCode-1:
3859 3859 self.__profIndex = 0
3860 3860 return dataOut
3861 3861
3862 3862 self.__profIndex += 1
3863 3863
3864 3864 #print("SHAPE",numpy.shape(dataOut.data))
3865 3865
3866 3866 return dataOut
3867 3867
3868 3868
3869 3869
3870 3870
3871 3871
3872 3872
3873 3873 class ProfileConcat(Operation):
3874 3874
3875 3875 isConfig = False
3876 3876 buffer = None
3877 3877
3878 3878 def __init__(self, **kwargs):
3879 3879
3880 3880 Operation.__init__(self, **kwargs)
3881 3881 self.profileIndex = 0
3882 3882
3883 3883 def reset(self):
3884 3884 self.buffer = numpy.zeros_like(self.buffer)
3885 3885 self.start_index = 0
3886 3886 self.times = 1
3887 3887
3888 3888 def setup(self, data, m, n=1):
3889 3889 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
3890 3890 self.nHeights = data.shape[1]#.nHeights
3891 3891 self.start_index = 0
3892 3892 self.times = 1
3893 3893
3894 3894 def concat(self, data):
3895 3895
3896 3896 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
3897 3897 self.start_index = self.start_index + self.nHeights
3898 3898
3899 3899 def run(self, dataOut, m):
3900 3900 dataOut.flagNoData = True
3901 3901
3902 3902 if not self.isConfig:
3903 3903 self.setup(dataOut.data, m, 1)
3904 3904 self.isConfig = True
3905 3905
3906 3906 if dataOut.flagDataAsBlock:
3907 3907 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
3908 3908
3909 3909 else:
3910 3910 self.concat(dataOut.data)
3911 3911 self.times += 1
3912 3912 if self.times > m:
3913 3913 dataOut.data = self.buffer
3914 3914 self.reset()
3915 3915 dataOut.flagNoData = False
3916 3916 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
3917 3917 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3918 3918 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
3919 3919 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
3920 3920 dataOut.ippSeconds *= m
3921 3921 return dataOut
3922 3922
3923 3923 class ProfileSelector(Operation):
3924 3924
3925 3925 profileIndex = None
3926 3926 # Tamanho total de los perfiles
3927 3927 nProfiles = None
3928 3928
3929 3929 def __init__(self, **kwargs):
3930 3930
3931 3931 Operation.__init__(self, **kwargs)
3932 3932 self.profileIndex = 0
3933 3933
3934 3934 def incProfileIndex(self):
3935 3935
3936 3936 self.profileIndex += 1
3937 3937
3938 3938 if self.profileIndex >= self.nProfiles:
3939 3939 self.profileIndex = 0
3940 3940
3941 3941 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
3942 3942
3943 3943 if profileIndex < minIndex:
3944 3944 return False
3945 3945
3946 3946 if profileIndex > maxIndex:
3947 3947 return False
3948 3948
3949 3949 return True
3950 3950
3951 3951 def isThisProfileInList(self, profileIndex, profileList):
3952 3952
3953 3953 if profileIndex not in profileList:
3954 3954 return False
3955 3955
3956 3956 return True
3957 3957
3958 3958 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
3959 3959
3960 3960 """
3961 3961 ProfileSelector:
3962 3962
3963 3963 Inputs:
3964 3964 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
3965 3965
3966 3966 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
3967 3967
3968 3968 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
3969 3969
3970 3970 """
3971 3971
3972 3972 if rangeList is not None:
3973 3973 if type(rangeList[0]) not in (tuple, list):
3974 3974 rangeList = [rangeList]
3975 3975
3976 3976 dataOut.flagNoData = True
3977 3977
3978 3978 if dataOut.flagDataAsBlock:
3979 3979 """
3980 3980 data dimension = [nChannels, nProfiles, nHeis]
3981 3981 """
3982 3982 if profileList != None:
3983 3983 dataOut.data = dataOut.data[:,profileList,:]
3984 3984
3985 3985 if profileRangeList != None:
3986 3986 minIndex = profileRangeList[0]
3987 3987 maxIndex = profileRangeList[1]
3988 3988 profileList = list(range(minIndex, maxIndex+1))
3989 3989
3990 3990 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
3991 3991
3992 3992 if rangeList != None:
3993 3993
3994 3994 profileList = []
3995 3995
3996 3996 for thisRange in rangeList:
3997 3997 minIndex = thisRange[0]
3998 3998 maxIndex = thisRange[1]
3999 3999
4000 4000 profileList.extend(list(range(minIndex, maxIndex+1)))
4001 4001
4002 4002 dataOut.data = dataOut.data[:,profileList,:]
4003 4003
4004 4004 dataOut.nProfiles = len(profileList)
4005 4005 dataOut.profileIndex = dataOut.nProfiles - 1
4006 4006 dataOut.flagNoData = False
4007 4007
4008 4008 return dataOut
4009 4009
4010 4010 """
4011 4011 data dimension = [nChannels, nHeis]
4012 4012 """
4013 4013
4014 4014 if profileList != None:
4015 4015
4016 4016 if self.isThisProfileInList(dataOut.profileIndex, profileList):
4017 4017
4018 4018 self.nProfiles = len(profileList)
4019 4019 dataOut.nProfiles = self.nProfiles
4020 4020 dataOut.profileIndex = self.profileIndex
4021 4021 dataOut.flagNoData = False
4022 4022
4023 4023 self.incProfileIndex()
4024 4024 return dataOut
4025 4025
4026 4026 if profileRangeList != None:
4027 4027
4028 4028 minIndex = profileRangeList[0]
4029 4029 maxIndex = profileRangeList[1]
4030 4030
4031 4031 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
4032 4032
4033 4033 self.nProfiles = maxIndex - minIndex + 1
4034 4034 dataOut.nProfiles = self.nProfiles
4035 4035 dataOut.profileIndex = self.profileIndex
4036 4036 dataOut.flagNoData = False
4037 4037
4038 4038 self.incProfileIndex()
4039 4039 return dataOut
4040 4040
4041 4041 if rangeList != None:
4042 4042
4043 4043 nProfiles = 0
4044 4044
4045 4045 for thisRange in rangeList:
4046 4046 minIndex = thisRange[0]
4047 4047 maxIndex = thisRange[1]
4048 4048
4049 4049 nProfiles += maxIndex - minIndex + 1
4050 4050
4051 4051 for thisRange in rangeList:
4052 4052
4053 4053 minIndex = thisRange[0]
4054 4054 maxIndex = thisRange[1]
4055 4055
4056 4056 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
4057 4057
4058 4058 self.nProfiles = nProfiles
4059 4059 dataOut.nProfiles = self.nProfiles
4060 4060 dataOut.profileIndex = self.profileIndex
4061 4061 dataOut.flagNoData = False
4062 4062
4063 4063 self.incProfileIndex()
4064 4064
4065 4065 break
4066 4066
4067 4067 return dataOut
4068 4068
4069 4069
4070 4070 if beam != None: #beam is only for AMISR data
4071 4071 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
4072 4072 dataOut.flagNoData = False
4073 4073 dataOut.profileIndex = self.profileIndex
4074 4074
4075 4075 self.incProfileIndex()
4076 4076
4077 4077 return dataOut
4078 4078
4079 4079 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
4080 4080
4081 4081 #return False
4082 4082 return dataOut
4083 4083
4084 4084 class Reshaper(Operation):
4085 4085
4086 4086 def __init__(self, **kwargs):
4087 4087
4088 4088 Operation.__init__(self, **kwargs)
4089 4089
4090 4090 self.__buffer = None
4091 4091 self.__nitems = 0
4092 4092
4093 4093 def __appendProfile(self, dataOut, nTxs):
4094 4094
4095 4095 if self.__buffer is None:
4096 4096 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
4097 4097 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
4098 4098
4099 4099 ini = dataOut.nHeights * self.__nitems
4100 4100 end = ini + dataOut.nHeights
4101 4101
4102 4102 self.__buffer[:, ini:end] = dataOut.data
4103 4103
4104 4104 self.__nitems += 1
4105 4105
4106 4106 return int(self.__nitems*nTxs)
4107 4107
4108 4108 def __getBuffer(self):
4109 4109
4110 4110 if self.__nitems == int(1./self.__nTxs):
4111 4111
4112 4112 self.__nitems = 0
4113 4113
4114 4114 return self.__buffer.copy()
4115 4115
4116 4116 return None
4117 4117
4118 4118 def __checkInputs(self, dataOut, shape, nTxs):
4119 4119
4120 4120 if shape is None and nTxs is None:
4121 4121 raise ValueError("Reshaper: shape of factor should be defined")
4122 4122
4123 4123 if nTxs:
4124 4124 if nTxs < 0:
4125 4125 raise ValueError("nTxs should be greater than 0")
4126 4126
4127 4127 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
4128 4128 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
4129 4129
4130 4130 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
4131 4131
4132 4132 return shape, nTxs
4133 4133
4134 4134 if len(shape) != 2 and len(shape) != 3:
4135 4135 raise ValueError("shape dimension should be equal to 2 or 3. shape = (nProfiles, nHeis) or (nChannels, nProfiles, nHeis). Actually shape = (%d, %d, %d)" %(dataOut.nChannels, dataOut.nProfiles, dataOut.nHeights))
4136 4136
4137 4137 if len(shape) == 2:
4138 4138 shape_tuple = [dataOut.nChannels]
4139 4139 shape_tuple.extend(shape)
4140 4140 else:
4141 4141 shape_tuple = list(shape)
4142 4142
4143 4143 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
4144 4144
4145 4145 return shape_tuple, nTxs
4146 4146
4147 4147 def run(self, dataOut, shape=None, nTxs=None):
4148 4148
4149 4149 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
4150 4150
4151 4151 dataOut.flagNoData = True
4152 4152 profileIndex = None
4153 4153
4154 4154 if dataOut.flagDataAsBlock:
4155 4155
4156 4156 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
4157 4157 dataOut.flagNoData = False
4158 4158
4159 4159 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
4160 4160
4161 4161 else:
4162 4162
4163 4163
4164 4164 if self.__nTxs < 1:
4165 4165
4166 4166 self.__appendProfile(dataOut, self.__nTxs)
4167 4167 new_data = self.__getBuffer()
4168 4168
4169 4169 if new_data is not None:
4170 4170 dataOut.data = new_data
4171 4171 dataOut.flagNoData = False
4172 4172
4173 4173 profileIndex = dataOut.profileIndex*nTxs
4174 4174
4175 4175 else:
4176 4176 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
4177 4177
4178 4178 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
4179 4179
4180 4180 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
4181 4181
4182 4182 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
4183 4183
4184 4184 dataOut.profileIndex = profileIndex
4185 4185
4186 4186 dataOut.ippSeconds /= self.__nTxs
4187 4187
4188 4188 return dataOut
4189 4189
4190 4190 class SplitProfiles(Operation):
4191 4191
4192 4192 def __init__(self, **kwargs):
4193 4193
4194 4194 Operation.__init__(self, **kwargs)
4195 4195
4196 4196 def run(self, dataOut, n):
4197 4197
4198 4198 dataOut.flagNoData = True
4199 4199 profileIndex = None
4200 4200
4201 4201 if dataOut.flagDataAsBlock:
4202 4202
4203 4203 #nchannels, nprofiles, nsamples
4204 4204 shape = dataOut.data.shape
4205 4205
4206 4206 if shape[2] % n != 0:
4207 4207 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
4208 4208
4209 4209 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
4210 4210
4211 4211 dataOut.data = numpy.reshape(dataOut.data, new_shape)
4212 4212 dataOut.flagNoData = False
4213 4213
4214 4214 profileIndex = int(dataOut.nProfiles/n) - 1
4215 4215
4216 4216 else:
4217 4217
4218 4218 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
4219 4219
4220 4220 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
4221 4221
4222 4222 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
4223 4223
4224 4224 dataOut.nProfiles = int(dataOut.nProfiles*n)
4225 4225
4226 4226 dataOut.profileIndex = profileIndex
4227 4227
4228 4228 dataOut.ippSeconds /= n
4229 4229
4230 4230 return dataOut
4231 4231
4232 4232 class CombineProfiles(Operation):
4233 4233 def __init__(self, **kwargs):
4234 4234
4235 4235 Operation.__init__(self, **kwargs)
4236 4236
4237 4237 self.__remData = None
4238 4238 self.__profileIndex = 0
4239 4239
4240 4240 def run(self, dataOut, n):
4241 4241
4242 4242 dataOut.flagNoData = True
4243 4243 profileIndex = None
4244 4244
4245 4245 if dataOut.flagDataAsBlock:
4246 4246
4247 4247 #nchannels, nprofiles, nsamples
4248 4248 shape = dataOut.data.shape
4249 4249 new_shape = shape[0], shape[1]/n, shape[2]*n
4250 4250
4251 4251 if shape[1] % n != 0:
4252 4252 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
4253 4253
4254 4254 dataOut.data = numpy.reshape(dataOut.data, new_shape)
4255 4255 dataOut.flagNoData = False
4256 4256
4257 4257 profileIndex = int(dataOut.nProfiles*n) - 1
4258 4258
4259 4259 else:
4260 4260
4261 4261 #nchannels, nsamples
4262 4262 if self.__remData is None:
4263 4263 newData = dataOut.data
4264 4264 else:
4265 4265 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
4266 4266
4267 4267 self.__profileIndex += 1
4268 4268
4269 4269 if self.__profileIndex < n:
4270 4270 self.__remData = newData
4271 4271 #continue
4272 4272 return
4273 4273
4274 4274 self.__profileIndex = 0
4275 4275 self.__remData = None
4276 4276
4277 4277 dataOut.data = newData
4278 4278 dataOut.flagNoData = False
4279 4279
4280 4280 profileIndex = dataOut.profileIndex/n
4281 4281
4282 4282
4283 4283 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
4284 4284
4285 4285 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
4286 4286
4287 4287 dataOut.nProfiles = int(dataOut.nProfiles/n)
4288 4288
4289 4289 dataOut.profileIndex = profileIndex
4290 4290
4291 4291 dataOut.ippSeconds *= n
4292 4292
4293 4293 return dataOut
4294 4294 # import collections
4295 4295 # from scipy.stats import mode
4296 4296 #
4297 4297 # class Synchronize(Operation):
4298 4298 #
4299 4299 # isConfig = False
4300 4300 # __profIndex = 0
4301 4301 #
4302 4302 # def __init__(self, **kwargs):
4303 4303 #
4304 4304 # Operation.__init__(self, **kwargs)
4305 4305 # # self.isConfig = False
4306 4306 # self.__powBuffer = None
4307 4307 # self.__startIndex = 0
4308 4308 # self.__pulseFound = False
4309 4309 #
4310 4310 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
4311 4311 #
4312 4312 # #Read data
4313 4313 #
4314 4314 # powerdB = dataOut.getPower(channel = channel)
4315 4315 # noisedB = dataOut.getNoise(channel = channel)[0]
4316 4316 #
4317 4317 # self.__powBuffer.extend(powerdB.flatten())
4318 4318 #
4319 4319 # dataArray = numpy.array(self.__powBuffer)
4320 4320 #
4321 4321 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
4322 4322 #
4323 4323 # maxValue = numpy.nanmax(filteredPower)
4324 4324 #
4325 4325 # if maxValue < noisedB + 10:
4326 4326 # #No se encuentra ningun pulso de transmision
4327 4327 # return None
4328 4328 #
4329 4329 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
4330 4330 #
4331 4331 # if len(maxValuesIndex) < 2:
4332 4332 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
4333 4333 # return None
4334 4334 #
4335 4335 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
4336 4336 #
4337 4337 # #Seleccionar solo valores con un espaciamiento de nSamples
4338 4338 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
4339 4339 #
4340 4340 # if len(pulseIndex) < 2:
4341 4341 # #Solo se encontro un pulso de transmision con ancho mayor a 1
4342 4342 # return None
4343 4343 #
4344 4344 # spacing = pulseIndex[1:] - pulseIndex[:-1]
4345 4345 #
4346 4346 # #remover senales que se distancien menos de 10 unidades o muestras
4347 4347 # #(No deberian existir IPP menor a 10 unidades)
4348 4348 #
4349 4349 # realIndex = numpy.where(spacing > 10 )[0]
4350 4350 #
4351 4351 # if len(realIndex) < 2:
4352 4352 # #Solo se encontro un pulso de transmision con ancho mayor a 1
4353 4353 # return None
4354 4354 #
4355 4355 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
4356 4356 # realPulseIndex = pulseIndex[realIndex]
4357 4357 #
4358 4358 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
4359 4359 #
4360 4360 # print "IPP = %d samples" %period
4361 4361 #
4362 4362 # self.__newNSamples = dataOut.nHeights #int(period)
4363 4363 # self.__startIndex = int(realPulseIndex[0])
4364 4364 #
4365 4365 # return 1
4366 4366 #
4367 4367 #
4368 4368 # def setup(self, nSamples, nChannels, buffer_size = 4):
4369 4369 #
4370 4370 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
4371 4371 # maxlen = buffer_size*nSamples)
4372 4372 #
4373 4373 # bufferList = []
4374 4374 #
4375 4375 # for i in range(nChannels):
4376 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
4376 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=complex) + numpy.NAN,
4377 4377 # maxlen = buffer_size*nSamples)
4378 4378 #
4379 4379 # bufferList.append(bufferByChannel)
4380 4380 #
4381 4381 # self.__nSamples = nSamples
4382 4382 # self.__nChannels = nChannels
4383 4383 # self.__bufferList = bufferList
4384 4384 #
4385 4385 # def run(self, dataOut, channel = 0):
4386 4386 #
4387 4387 # if not self.isConfig:
4388 4388 # nSamples = dataOut.nHeights
4389 4389 # nChannels = dataOut.nChannels
4390 4390 # self.setup(nSamples, nChannels)
4391 4391 # self.isConfig = True
4392 4392 #
4393 4393 # #Append new data to internal buffer
4394 4394 # for thisChannel in range(self.__nChannels):
4395 4395 # bufferByChannel = self.__bufferList[thisChannel]
4396 4396 # bufferByChannel.extend(dataOut.data[thisChannel])
4397 4397 #
4398 4398 # if self.__pulseFound:
4399 4399 # self.__startIndex -= self.__nSamples
4400 4400 #
4401 4401 # #Finding Tx Pulse
4402 4402 # if not self.__pulseFound:
4403 4403 # indexFound = self.__findTxPulse(dataOut, channel)
4404 4404 #
4405 4405 # if indexFound == None:
4406 4406 # dataOut.flagNoData = True
4407 4407 # return
4408 4408 #
4409 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
4409 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = complex)
4410 4410 # self.__pulseFound = True
4411 4411 # self.__startIndex = indexFound
4412 4412 #
4413 4413 # #If pulse was found ...
4414 4414 # for thisChannel in range(self.__nChannels):
4415 4415 # bufferByChannel = self.__bufferList[thisChannel]
4416 4416 # #print self.__startIndex
4417 4417 # x = numpy.array(bufferByChannel)
4418 4418 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
4419 4419 #
4420 4420 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
4421 4421 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
4422 4422 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
4423 4423 #
4424 4424 # dataOut.data = self.__arrayBuffer
4425 4425 #
4426 4426 # self.__startIndex += self.__newNSamples
4427 4427 #
4428 4428 # return
4429 4429
4430 4430
4431 4431
4432 4432
4433 4433
4434 4434
4435 4435
4436 4436 ##############################LONG PULSE##############################
4437 4437
4438 4438
4439 4439
4440 4440 class CrossProdHybrid(CrossProdDP):
4441 4441 """Operation to calculate cross products of the Hybrid Experiment.
4442 4442
4443 4443 Parameters:
4444 4444 -----------
4445 4445 NLAG : int
4446 4446 Number of lags for Long Pulse.
4447 4447 NRANGE : int
4448 4448 Number of samples (heights) for Long Pulse.
4449 4449 NCAL : int
4450 4450 .*
4451 4451 DPL : int
4452 4452 Number of lags for Double Pulse.
4453 4453 NDN : int
4454 4454 .*
4455 4455 NDT : int
4456 4456 Number of heights for Double Pulse.*
4457 4457 NDP : int
4458 4458 Number of heights for Double Pulse.*
4459 4459 NSCAN : int
4460 4460 Number of profiles when the transmitter is on.
4461 4461 lagind : intlist
4462 4462 .*
4463 4463 lagfirst : intlist
4464 4464 .*
4465 4465 NAVG : int
4466 4466 Number of blocks to be "averaged".
4467 4467 nkill : int
4468 4468 Number of blocks not to be considered when averaging.
4469 4469
4470 4470 Example
4471 4471 --------
4472 4472
4473 4473 op = proc_unit.addOperation(name='CrossProdHybrid', optype='other')
4474 4474 op.addParameter(name='NLAG', value='16', format='int')
4475 4475 op.addParameter(name='NRANGE', value='200', format='int')
4476 4476 op.addParameter(name='NCAL', value='0', format='int')
4477 4477 op.addParameter(name='DPL', value='11', format='int')
4478 4478 op.addParameter(name='NDN', value='0', format='int')
4479 4479 op.addParameter(name='NDT', value='67', format='int')
4480 4480 op.addParameter(name='NDP', value='67', format='int')
4481 4481 op.addParameter(name='NSCAN', value='128', format='int')
4482 4482 op.addParameter(name='lagind', value='(0,1,2,3,4,5,6,7,0,3,4,5,6,8,9,10)', format='intlist')
4483 4483 op.addParameter(name='lagfirst', value='(1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1)', format='intlist')
4484 4484 op.addParameter(name='NAVG', value='16', format='int')
4485 4485 op.addParameter(name='nkill', value='6', format='int')
4486 4486
4487 4487 """
4488 4488
4489 4489 def __init__(self, **kwargs):
4490 4490
4491 4491 Operation.__init__(self, **kwargs)
4492 4492 self.bcounter=0
4493 4493 self.aux=1
4494 4494 self.aux_cross_lp=1
4495 4495 self.lag_products_LP_median_estimates_aux=1
4496 4496
4497 4497 def get_products_cabxys_HP(self,dataOut):
4498 4498
4499 4499 if self.aux==1:
4500 4500 self.set_header_output(dataOut)
4501 4501 self.aux=0
4502 4502
4503 4503 self.cax=numpy.zeros((dataOut.NDP,dataOut.DPL,2))# hp:67x11x2 dp: 66x11x2
4504 4504 self.cay=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4505 4505 self.cbx=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4506 4506 self.cby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4507 4507 self.cax2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4508 4508 self.cay2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4509 4509 self.cbx2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4510 4510 self.cby2=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4511 4511 self.caxbx=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4512 4512 self.caxby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4513 4513 self.caybx=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4514 4514 self.cayby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4515 4515 self.caxay=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4516 4516 self.cbxby=numpy.zeros((dataOut.NDP,dataOut.DPL,2))
4517 4517 for i in range(2): # flipped and unflipped
4518 4518 for j in range(dataOut.NDP): # loop over true ranges # 67
4519 4519 for k in range(int(dataOut.NSCAN)): # 128
4520 4520
4521 4521 n=dataOut.lagind[k%dataOut.NLAG] # 128=16x8
4522 4522
4523 4523 ax=dataOut.data[0,k,dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT].real-dataOut.dc.real[0]
4524 4524 ay=dataOut.data[0,k,dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT].imag-dataOut.dc.imag[0]
4525 4525
4526 4526 if dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT+2*n<dataOut.read_samples:
4527 4527
4528 4528 bx=dataOut.data[1,k,dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT+2*n].real-dataOut.dc.real[1]
4529 4529 by=dataOut.data[1,k,dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT+2*n].imag-dataOut.dc.imag[1]
4530 4530
4531 4531 else:
4532 4532
4533 4533 if k+1<int(dataOut.NSCAN):
4534 4534 bx=dataOut.data[1,k+1,(dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT+2*n)%dataOut.NDP].real
4535 4535 by=dataOut.data[1,k+1,(dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT+2*n)%dataOut.NDP].imag
4536 4536
4537 4537 if k+1==int(dataOut.NSCAN):## ESTO ES UN PARCHE PUES NO SE TIENE EL SIGUIENTE BLOQUE
4538 4538 bx=dataOut.data[1,k,(dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT+2*n)%dataOut.NDP].real
4539 4539 by=dataOut.data[1,k,(dataOut.NRANGE+dataOut.NCAL+j+i*dataOut.NDT+2*n)%dataOut.NDP].imag
4540 4540
4541 4541 if(k<dataOut.NLAG and dataOut.lagfirst[k%dataOut.NLAG]==1):# if(k<16 && lagfirst[k%16]==1)
4542 4542 self.cax[j][n][i]=ax
4543 4543 self.cay[j][n][i]=ay
4544 4544 self.cbx[j][n][i]=bx
4545 4545 self.cby[j][n][i]=by
4546 4546 self.cax2[j][n][i]=ax*ax
4547 4547 self.cay2[j][n][i]=ay*ay
4548 4548 self.cbx2[j][n][i]=bx*bx
4549 4549 self.cby2[j][n][i]=by*by
4550 4550 self.caxbx[j][n][i]=ax*bx
4551 4551 self.caxby[j][n][i]=ax*by
4552 4552 self.caybx[j][n][i]=ay*bx
4553 4553 self.cayby[j][n][i]=ay*by
4554 4554 self.caxay[j][n][i]=ax*ay
4555 4555 self.cbxby[j][n][i]=bx*by
4556 4556 else:
4557 4557 self.cax[j][n][i]+=ax
4558 4558 self.cay[j][n][i]+=ay
4559 4559 self.cbx[j][n][i]+=bx
4560 4560 self.cby[j][n][i]+=by
4561 4561 self.cax2[j][n][i]+=ax*ax
4562 4562 self.cay2[j][n][i]+=ay*ay
4563 4563 self.cbx2[j][n][i]+=bx*bx
4564 4564 self.cby2[j][n][i]+=by*by
4565 4565 self.caxbx[j][n][i]+=ax*bx
4566 4566 self.caxby[j][n][i]+=ax*by
4567 4567 self.caybx[j][n][i]+=ay*bx
4568 4568 self.cayby[j][n][i]+=ay*by
4569 4569 self.caxay[j][n][i]+=ax*ay
4570 4570 self.cbxby[j][n][i]+=bx*by
4571 4571
4572 4572
4573 4573 #print(self.cax2[2,0,1])
4574 4574 #input()
4575 4575
4576 4576
4577 4577 def lag_products_LP(self,dataOut):
4578 4578
4579 4579
4580 4580 buffer=dataOut.data
4581 4581 if self.aux_cross_lp==1:
4582 4582
4583 4583 #self.dataOut.nptsfft2=150
4584 4584 self.cnorm=float((dataOut.nProfiles-dataOut.NSCAN)/dataOut.NSCAN)
4585 4585 self.lagp0=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4586 4586 self.lagp1=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4587 4587 self.lagp2=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4588 4588 self.lagp3=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4589 4589
4590 4590 #self.lagp4=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4591 4591 self.aux_cross_lp=0
4592 4592
4593 4593 #print(self.dataOut.data[0,0,0])
4594 4594
4595 4595 for i in range(dataOut.NR):
4596 4596 #print("inside i",i)
4597 4597 buffer_dc=dataOut.dc[i]
4598 4598 for j in range(dataOut.NRANGE):
4599 4599
4600 4600 range_for_n=numpy.min((dataOut.NRANGE-j,dataOut.NLAG))
4601 4601
4602 4602 buffer_aux=numpy.conj(buffer[i,:dataOut.nProfiles,j]-buffer_dc)
4603 4603 for n in range(range_for_n):
4604 4604
4605 4605 c=(buffer_aux)*(buffer[i,:dataOut.nProfiles,j+n]-buffer_dc)
4606 4606
4607 4607 if i==0:
4608 4608 self.lagp0[n][j][self.bcounter-1]=numpy.sum(c[:dataOut.NSCAN])
4609 4609 self.lagp3[n][j][self.bcounter-1]=numpy.sum(c[dataOut.NSCAN:]/self.cnorm)
4610 4610 elif i==1:
4611 4611 self.lagp1[n][j][self.bcounter-1]=numpy.sum(c[:dataOut.NSCAN])
4612 4612 elif i==2:
4613 4613 self.lagp2[n][j][self.bcounter-1]=numpy.sum(c[:dataOut.NSCAN])
4614 4614
4615 4615
4616 4616 self.lagp0[:,:,self.bcounter-1]=numpy.conj(self.lagp0[:,:,self.bcounter-1])
4617 4617 self.lagp1[:,:,self.bcounter-1]=numpy.conj(self.lagp1[:,:,self.bcounter-1])
4618 4618 self.lagp2[:,:,self.bcounter-1]=numpy.conj(self.lagp2[:,:,self.bcounter-1])
4619 4619 self.lagp3[:,:,self.bcounter-1]=numpy.conj(self.lagp3[:,:,self.bcounter-1])
4620 4620
4621 4621
4622 4622 def LP_median_estimates(self,dataOut):
4623 4623
4624 4624 if self.bcounter==dataOut.NAVG:
4625 4625
4626 4626 if self.lag_products_LP_median_estimates_aux==1:
4627 4627 self.output=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NR),'complex64')
4628 4628 self.lag_products_LP_median_estimates_aux=0
4629 4629
4630 4630
4631 4631 for i in range(dataOut.NLAG):
4632 4632 for j in range(dataOut.NRANGE):
4633 4633 for l in range(4): #four outputs
4634 4634
4635 4635 for k in range(dataOut.NAVG):
4636 4636
4637 4637
4638 4638 if k==0:
4639 4639 self.output[i,j,l]=0.0+0.j
4640 4640
4641 4641 if l==0:
4642 4642 self.lagp0[i,j,:]=sorted(self.lagp0[i,j,:], key=lambda x: x.real) #sorted(self.lagp0[i,j,:].real)
4643 4643
4644 4644 if l==1:
4645 4645 self.lagp1[i,j,:]=sorted(self.lagp1[i,j,:], key=lambda x: x.real) #sorted(self.lagp1[i,j,:].real)
4646 4646
4647 4647 if l==2:
4648 4648 self.lagp2[i,j,:]=sorted(self.lagp2[i,j,:], key=lambda x: x.real) #sorted(self.lagp2[i,j,:].real)
4649 4649
4650 4650 if l==3:
4651 4651 self.lagp3[i,j,:]=sorted(self.lagp3[i,j,:], key=lambda x: x.real) #sorted(self.lagp3[i,j,:].real)
4652 4652
4653 4653
4654 4654
4655 4655 if k>=dataOut.nkill/2 and k<dataOut.NAVG-dataOut.nkill/2:
4656 4656 if l==0:
4657 4657
4658 4658 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp0[i,j,k])
4659 4659 if l==1:
4660 4660 #print("lagp1: ",self.lagp1[0,0,:])
4661 4661 #input()
4662 4662 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp1[i,j,k])
4663 4663 #print("self.lagp1[i,j,k]: ",self.lagp1[i,j,k])
4664 4664 #input()
4665 4665 if l==2:
4666 4666 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp2[i,j,k])
4667 4667 if l==3:
4668 4668
4669 4669 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp3[i,j,k])
4670 4670
4671 4671
4672 4672 dataOut.output_LP=self.output
4673 4673 dataOut.data_for_RTI_LP=numpy.zeros((4,dataOut.NRANGE))
4674 4674 dataOut.data_for_RTI_LP[0],dataOut.data_for_RTI_LP[1],dataOut.data_for_RTI_LP[2],dataOut.data_for_RTI_LP[3]=self.RTI_LP(dataOut.output_LP,dataOut.NRANGE)
4675 4675
4676 4676
4677 4677 def get_dc(self,dataOut):
4678 4678
4679 4679 if self.bcounter==0:
4680 4680 dataOut.dc=numpy.zeros(dataOut.NR,dtype='complex64')
4681 4681
4682 4682 #print(numpy.shape(dataOut.data))
4683 4683 #input()
4684 4684
4685 4685 dataOut.dc+=numpy.sum(dataOut.data[:,:,2*dataOut.NLAG:dataOut.NRANGE],axis=(1,2))
4686 4686
4687 4687 dataOut.dc=dataOut.dc/float(dataOut.nProfiles*(dataOut.NRANGE-2*dataOut.NLAG))
4688 4688
4689 4689
4690 4690 #print("dc:",dataOut.dc[0])
4691 4691
4692 4692 def get_dc_new(self,dataOut):
4693 4693
4694 4694 if self.bcounter==0:
4695 4695 dataOut.dc_dp=numpy.zeros(dataOut.NR,dtype='complex64')
4696 4696 dataOut.dc_lp=numpy.zeros(dataOut.NR,dtype='complex64')
4697 4697
4698 4698 #print(numpy.shape(dataOut.data))
4699 4699 #input()
4700 4700
4701 4701 dataOut.dc+=numpy.sum(dataOut.data[:,:,2*dataOut.NLAG:dataOut.NRANGE],axis=(1,2))
4702 4702
4703 4703 dataOut.dc=dataOut.dc/float(dataOut.nProfiles*(dataOut.NRANGE-2*dataOut.NLAG))
4704 4704
4705 4705
4706 4706 #print("dc:",dataOut.dc[0])
4707 4707
4708 4708
4709 4709 def noise_estimation4x_HP(self,dataOut):
4710 4710 if self.bcounter==dataOut.NAVG:
4711 4711 dataOut.noise_final=numpy.zeros(dataOut.NR,'float32')
4712 4712 #snoise=numpy.zeros((NR,NAVG),'float32')
4713 4713 #nvector1=numpy.zeros((NR,NAVG,MAXNRANGENDT),'float32')
4714 4714 sorted_data=numpy.zeros((dataOut.MAXNRANGENDT,dataOut.NR,dataOut.NAVG),'float32')
4715 4715 for i in range(dataOut.NR):
4716 4716 dataOut.noise_final[i]=0.0
4717 4717 for j in range(dataOut.MAXNRANGENDT):
4718 4718 sorted_data[j,i,:]=numpy.copy(sorted(dataOut.noisevector[j,i,:]))
4719 4719 #print(sorted(noisevector[j,i,:]))
4720 4720 #input()
4721 4721 l=dataOut.MAXNRANGENDT-2
4722 4722 for k in range(dataOut.NAVG):
4723 4723 if k>=dataOut.nkill/2 and k<dataOut.NAVG-dataOut.nkill/2:
4724 4724 #print(k)
4725 4725 #print(sorted_data[min(j,l),i,k])
4726 4726 dataOut.noise_final[i]+=sorted_data[min(j,l),i,k]*float(dataOut.NAVG)/float(dataOut.NAVG-dataOut.nkill)
4727 4727 #print(dataOut.noise_final[i])
4728 4728 #input()
4729 4729 #print(dataOut.noise_final)
4730 4730 #input()
4731 4731
4732 4732 def noisevectorizer(self,NSCAN,nProfiles,NR,MAXNRANGENDT,noisevector,data,dc):
4733 4733
4734 4734 #rnormalizer= 1./(float(nProfiles - NSCAN))
4735 4735 rnormalizer= float(NSCAN)/((float(nProfiles - NSCAN))*float(MAXNRANGENDT))
4736 4736 for i in range(NR):
4737 4737 for j in range(MAXNRANGENDT):
4738 4738 for k in range(NSCAN,nProfiles):
4739 4739 #TODO:integrate just 2nd quartile gates
4740 4740 if k==NSCAN:
4741 4741 noisevector[j][i][self.bcounter]=(abs(data[i][k][j]-dc[i])**2)*rnormalizer
4742 4742 ##noisevector[j][i][iavg]=(abs(cdata[k][j][i])**2)*rnormalizer
4743 4743 else:
4744 4744 noisevector[j][i][self.bcounter]+=(abs(data[i][k][j]-dc[i])**2)*rnormalizer
4745 4745
4746 4746
4747 4747 def RTI_LP(self,output,NRANGE):
4748 4748 x00=numpy.zeros(NRANGE,dtype='float32')
4749 4749 x01=numpy.zeros(NRANGE,dtype='float32')
4750 4750 x02=numpy.zeros(NRANGE,dtype='float32')
4751 4751 x03=numpy.zeros(NRANGE,dtype='float32')
4752 4752
4753 4753 for i in range(2): #first couple of lags
4754 4754 for j in range(NRANGE): #
4755 4755 #fx=numpy.sqrt((kaxbx[i,j,k]+kayby[i,j,k])**2+(kaybx[i,j,k]-kaxby[i,j,k])**2)
4756 4756 x00[j]+=numpy.abs(output[i,j,0]) #Ch0
4757 4757 x01[j]+=numpy.abs(output[i,j,1]) #Ch1
4758 4758 x02[j]+=numpy.abs(output[i,j,2]) #Ch2
4759 4759 x03[j]+=numpy.abs(output[i,j,3]) #Ch3
4760 4760 #x02[i]=x02[i]+fx
4761 4761
4762 4762 x00[j]=10.0*numpy.log10(x00[j]/4.)
4763 4763 x01[j]=10.0*numpy.log10(x01[j]/4.)
4764 4764 x02[j]=10.0*numpy.log10(x02[j]/4.)
4765 4765 x03[j]=10.0*numpy.log10(x03[j]/4.)
4766 4766 #x02[i]=10.0*numpy.log10(x02[i])
4767 4767 return x00,x01,x02,x03
4768 4768
4769 4769 def run(self, dataOut, NLAG=None, NRANGE=None, NCAL=None, DPL=None,
4770 4770 NDN=None, NDT=None, NDP=None, NSCAN=None,
4771 4771 lagind=None, lagfirst=None,
4772 4772 NAVG=None, nkill=None):
4773 4773
4774 4774 dataOut.NLAG=NLAG
4775 4775 dataOut.NR=len(dataOut.channelList)
4776 4776 dataOut.NRANGE=NRANGE
4777 4777 dataOut.NCAL=NCAL
4778 4778 dataOut.DPL=DPL
4779 4779 dataOut.NDN=NDN
4780 4780 dataOut.NDT=NDT
4781 4781 dataOut.NDP=NDP
4782 4782 dataOut.NSCAN=NSCAN
4783 4783 dataOut.DH=dataOut.heightList[1]-dataOut.heightList[0]
4784 4784 dataOut.H0=int(dataOut.heightList[0])
4785 4785 dataOut.lagind=lagind
4786 4786 dataOut.lagfirst=lagfirst
4787 4787 dataOut.NAVG=NAVG
4788 4788 dataOut.nkill=nkill
4789 4789
4790 4790 dataOut.flagNoData = True
4791 4791
4792 4792 self.get_dc(dataOut)
4793 4793 self.get_products_cabxys_HP(dataOut)
4794 4794 self.cabxys_navg(dataOut)
4795 4795 self.lag_products_LP(dataOut)
4796 4796 self.LP_median_estimates(dataOut)
4797 4797 self.noise_estimation4x_HP(dataOut)
4798 4798 self.kabxys(dataOut)
4799 4799
4800 4800 return dataOut
4801 4801
4802 4802
4803 4803 class CrossProdLP(CrossProdDP):
4804 4804 """Operation to calculate cross products of the Hybrid Experiment.
4805 4805
4806 4806 Parameters:
4807 4807 -----------
4808 4808 NLAG : int
4809 4809 Number of lags for Long Pulse.
4810 4810 NRANGE : int
4811 4811 Number of samples (heights) for Long Pulse.
4812 4812 NCAL : int
4813 4813 .*
4814 4814 DPL : int
4815 4815 Number of lags for Double Pulse.
4816 4816 NDN : int
4817 4817 .*
4818 4818 NDT : int
4819 4819 Number of heights for Double Pulse.*
4820 4820 NDP : int
4821 4821 Number of heights for Double Pulse.*
4822 4822 NSCAN : int
4823 4823 Number of profiles when the transmitter is on.
4824 4824 lagind : intlist
4825 4825 .*
4826 4826 lagfirst : intlist
4827 4827 .*
4828 4828 NAVG : int
4829 4829 Number of blocks to be "averaged".
4830 4830 nkill : int
4831 4831 Number of blocks not to be considered when averaging.
4832 4832
4833 4833 Example
4834 4834 --------
4835 4835
4836 4836 op = proc_unit.addOperation(name='CrossProdHybrid', optype='other')
4837 4837 op.addParameter(name='NLAG', value='16', format='int')
4838 4838 op.addParameter(name='NRANGE', value='200', format='int')
4839 4839 op.addParameter(name='NCAL', value='0', format='int')
4840 4840 op.addParameter(name='DPL', value='11', format='int')
4841 4841 op.addParameter(name='NDN', value='0', format='int')
4842 4842 op.addParameter(name='NDT', value='67', format='int')
4843 4843 op.addParameter(name='NDP', value='67', format='int')
4844 4844 op.addParameter(name='NSCAN', value='128', format='int')
4845 4845 op.addParameter(name='lagind', value='(0,1,2,3,4,5,6,7,0,3,4,5,6,8,9,10)', format='intlist')
4846 4846 op.addParameter(name='lagfirst', value='(1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1)', format='intlist')
4847 4847 op.addParameter(name='NAVG', value='16', format='int')
4848 4848 op.addParameter(name='nkill', value='6', format='int')
4849 4849
4850 4850 """
4851 4851
4852 4852 def __init__(self, **kwargs):
4853 4853
4854 4854 Operation.__init__(self, **kwargs)
4855 4855 self.bcounter=0
4856 4856 self.aux=1
4857 4857 self.aux_cross_lp=1
4858 4858 self.lag_products_LP_median_estimates_aux=1
4859 4859
4860 4860
4861 4861
4862 4862 #print(self.cax2[2,0,1])
4863 4863 #input()
4864 4864
4865 4865
4866 4866 def lag_products_LP(self,dataOut):
4867 4867
4868 4868
4869 4869 buffer=dataOut.data
4870 4870 if self.aux_cross_lp==1:
4871 4871
4872 4872 #self.dataOut.nptsfft2=150
4873 4873 self.cnorm=float((dataOut.nProfiles-dataOut.NSCAN)/dataOut.NSCAN)
4874 4874 self.lagp0=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4875 4875 self.lagp1=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4876 4876 self.lagp2=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4877 4877 self.lagp3=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4878 4878 self.lagp4=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4879 4879 self.lagp5=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4880 4880
4881 4881 #self.lagp4=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NAVG),'complex64')
4882 4882 self.aux_cross_lp=0
4883 4883
4884 4884 dataOut.noisevector=numpy.zeros((dataOut.MAXNRANGENDT,dataOut.NR,dataOut.NAVG),'float32')
4885 4885
4886 4886 #print(self.dataOut.data[0,0,0])
4887 4887 self.noisevectorizer(dataOut.NSCAN,dataOut.nProfiles,dataOut.NR,dataOut.MAXNRANGENDT,dataOut.noisevector,dataOut.data,dataOut.dc) #30/03/2020
4888 4888
4889 4889
4890 4890 for i in range(dataOut.NR):
4891 4891 #print("inside i",i)
4892 4892 buffer_dc=dataOut.dc[i]
4893 4893 for j in range(dataOut.NRANGE):
4894 4894
4895 4895 range_for_n=numpy.min((dataOut.NRANGE-j,dataOut.NLAG))
4896 4896
4897 4897 buffer_aux=numpy.conj(buffer[i,:dataOut.nProfiles,j]-buffer_dc)
4898 4898 for n in range(range_for_n):
4899 4899
4900 4900 c=(buffer_aux)*(buffer[i,:dataOut.nProfiles,j+n]-buffer_dc)
4901 4901
4902 4902 if i==0:
4903 4903 self.lagp0[n][j][self.bcounter]=numpy.sum(c[:dataOut.NSCAN])
4904 4904 #self.lagp3[n][j][self.bcounter-1]=numpy.sum(c[dataOut.NSCAN:]/self.cnorm)
4905 4905 elif i==1:
4906 4906 self.lagp1[n][j][self.bcounter]=numpy.sum(c[:dataOut.NSCAN])
4907 4907 elif i==2:
4908 4908 self.lagp2[n][j][self.bcounter]=numpy.sum(c[:dataOut.NSCAN])
4909 4909 elif i==3:
4910 4910 self.lagp3[n][j][self.bcounter]=numpy.sum(c[:dataOut.NSCAN])
4911 4911 elif i==4:
4912 4912 self.lagp4[n][j][self.bcounter]=numpy.sum(c[:dataOut.NSCAN])
4913 4913 elif i==5:
4914 4914 self.lagp5[n][j][self.bcounter]=numpy.sum(c[:dataOut.NSCAN])
4915 4915
4916 4916
4917 4917 self.lagp0[:,:,self.bcounter]=numpy.conj(self.lagp0[:,:,self.bcounter])
4918 4918 self.lagp1[:,:,self.bcounter]=numpy.conj(self.lagp1[:,:,self.bcounter])
4919 4919 self.lagp2[:,:,self.bcounter]=numpy.conj(self.lagp2[:,:,self.bcounter])
4920 4920 self.lagp3[:,:,self.bcounter]=numpy.conj(self.lagp3[:,:,self.bcounter])
4921 4921
4922 4922 self.bcounter += 1
4923 4923
4924 4924
4925 4925 def LP_median_estimates(self,dataOut):
4926 4926
4927 4927 if self.bcounter==dataOut.NAVG:
4928 4928 dataOut.flagNoData = False
4929 4929
4930 4930 if self.lag_products_LP_median_estimates_aux==1:
4931 4931 self.output=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NR),'complex64')
4932 4932 self.lag_products_LP_median_estimates_aux=0
4933 4933
4934 4934
4935 4935 for i in range(dataOut.NLAG):
4936 4936 for j in range(dataOut.NRANGE):
4937 4937 for l in range(4): #four outputs
4938 4938
4939 4939 for k in range(dataOut.NAVG):
4940 4940
4941 4941
4942 4942 if k==0:
4943 4943 self.output[i,j,l]=0.0+0.j
4944 4944
4945 4945 if l==0:
4946 4946 self.lagp0[i,j,:]=sorted(self.lagp0[i,j,:], key=lambda x: x.real) #sorted(self.lagp0[i,j,:].real)
4947 4947
4948 4948 if l==1:
4949 4949 self.lagp1[i,j,:]=sorted(self.lagp1[i,j,:], key=lambda x: x.real) #sorted(self.lagp1[i,j,:].real)
4950 4950
4951 4951 if l==2:
4952 4952 self.lagp2[i,j,:]=sorted(self.lagp2[i,j,:], key=lambda x: x.real) #sorted(self.lagp2[i,j,:].real)
4953 4953
4954 4954 if l==3:
4955 4955 self.lagp3[i,j,:]=sorted(self.lagp3[i,j,:], key=lambda x: x.real) #sorted(self.lagp3[i,j,:].real)
4956 4956
4957 4957
4958 4958
4959 4959 if k>=dataOut.nkill/2 and k<dataOut.NAVG-dataOut.nkill/2:
4960 4960 if l==0:
4961 4961
4962 4962 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp0[i,j,k])
4963 4963 if l==1:
4964 4964 #print("lagp1: ",self.lagp1[0,0,:])
4965 4965 #input()
4966 4966 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp1[i,j,k])
4967 4967 #print("self.lagp1[i,j,k]: ",self.lagp1[i,j,k])
4968 4968 #input()
4969 4969 if l==2:
4970 4970 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp2[i,j,k])
4971 4971 if l==3:
4972 4972
4973 4973 self.output[i,j,l]=self.output[i,j,l]+((float(dataOut.NAVG)/(float)(dataOut.NAVG-dataOut.nkill))*self.lagp3[i,j,k])
4974 4974
4975 4975
4976 4976 dataOut.output_LP=self.output
4977 4977 dataOut.data_for_RTI_LP=numpy.zeros((4,dataOut.NRANGE))
4978 4978 dataOut.data_for_RTI_LP[0],dataOut.data_for_RTI_LP[1],dataOut.data_for_RTI_LP[2],dataOut.data_for_RTI_LP[3]=self.RTI_LP(dataOut.output_LP,dataOut.NRANGE)
4979 4979
4980 4980 self.bcounter = 0
4981 4981
4982 4982 def get_dc(self,dataOut):
4983 4983
4984 4984 if self.bcounter==0:
4985 4985 dataOut.dc=numpy.zeros(dataOut.NR,dtype='complex64')
4986 4986
4987 4987 #print(numpy.shape(dataOut.data))
4988 4988 #input()
4989 4989
4990 4990 dataOut.dc+=numpy.sum(dataOut.data[:,:,2*dataOut.NLAG:dataOut.NRANGE],axis=(1,2))
4991 4991
4992 4992 dataOut.dc=dataOut.dc/float(dataOut.nProfiles*(dataOut.NRANGE-2*dataOut.NLAG))
4993 4993
4994 4994
4995 4995 #print("dc:",dataOut.dc[0])
4996 4996
4997 4997
4998 4998
4999 4999
5000 5000 def noise_estimation4x_HP(self,dataOut):
5001 5001 if self.bcounter==dataOut.NAVG:
5002 5002 dataOut.noise_final=numpy.zeros(dataOut.NR,'float32')
5003 5003 #snoise=numpy.zeros((NR,NAVG),'float32')
5004 5004 #nvector1=numpy.zeros((NR,NAVG,MAXNRANGENDT),'float32')
5005 5005 sorted_data=numpy.zeros((dataOut.MAXNRANGENDT,dataOut.NR,dataOut.NAVG),'float32')
5006 5006 for i in range(dataOut.NR):
5007 5007 dataOut.noise_final[i]=0.0
5008 5008 for j in range(dataOut.MAXNRANGENDT):
5009 5009 sorted_data[j,i,:]=numpy.copy(sorted(dataOut.noisevector[j,i,:]))
5010 5010 #print(sorted(noisevector[j,i,:]))
5011 5011 #input()
5012 5012 l=dataOut.MAXNRANGENDT-2
5013 5013 for k in range(dataOut.NAVG):
5014 5014 if k>=dataOut.nkill/2 and k<dataOut.NAVG-dataOut.nkill/2:
5015 5015 #print(k)
5016 5016 #print(sorted_data[min(j,l),i,k])
5017 5017 dataOut.noise_final[i]+=sorted_data[min(j,l),i,k]*float(dataOut.NAVG)/float(dataOut.NAVG-dataOut.nkill)
5018 5018 #print(dataOut.noise_final[i])
5019 5019 #input()
5020 5020 #print(dataOut.noise_final)
5021 5021 #input()
5022 5022
5023 5023 def noisevectorizer(self,NSCAN,nProfiles,NR,MAXNRANGENDT,noisevector,data,dc):
5024 5024
5025 5025 #rnormalizer= 1./(float(nProfiles - NSCAN))
5026 5026 #rnormalizer= float(NSCAN)/((float(nProfiles - NSCAN))*float(MAXNRANGENDT))
5027 5027 rnormalizer= float(NSCAN)/((float(1))*float(MAXNRANGENDT))
5028 5028 for i in range(NR):
5029 5029 for j in range(MAXNRANGENDT):
5030 5030 for k in range(NSCAN,nProfiles):
5031 5031 #TODO:integrate just 2nd quartile gates
5032 5032 if k==NSCAN:
5033 5033 noisevector[j][i][self.bcounter]=(abs(data[i][k][j]-dc[i])**2)*rnormalizer
5034 5034 ##noisevector[j][i][iavg]=(abs(cdata[k][j][i])**2)*rnormalizer
5035 5035 else:
5036 5036 noisevector[j][i][self.bcounter]+=(abs(data[i][k][j]-dc[i])**2)*rnormalizer
5037 5037
5038 5038
5039 5039 def RTI_LP(self,output,NRANGE):
5040 5040 x00=numpy.zeros(NRANGE,dtype='float32')
5041 5041 x01=numpy.zeros(NRANGE,dtype='float32')
5042 5042 x02=numpy.zeros(NRANGE,dtype='float32')
5043 5043 x03=numpy.zeros(NRANGE,dtype='float32')
5044 5044
5045 5045 for i in range(1): #first couple of lags
5046 5046 for j in range(NRANGE): #
5047 5047 #fx=numpy.sqrt((kaxbx[i,j,k]+kayby[i,j,k])**2+(kaybx[i,j,k]-kaxby[i,j,k])**2)
5048 5048 x00[j]+=numpy.abs(output[i,j,0]) #Ch0
5049 5049 x01[j]+=numpy.abs(output[i,j,1]) #Ch1
5050 5050 x02[j]+=numpy.abs(output[i,j,2]) #Ch2
5051 5051 x03[j]+=numpy.abs(output[i,j,3]) #Ch3
5052 5052 #x02[i]=x02[i]+fx
5053 5053
5054 5054 x00[j]=10.0*numpy.log10(x00[j]/4.)
5055 5055 x01[j]=10.0*numpy.log10(x01[j]/4.)
5056 5056 x02[j]=10.0*numpy.log10(x02[j]/4.)
5057 5057 x03[j]=10.0*numpy.log10(x03[j]/4.)
5058 5058 #x02[i]=10.0*numpy.log10(x02[i])
5059 5059 return x00,x01,x02,x03
5060 5060
5061 5061 def run(self, dataOut, NLAG=None, NRANGE=None, NCAL=None, DPL=None,
5062 5062 NDN=None, NDT=None, NDP=None, NSCAN=None,
5063 5063 lagind=None, lagfirst=None,
5064 5064 NAVG=None, nkill=None):
5065 5065
5066 5066 dataOut.NLAG=NLAG
5067 5067 dataOut.NR=len(dataOut.channelList)
5068 5068 #dataOut.NRANGE=NRANGE
5069 5069 dataOut.NRANGE=dataOut.nHeights
5070 5070 dataOut.NCAL=NCAL
5071 5071 dataOut.DPL=DPL
5072 5072 dataOut.NDN=NDN
5073 5073 dataOut.NDT=NDT
5074 5074 dataOut.NDP=NDP
5075 5075 dataOut.NSCAN=NSCAN
5076 5076 dataOut.DH=dataOut.heightList[1]-dataOut.heightList[0]
5077 5077 dataOut.H0=int(dataOut.heightList[0])
5078 5078 dataOut.lagind=lagind
5079 5079 dataOut.lagfirst=lagfirst
5080 5080 dataOut.NAVG=NAVG
5081 5081 dataOut.nkill=nkill
5082 5082
5083 5083 dataOut.MAXNRANGENDT = dataOut.NRANGE
5084 5084
5085 5085 dataOut.flagNoData = True
5086 5086
5087 5087 print(self.bcounter)
5088 5088
5089 5089 self.get_dc(dataOut)
5090 5090 self.lag_products_LP(dataOut)
5091 5091 self.noise_estimation4x_HP(dataOut)
5092 5092 self.LP_median_estimates(dataOut)
5093 5093
5094 5094 print("******************DONE******************")
5095 5095
5096 5096
5097 5097
5098 5098 return dataOut
5099 5099
5100 5100
5101 5101 class RemoveDebris(Operation):
5102 5102 """Operation to remove blocks where an outlier is found for Double (Long) Pulse.
5103 5103
5104 5104 Parameters:
5105 5105 -----------
5106 5106 None
5107 5107
5108 5108 Example
5109 5109 --------
5110 5110
5111 5111 op = proc_unit.addOperation(name='RemoveDebris', optype='other')
5112 5112
5113 5113 """
5114 5114
5115 5115 def __init__(self, **kwargs):
5116 5116
5117 5117 Operation.__init__(self, **kwargs)
5118 5118
5119 5119 def run(self,dataOut):
5120 5120 print("init_debris",dataOut.flagNoData)
5121 5121 #dataOut.debris_activated=0
5122 5122 debris=numpy.zeros(dataOut.NRANGE,'float32')
5123 5123
5124 5124 for j in range(0,3):
5125 5125 for i in range(dataOut.NRANGE):
5126 5126 if j==0:
5127 5127 debris[i]=10*numpy.log10(numpy.abs(dataOut.output_LP[j,i,0]))
5128 5128 else:
5129 5129 debris[i]+=10*numpy.log10(numpy.abs(dataOut.output_LP[j,i,0]))
5130 5130
5131 5131 thresh=8.0+4+4+4
5132 5132 for i in range(47,100):
5133 5133 if ((debris[i-2]+debris[i-1]+debris[i]+debris[i+1])>
5134 5134 ((debris[i-12]+debris[i-11]+debris[i-10]+debris[i-9]+
5135 5135 debris[i+12]+debris[i+11]+debris[i+10]+debris[i+9])/2.0+
5136 5136 thresh)):
5137 5137
5138 5138 dataOut.flagNoData=True
5139 5139 print("LP Debris detected at",i*15,"km")
5140 5140
5141 5141 debris=numpy.zeros(dataOut.NDP,dtype='float32')
5142 5142 Range=numpy.arange(0,3000,15)
5143 5143 for k in range(2): #flip
5144 5144 for i in range(dataOut.NDP): #
5145 5145 debris[i]+=numpy.sqrt((dataOut.kaxbx[i,0,k]+dataOut.kayby[i,0,k])**2+(dataOut.kaybx[i,0,k]-dataOut.kaxby[i,0,k])**2)
5146 5146
5147 5147 if gmtime(dataOut.utctime).tm_hour > 11:
5148 5148 for i in range(2,dataOut.NDP-2):
5149 5149 if (debris[i]>3.0*debris[i-2] and
5150 5150 debris[i]>3.0*debris[i+2] and
5151 5151 Range[i]>200.0 and Range[i]<=540.0):
5152 5152 dataOut.flagNoData=True
5153 5153 print("DP Debris detected at",i*15,"km")
5154 5154
5155 5155 print("inside debris",dataOut.flagNoData)
5156 5156 return dataOut
5157 5157
5158 5158
5159 5159 class IntegrationHP(IntegrationDP):
5160 5160 """Operation to integrate Double Pulse and Long Pulse data.
5161 5161
5162 5162 Parameters:
5163 5163 -----------
5164 5164 nint : int
5165 5165 Number of integrations.
5166 5166
5167 5167 Example
5168 5168 --------
5169 5169
5170 5170 op = proc_unit.addOperation(name='IntegrationHP', optype='other')
5171 5171 op.addParameter(name='nint', value='30', format='int')
5172 5172
5173 5173 """
5174 5174
5175 5175 def __init__(self, **kwargs):
5176 5176
5177 5177 Operation.__init__(self, **kwargs)
5178 5178
5179 5179 self.counter = 0
5180 5180 self.aux = 0
5181 5181
5182 5182 def integration_noise(self,dataOut):
5183 5183
5184 5184 if self.counter == 0:
5185 5185 dataOut.tnoise=numpy.zeros((dataOut.NR),dtype='float32')
5186 5186
5187 5187 dataOut.tnoise+=dataOut.noise_final
5188 5188
5189 5189 def integration_for_long_pulse(self,dataOut):
5190 5190
5191 5191 if self.counter == 0:
5192 5192 dataOut.output_LP_integrated=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NR),order='F',dtype='complex64')
5193 5193
5194 5194 dataOut.output_LP_integrated+=dataOut.output_LP
5195 5195
5196 5196 def run(self,dataOut,nint=None):
5197 5197
5198 5198 dataOut.flagNoData=True
5199 5199
5200 5200 #print("flag_inside",dataOut.flagNoData)
5201 5201 dataOut.nint=nint
5202 5202 dataOut.paramInterval=0#int(dataOut.nint*dataOut.header[7][0]*2 )
5203 5203 dataOut.lat=-11.95
5204 5204 dataOut.lon=-76.87
5205 5205
5206 5206 self.integration_for_long_pulse(dataOut)
5207 5207
5208 5208 self.integration_noise(dataOut)
5209 5209
5210 5210
5211 5211 if self.counter==dataOut.nint-1:
5212 5212
5213 5213 dataOut.tnoise[0]*=0.995
5214 5214 dataOut.tnoise[1]*=0.995
5215 5215 dataOut.pan=dataOut.tnoise[0]/float(dataOut.NSCAN*dataOut.nint*dataOut.NAVG)
5216 5216 dataOut.pbn=dataOut.tnoise[1]/float(dataOut.NSCAN*dataOut.nint*dataOut.NAVG)
5217 5217
5218 5218 self.integration_for_double_pulse(dataOut)
5219 5219
5220 5220
5221 5221
5222 5222 return dataOut
5223 5223
5224 5224
5225 5225 class IntegrationLP(Operation):
5226 5226 """Operation to integrate Double Pulse and Long Pulse data.
5227 5227
5228 5228 Parameters:
5229 5229 -----------
5230 5230 nint : int
5231 5231 Number of integrations.
5232 5232
5233 5233 Example
5234 5234 --------
5235 5235
5236 5236 op = proc_unit.addOperation(name='IntegrationHP', optype='other')
5237 5237 op.addParameter(name='nint', value='30', format='int')
5238 5238
5239 5239 """
5240 5240
5241 5241 def __init__(self, **kwargs):
5242 5242
5243 5243 Operation.__init__(self, **kwargs)
5244 5244
5245 5245 self.counter = 0
5246 5246 self.aux = 0
5247 5247
5248 5248 def integration_noise(self,dataOut):
5249 5249
5250 5250 if self.counter == 0:
5251 5251 dataOut.tnoise=numpy.zeros((dataOut.NR),dtype='float32')
5252 5252
5253 5253 dataOut.tnoise+=dataOut.noise_final
5254 5254 '''
5255 5255 def integration_for_long_pulse(self,dataOut):
5256 5256
5257 5257 if self.counter == 0:
5258 5258 dataOut.output_LP_integrated=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NR),order='F',dtype='complex64')
5259 5259
5260 5260 dataOut.output_LP_integrated+=dataOut.output_LP
5261 5261 '''
5262 5262 def integration_for_long_pulse(self,dataOut):
5263 5263 #print("inside")
5264 5264 #print(self.aux)
5265 5265
5266 5266 if self.counter == 0:
5267 5267 dataOut.output_LP_integrated=numpy.zeros((dataOut.NLAG,dataOut.NRANGE,dataOut.NR),order='F',dtype='complex64')
5268 5268
5269 5269 dataOut.output_LP_integrated+=dataOut.output_LP
5270 5270
5271 5271 if self.aux==1:
5272 5272 #print("CurrentBlockBBBBB: ",dataOut.CurrentBlock)
5273 5273 #print(dataOut.datatime)
5274 5274
5275 5275 #dataOut.TimeBlockDate_for_dp_power=dataOut.TimeBlockDate
5276 5276 ########dataOut.TimeBlockSeconds_for_dp_power=dataOut.LastAVGDate
5277 5277 #print("Date: ",dataOut.TimeBlockDate_for_dp_power)
5278 5278
5279 5279 #dataOut.TimeBlockSeconds_for_dp_power=mktime(strptime(dataOut.TimeBlockDate_for_dp_power))
5280 5280 dataOut.TimeBlockSeconds_for_dp_power=dataOut.utctime#dataOut.TimeBlockSeconds-18000
5281 5281 #dataOut.TimeBlockSeconds_for_dp_power=dataOut.LastAVGDate
5282 5282 #print("Seconds: ",dataOut.TimeBlockSeconds_for_dp_power)
5283 5283 dataOut.bd_time=gmtime(dataOut.TimeBlockSeconds_for_dp_power)
5284 5284 #print(dataOut.bd_time)
5285 5285 #exit()
5286 5286 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
5287 5287 dataOut.ut_Faraday=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
5288 5288 #print("date: ", dataOut.TimeBlockDate)
5289 5289
5290 5290
5291 5291 self.aux=0
5292 5292
5293 5293 #print("after")
5294 5294
5295 5295 self.integration_noise(dataOut)
5296 5296
5297 5297 if self.counter==0:
5298 5298
5299 5299 self.init_time=dataOut.utctime
5300 5300
5301 5301 if self.counter < dataOut.nint:
5302 5302 #print("HERE")
5303 5303
5304 5304
5305 5305
5306 5306 self.counter+=1
5307 5307
5308 5308 if self.counter==dataOut.nint-1:
5309 5309 self.aux=1
5310 5310 #dataOut.TimeBlockDate_for_dp_power=dataOut.TimeBlockDate
5311 5311 if self.counter==dataOut.nint:
5312 5312
5313 5313 dataOut.flagNoData=False
5314 5314 dataOut.utctime=self.init_time
5315 5315 self.counter=0
5316 5316
5317 5317 def run(self,dataOut,nint=None):
5318 5318
5319 5319 dataOut.flagNoData=True
5320 5320
5321 5321 #print("flag_inside",dataOut.flagNoData)
5322 5322 dataOut.nint=nint
5323 5323 dataOut.paramInterval=0#int(dataOut.nint*dataOut.header[7][0]*2 )
5324 5324 dataOut.lat=-11.95
5325 5325 dataOut.lon=-76.87
5326 5326
5327 5327 self.integration_for_long_pulse(dataOut)
5328 5328
5329 5329
5330 5330 if self.counter==dataOut.nint:
5331 5331
5332 5332 dataOut.tnoise[0]*=0.995
5333 5333 dataOut.tnoise[1]*=0.995
5334 5334 dataOut.pan=dataOut.tnoise[0]/float(dataOut.NSCAN*dataOut.nint*dataOut.NAVG)
5335 5335 dataOut.pbn=dataOut.tnoise[1]/float(dataOut.NSCAN*dataOut.nint*dataOut.NAVG)
5336 5336
5337 5337 #self.integration_for_double_pulse(dataOut)
5338 5338 print("HERE2")
5339 5339
5340 5340
5341 5341
5342 5342 return dataOut
5343 5343
5344 5344
5345 5345 class SumFlipsHP(SumFlips):
5346 5346 """Operation to sum the flip and unflip part of certain cross products of the Double Pulse.
5347 5347
5348 5348 Parameters:
5349 5349 -----------
5350 5350 None
5351 5351
5352 5352 Example
5353 5353 --------
5354 5354
5355 5355 op = proc_unit.addOperation(name='SumFlipsHP', optype='other')
5356 5356
5357 5357 """
5358 5358
5359 5359 def __init__(self, **kwargs):
5360 5360
5361 5361 Operation.__init__(self, **kwargs)
5362 5362
5363 5363 def rint2HP(self,dataOut):
5364 5364
5365 5365 dataOut.rnint2=numpy.zeros(dataOut.DPL,'float32')
5366 5366
5367 5367 for l in range(dataOut.DPL):
5368 5368 if(l==0 or (l>=3 and l <=6)):
5369 5369 dataOut.rnint2[l]=0.5/float(dataOut.nint*dataOut.NAVG*16.0)
5370 5370 else:
5371 5371 dataOut.rnint2[l]=0.5/float(dataOut.nint*dataOut.NAVG*8.0)
5372 5372
5373 5373 def run(self,dataOut):
5374 5374
5375 5375 self.rint2HP(dataOut)
5376 5376 self.SumLags(dataOut)
5377 5377
5378 5378 return dataOut
5379 5379
5380 5380
5381 5381 class LongPulseAnalysis(Operation):
5382 5382 """Operation to estimate ACFs, temperatures, total electron density and Hydrogen/Helium fractions from the Long Pulse data.
5383 5383
5384 5384 Parameters:
5385 5385 -----------
5386 5386 NACF : int
5387 5387 .*
5388 5388
5389 5389 Example
5390 5390 --------
5391 5391
5392 5392 op = proc_unit.addOperation(name='LongPulseAnalysis', optype='other')
5393 5393 op.addParameter(name='NACF', value='16', format='int')
5394 5394
5395 5395 """
5396 5396
5397 5397 def __init__(self, **kwargs):
5398 5398
5399 5399 Operation.__init__(self, **kwargs)
5400 5400 self.aux=1
5401 5401
5402 5402 def run(self,dataOut,NACF):
5403 5403
5404 5404 dataOut.NACF=NACF
5405 5405 dataOut.heightList=dataOut.DH*(numpy.arange(dataOut.NACF))
5406 5406 anoise0=dataOut.tnoise[0]
5407 5407 anoise1=anoise0*0.0 #seems to be noise in 1st lag 0.015 before '14
5408 5408
5409 5409 if self.aux:
5410 5410 #dataOut.cut=31#26#height=31*15=465
5411 5411 self.cal=numpy.zeros((dataOut.NLAG),'float32')
5412 5412 self.drift=numpy.zeros((200),'float32')
5413 5413 self.rdrift=numpy.zeros((200),'float32')
5414 5414 self.ddrift=numpy.zeros((200),'float32')
5415 5415 self.sigma=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5416 5416 self.powera=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5417 5417 self.powerb=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5418 5418 self.perror=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5419 5419 dataOut.ene=numpy.zeros((dataOut.NRANGE),'float32')
5420 5420 self.dpulse=numpy.zeros((dataOut.NACF),'float32')
5421 5421 self.lpulse=numpy.zeros((dataOut.NACF),'float32')
5422 5422 dataOut.lags_LP=numpy.zeros((dataOut.IBITS),order='F',dtype='float32')
5423 5423 self.lagp=numpy.zeros((dataOut.NACF),'float32')
5424 5424 self.u=numpy.zeros((2*dataOut.NACF,2*dataOut.NACF),'float32')
5425 5425 dataOut.ne=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5426 5426 dataOut.te=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5427 5427 dataOut.ete=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5428 5428 dataOut.ti=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5429 5429 dataOut.eti=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5430 5430 dataOut.ph=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5431 5431 dataOut.eph=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5432 5432 dataOut.phe=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5433 5433 dataOut.ephe=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5434 5434 dataOut.errors=numpy.zeros((dataOut.IBITS,max(dataOut.NRANGE,dataOut.NSHTS)),order='F',dtype='float32')
5435 5435 dataOut.fit_array_real=numpy.zeros((max(dataOut.NRANGE,dataOut.NSHTS),dataOut.NLAG),order='F',dtype='float32')
5436 5436 dataOut.status=numpy.zeros(1,'float32')
5437 5437 dataOut.tx=240.0 #deberΓ­a provenir del header #hybrid
5438 5438
5439 5439 for i in range(dataOut.IBITS):
5440 5440 dataOut.lags_LP[i]=float(i)*(dataOut.tx/150.0)/float(dataOut.IBITS) # (float)i*(header.tx/150.0)/(float)IBITS;
5441 5441
5442 5442 self.aux=0
5443 5443
5444 5444 dataOut.cut=30
5445 5445 for i in range(30,15,-1):
5446 5446 if numpy.nanmax(dataOut.acfs_error_to_plot[i,:])>=10 or dataOut.info2[i]==0:
5447 5447 dataOut.cut=i-1
5448 5448 #print(dataOut.cut)
5449 5449 #print(dataOut.info2[:])
5450 5450 #print(dataOut.te2[:])
5451 5451 #print(dataOut.ti2[:])
5452 5452 for i in range(dataOut.NLAG):
5453 5453 self.cal[i]=sum(dataOut.output_LP_integrated[i,:,3].real)
5454 5454
5455 5455
5456 5456 self.cal/=float(dataOut.NRANGE)
5457 5457
5458 5458 for j in range(dataOut.NACF+2*dataOut.IBITS+2):
5459 5459
5460 5460 dataOut.output_LP_integrated.real[0,j,0]-=anoise0 #lag0 ch0
5461 5461 dataOut.output_LP_integrated.real[1,j,0]-=anoise1 #lag1 ch0
5462 5462
5463 5463 for i in range(1,dataOut.NLAG): #remove cal data from certain lags
5464 5464 dataOut.output_LP_integrated.real[i,j,0]-=self.cal[i]
5465 5465 k=max(j,26) #constant power below range 26
5466 5466 self.powera[j]=dataOut.output_LP_integrated.real[0,k,0]
5467 5467
5468 5468 ## examine drifts here - based on 60 'indep.' estimates
5469 5469
5470 5470 nis=dataOut.NSCAN*dataOut.NAVG*dataOut.nint*10
5471 5471 alpha=beta=delta=0.0
5472 5472 nest=0
5473 5473 gamma=3.0/(2.0*numpy.pi*dataOut.lags_LP[1]*1.0e-3)
5474 5474 beta=gamma*(math.atan2(dataOut.output_LP_integrated.imag[14,0,2],dataOut.output_LP_integrated.real[14,0,2])-math.atan2(dataOut.output_LP_integrated.imag[1,0,2],dataOut.output_LP_integrated.real[1,0,2]))/13.0
5475 5475 for i in range(1,3):
5476 5476 gamma=3.0/(2.0*numpy.pi*dataOut.lags_LP[i]*1.0e-3)
5477 5477 for j in range(34,44):
5478 5478 rho2=numpy.abs(dataOut.output_LP_integrated[i,j,0])/numpy.abs(dataOut.output_LP_integrated[0,j,0])
5479 5479 dataOut.dphi2=(1.0/rho2-1.0)/(float(2*nis))
5480 5480 dataOut.dphi2*=gamma**2
5481 5481 pest=gamma*math.atan(dataOut.output_LP_integrated.imag[i,j,0]/dataOut.output_LP_integrated.real[i,j,0])
5482 5482
5483 5483 self.drift[nest]=pest
5484 5484 self.ddrift[nest]=dataOut.dphi2
5485 5485 self.rdrift[nest]=float(nest)
5486 5486 nest+=1
5487 5487
5488 5488 sorted(self.drift[:nest])
5489 5489
5490 5490 for j in range(int(nest/4),int(3*nest/4)):
5491 5491 #i=int(self.rdrift[j])
5492 5492 alpha+=self.drift[j]/self.ddrift[j]
5493 5493 delta+=1.0/self.ddrift[j]
5494 5494
5495 5495 alpha/=delta
5496 5496 delta=1./numpy.sqrt(delta)
5497 5497 vdrift=alpha-beta
5498 5498 dvdrift=delta
5499 5499
5500 5500 #need to develop estimate of complete density profile using all
5501 5501 #available data
5502 5502
5503 5503 #estimate sample variances for long-pulse power profile
5504 5504
5505 5505 nis=dataOut.NSCAN*dataOut.NAVG*dataOut.nint
5506 5506
5507 5507 self.sigma[:dataOut.NACF+2*dataOut.IBITS+2]=((anoise0+self.powera[:dataOut.NACF+2*dataOut.IBITS+2])**2)/float(nis)
5508 5508
5509 5509 ioff=1
5510 5510
5511 5511 #deconvolve rectangular pulse shape from profile ==> powerb, perror
5512 5512
5513 5513
5514 5514 ############# START nnlswrap#############
5515 5515
5516 5516 if dataOut.ut_Faraday>14.0:
5517 5517 alpha_nnlswrap=20.0
5518 5518 else:
5519 5519 alpha_nnlswrap=30.0
5520 5520
5521 5521 range1_nnls=dataOut.NACF
5522 5522 range2_nnls=dataOut.NACF+dataOut.IBITS-1
5523 5523
5524 5524 g_nnlswrap=numpy.zeros((range1_nnls,range2_nnls),'float32')
5525 5525 a_nnlswrap=numpy.zeros((range2_nnls,range2_nnls),'float64')
5526 5526
5527 5527 for i in range(range1_nnls):
5528 5528 for j in range(range2_nnls):
5529 5529 if j>=i and j<i+dataOut.IBITS:
5530 5530 g_nnlswrap[i,j]=1.0
5531 5531 else:
5532 5532 g_nnlswrap[i,j]=0.0
5533 5533
5534 5534 a_nnlswrap[:]=numpy.matmul(numpy.transpose(g_nnlswrap),g_nnlswrap)
5535 5535
5536 5536 numpy.fill_diagonal(a_nnlswrap,a_nnlswrap.diagonal()+alpha_nnlswrap**2)
5537 5537
5538 5538 #ERROR ANALYSIS#
5539 5539
5540 5540 self.perror[:range2_nnls]=0.0
5541 5541 self.perror[:range2_nnls]=numpy.matmul(1./(self.sigma[dataOut.IBITS+ioff:range1_nnls+dataOut.IBITS+ioff]),g_nnlswrap**2)
5542 5542 self.perror[:range1_nnls]+=(alpha_nnlswrap**2)/(self.sigma[dataOut.IBITS+ioff:range1_nnls+dataOut.IBITS+ioff])
5543 5543 self.perror[:range2_nnls]=1.00/self.perror[:range2_nnls]
5544 5544
5545 5545 b_nnlswrap=numpy.zeros(range2_nnls,'float64')
5546 5546 b_nnlswrap[:]=numpy.matmul(self.powera[dataOut.IBITS+ioff:range1_nnls+dataOut.IBITS+ioff],g_nnlswrap)
5547 5547
5548 5548 x_nnlswrap=numpy.zeros(range2_nnls,'float64')
5549 5549 x_nnlswrap[:]=nnls(a_nnlswrap,b_nnlswrap)[0]
5550 5550
5551 5551 self.powerb[:range2_nnls]=x_nnlswrap
5552 5552
5553 5553 #############END nnlswrap#############
5554 5554
5555 5555 #estimate relative error for deconvolved profile (scaling irrelevant)
5556 5556
5557 5557 dataOut.ene[0:dataOut.NACF]=numpy.sqrt(self.perror[0:dataOut.NACF])/self.powerb[0:dataOut.NACF]
5558 5558
5559 5559 aux=0
5560 5560
5561 5561 for i in range(dataOut.IBITS,dataOut.NACF):
5562 5562 self.dpulse[i]=self.lpulse[i]=0.0
5563 5563 for j in range(dataOut.IBITS):
5564 5564 k=int(i-j)
5565 5565 if k<36-aux and k>16:
5566 5566 self.dpulse[i]+=dataOut.ph2[k]/dataOut.h2[k]
5567 5567 elif k>=36-aux:
5568 5568 self.lpulse[i]+=self.powerb[k]
5569 5569 self.lagp[i]=self.powera[i]
5570 5570
5571 5571 #find scale factor that best merges profiles
5572 5572
5573 5573 qi=sum(self.dpulse[32:dataOut.NACF]**2/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5574 5574 ri=sum((self.dpulse[32:dataOut.NACF]*self.lpulse[32:dataOut.NACF])/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5575 5575 si=sum((self.dpulse[32:dataOut.NACF]*self.lagp[32:dataOut.NACF])/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5576 5576 ui=sum(self.lpulse[32:dataOut.NACF]**2/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5577 5577 vi=sum((self.lpulse[32:dataOut.NACF]*self.lagp[32:dataOut.NACF])/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5578 5578
5579 5579 alpha=(si*ui-vi*ri)/(qi*ui-ri*ri)
5580 5580 beta=(qi*vi-ri*si)/(qi*ui-ri*ri)
5581 5581
5582 5582 #form density profile estimate, merging rescaled power profiles
5583 5583
5584 5584 self.powerb[16:36-aux]=alpha*dataOut.ph2[16:36-aux]/dataOut.h2[16:36-aux]
5585 5585 self.powerb[36-aux:dataOut.NACF]*=beta
5586 5586
5587 5587 #form Ne estimate, fill in error estimate at low altitudes
5588 5588
5589 5589 dataOut.ene[0:36-aux]=dataOut.sdp2[0:36-aux]/dataOut.ph2[0:36-aux]
5590 5590 dataOut.ne[:dataOut.NACF]=self.powerb[:dataOut.NACF]*dataOut.h2[:dataOut.NACF]/alpha
5591 5591
5592 5592 #now do error propagation: store zero lag error covariance in u
5593 5593
5594 5594 nis=dataOut.NSCAN*dataOut.NAVG*dataOut.nint/1 # DLH serious debris removal
5595 5595
5596 5596 for i in range(dataOut.NACF):
5597 5597 for j in range(i,dataOut.NACF):
5598 5598 if j-i>=dataOut.IBITS:
5599 5599 self.u[i,j]=0.0
5600 5600 else:
5601 5601 self.u[i,j]=dataOut.output_LP_integrated.real[j-i,i,0]**2/float(nis)
5602 5602 self.u[i,j]*=(anoise0+dataOut.output_LP_integrated.real[0,i,0])/dataOut.output_LP_integrated.real[0,i,0]
5603 5603 self.u[i,j]*=(anoise0+dataOut.output_LP_integrated.real[0,j,0])/dataOut.output_LP_integrated.real[0,j,0]
5604 5604
5605 5605 self.u[j,i]=self.u[i,j]
5606 5606
5607 5607 #now error analyis for lag product matrix (diag), place in acf_err
5608 5608
5609 5609 for i in range(dataOut.NACF):
5610 5610 for j in range(dataOut.IBITS):
5611 5611 if j==0:
5612 5612 dataOut.errors[0,i]=numpy.sqrt(self.u[i,i])
5613 5613 else:
5614 5614 dataOut.errors[j,i]=numpy.sqrt(((dataOut.output_LP_integrated.real[0,i,0]+anoise0)*(dataOut.output_LP_integrated.real[0,i+j,0]+anoise0)+dataOut.output_LP_integrated.real[j,i,0]**2)/float(2*nis))
5615 5615
5616 5616 #with suppress_stdout_stderr():
5617 5617 #full_profile_profile.profile(numpy.transpose(dataOut.output_LP_integrated,(2,1,0)),numpy.transpose(dataOut.errors),self.powerb,dataOut.ne,dataOut.lags_LP,dataOut.thb,dataOut.bfm,dataOut.te,dataOut.ete,dataOut.ti,dataOut.eti,dataOut.ph,dataOut.eph,dataOut.phe,dataOut.ephe,dataOut.range1,dataOut.ut,dataOut.NACF,dataOut.fit_array_real,dataOut.status,dataOut.NRANGE,dataOut.IBITS)
5618 5618
5619 5619 if dataOut.status>=3.5:
5620 5620 dataOut.te[:]=numpy.nan
5621 5621 dataOut.ete[:]=numpy.nan
5622 5622 dataOut.ti[:]=numpy.nan
5623 5623 dataOut.eti[:]=numpy.nan
5624 5624 dataOut.ph[:]=numpy.nan
5625 5625 dataOut.eph[:]=numpy.nan
5626 5626 dataOut.phe[:]=numpy.nan
5627 5627 dataOut.ephe[:]=numpy.nan
5628 5628
5629 5629 return dataOut
5630 5630
5631 5631
5632 5632 class LongPulseAnalysisLP(Operation):
5633 5633 """Operation to estimate ACFs, temperatures, total electron density and Hydrogen/Helium fractions from the Long Pulse data.
5634 5634
5635 5635 Parameters:
5636 5636 -----------
5637 5637 NACF : int
5638 5638 .*
5639 5639
5640 5640 Example
5641 5641 --------
5642 5642
5643 5643 op = proc_unit.addOperation(name='LongPulseAnalysis', optype='other')
5644 5644 op.addParameter(name='NACF', value='16', format='int')
5645 5645
5646 5646 """
5647 5647
5648 5648 def __init__(self, **kwargs):
5649 5649
5650 5650 Operation.__init__(self, **kwargs)
5651 5651 self.aux=1
5652 5652
5653 5653 def run(self,dataOut,NACF=None):
5654 5654
5655 5655
5656 5656 dataOut.IBITS = 64
5657 5657 dataOut.NACF = dataOut.nHeights# - (2*dataOut.IBITS+5)
5658 5658 #print(dataOut.heightList[int(dataOut.NACF)])
5659 5659 #exit(1)
5660 5660
5661 5661 #dataOut.heightList=dataOut.DH*(numpy.arange(dataOut.NACF))
5662 5662 anoise0=dataOut.tnoise[0]
5663 5663 anoise1=anoise0*0.0 #seems to be noise in 1st lag 0.015 before '14
5664 5664
5665 5665 if self.aux:
5666 5666 #dataOut.cut=31#26#height=31*15=465
5667 5667 self.cal=numpy.zeros((dataOut.NLAG),'float32')
5668 5668 self.drift=numpy.zeros((200),'float32')
5669 5669 self.rdrift=numpy.zeros((200),'float32')
5670 5670 self.ddrift=numpy.zeros((200),'float32')
5671 5671 self.sigma=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5672 5672 self.powera=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5673 5673 self.powerb=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5674 5674 self.perror=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5675 5675 dataOut.ene=numpy.zeros((dataOut.NRANGE),'float32')
5676 5676 self.dpulse=numpy.zeros((dataOut.NACF),'float32')
5677 5677 self.lpulse=numpy.zeros((dataOut.NACF),'float32')
5678 5678 dataOut.lags_LP=numpy.zeros((dataOut.IBITS),order='F',dtype='float32')
5679 5679 self.lagp=numpy.zeros((dataOut.NACF),'float32')
5680 5680 self.u=numpy.zeros((2*dataOut.NACF,2*dataOut.NACF),'float32')
5681 5681 dataOut.ne=numpy.zeros((dataOut.NRANGE),order='F',dtype='float32')
5682 5682 dataOut.te=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5683 5683 dataOut.ete=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5684 5684 dataOut.ti=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5685 5685 dataOut.eti=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5686 5686 dataOut.ph=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5687 5687 dataOut.eph=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5688 5688 dataOut.phe=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5689 5689 dataOut.ephe=numpy.zeros((dataOut.NACF),order='F',dtype='float32')
5690 5690 dataOut.errors=numpy.zeros((dataOut.IBITS,max(dataOut.NRANGE,1)),order='F',dtype='float32')
5691 5691 dataOut.fit_array_real=numpy.zeros((max(dataOut.NRANGE,1),dataOut.NLAG),order='F',dtype='float32')
5692 5692 dataOut.status=numpy.zeros(1,'float32')
5693 5693 dataOut.tx=480.0 #deberΓ­a provenir del header #HAE
5694 5694
5695 5695 dataOut.h2=numpy.zeros(dataOut.MAXNRANGENDT,'float32')
5696 5696 dataOut.range1=numpy.zeros(dataOut.MAXNRANGENDT,order='F',dtype='float32')
5697 5697
5698 5698
5699 5699
5700 5700 for i in range(dataOut.IBITS):
5701 5701 dataOut.lags_LP[i]=float(i)*(dataOut.tx/150.0)/float(dataOut.IBITS) # (float)i*(header.tx/150.0)/(float)IBITS;
5702 5702
5703 5703 self.aux=0
5704 5704
5705 5705
5706 5706
5707 5707 for i in range(dataOut.MAXNRANGENDT):
5708 5708 dataOut.range1[i]=dataOut.H0 + i*dataOut.DH
5709 5709 dataOut.h2[i]=dataOut.range1[i]**2
5710 5710
5711 5711 dataOut.cut=30
5712 5712 #for i in range(30,15,-1):
5713 5713 # if numpy.nanmax(dataOut.acfs_error_to_plot[i,:])>=10 or dataOut.info2[i]==0:
5714 5714 # dataOut.cut=i-1
5715 5715 #print(dataOut.cut)
5716 5716 #print(dataOut.info2[:])
5717 5717 #print(dataOut.te2[:])
5718 5718 #print(dataOut.ti2[:])
5719 5719 #for i in range(dataOut.NLAG):
5720 5720 # self.cal[i]=sum(dataOut.output_LP_integrated[i,:,3].real)
5721 5721
5722 5722
5723 5723 #self.cal/=float(dataOut.NRANGE)
5724 5724
5725 5725 for j in range(dataOut.NACF):#+2*dataOut.IBITS+2):
5726 5726
5727 5727 self.powera[j]=dataOut.output_LP_integrated.real[0,j,0]
5728 5728
5729 5729
5730 5730 print(dataOut.heightList[:dataOut.NACF])
5731 5731 import matplotlib.pyplot as plt
5732 5732 fig, axes = plt.subplots(figsize=(14, 10))
5733 5733 axes.plot(self.powera[:dataOut.NACF]*dataOut.h2[:dataOut.NACF],dataOut.heightList[:dataOut.NACF])
5734 5734 axes.set_xscale("log", nonposx='clip')
5735 5735 #axes.set_xlim(1e18,2e19)
5736 5736 axes.set_ylim(180,470)
5737 5737 import time
5738 5738
5739 5739 plt.title(time.ctime(dataOut.utctime))
5740 5740 plt.show()
5741 5741 time.sleep(50)
5742 5742 exit(1)
5743 5743 '''
5744 5744 for j in range(dataOut.NACF+2*dataOut.IBITS+2):
5745 5745
5746 5746 dataOut.output_LP_integrated.real[0,j,0]-=anoise0 #lag0 ch0
5747 5747 dataOut.output_LP_integrated.real[1,j,0]-=anoise1 #lag1 ch0
5748 5748
5749 5749 #for i in range(1,dataOut.NLAG): #remove cal data from certain lags
5750 5750 # dataOut.output_LP_integrated.real[i,j,0]-=self.cal[i]
5751 5751 k=max(j,26) #constant power below range 26
5752 5752 self.powera[j]=dataOut.output_LP_integrated.real[0,k,0]
5753 5753
5754 5754 ## examine drifts here - based on 60 'indep.' estimates
5755 5755
5756 5756 nis=dataOut.NSCAN*dataOut.NAVG*dataOut.nint*10
5757 5757 alpha=beta=delta=0.0
5758 5758 nest=0
5759 5759 gamma=3.0/(2.0*numpy.pi*dataOut.lags_LP[1]*1.0e-3)
5760 5760 beta=gamma*(math.atan2(dataOut.output_LP_integrated.imag[14,0,2],dataOut.output_LP_integrated.real[14,0,2])-math.atan2(dataOut.output_LP_integrated.imag[1,0,2],dataOut.output_LP_integrated.real[1,0,2]))/13.0
5761 5761 for i in range(1,3):
5762 5762 gamma=3.0/(2.0*numpy.pi*dataOut.lags_LP[i]*1.0e-3)
5763 5763 for j in range(34,44):
5764 5764 rho2=numpy.abs(dataOut.output_LP_integrated[i,j,0])/numpy.abs(dataOut.output_LP_integrated[0,j,0])
5765 5765 dataOut.dphi2=(1.0/rho2-1.0)/(float(2*nis))
5766 5766 dataOut.dphi2*=gamma**2
5767 5767 pest=gamma*math.atan(dataOut.output_LP_integrated.imag[i,j,0]/dataOut.output_LP_integrated.real[i,j,0])
5768 5768
5769 5769 self.drift[nest]=pest
5770 5770 self.ddrift[nest]=dataOut.dphi2
5771 5771 self.rdrift[nest]=float(nest)
5772 5772 nest+=1
5773 5773
5774 5774 sorted(self.drift[:nest])
5775 5775
5776 5776 for j in range(int(nest/4),int(3*nest/4)):
5777 5777 #i=int(self.rdrift[j])
5778 5778 alpha+=self.drift[j]/self.ddrift[j]
5779 5779 delta+=1.0/self.ddrift[j]
5780 5780
5781 5781 alpha/=delta
5782 5782 delta=1./numpy.sqrt(delta)
5783 5783 vdrift=alpha-beta
5784 5784 dvdrift=delta
5785 5785
5786 5786 #need to develop estimate of complete density profile using all
5787 5787 #available data
5788 5788
5789 5789 #estimate sample variances for long-pulse power profile
5790 5790
5791 5791 nis=dataOut.NSCAN*dataOut.NAVG*dataOut.nint
5792 5792
5793 5793 self.sigma[:dataOut.NACF+2*dataOut.IBITS+2]=((anoise0+self.powera[:dataOut.NACF+2*dataOut.IBITS+2])**2)/float(nis)
5794 5794 '''
5795 5795 ioff=1
5796 5796
5797 5797 #deconvolve rectangular pulse shape from profile ==> powerb, perror
5798 5798
5799 5799
5800 5800 ############# START nnlswrap#############
5801 5801
5802 5802 if dataOut.ut_Faraday>14.0:
5803 5803 alpha_nnlswrap=20.0
5804 5804 else:
5805 5805 alpha_nnlswrap=30.0
5806 5806
5807 5807 range1_nnls=dataOut.NACF
5808 5808 range2_nnls=dataOut.NACF+dataOut.IBITS-1
5809 5809
5810 5810 g_nnlswrap=numpy.zeros((range1_nnls,range2_nnls),'float32')
5811 5811 a_nnlswrap=numpy.zeros((range2_nnls,range2_nnls),'float64')
5812 5812
5813 5813 for i in range(range1_nnls):
5814 5814 for j in range(range2_nnls):
5815 5815 if j>=i and j<i+dataOut.IBITS:
5816 5816 g_nnlswrap[i,j]=1.0
5817 5817 else:
5818 5818 g_nnlswrap[i,j]=0.0
5819 5819
5820 5820 a_nnlswrap[:]=numpy.matmul(numpy.transpose(g_nnlswrap),g_nnlswrap)
5821 5821
5822 5822 numpy.fill_diagonal(a_nnlswrap,a_nnlswrap.diagonal()+alpha_nnlswrap**2)
5823 5823
5824 5824 #ERROR ANALYSIS#
5825 5825 '''
5826 5826 self.perror[:range2_nnls]=0.0
5827 5827 self.perror[:range2_nnls]=numpy.matmul(1./(self.sigma[dataOut.IBITS+ioff:range1_nnls+dataOut.IBITS+ioff]),g_nnlswrap**2)
5828 5828 self.perror[:range1_nnls]+=(alpha_nnlswrap**2)/(self.sigma[dataOut.IBITS+ioff:range1_nnls+dataOut.IBITS+ioff])
5829 5829 self.perror[:range2_nnls]=1.00/self.perror[:range2_nnls]
5830 5830 '''
5831 5831 b_nnlswrap=numpy.zeros(range2_nnls,'float64')
5832 5832 b_nnlswrap[:]=numpy.matmul(self.powera[dataOut.IBITS+ioff:range1_nnls+dataOut.IBITS+ioff],g_nnlswrap)
5833 5833
5834 5834 x_nnlswrap=numpy.zeros(range2_nnls,'float64')
5835 5835 x_nnlswrap[:]=nnls(a_nnlswrap,b_nnlswrap)[0]
5836 5836
5837 5837 self.powerb[:range2_nnls]=x_nnlswrap
5838 5838
5839 5839
5840 5840 import matplotlib.pyplot as plt
5841 5841 fig, axes = plt.subplots(figsize=(14, 10))
5842 5842 axes.plot(self.powerb[:dataOut.NACF]*dataOut.h2[:dataOut.NACF],dataOut.heightList[:dataOut.NACF])
5843 5843 axes.set_xscale("log", nonposx='clip')
5844 5844 #axes.set_xlim(1e10,8e12)
5845 5845 axes.set_ylim(0,300)
5846 5846 plt.show()
5847 5847 import time
5848 5848 time.sleep(60)
5849 5849 exit(1)
5850 5850
5851 5851
5852 5852 #############END nnlswrap#############
5853 5853
5854 5854 #estimate relative error for deconvolved profile (scaling irrelevant)
5855 5855
5856 5856 dataOut.ene[0:dataOut.NACF]=numpy.sqrt(self.perror[0:dataOut.NACF])/self.powerb[0:dataOut.NACF]
5857 5857
5858 5858 aux=0
5859 5859
5860 5860 for i in range(dataOut.IBITS,dataOut.NACF):
5861 5861 self.dpulse[i]=self.lpulse[i]=0.0
5862 5862 for j in range(dataOut.IBITS):
5863 5863 k=int(i-j)
5864 5864 if k<36-aux and k>16:
5865 5865 self.dpulse[i]+=dataOut.ph2[k]/dataOut.h2[k]
5866 5866 elif k>=36-aux:
5867 5867 self.lpulse[i]+=self.powerb[k]
5868 5868 self.lagp[i]=self.powera[i]
5869 5869
5870 5870 #find scale factor that best merges profiles
5871 5871
5872 5872 qi=sum(self.dpulse[32:dataOut.NACF]**2/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5873 5873 ri=sum((self.dpulse[32:dataOut.NACF]*self.lpulse[32:dataOut.NACF])/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5874 5874 si=sum((self.dpulse[32:dataOut.NACF]*self.lagp[32:dataOut.NACF])/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5875 5875 ui=sum(self.lpulse[32:dataOut.NACF]**2/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5876 5876 vi=sum((self.lpulse[32:dataOut.NACF]*self.lagp[32:dataOut.NACF])/(self.lagp[32:dataOut.NACF]+anoise0)**2)
5877 5877
5878 5878 alpha=(si*ui-vi*ri)/(qi*ui-ri*ri)
5879 5879 beta=(qi*vi-ri*si)/(qi*ui-ri*ri)
5880 5880
5881 5881 #form density profile estimate, merging rescaled power profiles
5882 5882
5883 5883 self.powerb[16:36-aux]=alpha*dataOut.ph2[16:36-aux]/dataOut.h2[16:36-aux]
5884 5884 self.powerb[36-aux:dataOut.NACF]*=beta
5885 5885
5886 5886 #form Ne estimate, fill in error estimate at low altitudes
5887 5887
5888 5888 dataOut.ene[0:36-aux]=dataOut.sdp2[0:36-aux]/dataOut.ph2[0:36-aux]
5889 5889 dataOut.ne[:dataOut.NACF]=self.powerb[:dataOut.NACF]*dataOut.h2[:dataOut.NACF]/alpha
5890 5890
5891 5891 #now do error propagation: store zero lag error covariance in u
5892 5892
5893 5893 nis=dataOut.NSCAN*dataOut.NAVG*dataOut.nint/1 # DLH serious debris removal
5894 5894
5895 5895 for i in range(dataOut.NACF):
5896 5896 for j in range(i,dataOut.NACF):
5897 5897 if j-i>=dataOut.IBITS:
5898 5898 self.u[i,j]=0.0
5899 5899 else:
5900 5900 self.u[i,j]=dataOut.output_LP_integrated.real[j-i,i,0]**2/float(nis)
5901 5901 self.u[i,j]*=(anoise0+dataOut.output_LP_integrated.real[0,i,0])/dataOut.output_LP_integrated.real[0,i,0]
5902 5902 self.u[i,j]*=(anoise0+dataOut.output_LP_integrated.real[0,j,0])/dataOut.output_LP_integrated.real[0,j,0]
5903 5903
5904 5904 self.u[j,i]=self.u[i,j]
5905 5905
5906 5906 #now error analyis for lag product matrix (diag), place in acf_err
5907 5907
5908 5908 for i in range(dataOut.NACF):
5909 5909 for j in range(dataOut.IBITS):
5910 5910 if j==0:
5911 5911 dataOut.errors[0,i]=numpy.sqrt(self.u[i,i])
5912 5912 else:
5913 5913 dataOut.errors[j,i]=numpy.sqrt(((dataOut.output_LP_integrated.real[0,i,0]+anoise0)*(dataOut.output_LP_integrated.real[0,i+j,0]+anoise0)+dataOut.output_LP_integrated.real[j,i,0]**2)/float(2*nis))
5914 5914
5915 5915 #with suppress_stdout_stderr():
5916 5916 #full_profile_profile.profile(numpy.transpose(dataOut.output_LP_integrated,(2,1,0)),numpy.transpose(dataOut.errors),self.powerb,dataOut.ne,dataOut.lags_LP,dataOut.thb,dataOut.bfm,dataOut.te,dataOut.ete,dataOut.ti,dataOut.eti,dataOut.ph,dataOut.eph,dataOut.phe,dataOut.ephe,dataOut.range1,dataOut.ut,dataOut.NACF,dataOut.fit_array_real,dataOut.status,dataOut.NRANGE,dataOut.IBITS)
5917 5917 '''
5918 5918 if dataOut.status>=3.5:
5919 5919 dataOut.te[:]=numpy.nan
5920 5920 dataOut.ete[:]=numpy.nan
5921 5921 dataOut.ti[:]=numpy.nan
5922 5922 dataOut.eti[:]=numpy.nan
5923 5923 dataOut.ph[:]=numpy.nan
5924 5924 dataOut.eph[:]=numpy.nan
5925 5925 dataOut.phe[:]=numpy.nan
5926 5926 dataOut.ephe[:]=numpy.nan
5927 5927 '''
5928 5928 return dataOut
5929 5929
5930 5930
5931 5931 class PulsePairVoltage(Operation):
5932 5932 '''
5933 5933 Function PulsePair(Signal Power, Velocity)
5934 5934 The real component of Lag[0] provides Intensity Information
5935 5935 The imag component of Lag[1] Phase provides Velocity Information
5936 5936
5937 5937 Configuration Parameters:
5938 5938 nPRF = Number of Several PRF
5939 5939 theta = Degree Azimuth angel Boundaries
5940 5940
5941 5941 Input:
5942 5942 self.dataOut
5943 5943 lag[N]
5944 5944 Affected:
5945 5945 self.dataOut.spc
5946 5946 '''
5947 5947 isConfig = False
5948 5948 __profIndex = 0
5949 5949 __initime = None
5950 5950 __lastdatatime = None
5951 5951 __buffer = None
5952 5952 noise = None
5953 5953 __dataReady = False
5954 5954 n = None
5955 5955 __nch = 0
5956 5956 __nHeis = 0
5957 5957 removeDC = False
5958 5958 ipp = None
5959 5959 lambda_ = 0
5960 5960
5961 5961 def __init__(self, **kwargs):
5962 5962 Operation.__init__(self, **kwargs)
5963 5963
5964 5964 def setup(self, dataOut, n=None, removeDC=False):
5965 5965 '''
5966 5966 n= Numero de PRF's de entrada
5967 5967 '''
5968 5968 self.__initime = None
5969 5969 self.__lastdatatime = 0
5970 5970 self.__dataReady = False
5971 5971 self.__buffer = 0
5972 5972 self.__profIndex = 0
5973 5973 self.noise = None
5974 5974 self.__nch = dataOut.nChannels
5975 5975 self.__nHeis = dataOut.nHeights
5976 5976 self.removeDC = removeDC
5977 5977 self.lambda_ = 3.0e8 / (9345.0e6)
5978 5978 self.ippSec = dataOut.ippSeconds
5979 5979 self.nCohInt = dataOut.nCohInt
5980 5980 print("IPPseconds", dataOut.ippSeconds)
5981 5981
5982 5982 print("ELVALOR DE n es:", n)
5983 5983 if n == None:
5984 5984 raise ValueError("n should be specified.")
5985 5985
5986 5986 if n != None:
5987 5987 if n < 2:
5988 5988 raise ValueError("n should be greater than 2")
5989 5989
5990 5990 self.n = n
5991 5991 self.__nProf = n
5992 5992
5993 5993 self.__buffer = numpy.zeros((dataOut.nChannels,
5994 5994 n,
5995 5995 dataOut.nHeights),
5996 5996 dtype='complex')
5997 5997
5998 5998 def putData(self, data):
5999 5999 '''
6000 6000 Add a profile to he __buffer and increase in one the __profiel Index
6001 6001 '''
6002 6002 self.__buffer[:, self.__profIndex, :] = data
6003 6003 self.__profIndex += 1
6004 6004 return
6005 6005
6006 6006 def pushData(self, dataOut):
6007 6007 '''
6008 6008 Return the PULSEPAIR and the profiles used in the operation
6009 6009 Affected : self.__profileIndex
6010 6010 '''
6011 6011 #----------------- Remove DC-----------------------------------
6012 6012 if self.removeDC == True:
6013 6013 mean = numpy.mean(self.__buffer, 1)
6014 6014 tmp = mean.reshape(self.__nch, 1, self.__nHeis)
6015 6015 dc = numpy.tile(tmp, [1, self.__nProf, 1])
6016 6016 self.__buffer = self.__buffer - dc
6017 6017 #------------------Calculo de Potencia ------------------------
6018 6018 pair0 = self.__buffer * numpy.conj(self.__buffer)
6019 6019 pair0 = pair0.real
6020 6020 lag_0 = numpy.sum(pair0, 1)
6021 6021 #------------------Calculo de Ruido x canal--------------------
6022 6022 self.noise = numpy.zeros(self.__nch)
6023 6023 for i in range(self.__nch):
6024 6024 daux = numpy.sort(pair0[i, :, :], axis=None)
6025 6025 self.noise[i] = hildebrand_sekhon(daux , self.nCohInt)
6026 6026
6027 6027 self.noise = self.noise.reshape(self.__nch, 1)
6028 6028 self.noise = numpy.tile(self.noise, [1, self.__nHeis])
6029 6029 noise_buffer = self.noise.reshape(self.__nch, 1, self.__nHeis)
6030 6030 noise_buffer = numpy.tile(noise_buffer, [1, self.__nProf, 1])
6031 6031 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
6032 6032 #------------------ P= S+N ,P=lag_0/N ---------------------------------
6033 6033 #-------------------- Power --------------------------------------------------
6034 6034 data_power = lag_0 / (self.n * self.nCohInt)
6035 6035 #------------------ Senal ---------------------------------------------------
6036 6036 data_intensity = pair0 - noise_buffer
6037 6037 data_intensity = numpy.sum(data_intensity, axis=1) * (self.n * self.nCohInt) # *self.nCohInt)
6038 6038 # data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
6039 6039 for i in range(self.__nch):
6040 6040 for j in range(self.__nHeis):
6041 6041 if data_intensity[i][j] < 0:
6042 6042 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
6043 6043
6044 6044 #----------------- Calculo de Frecuencia y Velocidad doppler--------
6045 6045 pair1 = self.__buffer[:, :-1, :] * numpy.conjugate(self.__buffer[:, 1:, :])
6046 6046 lag_1 = numpy.sum(pair1, 1)
6047 6047 data_freq = (-1 / (2.0 * math.pi * self.ippSec * self.nCohInt)) * numpy.angle(lag_1)
6048 6048 data_velocity = (self.lambda_ / 2.0) * data_freq
6049 6049
6050 6050 #---------------- Potencia promedio estimada de la Senal-----------
6051 6051 lag_0 = lag_0 / self.n
6052 6052 S = lag_0 - self.noise
6053 6053
6054 6054 #---------------- Frecuencia Doppler promedio ---------------------
6055 6055 lag_1 = lag_1 / (self.n - 1)
6056 6056 R1 = numpy.abs(lag_1)
6057 6057
6058 6058 #---------------- Calculo del SNR----------------------------------
6059 6059 data_snrPP = S / self.noise
6060 6060 for i in range(self.__nch):
6061 6061 for j in range(self.__nHeis):
6062 6062 if data_snrPP[i][j] < 1.e-20:
6063 6063 data_snrPP[i][j] = 1.e-20
6064 6064
6065 6065 #----------------- Calculo del ancho espectral ----------------------
6066 6066 L = S / R1
6067 6067 L = numpy.where(L < 0, 1, L)
6068 6068 L = numpy.log(L)
6069 6069 tmp = numpy.sqrt(numpy.absolute(L))
6070 6070 data_specwidth = (self.lambda_ / (2 * math.sqrt(2) * math.pi * self.ippSec * self.nCohInt)) * tmp * numpy.sign(L)
6071 6071 n = self.__profIndex
6072 6072
6073 6073 self.__buffer = numpy.zeros((self.__nch, self.__nProf, self.__nHeis), dtype='complex')
6074 6074 self.__profIndex = 0
6075 6075 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, n
6076 6076
6077 6077
6078 6078 def pulsePairbyProfiles(self, dataOut):
6079 6079
6080 6080 self.__dataReady = False
6081 6081 data_power = None
6082 6082 data_intensity = None
6083 6083 data_velocity = None
6084 6084 data_specwidth = None
6085 6085 data_snrPP = None
6086 6086 self.putData(data=dataOut.data)
6087 6087 if self.__profIndex == self.n:
6088 6088 data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, n = self.pushData(dataOut=dataOut)
6089 6089 self.__dataReady = True
6090 6090
6091 6091 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth
6092 6092
6093 6093
6094 6094 def pulsePairOp(self, dataOut, datatime=None):
6095 6095
6096 6096 if self.__initime == None:
6097 6097 self.__initime = datatime
6098 6098 data_power, data_intensity, data_velocity, data_snrPP, data_specwidth = self.pulsePairbyProfiles(dataOut)
6099 6099 self.__lastdatatime = datatime
6100 6100
6101 6101 if data_power is None:
6102 6102 return None, None, None, None, None, None
6103 6103
6104 6104 avgdatatime = self.__initime
6105 6105 deltatime = datatime - self.__lastdatatime
6106 6106 self.__initime = datatime
6107 6107
6108 6108 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, avgdatatime
6109 6109
6110 6110 def run(self, dataOut, n=None, removeDC=False, overlapping=False, **kwargs):
6111 6111
6112 6112 if not self.isConfig:
6113 6113 self.setup(dataOut=dataOut, n=n , removeDC=removeDC , **kwargs)
6114 6114 self.isConfig = True
6115 6115 data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, avgdatatime = self.pulsePairOp(dataOut, dataOut.utctime)
6116 6116 dataOut.flagNoData = True
6117 6117
6118 6118 if self.__dataReady:
6119 6119 dataOut.nCohInt *= self.n
6120 6120 dataOut.dataPP_POW = data_intensity # S
6121 6121 dataOut.dataPP_POWER = data_power # P
6122 6122 dataOut.dataPP_DOP = data_velocity
6123 6123 dataOut.dataPP_SNR = data_snrPP
6124 6124 dataOut.dataPP_WIDTH = data_specwidth
6125 6125 dataOut.PRFbyAngle = self.n # numero de PRF*cada angulo rotado que equivale a un tiempo.
6126 6126 dataOut.utctime = avgdatatime
6127 6127 dataOut.flagNoData = False
6128 6128 return dataOut
6129 6129
6130 6130
6131 6131
6132 6132 # import collections
6133 6133 # from scipy.stats import mode
6134 6134 #
6135 6135 # class Synchronize(Operation):
6136 6136 #
6137 6137 # isConfig = False
6138 6138 # __profIndex = 0
6139 6139 #
6140 6140 # def __init__(self, **kwargs):
6141 6141 #
6142 6142 # Operation.__init__(self, **kwargs)
6143 6143 # # self.isConfig = False
6144 6144 # self.__powBuffer = None
6145 6145 # self.__startIndex = 0
6146 6146 # self.__pulseFound = False
6147 6147 #
6148 6148 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
6149 6149 #
6150 6150 # #Read data
6151 6151 #
6152 6152 # powerdB = dataOut.getPower(channel = channel)
6153 6153 # noisedB = dataOut.getNoise(channel = channel)[0]
6154 6154 #
6155 6155 # self.__powBuffer.extend(powerdB.flatten())
6156 6156 #
6157 6157 # dataArray = numpy.array(self.__powBuffer)
6158 6158 #
6159 6159 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
6160 6160 #
6161 6161 # maxValue = numpy.nanmax(filteredPower)
6162 6162 #
6163 6163 # if maxValue < noisedB + 10:
6164 6164 # #No se encuentra ningun pulso de transmision
6165 6165 # return None
6166 6166 #
6167 6167 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
6168 6168 #
6169 6169 # if len(maxValuesIndex) < 2:
6170 6170 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
6171 6171 # return None
6172 6172 #
6173 6173 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
6174 6174 #
6175 6175 # #Seleccionar solo valores con un espaciamiento de nSamples
6176 6176 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
6177 6177 #
6178 6178 # if len(pulseIndex) < 2:
6179 6179 # #Solo se encontro un pulso de transmision con ancho mayor a 1
6180 6180 # return None
6181 6181 #
6182 6182 # spacing = pulseIndex[1:] - pulseIndex[:-1]
6183 6183 #
6184 6184 # #remover senales que se distancien menos de 10 unidades o muestras
6185 6185 # #(No deberian existir IPP menor a 10 unidades)
6186 6186 #
6187 6187 # realIndex = numpy.where(spacing > 10 )[0]
6188 6188 #
6189 6189 # if len(realIndex) < 2:
6190 6190 # #Solo se encontro un pulso de transmision con ancho mayor a 1
6191 6191 # return None
6192 6192 #
6193 6193 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
6194 6194 # realPulseIndex = pulseIndex[realIndex]
6195 6195 #
6196 6196 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
6197 6197 #
6198 6198 # print "IPP = %d samples" %period
6199 6199 #
6200 6200 # self.__newNSamples = dataOut.nHeights #int(period)
6201 6201 # self.__startIndex = int(realPulseIndex[0])
6202 6202 #
6203 6203 # return 1
6204 6204 #
6205 6205 #
6206 6206 # def setup(self, nSamples, nChannels, buffer_size = 4):
6207 6207 #
6208 6208 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
6209 6209 # maxlen = buffer_size*nSamples)
6210 6210 #
6211 6211 # bufferList = []
6212 6212 #
6213 6213 # for i in range(nChannels):
6214 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
6214 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=complex) + numpy.NAN,
6215 6215 # maxlen = buffer_size*nSamples)
6216 6216 #
6217 6217 # bufferList.append(bufferByChannel)
6218 6218 #
6219 6219 # self.__nSamples = nSamples
6220 6220 # self.__nChannels = nChannels
6221 6221 # self.__bufferList = bufferList
6222 6222 #
6223 6223 # def run(self, dataOut, channel = 0):
6224 6224 #
6225 6225 # if not self.isConfig:
6226 6226 # nSamples = dataOut.nHeights
6227 6227 # nChannels = dataOut.nChannels
6228 6228 # self.setup(nSamples, nChannels)
6229 6229 # self.isConfig = True
6230 6230 #
6231 6231 # #Append new data to internal buffer
6232 6232 # for thisChannel in range(self.__nChannels):
6233 6233 # bufferByChannel = self.__bufferList[thisChannel]
6234 6234 # bufferByChannel.extend(dataOut.data[thisChannel])
6235 6235 #
6236 6236 # if self.__pulseFound:
6237 6237 # self.__startIndex -= self.__nSamples
6238 6238 #
6239 6239 # #Finding Tx Pulse
6240 6240 # if not self.__pulseFound:
6241 6241 # indexFound = self.__findTxPulse(dataOut, channel)
6242 6242 #
6243 6243 # if indexFound == None:
6244 6244 # dataOut.flagNoData = True
6245 6245 # return
6246 6246 #
6247 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
6247 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = complex)
6248 6248 # self.__pulseFound = True
6249 6249 # self.__startIndex = indexFound
6250 6250 #
6251 6251 # #If pulse was found ...
6252 6252 # for thisChannel in range(self.__nChannels):
6253 6253 # bufferByChannel = self.__bufferList[thisChannel]
6254 6254 # #print self.__startIndex
6255 6255 # x = numpy.array(bufferByChannel)
6256 6256 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
6257 6257 #
6258 6258 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
6259 6259 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
6260 6260 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
6261 6261 #
6262 6262 # dataOut.data = self.__arrayBuffer
6263 6263 #
6264 6264 # self.__startIndex += self.__newNSamples
6265 6265 #
6266 6266 # return
General Comments 0
You need to be logged in to leave comments. Login now