##// END OF EJS Templates
update testing EWDrifts_19Jun2023
Alexander Valdez -
r1677:dbcdef2bc4fb
parent child
Show More
@@ -1,937 +1,939
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 import numpy
14 14 # repositorio
15 15 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
16 16 from schainpy.model.data.jrodata import Spectra
17 17 from schainpy.model.data.jrodata import hildebrand_sekhon
18 18 from schainpy.utils import log
19 19
20 20
21 21 class SpectraProc(ProcessingUnit):
22 22
23 23 def __init__(self):
24 24
25 25 ProcessingUnit.__init__(self)
26 26
27 27 self.buffer = None
28 28 self.firstdatatime = None
29 29 self.profIndex = 0
30 30 self.dataOut = Spectra()
31 31 self.id_min = None
32 32 self.id_max = None
33 33 self.setupReq = False #Agregar a todas las unidades de proc
34 34
35 35 def __updateSpecFromVoltage(self):
36 36
37 37 self.dataOut.timeZone = self.dataIn.timeZone
38 38 self.dataOut.dstFlag = self.dataIn.dstFlag
39 39 self.dataOut.errorCount = self.dataIn.errorCount
40 40 self.dataOut.useLocalTime = self.dataIn.useLocalTime
41 41 try:
42 42 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
43 43 except:
44 44 pass
45 45 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
46 46 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
47 47 self.dataOut.channelList = self.dataIn.channelList
48 48 self.dataOut.heightList = self.dataIn.heightList
49 49 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
50 50 self.dataOut.nProfiles = self.dataOut.nFFTPoints
51 51 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
52 52 self.dataOut.utctime = self.firstdatatime
53 53 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
54 54 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
55 55 self.dataOut.flagShiftFFT = False
56 56 self.dataOut.nCohInt = self.dataIn.nCohInt
57 57 self.dataOut.nIncohInt = 1
58 58 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
59 59 self.dataOut.frequency = self.dataIn.frequency
60 60 self.dataOut.realtime = self.dataIn.realtime
61 61 self.dataOut.azimuth = self.dataIn.azimuth
62 62 self.dataOut.zenith = self.dataIn.zenith
63 63 self.dataOut.beam.codeList = self.dataIn.beam.codeList
64 64 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
65 65 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
66 66 self.dataOut.runNextUnit = self.dataIn.runNextUnit
67 67 try:
68 68 self.dataOut.step = self.dataIn.step
69 69 except:
70 70 pass
71 71
72 72 def __getFft(self):
73 73 """
74 74 Convierte valores de Voltaje a Spectra
75 75
76 76 Affected:
77 77 self.dataOut.data_spc
78 78 self.dataOut.data_cspc
79 79 self.dataOut.data_dc
80 80 self.dataOut.heightList
81 81 self.profIndex
82 82 self.buffer
83 83 self.dataOut.flagNoData
84 84 """
85 85 fft_volt = numpy.fft.fft(
86 86 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
87 87 fft_volt = fft_volt.astype(numpy.dtype('complex'))
88 88 dc = fft_volt[:, 0, :]
89 89
90 90 # calculo de self-spectra
91 91 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
92 92 spc = fft_volt * numpy.conjugate(fft_volt)
93 93 spc = spc.real
94 94
95 95 blocksize = 0
96 96 blocksize += dc.size
97 97 blocksize += spc.size
98 98
99 99 cspc = None
100 100 pairIndex = 0
101 101 if self.dataOut.pairsList != None:
102 102 # calculo de cross-spectra
103 103 cspc = numpy.zeros(
104 104 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
105 105 for pair in self.dataOut.pairsList:
106 106 if pair[0] not in self.dataOut.channelList:
107 107 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
108 108 str(pair), str(self.dataOut.channelList)))
109 109 if pair[1] not in self.dataOut.channelList:
110 110 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
111 111 str(pair), str(self.dataOut.channelList)))
112 112
113 113 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
114 114 numpy.conjugate(fft_volt[pair[1], :, :])
115 115 pairIndex += 1
116 116 blocksize += cspc.size
117 117
118 118 self.dataOut.data_spc = spc
119 119 self.dataOut.data_cspc = cspc
120 120 self.dataOut.data_dc = dc
121 121 self.dataOut.blockSize = blocksize
122 122 self.dataOut.flagShiftFFT = False
123 123
124 124 def run(self, nProfiles=None, nFFTPoints=None, pairsList=None, ippFactor=None, shift_fft=False, runNextUnit = 0):
125 125
126 126 self.dataIn.runNextUnit = runNextUnit
127 127 if self.dataIn.type == "Spectra":
128 128 self.dataOut.copy(self.dataIn)
129 129 if shift_fft:
130 130 #desplaza a la derecha en el eje 2 determinadas posiciones
131 131 shift = int(self.dataOut.nFFTPoints/2)
132 132 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
133 133
134 134 if self.dataOut.data_cspc is not None:
135 135 #desplaza a la derecha en el eje 2 determinadas posiciones
136 136 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
137 137 if pairsList:
138 138 self.__selectPairs(pairsList)
139 139
140 140 elif self.dataIn.type == "Voltage":
141 141
142 142 self.dataOut.flagNoData = True
143 143
144 144 if nFFTPoints == None:
145 145 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
146 146
147 147 if nProfiles == None:
148 148 nProfiles = nFFTPoints
149 149
150 150 if ippFactor == None:
151 151 self.dataOut.ippFactor = 1
152 152
153 153 self.dataOut.nFFTPoints = nFFTPoints
154 154
155 155 if self.buffer is None:
156 156 self.buffer = numpy.zeros((self.dataIn.nChannels,
157 157 nProfiles,
158 158 self.dataIn.nHeights),
159 159 dtype='complex')
160 print("W",self.buffer.shape)
160 161
161 162 if self.dataIn.flagDataAsBlock:
162 163 nVoltProfiles = self.dataIn.data.shape[1]
163 164 if nVoltProfiles == nProfiles:
164 165 self.buffer = self.dataIn.data.copy()
165 166 self.profIndex = nVoltProfiles
166 167
167 168 elif nVoltProfiles < nProfiles:
168 169
169 170 if self.profIndex == 0:
170 171 self.id_min = 0
171 172 self.id_max = nVoltProfiles
172 173
173 174 self.buffer[:, self.id_min:self.id_max,
174 175 :] = self.dataIn.data
175 176 self.profIndex += nVoltProfiles
176 177 self.id_min += nVoltProfiles
177 178 self.id_max += nVoltProfiles
178 179 elif nVoltProfiles > nProfiles:
179 180 self.reader.bypass = True
180 181 if self.profIndex == 0:
181 182 self.id_min = 0
182 183 self.id_max = nProfiles
183 184
184 185 self.buffer = self.dataIn.data[:, self.id_min:self.id_max,:]
185 186 self.profIndex += nProfiles
186 187 self.id_min += nProfiles
187 188 self.id_max += nProfiles
188 189 if self.id_max == nVoltProfiles:
189 190 self.reader.bypass = False
190 191
191 192 else:
192 193 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
193 194 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
194 195 self.dataOut.flagNoData = True
195 196 else:
197 print(self.profIndex,self.dataIn.data.copy().shape)
196 198 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
197 199 self.profIndex += 1
198 200
199 201 if self.firstdatatime == None:
200 202 self.firstdatatime = self.dataIn.utctime
201 203
202 204 if self.profIndex == nProfiles:
203 205 self.__updateSpecFromVoltage()
204 206 if pairsList == None:
205 207 self.dataOut.pairsList = [pair for pair in itertools.combinations(self.dataOut.channelList, 2)]
206 208 else:
207 209 self.dataOut.pairsList = pairsList
208 210 self.__getFft()
209 211 self.dataOut.flagNoData = False
210 212 self.firstdatatime = None
211 if not self.reader.bypass:
212 self.profIndex = 0
213 #if not self.reader.bypass:
214 self.profIndex = 0
213 215 else:
214 216 raise ValueError("The type of input object '%s' is not valid".format(
215 217 self.dataIn.type))
216 218
217 219 def __selectPairs(self, pairsList):
218 220
219 221 if not pairsList:
220 222 return
221 223
222 224 pairs = []
223 225 pairsIndex = []
224 226
225 227 for pair in pairsList:
226 228 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
227 229 continue
228 230 pairs.append(pair)
229 231 pairsIndex.append(pairs.index(pair))
230 232
231 233 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
232 234 self.dataOut.pairsList = pairs
233 235
234 236 return
235 237
236 238 def selectFFTs(self, minFFT, maxFFT ):
237 239 """
238 240 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
239 241 minFFT<= FFT <= maxFFT
240 242 """
241 243
242 244 if (minFFT > maxFFT):
243 245 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
244 246
245 247 if (minFFT < self.dataOut.getFreqRange()[0]):
246 248 minFFT = self.dataOut.getFreqRange()[0]
247 249
248 250 if (maxFFT > self.dataOut.getFreqRange()[-1]):
249 251 maxFFT = self.dataOut.getFreqRange()[-1]
250 252
251 253 minIndex = 0
252 254 maxIndex = 0
253 255 FFTs = self.dataOut.getFreqRange()
254 256
255 257 inda = numpy.where(FFTs >= minFFT)
256 258 indb = numpy.where(FFTs <= maxFFT)
257 259
258 260 try:
259 261 minIndex = inda[0][0]
260 262 except:
261 263 minIndex = 0
262 264
263 265 try:
264 266 maxIndex = indb[0][-1]
265 267 except:
266 268 maxIndex = len(FFTs)
267 269
268 270 self.selectFFTsByIndex(minIndex, maxIndex)
269 271
270 272 return 1
271 273
272 274 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
273 275 newheis = numpy.where(
274 276 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
275 277
276 278 if hei_ref != None:
277 279 newheis = numpy.where(self.dataOut.heightList > hei_ref)
278 280
279 281 minIndex = min(newheis[0])
280 282 maxIndex = max(newheis[0])
281 283 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
282 284 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
283 285
284 286 # determina indices
285 287 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
286 288 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
287 289 avg_dB = 10 * \
288 290 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
289 291 beacon_dB = numpy.sort(avg_dB)[-nheis:]
290 292 beacon_heiIndexList = []
291 293 for val in avg_dB.tolist():
292 294 if val >= beacon_dB[0]:
293 295 beacon_heiIndexList.append(avg_dB.tolist().index(val))
294 296
295 297 data_cspc = None
296 298 if self.dataOut.data_cspc is not None:
297 299 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
298 300
299 301 data_dc = None
300 302 if self.dataOut.data_dc is not None:
301 303 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
302 304
303 305 self.dataOut.data_spc = data_spc
304 306 self.dataOut.data_cspc = data_cspc
305 307 self.dataOut.data_dc = data_dc
306 308 self.dataOut.heightList = heightList
307 309 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
308 310
309 311 return 1
310 312
311 313 def selectFFTsByIndex(self, minIndex, maxIndex):
312 314 """
313 315
314 316 """
315 317
316 318 if (minIndex < 0) or (minIndex > maxIndex):
317 319 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
318 320
319 321 if (maxIndex >= self.dataOut.nProfiles):
320 322 maxIndex = self.dataOut.nProfiles-1
321 323
322 324 #Spectra
323 325 data_spc = self.dataOut.data_spc[:,minIndex:maxIndex+1,:]
324 326
325 327 data_cspc = None
326 328 if self.dataOut.data_cspc is not None:
327 329 data_cspc = self.dataOut.data_cspc[:,minIndex:maxIndex+1,:]
328 330
329 331 data_dc = None
330 332 if self.dataOut.data_dc is not None:
331 333 data_dc = self.dataOut.data_dc[minIndex:maxIndex+1,:]
332 334
333 335 self.dataOut.data_spc = data_spc
334 336 self.dataOut.data_cspc = data_cspc
335 337 self.dataOut.data_dc = data_dc
336 338
337 339 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
338 340 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
339 341 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
340 342
341 343 return 1
342 344
343 345 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
344 346 # validacion de rango
345 347 if minHei == None:
346 348 minHei = self.dataOut.heightList[0]
347 349
348 350 if maxHei == None:
349 351 maxHei = self.dataOut.heightList[-1]
350 352
351 353 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
352 354 print('minHei: %.2f is out of the heights range' % (minHei))
353 355 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
354 356 minHei = self.dataOut.heightList[0]
355 357
356 358 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
357 359 print('maxHei: %.2f is out of the heights range' % (maxHei))
358 360 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
359 361 maxHei = self.dataOut.heightList[-1]
360 362
361 363 # validacion de velocidades
362 364 velrange = self.dataOut.getVelRange(1)
363 365
364 366 if minVel == None:
365 367 minVel = velrange[0]
366 368
367 369 if maxVel == None:
368 370 maxVel = velrange[-1]
369 371
370 372 if (minVel < velrange[0]) or (minVel > maxVel):
371 373 print('minVel: %.2f is out of the velocity range' % (minVel))
372 374 print('minVel is setting to %.2f' % (velrange[0]))
373 375 minVel = velrange[0]
374 376
375 377 if (maxVel > velrange[-1]) or (maxVel < minVel):
376 378 print('maxVel: %.2f is out of the velocity range' % (maxVel))
377 379 print('maxVel is setting to %.2f' % (velrange[-1]))
378 380 maxVel = velrange[-1]
379 381
380 382 # seleccion de indices para rango
381 383 minIndex = 0
382 384 maxIndex = 0
383 385 heights = self.dataOut.heightList
384 386
385 387 inda = numpy.where(heights >= minHei)
386 388 indb = numpy.where(heights <= maxHei)
387 389
388 390 try:
389 391 minIndex = inda[0][0]
390 392 except:
391 393 minIndex = 0
392 394
393 395 try:
394 396 maxIndex = indb[0][-1]
395 397 except:
396 398 maxIndex = len(heights)
397 399
398 400 if (minIndex < 0) or (minIndex > maxIndex):
399 401 raise ValueError("some value in (%d,%d) is not valid" % (
400 402 minIndex, maxIndex))
401 403
402 404 if (maxIndex >= self.dataOut.nHeights):
403 405 maxIndex = self.dataOut.nHeights - 1
404 406
405 407 # seleccion de indices para velocidades
406 408 indminvel = numpy.where(velrange >= minVel)
407 409 indmaxvel = numpy.where(velrange <= maxVel)
408 410 try:
409 411 minIndexVel = indminvel[0][0]
410 412 except:
411 413 minIndexVel = 0
412 414
413 415 try:
414 416 maxIndexVel = indmaxvel[0][-1]
415 417 except:
416 418 maxIndexVel = len(velrange)
417 419
418 420 # seleccion del espectro
419 421 data_spc = self.dataOut.data_spc[:,
420 422 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
421 423 # estimacion de ruido
422 424 noise = numpy.zeros(self.dataOut.nChannels)
423 425
424 426 for channel in range(self.dataOut.nChannels):
425 427 daux = data_spc[channel, :, :]
426 428 sortdata = numpy.sort(daux, axis=None)
427 429 noise[channel] = hildebrand_sekhon(sortdata, self.dataOut.nIncohInt)
428 430
429 431 self.dataOut.noise_estimation = noise.copy()
430 432
431 433 return 1
432 434
433 435 class removeDC(Operation):
434 436
435 437 def run(self, dataOut, mode=2):
436 438 self.dataOut = dataOut
437 439 jspectra = self.dataOut.data_spc
438 440 jcspectra = self.dataOut.data_cspc
439 441
440 442 num_chan = jspectra.shape[0]
441 443 num_hei = jspectra.shape[2]
442 444
443 445 if jcspectra is not None:
444 446 jcspectraExist = True
445 447 num_pairs = jcspectra.shape[0]
446 448 else:
447 449 jcspectraExist = False
448 450
449 451 freq_dc = int(jspectra.shape[1] / 2)
450 452 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
451 453 ind_vel = ind_vel.astype(int)
452 454
453 455 if ind_vel[0] < 0:
454 456 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
455 457
456 458 if mode == 1:
457 459 jspectra[:, freq_dc, :] = (
458 460 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
459 461
460 462 if jcspectraExist:
461 463 jcspectra[:, freq_dc, :] = (
462 464 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
463 465
464 466 if mode == 2:
465 467
466 468 vel = numpy.array([-2, -1, 1, 2])
467 469 xx = numpy.zeros([4, 4])
468 470
469 471 for fil in range(4):
470 472 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
471 473
472 474 xx_inv = numpy.linalg.inv(xx)
473 475 xx_aux = xx_inv[0, :]
474 476
475 477 for ich in range(num_chan):
476 478 yy = jspectra[ich, ind_vel, :]
477 479 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
478 480
479 481 junkid = jspectra[ich, freq_dc, :] <= 0
480 482 cjunkid = sum(junkid)
481 483
482 484 if cjunkid.any():
483 485 jspectra[ich, freq_dc, junkid.nonzero()] = (
484 486 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
485 487
486 488 if jcspectraExist:
487 489 for ip in range(num_pairs):
488 490 yy = jcspectra[ip, ind_vel, :]
489 491 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
490 492
491 493 self.dataOut.data_spc = jspectra
492 494 self.dataOut.data_cspc = jcspectra
493 495
494 496 return self.dataOut
495 497
496 498 class removeInterference(Operation):
497 499
498 500 def removeInterference2(self):
499 501
500 502 cspc = self.dataOut.data_cspc
501 503 spc = self.dataOut.data_spc
502 504 Heights = numpy.arange(cspc.shape[2])
503 505 realCspc = numpy.abs(cspc)
504 506
505 507 for i in range(cspc.shape[0]):
506 508 LinePower= numpy.sum(realCspc[i], axis=0)
507 509 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
508 510 SelectedHeights = Heights[ numpy.where(LinePower < Threshold) ]
509 511 InterferenceSum = numpy.sum(realCspc[i,:,SelectedHeights],axis=0)
510 512 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
511 513 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
512 514
513 515
514 516 InterferenceRange = numpy.where(([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
515 517 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
516 518 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
517 519 cspc[i,InterferenceRange,:] = numpy.NaN
518 520
519 521 self.dataOut.data_cspc = cspc
520 522
521 523 def removeInterference(self, interf=2, hei_interf=None, nhei_interf=None, offhei_interf=None):
522 524
523 525 jspectra = self.dataOut.data_spc
524 526 jcspectra = self.dataOut.data_cspc
525 527 jnoise = self.dataOut.getNoise()
526 528 num_incoh = self.dataOut.nIncohInt
527 529
528 530 num_channel = jspectra.shape[0]
529 531 num_prof = jspectra.shape[1]
530 532 num_hei = jspectra.shape[2]
531 533
532 534 # hei_interf
533 535 if hei_interf is None:
534 536 count_hei = int(num_hei / 2)
535 537 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
536 538 hei_interf = numpy.asarray(hei_interf)[0]
537 539 # nhei_interf
538 540 if (nhei_interf == None):
539 541 nhei_interf = 5
540 542 if (nhei_interf < 1):
541 543 nhei_interf = 1
542 544 if (nhei_interf > count_hei):
543 545 nhei_interf = count_hei
544 546 if (offhei_interf == None):
545 547 offhei_interf = 0
546 548
547 549 ind_hei = list(range(num_hei))
548 550 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
549 551 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
550 552 mask_prof = numpy.asarray(list(range(num_prof)))
551 553 num_mask_prof = mask_prof.size
552 554 comp_mask_prof = [0, num_prof / 2]
553 555
554 556 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
555 557 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
556 558 jnoise = numpy.nan
557 559 noise_exist = jnoise[0] < numpy.Inf
558 560
559 561 # Subrutina de Remocion de la Interferencia
560 562 for ich in range(num_channel):
561 563 # Se ordena los espectros segun su potencia (menor a mayor)
562 564 power = jspectra[ich, mask_prof, :]
563 565 power = power[:, hei_interf]
564 566 power = power.sum(axis=0)
565 567 psort = power.ravel().argsort()
566 568
567 569 # Se estima la interferencia promedio en los Espectros de Potencia empleando
568 570 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
569 571 offhei_interf, nhei_interf + offhei_interf))]]]
570 572
571 573 if noise_exist:
572 574 # tmp_noise = jnoise[ich] / num_prof
573 575 tmp_noise = jnoise[ich]
574 576 junkspc_interf = junkspc_interf - tmp_noise
575 577 #junkspc_interf[:,comp_mask_prof] = 0
576 578
577 579 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
578 580 jspc_interf = jspc_interf.transpose()
579 581 # Calculando el espectro de interferencia promedio
580 582 noiseid = numpy.where(
581 583 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
582 584 noiseid = noiseid[0]
583 585 cnoiseid = noiseid.size
584 586 interfid = numpy.where(
585 587 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
586 588 interfid = interfid[0]
587 589 cinterfid = interfid.size
588 590
589 591 if (cnoiseid > 0):
590 592 jspc_interf[noiseid] = 0
591 593
592 594 # Expandiendo los perfiles a limpiar
593 595 if (cinterfid > 0):
594 596 new_interfid = (
595 597 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
596 598 new_interfid = numpy.asarray(new_interfid)
597 599 new_interfid = {x for x in new_interfid}
598 600 new_interfid = numpy.array(list(new_interfid))
599 601 new_cinterfid = new_interfid.size
600 602 else:
601 603 new_cinterfid = 0
602 604
603 605 for ip in range(new_cinterfid):
604 606 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
605 607 jspc_interf[new_interfid[ip]
606 608 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
607 609
608 610 jspectra[ich, :, ind_hei] = jspectra[ich, :,
609 611 ind_hei] - jspc_interf # Corregir indices
610 612
611 613 # Removiendo la interferencia del punto de mayor interferencia
612 614 ListAux = jspc_interf[mask_prof].tolist()
613 615 maxid = ListAux.index(max(ListAux))
614 616
615 617 if cinterfid > 0:
616 618 for ip in range(cinterfid * (interf == 2) - 1):
617 619 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
618 620 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
619 621 cind = len(ind)
620 622
621 623 if (cind > 0):
622 624 jspectra[ich, interfid[ip], ind] = tmp_noise * \
623 625 (1 + (numpy.random.uniform(cind) - 0.5) /
624 626 numpy.sqrt(num_incoh))
625 627
626 628 ind = numpy.array([-2, -1, 1, 2])
627 629 xx = numpy.zeros([4, 4])
628 630
629 631 for id1 in range(4):
630 632 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
631 633
632 634 xx_inv = numpy.linalg.inv(xx)
633 635 xx = xx_inv[:, 0]
634 636 ind = (ind + maxid + num_mask_prof) % num_mask_prof
635 637 yy = jspectra[ich, mask_prof[ind], :]
636 638 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
637 639 yy.transpose(), xx)
638 640
639 641 indAux = (jspectra[ich, :, :] < tmp_noise *
640 642 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
641 643 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
642 644 (1 - 1 / numpy.sqrt(num_incoh))
643 645
644 646 # Remocion de Interferencia en el Cross Spectra
645 647 if jcspectra is None:
646 648 return jspectra, jcspectra
647 649 num_pairs = int(jcspectra.size / (num_prof * num_hei))
648 650 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
649 651
650 652 for ip in range(num_pairs):
651 653
652 654 #-------------------------------------------
653 655
654 656 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
655 657 cspower = cspower[:, hei_interf]
656 658 cspower = cspower.sum(axis=0)
657 659
658 660 cspsort = cspower.ravel().argsort()
659 661 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
660 662 offhei_interf, nhei_interf + offhei_interf))]]]
661 663 junkcspc_interf = junkcspc_interf.transpose()
662 664 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
663 665
664 666 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
665 667
666 668 median_real = int(numpy.median(numpy.real(
667 669 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
668 670 median_imag = int(numpy.median(numpy.imag(
669 671 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
670 672 comp_mask_prof = [int(e) for e in comp_mask_prof]
671 673 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
672 674 median_real, median_imag)
673 675
674 676 for iprof in range(num_prof):
675 677 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
676 678 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
677 679
678 680 # Removiendo la Interferencia
679 681 jcspectra[ip, :, ind_hei] = jcspectra[ip,
680 682 :, ind_hei] - jcspc_interf
681 683
682 684 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
683 685 maxid = ListAux.index(max(ListAux))
684 686
685 687 ind = numpy.array([-2, -1, 1, 2])
686 688 xx = numpy.zeros([4, 4])
687 689
688 690 for id1 in range(4):
689 691 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
690 692
691 693 xx_inv = numpy.linalg.inv(xx)
692 694 xx = xx_inv[:, 0]
693 695
694 696 ind = (ind + maxid + num_mask_prof) % num_mask_prof
695 697 yy = jcspectra[ip, mask_prof[ind], :]
696 698 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
697 699
698 700 # Guardar Resultados
699 701 self.dataOut.data_spc = jspectra
700 702 self.dataOut.data_cspc = jcspectra
701 703
702 704 return 1
703 705
704 706 def run(self, dataOut, interf=2,hei_interf=None, nhei_interf=None, offhei_interf=None, mode=1):
705 707
706 708 self.dataOut = dataOut
707 709
708 710 if mode == 1:
709 711 self.removeInterference(interf=2,hei_interf=None, nhei_interf=None, offhei_interf=None)
710 712 elif mode == 2:
711 713 self.removeInterference2()
712 714
713 715 return self.dataOut
714 716
715 717
716 718 class deflip(Operation):
717 719
718 720 def run(self, dataOut):
719 721 # arreglo 1: (num_chan, num_profiles, num_heights)
720 722 self.dataOut = dataOut
721 723
722 724 # JULIA-oblicua, indice 2
723 725 # arreglo 2: (num_profiles, num_heights)
724 726 jspectra = self.dataOut.data_spc[2]
725 727 jspectra_tmp=numpy.zeros(jspectra.shape)
726 728 num_profiles=jspectra.shape[0]
727 729 freq_dc = int(num_profiles / 2)
728 730 # Flip con for
729 731 for j in range(num_profiles):
730 732 jspectra_tmp[num_profiles-j-1]= jspectra[j]
731 733 # Intercambio perfil de DC con perfil inmediato anterior
732 734 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
733 735 jspectra_tmp[freq_dc]= jspectra[freq_dc]
734 736 # canal modificado es re-escrito en el arreglo de canales
735 737 self.dataOut.data_spc[2] = jspectra_tmp
736 738
737 739 return self.dataOut
738 740
739 741
740 742 class IncohInt(Operation):
741 743
742 744 __profIndex = 0
743 745 __withOverapping = False
744 746
745 747 __byTime = False
746 748 __initime = None
747 749 __lastdatatime = None
748 750 __integrationtime = None
749 751
750 752 __buffer_spc = None
751 753 __buffer_cspc = None
752 754 __buffer_dc = None
753 755
754 756 __dataReady = False
755 757
756 758 __timeInterval = None
757 759
758 760 n = None
759 761
760 762 def __init__(self):
761 763
762 764 Operation.__init__(self)
763 765
764 766 def setup(self, n=None, timeInterval=None, overlapping=False):
765 767 """
766 768 Set the parameters of the integration class.
767 769
768 770 Inputs:
769 771
770 772 n : Number of coherent integrations
771 773 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
772 774 overlapping :
773 775
774 776 """
775 777
776 778 self.__initime = None
777 779 self.__lastdatatime = 0
778 780
779 781 self.__buffer_spc = 0
780 782 self.__buffer_cspc = 0
781 783 self.__buffer_dc = 0
782 784
783 785 self.__profIndex = 0
784 786 self.__dataReady = False
785 787 self.__byTime = False
786 788
787 789 if n is None and timeInterval is None:
788 790 raise ValueError("n or timeInterval should be specified ...")
789 791
790 792 if n is not None:
791 793 self.n = int(n)
792 794 else:
793 795
794 796 self.__integrationtime = int(timeInterval)
795 797 self.n = None
796 798 self.__byTime = True
797 799
798 800 def putData(self, data_spc, data_cspc, data_dc):
799 801 """
800 802 Add a profile to the __buffer_spc and increase in one the __profileIndex
801 803
802 804 """
803 805
804 806 self.__buffer_spc += data_spc
805 807
806 808 if data_cspc is None:
807 809 self.__buffer_cspc = None
808 810 else:
809 811 self.__buffer_cspc += data_cspc
810 812
811 813 if data_dc is None:
812 814 self.__buffer_dc = None
813 815 else:
814 816 self.__buffer_dc += data_dc
815 817
816 818 self.__profIndex += 1
817 819
818 820 return
819 821
820 822 def pushData(self):
821 823 """
822 824 Return the sum of the last profiles and the profiles used in the sum.
823 825
824 826 Affected:
825 827
826 828 self.__profileIndex
827 829
828 830 """
829 831
830 832 data_spc = self.__buffer_spc
831 833 data_cspc = self.__buffer_cspc
832 834 data_dc = self.__buffer_dc
833 835 n = self.__profIndex
834 836
835 837 self.__buffer_spc = 0
836 838 self.__buffer_cspc = 0
837 839 self.__buffer_dc = 0
838 840 self.__profIndex = 0
839 841
840 842 return data_spc, data_cspc, data_dc, n
841 843
842 844 def byProfiles(self, *args):
843 845
844 846 self.__dataReady = False
845 847 avgdata_spc = None
846 848 avgdata_cspc = None
847 849 avgdata_dc = None
848 850
849 851 self.putData(*args)
850 852
851 853 if self.__profIndex == self.n:
852 854
853 855 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
854 856 self.n = n
855 857 self.__dataReady = True
856 858
857 859 return avgdata_spc, avgdata_cspc, avgdata_dc
858 860
859 861 def byTime(self, datatime, *args):
860 862
861 863 self.__dataReady = False
862 864 avgdata_spc = None
863 865 avgdata_cspc = None
864 866 avgdata_dc = None
865 867
866 868 self.putData(*args)
867 869
868 870 if (datatime - self.__initime) >= self.__integrationtime:
869 871 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
870 872 self.n = n
871 873 self.__dataReady = True
872 874
873 875 return avgdata_spc, avgdata_cspc, avgdata_dc
874 876
875 877 def integrate(self, datatime, *args):
876 878
877 879 if self.__profIndex == 0:
878 880 self.__initime = datatime
879 881
880 882 if self.__byTime:
881 883 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
882 884 datatime, *args)
883 885 else:
884 886 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
885 887
886 888 if not self.__dataReady:
887 889 return None, None, None, None
888 890
889 891 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
890 892
891 893 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
892 894 if n == 1:
893 895 return dataOut
894 896
895 897 dataOut.flagNoData = True
896 898
897 899 if not self.isConfig:
898 900 self.setup(n, timeInterval, overlapping)
899 901 self.isConfig = True
900 902
901 903 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
902 904 dataOut.data_spc,
903 905 dataOut.data_cspc,
904 906 dataOut.data_dc)
905 907
906 908 if self.__dataReady:
907 909
908 910 dataOut.data_spc = avgdata_spc
909 911 dataOut.data_cspc = avgdata_cspc
910 912 dataOut.data_dc = avgdata_dc
911 913 dataOut.nIncohInt *= self.n
912 914 dataOut.utctime = avgdatatime
913 915 dataOut.flagNoData = False
914 916
915 917 return dataOut
916 918
917 919 class dopplerFlip(Operation):
918 920
919 921 def run(self, dataOut):
920 922 # arreglo 1: (num_chan, num_profiles, num_heights)
921 923 self.dataOut = dataOut
922 924 # JULIA-oblicua, indice 2
923 925 # arreglo 2: (num_profiles, num_heights)
924 926 jspectra = self.dataOut.data_spc[2]
925 927 jspectra_tmp = numpy.zeros(jspectra.shape)
926 928 num_profiles = jspectra.shape[0]
927 929 freq_dc = int(num_profiles / 2)
928 930 # Flip con for
929 931 for j in range(num_profiles):
930 932 jspectra_tmp[num_profiles-j-1]= jspectra[j]
931 933 # Intercambio perfil de DC con perfil inmediato anterior
932 934 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
933 935 jspectra_tmp[freq_dc]= jspectra[freq_dc]
934 936 # canal modificado es re-escrito en el arreglo de canales
935 937 self.dataOut.data_spc[2] = jspectra_tmp
936 938
937 939 return self.dataOut No newline at end of file
@@ -1,1627 +1,1625
1 1 import sys
2 2 import numpy,math
3 3 from scipy import interpolate
4 4 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
5 5 from schainpy.model.data.jrodata import Voltage,hildebrand_sekhon
6 6 from schainpy.utils import log
7 7 from time import time
8 8 # voltage proc master
9 9
10 10 class VoltageProc(ProcessingUnit):
11 11
12 12 def __init__(self):
13 13
14 14 ProcessingUnit.__init__(self)
15 15
16 16 self.dataOut = Voltage()
17 17 self.flip = 1
18 18 self.setupReq = False
19 19
20 20 def run(self, runNextUnit = 0):
21 21
22 22 if self.dataIn.type == 'AMISR':
23 23 self.__updateObjFromAmisrInput()
24 24
25 25 if self.dataIn.type == 'Voltage':
26 26 self.dataOut.copy(self.dataIn)
27 27 self.dataOut.runNextUnit = runNextUnit
28 28
29 29
30 30 def __updateObjFromAmisrInput(self):
31 31
32 32 self.dataOut.timeZone = self.dataIn.timeZone
33 33 self.dataOut.dstFlag = self.dataIn.dstFlag
34 34 self.dataOut.errorCount = self.dataIn.errorCount
35 35 self.dataOut.useLocalTime = self.dataIn.useLocalTime
36 36
37 37 self.dataOut.flagNoData = self.dataIn.flagNoData
38 38 self.dataOut.data = self.dataIn.data
39 39 self.dataOut.utctime = self.dataIn.utctime
40 40 self.dataOut.channelList = self.dataIn.channelList
41 41 #self.dataOut.timeInterval = self.dataIn.timeInterval
42 42 self.dataOut.heightList = self.dataIn.heightList
43 43 self.dataOut.nProfiles = self.dataIn.nProfiles
44 44
45 45 self.dataOut.nCohInt = self.dataIn.nCohInt
46 46 self.dataOut.ippSeconds = self.dataIn.ippSeconds
47 47 self.dataOut.frequency = self.dataIn.frequency
48 48
49 49 self.dataOut.azimuth = self.dataIn.azimuth
50 50 self.dataOut.zenith = self.dataIn.zenith
51 51
52 52 self.dataOut.beam.codeList = self.dataIn.beam.codeList
53 53 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
54 54 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
55 55
56 56
57 57 class selectChannels(Operation):
58 58
59 59 def run(self, dataOut, channelList):
60 60
61 61 channelIndexList = []
62 62 self.dataOut = dataOut
63 63 for channel in channelList:
64 64 if channel not in self.dataOut.channelList:
65 65 raise ValueError("Channel %d is not in %s" %(channel, str(self.dataOut.channelList)))
66 66
67 67 index = self.dataOut.channelList.index(channel)
68 68 channelIndexList.append(index)
69 69 self.selectChannelsByIndex(channelIndexList)
70 70 return self.dataOut
71 71
72 72 def selectChannelsByIndex(self, channelIndexList):
73 73 """
74 74 Selecciona un bloque de datos en base a canales segun el channelIndexList
75 75
76 76 Input:
77 77 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
78 78
79 79 Affected:
80 80 self.dataOut.data
81 81 self.dataOut.channelIndexList
82 82 self.dataOut.nChannels
83 83 self.dataOut.m_ProcessingHeader.totalSpectra
84 84 self.dataOut.systemHeaderObj.numChannels
85 85 self.dataOut.m_ProcessingHeader.blockSize
86 86
87 87 Return:
88 88 None
89 89 """
90 90
91 91 for channelIndex in channelIndexList:
92 92 if channelIndex not in self.dataOut.channelIndexList:
93 93 raise ValueError("The value %d in channelIndexList is not valid" %channelIndex)
94 94
95 95 if self.dataOut.type == 'Voltage':
96 96 if self.dataOut.flagDataAsBlock:
97 97 """
98 98 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
99 99 """
100 100 data = self.dataOut.data[channelIndexList,:,:]
101 101 else:
102 102 data = self.dataOut.data[channelIndexList,:]
103 103
104 104 self.dataOut.data = data
105 105 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
106 106 self.dataOut.channelList = range(len(channelIndexList))
107 107
108 108 elif self.dataOut.type == 'Spectra':
109 109 data_spc = self.dataOut.data_spc[channelIndexList, :]
110 110 data_dc = self.dataOut.data_dc[channelIndexList, :]
111 111
112 112 self.dataOut.data_spc = data_spc
113 113 self.dataOut.data_dc = data_dc
114 114
115 115 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
116 116 self.dataOut.channelList = range(len(channelIndexList))
117 117 self.__selectPairsByChannel(channelIndexList)
118 118
119 119 return 1
120 120
121 121 def __selectPairsByChannel(self, channelList=None):
122 122
123 123 if channelList == None:
124 124 return
125 125
126 126 pairsIndexListSelected = []
127 127 for pairIndex in self.dataOut.pairsIndexList:
128 128 # First pair
129 129 if self.dataOut.pairsList[pairIndex][0] not in channelList:
130 130 continue
131 131 # Second pair
132 132 if self.dataOut.pairsList[pairIndex][1] not in channelList:
133 133 continue
134 134
135 135 pairsIndexListSelected.append(pairIndex)
136 136
137 137 if not pairsIndexListSelected:
138 138 self.dataOut.data_cspc = None
139 139 self.dataOut.pairsList = []
140 140 return
141 141
142 142 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
143 143 self.dataOut.pairsList = [self.dataOut.pairsList[i]
144 144 for i in pairsIndexListSelected]
145 145
146 146 return
147 147
148 148 class selectHeights(Operation):
149 149
150 150 def run(self, dataOut, minHei=None, maxHei=None, minIndex=None, maxIndex=None):
151 151 """
152 152 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
153 153 minHei <= height <= maxHei
154 154
155 155 Input:
156 156 minHei : valor minimo de altura a considerar
157 157 maxHei : valor maximo de altura a considerar
158 158
159 159 Affected:
160 160 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
161 161
162 162 Return:
163 163 1 si el metodo se ejecuto con exito caso contrario devuelve 0
164 164 """
165 165
166 166 self.dataOut = dataOut
167 167
168 168 if type(minHei) == int or type(minHei) == float:
169 169 v_minHei= True
170 170 else:
171 171 v_minHei= False
172 172
173 173 if v_minHei and maxHei:
174 174 if (minHei < self.dataOut.heightList[0]):
175 175 minHei = self.dataOut.heightList[0]
176 176
177 177 if (maxHei > self.dataOut.heightList[-1]):
178 178 maxHei = self.dataOut.heightList[-1]
179 179
180 180 minIndex = 0
181 181 maxIndex = 0
182 182 heights = self.dataOut.heightList
183 183 inda = numpy.where(heights >= minHei)
184 184 indb = numpy.where(heights <= maxHei)
185 185
186 186 try:
187 187 minIndex = inda[0][0]
188 188 except:
189 189 minIndex = 0
190 190
191 191 try:
192 192 maxIndex = indb[0][-1]
193 193 except:
194 194 maxIndex = len(heights)
195 195 self.selectHeightsByIndex(minIndex, maxIndex)
196 196
197 197 return self.dataOut
198 198
199 199 def selectHeightsByIndex(self, minIndex, maxIndex):
200 200 """
201 201 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
202 202 minIndex <= index <= maxIndex
203 203
204 204 Input:
205 205 minIndex : valor de indice minimo de altura a considerar
206 206 maxIndex : valor de indice maximo de altura a considerar
207 207
208 208 Affected:
209 209 self.dataOut.data
210 210 self.dataOut.heightList
211 211
212 212 Return:
213 213 1 si el metodo se ejecuto con exito caso contrario devuelve 0
214 214 """
215 215
216 216 if self.dataOut.type == 'Voltage':
217 print(minIndex)
218 print(maxIndex)
219 217 if (minIndex < 0) or (minIndex > maxIndex):
220 218 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
221 219
222 220 if (maxIndex >= self.dataOut.nHeights):
223 221 maxIndex = self.dataOut.nHeights
224 222
225 223 #voltage
226 224 if self.dataOut.flagDataAsBlock:
227 225 """
228 226 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
229 227 """
230 228 data = self.dataOut.data[:,:, minIndex:maxIndex]
231 229 else:
232 230 data = self.dataOut.data[:, minIndex:maxIndex]
233 231
234 232 # firstHeight = self.dataOut.heightList[minIndex]
235 233
236 234 self.dataOut.data = data
237 235 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
238 236
239 237 if self.dataOut.nHeights <= 1:
240 238 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights))
241 239 elif self.dataOut.type == 'Spectra':
242 240 if (minIndex < 0) or (minIndex > maxIndex):
243 241 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (
244 242 minIndex, maxIndex))
245 243
246 244 if (maxIndex >= self.dataOut.nHeights):
247 245 maxIndex = self.dataOut.nHeights - 1
248 246
249 247 # Spectra
250 248 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
251 249
252 250 data_cspc = None
253 251 if self.dataOut.data_cspc is not None:
254 252 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
255 253
256 254 data_dc = None
257 255 if self.dataOut.data_dc is not None:
258 256 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
259 257
260 258 self.dataOut.data_spc = data_spc
261 259 self.dataOut.data_cspc = data_cspc
262 260 self.dataOut.data_dc = data_dc
263 261
264 262 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
265 263
266 264 return 1
267 265
268 266
269 267 class filterByHeights(Operation):
270 268
271 269 def run(self, dataOut, window):
272 270
273 271 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
274 272
275 273 if window == None:
276 274 window = (dataOut.radarControllerHeaderObj.txA/dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
277 275
278 276 newdelta = deltaHeight * window
279 277 r = dataOut.nHeights % window
280 278 newheights = (dataOut.nHeights-r)/window
281 279
282 280 if newheights <= 1:
283 281 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(dataOut.nHeights, window))
284 282
285 283 if dataOut.flagDataAsBlock:
286 284 """
287 285 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
288 286 """
289 287 buffer = dataOut.data[:, :, 0:int(dataOut.nHeights-r)]
290 288 buffer = buffer.reshape(dataOut.nChannels, dataOut.nProfiles, int(dataOut.nHeights/window), window)
291 289 buffer = numpy.sum(buffer,3)
292 290
293 291 else:
294 292 buffer = dataOut.data[:,0:int(dataOut.nHeights-r)]
295 293 buffer = buffer.reshape(dataOut.nChannels,int(dataOut.nHeights/window),int(window))
296 294 buffer = numpy.sum(buffer,2)
297 295
298 296 dataOut.data = buffer
299 297 dataOut.heightList = dataOut.heightList[0] + numpy.arange( newheights )*newdelta
300 298 dataOut.windowOfFilter = window
301 299
302 300 return dataOut
303 301
304 302
305 303 class setH0(Operation):
306 304
307 305 def run(self, dataOut, h0, deltaHeight = None):
308 306
309 307 if not deltaHeight:
310 308 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
311 309
312 310 nHeights = dataOut.nHeights
313 311
314 312 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
315 313
316 314 dataOut.heightList = newHeiRange
317 315
318 316 return dataOut
319 317
320 318
321 319 class deFlip(Operation):
322 320
323 321 def run(self, dataOut, channelList = []):
324 322
325 323 data = dataOut.data.copy()
326 324
327 325 if dataOut.flagDataAsBlock:
328 326 flip = self.flip
329 327 profileList = list(range(dataOut.nProfiles))
330 328
331 329 if not channelList:
332 330 for thisProfile in profileList:
333 331 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
334 332 flip *= -1.0
335 333 else:
336 334 for thisChannel in channelList:
337 335 if thisChannel not in dataOut.channelList:
338 336 continue
339 337
340 338 for thisProfile in profileList:
341 339 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
342 340 flip *= -1.0
343 341
344 342 self.flip = flip
345 343
346 344 else:
347 345 if not channelList:
348 346 data[:,:] = data[:,:]*self.flip
349 347 else:
350 348 for thisChannel in channelList:
351 349 if thisChannel not in dataOut.channelList:
352 350 continue
353 351
354 352 data[thisChannel,:] = data[thisChannel,:]*self.flip
355 353
356 354 self.flip *= -1.
357 355
358 356 dataOut.data = data
359 357
360 358 return dataOut
361 359
362 360
363 361 class setAttribute(Operation):
364 362 '''
365 363 Set an arbitrary attribute(s) to dataOut
366 364 '''
367 365
368 366 def __init__(self):
369 367
370 368 Operation.__init__(self)
371 369 self._ready = False
372 370
373 371 def run(self, dataOut, **kwargs):
374 372
375 373 for key, value in kwargs.items():
376 374 setattr(dataOut, key, value)
377 375
378 376 return dataOut
379 377
380 378
381 379 @MPDecorator
382 380 class printAttribute(Operation):
383 381 '''
384 382 Print an arbitrary attribute of dataOut
385 383 '''
386 384
387 385 def __init__(self):
388 386
389 387 Operation.__init__(self)
390 388
391 389 def run(self, dataOut, attributes):
392 390
393 391 if isinstance(attributes, str):
394 392 attributes = [attributes]
395 393 for attr in attributes:
396 394 if hasattr(dataOut, attr):
397 395 log.log(getattr(dataOut, attr), attr)
398 396
399 397
400 398 class interpolateHeights(Operation):
401 399
402 400 def run(self, dataOut, topLim, botLim):
403 401 #69 al 72 para julia
404 402 #82-84 para meteoros
405 403 if len(numpy.shape(dataOut.data))==2:
406 404 sampInterp = (dataOut.data[:,botLim-1] + dataOut.data[:,topLim+1])/2
407 405 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
408 406 #dataOut.data[:,botLim:limSup+1] = sampInterp
409 407 dataOut.data[:,botLim:topLim+1] = sampInterp
410 408 else:
411 409 nHeights = dataOut.data.shape[2]
412 410 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
413 411 y = dataOut.data[:,:,list(range(botLim))+list(range(topLim+1,nHeights))]
414 412 f = interpolate.interp1d(x, y, axis = 2)
415 413 xnew = numpy.arange(botLim,topLim+1)
416 414 ynew = f(xnew)
417 415 dataOut.data[:,:,botLim:topLim+1] = ynew
418 416
419 417 return dataOut
420 418
421 419
422 420 class CohInt(Operation):
423 421
424 422 isConfig = False
425 423 __profIndex = 0
426 424 __byTime = False
427 425 __initime = None
428 426 __lastdatatime = None
429 427 __integrationtime = None
430 428 __buffer = None
431 429 __bufferStride = []
432 430 __dataReady = False
433 431 __profIndexStride = 0
434 432 __dataToPutStride = False
435 433 n = None
436 434
437 435 def __init__(self, **kwargs):
438 436
439 437 Operation.__init__(self, **kwargs)
440 438
441 439 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
442 440 """
443 441 Set the parameters of the integration class.
444 442
445 443 Inputs:
446 444
447 445 n : Number of coherent integrations
448 446 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
449 447 overlapping :
450 448 """
451 449
452 450 self.__initime = None
453 451 self.__lastdatatime = 0
454 452 self.__buffer = None
455 453 self.__dataReady = False
456 454 self.byblock = byblock
457 455 self.stride = stride
458 456
459 457 if n == None and timeInterval == None:
460 458 raise ValueError("n or timeInterval should be specified ...")
461 459
462 460 if n != None:
463 461 self.n = n
464 462 self.__byTime = False
465 463 else:
466 464 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
467 465 self.n = 9999
468 466 self.__byTime = True
469 467
470 468 if overlapping:
471 469 self.__withOverlapping = True
472 470 self.__buffer = None
473 471 else:
474 472 self.__withOverlapping = False
475 473 self.__buffer = 0
476 474
477 475 self.__profIndex = 0
478 476
479 477 def putData(self, data):
480 478
481 479 """
482 480 Add a profile to the __buffer and increase in one the __profileIndex
483 481
484 482 """
485 483
486 484 if not self.__withOverlapping:
487 485 self.__buffer += data.copy()
488 486 self.__profIndex += 1
489 487 return
490 488
491 489 #Overlapping data
492 490 nChannels, nHeis = data.shape
493 491 data = numpy.reshape(data, (1, nChannels, nHeis))
494 492
495 493 #If the buffer is empty then it takes the data value
496 494 if self.__buffer is None:
497 495 self.__buffer = data
498 496 self.__profIndex += 1
499 497 return
500 498
501 499 #If the buffer length is lower than n then stakcing the data value
502 500 if self.__profIndex < self.n:
503 501 self.__buffer = numpy.vstack((self.__buffer, data))
504 502 self.__profIndex += 1
505 503 return
506 504
507 505 #If the buffer length is equal to n then replacing the last buffer value with the data value
508 506 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
509 507 self.__buffer[self.n-1] = data
510 508 self.__profIndex = self.n
511 509 return
512 510
513 511
514 512 def pushData(self):
515 513 """
516 514 Return the sum of the last profiles and the profiles used in the sum.
517 515
518 516 Affected:
519 517
520 518 self.__profileIndex
521 519
522 520 """
523 521
524 522 if not self.__withOverlapping:
525 523 data = self.__buffer
526 524 n = self.__profIndex
527 525
528 526 self.__buffer = 0
529 527 self.__profIndex = 0
530 528
531 529 return data, n
532 530
533 531 #Integration with Overlapping
534 532 data = numpy.sum(self.__buffer, axis=0)
535 533 # print data
536 534 # raise
537 535 n = self.__profIndex
538 536
539 537 return data, n
540 538
541 539 def byProfiles(self, data):
542 540
543 541 self.__dataReady = False
544 542 avgdata = None
545 543 # n = None
546 544 # print data
547 545 # raise
548 546 self.putData(data)
549 547
550 548 if self.__profIndex == self.n:
551 549 avgdata, n = self.pushData()
552 550 self.__dataReady = True
553 551
554 552 return avgdata
555 553
556 554 def byTime(self, data, datatime):
557 555
558 556 self.__dataReady = False
559 557 avgdata = None
560 558 n = None
561 559
562 560 self.putData(data)
563 561
564 562 if (datatime - self.__initime) >= self.__integrationtime:
565 563 avgdata, n = self.pushData()
566 564 self.n = n
567 565 self.__dataReady = True
568 566
569 567 return avgdata
570 568
571 569 def integrateByStride(self, data, datatime):
572 570 # print data
573 571 if self.__profIndex == 0:
574 572 self.__buffer = [[data.copy(), datatime]]
575 573 else:
576 574 self.__buffer.append([data.copy(),datatime])
577 575 self.__profIndex += 1
578 576 self.__dataReady = False
579 577
580 578 if self.__profIndex == self.n * self.stride :
581 579 self.__dataToPutStride = True
582 580 self.__profIndexStride = 0
583 581 self.__profIndex = 0
584 582 self.__bufferStride = []
585 583 for i in range(self.stride):
586 584 current = self.__buffer[i::self.stride]
587 585 data = numpy.sum([t[0] for t in current], axis=0)
588 586 avgdatatime = numpy.average([t[1] for t in current])
589 587 # print data
590 588 self.__bufferStride.append((data, avgdatatime))
591 589
592 590 if self.__dataToPutStride:
593 591 self.__dataReady = True
594 592 self.__profIndexStride += 1
595 593 if self.__profIndexStride == self.stride:
596 594 self.__dataToPutStride = False
597 595 # print self.__bufferStride[self.__profIndexStride - 1]
598 596 # raise
599 597 return self.__bufferStride[self.__profIndexStride - 1]
600 598
601 599
602 600 return None, None
603 601
604 602 def integrate(self, data, datatime=None):
605 603
606 604 if self.__initime == None:
607 605 self.__initime = datatime
608 606
609 607 if self.__byTime:
610 608 avgdata = self.byTime(data, datatime)
611 609 else:
612 610 avgdata = self.byProfiles(data)
613 611
614 612
615 613 self.__lastdatatime = datatime
616 614
617 615 if avgdata is None:
618 616 return None, None
619 617
620 618 avgdatatime = self.__initime
621 619
622 620 deltatime = datatime - self.__lastdatatime
623 621
624 622 if not self.__withOverlapping:
625 623 self.__initime = datatime
626 624 else:
627 625 self.__initime += deltatime
628 626
629 627 return avgdata, avgdatatime
630 628
631 629 def integrateByBlock(self, dataOut):
632 630
633 631 times = int(dataOut.data.shape[1]/self.n)
634 632 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
635 633
636 634 id_min = 0
637 635 id_max = self.n
638 636
639 637 for i in range(times):
640 638 junk = dataOut.data[:,id_min:id_max,:]
641 639 avgdata[:,i,:] = junk.sum(axis=1)
642 640 id_min += self.n
643 641 id_max += self.n
644 642
645 643 timeInterval = dataOut.ippSeconds*self.n
646 644 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
647 645 self.__dataReady = True
648 646 return avgdata, avgdatatime
649 647
650 648 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
651 649
652 650 if not self.isConfig:
653 651 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
654 652 self.isConfig = True
655 653 if dataOut.flagDataAsBlock:
656 654 """
657 655 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
658 656 """
659 657 avgdata, avgdatatime = self.integrateByBlock(dataOut)
660 658 dataOut.nProfiles /= self.n
661 659 else:
662 660 if stride is None:
663 661 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
664 662 else:
665 663 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
666 664
667 665
668 666 # dataOut.timeInterval *= n
669 667 dataOut.flagNoData = True
670 668
671 669 if self.__dataReady:
672 670 dataOut.data = avgdata
673 671 if not dataOut.flagCohInt:
674 672 dataOut.nCohInt *= self.n
675 673 dataOut.flagCohInt = True
676 674 dataOut.utctime = avgdatatime
677 675 # print avgdata, avgdatatime
678 676 # raise
679 677 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
680 678 dataOut.flagNoData = False
681 679 return dataOut
682 680
683 681 class Decoder(Operation):
684 682
685 683 isConfig = False
686 684 __profIndex = 0
687 685
688 686 code = None
689 687
690 688 nCode = None
691 689 nBaud = None
692 690
693 691 def __init__(self, **kwargs):
694 692
695 693 Operation.__init__(self, **kwargs)
696 694
697 695 self.times = None
698 696 self.osamp = None
699 697 # self.__setValues = False
700 698 self.isConfig = False
701 699 self.setupReq = False
702 700 def setup(self, code, osamp, dataOut):
703 701
704 702 self.__profIndex = 0
705 703
706 704 self.code = code
707 705
708 706 self.nCode = len(code)
709 707 self.nBaud = len(code[0])
710 708
711 709 if (osamp != None) and (osamp >1):
712 710 self.osamp = osamp
713 711 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
714 712 self.nBaud = self.nBaud*self.osamp
715 713
716 714 self.__nChannels = dataOut.nChannels
717 715 self.__nProfiles = dataOut.nProfiles
718 716 self.__nHeis = dataOut.nHeights
719 717
720 718 if self.__nHeis < self.nBaud:
721 719 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
722 720
723 721 #Frequency
724 722 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
725 723
726 724 __codeBuffer[:,0:self.nBaud] = self.code
727 725
728 726 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
729 727
730 728 if dataOut.flagDataAsBlock:
731 729
732 730 self.ndatadec = self.__nHeis #- self.nBaud + 1
733 731
734 732 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
735 733
736 734 else:
737 735
738 736 #Time
739 737 self.ndatadec = self.__nHeis #- self.nBaud + 1
740 738
741 739 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
742 740
743 741 def __convolutionInFreq(self, data):
744 742
745 743 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
746 744
747 745 fft_data = numpy.fft.fft(data, axis=1)
748 746
749 747 conv = fft_data*fft_code
750 748
751 749 data = numpy.fft.ifft(conv,axis=1)
752 750
753 751 return data
754 752
755 753 def __convolutionInFreqOpt(self, data):
756 754
757 755 raise NotImplementedError
758 756
759 757 def __convolutionInTime(self, data):
760 758
761 759 code = self.code[self.__profIndex]
762 760 for i in range(self.__nChannels):
763 761 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
764 762
765 763 return self.datadecTime
766 764
767 765 def __convolutionByBlockInTime(self, data):
768 766
769 767 repetitions = int(self.__nProfiles / self.nCode)
770 768 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
771 769 junk = junk.flatten()
772 770 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
773 771 profilesList = range(self.__nProfiles)
774 772
775 773 for i in range(self.__nChannels):
776 774 for j in profilesList:
777 775 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
778 776 return self.datadecTime
779 777
780 778 def __convolutionByBlockInFreq(self, data):
781 779
782 780 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
783 781
784 782
785 783 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
786 784
787 785 fft_data = numpy.fft.fft(data, axis=2)
788 786
789 787 conv = fft_data*fft_code
790 788
791 789 data = numpy.fft.ifft(conv,axis=2)
792 790
793 791 return data
794 792
795 793
796 794 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
797 795
798 796 if dataOut.flagDecodeData:
799 797 print("This data is already decoded, recoding again ...")
800 798
801 799 if not self.isConfig:
802 800
803 801 if code is None:
804 802 if dataOut.code is None:
805 803 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
806 804
807 805 code = dataOut.code
808 806 else:
809 807 code = numpy.array(code).reshape(nCode,nBaud)
810 808 self.setup(code, osamp, dataOut)
811 809
812 810 self.isConfig = True
813 811
814 812 if mode == 3:
815 813 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
816 814
817 815 if times != None:
818 816 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
819 817
820 818 if self.code is None:
821 819 print("Fail decoding: Code is not defined.")
822 820 return
823 821
824 822 self.__nProfiles = dataOut.nProfiles
825 823 datadec = None
826 824
827 825 if mode == 3:
828 826 mode = 0
829 827
830 828 if dataOut.flagDataAsBlock:
831 829 """
832 830 Decoding when data have been read as block,
833 831 """
834 832
835 833 if mode == 0:
836 834 datadec = self.__convolutionByBlockInTime(dataOut.data)
837 835 if mode == 1:
838 836 datadec = self.__convolutionByBlockInFreq(dataOut.data)
839 837 else:
840 838 """
841 839 Decoding when data have been read profile by profile
842 840 """
843 841 if mode == 0:
844 842 datadec = self.__convolutionInTime(dataOut.data)
845 843
846 844 if mode == 1:
847 845 datadec = self.__convolutionInFreq(dataOut.data)
848 846
849 847 if mode == 2:
850 848 datadec = self.__convolutionInFreqOpt(dataOut.data)
851 849
852 850 if datadec is None:
853 851 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
854 852
855 853 dataOut.code = self.code
856 854 dataOut.nCode = self.nCode
857 855 dataOut.nBaud = self.nBaud
858 856
859 857 dataOut.data = datadec
860 858 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
861 859
862 860 dataOut.flagDecodeData = True #asumo q la data esta decodificada
863 861
864 862 if self.__profIndex == self.nCode-1:
865 863 self.__profIndex = 0
866 864 return dataOut
867 865
868 866 self.__profIndex += 1
869 867
870 868 return dataOut
871 869
872 870
873 871 class ProfileConcat(Operation):
874 872
875 873 isConfig = False
876 874 buffer = None
877 875
878 876 def __init__(self, **kwargs):
879 877
880 878 Operation.__init__(self, **kwargs)
881 879 self.profileIndex = 0
882 880
883 881 def reset(self):
884 882 self.buffer = numpy.zeros_like(self.buffer)
885 883 self.start_index = 0
886 884 self.times = 1
887 885
888 886 def setup(self, data, m, n=1):
889 887 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
890 888 self.nHeights = data.shape[1]#.nHeights
891 889 self.start_index = 0
892 890 self.times = 1
893 891
894 892 def concat(self, data):
895 893
896 894 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
897 895 self.start_index = self.start_index + self.nHeights
898 896
899 897 def run(self, dataOut, m):
900 898 dataOut.flagNoData = True
901 899
902 900 if not self.isConfig:
903 901 self.setup(dataOut.data, m, 1)
904 902 self.isConfig = True
905 903
906 904 if dataOut.flagDataAsBlock:
907 905 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
908 906
909 907 else:
910 908 self.concat(dataOut.data)
911 909 self.times += 1
912 910 if self.times > m:
913 911 dataOut.data = self.buffer
914 912 self.reset()
915 913 dataOut.flagNoData = False
916 914 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
917 915 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
918 916 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
919 917 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
920 918 dataOut.ippSeconds *= m
921 919 return dataOut
922 920
923 921 class ProfileSelector(Operation):
924 922
925 923 profileIndex = None
926 924 # Tamanho total de los perfiles
927 925 nProfiles = None
928 926
929 927 def __init__(self, **kwargs):
930 928
931 929 Operation.__init__(self, **kwargs)
932 930 self.profileIndex = 0
933 931
934 932 def incProfileIndex(self):
935 933
936 934 self.profileIndex += 1
937 935
938 936 if self.profileIndex >= self.nProfiles:
939 937 self.profileIndex = 0
940 938
941 939 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
942 940
943 941 if profileIndex < minIndex:
944 942 return False
945 943
946 944 if profileIndex > maxIndex:
947 945 return False
948 946
949 947 return True
950 948
951 949 def isThisProfileInList(self, profileIndex, profileList):
952 950
953 951 if profileIndex not in profileList:
954 952 return False
955 953
956 954 return True
957 955
958 956 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
959 957
960 958 """
961 959 ProfileSelector:
962 960
963 961 Inputs:
964 962 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
965 963
966 964 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
967 965
968 966 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
969 967
970 968 """
971 969
972 970 if rangeList is not None:
973 971 if type(rangeList[0]) not in (tuple, list):
974 972 rangeList = [rangeList]
975 973
976 974 dataOut.flagNoData = True
977 975
978 976 if dataOut.flagDataAsBlock:
979 977 """
980 978 data dimension = [nChannels, nProfiles, nHeis]
981 979 """
982 980 if profileList != None:
983 981 dataOut.data = dataOut.data[:,profileList,:]
984 982
985 983 if profileRangeList != None:
986 984 minIndex = profileRangeList[0]
987 985 maxIndex = profileRangeList[1]
988 986 profileList = list(range(minIndex, maxIndex+1))
989 987
990 988 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
991 989
992 990 if rangeList != None:
993 991
994 992 profileList = []
995 993
996 994 for thisRange in rangeList:
997 995 minIndex = thisRange[0]
998 996 maxIndex = thisRange[1]
999 997
1000 998 profileList.extend(list(range(minIndex, maxIndex+1)))
1001 999
1002 1000 dataOut.data = dataOut.data[:,profileList,:]
1003 1001
1004 1002 dataOut.nProfiles = len(profileList)
1005 1003 dataOut.profileIndex = dataOut.nProfiles - 1
1006 1004 dataOut.flagNoData = False
1007 1005
1008 1006 return dataOut
1009 1007
1010 1008 """
1011 1009 data dimension = [nChannels, nHeis]
1012 1010 """
1013 1011
1014 1012 if profileList != None:
1015 1013
1016 1014 if self.isThisProfileInList(dataOut.profileIndex, profileList):
1017 1015
1018 1016 self.nProfiles = len(profileList)
1019 1017 dataOut.nProfiles = self.nProfiles
1020 1018 dataOut.profileIndex = self.profileIndex
1021 1019 dataOut.flagNoData = False
1022 1020
1023 1021 self.incProfileIndex()
1024 1022 return dataOut
1025 1023
1026 1024 if profileRangeList != None:
1027 1025
1028 1026 minIndex = profileRangeList[0]
1029 1027 maxIndex = profileRangeList[1]
1030 1028
1031 1029 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1032 1030
1033 1031 self.nProfiles = maxIndex - minIndex + 1
1034 1032 dataOut.nProfiles = self.nProfiles
1035 1033 dataOut.profileIndex = self.profileIndex
1036 1034 dataOut.flagNoData = False
1037 1035
1038 1036 self.incProfileIndex()
1039 1037 return dataOut
1040 1038
1041 1039 if rangeList != None:
1042 1040
1043 1041 nProfiles = 0
1044 1042
1045 1043 for thisRange in rangeList:
1046 1044 minIndex = thisRange[0]
1047 1045 maxIndex = thisRange[1]
1048 1046
1049 1047 nProfiles += maxIndex - minIndex + 1
1050 1048
1051 1049 for thisRange in rangeList:
1052 1050
1053 1051 minIndex = thisRange[0]
1054 1052 maxIndex = thisRange[1]
1055 1053
1056 1054 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1057 1055
1058 1056 self.nProfiles = nProfiles
1059 1057 dataOut.nProfiles = self.nProfiles
1060 1058 dataOut.profileIndex = self.profileIndex
1061 1059 dataOut.flagNoData = False
1062 1060
1063 1061 self.incProfileIndex()
1064 1062
1065 1063 break
1066 1064
1067 1065 return dataOut
1068 1066
1069 1067
1070 1068 if beam != None: #beam is only for AMISR data
1071 1069 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
1072 1070 dataOut.flagNoData = False
1073 1071 dataOut.profileIndex = self.profileIndex
1074 1072
1075 1073 self.incProfileIndex()
1076 1074
1077 1075 return dataOut
1078 1076
1079 1077 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
1080 1078
1081 1079
1082 1080 class Reshaper(Operation):
1083 1081
1084 1082 def __init__(self, **kwargs):
1085 1083
1086 1084 Operation.__init__(self, **kwargs)
1087 1085
1088 1086 self.__buffer = None
1089 1087 self.__nitems = 0
1090 1088
1091 1089 def __appendProfile(self, dataOut, nTxs):
1092 1090
1093 1091 if self.__buffer is None:
1094 1092 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
1095 1093 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
1096 1094
1097 1095 ini = dataOut.nHeights * self.__nitems
1098 1096 end = ini + dataOut.nHeights
1099 1097
1100 1098 self.__buffer[:, ini:end] = dataOut.data
1101 1099
1102 1100 self.__nitems += 1
1103 1101
1104 1102 return int(self.__nitems*nTxs)
1105 1103
1106 1104 def __getBuffer(self):
1107 1105
1108 1106 if self.__nitems == int(1./self.__nTxs):
1109 1107
1110 1108 self.__nitems = 0
1111 1109
1112 1110 return self.__buffer.copy()
1113 1111
1114 1112 return None
1115 1113
1116 1114 def __checkInputs(self, dataOut, shape, nTxs):
1117 1115
1118 1116 if shape is None and nTxs is None:
1119 1117 raise ValueError("Reshaper: shape of factor should be defined")
1120 1118
1121 1119 if nTxs:
1122 1120 if nTxs < 0:
1123 1121 raise ValueError("nTxs should be greater than 0")
1124 1122
1125 1123 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1126 1124 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
1127 1125
1128 1126 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1129 1127
1130 1128 return shape, nTxs
1131 1129
1132 1130 if len(shape) != 2 and len(shape) != 3:
1133 1131 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))
1134 1132
1135 1133 if len(shape) == 2:
1136 1134 shape_tuple = [dataOut.nChannels]
1137 1135 shape_tuple.extend(shape)
1138 1136 else:
1139 1137 shape_tuple = list(shape)
1140 1138
1141 1139 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1142 1140
1143 1141 return shape_tuple, nTxs
1144 1142
1145 1143 def run(self, dataOut, shape=None, nTxs=None):
1146 1144
1147 1145 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1148 1146
1149 1147 dataOut.flagNoData = True
1150 1148 profileIndex = None
1151 1149
1152 1150 if dataOut.flagDataAsBlock:
1153 1151
1154 1152 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1155 1153 dataOut.flagNoData = False
1156 1154
1157 1155 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1158 1156
1159 1157 else:
1160 1158
1161 1159 if self.__nTxs < 1:
1162 1160
1163 1161 self.__appendProfile(dataOut, self.__nTxs)
1164 1162 new_data = self.__getBuffer()
1165 1163
1166 1164 if new_data is not None:
1167 1165 dataOut.data = new_data
1168 1166 dataOut.flagNoData = False
1169 1167
1170 1168 profileIndex = dataOut.profileIndex*nTxs
1171 1169
1172 1170 else:
1173 1171 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
1174 1172
1175 1173 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1176 1174
1177 1175 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1178 1176
1179 1177 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1180 1178
1181 1179 dataOut.profileIndex = profileIndex
1182 1180
1183 1181 dataOut.ippSeconds /= self.__nTxs
1184 1182
1185 1183 return dataOut
1186 1184
1187 1185 class SplitProfiles(Operation):
1188 1186
1189 1187 def __init__(self, **kwargs):
1190 1188
1191 1189 Operation.__init__(self, **kwargs)
1192 1190
1193 1191 def run(self, dataOut, n):
1194 1192
1195 1193 dataOut.flagNoData = True
1196 1194 profileIndex = None
1197 1195
1198 1196 if dataOut.flagDataAsBlock:
1199 1197
1200 1198 #nchannels, nprofiles, nsamples
1201 1199 shape = dataOut.data.shape
1202 1200
1203 1201 if shape[2] % n != 0:
1204 1202 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1205 1203
1206 1204 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1207 1205
1208 1206 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1209 1207 dataOut.flagNoData = False
1210 1208
1211 1209 profileIndex = int(dataOut.nProfiles/n) - 1
1212 1210
1213 1211 else:
1214 1212
1215 1213 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
1216 1214
1217 1215 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1218 1216
1219 1217 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1220 1218
1221 1219 dataOut.nProfiles = int(dataOut.nProfiles*n)
1222 1220
1223 1221 dataOut.profileIndex = profileIndex
1224 1222
1225 1223 dataOut.ippSeconds /= n
1226 1224
1227 1225 return dataOut
1228 1226
1229 1227 class CombineProfiles(Operation):
1230 1228 def __init__(self, **kwargs):
1231 1229
1232 1230 Operation.__init__(self, **kwargs)
1233 1231
1234 1232 self.__remData = None
1235 1233 self.__profileIndex = 0
1236 1234
1237 1235 def run(self, dataOut, n):
1238 1236
1239 1237 dataOut.flagNoData = True
1240 1238 profileIndex = None
1241 1239
1242 1240 if dataOut.flagDataAsBlock:
1243 1241
1244 1242 #nchannels, nprofiles, nsamples
1245 1243 shape = dataOut.data.shape
1246 1244 new_shape = shape[0], shape[1]/n, shape[2]*n
1247 1245
1248 1246 if shape[1] % n != 0:
1249 1247 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
1250 1248
1251 1249 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1252 1250 dataOut.flagNoData = False
1253 1251
1254 1252 profileIndex = int(dataOut.nProfiles*n) - 1
1255 1253
1256 1254 else:
1257 1255
1258 1256 #nchannels, nsamples
1259 1257 if self.__remData is None:
1260 1258 newData = dataOut.data
1261 1259 else:
1262 1260 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1263 1261
1264 1262 self.__profileIndex += 1
1265 1263
1266 1264 if self.__profileIndex < n:
1267 1265 self.__remData = newData
1268 1266 #continue
1269 1267 return
1270 1268
1271 1269 self.__profileIndex = 0
1272 1270 self.__remData = None
1273 1271
1274 1272 dataOut.data = newData
1275 1273 dataOut.flagNoData = False
1276 1274
1277 1275 profileIndex = dataOut.profileIndex/n
1278 1276
1279 1277
1280 1278 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1281 1279
1282 1280 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1283 1281
1284 1282 dataOut.nProfiles = int(dataOut.nProfiles/n)
1285 1283
1286 1284 dataOut.profileIndex = profileIndex
1287 1285
1288 1286 dataOut.ippSeconds *= n
1289 1287
1290 1288 return dataOut
1291 1289
1292 1290 class PulsePairVoltage(Operation):
1293 1291 '''
1294 1292 Function PulsePair(Signal Power, Velocity)
1295 1293 The real component of Lag[0] provides Intensity Information
1296 1294 The imag component of Lag[1] Phase provides Velocity Information
1297 1295
1298 1296 Configuration Parameters:
1299 1297 nPRF = Number of Several PRF
1300 1298 theta = Degree Azimuth angel Boundaries
1301 1299
1302 1300 Input:
1303 1301 self.dataOut
1304 1302 lag[N]
1305 1303 Affected:
1306 1304 self.dataOut.spc
1307 1305 '''
1308 1306 isConfig = False
1309 1307 __profIndex = 0
1310 1308 __initime = None
1311 1309 __lastdatatime = None
1312 1310 __buffer = None
1313 1311 noise = None
1314 1312 __dataReady = False
1315 1313 n = None
1316 1314 __nch = 0
1317 1315 __nHeis = 0
1318 1316 removeDC = False
1319 1317 ipp = None
1320 1318 lambda_ = 0
1321 1319
1322 1320 def __init__(self,**kwargs):
1323 1321 Operation.__init__(self,**kwargs)
1324 1322
1325 1323 def setup(self, dataOut, n = None, removeDC=False):
1326 1324 '''
1327 1325 n= Numero de PRF's de entrada
1328 1326 '''
1329 1327 self.__initime = None
1330 1328 self.__lastdatatime = 0
1331 1329 self.__dataReady = False
1332 1330 self.__buffer = 0
1333 1331 self.__profIndex = 0
1334 1332 self.noise = None
1335 1333 self.__nch = dataOut.nChannels
1336 1334 self.__nHeis = dataOut.nHeights
1337 1335 self.removeDC = removeDC
1338 1336 self.lambda_ = 3.0e8/(9345.0e6)
1339 1337 self.ippSec = dataOut.ippSeconds
1340 1338 self.nCohInt = dataOut.nCohInt
1341 1339 print("IPPseconds",dataOut.ippSeconds)
1342 1340
1343 1341 print("ELVALOR DE n es:", n)
1344 1342 if n == None:
1345 1343 raise ValueError("n should be specified.")
1346 1344
1347 1345 if n != None:
1348 1346 if n<2:
1349 1347 raise ValueError("n should be greater than 2")
1350 1348
1351 1349 self.n = n
1352 1350 self.__nProf = n
1353 1351
1354 1352 self.__buffer = numpy.zeros((dataOut.nChannels,
1355 1353 n,
1356 1354 dataOut.nHeights),
1357 1355 dtype='complex')
1358 1356
1359 1357 def putData(self,data):
1360 1358 '''
1361 1359 Add a profile to he __buffer and increase in one the __profiel Index
1362 1360 '''
1363 1361 self.__buffer[:,self.__profIndex,:]= data
1364 1362 self.__profIndex += 1
1365 1363 return
1366 1364
1367 1365 def pushData(self,dataOut):
1368 1366 '''
1369 1367 Return the PULSEPAIR and the profiles used in the operation
1370 1368 Affected : self.__profileIndex
1371 1369 '''
1372 1370 #----------------- Remove DC-----------------------------------
1373 1371 if self.removeDC==True:
1374 1372 mean = numpy.mean(self.__buffer,1)
1375 1373 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1376 1374 dc= numpy.tile(tmp,[1,self.__nProf,1])
1377 1375 self.__buffer = self.__buffer - dc
1378 1376 #------------------Calculo de Potencia ------------------------
1379 1377 pair0 = self.__buffer*numpy.conj(self.__buffer)
1380 1378 pair0 = pair0.real
1381 1379 lag_0 = numpy.sum(pair0,1)
1382 1380 #------------------Calculo de Ruido x canal--------------------
1383 1381 self.noise = numpy.zeros(self.__nch)
1384 1382 for i in range(self.__nch):
1385 1383 daux = numpy.sort(pair0[i,:,:],axis= None)
1386 1384 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1387 1385
1388 1386 self.noise = self.noise.reshape(self.__nch,1)
1389 1387 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1390 1388 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1391 1389 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1392 1390 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1393 1391 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1394 1392 #-------------------- Power --------------------------------------------------
1395 1393 data_power = lag_0/(self.n*self.nCohInt)
1396 1394 #------------------ Senal ---------------------------------------------------
1397 1395 data_intensity = pair0 - noise_buffer
1398 1396 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1399 1397 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1400 1398 for i in range(self.__nch):
1401 1399 for j in range(self.__nHeis):
1402 1400 if data_intensity[i][j] < 0:
1403 1401 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1404 1402
1405 1403 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1406 1404 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1407 1405 lag_1 = numpy.sum(pair1,1)
1408 1406 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1409 1407 data_velocity = (self.lambda_/2.0)*data_freq
1410 1408
1411 1409 #---------------- Potencia promedio estimada de la Senal-----------
1412 1410 lag_0 = lag_0/self.n
1413 1411 S = lag_0-self.noise
1414 1412
1415 1413 #---------------- Frecuencia Doppler promedio ---------------------
1416 1414 lag_1 = lag_1/(self.n-1)
1417 1415 R1 = numpy.abs(lag_1)
1418 1416
1419 1417 #---------------- Calculo del SNR----------------------------------
1420 1418 data_snrPP = S/self.noise
1421 1419 for i in range(self.__nch):
1422 1420 for j in range(self.__nHeis):
1423 1421 if data_snrPP[i][j] < 1.e-20:
1424 1422 data_snrPP[i][j] = 1.e-20
1425 1423
1426 1424 #----------------- Calculo del ancho espectral ----------------------
1427 1425 L = S/R1
1428 1426 L = numpy.where(L<0,1,L)
1429 1427 L = numpy.log(L)
1430 1428 tmp = numpy.sqrt(numpy.absolute(L))
1431 1429 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1432 1430 n = self.__profIndex
1433 1431
1434 1432 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1435 1433 self.__profIndex = 0
1436 1434 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,n
1437 1435
1438 1436
1439 1437 def pulsePairbyProfiles(self,dataOut):
1440 1438
1441 1439 self.__dataReady = False
1442 1440 data_power = None
1443 1441 data_intensity = None
1444 1442 data_velocity = None
1445 1443 data_specwidth = None
1446 1444 data_snrPP = None
1447 1445 self.putData(data=dataOut.data)
1448 1446 if self.__profIndex == self.n:
1449 1447 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth, n = self.pushData(dataOut=dataOut)
1450 1448 self.__dataReady = True
1451 1449
1452 1450 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth
1453 1451
1454 1452
1455 1453 def pulsePairOp(self, dataOut, datatime= None):
1456 1454
1457 1455 if self.__initime == None:
1458 1456 self.__initime = datatime
1459 1457 data_power, data_intensity, data_velocity, data_snrPP, data_specwidth = self.pulsePairbyProfiles(dataOut)
1460 1458 self.__lastdatatime = datatime
1461 1459
1462 1460 if data_power is None:
1463 1461 return None, None, None,None,None,None
1464 1462
1465 1463 avgdatatime = self.__initime
1466 1464 deltatime = datatime - self.__lastdatatime
1467 1465 self.__initime = datatime
1468 1466
1469 1467 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, avgdatatime
1470 1468
1471 1469 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1472 1470
1473 1471 if not self.isConfig:
1474 1472 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1475 1473 self.isConfig = True
1476 1474 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth, avgdatatime = self.pulsePairOp(dataOut, dataOut.utctime)
1477 1475 dataOut.flagNoData = True
1478 1476
1479 1477 if self.__dataReady:
1480 1478 dataOut.nCohInt *= self.n
1481 1479 dataOut.dataPP_POW = data_intensity # S
1482 1480 dataOut.dataPP_POWER = data_power # P
1483 1481 dataOut.dataPP_DOP = data_velocity
1484 1482 dataOut.dataPP_SNR = data_snrPP
1485 1483 dataOut.dataPP_WIDTH = data_specwidth
1486 1484 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1487 1485 dataOut.utctime = avgdatatime
1488 1486 dataOut.flagNoData = False
1489 1487 return dataOut
1490 1488
1491 1489
1492 1490
1493 1491 # import collections
1494 1492 # from scipy.stats import mode
1495 1493 #
1496 1494 # class Synchronize(Operation):
1497 1495 #
1498 1496 # isConfig = False
1499 1497 # __profIndex = 0
1500 1498 #
1501 1499 # def __init__(self, **kwargs):
1502 1500 #
1503 1501 # Operation.__init__(self, **kwargs)
1504 1502 # # self.isConfig = False
1505 1503 # self.__powBuffer = None
1506 1504 # self.__startIndex = 0
1507 1505 # self.__pulseFound = False
1508 1506 #
1509 1507 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1510 1508 #
1511 1509 # #Read data
1512 1510 #
1513 1511 # powerdB = dataOut.getPower(channel = channel)
1514 1512 # noisedB = dataOut.getNoise(channel = channel)[0]
1515 1513 #
1516 1514 # self.__powBuffer.extend(powerdB.flatten())
1517 1515 #
1518 1516 # dataArray = numpy.array(self.__powBuffer)
1519 1517 #
1520 1518 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1521 1519 #
1522 1520 # maxValue = numpy.nanmax(filteredPower)
1523 1521 #
1524 1522 # if maxValue < noisedB + 10:
1525 1523 # #No se encuentra ningun pulso de transmision
1526 1524 # return None
1527 1525 #
1528 1526 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1529 1527 #
1530 1528 # if len(maxValuesIndex) < 2:
1531 1529 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1532 1530 # return None
1533 1531 #
1534 1532 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1535 1533 #
1536 1534 # #Seleccionar solo valores con un espaciamiento de nSamples
1537 1535 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1538 1536 #
1539 1537 # if len(pulseIndex) < 2:
1540 1538 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1541 1539 # return None
1542 1540 #
1543 1541 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1544 1542 #
1545 1543 # #remover senales que se distancien menos de 10 unidades o muestras
1546 1544 # #(No deberian existir IPP menor a 10 unidades)
1547 1545 #
1548 1546 # realIndex = numpy.where(spacing > 10 )[0]
1549 1547 #
1550 1548 # if len(realIndex) < 2:
1551 1549 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1552 1550 # return None
1553 1551 #
1554 1552 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1555 1553 # realPulseIndex = pulseIndex[realIndex]
1556 1554 #
1557 1555 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1558 1556 #
1559 1557 # print "IPP = %d samples" %period
1560 1558 #
1561 1559 # self.__newNSamples = dataOut.nHeights #int(period)
1562 1560 # self.__startIndex = int(realPulseIndex[0])
1563 1561 #
1564 1562 # return 1
1565 1563 #
1566 1564 #
1567 1565 # def setup(self, nSamples, nChannels, buffer_size = 4):
1568 1566 #
1569 1567 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1570 1568 # maxlen = buffer_size*nSamples)
1571 1569 #
1572 1570 # bufferList = []
1573 1571 #
1574 1572 # for i in range(nChannels):
1575 1573 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1576 1574 # maxlen = buffer_size*nSamples)
1577 1575 #
1578 1576 # bufferList.append(bufferByChannel)
1579 1577 #
1580 1578 # self.__nSamples = nSamples
1581 1579 # self.__nChannels = nChannels
1582 1580 # self.__bufferList = bufferList
1583 1581 #
1584 1582 # def run(self, dataOut, channel = 0):
1585 1583 #
1586 1584 # if not self.isConfig:
1587 1585 # nSamples = dataOut.nHeights
1588 1586 # nChannels = dataOut.nChannels
1589 1587 # self.setup(nSamples, nChannels)
1590 1588 # self.isConfig = True
1591 1589 #
1592 1590 # #Append new data to internal buffer
1593 1591 # for thisChannel in range(self.__nChannels):
1594 1592 # bufferByChannel = self.__bufferList[thisChannel]
1595 1593 # bufferByChannel.extend(dataOut.data[thisChannel])
1596 1594 #
1597 1595 # if self.__pulseFound:
1598 1596 # self.__startIndex -= self.__nSamples
1599 1597 #
1600 1598 # #Finding Tx Pulse
1601 1599 # if not self.__pulseFound:
1602 1600 # indexFound = self.__findTxPulse(dataOut, channel)
1603 1601 #
1604 1602 # if indexFound == None:
1605 1603 # dataOut.flagNoData = True
1606 1604 # return
1607 1605 #
1608 1606 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1609 1607 # self.__pulseFound = True
1610 1608 # self.__startIndex = indexFound
1611 1609 #
1612 1610 # #If pulse was found ...
1613 1611 # for thisChannel in range(self.__nChannels):
1614 1612 # bufferByChannel = self.__bufferList[thisChannel]
1615 1613 # #print self.__startIndex
1616 1614 # x = numpy.array(bufferByChannel)
1617 1615 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1618 1616 #
1619 1617 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1620 1618 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1621 1619 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1622 1620 #
1623 1621 # dataOut.data = self.__arrayBuffer
1624 1622 #
1625 1623 # self.__startIndex += self.__newNSamples
1626 1624 #
1627 1625 # return No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now