##// END OF EJS Templates
Update de WR-Project
avaldez -
r1282:f590e95f1fbc
parent child
Show More
@@ -1,1372 +1,1372
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 5 '''
6 6
7 7 import copy
8 8 import numpy
9 9 import datetime
10 10 import json
11 11
12 12 from schainpy.utils import log
13 13 from .jroheaderIO import SystemHeader, RadarControllerHeader
14 14
15 15
16 16 def getNumpyDtype(dataTypeCode):
17 17
18 18 if dataTypeCode == 0:
19 19 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
20 20 elif dataTypeCode == 1:
21 21 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
22 22 elif dataTypeCode == 2:
23 23 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
24 24 elif dataTypeCode == 3:
25 25 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
26 26 elif dataTypeCode == 4:
27 27 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
28 28 elif dataTypeCode == 5:
29 29 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
30 30 else:
31 31 raise ValueError('dataTypeCode was not defined')
32 32
33 33 return numpyDtype
34 34
35 35
36 36 def getDataTypeCode(numpyDtype):
37 37
38 38 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
39 39 datatype = 0
40 40 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
41 41 datatype = 1
42 42 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
43 43 datatype = 2
44 44 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
45 45 datatype = 3
46 46 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
47 47 datatype = 4
48 48 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
49 49 datatype = 5
50 50 else:
51 51 datatype = None
52 52
53 53 return datatype
54 54
55 55
56 56 def hildebrand_sekhon(data, navg):
57 57 """
58 58 This method is for the objective determination of the noise level in Doppler spectra. This
59 59 implementation technique is based on the fact that the standard deviation of the spectral
60 60 densities is equal to the mean spectral density for white Gaussian noise
61 61
62 62 Inputs:
63 63 Data : heights
64 64 navg : numbers of averages
65 65
66 66 Return:
67 67 mean : noise's level
68 68 """
69 69
70 70 sortdata = numpy.sort(data, axis=None)
71 71 lenOfData = len(sortdata)
72 72 nums_min = lenOfData*0.2
73 73
74 74 if nums_min <= 5:
75 75
76 76 nums_min = 5
77 77
78 78 sump = 0.
79 79 sumq = 0.
80 80
81 81 j = 0
82 82 cont = 1
83 83
84 84 while((cont == 1)and(j < lenOfData)):
85 85
86 86 sump += sortdata[j]
87 87 sumq += sortdata[j]**2
88 88
89 89 if j > nums_min:
90 90 rtest = float(j)/(j-1) + 1.0/navg
91 91 if ((sumq*j) > (rtest*sump**2)):
92 92 j = j - 1
93 93 sump = sump - sortdata[j]
94 94 sumq = sumq - sortdata[j]**2
95 95 cont = 0
96 96
97 97 j += 1
98 98
99 99 lnoise = sump / j
100 100
101 101 return lnoise
102 102
103 103
104 104 class Beam:
105 105
106 106 def __init__(self):
107 107 self.codeList = []
108 108 self.azimuthList = []
109 109 self.zenithList = []
110 110
111 111
112 112 class GenericData(object):
113 113
114 114 flagNoData = True
115 115
116 116 def copy(self, inputObj=None):
117 117
118 118 if inputObj == None:
119 119 return copy.deepcopy(self)
120 120
121 121 for key in list(inputObj.__dict__.keys()):
122 122
123 123 attribute = inputObj.__dict__[key]
124 124
125 125 # If this attribute is a tuple or list
126 126 if type(inputObj.__dict__[key]) in (tuple, list):
127 127 self.__dict__[key] = attribute[:]
128 128 continue
129 129
130 130 # If this attribute is another object or instance
131 131 if hasattr(attribute, '__dict__'):
132 132 self.__dict__[key] = attribute.copy()
133 133 continue
134 134
135 135 self.__dict__[key] = inputObj.__dict__[key]
136 136
137 137 def deepcopy(self):
138 138
139 139 return copy.deepcopy(self)
140 140
141 141 def isEmpty(self):
142 142
143 143 return self.flagNoData
144 144
145 145
146 146 class JROData(GenericData):
147 147
148 148 # m_BasicHeader = BasicHeader()
149 149 # m_ProcessingHeader = ProcessingHeader()
150 150
151 151 systemHeaderObj = SystemHeader()
152 152 radarControllerHeaderObj = RadarControllerHeader()
153 153 # data = None
154 154 type = None
155 155 datatype = None # dtype but in string
156 156 # dtype = None
157 157 # nChannels = None
158 158 # nHeights = None
159 159 nProfiles = None
160 160 heightList = None
161 161 channelList = None
162 162 flagDiscontinuousBlock = False
163 163 useLocalTime = False
164 164 utctime = None
165 165 timeZone = None
166 166 dstFlag = None
167 167 errorCount = None
168 168 blocksize = None
169 169 # nCode = None
170 170 # nBaud = None
171 171 # code = None
172 172 flagDecodeData = False # asumo q la data no esta decodificada
173 173 flagDeflipData = False # asumo q la data no esta sin flip
174 174 flagShiftFFT = False
175 175 # ippSeconds = None
176 176 # timeInterval = None
177 177 nCohInt = None
178 178 # noise = None
179 179 windowOfFilter = 1
180 180 # Speed of ligth
181 181 C = 3e8
182 182 frequency = 49.92e6
183 183 realtime = False
184 184 beacon_heiIndexList = None
185 185 last_block = None
186 186 blocknow = None
187 187 azimuth = None
188 188 zenith = None
189 189 beam = Beam()
190 190 profileIndex = None
191 191 error = None
192 192 data = None
193 193 nmodes = None
194 194
195 195 def __str__(self):
196 196
197 197 return '{} - {}'.format(self.type, self.getDatatime())
198 198
199 199 def getNoise(self):
200 200
201 201 raise NotImplementedError
202 202
203 203 def getNChannels(self):
204 204
205 205 return len(self.channelList)
206 206
207 207 def getChannelIndexList(self):
208 208
209 209 return list(range(self.nChannels))
210 210
211 211 def getNHeights(self):
212 212
213 213 return len(self.heightList)
214 214
215 215 def getHeiRange(self, extrapoints=0):
216 216
217 217 heis = self.heightList
218 218 # deltah = self.heightList[1] - self.heightList[0]
219 219 #
220 220 # heis.append(self.heightList[-1])
221 221
222 222 return heis
223 223
224 224 def getDeltaH(self):
225 225
226 226 delta = self.heightList[1] - self.heightList[0]
227 227
228 228 return delta
229 229
230 230 def getltctime(self):
231 231
232 232 if self.useLocalTime:
233 233 return self.utctime - self.timeZone * 60
234 234
235 235 return self.utctime
236 236
237 237 def getDatatime(self):
238 238
239 239 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
240 240 return datatimeValue
241 241
242 242 def getTimeRange(self):
243 243
244 244 datatime = []
245 245
246 246 datatime.append(self.ltctime)
247 247 datatime.append(self.ltctime + self.timeInterval + 1)
248 248
249 249 datatime = numpy.array(datatime)
250 250
251 251 return datatime
252 252
253 253 def getFmaxTimeResponse(self):
254 254
255 255 period = (10**-6) * self.getDeltaH() / (0.15)
256 256
257 257 PRF = 1. / (period * self.nCohInt)
258 258
259 259 fmax = PRF
260 260
261 261 return fmax
262 262
263 263 def getFmax(self):
264 264 PRF = 1. / (self.ippSeconds * self.nCohInt)
265 265
266 266 fmax = PRF
267 267 return fmax
268 268
269 269 def getVmax(self):
270 270
271 271 _lambda = self.C / self.frequency
272 272
273 273 vmax = self.getFmax() * _lambda / 2
274 274
275 275 return vmax
276 276
277 277 def get_ippSeconds(self):
278 278 '''
279 279 '''
280 280 return self.radarControllerHeaderObj.ippSeconds
281 281
282 282 def set_ippSeconds(self, ippSeconds):
283 283 '''
284 284 '''
285 285
286 286 self.radarControllerHeaderObj.ippSeconds = ippSeconds
287 287
288 288 return
289 289
290 290 def get_dtype(self):
291 291 '''
292 292 '''
293 293 return getNumpyDtype(self.datatype)
294 294
295 295 def set_dtype(self, numpyDtype):
296 296 '''
297 297 '''
298 298
299 299 self.datatype = getDataTypeCode(numpyDtype)
300 300
301 301 def get_code(self):
302 302 '''
303 303 '''
304 304 return self.radarControllerHeaderObj.code
305 305
306 306 def set_code(self, code):
307 307 '''
308 308 '''
309 309 self.radarControllerHeaderObj.code = code
310 310
311 311 return
312 312
313 313 def get_ncode(self):
314 314 '''
315 315 '''
316 316 return self.radarControllerHeaderObj.nCode
317 317
318 318 def set_ncode(self, nCode):
319 319 '''
320 320 '''
321 321 self.radarControllerHeaderObj.nCode = nCode
322 322
323 323 return
324 324
325 325 def get_nbaud(self):
326 326 '''
327 327 '''
328 328 return self.radarControllerHeaderObj.nBaud
329 329
330 330 def set_nbaud(self, nBaud):
331 331 '''
332 332 '''
333 333 self.radarControllerHeaderObj.nBaud = nBaud
334 334
335 335 return
336 336
337 337 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
338 338 channelIndexList = property(
339 339 getChannelIndexList, "I'm the 'channelIndexList' property.")
340 340 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
341 341 #noise = property(getNoise, "I'm the 'nHeights' property.")
342 342 datatime = property(getDatatime, "I'm the 'datatime' property")
343 343 ltctime = property(getltctime, "I'm the 'ltctime' property")
344 344 ippSeconds = property(get_ippSeconds, set_ippSeconds)
345 345 dtype = property(get_dtype, set_dtype)
346 346 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
347 347 code = property(get_code, set_code)
348 348 nCode = property(get_ncode, set_ncode)
349 349 nBaud = property(get_nbaud, set_nbaud)
350 350
351 351
352 352 class Voltage(JROData):
353 353
354 354 # data es un numpy array de 2 dmensiones (canales, alturas)
355 355 data = None
356 356
357 357 def __init__(self):
358 358 '''
359 359 Constructor
360 360 '''
361 361
362 362 self.useLocalTime = True
363 363 self.radarControllerHeaderObj = RadarControllerHeader()
364 364 self.systemHeaderObj = SystemHeader()
365 365 self.type = "Voltage"
366 366 self.data = None
367 367 # self.dtype = None
368 368 # self.nChannels = 0
369 369 # self.nHeights = 0
370 370 self.nProfiles = None
371 371 self.heightList = None
372 372 self.channelList = None
373 373 # self.channelIndexList = None
374 374 self.flagNoData = True
375 375 self.flagDiscontinuousBlock = False
376 376 self.utctime = None
377 377 self.timeZone = None
378 378 self.dstFlag = None
379 379 self.errorCount = None
380 380 self.nCohInt = None
381 381 self.blocksize = None
382 382 self.flagDecodeData = False # asumo q la data no esta decodificada
383 383 self.flagDeflipData = False # asumo q la data no esta sin flip
384 384 self.flagShiftFFT = False
385 385 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
386 386 self.profileIndex = 0
387 387
388 388 def getNoisebyHildebrand(self, channel=None):
389 389 """
390 390 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
391 391
392 392 Return:
393 393 noiselevel
394 394 """
395 395
396 396 if channel != None:
397 397 data = self.data[channel]
398 398 nChannels = 1
399 399 else:
400 400 data = self.data
401 401 nChannels = self.nChannels
402 402
403 403 noise = numpy.zeros(nChannels)
404 404 power = data * numpy.conjugate(data)
405 405
406 406 for thisChannel in range(nChannels):
407 407 if nChannels == 1:
408 408 daux = power[:].real
409 409 else:
410 410 daux = power[thisChannel, :].real
411 411 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
412 412
413 413 return noise
414 414
415 415 def getNoise(self, type=1, channel=None):
416 416
417 417 if type == 1:
418 418 noise = self.getNoisebyHildebrand(channel)
419 419
420 420 return noise
421 421
422 422 def getPower(self, channel=None):
423 423
424 424 if channel != None:
425 425 data = self.data[channel]
426 426 else:
427 427 data = self.data
428 428
429 429 power = data * numpy.conjugate(data)
430 430 powerdB = 10 * numpy.log10(power.real)
431 431 powerdB = numpy.squeeze(powerdB)
432 432
433 433 return powerdB
434 434
435 435 def getTimeInterval(self):
436 436
437 437 timeInterval = self.ippSeconds * self.nCohInt
438 438
439 439 return timeInterval
440 440
441 441 noise = property(getNoise, "I'm the 'nHeights' property.")
442 442 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
443 443
444 444
445 445 class Spectra(JROData):
446 446
447 447 # data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
448 448 data_spc = None
449 449 # data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
450 450 data_cspc = None
451 451 # data dc es un numpy array de 2 dmensiones (canales, alturas)
452 452 data_dc = None
453 453 # data power
454 454 data_pwr = None
455 455 nFFTPoints = None
456 456 # nPairs = None
457 457 pairsList = None
458 458 nIncohInt = None
459 459 wavelength = None # Necesario para cacular el rango de velocidad desde la frecuencia
460 460 nCohInt = None # se requiere para determinar el valor de timeInterval
461 461 ippFactor = None
462 462 profileIndex = 0
463 463 plotting = "spectra"
464 464
465 465 def __init__(self):
466 466 '''
467 467 Constructor
468 468 '''
469 469
470 470 self.useLocalTime = True
471 471 self.radarControllerHeaderObj = RadarControllerHeader()
472 472 self.systemHeaderObj = SystemHeader()
473 473 self.type = "Spectra"
474 474 # self.data = None
475 475 # self.dtype = None
476 476 # self.nChannels = 0
477 477 # self.nHeights = 0
478 478 self.nProfiles = None
479 479 self.heightList = None
480 480 self.channelList = None
481 481 # self.channelIndexList = None
482 482 self.pairsList = None
483 483 self.flagNoData = True
484 484 self.flagDiscontinuousBlock = False
485 485 self.utctime = None
486 486 self.nCohInt = None
487 487 self.nIncohInt = None
488 488 self.blocksize = None
489 489 self.nFFTPoints = None
490 490 self.wavelength = None
491 491 self.flagDecodeData = False # asumo q la data no esta decodificada
492 492 self.flagDeflipData = False # asumo q la data no esta sin flip
493 493 self.flagShiftFFT = False
494 494 self.ippFactor = 1
495 495 #self.noise = None
496 496 self.beacon_heiIndexList = []
497 497 self.noise_estimation = None
498 498
499 499 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
500 500 """
501 501 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
502 502
503 503 Return:
504 504 noiselevel
505 505 """
506 506
507 507 noise = numpy.zeros(self.nChannels)
508 508
509 509 for channel in range(self.nChannels):
510 510 daux = self.data_spc[channel,
511 511 xmin_index:xmax_index, ymin_index:ymax_index]
512 512 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
513 513
514 514 return noise
515 515
516 516 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
517 517
518 518 if self.noise_estimation is not None:
519 519 # this was estimated by getNoise Operation defined in jroproc_spectra.py
520 520 return self.noise_estimation
521 521 else:
522 522 noise = self.getNoisebyHildebrand(
523 523 xmin_index, xmax_index, ymin_index, ymax_index)
524 524 return noise
525 525
526 526 def getFreqRangeTimeResponse(self, extrapoints=0):
527 527
528 528 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
529 529 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
530 530
531 531 return freqrange
532 532
533 533 def getAcfRange(self, extrapoints=0):
534 534
535 535 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
536 536 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
537 537
538 538 return freqrange
539 539
540 540 def getFreqRange(self, extrapoints=0):
541 541
542 542 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
543 543 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
544 544
545 545 return freqrange
546 546
547 547 def getVelRange(self, extrapoints=0):
548 548
549 549 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
550 550 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
551
551
552 552 if self.nmodes:
553 553 return velrange/self.nmodes
554 554 else:
555 555 return velrange
556 556
557 557 def getNPairs(self):
558 558
559 559 return len(self.pairsList)
560 560
561 561 def getPairsIndexList(self):
562 562
563 563 return list(range(self.nPairs))
564 564
565 565 def getNormFactor(self):
566 566
567 567 pwcode = 1
568 568
569 569 if self.flagDecodeData:
570 570 pwcode = numpy.sum(self.code[0]**2)
571 571 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
572 572 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
573 573
574 574 return normFactor
575 575
576 576 def getFlagCspc(self):
577 577
578 578 if self.data_cspc is None:
579 579 return True
580 580
581 581 return False
582 582
583 583 def getFlagDc(self):
584 584
585 585 if self.data_dc is None:
586 586 return True
587 587
588 588 return False
589 589
590 590 def getTimeInterval(self):
591 591
592 592 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
593 593 if self.nmodes:
594 594 return self.nmodes*timeInterval
595 595 else:
596 596 return timeInterval
597 597
598 598 def getPower(self):
599 599
600 600 factor = self.normFactor
601 601 z = self.data_spc / factor
602 602 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
603 603 avg = numpy.average(z, axis=1)
604 604
605 605 return 10 * numpy.log10(avg)
606 606
607 607 def getCoherence(self, pairsList=None, phase=False):
608 608
609 609 z = []
610 610 if pairsList is None:
611 611 pairsIndexList = self.pairsIndexList
612 612 else:
613 613 pairsIndexList = []
614 614 for pair in pairsList:
615 615 if pair not in self.pairsList:
616 616 raise ValueError("Pair %s is not in dataOut.pairsList" % (
617 617 pair))
618 618 pairsIndexList.append(self.pairsList.index(pair))
619 619 for i in range(len(pairsIndexList)):
620 620 pair = self.pairsList[pairsIndexList[i]]
621 621 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
622 622 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
623 623 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
624 624 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
625 625 if phase:
626 626 data = numpy.arctan2(avgcoherenceComplex.imag,
627 627 avgcoherenceComplex.real) * 180 / numpy.pi
628 628 else:
629 629 data = numpy.abs(avgcoherenceComplex)
630 630
631 631 z.append(data)
632 632
633 633 return numpy.array(z)
634 634
635 635 def setValue(self, value):
636 636
637 637 print("This property should not be initialized")
638 638
639 639 return
640 640
641 641 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
642 642 pairsIndexList = property(
643 643 getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
644 644 normFactor = property(getNormFactor, setValue,
645 645 "I'm the 'getNormFactor' property.")
646 646 flag_cspc = property(getFlagCspc, setValue)
647 647 flag_dc = property(getFlagDc, setValue)
648 648 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
649 649 timeInterval = property(getTimeInterval, setValue,
650 650 "I'm the 'timeInterval' property")
651 651
652 652
653 653 class SpectraHeis(Spectra):
654 654
655 655 data_spc = None
656 656 data_cspc = None
657 657 data_dc = None
658 658 nFFTPoints = None
659 659 # nPairs = None
660 660 pairsList = None
661 661 nCohInt = None
662 662 nIncohInt = None
663 663
664 664 def __init__(self):
665 665
666 666 self.radarControllerHeaderObj = RadarControllerHeader()
667 667
668 668 self.systemHeaderObj = SystemHeader()
669 669
670 670 self.type = "SpectraHeis"
671 671
672 672 # self.dtype = None
673 673
674 674 # self.nChannels = 0
675 675
676 676 # self.nHeights = 0
677 677
678 678 self.nProfiles = None
679 679
680 680 self.heightList = None
681 681
682 682 self.channelList = None
683 683
684 684 # self.channelIndexList = None
685 685
686 686 self.flagNoData = True
687 687
688 688 self.flagDiscontinuousBlock = False
689 689
690 690 # self.nPairs = 0
691 691
692 692 self.utctime = None
693 693
694 694 self.blocksize = None
695 695
696 696 self.profileIndex = 0
697 697
698 698 self.nCohInt = 1
699 699
700 700 self.nIncohInt = 1
701 701
702 702 def getNormFactor(self):
703 703 pwcode = 1
704 704 if self.flagDecodeData:
705 705 pwcode = numpy.sum(self.code[0]**2)
706 706
707 707 normFactor = self.nIncohInt * self.nCohInt * pwcode
708 708
709 709 return normFactor
710 710
711 711 def getTimeInterval(self):
712 712
713 713 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
714 714
715 715 return timeInterval
716 716
717 717 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
718 718 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
719 719
720 720
721 721 class Fits(JROData):
722 722
723 723 heightList = None
724 724 channelList = None
725 725 flagNoData = True
726 726 flagDiscontinuousBlock = False
727 727 useLocalTime = False
728 728 utctime = None
729 729 timeZone = None
730 730 # ippSeconds = None
731 731 # timeInterval = None
732 732 nCohInt = None
733 733 nIncohInt = None
734 734 noise = None
735 735 windowOfFilter = 1
736 736 # Speed of ligth
737 737 C = 3e8
738 738 frequency = 49.92e6
739 739 realtime = False
740 740
741 741 def __init__(self):
742 742
743 743 self.type = "Fits"
744 744
745 745 self.nProfiles = None
746 746
747 747 self.heightList = None
748 748
749 749 self.channelList = None
750 750
751 751 # self.channelIndexList = None
752 752
753 753 self.flagNoData = True
754 754
755 755 self.utctime = None
756 756
757 757 self.nCohInt = 1
758 758
759 759 self.nIncohInt = 1
760 760
761 761 self.useLocalTime = True
762 762
763 763 self.profileIndex = 0
764 764
765 765 # self.utctime = None
766 766 # self.timeZone = None
767 767 # self.ltctime = None
768 768 # self.timeInterval = None
769 769 # self.header = None
770 770 # self.data_header = None
771 771 # self.data = None
772 772 # self.datatime = None
773 773 # self.flagNoData = False
774 774 # self.expName = ''
775 775 # self.nChannels = None
776 776 # self.nSamples = None
777 777 # self.dataBlocksPerFile = None
778 778 # self.comments = ''
779 779 #
780 780
781 781 def getltctime(self):
782 782
783 783 if self.useLocalTime:
784 784 return self.utctime - self.timeZone * 60
785 785
786 786 return self.utctime
787 787
788 788 def getDatatime(self):
789 789
790 790 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
791 791 return datatime
792 792
793 793 def getTimeRange(self):
794 794
795 795 datatime = []
796 796
797 797 datatime.append(self.ltctime)
798 798 datatime.append(self.ltctime + self.timeInterval)
799 799
800 800 datatime = numpy.array(datatime)
801 801
802 802 return datatime
803 803
804 804 def getHeiRange(self):
805 805
806 806 heis = self.heightList
807 807
808 808 return heis
809 809
810 810 def getNHeights(self):
811 811
812 812 return len(self.heightList)
813 813
814 814 def getNChannels(self):
815 815
816 816 return len(self.channelList)
817 817
818 818 def getChannelIndexList(self):
819 819
820 820 return list(range(self.nChannels))
821 821
822 822 def getNoise(self, type=1):
823 823
824 824 #noise = numpy.zeros(self.nChannels)
825 825
826 826 if type == 1:
827 827 noise = self.getNoisebyHildebrand()
828 828
829 829 if type == 2:
830 830 noise = self.getNoisebySort()
831 831
832 832 if type == 3:
833 833 noise = self.getNoisebyWindow()
834 834
835 835 return noise
836 836
837 837 def getTimeInterval(self):
838 838
839 839 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
840 840
841 841 return timeInterval
842 842
843 843 def get_ippSeconds(self):
844 844 '''
845 845 '''
846 846 return self.ipp_sec
847 847
848 848
849 849 datatime = property(getDatatime, "I'm the 'datatime' property")
850 850 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
851 851 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
852 852 channelIndexList = property(
853 853 getChannelIndexList, "I'm the 'channelIndexList' property.")
854 854 noise = property(getNoise, "I'm the 'nHeights' property.")
855 855
856 856 ltctime = property(getltctime, "I'm the 'ltctime' property")
857 857 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
858 858 ippSeconds = property(get_ippSeconds, '')
859 859
860 860 class Correlation(JROData):
861 861
862 862 noise = None
863 863 SNR = None
864 864 #--------------------------------------------------
865 865 mode = None
866 866 split = False
867 867 data_cf = None
868 868 lags = None
869 869 lagRange = None
870 870 pairsList = None
871 871 normFactor = None
872 872 #--------------------------------------------------
873 873 # calculateVelocity = None
874 874 nLags = None
875 875 nPairs = None
876 876 nAvg = None
877 877
878 878 def __init__(self):
879 879 '''
880 880 Constructor
881 881 '''
882 882 self.radarControllerHeaderObj = RadarControllerHeader()
883 883
884 884 self.systemHeaderObj = SystemHeader()
885 885
886 886 self.type = "Correlation"
887 887
888 888 self.data = None
889 889
890 890 self.dtype = None
891 891
892 892 self.nProfiles = None
893 893
894 894 self.heightList = None
895 895
896 896 self.channelList = None
897 897
898 898 self.flagNoData = True
899 899
900 900 self.flagDiscontinuousBlock = False
901 901
902 902 self.utctime = None
903 903
904 904 self.timeZone = None
905 905
906 906 self.dstFlag = None
907 907
908 908 self.errorCount = None
909 909
910 910 self.blocksize = None
911 911
912 912 self.flagDecodeData = False # asumo q la data no esta decodificada
913 913
914 914 self.flagDeflipData = False # asumo q la data no esta sin flip
915 915
916 916 self.pairsList = None
917 917
918 918 self.nPoints = None
919 919
920 920 def getPairsList(self):
921 921
922 922 return self.pairsList
923 923
924 924 def getNoise(self, mode=2):
925 925
926 926 indR = numpy.where(self.lagR == 0)[0][0]
927 927 indT = numpy.where(self.lagT == 0)[0][0]
928 928
929 929 jspectra0 = self.data_corr[:, :, indR, :]
930 930 jspectra = copy.copy(jspectra0)
931 931
932 932 num_chan = jspectra.shape[0]
933 933 num_hei = jspectra.shape[2]
934 934
935 935 freq_dc = jspectra.shape[1] / 2
936 936 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
937 937
938 938 if ind_vel[0] < 0:
939 939 ind_vel[list(range(0, 1))] = ind_vel[list(
940 940 range(0, 1))] + self.num_prof
941 941
942 942 if mode == 1:
943 943 jspectra[:, freq_dc, :] = (
944 944 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
945 945
946 946 if mode == 2:
947 947
948 948 vel = numpy.array([-2, -1, 1, 2])
949 949 xx = numpy.zeros([4, 4])
950 950
951 951 for fil in range(4):
952 952 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
953 953
954 954 xx_inv = numpy.linalg.inv(xx)
955 955 xx_aux = xx_inv[0, :]
956 956
957 957 for ich in range(num_chan):
958 958 yy = jspectra[ich, ind_vel, :]
959 959 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
960 960
961 961 junkid = jspectra[ich, freq_dc, :] <= 0
962 962 cjunkid = sum(junkid)
963 963
964 964 if cjunkid.any():
965 965 jspectra[ich, freq_dc, junkid.nonzero()] = (
966 966 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
967 967
968 968 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
969 969
970 970 return noise
971 971
972 972 def getTimeInterval(self):
973 973
974 974 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
975 975
976 976 return timeInterval
977 977
978 978 def splitFunctions(self):
979 979
980 980 pairsList = self.pairsList
981 981 ccf_pairs = []
982 982 acf_pairs = []
983 983 ccf_ind = []
984 984 acf_ind = []
985 985 for l in range(len(pairsList)):
986 986 chan0 = pairsList[l][0]
987 987 chan1 = pairsList[l][1]
988 988
989 989 # Obteniendo pares de Autocorrelacion
990 990 if chan0 == chan1:
991 991 acf_pairs.append(chan0)
992 992 acf_ind.append(l)
993 993 else:
994 994 ccf_pairs.append(pairsList[l])
995 995 ccf_ind.append(l)
996 996
997 997 data_acf = self.data_cf[acf_ind]
998 998 data_ccf = self.data_cf[ccf_ind]
999 999
1000 1000 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1001 1001
1002 1002 def getNormFactor(self):
1003 1003 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1004 1004 acf_pairs = numpy.array(acf_pairs)
1005 1005 normFactor = numpy.zeros((self.nPairs, self.nHeights))
1006 1006
1007 1007 for p in range(self.nPairs):
1008 1008 pair = self.pairsList[p]
1009 1009
1010 1010 ch0 = pair[0]
1011 1011 ch1 = pair[1]
1012 1012
1013 1013 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
1014 1014 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
1015 1015 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
1016 1016
1017 1017 return normFactor
1018 1018
1019 1019 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1020 1020 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1021 1021
1022 1022
1023 1023 class Parameters(Spectra):
1024 1024
1025 1025 experimentInfo = None # Information about the experiment
1026 1026 # Information from previous data
1027 1027 inputUnit = None # Type of data to be processed
1028 1028 operation = None # Type of operation to parametrize
1029 1029 # normFactor = None #Normalization Factor
1030 1030 groupList = None # List of Pairs, Groups, etc
1031 1031 # Parameters
1032 1032 data_param = None # Parameters obtained
1033 1033 data_pre = None # Data Pre Parametrization
1034 1034 data_SNR = None # Signal to Noise Ratio
1035 1035 # heightRange = None #Heights
1036 1036 abscissaList = None # Abscissa, can be velocities, lags or time
1037 1037 # noise = None #Noise Potency
1038 1038 utctimeInit = None # Initial UTC time
1039 1039 paramInterval = None # Time interval to calculate Parameters in seconds
1040 1040 useLocalTime = True
1041 1041 # Fitting
1042 1042 data_error = None # Error of the estimation
1043 1043 constants = None
1044 1044 library = None
1045 1045 # Output signal
1046 1046 outputInterval = None # Time interval to calculate output signal in seconds
1047 1047 data_output = None # Out signal
1048 1048 nAvg = None
1049 1049 noise_estimation = None
1050 1050 GauSPC = None # Fit gaussian SPC
1051 1051
1052 1052 def __init__(self):
1053 1053 '''
1054 1054 Constructor
1055 1055 '''
1056 1056 self.radarControllerHeaderObj = RadarControllerHeader()
1057 1057
1058 1058 self.systemHeaderObj = SystemHeader()
1059 1059
1060 1060 self.type = "Parameters"
1061 1061
1062 1062 def getTimeRange1(self, interval):
1063 1063
1064 1064 datatime = []
1065 1065
1066 1066 if self.useLocalTime:
1067 1067 time1 = self.utctimeInit - self.timeZone * 60
1068 1068 else:
1069 1069 time1 = self.utctimeInit
1070 1070
1071 1071 datatime.append(time1)
1072 1072 datatime.append(time1 + interval)
1073 1073 datatime = numpy.array(datatime)
1074 1074
1075 1075 return datatime
1076 1076
1077 1077 def getTimeInterval(self):
1078 1078
1079 1079 if hasattr(self, 'timeInterval1'):
1080 1080 return self.timeInterval1
1081 1081 else:
1082 1082 return self.paramInterval
1083 1083
1084 1084 def setValue(self, value):
1085 1085
1086 1086 print("This property should not be initialized")
1087 1087
1088 1088 return
1089 1089
1090 1090 def getNoise(self):
1091 1091
1092 1092 return self.spc_noise
1093 1093
1094 1094 timeInterval = property(getTimeInterval)
1095 1095 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
1096 1096
1097 1097
1098 1098 class PlotterData(object):
1099 1099 '''
1100 1100 Object to hold data to be plotted
1101 1101 '''
1102 1102
1103 1103 MAXNUMX = 100
1104 1104 MAXNUMY = 100
1105 1105
1106 1106 def __init__(self, code, throttle_value, exp_code, buffering=True, snr=False):
1107
1107
1108 1108 self.key = code
1109 1109 self.throttle = throttle_value
1110 1110 self.exp_code = exp_code
1111 1111 self.buffering = buffering
1112 1112 self.ready = False
1113 1113 self.localtime = False
1114 1114 self.data = {}
1115 1115 self.meta = {}
1116 1116 self.__times = []
1117 1117 self.__heights = []
1118 1118
1119 1119 if 'snr' in code:
1120 1120 self.plottypes = ['snr']
1121 1121 elif code == 'spc':
1122 1122 self.plottypes = ['spc', 'noise', 'rti']
1123 1123 elif code == 'rti':
1124 1124 self.plottypes = ['noise', 'rti']
1125 1125 else:
1126 1126 self.plottypes = [code]
1127 1127
1128 1128 if 'snr' not in self.plottypes and snr:
1129 1129 self.plottypes.append('snr')
1130 1130
1131 1131 for plot in self.plottypes:
1132 1132 self.data[plot] = {}
1133 1133
1134 1134 def __str__(self):
1135 1135 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1136 1136 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
1137 1137
1138 1138 def __len__(self):
1139 1139 return len(self.__times)
1140 1140
1141 1141 def __getitem__(self, key):
1142
1142
1143 1143 if key not in self.data:
1144 1144 raise KeyError(log.error('Missing key: {}'.format(key)))
1145 1145 if 'spc' in key or not self.buffering:
1146 1146 ret = self.data[key]
1147 1147 elif 'scope' in key:
1148 1148 ret = numpy.array(self.data[key][float(self.tm)])
1149 1149 else:
1150 1150 ret = numpy.array([self.data[key][x] for x in self.times])
1151 1151 if ret.ndim > 1:
1152 1152 ret = numpy.swapaxes(ret, 0, 1)
1153 1153 return ret
1154 1154
1155 1155 def __contains__(self, key):
1156 1156 return key in self.data
1157 1157
1158 1158 def setup(self):
1159 1159 '''
1160 1160 Configure object
1161 1161 '''
1162 1162
1163 1163 self.type = ''
1164 1164 self.ready = False
1165 1165 self.data = {}
1166 1166 self.__times = []
1167 1167 self.__heights = []
1168 1168 self.__all_heights = set()
1169 1169 for plot in self.plottypes:
1170 1170 if 'snr' in plot:
1171 1171 plot = 'snr'
1172 1172 elif 'spc_moments' == plot:
1173 1173 plot = 'moments'
1174 1174 self.data[plot] = {}
1175
1175
1176 1176 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data:
1177 1177 self.data['noise'] = {}
1178 1178 self.data['rti'] = {}
1179 1179 if 'noise' not in self.plottypes:
1180 1180 self.plottypes.append('noise')
1181 1181 if 'rti' not in self.plottypes:
1182 1182 self.plottypes.append('rti')
1183
1183
1184 1184 def shape(self, key):
1185 1185 '''
1186 1186 Get the shape of the one-element data for the given key
1187 1187 '''
1188 1188
1189 1189 if len(self.data[key]):
1190 1190 if 'spc' in key or not self.buffering:
1191 1191 return self.data[key].shape
1192 1192 return self.data[key][self.__times[0]].shape
1193 1193 return (0,)
1194 1194
1195 1195 def update(self, dataOut, tm):
1196 1196 '''
1197 1197 Update data object with new dataOut
1198 1198 '''
1199
1199
1200 1200 if tm in self.__times:
1201 1201 return
1202 1202 self.profileIndex = dataOut.profileIndex
1203 1203 self.tm = tm
1204 1204 self.type = dataOut.type
1205 1205 self.parameters = getattr(dataOut, 'parameters', [])
1206
1206
1207 1207 if hasattr(dataOut, 'meta'):
1208 1208 self.meta.update(dataOut.meta)
1209
1209
1210 1210 self.pairs = dataOut.pairsList
1211 1211 self.interval = dataOut.getTimeInterval()
1212 1212 self.localtime = dataOut.useLocalTime
1213 1213 if 'spc' in self.plottypes or 'cspc' in self.plottypes or 'spc_moments' in self.plottypes:
1214 1214 self.xrange = (dataOut.getFreqRange(1)/1000.,
1215 1215 dataOut.getAcfRange(1), dataOut.getVelRange(1))
1216 1216 self.factor = dataOut.normFactor
1217 1217 self.__heights.append(dataOut.heightList)
1218 1218 self.__all_heights.update(dataOut.heightList)
1219 1219 self.__times.append(tm)
1220
1220
1221 1221 for plot in self.plottypes:
1222 1222 if plot in ('spc', 'spc_moments'):
1223 1223 z = dataOut.data_spc/dataOut.normFactor
1224 1224 buffer = 10*numpy.log10(z)
1225 1225 if plot == 'cspc':
1226 1226 z = dataOut.data_spc/dataOut.normFactor
1227 1227 buffer = (dataOut.data_spc, dataOut.data_cspc)
1228 1228 if plot == 'noise':
1229 1229 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
1230 1230 if plot == 'rti':
1231 1231 buffer = dataOut.getPower()
1232 1232 if plot == 'snr_db':
1233 1233 buffer = dataOut.data_SNR
1234 1234 if plot == 'snr':
1235 1235 buffer = 10*numpy.log10(dataOut.data_SNR)
1236 1236 if plot == 'dop':
1237 1237 buffer = dataOut.data_DOP
1238 1238 if plot == 'pow':
1239 1239 buffer = 10*numpy.log10(dataOut.data_POW)
1240 1240 if plot == 'width':
1241 1241 buffer = dataOut.data_WIDTH
1242 1242 if plot == 'coh':
1243 1243 buffer = dataOut.getCoherence()
1244 1244 if plot == 'phase':
1245 1245 buffer = dataOut.getCoherence(phase=True)
1246 1246 if plot == 'output':
1247 1247 buffer = dataOut.data_output
1248 1248 if plot == 'param':
1249 1249 buffer = dataOut.data_param
1250 1250 if plot == 'scope':
1251 1251 buffer = dataOut.data
1252 1252 self.flagDataAsBlock = dataOut.flagDataAsBlock
1253 self.nProfiles = dataOut.nProfiles
1254
1253 self.nProfiles = dataOut.nProfiles
1254
1255 1255 if plot == 'spc':
1256 1256 self.data['spc'] = buffer
1257 1257 elif plot == 'cspc':
1258 1258 self.data['spc'] = buffer[0]
1259 1259 self.data['cspc'] = buffer[1]
1260 1260 elif plot == 'spc_moments':
1261 1261 self.data['spc'] = buffer
1262 1262 self.data['moments'][tm] = dataOut.moments
1263 1263 else:
1264 1264 if self.buffering:
1265 1265 self.data[plot][tm] = buffer
1266 1266 else:
1267 1267 self.data[plot] = buffer
1268 1268
1269 1269 if dataOut.channelList is None:
1270 1270 self.channels = range(buffer.shape[0])
1271 1271 else:
1272 1272 self.channels = dataOut.channelList
1273 1273
1274 1274 def normalize_heights(self):
1275 1275 '''
1276 1276 Ensure same-dimension of the data for different heighList
1277 1277 '''
1278 1278
1279 1279 H = numpy.array(list(self.__all_heights))
1280 1280 H.sort()
1281 1281 for key in self.data:
1282 1282 shape = self.shape(key)[:-1] + H.shape
1283 1283 for tm, obj in list(self.data[key].items()):
1284 1284 h = self.__heights[self.__times.index(tm)]
1285 1285 if H.size == h.size:
1286 1286 continue
1287 1287 index = numpy.where(numpy.in1d(H, h))[0]
1288 1288 dummy = numpy.zeros(shape) + numpy.nan
1289 1289 if len(shape) == 2:
1290 1290 dummy[:, index] = obj
1291 1291 else:
1292 1292 dummy[index] = obj
1293 1293 self.data[key][tm] = dummy
1294 1294
1295 1295 self.__heights = [H for tm in self.__times]
1296 1296
1297 1297 def jsonify(self, plot_name, plot_type, decimate=False):
1298 1298 '''
1299 1299 Convert data to json
1300 1300 '''
1301 1301
1302 1302 tm = self.times[-1]
1303 1303 dy = int(self.heights.size/self.MAXNUMY) + 1
1304 1304 if self.key in ('spc', 'cspc') or not self.buffering:
1305 1305 dx = int(self.data[self.key].shape[1]/self.MAXNUMX) + 1
1306 1306 data = self.roundFloats(
1307 1307 self.data[self.key][::, ::dx, ::dy].tolist())
1308 1308 else:
1309 1309 data = self.roundFloats(self.data[self.key][tm].tolist())
1310 1310 if self.key is 'noise':
1311 1311 data = [[x] for x in data]
1312 1312
1313 1313 meta = {}
1314 1314 ret = {
1315 1315 'plot': plot_name,
1316 1316 'code': self.exp_code,
1317 1317 'time': float(tm),
1318 1318 'data': data,
1319 1319 }
1320 1320 meta['type'] = plot_type
1321 1321 meta['interval'] = float(self.interval)
1322 1322 meta['localtime'] = self.localtime
1323 1323 meta['yrange'] = self.roundFloats(self.heights[::dy].tolist())
1324 1324 if 'spc' in self.data or 'cspc' in self.data:
1325 1325 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1326 1326 else:
1327 1327 meta['xrange'] = []
1328 1328
1329 meta.update(self.meta)
1329 meta.update(self.meta)
1330 1330 ret['metadata'] = meta
1331 1331 return json.dumps(ret)
1332 1332
1333 1333 @property
1334 1334 def times(self):
1335 1335 '''
1336 1336 Return the list of times of the current data
1337 1337 '''
1338 1338
1339 1339 ret = numpy.array(self.__times)
1340 1340 ret.sort()
1341 1341 return ret
1342 1342
1343 1343 @property
1344 1344 def min_time(self):
1345 1345 '''
1346 1346 Return the minimun time value
1347 1347 '''
1348 1348
1349 1349 return self.times[0]
1350 1350
1351 1351 @property
1352 1352 def max_time(self):
1353 1353 '''
1354 1354 Return the maximun time value
1355 1355 '''
1356 1356
1357 1357 return self.times[-1]
1358 1358
1359 1359 @property
1360 1360 def heights(self):
1361 1361 '''
1362 1362 Return the list of heights of the current data
1363 1363 '''
1364 1364
1365 1365 return numpy.array(self.__heights[-1])
1366 1366
1367 1367 @staticmethod
1368 1368 def roundFloats(obj):
1369 1369 if isinstance(obj, list):
1370 1370 return list(map(PlotterData.roundFloats, obj))
1371 1371 elif isinstance(obj, float):
1372 1372 return round(obj, 2)
@@ -1,1589 +1,1809
1 1 '''
2 2 Created on Jul 9, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9
10 10 from .figure import Figure, isRealtime, isTimeInHourRange
11 11 from .plotting_codes import *
12 12 from schainpy.model.proc.jroproc_base import MPDecorator
13 13
14 14 from schainpy.utils import log
15 15
16 16 @MPDecorator
17 17 class SpectraPlot_(Figure):
18 18
19 19 isConfig = None
20 20 __nsubplots = None
21 21
22 22 WIDTHPROF = None
23 23 HEIGHTPROF = None
24 24 PREFIX = 'spc'
25 25
26 26 def __init__(self):
27 27 Figure.__init__(self)
28 28 self.isConfig = False
29 29 self.__nsubplots = 1
30 30 self.WIDTH = 250
31 31 self.HEIGHT = 250
32 32 self.WIDTHPROF = 120
33 33 self.HEIGHTPROF = 0
34 34 self.counter_imagwr = 0
35 35
36 36 self.PLOT_CODE = SPEC_CODE
37 37
38 38 self.FTP_WEI = None
39 39 self.EXP_CODE = None
40 40 self.SUB_EXP_CODE = None
41 41 self.PLOT_POS = None
42 42
43 43 self.__xfilter_ena = False
44 44 self.__yfilter_ena = False
45
45
46 46 self.indice=1
47 47
48 48 def getSubplots(self):
49 49
50 50 ncol = int(numpy.sqrt(self.nplots)+0.9)
51 51 nrow = int(self.nplots*1./ncol + 0.9)
52 52
53 53 return nrow, ncol
54 54
55 55 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
56 56
57 57 self.__showprofile = showprofile
58 58 self.nplots = nplots
59 59
60 60 ncolspan = 1
61 61 colspan = 1
62 62 if showprofile:
63 63 ncolspan = 3
64 64 colspan = 2
65 65 self.__nsubplots = 2
66 66
67 67 self.createFigure(id = id,
68 68 wintitle = wintitle,
69 69 widthplot = self.WIDTH + self.WIDTHPROF,
70 70 heightplot = self.HEIGHT + self.HEIGHTPROF,
71 71 show=show)
72 72
73 73 nrow, ncol = self.getSubplots()
74 74
75 75 counter = 0
76 76 for y in range(nrow):
77 77 for x in range(ncol):
78 78
79 79 if counter >= self.nplots:
80 80 break
81 81
82 82 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
83 83
84 84 if showprofile:
85 85 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
86 86
87 87 counter += 1
88 88
89 89 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
90 90 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
91 91 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
92 92 server=None, folder=None, username=None, password=None,
93 93 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
94 94 xaxis="frequency", colormap='jet', normFactor=None):
95 95
96 96 """
97 97
98 98 Input:
99 99 dataOut :
100 100 id :
101 101 wintitle :
102 102 channelList :
103 103 showProfile :
104 104 xmin : None,
105 105 xmax : None,
106 106 ymin : None,
107 107 ymax : None,
108 108 zmin : None,
109 109 zmax : None
110 110 """
111 111 if dataOut.flagNoData:
112 112 return dataOut
113 113
114 114 if realtime:
115 115 if not(isRealtime(utcdatatime = dataOut.utctime)):
116 116 print('Skipping this plot function')
117 117 return
118 118
119 119 if channelList == None:
120 120 channelIndexList = dataOut.channelIndexList
121 121 else:
122 122 channelIndexList = []
123 123 for channel in channelList:
124 124 if channel not in dataOut.channelList:
125 125 raise ValueError("Channel %d is not in dataOut.channelList" %channel)
126 126 channelIndexList.append(dataOut.channelList.index(channel))
127 127
128 128 if normFactor is None:
129 129 factor = dataOut.normFactor
130 130 else:
131 131 factor = normFactor
132 132 if xaxis == "frequency":
133 133 x = dataOut.getFreqRange(1)/1000.
134 134 xlabel = "Frequency (kHz)"
135 135
136 136 elif xaxis == "time":
137 137 x = dataOut.getAcfRange(1)
138 138 xlabel = "Time (ms)"
139 139
140 140 else:
141 141 x = dataOut.getVelRange(1)
142 142 xlabel = "Velocity (m/s)"
143 143
144 144 ylabel = "Range (km)"
145 145
146 146 y = dataOut.getHeiRange()
147 147 z = dataOut.data_spc/factor
148 148 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
149 149 zdB = 10*numpy.log10(z)
150 150
151 151 avg = numpy.average(z, axis=1)
152 152 avgdB = 10*numpy.log10(avg)
153 153
154 154 noise = dataOut.getNoise()/factor
155 155 noisedB = 10*numpy.log10(noise)
156 156
157 157 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
158 158 title = wintitle + " Spectra"
159 159
160 160 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
161 161 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
162 162
163 163 if not self.isConfig:
164 164
165 165 nplots = len(channelIndexList)
166 166
167 167 self.setup(id=id,
168 168 nplots=nplots,
169 169 wintitle=wintitle,
170 170 showprofile=showprofile,
171 171 show=show)
172 172
173 173 if xmin == None: xmin = numpy.nanmin(x)
174 174 if xmax == None: xmax = numpy.nanmax(x)
175 175 if ymin == None: ymin = numpy.nanmin(y)
176 176 if ymax == None: ymax = numpy.nanmax(y)
177 177 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
178 178 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
179 179
180 180 self.FTP_WEI = ftp_wei
181 181 self.EXP_CODE = exp_code
182 182 self.SUB_EXP_CODE = sub_exp_code
183 183 self.PLOT_POS = plot_pos
184 184
185 185 self.isConfig = True
186 186
187 187 self.setWinTitle(title)
188 188
189 189 for i in range(self.nplots):
190 190 index = channelIndexList[i]
191 191 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
192 192 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime)
193 193 if len(dataOut.beam.codeList) != 0:
194 194 title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime)
195 195
196 196 axes = self.axesList[i*self.__nsubplots]
197 197 axes.pcolor(x, y, zdB[index,:,:],
198 198 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
199 199 xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap,
200 200 ticksize=9, cblabel='')
201 201
202 202 if self.__showprofile:
203 203 axes = self.axesList[i*self.__nsubplots +1]
204 204 axes.pline(avgdB[index,:], y,
205 205 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
206 206 xlabel='dB', ylabel='', title='',
207 207 ytick_visible=False,
208 208 grid='x')
209 209
210 210 noiseline = numpy.repeat(noisedB[index], len(y))
211 211 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
212 212
213 213 self.draw()
214 214
215 215 if figfile == None:
216 216 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
217 217 name = str_datetime
218 218 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
219 219 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
220 220 figfile = self.getFilename(name)
221 221
222 222 self.save(figpath=figpath,
223 223 figfile=figfile,
224 224 save=save,
225 225 ftp=ftp,
226 226 wr_period=wr_period,
227 227 thisDatetime=thisDatetime)
228
228
229 229
230 230 return dataOut
231 231
232 232 @MPDecorator
233 class WpowerPlot_(Figure):
234
235 isConfig = None
236 __nsubplots = None
237
238 WIDTHPROF = None
239 HEIGHTPROF = None
240 PREFIX = 'wpo'
241
242 def __init__(self):
243 Figure.__init__(self)
244 self.isConfig = False
245 self.__nsubplots = 1
246 self.WIDTH = 250
247 self.HEIGHT = 250
248 self.WIDTHPROF = 120
249 self.HEIGHTPROF = 0
250 self.counter_imagwr = 0
251
252 self.PLOT_CODE = WPO_CODE
253
254 self.FTP_WEI = None
255 self.EXP_CODE = None
256 self.SUB_EXP_CODE = None
257 self.PLOT_POS = None
258
259 self.__xfilter_ena = False
260 self.__yfilter_ena = False
261
262 self.indice=1
263
264 def getSubplots(self):
265
266 ncol = int(numpy.sqrt(self.nplots)+0.9)
267 nrow = int(self.nplots*1./ncol + 0.9)
268
269 return nrow, ncol
270
271 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
272
273 self.__showprofile = showprofile
274 self.nplots = nplots
275
276 ncolspan = 1
277 colspan = 1
278 if showprofile:
279 ncolspan = 3
280 colspan = 2
281 self.__nsubplots = 2
282
283 self.createFigure(id = id,
284 wintitle = wintitle,
285 widthplot = self.WIDTH + self.WIDTHPROF,
286 heightplot = self.HEIGHT + self.HEIGHTPROF,
287 show=show)
288
289 nrow, ncol = self.getSubplots()
290
291 counter = 0
292 for y in range(nrow):
293 for x in range(ncol):
294
295 if counter >= self.nplots:
296 break
297
298 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
299
300 if showprofile:
301 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
302
303 counter += 1
304
305 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
306 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
307 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
308 server=None, folder=None, username=None, password=None,
309 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
310 xaxis="frequency", colormap='jet', normFactor=None):
311
312 """
313
314 Input:
315 dataOut :
316 id :
317 wintitle :
318 channelList :
319 showProfile :
320 xmin : None,
321 xmax : None,
322 ymin : None,
323 ymax : None,
324 zmin : None,
325 zmax : None
326 """
327 print("***************PLOTEO******************")
328 print("DATAOUT SHAPE : ",dataOut.data.shape)
329 if dataOut.flagNoData:
330 return dataOut
331
332 if realtime:
333 if not(isRealtime(utcdatatime = dataOut.utctime)):
334 print('Skipping this plot function')
335 return
336
337 if channelList == None:
338 channelIndexList = dataOut.channelIndexList
339 else:
340 channelIndexList = []
341 for channel in channelList:
342 if channel not in dataOut.channelList:
343 raise ValueError("Channel %d is not in dataOut.channelList" %channel)
344 channelIndexList.append(dataOut.channelList.index(channel))
345
346
347 print("channelIndexList",channelIndexList)
348 if normFactor is None:
349 factor = dataOut.normFactor
350 else:
351 factor = normFactor
352 if xaxis == "frequency":
353 x = dataOut.getFreqRange(1)/1000.
354 xlabel = "Frequency (kHz)"
355
356 elif xaxis == "time":
357 x = dataOut.getAcfRange(1)
358 xlabel = "Time (ms)"
359
360 else:
361 x = dataOut.getVelRange(1)
362 xlabel = "Velocity (m/s)"
363
364 ylabel = "Range (km)"
365
366 y = dataOut.getHeiRange()
367 print("factor",factor)
368
369 z = dataOut.data/factor # dividido /factor
370 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
371 zdB = 10*numpy.log10(z)
372
373 avg = numpy.average(z, axis=1)
374 avgdB = 10*numpy.log10(avg)
375
376 noise = dataOut.getNoise()/factor
377 noisedB = 10*numpy.log10(noise)
378
379 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
380 title = wintitle + "Weather Power"
381
382 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
383 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
384
385 if not self.isConfig:
386
387 nplots = len(channelIndexList)
388
389 self.setup(id=id,
390 nplots=nplots,
391 wintitle=wintitle,
392 showprofile=showprofile,
393 show=show)
394
395 if xmin == None: xmin = numpy.nanmin(x)
396 if xmax == None: xmax = numpy.nanmax(x)
397 if ymin == None: ymin = numpy.nanmin(y)
398 if ymax == None: ymax = numpy.nanmax(y)
399 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
400 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
401
402 self.FTP_WEI = ftp_wei
403 self.EXP_CODE = exp_code
404 self.SUB_EXP_CODE = sub_exp_code
405 self.PLOT_POS = plot_pos
406
407 self.isConfig = True
408
409 self.setWinTitle(title)
410
411 for i in range(self.nplots):
412 index = channelIndexList[i]
413 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
414 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime)
415 if len(dataOut.beam.codeList) != 0:
416 title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime)
417
418 axes = self.axesList[i*self.__nsubplots]
419 axes.pcolor(x, y, zdB[index,:,:],
420 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
421 xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap,
422 ticksize=9, cblabel='')
423
424 if self.__showprofile:
425 axes = self.axesList[i*self.__nsubplots +1]
426 axes.pline(avgdB[index,:], y,
427 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
428 xlabel='dB', ylabel='', title='',
429 ytick_visible=False,
430 grid='x')
431
432 noiseline = numpy.repeat(noisedB[index], len(y))
433 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
434
435 self.draw()
436
437 if figfile == None:
438 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
439 name = str_datetime
440 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
441 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
442 figfile = self.getFilename(name)
443
444 self.save(figpath=figpath,
445 figfile=figfile,
446 save=save,
447 ftp=ftp,
448 wr_period=wr_period,
449 thisDatetime=thisDatetime)
450 return dataOut
451
452 @MPDecorator
233 453 class CrossSpectraPlot_(Figure):
234 454
235 455 isConfig = None
236 456 __nsubplots = None
237 457
238 458 WIDTH = None
239 459 HEIGHT = None
240 460 WIDTHPROF = None
241 461 HEIGHTPROF = None
242 462 PREFIX = 'cspc'
243 463
244 464 def __init__(self):
245 465 Figure.__init__(self)
246 466 self.isConfig = False
247 467 self.__nsubplots = 4
248 468 self.counter_imagwr = 0
249 469 self.WIDTH = 250
250 470 self.HEIGHT = 250
251 471 self.WIDTHPROF = 0
252 472 self.HEIGHTPROF = 0
253 473
254 474 self.PLOT_CODE = CROSS_CODE
255 475 self.FTP_WEI = None
256 476 self.EXP_CODE = None
257 477 self.SUB_EXP_CODE = None
258 478 self.PLOT_POS = None
259
479
260 480 self.indice=0
261 481
262 482 def getSubplots(self):
263 483
264 484 ncol = 4
265 485 nrow = self.nplots
266 486
267 487 return nrow, ncol
268 488
269 489 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
270 490
271 491 self.__showprofile = showprofile
272 492 self.nplots = nplots
273 493
274 494 ncolspan = 1
275 495 colspan = 1
276 496
277 497 self.createFigure(id = id,
278 498 wintitle = wintitle,
279 499 widthplot = self.WIDTH + self.WIDTHPROF,
280 500 heightplot = self.HEIGHT + self.HEIGHTPROF,
281 501 show=True)
282 502
283 503 nrow, ncol = self.getSubplots()
284 504
285 505 counter = 0
286 506 for y in range(nrow):
287 507 for x in range(ncol):
288 508 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
289 509
290 510 counter += 1
291 511
292 512 def run(self, dataOut, id, wintitle="", pairsList=None,
293 513 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
294 514 coh_min=None, coh_max=None, phase_min=None, phase_max=None,
295 515 save=False, figpath='./', figfile=None, ftp=False, wr_period=1,
296 516 power_cmap='jet', coherence_cmap='jet', phase_cmap='RdBu_r', show=True,
297 517 server=None, folder=None, username=None, password=None,
298 518 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, normFactor=None,
299 519 xaxis='frequency'):
300 520
301 521 """
302 522
303 523 Input:
304 524 dataOut :
305 525 id :
306 526 wintitle :
307 527 channelList :
308 528 showProfile :
309 529 xmin : None,
310 530 xmax : None,
311 531 ymin : None,
312 532 ymax : None,
313 533 zmin : None,
314 534 zmax : None
315 535 """
316 536
317 if dataOut.flagNoData:
537 if dataOut.flagNoData:
318 538 return dataOut
319 539
320 540 if pairsList == None:
321 541 pairsIndexList = dataOut.pairsIndexList
322 542 else:
323 543 pairsIndexList = []
324 544 for pair in pairsList:
325 545 if pair not in dataOut.pairsList:
326 546 raise ValueError("Pair %s is not in dataOut.pairsList" %str(pair))
327 547 pairsIndexList.append(dataOut.pairsList.index(pair))
328 548
329 549 if not pairsIndexList:
330 550 return
331 551
332 552 if len(pairsIndexList) > 4:
333 553 pairsIndexList = pairsIndexList[0:4]
334
554
335 555 if normFactor is None:
336 556 factor = dataOut.normFactor
337 557 else:
338 558 factor = normFactor
339 559 x = dataOut.getVelRange(1)
340 560 y = dataOut.getHeiRange()
341 561 z = dataOut.data_spc[:,:,:]/factor
342 562 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
343 563
344 564 noise = dataOut.noise/factor
345 565
346 566 zdB = 10*numpy.log10(z)
347 567 noisedB = 10*numpy.log10(noise)
348 568
349 569 if coh_min == None:
350 570 coh_min = 0.0
351 571 if coh_max == None:
352 572 coh_max = 1.0
353 573
354 574 if phase_min == None:
355 575 phase_min = -180
356 576 if phase_max == None:
357 577 phase_max = 180
358 578
359 579 #thisDatetime = dataOut.datatime
360 580 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
361 581 title = wintitle + " Cross-Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
362 582 # xlabel = "Velocity (m/s)"
363 583 ylabel = "Range (Km)"
364 584
365 585 if xaxis == "frequency":
366 586 x = dataOut.getFreqRange(1)/1000.
367 587 xlabel = "Frequency (kHz)"
368 588
369 589 elif xaxis == "time":
370 590 x = dataOut.getAcfRange(1)
371 591 xlabel = "Time (ms)"
372 592
373 593 else:
374 594 x = dataOut.getVelRange(1)
375 595 xlabel = "Velocity (m/s)"
376 596
377 597 if not self.isConfig:
378 598
379 599 nplots = len(pairsIndexList)
380 600
381 601 self.setup(id=id,
382 602 nplots=nplots,
383 603 wintitle=wintitle,
384 604 showprofile=False,
385 605 show=show)
386 606
387 607 avg = numpy.abs(numpy.average(z, axis=1))
388 608 avgdB = 10*numpy.log10(avg)
389 609
390 610 if xmin == None: xmin = numpy.nanmin(x)
391 611 if xmax == None: xmax = numpy.nanmax(x)
392 612 if ymin == None: ymin = numpy.nanmin(y)
393 613 if ymax == None: ymax = numpy.nanmax(y)
394 614 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
395 615 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
396 616
397 617 self.FTP_WEI = ftp_wei
398 618 self.EXP_CODE = exp_code
399 619 self.SUB_EXP_CODE = sub_exp_code
400 620 self.PLOT_POS = plot_pos
401 621
402 622 self.isConfig = True
403 623
404 624 self.setWinTitle(title)
405
625
406 626
407 627 for i in range(self.nplots):
408 628 pair = dataOut.pairsList[pairsIndexList[i]]
409 629
410 630 chan_index0 = dataOut.channelList.index(pair[0])
411 631 chan_index1 = dataOut.channelList.index(pair[1])
412 632
413 633 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
414 634 title = "Ch%d: %4.2fdB: %s" %(pair[0], noisedB[chan_index0], str_datetime)
415 635 zdB = 10.*numpy.log10(dataOut.data_spc[chan_index0,:,:]/factor)
416 636 axes0 = self.axesList[i*self.__nsubplots]
417 637 axes0.pcolor(x, y, zdB,
418 638 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
419 639 xlabel=xlabel, ylabel=ylabel, title=title,
420 640 ticksize=9, colormap=power_cmap, cblabel='')
421 641
422 642 title = "Ch%d: %4.2fdB: %s" %(pair[1], noisedB[chan_index1], str_datetime)
423 643 zdB = 10.*numpy.log10(dataOut.data_spc[chan_index1,:,:]/factor)
424 644 axes0 = self.axesList[i*self.__nsubplots+1]
425 645 axes0.pcolor(x, y, zdB,
426 646 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
427 647 xlabel=xlabel, ylabel=ylabel, title=title,
428 648 ticksize=9, colormap=power_cmap, cblabel='')
429 649
430 650 coherenceComplex = dataOut.data_cspc[pairsIndexList[i],:,:] / numpy.sqrt( dataOut.data_spc[chan_index0,:,:]*dataOut.data_spc[chan_index1,:,:] )
431 651 coherence = numpy.abs(coherenceComplex)
432 652 # phase = numpy.arctan(-1*coherenceComplex.imag/coherenceComplex.real)*180/numpy.pi
433 653 phase = numpy.arctan2(coherenceComplex.imag, coherenceComplex.real)*180/numpy.pi
434 654
435 655 title = "Coherence Ch%d * Ch%d" %(pair[0], pair[1])
436 656 axes0 = self.axesList[i*self.__nsubplots+2]
437 657 axes0.pcolor(x, y, coherence,
438 658 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=coh_min, zmax=coh_max,
439 659 xlabel=xlabel, ylabel=ylabel, title=title,
440 660 ticksize=9, colormap=coherence_cmap, cblabel='')
441 661
442 662 title = "Phase Ch%d * Ch%d" %(pair[0], pair[1])
443 663 axes0 = self.axesList[i*self.__nsubplots+3]
444 664 axes0.pcolor(x, y, phase,
445 665 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max,
446 666 xlabel=xlabel, ylabel=ylabel, title=title,
447 667 ticksize=9, colormap=phase_cmap, cblabel='')
448 668
449 669 self.draw()
450 670
451 671 self.save(figpath=figpath,
452 672 figfile=figfile,
453 673 save=save,
454 674 ftp=ftp,
455 675 wr_period=wr_period,
456 676 thisDatetime=thisDatetime)
457 677
458 678 return dataOut
459 679
460 680 @MPDecorator
461 681 class RTIPlot_(Figure):
462 682
463 683 __isConfig = None
464 684 __nsubplots = None
465 685
466 686 WIDTHPROF = None
467 687 HEIGHTPROF = None
468 688 PREFIX = 'rti'
469 689
470 690 def __init__(self):
471 691
472 692 Figure.__init__(self)
473 693 self.timerange = None
474 694 self.isConfig = False
475 695 self.__nsubplots = 1
476 696
477 697 self.WIDTH = 800
478 698 self.HEIGHT = 250
479 699 self.WIDTHPROF = 120
480 700 self.HEIGHTPROF = 0
481 701 self.counter_imagwr = 0
482 702
483 703 self.PLOT_CODE = RTI_CODE
484 704
485 705 self.FTP_WEI = None
486 706 self.EXP_CODE = None
487 707 self.SUB_EXP_CODE = None
488 708 self.PLOT_POS = None
489 709 self.tmin = None
490 710 self.tmax = None
491 711
492 712 self.xmin = None
493 713 self.xmax = None
494 714
495 715 self.figfile = None
496 716
497 717 def getSubplots(self):
498 718
499 719 ncol = 1
500 720 nrow = self.nplots
501 721
502 722 return nrow, ncol
503 723
504 724 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
505 725
506 726 self.__showprofile = showprofile
507 727 self.nplots = nplots
508 728
509 729 ncolspan = 1
510 730 colspan = 1
511 731 if showprofile:
512 732 ncolspan = 7
513 733 colspan = 6
514 734 self.__nsubplots = 2
515 735
516 736 self.createFigure(id = id,
517 737 wintitle = wintitle,
518 738 widthplot = self.WIDTH + self.WIDTHPROF,
519 739 heightplot = self.HEIGHT + self.HEIGHTPROF,
520 740 show=show)
521 741
522 742 nrow, ncol = self.getSubplots()
523 743
524 744 counter = 0
525 745 for y in range(nrow):
526 746 for x in range(ncol):
527 747
528 748 if counter >= self.nplots:
529 749 break
530 750
531 751 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
532 752
533 753 if showprofile:
534 754 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
535 755
536 756 counter += 1
537 757
538 758 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
539 759 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
540 760 timerange=None, colormap='jet',
541 761 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
542 762 server=None, folder=None, username=None, password=None,
543 763 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, normFactor=None, HEIGHT=None):
544 764
545 765 """
546 766
547 767 Input:
548 768 dataOut :
549 769 id :
550 770 wintitle :
551 771 channelList :
552 772 showProfile :
553 773 xmin : None,
554 774 xmax : None,
555 775 ymin : None,
556 776 ymax : None,
557 777 zmin : None,
558 778 zmax : None
559 779 """
560 780 if dataOut.flagNoData:
561 781 return dataOut
562 782
563 783 #colormap = kwargs.get('colormap', 'jet')
564 784 if HEIGHT is not None:
565 785 self.HEIGHT = HEIGHT
566
786
567 787 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
568 788 return
569 789
570 790 if channelList == None:
571 791 channelIndexList = dataOut.channelIndexList
572 792 else:
573 793 channelIndexList = []
574 794 for channel in channelList:
575 795 if channel not in dataOut.channelList:
576 796 raise ValueError("Channel %d is not in dataOut.channelList")
577 797 channelIndexList.append(dataOut.channelList.index(channel))
578 798
579 799 if normFactor is None:
580 800 factor = dataOut.normFactor
581 801 else:
582 802 factor = normFactor
583 803
584 804 #factor = dataOut.normFactor
585 805 x = dataOut.getTimeRange()
586 806 y = dataOut.getHeiRange()
587 807
588 808 z = dataOut.data_spc/factor
589 809 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
590 810 avg = numpy.average(z, axis=1)
591 811 avgdB = 10.*numpy.log10(avg)
592 812 # avgdB = dataOut.getPower()
593 813
594 814
595 815 thisDatetime = dataOut.datatime
596 816 #thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
597 817 title = wintitle + " RTI" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
598 818 xlabel = ""
599 819 ylabel = "Range (Km)"
600 820
601 821 update_figfile = False
602 822
603 823 if self.xmax is not None and dataOut.ltctime >= self.xmax: #yong
604 824 self.counter_imagwr = wr_period
605 825 self.isConfig = False
606 826 update_figfile = True
607 827
608 828 if not self.isConfig:
609 829
610 830 nplots = len(channelIndexList)
611 831
612 832 self.setup(id=id,
613 833 nplots=nplots,
614 834 wintitle=wintitle,
615 835 showprofile=showprofile,
616 836 show=show)
617 837
618 838 if timerange != None:
619 839 self.timerange = timerange
620 840
621 841 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
622 842
623 843 noise = dataOut.noise/factor
624 844 noisedB = 10*numpy.log10(noise)
625 845
626 846 if ymin == None: ymin = numpy.nanmin(y)
627 847 if ymax == None: ymax = numpy.nanmax(y)
628 848 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
629 849 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
630 850
631 851 self.FTP_WEI = ftp_wei
632 852 self.EXP_CODE = exp_code
633 853 self.SUB_EXP_CODE = sub_exp_code
634 854 self.PLOT_POS = plot_pos
635 855
636 856 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
637 857 self.isConfig = True
638 858 self.figfile = figfile
639 859 update_figfile = True
640 860
641 861 self.setWinTitle(title)
642 862
643 863 for i in range(self.nplots):
644 864 index = channelIndexList[i]
645 865 title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
646 866 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
647 867 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
648 868 axes = self.axesList[i*self.__nsubplots]
649 869 zdB = avgdB[index].reshape((1,-1))
650 870 axes.pcolorbuffer(x, y, zdB,
651 871 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
652 872 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
653 873 ticksize=9, cblabel='', cbsize="1%", colormap=colormap)
654 874
655 875 if self.__showprofile:
656 876 axes = self.axesList[i*self.__nsubplots +1]
657 877 axes.pline(avgdB[index], y,
658 878 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
659 879 xlabel='dB', ylabel='', title='',
660 880 ytick_visible=False,
661 881 grid='x')
662 882
663 883 self.draw()
664 884
665 885 self.save(figpath=figpath,
666 886 figfile=figfile,
667 887 save=save,
668 888 ftp=ftp,
669 889 wr_period=wr_period,
670 890 thisDatetime=thisDatetime,
671 891 update_figfile=update_figfile)
672 892 return dataOut
673 893
674 894 @MPDecorator
675 895 class CoherenceMap_(Figure):
676 896 isConfig = None
677 897 __nsubplots = None
678 898
679 899 WIDTHPROF = None
680 900 HEIGHTPROF = None
681 901 PREFIX = 'cmap'
682 902
683 903 def __init__(self):
684 904 Figure.__init__(self)
685 905 self.timerange = 2*60*60
686 906 self.isConfig = False
687 907 self.__nsubplots = 1
688 908
689 909 self.WIDTH = 800
690 910 self.HEIGHT = 180
691 911 self.WIDTHPROF = 120
692 912 self.HEIGHTPROF = 0
693 913 self.counter_imagwr = 0
694 914
695 915 self.PLOT_CODE = COH_CODE
696 916
697 917 self.FTP_WEI = None
698 918 self.EXP_CODE = None
699 919 self.SUB_EXP_CODE = None
700 920 self.PLOT_POS = None
701 921 self.counter_imagwr = 0
702 922
703 923 self.xmin = None
704 924 self.xmax = None
705 925
706 926 def getSubplots(self):
707 927 ncol = 1
708 928 nrow = self.nplots*2
709 929
710 930 return nrow, ncol
711 931
712 932 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
713 933 self.__showprofile = showprofile
714 934 self.nplots = nplots
715 935
716 936 ncolspan = 1
717 937 colspan = 1
718 938 if showprofile:
719 939 ncolspan = 7
720 940 colspan = 6
721 941 self.__nsubplots = 2
722 942
723 943 self.createFigure(id = id,
724 944 wintitle = wintitle,
725 945 widthplot = self.WIDTH + self.WIDTHPROF,
726 946 heightplot = self.HEIGHT + self.HEIGHTPROF,
727 947 show=True)
728 948
729 949 nrow, ncol = self.getSubplots()
730 950
731 951 for y in range(nrow):
732 952 for x in range(ncol):
733 953
734 954 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
735 955
736 956 if showprofile:
737 957 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
738 958
739 959 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
740 960 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
741 961 timerange=None, phase_min=None, phase_max=None,
742 962 save=False, figpath='./', figfile=None, ftp=False, wr_period=1,
743 963 coherence_cmap='jet', phase_cmap='RdBu_r', show=True,
744 964 server=None, folder=None, username=None, password=None,
745 965 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
746 966
747 967
748 if dataOut.flagNoData:
968 if dataOut.flagNoData:
749 969 return dataOut
750 970
751 971 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
752 972 return
753 973
754 974 if pairsList == None:
755 975 pairsIndexList = dataOut.pairsIndexList
756 976 else:
757 977 pairsIndexList = []
758 978 for pair in pairsList:
759 979 if pair not in dataOut.pairsList:
760 980 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
761 981 pairsIndexList.append(dataOut.pairsList.index(pair))
762 982
763 983 if pairsIndexList == []:
764 984 return
765 985
766 986 if len(pairsIndexList) > 4:
767 987 pairsIndexList = pairsIndexList[0:4]
768 988
769 989 if phase_min == None:
770 990 phase_min = -180
771 991 if phase_max == None:
772 992 phase_max = 180
773 993
774 994 x = dataOut.getTimeRange()
775 995 y = dataOut.getHeiRange()
776 996
777 997 thisDatetime = dataOut.datatime
778 998
779 999 title = wintitle + " CoherenceMap" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
780 1000 xlabel = ""
781 1001 ylabel = "Range (Km)"
782 1002 update_figfile = False
783 1003
784 1004 if not self.isConfig:
785 1005 nplots = len(pairsIndexList)
786 1006 self.setup(id=id,
787 1007 nplots=nplots,
788 1008 wintitle=wintitle,
789 1009 showprofile=showprofile,
790 1010 show=show)
791 1011
792 1012 if timerange != None:
793 1013 self.timerange = timerange
794 1014
795 1015 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
796 1016
797 1017 if ymin == None: ymin = numpy.nanmin(y)
798 1018 if ymax == None: ymax = numpy.nanmax(y)
799 1019 if zmin == None: zmin = 0.
800 1020 if zmax == None: zmax = 1.
801 1021
802 1022 self.FTP_WEI = ftp_wei
803 1023 self.EXP_CODE = exp_code
804 1024 self.SUB_EXP_CODE = sub_exp_code
805 1025 self.PLOT_POS = plot_pos
806 1026
807 1027 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
808 1028
809 1029 self.isConfig = True
810 1030 update_figfile = True
811 1031
812 1032 self.setWinTitle(title)
813 1033
814 1034 for i in range(self.nplots):
815 1035
816 1036 pair = dataOut.pairsList[pairsIndexList[i]]
817 1037
818 1038 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i],:,:],axis=0)
819 1039 powa = numpy.average(dataOut.data_spc[pair[0],:,:],axis=0)
820 1040 powb = numpy.average(dataOut.data_spc[pair[1],:,:],axis=0)
821 1041
822 1042
823 1043 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
824 1044 coherence = numpy.abs(avgcoherenceComplex)
825 1045
826 1046 z = coherence.reshape((1,-1))
827 1047
828 1048 counter = 0
829 1049
830 1050 title = "Coherence Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
831 1051 axes = self.axesList[i*self.__nsubplots*2]
832 1052 axes.pcolorbuffer(x, y, z,
833 1053 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
834 1054 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
835 1055 ticksize=9, cblabel='', colormap=coherence_cmap, cbsize="1%")
836 1056
837 1057 if self.__showprofile:
838 1058 counter += 1
839 1059 axes = self.axesList[i*self.__nsubplots*2 + counter]
840 1060 axes.pline(coherence, y,
841 1061 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
842 1062 xlabel='', ylabel='', title='', ticksize=7,
843 1063 ytick_visible=False, nxticks=5,
844 1064 grid='x')
845 1065
846 1066 counter += 1
847 1067
848 1068 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
849 1069
850 1070 z = phase.reshape((1,-1))
851 1071
852 1072 title = "Phase Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
853 1073 axes = self.axesList[i*self.__nsubplots*2 + counter]
854 1074 axes.pcolorbuffer(x, y, z,
855 1075 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max,
856 1076 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
857 1077 ticksize=9, cblabel='', colormap=phase_cmap, cbsize="1%")
858 1078
859 1079 if self.__showprofile:
860 1080 counter += 1
861 1081 axes = self.axesList[i*self.__nsubplots*2 + counter]
862 1082 axes.pline(phase, y,
863 1083 xmin=phase_min, xmax=phase_max, ymin=ymin, ymax=ymax,
864 1084 xlabel='', ylabel='', title='', ticksize=7,
865 1085 ytick_visible=False, nxticks=4,
866 1086 grid='x')
867 1087
868 1088 self.draw()
869 1089
870 1090 if dataOut.ltctime >= self.xmax:
871 1091 self.counter_imagwr = wr_period
872 1092 self.isConfig = False
873 1093 update_figfile = True
874 1094
875 1095 self.save(figpath=figpath,
876 1096 figfile=figfile,
877 1097 save=save,
878 1098 ftp=ftp,
879 1099 wr_period=wr_period,
880 1100 thisDatetime=thisDatetime,
881 1101 update_figfile=update_figfile)
882 1102
883 1103 return dataOut
884 1104
885 1105 @MPDecorator
886 1106 class PowerProfilePlot_(Figure):
887 1107
888 1108 isConfig = None
889 1109 __nsubplots = None
890 1110
891 1111 WIDTHPROF = None
892 1112 HEIGHTPROF = None
893 1113 PREFIX = 'spcprofile'
894 1114
895 1115 def __init__(self):
896 1116 Figure.__init__(self)
897 1117 self.isConfig = False
898 1118 self.__nsubplots = 1
899 1119
900 1120 self.PLOT_CODE = POWER_CODE
901 1121
902 1122 self.WIDTH = 300
903 1123 self.HEIGHT = 500
904 1124 self.counter_imagwr = 0
905 1125
906 1126 def getSubplots(self):
907 1127 ncol = 1
908 1128 nrow = 1
909 1129
910 1130 return nrow, ncol
911 1131
912 1132 def setup(self, id, nplots, wintitle, show):
913 1133
914 1134 self.nplots = nplots
915 1135
916 1136 ncolspan = 1
917 1137 colspan = 1
918 1138
919 1139 self.createFigure(id = id,
920 1140 wintitle = wintitle,
921 1141 widthplot = self.WIDTH,
922 1142 heightplot = self.HEIGHT,
923 1143 show=show)
924 1144
925 1145 nrow, ncol = self.getSubplots()
926 1146
927 1147 counter = 0
928 1148 for y in range(nrow):
929 1149 for x in range(ncol):
930 1150 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
931 1151
932 1152 def run(self, dataOut, id, wintitle="", channelList=None,
933 1153 xmin=None, xmax=None, ymin=None, ymax=None,
934 1154 save=False, figpath='./', figfile=None, show=True,
935 1155 ftp=False, wr_period=1, server=None,
936 1156 folder=None, username=None, password=None):
937 1157
938 if dataOut.flagNoData:
1158 if dataOut.flagNoData:
939 1159 return dataOut
940 1160
941 1161
942 1162 if channelList == None:
943 1163 channelIndexList = dataOut.channelIndexList
944 1164 channelList = dataOut.channelList
945 1165 else:
946 1166 channelIndexList = []
947 1167 for channel in channelList:
948 1168 if channel not in dataOut.channelList:
949 1169 raise ValueError("Channel %d is not in dataOut.channelList")
950 1170 channelIndexList.append(dataOut.channelList.index(channel))
951 1171
952 1172 factor = dataOut.normFactor
953 1173
954 1174 y = dataOut.getHeiRange()
955 1175
956 1176 #for voltage
957 1177 if dataOut.type == 'Voltage':
958 1178 x = dataOut.data[channelIndexList,:] * numpy.conjugate(dataOut.data[channelIndexList,:])
959 1179 x = x.real
960 1180 x = numpy.where(numpy.isfinite(x), x, numpy.NAN)
961 1181
962 1182 #for spectra
963 1183 if dataOut.type == 'Spectra':
964 1184 x = dataOut.data_spc[channelIndexList,:,:]/factor
965 1185 x = numpy.where(numpy.isfinite(x), x, numpy.NAN)
966 1186 x = numpy.average(x, axis=1)
967 1187
968 1188
969 1189 xdB = 10*numpy.log10(x)
970 1190
971 1191 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
972 1192 title = wintitle + " Power Profile %s" %(thisDatetime.strftime("%d-%b-%Y"))
973 1193 xlabel = "dB"
974 1194 ylabel = "Range (Km)"
975 1195
976 1196 if not self.isConfig:
977 1197
978 1198 nplots = 1
979 1199
980 1200 self.setup(id=id,
981 1201 nplots=nplots,
982 1202 wintitle=wintitle,
983 1203 show=show)
984 1204
985 1205 if ymin == None: ymin = numpy.nanmin(y)
986 1206 if ymax == None: ymax = numpy.nanmax(y)
987 1207 if xmin == None: xmin = numpy.nanmin(xdB)*0.9
988 1208 if xmax == None: xmax = numpy.nanmax(xdB)*1.1
989 1209
990 1210 self.isConfig = True
991 1211
992 1212 self.setWinTitle(title)
993 1213
994 1214 title = "Power Profile: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
995 1215 axes = self.axesList[0]
996 1216
997 1217 legendlabels = ["channel %d"%x for x in channelList]
998 1218 axes.pmultiline(xdB, y,
999 1219 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1000 1220 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels,
1001 1221 ytick_visible=True, nxticks=5,
1002 1222 grid='x')
1003 1223
1004 1224 self.draw()
1005 1225
1006 1226 self.save(figpath=figpath,
1007 1227 figfile=figfile,
1008 1228 save=save,
1009 1229 ftp=ftp,
1010 1230 wr_period=wr_period,
1011 1231 thisDatetime=thisDatetime)
1012
1232
1013 1233 return dataOut
1014 1234
1015 1235 @MPDecorator
1016 1236 class SpectraCutPlot_(Figure):
1017 1237
1018 1238 isConfig = None
1019 1239 __nsubplots = None
1020 1240
1021 1241 WIDTHPROF = None
1022 1242 HEIGHTPROF = None
1023 1243 PREFIX = 'spc_cut'
1024 1244
1025 1245 def __init__(self):
1026 1246 Figure.__init__(self)
1027 1247 self.isConfig = False
1028 1248 self.__nsubplots = 1
1029 1249
1030 1250 self.PLOT_CODE = POWER_CODE
1031 1251
1032 1252 self.WIDTH = 700
1033 1253 self.HEIGHT = 500
1034 1254 self.counter_imagwr = 0
1035 1255
1036 1256 def getSubplots(self):
1037 1257 ncol = 1
1038 1258 nrow = 1
1039 1259
1040 1260 return nrow, ncol
1041 1261
1042 1262 def setup(self, id, nplots, wintitle, show):
1043 1263
1044 1264 self.nplots = nplots
1045 1265
1046 1266 ncolspan = 1
1047 1267 colspan = 1
1048 1268
1049 1269 self.createFigure(id = id,
1050 1270 wintitle = wintitle,
1051 1271 widthplot = self.WIDTH,
1052 1272 heightplot = self.HEIGHT,
1053 1273 show=show)
1054 1274
1055 1275 nrow, ncol = self.getSubplots()
1056 1276
1057 1277 counter = 0
1058 1278 for y in range(nrow):
1059 1279 for x in range(ncol):
1060 1280 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1061 1281
1062 1282 def run(self, dataOut, id, wintitle="", channelList=None,
1063 1283 xmin=None, xmax=None, ymin=None, ymax=None,
1064 1284 save=False, figpath='./', figfile=None, show=True,
1065 1285 ftp=False, wr_period=1, server=None,
1066 1286 folder=None, username=None, password=None,
1067 1287 xaxis="frequency"):
1068 1288
1069 if dataOut.flagNoData:
1289 if dataOut.flagNoData:
1070 1290 return dataOut
1071 1291
1072 1292 if channelList == None:
1073 1293 channelIndexList = dataOut.channelIndexList
1074 1294 channelList = dataOut.channelList
1075 1295 else:
1076 1296 channelIndexList = []
1077 1297 for channel in channelList:
1078 1298 if channel not in dataOut.channelList:
1079 1299 raise ValueError("Channel %d is not in dataOut.channelList")
1080 1300 channelIndexList.append(dataOut.channelList.index(channel))
1081 1301
1082 1302 factor = dataOut.normFactor
1083 1303
1084 1304 y = dataOut.getHeiRange()
1085 1305
1086 1306 z = dataOut.data_spc/factor
1087 1307 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1088 1308
1089 1309 hei_index = numpy.arange(25)*3 + 20
1090 1310
1091 1311 if xaxis == "frequency":
1092 1312 x = dataOut.getFreqRange()/1000.
1093 1313 zdB = 10*numpy.log10(z[0,:,hei_index])
1094 1314 xlabel = "Frequency (kHz)"
1095 1315 ylabel = "Power (dB)"
1096 1316
1097 1317 elif xaxis == "time":
1098 1318 x = dataOut.getAcfRange()
1099 1319 zdB = z[0,:,hei_index]
1100 1320 xlabel = "Time (ms)"
1101 1321 ylabel = "ACF"
1102 1322
1103 1323 else:
1104 1324 x = dataOut.getVelRange()
1105 1325 zdB = 10*numpy.log10(z[0,:,hei_index])
1106 1326 xlabel = "Velocity (m/s)"
1107 1327 ylabel = "Power (dB)"
1108 1328
1109 1329 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1110 1330 title = wintitle + " Range Cuts %s" %(thisDatetime.strftime("%d-%b-%Y"))
1111 1331
1112 1332 if not self.isConfig:
1113 1333
1114 1334 nplots = 1
1115 1335
1116 1336 self.setup(id=id,
1117 1337 nplots=nplots,
1118 1338 wintitle=wintitle,
1119 1339 show=show)
1120 1340
1121 1341 if xmin == None: xmin = numpy.nanmin(x)*0.9
1122 1342 if xmax == None: xmax = numpy.nanmax(x)*1.1
1123 1343 if ymin == None: ymin = numpy.nanmin(zdB)
1124 1344 if ymax == None: ymax = numpy.nanmax(zdB)
1125 1345
1126 1346 self.isConfig = True
1127 1347
1128 1348 self.setWinTitle(title)
1129 1349
1130 1350 title = "Spectra Cuts: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
1131 1351 axes = self.axesList[0]
1132 1352
1133 1353 legendlabels = ["Range = %dKm" %y[i] for i in hei_index]
1134 1354
1135 1355 axes.pmultilineyaxis( x, zdB,
1136 1356 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1137 1357 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels,
1138 1358 ytick_visible=True, nxticks=5,
1139 1359 grid='x')
1140 1360
1141 1361 self.draw()
1142 1362
1143 1363 self.save(figpath=figpath,
1144 1364 figfile=figfile,
1145 1365 save=save,
1146 1366 ftp=ftp,
1147 1367 wr_period=wr_period,
1148 1368 thisDatetime=thisDatetime)
1149 1369
1150 1370 return dataOut
1151 1371
1152 1372 @MPDecorator
1153 1373 class Noise_(Figure):
1154 1374
1155 1375 isConfig = None
1156 1376 __nsubplots = None
1157 1377
1158 1378 PREFIX = 'noise'
1159 1379
1160 1380
1161 1381 def __init__(self):
1162 1382 Figure.__init__(self)
1163 1383 self.timerange = 24*60*60
1164 1384 self.isConfig = False
1165 1385 self.__nsubplots = 1
1166 1386 self.counter_imagwr = 0
1167 1387 self.WIDTH = 800
1168 1388 self.HEIGHT = 400
1169 1389 self.WIDTHPROF = 120
1170 1390 self.HEIGHTPROF = 0
1171 1391 self.xdata = None
1172 1392 self.ydata = None
1173 1393
1174 1394 self.PLOT_CODE = NOISE_CODE
1175 1395
1176 1396 self.FTP_WEI = None
1177 1397 self.EXP_CODE = None
1178 1398 self.SUB_EXP_CODE = None
1179 1399 self.PLOT_POS = None
1180 1400 self.figfile = None
1181 1401
1182 1402 self.xmin = None
1183 1403 self.xmax = None
1184 1404
1185 1405 def getSubplots(self):
1186 1406
1187 1407 ncol = 1
1188 1408 nrow = 1
1189 1409
1190 1410 return nrow, ncol
1191 1411
1192 1412 def openfile(self, filename):
1193 1413 dirname = os.path.dirname(filename)
1194 1414
1195 1415 if not os.path.exists(dirname):
1196 1416 os.mkdir(dirname)
1197 1417
1198 1418 f = open(filename,'w+')
1199 1419 f.write('\n\n')
1200 1420 f.write('JICAMARCA RADIO OBSERVATORY - Noise \n')
1201 1421 f.write('DD MM YYYY HH MM SS Channel0 Channel1 Channel2 Channel3\n\n' )
1202 1422 f.close()
1203 1423
1204 1424 def save_data(self, filename_phase, data, data_datetime):
1205 1425
1206 1426 f=open(filename_phase,'a')
1207 1427
1208 1428 timetuple_data = data_datetime.timetuple()
1209 1429 day = str(timetuple_data.tm_mday)
1210 1430 month = str(timetuple_data.tm_mon)
1211 1431 year = str(timetuple_data.tm_year)
1212 1432 hour = str(timetuple_data.tm_hour)
1213 1433 minute = str(timetuple_data.tm_min)
1214 1434 second = str(timetuple_data.tm_sec)
1215 1435
1216 1436 data_msg = ''
1217 1437 for i in range(len(data)):
1218 1438 data_msg += str(data[i]) + ' '
1219 1439
1220 1440 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' ' + data_msg + '\n')
1221 1441 f.close()
1222 1442
1223 1443
1224 1444 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1225 1445
1226 1446 self.__showprofile = showprofile
1227 1447 self.nplots = nplots
1228 1448
1229 1449 ncolspan = 7
1230 1450 colspan = 6
1231 1451 self.__nsubplots = 2
1232 1452
1233 1453 self.createFigure(id = id,
1234 1454 wintitle = wintitle,
1235 1455 widthplot = self.WIDTH+self.WIDTHPROF,
1236 1456 heightplot = self.HEIGHT+self.HEIGHTPROF,
1237 1457 show=show)
1238 1458
1239 1459 nrow, ncol = self.getSubplots()
1240 1460
1241 1461 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1242 1462
1243 1463
1244 1464 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
1245 1465 xmin=None, xmax=None, ymin=None, ymax=None,
1246 1466 timerange=None,
1247 1467 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1248 1468 server=None, folder=None, username=None, password=None,
1249 1469 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1250 1470
1251 if dataOut.flagNoData:
1471 if dataOut.flagNoData:
1252 1472 return dataOut
1253 1473
1254 1474 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1255 1475 return
1256 1476
1257 1477 if channelList == None:
1258 1478 channelIndexList = dataOut.channelIndexList
1259 1479 channelList = dataOut.channelList
1260 1480 else:
1261 1481 channelIndexList = []
1262 1482 for channel in channelList:
1263 1483 if channel not in dataOut.channelList:
1264 1484 raise ValueError("Channel %d is not in dataOut.channelList")
1265 1485 channelIndexList.append(dataOut.channelList.index(channel))
1266 1486
1267 1487 x = dataOut.getTimeRange()
1268 1488 #y = dataOut.getHeiRange()
1269 1489 factor = dataOut.normFactor
1270 1490 noise = dataOut.noise[channelIndexList]/factor
1271 1491 noisedB = 10*numpy.log10(noise)
1272 1492
1273 1493 thisDatetime = dataOut.datatime
1274 1494
1275 1495 title = wintitle + " Noise" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1276 1496 xlabel = ""
1277 1497 ylabel = "Intensity (dB)"
1278 1498 update_figfile = False
1279 1499
1280 1500 if not self.isConfig:
1281 1501
1282 1502 nplots = 1
1283 1503
1284 1504 self.setup(id=id,
1285 1505 nplots=nplots,
1286 1506 wintitle=wintitle,
1287 1507 showprofile=showprofile,
1288 1508 show=show)
1289 1509
1290 1510 if timerange != None:
1291 1511 self.timerange = timerange
1292 1512
1293 1513 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1294 1514
1295 1515 if ymin == None: ymin = numpy.floor(numpy.nanmin(noisedB)) - 10.0
1296 1516 if ymax == None: ymax = numpy.nanmax(noisedB) + 10.0
1297 1517
1298 1518 self.FTP_WEI = ftp_wei
1299 1519 self.EXP_CODE = exp_code
1300 1520 self.SUB_EXP_CODE = sub_exp_code
1301 1521 self.PLOT_POS = plot_pos
1302 1522
1303 1523
1304 1524 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1305 1525 self.isConfig = True
1306 1526 self.figfile = figfile
1307 1527 self.xdata = numpy.array([])
1308 1528 self.ydata = numpy.array([])
1309 1529
1310 1530 update_figfile = True
1311 1531
1312 1532 #open file beacon phase
1313 1533 path = '%s%03d' %(self.PREFIX, self.id)
1314 1534 noise_file = os.path.join(path,'%s.txt'%self.name)
1315 1535 self.filename_noise = os.path.join(figpath,noise_file)
1316 1536
1317 1537 self.setWinTitle(title)
1318 1538
1319 1539 title = "Noise %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1320 1540
1321 1541 legendlabels = ["channel %d"%(idchannel) for idchannel in channelList]
1322 1542 axes = self.axesList[0]
1323 1543
1324 1544 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1325 1545
1326 1546 if len(self.ydata)==0:
1327 1547 self.ydata = noisedB.reshape(-1,1)
1328 1548 else:
1329 1549 self.ydata = numpy.hstack((self.ydata, noisedB.reshape(-1,1)))
1330 1550
1331 1551
1332 1552 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1333 1553 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1334 1554 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1335 1555 XAxisAsTime=True, grid='both'
1336 1556 )
1337 1557
1338 1558 self.draw()
1339 1559
1340 1560 if dataOut.ltctime >= self.xmax:
1341 1561 self.counter_imagwr = wr_period
1342 1562 self.isConfig = False
1343 1563 update_figfile = True
1344 1564
1345 1565 self.save(figpath=figpath,
1346 1566 figfile=figfile,
1347 1567 save=save,
1348 1568 ftp=ftp,
1349 1569 wr_period=wr_period,
1350 1570 thisDatetime=thisDatetime,
1351 1571 update_figfile=update_figfile)
1352 1572
1353 1573 #store data beacon phase
1354 1574 if save:
1355 1575 self.save_data(self.filename_noise, noisedB, thisDatetime)
1356 1576
1357 1577 return dataOut
1358 1578
1359 1579 @MPDecorator
1360 1580 class BeaconPhase_(Figure):
1361 1581
1362 1582 __isConfig = None
1363 1583 __nsubplots = None
1364 1584
1365 1585 PREFIX = 'beacon_phase'
1366 1586
1367 1587 def __init__(self):
1368 1588 Figure.__init__(self)
1369 1589 self.timerange = 24*60*60
1370 1590 self.isConfig = False
1371 1591 self.__nsubplots = 1
1372 1592 self.counter_imagwr = 0
1373 1593 self.WIDTH = 800
1374 1594 self.HEIGHT = 400
1375 1595 self.WIDTHPROF = 120
1376 1596 self.HEIGHTPROF = 0
1377 1597 self.xdata = None
1378 1598 self.ydata = None
1379 1599
1380 1600 self.PLOT_CODE = BEACON_CODE
1381 1601
1382 1602 self.FTP_WEI = None
1383 1603 self.EXP_CODE = None
1384 1604 self.SUB_EXP_CODE = None
1385 1605 self.PLOT_POS = None
1386 1606
1387 1607 self.filename_phase = None
1388 1608
1389 1609 self.figfile = None
1390 1610
1391 1611 self.xmin = None
1392 1612 self.xmax = None
1393 1613
1394 1614 def getSubplots(self):
1395 1615
1396 1616 ncol = 1
1397 1617 nrow = 1
1398 1618
1399 1619 return nrow, ncol
1400 1620
1401 1621 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1402 1622
1403 1623 self.__showprofile = showprofile
1404 1624 self.nplots = nplots
1405 1625
1406 1626 ncolspan = 7
1407 1627 colspan = 6
1408 1628 self.__nsubplots = 2
1409 1629
1410 1630 self.createFigure(id = id,
1411 1631 wintitle = wintitle,
1412 1632 widthplot = self.WIDTH+self.WIDTHPROF,
1413 1633 heightplot = self.HEIGHT+self.HEIGHTPROF,
1414 1634 show=show)
1415 1635
1416 1636 nrow, ncol = self.getSubplots()
1417 1637
1418 1638 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1419 1639
1420 1640 def save_phase(self, filename_phase):
1421 1641 f = open(filename_phase,'w+')
1422 1642 f.write('\n\n')
1423 1643 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1424 1644 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1425 1645 f.close()
1426 1646
1427 1647 def save_data(self, filename_phase, data, data_datetime):
1428 1648 f=open(filename_phase,'a')
1429 1649 timetuple_data = data_datetime.timetuple()
1430 1650 day = str(timetuple_data.tm_mday)
1431 1651 month = str(timetuple_data.tm_mon)
1432 1652 year = str(timetuple_data.tm_year)
1433 1653 hour = str(timetuple_data.tm_hour)
1434 1654 minute = str(timetuple_data.tm_min)
1435 1655 second = str(timetuple_data.tm_sec)
1436 1656 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1437 1657 f.close()
1438 1658
1439 1659
1440 1660 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1441 1661 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1442 1662 timerange=None,
1443 1663 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1444 1664 server=None, folder=None, username=None, password=None,
1445 1665 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1446 1666
1447 if dataOut.flagNoData:
1667 if dataOut.flagNoData:
1448 1668 return dataOut
1449 1669
1450 1670 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1451 1671 return
1452 1672
1453 1673 if pairsList == None:
1454 1674 pairsIndexList = dataOut.pairsIndexList[:10]
1455 1675 else:
1456 1676 pairsIndexList = []
1457 1677 for pair in pairsList:
1458 1678 if pair not in dataOut.pairsList:
1459 1679 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1460 1680 pairsIndexList.append(dataOut.pairsList.index(pair))
1461 1681
1462 1682 if pairsIndexList == []:
1463 1683 return
1464 1684
1465 1685 # if len(pairsIndexList) > 4:
1466 1686 # pairsIndexList = pairsIndexList[0:4]
1467 1687
1468 1688 hmin_index = None
1469 1689 hmax_index = None
1470 1690
1471 1691 if hmin != None and hmax != None:
1472 1692 indexes = numpy.arange(dataOut.nHeights)
1473 1693 hmin_list = indexes[dataOut.heightList >= hmin]
1474 1694 hmax_list = indexes[dataOut.heightList <= hmax]
1475 1695
1476 1696 if hmin_list.any():
1477 1697 hmin_index = hmin_list[0]
1478 1698
1479 1699 if hmax_list.any():
1480 1700 hmax_index = hmax_list[-1]+1
1481 1701
1482 1702 x = dataOut.getTimeRange()
1483 1703 #y = dataOut.getHeiRange()
1484 1704
1485 1705
1486 1706 thisDatetime = dataOut.datatime
1487 1707
1488 1708 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1489 1709 xlabel = "Local Time"
1490 1710 ylabel = "Phase (degrees)"
1491 1711
1492 1712 update_figfile = False
1493 1713
1494 1714 nplots = len(pairsIndexList)
1495 1715 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1496 1716 phase_beacon = numpy.zeros(len(pairsIndexList))
1497 1717 for i in range(nplots):
1498 1718 pair = dataOut.pairsList[pairsIndexList[i]]
1499 1719 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1500 1720 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1501 1721 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1502 1722 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1503 1723 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1504 1724
1505 1725 if dataOut.beacon_heiIndexList:
1506 1726 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1507 1727 else:
1508 1728 phase_beacon[i] = numpy.average(phase)
1509 1729
1510 1730 if not self.isConfig:
1511 1731
1512 1732 nplots = len(pairsIndexList)
1513 1733
1514 1734 self.setup(id=id,
1515 1735 nplots=nplots,
1516 1736 wintitle=wintitle,
1517 1737 showprofile=showprofile,
1518 1738 show=show)
1519 1739
1520 1740 if timerange != None:
1521 1741 self.timerange = timerange
1522 1742
1523 1743 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1524 1744
1525 1745 if ymin == None: ymin = 0
1526 1746 if ymax == None: ymax = 360
1527 1747
1528 1748 self.FTP_WEI = ftp_wei
1529 1749 self.EXP_CODE = exp_code
1530 1750 self.SUB_EXP_CODE = sub_exp_code
1531 1751 self.PLOT_POS = plot_pos
1532 1752
1533 1753 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1534 1754 self.isConfig = True
1535 1755 self.figfile = figfile
1536 1756 self.xdata = numpy.array([])
1537 1757 self.ydata = numpy.array([])
1538 1758
1539 1759 update_figfile = True
1540 1760
1541 1761 #open file beacon phase
1542 1762 path = '%s%03d' %(self.PREFIX, self.id)
1543 1763 beacon_file = os.path.join(path,'%s.txt'%self.name)
1544 1764 self.filename_phase = os.path.join(figpath,beacon_file)
1545 1765 #self.save_phase(self.filename_phase)
1546 1766
1547 1767
1548 1768 #store data beacon phase
1549 1769 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1550 1770
1551 1771 self.setWinTitle(title)
1552 1772
1553 1773
1554 1774 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1555 1775
1556 1776 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1557 1777
1558 1778 axes = self.axesList[0]
1559 1779
1560 1780 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1561 1781
1562 1782 if len(self.ydata)==0:
1563 1783 self.ydata = phase_beacon.reshape(-1,1)
1564 1784 else:
1565 1785 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1566 1786
1567 1787
1568 1788 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1569 1789 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1570 1790 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1571 1791 XAxisAsTime=True, grid='both'
1572 1792 )
1573 1793
1574 1794 self.draw()
1575 1795
1576 1796 if dataOut.ltctime >= self.xmax:
1577 1797 self.counter_imagwr = wr_period
1578 1798 self.isConfig = False
1579 1799 update_figfile = True
1580 1800
1581 1801 self.save(figpath=figpath,
1582 1802 figfile=figfile,
1583 1803 save=save,
1584 1804 ftp=ftp,
1585 1805 wr_period=wr_period,
1586 1806 thisDatetime=thisDatetime,
1587 1807 update_figfile=update_figfile)
1588 1808
1589 return dataOut No newline at end of file
1809 return dataOut
@@ -1,232 +1,294
1 1 '''
2 2 Created on Jul 9, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator #YONG
10 10 from schainpy.utils import log
11 11 from .figure import Figure
12 12
13 13
14 14 @MPDecorator
15 15 class Scope_(Figure):
16
16
17 17 isConfig = None
18
18
19 19 def __init__(self):#, **kwargs): #YONG
20 20 Figure.__init__(self)#, **kwargs)
21 21 self.isConfig = False
22 22 self.WIDTH = 300
23 23 self.HEIGHT = 200
24 24 self.counter_imagwr = 0
25
25
26 26 def getSubplots(self):
27
27
28 28 nrow = self.nplots
29 29 ncol = 3
30 30 return nrow, ncol
31
31
32 32 def setup(self, id, nplots, wintitle, show):
33
33
34 34 self.nplots = nplots
35
36 self.createFigure(id=id,
37 wintitle=wintitle,
35
36 self.createFigure(id=id,
37 wintitle=wintitle,
38 38 show=show)
39
39
40 40 nrow,ncol = self.getSubplots()
41 41 colspan = 3
42 42 rowspan = 1
43
43
44 44 for i in range(nplots):
45 45 self.addAxes(nrow, ncol, i, 0, colspan, rowspan)
46
46
47 47 def plot_iq(self, x, y, id, channelIndexList, thisDatetime, wintitle, show, xmin, xmax, ymin, ymax):
48 48 yreal = y[channelIndexList,:].real
49 49 yimag = y[channelIndexList,:].imag
50
50
51 51 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
52 52 xlabel = "Range (Km)"
53 53 ylabel = "Intensity - IQ"
54
54
55 55 if not self.isConfig:
56 56 nplots = len(channelIndexList)
57
57
58 58 self.setup(id=id,
59 59 nplots=nplots,
60 60 wintitle='',
61 61 show=show)
62
62
63 63 if xmin == None: xmin = numpy.nanmin(x)
64 64 if xmax == None: xmax = numpy.nanmax(x)
65 65 if ymin == None: ymin = min(numpy.nanmin(yreal),numpy.nanmin(yimag))
66 66 if ymax == None: ymax = max(numpy.nanmax(yreal),numpy.nanmax(yimag))
67
67
68 68 self.isConfig = True
69
69
70 70 self.setWinTitle(title)
71
71
72 72 for i in range(len(self.axesList)):
73 73 title = "Channel %d" %(i)
74 74 axes = self.axesList[i]
75 75
76 76 axes.pline(x, yreal[i,:],
77 77 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
78 78 xlabel=xlabel, ylabel=ylabel, title=title)
79 79
80 80 axes.addpline(x, yimag[i,:], idline=1, color="red", linestyle="solid", lw=2)
81
81
82 82 def plot_power(self, x, y, id, channelIndexList, thisDatetime, wintitle, show, xmin, xmax, ymin, ymax):
83 83 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
84 84 yreal = y.real
85
85
86 86 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
87 87 xlabel = "Range (Km)"
88 88 ylabel = "Intensity"
89
89
90 90 if not self.isConfig:
91 91 nplots = len(channelIndexList)
92
92
93 93 self.setup(id=id,
94 94 nplots=nplots,
95 95 wintitle='',
96 96 show=show)
97
97
98 98 if xmin == None: xmin = numpy.nanmin(x)
99 99 if xmax == None: xmax = numpy.nanmax(x)
100 100 if ymin == None: ymin = numpy.nanmin(yreal)
101 101 if ymax == None: ymax = numpy.nanmax(yreal)
102
102
103 103 self.isConfig = True
104
104
105 105 self.setWinTitle(title)
106
106
107 107 for i in range(len(self.axesList)):
108 108 title = "Channel %d" %(i)
109 109 axes = self.axesList[i]
110 110 ychannel = yreal[i,:]
111 111 axes.pline(x, ychannel,
112 112 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
113 113 xlabel=xlabel, ylabel=ylabel, title=title)
114 114
115
115 def plot_weatherpower(self, x, y, id, channelIndexList, thisDatetime, wintitle, show, xmin, xmax, ymin, ymax):
116 y = y[channelIndexList,:]
117 yreal = y
118
119 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
120 xlabel = "Range (Km)"
121 ylabel = "Intensity"
122
123 if not self.isConfig:
124 nplots = len(channelIndexList)
125
126 self.setup(id=id,
127 nplots=nplots,
128 wintitle='',
129 show=show)
130
131 if xmin == None: xmin = numpy.nanmin(x)
132 if xmax == None: xmax = numpy.nanmax(x)
133 if ymin == None: ymin = numpy.nanmin(yreal)
134 if ymax == None: ymax = numpy.nanmax(yreal)
135
136 self.isConfig = True
137
138 self.setWinTitle(title)
139
140 for i in range(len(self.axesList)):
141 title = "Channel %d" %(i)
142 axes = self.axesList[i]
143 ychannel = yreal[i,:]
144 axes.pline(x, ychannel,
145 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
146 xlabel=xlabel, ylabel=ylabel, title=title)
147
148
149
116 150 def run(self, dataOut, id, wintitle="", channelList=None,
117 151 xmin=None, xmax=None, ymin=None, ymax=None, save=False,
118 152 figpath='./', figfile=None, show=True, wr_period=1,
119 153 ftp=False, server=None, folder=None, username=None, password=None, type='power', **kwargs):
120
154
121 155 """
122
156
123 157 Input:
124 158 dataOut :
125 159 id :
126 160 wintitle :
127 161 channelList :
128 162 xmin : None,
129 163 xmax : None,
130 164 ymin : None,
131 165 ymax : None,
132 166 """
133 if dataOut.flagNoData:
167 if dataOut.flagNoData:
134 168 return dataOut
135
169
136 170 if channelList == None:
137 171 channelIndexList = dataOut.channelIndexList
138 172 else:
139 173 channelIndexList = []
140 174 for channel in channelList:
141 175 if channel not in dataOut.channelList:
142 176 raise ValueError("Channel %d is not in dataOut.channelList")
143 177 channelIndexList.append(dataOut.channelList.index(channel))
144
178
145 179 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
146
180 ### print("***************** PLOTEO **************************")
181 ### print(dataOut.nProfiles)
182 ### print(dataOut.heightList.shape)
147 183 if dataOut.flagDataAsBlock:
148
184
149 185 for i in range(dataOut.nProfiles):
150
186
151 187 wintitle1 = wintitle + " [Profile = %d] " %i
152
188
153 189 if type == "power":
154 self.plot_power(dataOut.heightList,
190 self.plot_power(dataOut.heightList,
155 191 dataOut.data[:,i,:],
156 id,
157 channelIndexList,
192 id,
193 channelIndexList,
158 194 thisDatetime,
159 195 wintitle1,
160 196 show,
161 197 xmin,
162 198 xmax,
163 199 ymin,
164 200 ymax)
165
201
202 if type == "weatherpower":
203 self.plot_weatherpower(dataOut.heightList,
204 dataOut.data[:,i,:],
205 id,
206 channelIndexList,
207 thisDatetime,
208 wintitle1,
209 show,
210 xmin,
211 xmax,
212 ymin,
213 ymax)
214
215 if type == "weathervelocity":
216 self.plot_weatherpower(dataOut.heightList,
217 dataOut.data_velocity[:,i,:],
218 id,
219 channelIndexList,
220 thisDatetime,
221 wintitle1,
222 show,
223 xmin,
224 xmax,
225 ymin,
226 ymax)
227
166 228 if type == "iq":
167 self.plot_iq(dataOut.heightList,
229 self.plot_iq(dataOut.heightList,
168 230 dataOut.data[:,i,:],
169 id,
170 channelIndexList,
231 id,
232 channelIndexList,
171 233 thisDatetime,
172 234 wintitle1,
173 235 show,
174 236 xmin,
175 237 xmax,
176 238 ymin,
177 239 ymax)
178
240
179 241 self.draw()
180
242
181 243 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
182 244 figfile = self.getFilename(name = str_datetime) + "_" + str(i)
183
245
184 246 self.save(figpath=figpath,
185 247 figfile=figfile,
186 248 save=save,
187 249 ftp=ftp,
188 250 wr_period=wr_period,
189 251 thisDatetime=thisDatetime)
190
252
191 253 else:
192 254 wintitle += " [Profile = %d] " %dataOut.profileIndex
193
255
194 256 if type == "power":
195 self.plot_power(dataOut.heightList,
257 self.plot_power(dataOut.heightList,
196 258 dataOut.data,
197 id,
198 channelIndexList,
259 id,
260 channelIndexList,
199 261 thisDatetime,
200 262 wintitle,
201 263 show,
202 264 xmin,
203 265 xmax,
204 266 ymin,
205 267 ymax)
206
268
207 269 if type == "iq":
208 self.plot_iq(dataOut.heightList,
270 self.plot_iq(dataOut.heightList,
209 271 dataOut.data,
210 id,
211 channelIndexList,
272 id,
273 channelIndexList,
212 274 thisDatetime,
213 275 wintitle,
214 276 show,
215 277 xmin,
216 278 xmax,
217 279 ymin,
218 280 ymax)
219
281
220 282 self.draw()
221
283
222 284 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S") + "_" + str(dataOut.profileIndex)
223 figfile = self.getFilename(name = str_datetime)
224
285 figfile = self.getFilename(name = str_datetime)
286
225 287 self.save(figpath=figpath,
226 288 figfile=figfile,
227 289 save=save,
228 290 ftp=ftp,
229 291 wr_period=wr_period,
230 292 thisDatetime=thisDatetime)
231 293
232 return dataOut No newline at end of file
294 return dataOut
@@ -1,28 +1,30
1 1 '''
2 2 @author: roj-idl71
3 3 '''
4 4 #USED IN jroplot_spectra.py
5 5 RTI_CODE = 0 #Range time intensity (RTI).
6 6 SPEC_CODE = 1 #Spectra (and Cross-spectra) information.
7 7 CROSS_CODE = 2 #Cross-Correlation information.
8 8 COH_CODE = 3 #Coherence map.
9 9 BASE_CODE = 4 #Base lines graphic.
10 10 ROW_CODE = 5 #Row Spectra.
11 11 TOTAL_CODE = 6 #Total Power.
12 12 DRIFT_CODE = 7 #Drifts graphics.
13 13 HEIGHT_CODE = 8 #Height profile.
14 14 PHASE_CODE = 9 #Signal Phase.
15 15
16 16 POWER_CODE = 16
17 17 NOISE_CODE = 17
18 18 BEACON_CODE = 18
19 19
20 20 #USED IN jroplot_parameters.py
21 21 WIND_CODE = 22
22 22 MSKYMAP_CODE = 23
23 23 MPHASE_CODE = 24
24 24
25 25 MOMENTS_CODE = 25
26 PARMS_CODE = 26
26 PARMS_CODE = 26
27 27 SPECFIT_CODE = 27
28 28 EWDRIFT_CODE = 28
29
30 WPO_CODE = 29 #Weather Intensity - Power
@@ -1,1435 +1,1458
1 1 import numpy
2 2 import time
3 3 import os
4 4 import h5py
5 5 import re
6 6 import datetime
7 7
8 8 import schainpy.admin
9 9 from schainpy.model.data.jrodata import *
10 10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 11 from schainpy.model.io.jroIO_base import *
12 12 from schainpy.utils import log
13 13
14 14 @MPDecorator
15 15 class ParamReader(JRODataReader,ProcessingUnit):
16 16 '''
17 17 Reads HDF5 format files
18 18 path
19 19 startDate
20 20 endDate
21 21 startTime
22 22 endTime
23 23 '''
24 24
25 25 ext = ".hdf5"
26 26 optchar = "D"
27 27 timezone = None
28 28 startTime = None
29 29 endTime = None
30 30 fileIndex = None
31 31 utcList = None #To select data in the utctime list
32 32 blockList = None #List to blocks to be read from the file
33 33 blocksPerFile = None #Number of blocks to be read
34 34 blockIndex = None
35 35 path = None
36 36 #List of Files
37 37 filenameList = None
38 38 datetimeList = None
39 39 #Hdf5 File
40 40 listMetaname = None
41 41 listMeta = None
42 42 listDataname = None
43 43 listData = None
44 44 listShapes = None
45 45 fp = None
46 46 #dataOut reconstruction
47 47 dataOut = None
48 48
49 49 def __init__(self):#, **kwargs):
50 50 ProcessingUnit.__init__(self) #, **kwargs)
51 51 self.dataOut = Parameters()
52 52 return
53 53
54 54 def setup(self, **kwargs):
55 55
56 56 path = kwargs['path']
57 57 startDate = kwargs['startDate']
58 58 endDate = kwargs['endDate']
59 59 startTime = kwargs['startTime']
60 60 endTime = kwargs['endTime']
61 61 walk = kwargs['walk']
62 62 if 'ext' in kwargs:
63 63 ext = kwargs['ext']
64 64 else:
65 65 ext = '.hdf5'
66 66 if 'timezone' in kwargs:
67 67 self.timezone = kwargs['timezone']
68 68 else:
69 69 self.timezone = 'lt'
70 70
71 71 print("[Reading] Searching files in offline mode ...")
72 72 pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate,
73 73 startTime=startTime, endTime=endTime,
74 74 ext=ext, walk=walk)
75 75
76 76 if not(filenameList):
77 77 print("There is no files into the folder: %s"%(path))
78 78 sys.exit(-1)
79 79
80 80 self.fileIndex = -1
81 81 self.startTime = startTime
82 82 self.endTime = endTime
83 83
84 84 self.__readMetadata()
85 85
86 86 self.__setNextFileOffline()
87 87
88 88 return
89 89
90 90 def searchFilesOffLine(self,
91 91 path,
92 92 startDate=None,
93 93 endDate=None,
94 94 startTime=datetime.time(0,0,0),
95 95 endTime=datetime.time(23,59,59),
96 96 ext='.hdf5',
97 97 walk=True):
98 98
99 99 expLabel = ''
100 100 self.filenameList = []
101 101 self.datetimeList = []
102 102
103 103 pathList = []
104 104
105 105 JRODataObj = JRODataReader()
106 106 dateList, pathList = JRODataObj.findDatafiles(path, startDate, endDate, expLabel, ext, walk, include_path=True)
107 107
108 108 if dateList == []:
109 109 print("[Reading] No *%s files in %s from %s to %s)"%(ext, path,
110 110 datetime.datetime.combine(startDate,startTime).ctime(),
111 111 datetime.datetime.combine(endDate,endTime).ctime()))
112 112
113 113 return None, None
114 114
115 115 if len(dateList) > 1:
116 116 print("[Reading] %d days were found in date range: %s - %s" %(len(dateList), startDate, endDate))
117 117 else:
118 118 print("[Reading] data was found for the date %s" %(dateList[0]))
119 119
120 120 filenameList = []
121 121 datetimeList = []
122 122
123 123 #----------------------------------------------------------------------------------
124 124
125 125 for thisPath in pathList:
126 126
127 127 fileList = glob.glob1(thisPath, "*%s" %ext)
128 128 fileList.sort()
129 129
130 130 for file in fileList:
131 131
132 132 filename = os.path.join(thisPath,file)
133 133
134 134 if not isFileInDateRange(filename, startDate, endDate):
135 135 continue
136 136
137 137 thisDatetime = self.__isFileInTimeRange(filename, startDate, endDate, startTime, endTime)
138 138
139 139 if not(thisDatetime):
140 140 continue
141 141
142 142 filenameList.append(filename)
143 143 datetimeList.append(thisDatetime)
144 144
145 145 if not(filenameList):
146 146 print("[Reading] Any file was found int time range %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime()))
147 147 return None, None
148 148
149 149 print("[Reading] %d file(s) was(were) found in time range: %s - %s" %(len(filenameList), startTime, endTime))
150 150 print()
151 151
152 152 self.filenameList = filenameList
153 153 self.datetimeList = datetimeList
154 154
155 155 return pathList, filenameList
156 156
157 157 def __isFileInTimeRange(self,filename, startDate, endDate, startTime, endTime):
158 158
159 159 """
160 160 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
161 161
162 162 Inputs:
163 163 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
164 164 startDate : fecha inicial del rango seleccionado en formato datetime.date
165 165 endDate : fecha final del rango seleccionado en formato datetime.date
166 166 startTime : tiempo inicial del rango seleccionado en formato datetime.time
167 167 endTime : tiempo final del rango seleccionado en formato datetime.time
168 168
169 169 Return:
170 170 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
171 171 fecha especificado, de lo contrario retorna False.
172 172
173 173 Excepciones:
174 174 Si el archivo no existe o no puede ser abierto
175 175 Si la cabecera no puede ser leida.
176 176
177 177 """
178 178
179 179 try:
180 180 fp = h5py.File(filename,'r')
181 181 grp1 = fp['Data']
182 182
183 183 except IOError:
184 184 traceback.print_exc()
185 185 raise IOError("The file %s can't be opened" %(filename))
186
186
187 187 #In case has utctime attribute
188 188 grp2 = grp1['utctime']
189 189 # thisUtcTime = grp2.value[0] - 5*3600 #To convert to local time
190 190 thisUtcTime = grp2.value[0]
191 191
192 192 fp.close()
193 193
194 194 if self.timezone == 'lt':
195 195 thisUtcTime -= 5*3600
196 196
197 197 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
198 198 thisDate = thisDatetime.date()
199 199 thisTime = thisDatetime.time()
200 200
201 201 startUtcTime = (datetime.datetime.combine(thisDate,startTime)- datetime.datetime(1970, 1, 1)).total_seconds()
202 202 endUtcTime = (datetime.datetime.combine(thisDate,endTime)- datetime.datetime(1970, 1, 1)).total_seconds()
203 203
204 204 #General case
205 205 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
206 206 #-----------o----------------------------o-----------
207 207 # startTime endTime
208 208
209 209 if endTime >= startTime:
210 210 thisUtcLog = numpy.logical_and(thisUtcTime > startUtcTime, thisUtcTime < endUtcTime)
211 211 if numpy.any(thisUtcLog): #If there is one block between the hours mentioned
212 212 return thisDatetime
213 213 return None
214 214
215 215 #If endTime < startTime then endTime belongs to the next day
216 216 #<<<<<<<<<<<o o>>>>>>>>>>>
217 217 #-----------o----------------------------o-----------
218 218 # endTime startTime
219 219
220 220 if (thisDate == startDate) and numpy.all(thisUtcTime < startUtcTime):
221 221 return None
222 222
223 223 if (thisDate == endDate) and numpy.all(thisUtcTime > endUtcTime):
224 224 return None
225 225
226 226 if numpy.all(thisUtcTime < startUtcTime) and numpy.all(thisUtcTime > endUtcTime):
227 227 return None
228 228
229 229 return thisDatetime
230 230
231 231 def __setNextFileOffline(self):
232 232
233 233 self.fileIndex += 1
234 234 idFile = self.fileIndex
235 235
236 236 if not(idFile < len(self.filenameList)):
237 237 raise schainpy.admin.SchainError("No more Files")
238 238 return 0
239 239
240 240 filename = self.filenameList[idFile]
241 241 filePointer = h5py.File(filename,'r')
242 242 self.filename = filename
243 243 self.fp = filePointer
244 244
245 245 print("Setting the file: %s"%self.filename)
246 246
247 247 self.__setBlockList()
248 248 self.__readData()
249 249 self.blockIndex = 0
250 250 return 1
251 251
252 252 def __setBlockList(self):
253 253 '''
254 254 Selects the data within the times defined
255 255
256 256 self.fp
257 257 self.startTime
258 258 self.endTime
259 259
260 260 self.blockList
261 261 self.blocksPerFile
262 262
263 263 '''
264 264 fp = self.fp
265 265 startTime = self.startTime
266 266 endTime = self.endTime
267 267
268 268 grp = fp['Data']
269 269 thisUtcTime = grp['utctime'].value.astype(numpy.float)[0]
270 270
271 271 #ERROOOOR
272 272 if self.timezone == 'lt':
273 273 thisUtcTime -= 5*3600
274 274
275 275 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
276 276
277 277 thisDate = thisDatetime.date()
278 278 thisTime = thisDatetime.time()
279 279
280 280 startUtcTime = (datetime.datetime.combine(thisDate,startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
281 281 endUtcTime = (datetime.datetime.combine(thisDate,endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
282 282
283 283 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
284 284
285 285 self.blockList = ind
286 286 self.blocksPerFile = len(ind)
287 287
288 288 return
289 289
290 290 def __readMetadata(self):
291 291 '''
292 292 Reads Metadata
293 293
294 294 self.pathMeta
295 295 self.listShapes
296 296 self.listMetaname
297 297 self.listMeta
298 298
299 299 '''
300 300
301 301 filename = self.filenameList[0]
302 302 fp = h5py.File(filename,'r')
303 303 gp = fp['Metadata']
304 304
305 305 listMetaname = []
306 306 listMetadata = []
307 307 for item in list(gp.items()):
308 308 name = item[0]
309 309
310 310 if name=='array dimensions':
311 311 table = gp[name][:]
312 312 listShapes = {}
313 313 for shapes in table:
314 314 listShapes[shapes[0]] = numpy.array([shapes[1],shapes[2],shapes[3],shapes[4],shapes[5]])
315 315 else:
316 316 data = gp[name].value
317 317 listMetaname.append(name)
318 318 listMetadata.append(data)
319 319
320 320 self.listShapes = listShapes
321 321 self.listMetaname = listMetaname
322 322 self.listMeta = listMetadata
323 323
324 324 fp.close()
325 325 return
326 326
327 327 def __readData(self):
328 328 grp = self.fp['Data']
329 329 listdataname = []
330 330 listdata = []
331 331
332 332 for item in list(grp.items()):
333 333 name = item[0]
334 334 listdataname.append(name)
335 335
336 336 array = self.__setDataArray(grp[name],self.listShapes[name])
337 337 listdata.append(array)
338 338
339 339 self.listDataname = listdataname
340 340 self.listData = listdata
341 341 return
342 342
343 343 def __setDataArray(self, dataset, shapes):
344 344
345 345 nDims = shapes[0]
346 346 nDim2 = shapes[1] #Dimension 0
347 347 nDim1 = shapes[2] #Dimension 1, number of Points or Parameters
348 348 nDim0 = shapes[3] #Dimension 2, number of samples or ranges
349 349 mode = shapes[4] #Mode of storing
350 350 blockList = self.blockList
351 351 blocksPerFile = self.blocksPerFile
352 352
353 353 #Depending on what mode the data was stored
354 354 if mode == 0: #Divided in channels
355 355 arrayData = dataset.value.astype(numpy.float)[0][blockList]
356 356 if mode == 1: #Divided in parameter
357 357 strds = 'table'
358 358 nDatas = nDim1
359 359 newShapes = (blocksPerFile,nDim2,nDim0)
360 360 elif mode==2: #Concatenated in a table
361 361 strds = 'table0'
362 362 arrayData = dataset[strds].value
363 363 #Selecting part of the dataset
364 364 utctime = arrayData[:,0]
365 365 u, indices = numpy.unique(utctime, return_index=True)
366 366
367 367 if blockList.size != indices.size:
368 368 indMin = indices[blockList[0]]
369 369 if blockList[1] + 1 >= indices.size:
370 370 arrayData = arrayData[indMin:,:]
371 371 else:
372 372 indMax = indices[blockList[1] + 1]
373 373 arrayData = arrayData[indMin:indMax,:]
374 374 return arrayData
375 375
376 376 # One dimension
377 377 if nDims == 0:
378 378 arrayData = dataset.value.astype(numpy.float)[0][blockList]
379 379
380 380 # Two dimensions
381 381 elif nDims == 2:
382 382 arrayData = numpy.zeros((blocksPerFile,nDim1,nDim0))
383 383 newShapes = (blocksPerFile,nDim0)
384 384 nDatas = nDim1
385 385
386 386 for i in range(nDatas):
387 387 data = dataset[strds + str(i)].value
388 388 arrayData[:,i,:] = data[blockList,:]
389 389
390 390 # Three dimensions
391 391 else:
392 392 arrayData = numpy.zeros((blocksPerFile,nDim2,nDim1,nDim0))
393 393 for i in range(nDatas):
394 394
395 395 data = dataset[strds + str(i)].value
396 396
397 397 for b in range(blockList.size):
398 398 arrayData[b,:,i,:] = data[:,:,blockList[b]]
399 399
400 400 return arrayData
401 401
402 402 def __setDataOut(self):
403 403 listMeta = self.listMeta
404 404 listMetaname = self.listMetaname
405 405 listDataname = self.listDataname
406 406 listData = self.listData
407 407 listShapes = self.listShapes
408 408
409 409 blockIndex = self.blockIndex
410 410 # blockList = self.blockList
411 411
412 412 for i in range(len(listMeta)):
413 413 setattr(self.dataOut,listMetaname[i],listMeta[i])
414 414
415 415 for j in range(len(listData)):
416 416 nShapes = listShapes[listDataname[j]][0]
417 417 mode = listShapes[listDataname[j]][4]
418 418 if nShapes == 1:
419 419 setattr(self.dataOut,listDataname[j],listData[j][blockIndex])
420 420 elif nShapes > 1:
421 421 setattr(self.dataOut,listDataname[j],listData[j][blockIndex,:])
422 422 elif mode==0:
423 423 setattr(self.dataOut,listDataname[j],listData[j][blockIndex])
424 424 #Mode Meteors
425 425 elif mode ==2:
426 426 selectedData = self.__selectDataMode2(listData[j], blockIndex)
427 427 setattr(self.dataOut, listDataname[j], selectedData)
428 428 return
429 429
430 430 def __selectDataMode2(self, data, blockIndex):
431 431 utctime = data[:,0]
432 432 aux, indices = numpy.unique(utctime, return_inverse=True)
433 433 selInd = numpy.where(indices == blockIndex)[0]
434 434 selData = data[selInd,:]
435 435
436 436 return selData
437 437
438 438 def getData(self):
439 439
440 440 if self.blockIndex==self.blocksPerFile:
441 441 if not( self.__setNextFileOffline() ):
442 442 self.dataOut.flagNoData = True
443 443 return 0
444 444
445 445 self.__setDataOut()
446 446 self.dataOut.flagNoData = False
447 447
448 448 self.blockIndex += 1
449 449
450 450 return
451 451
452 452 def run(self, **kwargs):
453 453
454 454 if not(self.isConfig):
455 455 self.setup(**kwargs)
456 456 self.isConfig = True
457 457
458 458 self.getData()
459 459
460 460 return
461 461
462 462 @MPDecorator
463 463 class ParamWriter(Operation):
464 464 '''
465 465 HDF5 Writer, stores parameters data in HDF5 format files
466 466
467 467 path: path where the files will be stored
468 468 blocksPerFile: number of blocks that will be saved in per HDF5 format file
469 469 mode: selects the data stacking mode: '0' channels, '1' parameters, '3' table (for meteors)
470 470 metadataList: list of attributes that will be stored as metadata
471 471 dataList: list of attributes that will be stores as data
472 472 '''
473 473
474 474 ext = ".hdf5"
475 475 optchar = "D"
476 476 metaoptchar = "M"
477 477 metaFile = None
478 478 filename = None
479 479 path = None
480 480 setFile = None
481 481 fp = None
482 482 grp = None
483 483 ds = None
484 484 firsttime = True
485 485 #Configurations
486 486 blocksPerFile = None
487 487 blockIndex = None
488 488 dataOut = None
489 489 #Data Arrays
490 490 dataList = None
491 491 metadataList = None
492 492 dsList = None #List of dictionaries with dataset properties
493 493 tableDim = None
494 494 dtype = [('arrayName', 'S20'),('nDimensions', 'i'), ('dim2', 'i'), ('dim1', 'i'),('dim0', 'i'),('mode', 'b')]
495 495 currentDay = None
496 496 lastTime = None
497 497 setType = None
498 498
499 499 def __init__(self):
500
500
501 501 Operation.__init__(self)
502 502 return
503 503
504 504 def setup(self, dataOut, path=None, blocksPerFile=10, metadataList=None, dataList=None, mode=None, setType=None):
505 505 self.path = path
506 506 self.blocksPerFile = blocksPerFile
507 507 self.metadataList = metadataList
508 508 self.dataList = dataList
509 509 self.dataOut = dataOut
510 510 self.mode = mode
511 511 if self.mode is not None:
512 512 self.mode = numpy.zeros(len(self.dataList)) + mode
513 513 else:
514 514 self.mode = numpy.ones(len(self.dataList))
515 515
516 516 self.setType = setType
517 517
518 518 arrayDim = numpy.zeros((len(self.dataList),5))
519 519
520 520 #Table dimensions
521 521 dtype0 = self.dtype
522 522 tableList = []
523 523
524 524 #Dictionary and list of tables
525 525 dsList = []
526 526
527 527 for i in range(len(self.dataList)):
528 528 dsDict = {}
529 529 dataAux = getattr(self.dataOut, self.dataList[i])
530 530 dsDict['variable'] = self.dataList[i]
531 531 #--------------------- Conditionals ------------------------
532 532 #There is no data
533
533
534 534 if dataAux is None:
535
535
536 536 return 0
537 537
538 538 if isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
539 539 dsDict['mode'] = 0
540 540 dsDict['nDim'] = 0
541 541 arrayDim[i,0] = 0
542 542 dsList.append(dsDict)
543 543
544 544 #Mode 2: meteors
545 545 elif self.mode[i] == 2:
546 546 dsDict['dsName'] = 'table0'
547 547 dsDict['mode'] = 2 # Mode meteors
548 548 dsDict['shape'] = dataAux.shape[-1]
549 549 dsDict['nDim'] = 0
550 550 dsDict['dsNumber'] = 1
551 551 arrayDim[i,3] = dataAux.shape[-1]
552 552 arrayDim[i,4] = self.mode[i] #Mode the data was stored
553 553 dsList.append(dsDict)
554 554
555 555 #Mode 1
556 556 else:
557 557 arrayDim0 = dataAux.shape #Data dimensions
558 558 arrayDim[i,0] = len(arrayDim0) #Number of array dimensions
559 559 arrayDim[i,4] = self.mode[i] #Mode the data was stored
560 560 strtable = 'table'
561 561 dsDict['mode'] = 1 # Mode parameters
562 562
563 563 # Three-dimension arrays
564 564 if len(arrayDim0) == 3:
565 565 arrayDim[i,1:-1] = numpy.array(arrayDim0)
566 566 nTables = int(arrayDim[i,2])
567 567 dsDict['dsNumber'] = nTables
568 568 dsDict['shape'] = arrayDim[i,2:4]
569 569 dsDict['nDim'] = 3
570 570
571 571 for j in range(nTables):
572 572 dsDict = dsDict.copy()
573 573 dsDict['dsName'] = strtable + str(j)
574 574 dsList.append(dsDict)
575 575
576 576 # Two-dimension arrays
577 577 elif len(arrayDim0) == 2:
578 578 arrayDim[i,2:-1] = numpy.array(arrayDim0)
579 579 nTables = int(arrayDim[i,2])
580 580 dsDict['dsNumber'] = nTables
581 581 dsDict['shape'] = arrayDim[i,3]
582 582 dsDict['nDim'] = 2
583 583
584 584 for j in range(nTables):
585 585 dsDict = dsDict.copy()
586 586 dsDict['dsName'] = strtable + str(j)
587 587 dsList.append(dsDict)
588 588
589 589 # One-dimension arrays
590 590 elif len(arrayDim0) == 1:
591 591 arrayDim[i,3] = arrayDim0[0]
592 592 dsDict['shape'] = arrayDim0[0]
593 593 dsDict['dsNumber'] = 1
594 594 dsDict['dsName'] = strtable + str(0)
595 595 dsDict['nDim'] = 1
596 596 dsList.append(dsDict)
597 597
598 598 table = numpy.array((self.dataList[i],) + tuple(arrayDim[i,:]),dtype = dtype0)
599 599 tableList.append(table)
600 600
601 601 self.dsList = dsList
602 602 self.tableDim = numpy.array(tableList, dtype = dtype0)
603 603 self.blockIndex = 0
604 604 timeTuple = time.localtime(dataOut.utctime)
605 605 self.currentDay = timeTuple.tm_yday
606 606
607 607 def putMetadata(self):
608 608
609 609 fp = self.createMetadataFile()
610 610 self.writeMetadata(fp)
611 611 fp.close()
612 612 return
613 613
614 614 def createMetadataFile(self):
615 615 ext = self.ext
616 616 path = self.path
617 617 setFile = self.setFile
618 618
619 619 timeTuple = time.localtime(self.dataOut.utctime)
620 620
621 621 subfolder = ''
622 622 fullpath = os.path.join( path, subfolder )
623 623
624 624 if not( os.path.exists(fullpath) ):
625 625 os.mkdir(fullpath)
626 626 setFile = -1 #inicializo mi contador de seteo
627 627
628 628 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
629 629 fullpath = os.path.join( path, subfolder )
630 630
631 631 if not( os.path.exists(fullpath) ):
632 632 os.mkdir(fullpath)
633 633 setFile = -1 #inicializo mi contador de seteo
634 634
635 635 else:
636 636 filesList = os.listdir( fullpath )
637 637 filesList = sorted( filesList, key=str.lower )
638 638 if len( filesList ) > 0:
639 639 filesList = [k for k in filesList if k.startswith(self.metaoptchar)]
640 640 filen = filesList[-1]
641 641 # el filename debera tener el siguiente formato
642 642 # 0 1234 567 89A BCDE (hex)
643 643 # x YYYY DDD SSS .ext
644 644 if isNumber( filen[8:11] ):
645 645 setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
646 646 else:
647 647 setFile = -1
648 648 else:
649 649 setFile = -1 #inicializo mi contador de seteo
650 650
651 651 if self.setType is None:
652 652 setFile += 1
653 653 file = '%s%4.4d%3.3d%03d%s' % (self.metaoptchar,
654 654 timeTuple.tm_year,
655 655 timeTuple.tm_yday,
656 656 setFile,
657 657 ext )
658 658 else:
659 659 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
660 660 file = '%s%4.4d%3.3d%04d%s' % (self.metaoptchar,
661 661 timeTuple.tm_year,
662 662 timeTuple.tm_yday,
663 663 setFile,
664 664 ext )
665 665
666 666 filename = os.path.join( path, subfolder, file )
667 667 self.metaFile = file
668 668 #Setting HDF5 File
669 669 fp = h5py.File(filename,'w')
670 670
671 671 return fp
672 672
673 673 def writeMetadata(self, fp):
674 674
675 675 grp = fp.create_group("Metadata")
676 676 grp.create_dataset('array dimensions', data = self.tableDim, dtype = self.dtype)
677 677
678 678 for i in range(len(self.metadataList)):
679 679 grp.create_dataset(self.metadataList[i], data=getattr(self.dataOut, self.metadataList[i]))
680 680 return
681 681
682 682 def timeFlag(self):
683 683 currentTime = self.dataOut.utctime
684 684
685 685 if self.lastTime is None:
686 686 self.lastTime = currentTime
687 687
688 688 #Day
689 689 timeTuple = time.localtime(currentTime)
690 690 dataDay = timeTuple.tm_yday
691 691
692 692 #Time
693 693 timeDiff = currentTime - self.lastTime
694 694
695 695 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
696 696 if dataDay != self.currentDay:
697 697 self.currentDay = dataDay
698 698 return True
699 699 elif timeDiff > 3*60*60:
700 700 self.lastTime = currentTime
701 701 return True
702 702 else:
703 703 self.lastTime = currentTime
704 704 return False
705 705
706 706 def setNextFile(self):
707
707
708 708 ext = self.ext
709 709 path = self.path
710 710 setFile = self.setFile
711 711 mode = self.mode
712 712
713 713 timeTuple = time.localtime(self.dataOut.utctime)
714 714 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
715 715
716 716 fullpath = os.path.join( path, subfolder )
717 717
718 718 if os.path.exists(fullpath):
719 719 filesList = os.listdir( fullpath )
720 720 filesList = [k for k in filesList if 'M' in k]
721 721 if len( filesList ) > 0:
722 722 filesList = sorted( filesList, key=str.lower )
723 723 filen = filesList[-1]
724 724 # el filename debera tener el siguiente formato
725 725 # 0 1234 567 89A BCDE (hex)
726 726 # x YYYY DDD SSS .ext
727 727 if isNumber( filen[8:11] ):
728 728 setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
729 729 else:
730 730 setFile = -1
731 731 else:
732 732 setFile = -1 #inicializo mi contador de seteo
733 733 else:
734 734 os.makedirs(fullpath)
735 735 setFile = -1 #inicializo mi contador de seteo
736 736
737 737 if self.setType is None:
738 738 setFile += 1
739 739 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
740 740 timeTuple.tm_year,
741 741 timeTuple.tm_yday,
742 742 setFile,
743 743 ext )
744 744 else:
745 745 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
746 746 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
747 747 timeTuple.tm_year,
748 748 timeTuple.tm_yday,
749 749 setFile,
750 750 ext )
751 751
752 752 filename = os.path.join( path, subfolder, file )
753 753
754 754 #Setting HDF5 File
755 755 fp = h5py.File(filename,'w')
756 756 #write metadata
757 757 self.writeMetadata(fp)
758 758 #Write data
759 759 grp = fp.create_group("Data")
760 760 ds = []
761 761 data = []
762 762 dsList = self.dsList
763 763 i = 0
764 764 while i < len(dsList):
765 765 dsInfo = dsList[i]
766 766 #One-dimension data
767 767 if dsInfo['mode'] == 0:
768 768 ds0 = grp.create_dataset(dsInfo['variable'], (1,1), maxshape=(1,self.blocksPerFile) , chunks = True, dtype=numpy.float64)
769 769 ds.append(ds0)
770 770 data.append([])
771 771 i += 1
772 772 continue
773 773
774 774 elif dsInfo['mode'] == 2:
775 775 grp0 = grp.create_group(dsInfo['variable'])
776 776 ds0 = grp0.create_dataset(dsInfo['dsName'], (1,dsInfo['shape']), data = numpy.zeros((1,dsInfo['shape'])) , maxshape=(None,dsInfo['shape']), chunks=True)
777 777 ds.append(ds0)
778 778 data.append([])
779 779 i += 1
780 780 continue
781 781
782 782 elif dsInfo['mode'] == 1:
783 783 grp0 = grp.create_group(dsInfo['variable'])
784 784
785 785 for j in range(dsInfo['dsNumber']):
786 786 dsInfo = dsList[i]
787 787 tableName = dsInfo['dsName']
788
788
789 789
790 790 if dsInfo['nDim'] == 3:
791 791 shape = dsInfo['shape'].astype(int)
792 792 ds0 = grp0.create_dataset(tableName, (shape[0],shape[1],1) , data = numpy.zeros((shape[0],shape[1],1)), maxshape = (None,shape[1],None), chunks=True)
793 793 else:
794 794 shape = int(dsInfo['shape'])
795 795 ds0 = grp0.create_dataset(tableName, (1,shape), data = numpy.zeros((1,shape)) , maxshape=(None,shape), chunks=True)
796 796
797 797 ds.append(ds0)
798 798 data.append([])
799 799 i += 1
800 800
801 801 fp.flush()
802 802 fp.close()
803 803
804 804 log.log('creating file: {}'.format(filename), 'Writing')
805 805 self.filename = filename
806 806 self.ds = ds
807 807 self.data = data
808 808 self.firsttime = True
809 809 self.blockIndex = 0
810 810 return
811 811
812 812 def putData(self):
813 813
814 814 if self.blockIndex == self.blocksPerFile or self.timeFlag():
815 815 self.setNextFile()
816 816
817 817 self.readBlock()
818 818 self.setBlock() #Prepare data to be written
819 819 self.writeBlock() #Write data
820 820
821 821 return
822 822
823 823 def readBlock(self):
824 824
825 825 '''
826 826 data Array configured
827 827
828 828
829 829 self.data
830 830 '''
831 831 dsList = self.dsList
832 832 ds = self.ds
833 833 #Setting HDF5 File
834 834 fp = h5py.File(self.filename,'r+')
835 835 grp = fp["Data"]
836 836 ind = 0
837 837
838 838 while ind < len(dsList):
839 839 dsInfo = dsList[ind]
840 840
841 841 if dsInfo['mode'] == 0:
842 842 ds0 = grp[dsInfo['variable']]
843 843 ds[ind] = ds0
844 844 ind += 1
845 845 else:
846 846
847 847 grp0 = grp[dsInfo['variable']]
848 848
849 849 for j in range(dsInfo['dsNumber']):
850 850 dsInfo = dsList[ind]
851 851 ds0 = grp0[dsInfo['dsName']]
852 852 ds[ind] = ds0
853 853 ind += 1
854 854
855 855 self.fp = fp
856 856 self.grp = grp
857 857 self.ds = ds
858 858
859 859 return
860 860
861 861 def setBlock(self):
862 862 '''
863 863 data Array configured
864 864
865 865
866 866 self.data
867 867 '''
868 868 #Creating Arrays
869 869 dsList = self.dsList
870 870 data = self.data
871 871 ind = 0
872
872 #print("dsList ",dsList)
873 #print("len ",len(dsList))
873 874 while ind < len(dsList):
874 875 dsInfo = dsList[ind]
875 876 dataAux = getattr(self.dataOut, dsInfo['variable'])
876 877
877 878 mode = dsInfo['mode']
878 879 nDim = dsInfo['nDim']
879 880
880 881 if mode == 0 or mode == 2 or nDim == 1:
881 882 data[ind] = dataAux
882 883 ind += 1
883 884 # elif nDim == 1:
884 885 # data[ind] = numpy.reshape(dataAux,(numpy.size(dataAux),1))
885 886 # ind += 1
886 887 elif nDim == 2:
887 888 for j in range(dsInfo['dsNumber']):
888 889 data[ind] = dataAux[j,:]
889 890 ind += 1
890 891 elif nDim == 3:
891 892 for j in range(dsInfo['dsNumber']):
892 893 data[ind] = dataAux[:,j,:]
893 894 ind += 1
894 895
895 896 self.data = data
896 897 return
897 898
898 899 def writeBlock(self):
899 900 '''
900 901 Saves the block in the HDF5 file
901 902 '''
902 903 dsList = self.dsList
903 904
904 905 for i in range(len(self.ds)):
906 print("#############", i , "#######################")
905 907 dsInfo = dsList[i]
906 908 nDim = dsInfo['nDim']
907 909 mode = dsInfo['mode']
908
910 print("dsInfo",dsInfo)
911 print("nDim",nDim)
912 print("mode",mode)
909 913 # First time
910 914 if self.firsttime:
915 print("ENTRE FIRSTIME")
911 916 if type(self.data[i]) == numpy.ndarray:
912 917
913 918 if nDim == 3:
919 print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
920 print("ndim","dentro del primer if 3")
914 921 self.data[i] = self.data[i].reshape((self.data[i].shape[0],self.data[i].shape[1],1))
922 print(self.data[i].shape)
923 print(type(self.data[i]))
915 924 self.ds[i].resize(self.data[i].shape)
925 print(self.ds[i].shape)
926 print(type(self.ds[i]))
916 927 if mode == 2:
917 928 self.ds[i].resize(self.data[i].shape)
918 self.ds[i][:] = self.data[i]
919 else:
929 try:
930 print("PTM ODIO ESTO")
931 print(self.ds[i][:].shape)
932 self.ds[i][:] = self.data[i]
933 print("*****___________********______******")
920 934
935 except:
936 print("q habra pasaado")
937 return
938 print("LLEGUE Y CUMPLI EL IF")
939 else:
940 print("ELSE -----------------------")
921 941 # From second time
922 942 # Meteors!
923 943 if mode == 2:
924 944 dataShape = self.data[i].shape
925 945 dsShape = self.ds[i].shape
926 946 self.ds[i].resize((self.ds[i].shape[0] + dataShape[0],self.ds[i].shape[1]))
927 947 self.ds[i][dsShape[0]:,:] = self.data[i]
928 948 # No dimension
929 949 elif mode == 0:
930 950 self.ds[i].resize((self.ds[i].shape[0], self.ds[i].shape[1] + 1))
931 951 self.ds[i][0,-1] = self.data[i]
932 952 # One dimension
933 953 elif nDim == 1:
934 954 self.ds[i].resize((self.ds[i].shape[0] + 1, self.ds[i].shape[1]))
935 955 self.ds[i][-1,:] = self.data[i]
936 956 # Two dimension
937 957 elif nDim == 2:
938 958 self.ds[i].resize((self.ds[i].shape[0] + 1,self.ds[i].shape[1]))
939 959 self.ds[i][self.blockIndex,:] = self.data[i]
940 960 # Three dimensions
941 961 elif nDim == 3:
942 962 self.ds[i].resize((self.ds[i].shape[0],self.ds[i].shape[1],self.ds[i].shape[2]+1))
943 963 self.ds[i][:,:,-1] = self.data[i]
944 964
945 965 self.firsttime = False
946 966 self.blockIndex += 1
947
967 print("HOLA AMIGOS COMO ESTAN LLEGUE")
968 print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
948 969 #Close to save changes
949 970 self.fp.flush()
950 971 self.fp.close()
951 972 return
952 973
953 974 def run(self, dataOut, path, blocksPerFile=10, metadataList=None, dataList=None, mode=None, setType=None):
954 975
955 976 self.dataOut = dataOut
956 977 if not(self.isConfig):
957 self.setup(dataOut, path=path, blocksPerFile=blocksPerFile,
978 self.setup(dataOut, path=path, blocksPerFile=blocksPerFile,
958 979 metadataList=metadataList, dataList=dataList, mode=mode,
959 980 setType=setType)
960 981
961 982 self.isConfig = True
962 983 self.setNextFile()
963 984
964 985 self.putData()
965 986 return
966
987
967 988
968 989 @MPDecorator
969 990 class ParameterReader(Reader, ProcessingUnit):
970 991 '''
971 992 Reads HDF5 format files
972 993 '''
973 994
974 995 def __init__(self):
975 996 ProcessingUnit.__init__(self)
976 997 self.dataOut = Parameters()
977 998 self.ext = ".hdf5"
978 999 self.optchar = "D"
979 1000 self.timezone = "lt"
980 1001 self.listMetaname = []
981 1002 self.listMeta = []
982 1003 self.listDataname = []
983 1004 self.listData = []
984 1005 self.listShapes = []
985 1006 self.open_file = h5py.File
986 1007 self.open_mode = 'r'
987 1008 self.metadata = False
988 1009 self.filefmt = "*%Y%j***"
989 1010 self.folderfmt = "*%Y%j"
990 1011
991 1012 def setup(self, **kwargs):
992 1013
993 1014 self.set_kwargs(**kwargs)
994 1015 if not self.ext.startswith('.'):
995 self.ext = '.{}'.format(self.ext)
1016 self.ext = '.{}'.format(self.ext)
996 1017
997 1018 if self.online:
998 1019 log.log("Searching files in online mode...", self.name)
999 1020
1000 1021 for nTries in range(self.nTries):
1001 1022 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1002 self.endDate, self.expLabel, self.ext, self.walk,
1023 self.endDate, self.expLabel, self.ext, self.walk,
1003 1024 self.filefmt, self.folderfmt)
1004 1025
1005 1026 try:
1006 1027 fullpath = next(fullpath)
1007 1028 except:
1008 1029 fullpath = None
1009
1030
1010 1031 if fullpath:
1011 1032 break
1012 1033
1013 1034 log.warning(
1014 1035 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1015 self.delay, self.path, nTries + 1),
1036 self.delay, self.path, nTries + 1),
1016 1037 self.name)
1017 1038 time.sleep(self.delay)
1018 1039
1019 1040 if not(fullpath):
1020 1041 raise schainpy.admin.SchainError(
1021 'There isn\'t any valid file in {}'.format(self.path))
1042 'There isn\'t any valid file in {}'.format(self.path))
1022 1043
1023 1044 pathname, filename = os.path.split(fullpath)
1024 1045 self.year = int(filename[1:5])
1025 1046 self.doy = int(filename[5:8])
1026 self.set = int(filename[8:11]) - 1
1047 self.set = int(filename[8:11]) - 1
1027 1048 else:
1028 1049 log.log("Searching files in {}".format(self.path), self.name)
1029 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1050 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1030 1051 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1031
1052
1032 1053 self.setNextFile()
1033 1054
1034 1055 return
1035 1056
1036 1057 def readFirstHeader(self):
1037 1058 '''Read metadata and data'''
1038 1059
1039 self.__readMetadata()
1060 self.__readMetadata()
1040 1061 self.__readData()
1041 1062 self.__setBlockList()
1042 1063 self.blockIndex = 0
1043
1064
1044 1065 return
1045 1066
1046 1067 def __setBlockList(self):
1047 1068 '''
1048 1069 Selects the data within the times defined
1049 1070
1050 1071 self.fp
1051 1072 self.startTime
1052 1073 self.endTime
1053 1074 self.blockList
1054 1075 self.blocksPerFile
1055 1076
1056 1077 '''
1057 1078
1058 1079 startTime = self.startTime
1059 1080 endTime = self.endTime
1060 1081
1061 1082 index = self.listDataname.index('utctime')
1062 1083 thisUtcTime = self.listData[index]
1063 1084 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
1064 1085
1065 1086 if self.timezone == 'lt':
1066 1087 thisUtcTime -= 5*3600
1067 1088
1068 1089 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
1069 1090
1070 1091 thisDate = thisDatetime.date()
1071 1092 thisTime = thisDatetime.time()
1072 1093
1073 1094 startUtcTime = (datetime.datetime.combine(thisDate,startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
1074 1095 endUtcTime = (datetime.datetime.combine(thisDate,endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
1075 1096
1076 1097 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
1077 1098
1078 1099 self.blockList = ind
1079 1100 self.blocksPerFile = len(ind)
1080 1101 return
1081 1102
1082 1103 def __readMetadata(self):
1083 1104 '''
1084 1105 Reads Metadata
1085 1106 '''
1086 1107
1087 1108 listMetaname = []
1088 1109 listMetadata = []
1089 1110 if 'Metadata' in self.fp:
1090 1111 gp = self.fp['Metadata']
1091 1112 for item in list(gp.items()):
1092 1113 name = item[0]
1093 1114
1094 1115 if name=='variables':
1095 1116 table = gp[name][:]
1096 1117 listShapes = {}
1097 1118 for shapes in table:
1098 1119 listShapes[shapes[0].decode()] = numpy.array([shapes[1]])
1099 1120 else:
1100 1121 data = gp[name].value
1101 1122 listMetaname.append(name)
1102 listMetadata.append(data)
1123 listMetadata.append(data)
1103 1124 elif self.metadata:
1104 1125 metadata = json.loads(self.metadata)
1105 1126 listShapes = {}
1106 1127 for tup in metadata:
1107 1128 name, values, dim = tup
1108 1129 if dim == -1:
1109 1130 listMetaname.append(name)
1110 1131 listMetadata.append(self.fp[values].value)
1111 1132 else:
1112 1133 listShapes[name] = numpy.array([dim])
1113 1134 else:
1114 1135 raise IOError('Missing Metadata group in file or metadata info')
1115 1136
1116 1137 self.listShapes = listShapes
1117 1138 self.listMetaname = listMetaname
1118 self.listMeta = listMetadata
1139 self.listMeta = listMetadata
1119 1140
1120 1141 return
1121 1142
1122 1143 def __readData(self):
1123 1144
1124 1145 listdataname = []
1125 1146 listdata = []
1126
1147
1127 1148 if 'Data' in self.fp:
1128 1149 grp = self.fp['Data']
1129 1150 for item in list(grp.items()):
1130 1151 name = item[0]
1131 1152 listdataname.append(name)
1132 1153 dim = self.listShapes[name][0]
1133 1154 if dim == 0:
1134 1155 array = grp[name].value
1135 1156 else:
1136 1157 array = []
1137 1158 for i in range(dim):
1138 1159 array.append(grp[name]['table{:02d}'.format(i)].value)
1139 1160 array = numpy.array(array)
1140
1161
1141 1162 listdata.append(array)
1142 1163 elif self.metadata:
1143 1164 metadata = json.loads(self.metadata)
1144 1165 for tup in metadata:
1145 1166 name, values, dim = tup
1146 1167 listdataname.append(name)
1147 1168 if dim == -1:
1148 1169 continue
1149 1170 elif dim == 0:
1150 1171 array = self.fp[values].value
1151 1172 else:
1152 1173 array = []
1153 1174 for var in values:
1154 1175 array.append(self.fp[var].value)
1155 1176 array = numpy.array(array)
1156 1177 listdata.append(array)
1157 1178 else:
1158 1179 raise IOError('Missing Data group in file or metadata info')
1159 1180
1160 1181 self.listDataname = listdataname
1161 1182 self.listData = listdata
1162 1183 return
1163
1184
1164 1185 def getData(self):
1165 1186
1166 1187 for i in range(len(self.listMeta)):
1167 1188 setattr(self.dataOut, self.listMetaname[i], self.listMeta[i])
1168 1189
1169 1190 for j in range(len(self.listData)):
1170 1191 dim = self.listShapes[self.listDataname[j]][0]
1171 1192 if dim == 0:
1172 1193 setattr(self.dataOut, self.listDataname[j], self.listData[j][self.blockIndex])
1173 1194 else:
1174 1195 setattr(self.dataOut, self.listDataname[j], self.listData[j][:,self.blockIndex])
1175 1196
1176 1197 self.dataOut.paramInterval = self.interval
1177 1198 self.dataOut.flagNoData = False
1178 1199 self.blockIndex += 1
1179 1200
1180 1201 return
1181 1202
1182 1203 def run(self, **kwargs):
1183 1204
1184 1205 if not(self.isConfig):
1185 1206 self.setup(**kwargs)
1186 1207 self.isConfig = True
1187 1208
1188 1209 if self.blockIndex == self.blocksPerFile:
1189 1210 self.setNextFile()
1190 1211
1191 1212 self.getData()
1192 1213
1193 1214 return
1194 1215
1195 1216 @MPDecorator
1196 1217 class ParameterWriter(Operation):
1197 1218 '''
1198 1219 HDF5 Writer, stores parameters data in HDF5 format files
1199 1220
1200 1221 path: path where the files will be stored
1201 1222 blocksPerFile: number of blocks that will be saved in per HDF5 format file
1202 1223 mode: selects the data stacking mode: '0' channels, '1' parameters, '3' table (for meteors)
1203 1224 metadataList: list of attributes that will be stored as metadata
1204 1225 dataList: list of attributes that will be stores as data
1205 1226 '''
1206 1227
1207 1228
1208 1229 ext = ".hdf5"
1209 1230 optchar = "D"
1210 1231 metaoptchar = "M"
1211 1232 metaFile = None
1212 1233 filename = None
1213 1234 path = None
1214 1235 setFile = None
1215 1236 fp = None
1216 1237 grp = None
1217 1238 ds = None
1218 1239 firsttime = True
1219 1240 #Configurations
1220 1241 blocksPerFile = None
1221 1242 blockIndex = None
1222 1243 dataOut = None
1223 1244 #Data Arrays
1224 1245 dataList = None
1225 1246 metadataList = None
1226 1247 dsList = None #List of dictionaries with dataset properties
1227 1248 tableDim = None
1228 1249 dtype = [('name', 'S20'),('nDim', 'i')]
1229 1250 currentDay = None
1230 1251 lastTime = None
1231 1252
1232 1253 def __init__(self):
1233
1254
1234 1255 Operation.__init__(self)
1235 1256 return
1236 1257
1237 1258 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None):
1238 1259 self.path = path
1239 1260 self.blocksPerFile = blocksPerFile
1240 1261 self.metadataList = metadataList
1241 1262 self.dataList = dataList
1242 1263 self.setType = setType
1243 1264
1244 1265 tableList = []
1245 1266 dsList = []
1246 1267
1247 1268 for i in range(len(self.dataList)):
1248 1269 dsDict = {}
1249 1270 dataAux = getattr(self.dataOut, self.dataList[i])
1250 1271 dsDict['variable'] = self.dataList[i]
1251 1272
1252 1273 if dataAux is None:
1253 1274 continue
1254 1275 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
1255 1276 dsDict['nDim'] = 0
1256 1277 else:
1257 1278 dsDict['nDim'] = len(dataAux.shape)
1258 1279 dsDict['shape'] = dataAux.shape
1259 1280 dsDict['dsNumber'] = dataAux.shape[0]
1260
1281
1261 1282 dsList.append(dsDict)
1262 1283 tableList.append((self.dataList[i], dsDict['nDim']))
1263 1284
1264 1285 self.dsList = dsList
1265 1286 self.tableDim = numpy.array(tableList, dtype=self.dtype)
1266 1287 self.currentDay = self.dataOut.datatime.date()
1267 1288
1268 1289 def timeFlag(self):
1269 1290 currentTime = self.dataOut.utctime
1270 1291 timeTuple = time.localtime(currentTime)
1271 1292 dataDay = timeTuple.tm_yday
1272 1293
1273 1294 if self.lastTime is None:
1274 1295 self.lastTime = currentTime
1275 1296 self.currentDay = dataDay
1276 1297 return False
1277
1298
1278 1299 timeDiff = currentTime - self.lastTime
1279 1300
1280 1301 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
1281 1302 if dataDay != self.currentDay:
1282 1303 self.currentDay = dataDay
1283 1304 return True
1284 1305 elif timeDiff > 3*60*60:
1285 1306 self.lastTime = currentTime
1286 1307 return True
1287 1308 else:
1288 1309 self.lastTime = currentTime
1289 1310 return False
1290 1311
1291 1312 def run(self, dataOut, path, blocksPerFile=10, metadataList=None, dataList=None, setType=None):
1292 1313
1293 1314 self.dataOut = dataOut
1294 1315 if not(self.isConfig):
1295 self.setup(path=path, blocksPerFile=blocksPerFile,
1316 self.setup(path=path, blocksPerFile=blocksPerFile,
1296 1317 metadataList=metadataList, dataList=dataList,
1297 1318 setType=setType)
1298 1319
1299 1320 self.isConfig = True
1300 1321 self.setNextFile()
1301 1322
1302 1323 self.putData()
1303 1324 return
1304
1325
1305 1326 def setNextFile(self):
1306
1327
1307 1328 ext = self.ext
1308 1329 path = self.path
1309 1330 setFile = self.setFile
1310 1331
1311 1332 timeTuple = time.localtime(self.dataOut.utctime)
1312 1333 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
1313 1334 fullpath = os.path.join(path, subfolder)
1314 1335
1315 1336 if os.path.exists(fullpath):
1316 1337 filesList = os.listdir(fullpath)
1317 1338 filesList = [k for k in filesList if k.startswith(self.optchar)]
1318 1339 if len( filesList ) > 0:
1319 1340 filesList = sorted(filesList, key=str.lower)
1320 1341 filen = filesList[-1]
1321 1342 # el filename debera tener el siguiente formato
1322 1343 # 0 1234 567 89A BCDE (hex)
1323 1344 # x YYYY DDD SSS .ext
1324 1345 if isNumber(filen[8:11]):
1325 1346 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
1326 1347 else:
1327 1348 setFile = -1
1328 1349 else:
1329 1350 setFile = -1 #inicializo mi contador de seteo
1330 1351 else:
1331 1352 os.makedirs(fullpath)
1332 1353 setFile = -1 #inicializo mi contador de seteo
1333 1354
1334 1355 if self.setType is None:
1335 1356 setFile += 1
1336 1357 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
1337 1358 timeTuple.tm_year,
1338 1359 timeTuple.tm_yday,
1339 1360 setFile,
1340 1361 ext )
1341 1362 else:
1342 1363 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
1343 1364 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
1344 1365 timeTuple.tm_year,
1345 1366 timeTuple.tm_yday,
1346 1367 setFile,
1347 1368 ext )
1348 1369
1349 1370 self.filename = os.path.join( path, subfolder, file )
1350 1371
1351 1372 #Setting HDF5 File
1352 1373 self.fp = h5py.File(self.filename, 'w')
1353 1374 #write metadata
1354 1375 self.writeMetadata(self.fp)
1355 1376 #Write data
1356 1377 self.writeData(self.fp)
1357 1378
1358 1379 def writeMetadata(self, fp):
1359 1380
1360 1381 grp = fp.create_group("Metadata")
1361 1382 grp.create_dataset('variables', data=self.tableDim, dtype=self.dtype)
1362 1383
1363 1384 for i in range(len(self.metadataList)):
1364 1385 if not hasattr(self.dataOut, self.metadataList[i]):
1365 1386 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
1366 1387 continue
1367 1388 value = getattr(self.dataOut, self.metadataList[i])
1368 1389 grp.create_dataset(self.metadataList[i], data=value)
1369 1390 return
1370 1391
1371 1392 def writeData(self, fp):
1372
1393
1373 1394 grp = fp.create_group("Data")
1374 1395 dtsets = []
1375 1396 data = []
1376
1397
1377 1398 for dsInfo in self.dsList:
1378 1399 if dsInfo['nDim'] == 0:
1379 1400 ds = grp.create_dataset(
1380 dsInfo['variable'],
1401 dsInfo['variable'],
1381 1402 (self.blocksPerFile, ),
1382 chunks=True,
1403 chunks=True,
1383 1404 dtype=numpy.float64)
1384 1405 dtsets.append(ds)
1385 1406 data.append((dsInfo['variable'], -1))
1386 1407 else:
1387 1408 sgrp = grp.create_group(dsInfo['variable'])
1388 1409 for i in range(dsInfo['dsNumber']):
1389 1410 ds = sgrp.create_dataset(
1390 'table{:02d}'.format(i),
1411 'table{:02d}'.format(i),
1391 1412 (self.blocksPerFile, ) + dsInfo['shape'][1:],
1392 1413 chunks=True)
1393 1414 dtsets.append(ds)
1394 1415 data.append((dsInfo['variable'], i))
1395 1416 fp.flush()
1396 1417
1397 1418 log.log('Creating file: {}'.format(fp.filename), self.name)
1398
1419
1399 1420 self.ds = dtsets
1400 1421 self.data = data
1401 1422 self.firsttime = True
1402 1423 self.blockIndex = 0
1403 1424 return
1404 1425
1405 1426 def putData(self):
1406 1427
1407 1428 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
1408 1429 self.closeFile()
1409 1430 self.setNextFile()
1410 1431
1411 1432 for i, ds in enumerate(self.ds):
1433 print(i,ds)
1412 1434 attr, ch = self.data[i]
1413 1435 if ch == -1:
1414 1436 ds[self.blockIndex] = getattr(self.dataOut, attr)
1415 1437 else:
1438 print(ch, getattr(self.dataOut, attr).shape)
1416 1439 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
1417 1440
1418 1441 self.fp.flush()
1419 1442 self.blockIndex += 1
1420 1443 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
1421 1444
1422 1445 return
1423 1446
1424 1447 def closeFile(self):
1425 1448
1426 1449 if self.blockIndex != self.blocksPerFile:
1427 1450 for ds in self.ds:
1428 1451 ds.resize(self.blockIndex, axis=0)
1429 1452
1430 1453 self.fp.flush()
1431 1454 self.fp.close()
1432 1455
1433 1456 def close(self):
1434 1457
1435 1458 self.closeFile()
This diff has been collapsed as it changes many lines, (2157 lines changed) Show them Hide them
@@ -1,3983 +1,4000
1 1 import numpy
2 2 import math
3 3 from scipy import optimize, interpolate, signal, stats, ndimage
4 4 import scipy
5 5 import re
6 6 import datetime
7 7 import copy
8 8 import sys
9 9 import importlib
10 10 import itertools
11 from multiprocessing import Pool, TimeoutError
11 from multiprocessing import Pool, TimeoutError
12 12 from multiprocessing.pool import ThreadPool
13 13 import time
14 14
15 15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 18 from scipy import asarray as ar,exp
19 19 from scipy.optimize import curve_fit
20 20 from schainpy.utils import log
21 21 import warnings
22 22 from numpy import NaN
23 23 from scipy.optimize.optimize import OptimizeWarning
24 24 warnings.filterwarnings('ignore')
25 25
26 26 import matplotlib.pyplot as plt
27 27
28 28 SPEED_OF_LIGHT = 299792458
29 29
30 30
31 31 '''solving pickling issue'''
32 32
33 33 def _pickle_method(method):
34 34 func_name = method.__func__.__name__
35 35 obj = method.__self__
36 36 cls = method.__self__.__class__
37 37 return _unpickle_method, (func_name, obj, cls)
38 38
39 39 def _unpickle_method(func_name, obj, cls):
40 40 for cls in cls.mro():
41 41 try:
42 42 func = cls.__dict__[func_name]
43 43 except KeyError:
44 44 pass
45 45 else:
46 46 break
47 47 return func.__get__(obj, cls)
48 48
49 49 @MPDecorator
50 50 class ParametersProc(ProcessingUnit):
51
51
52 52 METHODS = {}
53 53 nSeconds = None
54 54
55 55 def __init__(self):
56 56 ProcessingUnit.__init__(self)
57
57
58 58 # self.objectDict = {}
59 59 self.buffer = None
60 60 self.firstdatatime = None
61 61 self.profIndex = 0
62 62 self.dataOut = Parameters()
63 63 self.setupReq = False #Agregar a todas las unidades de proc
64 64
65 65 def __updateObjFromInput(self):
66
66
67 67 self.dataOut.inputUnit = self.dataIn.type
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.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
75 75 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
76 76 self.dataOut.channelList = self.dataIn.channelList
77 77 self.dataOut.heightList = self.dataIn.heightList
78 78 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
79 79 # self.dataOut.nHeights = self.dataIn.nHeights
80 80 # self.dataOut.nChannels = self.dataIn.nChannels
81 81 self.dataOut.nBaud = self.dataIn.nBaud
82 82 self.dataOut.nCode = self.dataIn.nCode
83 83 self.dataOut.code = self.dataIn.code
84 84 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
85 85 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
86 86 # self.dataOut.utctime = self.firstdatatime
87 87 self.dataOut.utctime = self.dataIn.utctime
88 88 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
89 89 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
90 90 self.dataOut.nCohInt = self.dataIn.nCohInt
91 91 # self.dataOut.nIncohInt = 1
92 92 self.dataOut.ippSeconds = self.dataIn.ippSeconds
93 93 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
94 94 self.dataOut.timeInterval1 = self.dataIn.timeInterval
95 self.dataOut.heightList = self.dataIn.getHeiRange()
95 self.dataOut.heightList = self.dataIn.getHeiRange()
96 96 self.dataOut.frequency = self.dataIn.frequency
97 97 # self.dataOut.noise = self.dataIn.noise
98
99 def run(self):
100
101
102 98
99 def run(self):
103 100 #---------------------- Voltage Data ---------------------------
104
105 101 if self.dataIn.type == "Voltage":
106
102 print(" *************INSIDE PARAMETER********")
107 103 self.__updateObjFromInput()
108 104 self.dataOut.data_pre = self.dataIn.data.copy()
109 105 self.dataOut.flagNoData = False
110 106 self.dataOut.utctimeInit = self.dataIn.utctime
111 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
107 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
108
109 if self.dataIn.identifierWR== True:
110 print("**********************************************")
111 self.dataOut.data_intensity = self.dataIn.data #valor para intensidad
112 self.dataOut.data_velocity = self.dataIn.data_velocity #valor para velocidad
113 self.dataOut.identifierWR = self.dataIn.identifierWR
114 self.dataOut.PRFbyAngle = self.dataIn.PRFbyAngle
115 print(self.dataOut.data_intensity.shape)
116 print(self.dataOut.utctimeInit)
117 print(self.dataOut.nCohInt )
118 print(self.dataOut.PRFbyAngle)
112 119 return
113
114 120 #---------------------- Spectra Data ---------------------------
115
116 121 if self.dataIn.type == "Spectra":
117 122
118 123 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
119 124 self.dataOut.data_spc = self.dataIn.data_spc
120 125 self.dataOut.data_cspc = self.dataIn.data_cspc
121 126 self.dataOut.nProfiles = self.dataIn.nProfiles
122 127 self.dataOut.nIncohInt = self.dataIn.nIncohInt
123 128 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
124 129 self.dataOut.ippFactor = self.dataIn.ippFactor
125 130 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
126 131 self.dataOut.spc_noise = self.dataIn.getNoise()
127 132 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
128 133 # self.dataOut.normFactor = self.dataIn.normFactor
129 self.dataOut.pairsList = self.dataIn.pairsList
134 self.dataOut.pairsList = self.dataIn.pairsList
130 135 self.dataOut.groupList = self.dataIn.pairsList
131 self.dataOut.flagNoData = False
132
136 self.dataOut.flagNoData = False
137
138 if self.dataIn.flagWR== True:
139 print("##############################################")
140 self.dataOut.nIncohInt = self.dataIn.nIncohInt
141 self.dataOut.utctimeInit = self.dataIn.utctime
142 self.dataOut.data_intensity = self.dataIn.data #valor para intensidad
143 self.dataOut.data_velocity = self.dataIn.data_velocity #valor para velocidad
144 self.dataOut.flagWR = self.dataIn.flagWR
145 self.dataOut.PRFbyAngle = self.dataIn.PRFbyAngle
146 print(self.dataOut.data_intensity.shape)
147 print(self.dataOut.utctimeInit)
148 print(self.dataOut.nIncohInt )
149 print(self.dataOut.PRFbyAngle)
150
133 151 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
134 152 self.dataOut.ChanDist = self.dataIn.ChanDist
135 else: self.dataOut.ChanDist = None
136
153 else: self.dataOut.ChanDist = None
154
137 155 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
138 156 # self.dataOut.VelRange = self.dataIn.VelRange
139 157 #else: self.dataOut.VelRange = None
140
158
141 159 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
142 160 self.dataOut.RadarConst = self.dataIn.RadarConst
143
161
144 162 if hasattr(self.dataIn, 'NPW'): #NPW
145 163 self.dataOut.NPW = self.dataIn.NPW
146
164
147 165 if hasattr(self.dataIn, 'COFA'): #COFA
148 166 self.dataOut.COFA = self.dataIn.COFA
149
150
151
167
168
169
152 170 #---------------------- Correlation Data ---------------------------
153
171
154 172 if self.dataIn.type == "Correlation":
155 173 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
156
174
157 175 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
158 176 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
159 177 self.dataOut.groupList = (acf_pairs, ccf_pairs)
160
178
161 179 self.dataOut.abscissaList = self.dataIn.lagRange
162 180 self.dataOut.noise = self.dataIn.noise
163 181 self.dataOut.data_SNR = self.dataIn.SNR
164 182 self.dataOut.flagNoData = False
165 183 self.dataOut.nAvg = self.dataIn.nAvg
166
184
167 185 #---------------------- Parameters Data ---------------------------
168
186
169 187 if self.dataIn.type == "Parameters":
170 188 self.dataOut.copy(self.dataIn)
171 189 self.dataOut.flagNoData = False
172
190
173 191 return True
174
192
175 193 self.__updateObjFromInput()
176 194 self.dataOut.utctimeInit = self.dataIn.utctime
177 195 self.dataOut.paramInterval = self.dataIn.timeInterval
178
196
179 197 return
180 198
181 199
182 200 def target(tups):
183
201
184 202 obj, args = tups
185
203
186 204 return obj.FitGau(args)
187
188
205
206
189 207 class SpectralFilters(Operation):
190
208
191 209 '''This class allows the Rainfall / Wind Selection for CLAIRE RADAR
192
210
193 211 LimitR : It is the limit in m/s of Rainfall
194 212 LimitW : It is the limit in m/s for Winds
195
213
196 214 Input:
197
215
198 216 self.dataOut.data_pre : SPC and CSPC
199 217 self.dataOut.spc_range : To select wind and rainfall velocities
200
218
201 219 Affected:
202
220
203 221 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
204 self.dataOut.spcparam_range : Used in SpcParamPlot
222 self.dataOut.spcparam_range : Used in SpcParamPlot
205 223 self.dataOut.SPCparam : Used in PrecipitationProc
206
207
224
225
208 226 '''
209
227
210 228 def __init__(self):
211 229 Operation.__init__(self)
212 230 self.i=0
213
214 def run(self, dataOut, PositiveLimit=1.5, NegativeLimit=2.5):
215
216
217 #Limite de vientos
231
232 def run(self, dataOut, PositiveLimit=1.5, NegativeLimit=2.5):
233
234
235 #Limite de vientos
218 236 LimitR = PositiveLimit
219 237 LimitN = NegativeLimit
220
238
221 239 self.spc = dataOut.data_pre[0].copy()
222 240 self.cspc = dataOut.data_pre[1].copy()
223
241
224 242 self.Num_Hei = self.spc.shape[2]
225 243 self.Num_Bin = self.spc.shape[1]
226 244 self.Num_Chn = self.spc.shape[0]
227
245
228 246 VelRange = dataOut.spc_range[2]
229 247 TimeRange = dataOut.spc_range[1]
230 248 FrecRange = dataOut.spc_range[0]
231
249
232 250 Vmax= 2*numpy.max(dataOut.spc_range[2])
233 251 Tmax= 2*numpy.max(dataOut.spc_range[1])
234 252 Fmax= 2*numpy.max(dataOut.spc_range[0])
235
253
236 254 Breaker1R=VelRange[numpy.abs(VelRange-(-LimitN)).argmin()]
237 255 Breaker1R=numpy.where(VelRange == Breaker1R)
238
239 Delta = self.Num_Bin/2 - Breaker1R[0]
240
241
256
257 Delta = self.Num_Bin/2 - Breaker1R[0]
258
259
242 260 '''Reacomodando SPCrange'''
243 261
244 262 VelRange=numpy.roll(VelRange,-(int(self.Num_Bin/2)) ,axis=0)
245
263
246 264 VelRange[-(int(self.Num_Bin/2)):]+= Vmax
247
265
248 266 FrecRange=numpy.roll(FrecRange,-(int(self.Num_Bin/2)),axis=0)
249
267
250 268 FrecRange[-(int(self.Num_Bin/2)):]+= Fmax
251
269
252 270 TimeRange=numpy.roll(TimeRange,-(int(self.Num_Bin/2)),axis=0)
253
271
254 272 TimeRange[-(int(self.Num_Bin/2)):]+= Tmax
255
273
256 274 ''' ------------------ '''
257
275
258 276 Breaker2R=VelRange[numpy.abs(VelRange-(LimitR)).argmin()]
259 277 Breaker2R=numpy.where(VelRange == Breaker2R)
260
261
278
279
262 280 SPCroll = numpy.roll(self.spc,-(int(self.Num_Bin/2)) ,axis=1)
263
281
264 282 SPCcut = SPCroll.copy()
265 283 for i in range(self.Num_Chn):
266
284
267 285 SPCcut[i,0:int(Breaker2R[0]),:] = dataOut.noise[i]
268 286 SPCcut[i,-int(Delta):,:] = dataOut.noise[i]
269
287
270 288 SPCcut[i]=SPCcut[i]- dataOut.noise[i]
271 289 SPCcut[ numpy.where( SPCcut<0 ) ] = 1e-20
272
290
273 291 SPCroll[i]=SPCroll[i]-dataOut.noise[i]
274 292 SPCroll[ numpy.where( SPCroll<0 ) ] = 1e-20
275
293
276 294 SPC_ch1 = SPCroll
277
295
278 296 SPC_ch2 = SPCcut
279
297
280 298 SPCparam = (SPC_ch1, SPC_ch2, self.spc)
281 dataOut.SPCparam = numpy.asarray(SPCparam)
282
283
299 dataOut.SPCparam = numpy.asarray(SPCparam)
300
301
284 302 dataOut.spcparam_range=numpy.zeros([self.Num_Chn,self.Num_Bin+1])
285
303
286 304 dataOut.spcparam_range[2]=VelRange
287 305 dataOut.spcparam_range[1]=TimeRange
288 306 dataOut.spcparam_range[0]=FrecRange
289 307 return dataOut
290
308
291 309 class GaussianFit(Operation):
292
310
293 311 '''
294 Function that fit of one and two generalized gaussians (gg) based
295 on the PSD shape across an "power band" identified from a cumsum of
312 Function that fit of one and two generalized gaussians (gg) based
313 on the PSD shape across an "power band" identified from a cumsum of
296 314 the measured spectrum - noise.
297
315
298 316 Input:
299 317 self.dataOut.data_pre : SelfSpectra
300
318
301 319 Output:
302 320 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
303
321
304 322 '''
305 323 def __init__(self):
306 324 Operation.__init__(self)
307 325 self.i=0
308
309
326
327
310 328 def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
311 329 """This routine will find a couple of generalized Gaussians to a power spectrum
312 330 input: spc
313 331 output:
314 332 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
315 333 """
316
334
317 335 self.spc = dataOut.data_pre[0].copy()
318 336 self.Num_Hei = self.spc.shape[2]
319 337 self.Num_Bin = self.spc.shape[1]
320 338 self.Num_Chn = self.spc.shape[0]
321 339 Vrange = dataOut.abscissaList
322
340
323 341 GauSPC = numpy.empty([self.Num_Chn,self.Num_Bin,self.Num_Hei])
324 342 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
325 343 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
326 344 SPC_ch1[:] = numpy.NaN
327 345 SPC_ch2[:] = numpy.NaN
328 346
329
347
330 348 start_time = time.time()
331
349
332 350 noise_ = dataOut.spc_noise[0].copy()
333
334
335 pool = Pool(processes=self.Num_Chn)
351
352
353 pool = Pool(processes=self.Num_Chn)
336 354 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
337 objs = [self for __ in range(self.Num_Chn)]
338 attrs = list(zip(objs, args))
355 objs = [self for __ in range(self.Num_Chn)]
356 attrs = list(zip(objs, args))
339 357 gauSPC = pool.map(target, attrs)
340 358 dataOut.SPCparam = numpy.asarray(SPCparam)
341
359
342 360 ''' Parameters:
343 361 1. Amplitude
344 362 2. Shift
345 363 3. Width
346 364 4. Power
347 365 '''
348
366
349 367 def FitGau(self, X):
350
368
351 369 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
352
370
353 371 SPCparam = []
354 372 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
355 373 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
356 374 SPC_ch1[:] = 0#numpy.NaN
357 375 SPC_ch2[:] = 0#numpy.NaN
358
359
360
376
377
378
361 379 for ht in range(self.Num_Hei):
362
363
380
381
364 382 spc = numpy.asarray(self.spc)[ch,:,ht]
365
383
366 384 #############################################
367 385 # normalizing spc and noise
368 386 # This part differs from gg1
369 387 spc_norm_max = max(spc)
370 388 #spc = spc / spc_norm_max
371 389 pnoise = pnoise #/ spc_norm_max
372 390 #############################################
373
391
374 392 fatspectra=1.0
375
393
376 394 wnoise = noise_ #/ spc_norm_max
377 395 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
378 #if wnoise>1.1*pnoise: # to be tested later
396 #if wnoise>1.1*pnoise: # to be tested later
379 397 # wnoise=pnoise
380 noisebl=wnoise*0.9;
398 noisebl=wnoise*0.9;
381 399 noisebh=wnoise*1.1
382 400 spc=spc-wnoise
383
401
384 402 minx=numpy.argmin(spc)
385 #spcs=spc.copy()
403 #spcs=spc.copy()
386 404 spcs=numpy.roll(spc,-minx)
387 405 cum=numpy.cumsum(spcs)
388 406 tot_noise=wnoise * self.Num_Bin #64;
389
407
390 408 snr = sum(spcs)/tot_noise
391 409 snrdB=10.*numpy.log10(snr)
392
410
393 411 if snrdB < SNRlimit :
394 412 snr = numpy.NaN
395 413 SPC_ch1[:,ht] = 0#numpy.NaN
396 414 SPC_ch1[:,ht] = 0#numpy.NaN
397 415 SPCparam = (SPC_ch1,SPC_ch2)
398 416 continue
399
400
417
418
401 419 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
402 420 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
403
404 cummax=max(cum);
421
422 cummax=max(cum);
405 423 epsi=0.08*fatspectra # cumsum to narrow down the energy region
406 cumlo=cummax*epsi;
424 cumlo=cummax*epsi;
407 425 cumhi=cummax*(1-epsi)
408 426 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
409
410
427
428
411 429 if len(powerindex) < 1:# case for powerindex 0
412 430 continue
413 431 powerlo=powerindex[0]
414 432 powerhi=powerindex[-1]
415 433 powerwidth=powerhi-powerlo
416
434
417 435 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
418 436 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
419 437 midpeak=(firstpeak+secondpeak)/2.
420 438 firstamp=spcs[int(firstpeak)]
421 439 secondamp=spcs[int(secondpeak)]
422 440 midamp=spcs[int(midpeak)]
423
441
424 442 x=numpy.arange( self.Num_Bin )
425 443 y_data=spc+wnoise
426
444
427 445 ''' single Gaussian '''
428 446 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
429 447 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
430 448 power0=2.
431 449 amplitude0=midamp
432 450 state0=[shift0,width0,amplitude0,power0,wnoise]
433 451 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
434 452 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
435
436 chiSq1=lsq1[1];
437 453
438
454 chiSq1=lsq1[1];
455
456
439 457 if fatspectra<1.0 and powerwidth<4:
440 458 choice=0
441 459 Amplitude0=lsq1[0][2]
442 460 shift0=lsq1[0][0]
443 461 width0=lsq1[0][1]
444 462 p0=lsq1[0][3]
445 463 Amplitude1=0.
446 464 shift1=0.
447 465 width1=0.
448 466 p1=0.
449 467 noise=lsq1[0][4]
450 468 #return (numpy.array([shift0,width0,Amplitude0,p0]),
451 469 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
452
470
453 471 ''' two gaussians '''
454 472 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
455 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
473 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
456 474 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
457 width0=powerwidth/6.;
475 width0=powerwidth/6.;
458 476 width1=width0
459 power0=2.;
477 power0=2.;
460 478 power1=power0
461 amplitude0=firstamp;
479 amplitude0=firstamp;
462 480 amplitude1=secondamp
463 481 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
464 482 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
465 483 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
466 484 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
467
485
468 486 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
469
470
471 chiSq2=lsq2[1];
472
473
474
487
488
489 chiSq2=lsq2[1];
490
491
492
475 493 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
476
494
477 495 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
478 496 if oneG:
479 497 choice=0
480 498 else:
481 499 w1=lsq2[0][1]; w2=lsq2[0][5]
482 500 a1=lsq2[0][2]; a2=lsq2[0][6]
483 501 p1=lsq2[0][3]; p2=lsq2[0][7]
484 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
502 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
485 503 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
486 504 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
487
505
488 506 if gp1>gp2:
489 507 if a1>0.7*a2:
490 508 choice=1
491 509 else:
492 510 choice=2
493 511 elif gp2>gp1:
494 512 if a2>0.7*a1:
495 513 choice=2
496 514 else:
497 515 choice=1
498 516 else:
499 517 choice=numpy.argmax([a1,a2])+1
500 518 #else:
501 519 #choice=argmin([std2a,std2b])+1
502
520
503 521 else: # with low SNR go to the most energetic peak
504 522 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
505
506
507 shift0=lsq2[0][0];
523
524
525 shift0=lsq2[0][0];
508 526 vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
509 shift1=lsq2[0][4];
527 shift1=lsq2[0][4];
510 528 vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
511
529
512 530 max_vel = 1.0
513
531
514 532 #first peak will be 0, second peak will be 1
515 533 if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range
516 534 shift0=lsq2[0][0]
517 535 width0=lsq2[0][1]
518 536 Amplitude0=lsq2[0][2]
519 537 p0=lsq2[0][3]
520
538
521 539 shift1=lsq2[0][4]
522 540 width1=lsq2[0][5]
523 541 Amplitude1=lsq2[0][6]
524 542 p1=lsq2[0][7]
525 noise=lsq2[0][8]
543 noise=lsq2[0][8]
526 544 else:
527 545 shift1=lsq2[0][0]
528 546 width1=lsq2[0][1]
529 547 Amplitude1=lsq2[0][2]
530 548 p1=lsq2[0][3]
531
549
532 550 shift0=lsq2[0][4]
533 551 width0=lsq2[0][5]
534 552 Amplitude0=lsq2[0][6]
535 p0=lsq2[0][7]
536 noise=lsq2[0][8]
537
553 p0=lsq2[0][7]
554 noise=lsq2[0][8]
555
538 556 if Amplitude0<0.05: # in case the peak is noise
539 shift0,width0,Amplitude0,p0 = [0,0,0,0]#4*[numpy.NaN]
557 shift0,width0,Amplitude0,p0 = [0,0,0,0]#4*[numpy.NaN]
540 558 if Amplitude1<0.05:
541 shift1,width1,Amplitude1,p1 = [0,0,0,0]#4*[numpy.NaN]
542
543
559 shift1,width1,Amplitude1,p1 = [0,0,0,0]#4*[numpy.NaN]
560
561
544 562 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
545 563 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
546 564 SPCparam = (SPC_ch1,SPC_ch2)
547
548
565
566
549 567 return GauSPC
550
568
551 569 def y_model1(self,x,state):
552 570 shift0,width0,amplitude0,power0,noise=state
553 571 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
554
572
555 573 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
556
574
557 575 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
558 576 return model0+model0u+model0d+noise
559
560 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
577
578 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
561 579 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
562 580 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
563
581
564 582 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
565
583
566 584 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
567 585 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
568
586
569 587 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
570
588
571 589 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
572 590 return model0+model0u+model0d+model1+model1u+model1d+noise
573
574 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
591
592 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
575 593
576 594 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
577
595
578 596 def misfit2(self,state,y_data,x,num_intg):
579 597 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
580
581
598
599
582 600
583 601 class PrecipitationProc(Operation):
584
602
585 603 '''
586 604 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
587
588 Input:
605
606 Input:
589 607 self.dataOut.data_pre : SelfSpectra
590
591 Output:
592
593 self.dataOut.data_output : Reflectivity factor, rainfall Rate
594
595
596 Parameters affected:
608
609 Output:
610
611 self.dataOut.data_output : Reflectivity factor, rainfall Rate
612
613
614 Parameters affected:
597 615 '''
598
616
599 617 def __init__(self):
600 618 Operation.__init__(self)
601 619 self.i=0
602
603
620
621
604 622 def gaus(self,xSamples,Amp,Mu,Sigma):
605 623 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
606
607
608
624
625
626
609 627 def Moments(self, ySamples, xSamples):
610 628 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
611 629 yNorm = ySamples / Pot
612
630
613 631 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
614 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
632 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
615 633 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
616
617 return numpy.array([Pot, Vr, Desv])
618
619 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
634
635 return numpy.array([Pot, Vr, Desv])
636
637 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
620 638 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km = 0.93, Altitude=3350):
621
622
639
640
623 641 Velrange = dataOut.spcparam_range[2]
624 642 FrecRange = dataOut.spcparam_range[0]
625
643
626 644 dV= Velrange[1]-Velrange[0]
627 645 dF= FrecRange[1]-FrecRange[0]
628
646
629 647 if radar == "MIRA35C" :
630
648
631 649 self.spc = dataOut.data_pre[0].copy()
632 650 self.Num_Hei = self.spc.shape[2]
633 651 self.Num_Bin = self.spc.shape[1]
634 652 self.Num_Chn = self.spc.shape[0]
635 653 Ze = self.dBZeMODE2(dataOut)
636
654
637 655 else:
638
656
639 657 self.spc = dataOut.SPCparam[1].copy() #dataOut.data_pre[0].copy() #
640
658
641 659 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
642
643 self.spc[:,:,0:7]= numpy.NaN
644
660
661 self.spc[:,:,0:7]= numpy.NaN
662
645 663 """##########################################"""
646
664
647 665 self.Num_Hei = self.spc.shape[2]
648 666 self.Num_Bin = self.spc.shape[1]
649 667 self.Num_Chn = self.spc.shape[0]
650
668
651 669 ''' Se obtiene la constante del RADAR '''
652
670
653 671 self.Pt = Pt
654 672 self.Gt = Gt
655 673 self.Gr = Gr
656 674 self.Lambda = Lambda
657 675 self.aL = aL
658 676 self.tauW = tauW
659 677 self.ThetaT = ThetaT
660 678 self.ThetaR = ThetaR
661
679
662 680 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
663 681 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
664 682 RadarConstant = 10e-26 * Numerator / Denominator #
665
683
666 684 ''' ============================= '''
667
668 self.spc[0] = (self.spc[0]-dataOut.noise[0])
669 self.spc[1] = (self.spc[1]-dataOut.noise[1])
670 self.spc[2] = (self.spc[2]-dataOut.noise[2])
671
685
686 self.spc[0] = (self.spc[0]-dataOut.noise[0])
687 self.spc[1] = (self.spc[1]-dataOut.noise[1])
688 self.spc[2] = (self.spc[2]-dataOut.noise[2])
689
672 690 self.spc[ numpy.where(self.spc < 0)] = 0
673
674 SPCmean = (numpy.mean(self.spc,0) - numpy.mean(dataOut.noise))
691
692 SPCmean = (numpy.mean(self.spc,0) - numpy.mean(dataOut.noise))
675 693 SPCmean[ numpy.where(SPCmean < 0)] = 0
676
694
677 695 ETAn = numpy.zeros([self.Num_Bin,self.Num_Hei])
678 696 ETAv = numpy.zeros([self.Num_Bin,self.Num_Hei])
679 697 ETAd = numpy.zeros([self.Num_Bin,self.Num_Hei])
680
698
681 699 Pr = SPCmean[:,:]
682
700
683 701 VelMeteoro = numpy.mean(SPCmean,axis=0)
684
702
685 703 D_range = numpy.zeros([self.Num_Bin,self.Num_Hei])
686 704 SIGMA = numpy.zeros([self.Num_Bin,self.Num_Hei])
687 705 N_dist = numpy.zeros([self.Num_Bin,self.Num_Hei])
688 706 V_mean = numpy.zeros(self.Num_Hei)
689 707 del_V = numpy.zeros(self.Num_Hei)
690 708 Z = numpy.zeros(self.Num_Hei)
691 709 Ze = numpy.zeros(self.Num_Hei)
692 710 RR = numpy.zeros(self.Num_Hei)
693
711
694 712 Range = dataOut.heightList*1000.
695
713
696 714 for R in range(self.Num_Hei):
697
715
698 716 h = Range[R] + Altitude #Range from ground to radar pulse altitude
699 717 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
700
718
701 719 D_range[:,R] = numpy.log( (9.65 - (Velrange[0:self.Num_Bin] / del_V[R])) / 10.3 ) / -0.6 #Diameter range [m]x10**-3
702
720
703 721 '''NOTA: ETA(n) dn = ETA(f) df
704
722
705 723 dn = 1 Diferencial de muestreo
706 724 df = ETA(n) / ETA(f)
707
725
708 726 '''
709
727
710 728 ETAn[:,R] = RadarConstant * Pr[:,R] * (Range[R] )**2 #Reflectivity (ETA)
711
729
712 730 ETAv[:,R]=ETAn[:,R]/dV
713
731
714 732 ETAd[:,R]=ETAv[:,R]*6.18*exp(-0.6*D_range[:,R])
715
733
716 734 SIGMA[:,R] = Km * (D_range[:,R] * 1e-3 )**6 * numpy.pi**5 / Lambda**4 #Equivalent Section of drops (sigma)
717
718 N_dist[:,R] = ETAn[:,R] / SIGMA[:,R]
719
735
736 N_dist[:,R] = ETAn[:,R] / SIGMA[:,R]
737
720 738 DMoments = self.Moments(Pr[:,R], Velrange[0:self.Num_Bin])
721
739
722 740 try:
723 741 popt01,pcov = curve_fit(self.gaus, Velrange[0:self.Num_Bin] , Pr[:,R] , p0=DMoments)
724 except:
742 except:
725 743 popt01=numpy.zeros(3)
726 744 popt01[1]= DMoments[1]
727
745
728 746 if popt01[1]<0 or popt01[1]>20:
729 747 popt01[1]=numpy.NaN
730
731
748
749
732 750 V_mean[R]=popt01[1]
733
751
734 752 Z[R] = numpy.nansum( N_dist[:,R] * (D_range[:,R])**6 )#*10**-18
735
753
736 754 RR[R] = 0.0006*numpy.pi * numpy.nansum( D_range[:,R]**3 * N_dist[:,R] * Velrange[0:self.Num_Bin] ) #Rainfall rate
737
755
738 756 Ze[R] = (numpy.nansum( ETAn[:,R]) * Lambda**4) / ( 10**-18*numpy.pi**5 * Km)
739
740
741
757
758
759
742 760 RR2 = (Z/200)**(1/1.6)
743 761 dBRR = 10*numpy.log10(RR)
744 762 dBRR2 = 10*numpy.log10(RR2)
745
763
746 764 dBZe = 10*numpy.log10(Ze)
747 765 dBZ = 10*numpy.log10(Z)
748
766
749 767 dataOut.data_output = RR[8]
750 768 dataOut.data_param = numpy.ones([3,self.Num_Hei])
751 769 dataOut.channelList = [0,1,2]
752
770
753 771 dataOut.data_param[0]=dBZ
754 772 dataOut.data_param[1]=V_mean
755 773 dataOut.data_param[2]=RR
756 774
757 775 return dataOut
758
776
759 777 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
760
778
761 779 NPW = dataOut.NPW
762 780 COFA = dataOut.COFA
763
781
764 782 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
765 783 RadarConst = dataOut.RadarConst
766 784 #frequency = 34.85*10**9
767
785
768 786 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
769 787 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
770
788
771 789 ETA = numpy.sum(SNR,1)
772
790
773 791 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
774
792
775 793 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
776
794
777 795 for r in range(self.Num_Hei):
778
796
779 797 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
780 798 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
781
799
782 800 return Ze
783
801
784 802 # def GetRadarConstant(self):
785 #
786 # """
803 #
804 # """
787 805 # Constants:
788 #
806 #
789 807 # Pt: Transmission Power dB 5kW 5000
790 808 # Gt: Transmission Gain dB 24.7 dB 295.1209
791 809 # Gr: Reception Gain dB 18.5 dB 70.7945
792 810 # Lambda: Wavelenght m 0.6741 m 0.6741
793 811 # aL: Attenuation loses dB 4dB 2.5118
794 812 # tauW: Width of transmission pulse s 4us 4e-6
795 813 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
796 814 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
797 #
815 #
798 816 # """
799 #
817 #
800 818 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
801 819 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
802 820 # RadarConstant = Numerator / Denominator
803 #
821 #
804 822 # return RadarConstant
805
806
807
808 class FullSpectralAnalysis(Operation):
809
823
824
825
826 class FullSpectralAnalysis(Operation):
827
810 828 """
811 829 Function that implements Full Spectral Analysis technique.
812
813 Input:
830
831 Input:
814 832 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
815 833 self.dataOut.groupList : Pairlist of channels
816 834 self.dataOut.ChanDist : Physical distance between receivers
817
818
819 Output:
820
821 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
822
823
835
836
837 Output:
838
839 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
840
841
824 842 Parameters affected: Winds, height range, SNR
825
843
826 844 """
827 845 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRlimit=7, minheight=None, maxheight=None):
828
829 self.indice=int(numpy.random.rand()*1000)
830
846
847 self.indice=int(numpy.random.rand()*1000)
848
831 849 spc = dataOut.data_pre[0].copy()
832 850 cspc = dataOut.data_pre[1]
833
851
834 852 """Erick: NOTE THE RANGE OF THE PULSE TX MUST BE REMOVED"""
835 853
836 854 SNRspc = spc.copy()
837 855 SNRspc[:,:,0:7]= numpy.NaN
838
856
839 857 """##########################################"""
840
841
858
859
842 860 nChannel = spc.shape[0]
843 861 nProfiles = spc.shape[1]
844 862 nHeights = spc.shape[2]
845
863
846 864 # first_height = 0.75 #km (ref: data header 20170822)
847 865 # resolution_height = 0.075 #km
848 866 '''
849 867 finding height range. check this when radar parameters are changed!
850 868 '''
851 869 if maxheight is not None:
852 870 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
853 871 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
854 872 else:
855 873 range_max = nHeights
856 874 if minheight is not None:
857 875 # range_min = int((minheight - first_height) / resolution_height) # theoretical
858 876 range_min = int(13.26 * minheight - 5) # empirical, works better
859 877 if range_min < 0:
860 878 range_min = 0
861 879 else:
862 880 range_min = 0
863 881
864 882 pairsList = dataOut.groupList
865 883 if dataOut.ChanDist is not None :
866 884 ChanDist = dataOut.ChanDist
867 885 else:
868 886 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
869
887
870 888 FrecRange = dataOut.spc_range[0]
871
889
872 890 data_SNR=numpy.zeros([nProfiles])
873 891 noise = dataOut.noise
874
892
875 893 dataOut.data_SNR = (numpy.mean(SNRspc,axis=1)- noise[0]) / noise[0]
876
894
877 895 dataOut.data_SNR[numpy.where( dataOut.data_SNR <0 )] = 1e-20
878
879
896
897
880 898 data_output=numpy.ones([spc.shape[0],spc.shape[2]])*numpy.NaN
881
899
882 900 velocityX=[]
883 901 velocityY=[]
884 velocityV=[]
885
902 velocityV=[]
903
886 904 dbSNR = 10*numpy.log10(dataOut.data_SNR)
887 905 dbSNR = numpy.average(dbSNR,0)
888
906
889 907 '''***********************************************WIND ESTIMATION**************************************'''
890
908
891 909 for Height in range(nHeights):
892
893 if Height >= range_min and Height < range_max:
894 # error_code unused, yet maybe useful for future analysis.
910
911 if Height >= range_min and Height < range_max:
912 # error_code unused, yet maybe useful for future analysis.
895 913 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList, ChanDist, Height, noise, dataOut.spc_range, dbSNR[Height], SNRlimit)
896 914 else:
897 915 Vzon,Vmer,Vver = 0., 0., numpy.NaN
898
899
916
917
900 918 if abs(Vzon) < 100. and abs(Vzon) > 0. and abs(Vmer) < 100. and abs(Vmer) > 0.:
901 919 velocityX=numpy.append(velocityX, Vzon)
902 920 velocityY=numpy.append(velocityY, -Vmer)
903 921
904 922 else:
905 923 velocityX=numpy.append(velocityX, numpy.NaN)
906 924 velocityY=numpy.append(velocityY, numpy.NaN)
907
925
908 926 if dbSNR[Height] > SNRlimit:
909 927 velocityV=numpy.append(velocityV, -Vver) # reason for this minus sign -> convention? (taken from Ericks version)
910 928 else:
911 929 velocityV=numpy.append(velocityV, numpy.NaN)
912
913
930
931
914 932 '''Change the numpy.array (velocityX) sign when trying to process BLTR data (Erick)'''
915 data_output[0] = numpy.array(velocityX)
916 data_output[1] = numpy.array(velocityY)
933 data_output[0] = numpy.array(velocityX)
934 data_output[1] = numpy.array(velocityY)
917 935 data_output[2] = velocityV
918
919
936
937
920 938 dataOut.data_output = data_output
921
939
922 940 return dataOut
923
941
924 942
925 943 def moving_average(self,x, N=2):
926 944 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
927 945 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
928
946
929 947 def gaus(self,xSamples,Amp,Mu,Sigma):
930 948 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
931
949
932 950 def Moments(self, ySamples, xSamples):
933 '''***
951 '''***
934 952 Variables corresponding to moments of distribution.
935 953 Also used as initial coefficients for curve_fit.
936 954 Vr was corrected. Only a velocity when x is velocity, of course.
937 955 ***'''
938 956 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
939 957 yNorm = ySamples / Pot
940 958 x_range = (numpy.max(xSamples)-numpy.min(xSamples))
941 959 Vr = numpy.nansum( yNorm * xSamples )*x_range/len(xSamples) # Velocidad radial, mu, corrimiento doppler, primer momento
942 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
960 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
943 961 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
944
962
945 963 return numpy.array([Pot, Vr, Desv])
946 964
947 965 def StopWindEstimation(self, error_code):
948 966 '''
949 967 the wind calculation and returns zeros
950 968 '''
951 969 Vzon = 0
952 970 Vmer = 0
953 971 Vver = numpy.nan
954 972 return Vzon, Vmer, Vver, error_code
955 973
956 974 def AntiAliasing(self, interval, maxstep):
957 """
975 """
958 976 function to prevent errors from aliased values when computing phaseslope
959 977 """
960 978 antialiased = numpy.zeros(len(interval))*0.0
961 979 copyinterval = interval.copy()
962 980
963 981 antialiased[0] = copyinterval[0]
964 982
965 983 for i in range(1,len(antialiased)):
966 984
967 step = interval[i] - interval[i-1]
968
985 step = interval[i] - interval[i-1]
986
969 987 if step > maxstep:
970 988 copyinterval -= 2*numpy.pi
971 989 antialiased[i] = copyinterval[i]
972 990
973 991 elif step < maxstep*(-1):
974 992 copyinterval += 2*numpy.pi
975 993 antialiased[i] = copyinterval[i]
976
994
977 995 else:
978 996 antialiased[i] = copyinterval[i].copy()
979 997
980 998 return antialiased
981 999
982 1000 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit):
983 1001 """
984 1002 Function that Calculates Zonal, Meridional and Vertical wind velocities.
985 1003 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
986 1004
987 1005 Input:
988 1006 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
989 1007 pairsList : Pairlist of channels
990 1008 ChanDist : array of xi_ij and eta_ij
991 1009 Height : height at which data is processed
992 1010 noise : noise in [channels] format for specific height
993 1011 Abbsisarange : range of the frequencies or velocities
994 1012 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
995 1013
996 1014 Output:
997 1015 Vzon, Vmer, Vver : wind velocities
998 1016 error_code : int that states where code is terminated
999 1017
1000 1018 0 : no error detected
1001 1019 1 : Gaussian of mean spc exceeds widthlimit
1002 1020 2 : no Gaussian of mean spc found
1003 1021 3 : SNR to low or velocity to high -> prec. e.g.
1004 1022 4 : at least one Gaussian of cspc exceeds widthlimit
1005 1023 5 : zero out of three cspc Gaussian fits converged
1006 6 : phase slope fit could not be found
1024 6 : phase slope fit could not be found
1007 1025 7 : arrays used to fit phase have different length
1008 1026 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1009 1027
1010 1028 """
1011 1029
1012 1030 error_code = 0
1013
1031
1014 1032
1015 1033 SPC_Samples = numpy.ones([spc.shape[0],spc.shape[1]]) # for normalized spc values for one height
1016 1034 phase = numpy.ones([spc.shape[0],spc.shape[1]]) # phase between channels
1017 1035 CSPC_Samples = numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_) # for normalized cspc values
1018 1036 PhaseSlope = numpy.zeros(spc.shape[0]) # slope of the phases, channelwise
1019 1037 PhaseInter = numpy.ones(spc.shape[0]) # intercept to the slope of the phases, channelwise
1020 xFrec = AbbsisaRange[0][0:spc.shape[1]] # frequency range
1038 xFrec = AbbsisaRange[0][0:spc.shape[1]] # frequency range
1021 1039 xVel = AbbsisaRange[2][0:spc.shape[1]] # velocity range
1022 1040 SPCav = numpy.average(spc, axis=0)-numpy.average(noise) # spc[0]-noise[0]
1023
1041
1024 1042 SPCmoments_vel = self.Moments(SPCav, xVel ) # SPCmoments_vel[1] corresponds to vertical velocity and is used to determine if signal corresponds to wind (if .. <3)
1025 1043 CSPCmoments = []
1026
1044
1027 1045
1028 1046 '''Getting Eij and Nij'''
1029 1047
1030 1048 Xi01, Xi02, Xi12 = ChanDist[:,0]
1031 1049 Eta01, Eta02, Eta12 = ChanDist[:,1]
1032 1050
1033 1051 # update nov 19
1034 1052 widthlimit = 7 # maximum width in Hz of the gaussian, empirically determined. Anything above 10 is unrealistic, often values between 1 and 5 correspond to proper fits.
1035 1053
1036 1054 '''************************* SPC is normalized ********************************'''
1037 1055
1038 1056 spc_norm = spc.copy() # need copy() because untouched spc is needed for normalization of cspc below
1039 1057 spc_norm = numpy.where(numpy.isfinite(spc_norm), spc_norm, numpy.NAN)
1040 1058
1041 for i in range(spc.shape[0]):
1042
1059 for i in range(spc.shape[0]):
1060
1043 1061 spc_sub = spc_norm[i,:] - noise[i] # spc not smoothed here or in previous version.
1044 1062
1045 1063 Factor_Norm = 2*numpy.max(xFrec) / numpy.count_nonzero(~numpy.isnan(spc_sub)) # usually = Freq range / nfft
1046 normalized_spc = spc_sub / (numpy.nansum(numpy.abs(spc_sub)) * Factor_Norm)
1047
1064 normalized_spc = spc_sub / (numpy.nansum(numpy.abs(spc_sub)) * Factor_Norm)
1065
1048 1066 xSamples = xFrec # the frequency range is taken
1049 1067 SPC_Samples[i] = normalized_spc # Normalized SPC values are taken
1050 1068
1051 1069 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1052 1070
1053 1071 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1054 1072 you only fit the curve and don't need the absolute value of height for calculation,
1055 1073 only for estimation of width. for normalization of cross spectra, you need initial,
1056 1074 unnormalized self-spectra With noise.
1057 1075
1058 Technically, you don't even need to normalize the self-spectra, as you only need the
1076 Technically, you don't even need to normalize the self-spectra, as you only need the
1059 1077 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1060 1078 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1061 1079 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1062 1080 """
1063 1081
1064 SPCMean = numpy.average(SPC_Samples, axis=0)
1065
1082 SPCMean = numpy.average(SPC_Samples, axis=0)
1083
1066 1084 popt = [1e-10,0,1e-10]
1067 1085 SPCMoments = self.Moments(SPCMean, xSamples)
1068 1086
1069 if dbSNR > SNRlimit and numpy.abs(SPCmoments_vel[1]) < 3:
1087 if dbSNR > SNRlimit and numpy.abs(SPCmoments_vel[1]) < 3:
1070 1088 try:
1071 1089 popt,pcov = curve_fit(self.gaus,xSamples,SPCMean,p0=SPCMoments)#, bounds=(-numpy.inf, [numpy.inf, numpy.inf, 10])). Setting bounds does not make the code faster but only keeps the fit from finding the minimum.
1072 1090 if popt[2] > widthlimit: # CONDITION
1073 1091 return self.StopWindEstimation(error_code = 1)
1074 1092
1075 1093 FitGauss = self.gaus(xSamples,*popt)
1076
1094
1077 1095 except :#RuntimeError:
1078 1096 return self.StopWindEstimation(error_code = 2)
1079 1097
1080 1098 else:
1081 1099 return self.StopWindEstimation(error_code = 3)
1082
1100
1083 1101
1084 1102
1085 1103 '''***************************** CSPC Normalization *************************
1086 1104 new section:
1087 1105 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1088 influence the norm which is not desired. First, a range is identified where the
1089 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1090 around it gets cut off and values replaced by mean determined by the boundary
1106 influence the norm which is not desired. First, a range is identified where the
1107 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1108 around it gets cut off and values replaced by mean determined by the boundary
1091 1109 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1092 1110
1093 1111 The sums are then added and multiplied by range/datapoints, because you need
1094 1112 an integral and not a sum for normalization.
1095
1096 A norm is found according to Briggs 92.
1113
1114 A norm is found according to Briggs 92.
1097 1115 '''
1098 1116
1099 1117 radarWavelength = 0.6741 # meters
1100 count_limit_freq = numpy.abs(popt[1]) + widthlimit # Hz, m/s can be also used if velocity is desired abscissa.
1118 count_limit_freq = numpy.abs(popt[1]) + widthlimit # Hz, m/s can be also used if velocity is desired abscissa.
1101 1119 # count_limit_freq = numpy.max(xFrec)
1102 1120
1103 1121 channel_integrals = numpy.zeros(3)
1104 1122
1105 1123 for i in range(spc.shape[0]):
1106 1124 '''
1107 1125 find the point in array corresponding to count_limit frequency.
1108 1126 sum over all frequencies in the range around zero Hz @ math.ceil(N_freq/2)
1109 1127 '''
1110 1128 N_freq = numpy.count_nonzero(~numpy.isnan(spc[i,:]))
1111 count_limit_int = int(math.ceil( count_limit_freq / numpy.max(xFrec) * (N_freq / 2) )) # gives integer point
1129 count_limit_int = int(math.ceil( count_limit_freq / numpy.max(xFrec) * (N_freq / 2) )) # gives integer point
1112 1130 sum_wind = numpy.nansum( spc[i, (math.ceil(N_freq/2) - count_limit_int) : (math.ceil(N_freq / 2) + count_limit_int)] ) #N_freq/2 is where frequency (velocity) is zero, i.e. middle of spectrum.
1113 1131 sum_noise = (numpy.mean(spc[i, :4]) + numpy.mean(spc[i, -6:-2]))/2.0 * (N_freq - 2*count_limit_int)
1114 1132 channel_integrals[i] = (sum_noise + sum_wind) * (2*numpy.max(xFrec) / N_freq)
1115
1133
1116 1134
1117 1135 cross_integrals_peak = numpy.zeros(3)
1118 1136 # cross_integrals_totalrange = numpy.zeros(3)
1119 1137
1120 1138 for i in range(spc.shape[0]):
1121 1139
1122 1140 cspc_norm = cspc[i,:].copy() # cspc not smoothed here or in previous version
1123 1141
1124 1142 chan_index0 = pairsList[i][0]
1125 1143 chan_index1 = pairsList[i][1]
1126 1144
1127 1145 cross_integrals_peak[i] = channel_integrals[chan_index0]*channel_integrals[chan_index1]
1128 normalized_cspc = cspc_norm / numpy.sqrt(cross_integrals_peak[i])
1146 normalized_cspc = cspc_norm / numpy.sqrt(cross_integrals_peak[i])
1129 1147 CSPC_Samples[i] = normalized_cspc
1130 1148
1131 1149 ''' Finding cross integrals without subtracting any peaks:'''
1132 1150 # FactorNorm0 = 2*numpy.max(xFrec) / numpy.count_nonzero(~numpy.isnan(spc[chan_index0,:]))
1133 1151 # FactorNorm1 = 2*numpy.max(xFrec) / numpy.count_nonzero(~numpy.isnan(spc[chan_index1,:]))
1134 # cross_integrals_totalrange[i] = (numpy.nansum(spc[chan_index0,:])) * FactorNorm0 * (numpy.nansum(spc[chan_index1,:])) * FactorNorm1
1135 # normalized_cspc = cspc_norm / numpy.sqrt(cross_integrals_totalrange[i])
1152 # cross_integrals_totalrange[i] = (numpy.nansum(spc[chan_index0,:])) * FactorNorm0 * (numpy.nansum(spc[chan_index1,:])) * FactorNorm1
1153 # normalized_cspc = cspc_norm / numpy.sqrt(cross_integrals_totalrange[i])
1136 1154 # CSPC_Samples[i] = normalized_cspc
1137
1138
1155
1156
1139 1157 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1140 1158
1141 1159
1142 1160 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0]), xSamples),
1143 1161 self.Moments(numpy.abs(CSPC_Samples[1]), xSamples),
1144 1162 self.Moments(numpy.abs(CSPC_Samples[2]), xSamples)])
1145
1163
1146 1164
1147 1165 '''***Sorting out NaN entries***'''
1148 1166 CSPCMask01 = numpy.abs(CSPC_Samples[0])
1149 1167 CSPCMask02 = numpy.abs(CSPC_Samples[1])
1150 1168 CSPCMask12 = numpy.abs(CSPC_Samples[2])
1151
1169
1152 1170 mask01 = ~numpy.isnan(CSPCMask01)
1153 1171 mask02 = ~numpy.isnan(CSPCMask02)
1154 1172 mask12 = ~numpy.isnan(CSPCMask12)
1155
1173
1156 1174 CSPCMask01 = CSPCMask01[mask01]
1157 1175 CSPCMask02 = CSPCMask02[mask02]
1158 1176 CSPCMask12 = CSPCMask12[mask12]
1159 1177
1160
1161 popt01, popt02, popt12 = [1e-10,1e-10,1e-10], [1e-10,1e-10,1e-10] ,[1e-10,1e-10,1e-10]
1178
1179 popt01, popt02, popt12 = [1e-10,1e-10,1e-10], [1e-10,1e-10,1e-10] ,[1e-10,1e-10,1e-10]
1162 1180 FitGauss01, FitGauss02, FitGauss12 = numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0
1163
1181
1164 1182 '''*******************************FIT GAUSS CSPC************************************'''
1165 1183
1166 try:
1184 try:
1167 1185 popt01,pcov = curve_fit(self.gaus,xSamples[mask01],numpy.abs(CSPCMask01),p0=CSPCmoments[0])
1168 1186 if popt01[2] > widthlimit: # CONDITION
1169 1187 return self.StopWindEstimation(error_code = 4)
1170 1188
1171 1189 popt02,pcov = curve_fit(self.gaus,xSamples[mask02],numpy.abs(CSPCMask02),p0=CSPCmoments[1])
1172 1190 if popt02[2] > widthlimit: # CONDITION
1173 1191 return self.StopWindEstimation(error_code = 4)
1174 1192
1175 1193 popt12,pcov = curve_fit(self.gaus,xSamples[mask12],numpy.abs(CSPCMask12),p0=CSPCmoments[2])
1176 1194 if popt12[2] > widthlimit: # CONDITION
1177 1195 return self.StopWindEstimation(error_code = 4)
1178 1196
1179 1197 FitGauss01 = self.gaus(xSamples, *popt01)
1180 1198 FitGauss02 = self.gaus(xSamples, *popt02)
1181 1199 FitGauss12 = self.gaus(xSamples, *popt12)
1182 1200
1183 1201 except:
1184 1202 return self.StopWindEstimation(error_code = 5)
1185 1203
1186 1204
1187 1205 '''************* Getting Fij ***************'''
1188 1206
1189
1190 #Punto en Eje X de la Gaussiana donde se encuentra el centro -- x-axis point of the gaussian where the center is located
1191 # -> PointGauCenter
1192 GaussCenter = popt[1]
1207
1208 #Punto en Eje X de la Gaussiana donde se encuentra el centro -- x-axis point of the gaussian where the center is located
1209 # -> PointGauCenter
1210 GaussCenter = popt[1]
1193 1211 ClosestCenter = xSamples[numpy.abs(xSamples-GaussCenter).argmin()]
1194 1212 PointGauCenter = numpy.where(xSamples==ClosestCenter)[0][0]
1195
1213
1196 1214 #Punto e^-1 hubicado en la Gaussiana -- point where e^-1 is located in the gaussian
1197 1215 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1198 1216 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # El punto mas cercano a "Peminus1" dentro de "FitGauss"
1199 1217 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1200 1218
1201 1219 Fij = numpy.abs(xSamples[PointFij] - xSamples[PointGauCenter])
1202
1220
1203 1221 '''********** Taking frequency ranges from mean SPCs **********'''
1204
1222
1205 1223 #GaussCenter = popt[1] #Primer momento 01
1206 1224 GauWidth = popt[2] * 3/2 #Ancho de banda de Gau01 -- Bandwidth of Gau01 TODO why *3/2?
1207 1225 Range = numpy.empty(2)
1208 1226 Range[0] = GaussCenter - GauWidth
1209 Range[1] = GaussCenter + GauWidth
1227 Range[1] = GaussCenter + GauWidth
1210 1228 #Punto en Eje X de la Gaussiana donde se encuentra ancho de banda (min:max) -- Point in x-axis where the bandwidth is located (min:max)
1211 1229 ClosRangeMin = xSamples[numpy.abs(xSamples-Range[0]).argmin()]
1212 1230 ClosRangeMax = xSamples[numpy.abs(xSamples-Range[1]).argmin()]
1213
1231
1214 1232 PointRangeMin = numpy.where(xSamples==ClosRangeMin)[0][0]
1215 1233 PointRangeMax = numpy.where(xSamples==ClosRangeMax)[0][0]
1216
1234
1217 1235 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1218
1236
1219 1237 FrecRange = xFrec[ Range[0] : Range[1] ]
1220 1238
1221
1222 '''************************** Getting Phase Slope ***************************'''
1223
1224 for i in range(1,3): # Changed to only compute two
1225
1239
1240 '''************************** Getting Phase Slope ***************************'''
1241
1242 for i in range(1,3): # Changed to only compute two
1243
1226 1244 if len(FrecRange) > 5 and len(FrecRange) < spc.shape[1] * 0.3:
1227 1245 # PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=1) #used before to smooth phase with N=3
1228 1246 PhaseRange = phase[i,Range[0]:Range[1]].copy()
1229
1247
1230 1248 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1231
1249
1232 1250
1233 1251 if len(FrecRange) == len(PhaseRange):
1234
1235 try:
1252
1253 try:
1236 1254 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1237 1255 PhaseSlope[i] = slope
1238 1256 PhaseInter[i] = intercept
1239 1257
1240 1258 except:
1241 1259 return self.StopWindEstimation(error_code = 6)
1242 1260
1243 1261 else:
1244 1262 return self.StopWindEstimation(error_code = 7)
1245
1263
1246 1264 else:
1247 1265 return self.StopWindEstimation(error_code = 8)
1248
1249
1250
1266
1267
1268
1251 1269 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1252 1270
1253 1271 '''Getting constant C'''
1254 1272 cC=(Fij*numpy.pi)**2
1255
1273
1256 1274 '''****** Getting constants F and G ******'''
1257 1275 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1258 1276 MijResult0 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1259 MijResult1 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1277 MijResult1 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1260 1278 MijResults = numpy.array([MijResult0,MijResult1])
1261 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1262
1279 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1280
1263 1281 '''****** Getting constants A, B and H ******'''
1264 W01 = numpy.nanmax( FitGauss01 )
1265 W02 = numpy.nanmax( FitGauss02 )
1266 W12 = numpy.nanmax( FitGauss12 )
1267
1282 W01 = numpy.nanmax( FitGauss01 )
1283 W02 = numpy.nanmax( FitGauss02 )
1284 W12 = numpy.nanmax( FitGauss12 )
1285
1268 1286 WijResult0 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1269 1287 WijResult1 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1270 1288 WijResult2 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1271
1289
1272 1290 WijResults = numpy.array([WijResult0, WijResult1, WijResult2])
1273
1274 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1291
1292 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1275 1293 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1276
1294
1277 1295 VxVy = numpy.array([[cA,cH],[cH,cB]])
1278 1296 VxVyResults = numpy.array([-cF,-cG])
1279 1297 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1280
1298
1281 1299 Vzon = Vy
1282 1300 Vmer = Vx
1283
1301
1284 1302 # Vmag=numpy.sqrt(Vzon**2+Vmer**2) # unused
1285 1303 # Vang=numpy.arctan2(Vmer,Vzon) # unused
1286 1304
1287
1305
1288 1306 ''' using frequency as abscissa. Due to three channels, the offzenith angle is zero
1289 1307 and Vrad equal to Vver. formula taken from Briggs 92, figure 4.
1290 1308 '''
1291 1309 if numpy.abs( popt[1] ) < 3.5 and len(FrecRange) > 4:
1292 1310 Vver = 0.5 * radarWavelength * popt[1] * 100 # *100 to get cm (/s)
1293 1311 else:
1294 1312 Vver = numpy.NaN
1295 1313
1296 1314 error_code = 0
1297 1315
1298 return Vzon, Vmer, Vver, error_code
1316 return Vzon, Vmer, Vver, error_code
1299 1317
1300 1318
1301 1319 class SpectralMoments(Operation):
1302
1320
1303 1321 '''
1304 1322 Function SpectralMoments()
1305
1323
1306 1324 Calculates moments (power, mean, standard deviation) and SNR of the signal
1307
1325
1308 1326 Type of dataIn: Spectra
1309
1327
1310 1328 Configuration Parameters:
1311
1329
1312 1330 dirCosx : Cosine director in X axis
1313 1331 dirCosy : Cosine director in Y axis
1314
1332
1315 1333 elevation :
1316 1334 azimuth :
1317
1335
1318 1336 Input:
1319 channelList : simple channel list to select e.g. [2,3,7]
1337 channelList : simple channel list to select e.g. [2,3,7]
1320 1338 self.dataOut.data_pre : Spectral data
1321 1339 self.dataOut.abscissaList : List of frequencies
1322 1340 self.dataOut.noise : Noise level per channel
1323
1341
1324 1342 Affected:
1325 1343 self.dataOut.moments : Parameters per channel
1326 1344 self.dataOut.data_SNR : SNR per channel
1327
1345
1328 1346 '''
1329
1347
1330 1348 def run(self, dataOut):
1331
1349
1332 1350 #dataOut.data_pre = dataOut.data_pre[0]
1333 1351 data = dataOut.data_pre[0]
1334 1352 absc = dataOut.abscissaList[:-1]
1335 1353 noise = dataOut.noise
1336 1354 nChannel = data.shape[0]
1337 1355 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1338
1356
1339 1357 for ind in range(nChannel):
1340 1358 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1341
1359
1342 1360 dataOut.moments = data_param[:,1:,:]
1343 1361 dataOut.data_SNR = data_param[:,0]
1344 1362 dataOut.data_POW = data_param[:,1]
1345 1363 dataOut.data_DOP = data_param[:,2]
1346 1364 dataOut.data_WIDTH = data_param[:,3]
1347 1365 return dataOut
1348
1349 def __calculateMoments(self, oldspec, oldfreq, n0,
1366
1367 def __calculateMoments(self, oldspec, oldfreq, n0,
1350 1368 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1351
1369
1352 1370 if (nicoh is None): nicoh = 1
1353 if (graph is None): graph = 0
1371 if (graph is None): graph = 0
1354 1372 if (smooth is None): smooth = 0
1355 1373 elif (self.smooth < 3): smooth = 0
1356 1374
1357 1375 if (type1 is None): type1 = 0
1358 1376 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1359 1377 if (snrth is None): snrth = -3
1360 1378 if (dc is None): dc = 0
1361 1379 if (aliasing is None): aliasing = 0
1362 1380 if (oldfd is None): oldfd = 0
1363 1381 if (wwauto is None): wwauto = 0
1364
1382
1365 1383 if (n0 < 1.e-20): n0 = 1.e-20
1366
1384
1367 1385 freq = oldfreq
1368 1386 vec_power = numpy.zeros(oldspec.shape[1])
1369 1387 vec_fd = numpy.zeros(oldspec.shape[1])
1370 1388 vec_w = numpy.zeros(oldspec.shape[1])
1371 1389 vec_snr = numpy.zeros(oldspec.shape[1])
1372
1390
1373 1391 oldspec = numpy.ma.masked_invalid(oldspec)
1374 1392
1375 1393 for ind in range(oldspec.shape[1]):
1376
1394
1377 1395 spec = oldspec[:,ind]
1378 1396 aux = spec*fwindow
1379 1397 max_spec = aux.max()
1380 1398 m = list(aux).index(max_spec)
1381
1382 #Smooth
1399
1400 #Smooth
1383 1401 if (smooth == 0): spec2 = spec
1384 1402 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1385
1403
1386 1404 # Calculo de Momentos
1387 1405 bb = spec2[list(range(m,spec2.size))]
1388 1406 bb = (bb<n0).nonzero()
1389 1407 bb = bb[0]
1390
1408
1391 1409 ss = spec2[list(range(0,m + 1))]
1392 1410 ss = (ss<n0).nonzero()
1393 1411 ss = ss[0]
1394
1412
1395 1413 if (bb.size == 0):
1396 1414 bb0 = spec.size - 1 - m
1397 else:
1415 else:
1398 1416 bb0 = bb[0] - 1
1399 1417 if (bb0 < 0):
1400 1418 bb0 = 0
1401
1419
1402 1420 if (ss.size == 0): ss1 = 1
1403 1421 else: ss1 = max(ss) + 1
1404
1422
1405 1423 if (ss1 > m): ss1 = m
1406
1407 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
1424
1425 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
1408 1426 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
1409 1427 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
1410 1428 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1411 snr = (spec2.mean()-n0)/n0
1412
1413 if (snr < 1.e-20) :
1429 snr = (spec2.mean()-n0)/n0
1430
1431 if (snr < 1.e-20) :
1414 1432 snr = 1.e-20
1415
1433
1416 1434 vec_power[ind] = power
1417 1435 vec_fd[ind] = fd
1418 1436 vec_w[ind] = w
1419 1437 vec_snr[ind] = snr
1420
1438
1421 1439 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1422 1440 return moments
1423
1441
1424 1442 #------------------ Get SA Parameters --------------------------
1425
1443
1426 1444 def GetSAParameters(self):
1427 1445 #SA en frecuencia
1428 1446 pairslist = self.dataOut.groupList
1429 1447 num_pairs = len(pairslist)
1430
1448
1431 1449 vel = self.dataOut.abscissaList
1432 1450 spectra = self.dataOut.data_pre
1433 1451 cspectra = self.dataIn.data_cspc
1434 delta_v = vel[1] - vel[0]
1435
1452 delta_v = vel[1] - vel[0]
1453
1436 1454 #Calculating the power spectrum
1437 1455 spc_pow = numpy.sum(spectra, 3)*delta_v
1438 1456 #Normalizing Spectra
1439 1457 norm_spectra = spectra/spc_pow
1440 1458 #Calculating the norm_spectra at peak
1441 max_spectra = numpy.max(norm_spectra, 3)
1442
1459 max_spectra = numpy.max(norm_spectra, 3)
1460
1443 1461 #Normalizing Cross Spectra
1444 1462 norm_cspectra = numpy.zeros(cspectra.shape)
1445
1463
1446 1464 for i in range(num_chan):
1447 1465 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1448
1466
1449 1467 max_cspectra = numpy.max(norm_cspectra,2)
1450 1468 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1451
1469
1452 1470 for i in range(num_pairs):
1453 1471 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1454 1472 #------------------- Get Lags ----------------------------------
1455
1473
1456 1474 class SALags(Operation):
1457 1475 '''
1458 1476 Function GetMoments()
1459 1477
1460 1478 Input:
1461 1479 self.dataOut.data_pre
1462 1480 self.dataOut.abscissaList
1463 1481 self.dataOut.noise
1464 1482 self.dataOut.normFactor
1465 1483 self.dataOut.data_SNR
1466 1484 self.dataOut.groupList
1467 1485 self.dataOut.nChannels
1468
1486
1469 1487 Affected:
1470 1488 self.dataOut.data_param
1471
1489
1472 1490 '''
1473 def run(self, dataOut):
1491 def run(self, dataOut):
1474 1492 data_acf = dataOut.data_pre[0]
1475 1493 data_ccf = dataOut.data_pre[1]
1476 1494 normFactor_acf = dataOut.normFactor[0]
1477 1495 normFactor_ccf = dataOut.normFactor[1]
1478 1496 pairs_acf = dataOut.groupList[0]
1479 1497 pairs_ccf = dataOut.groupList[1]
1480
1498
1481 1499 nHeights = dataOut.nHeights
1482 1500 absc = dataOut.abscissaList
1483 1501 noise = dataOut.noise
1484 1502 SNR = dataOut.data_SNR
1485 1503 nChannels = dataOut.nChannels
1486 1504 # pairsList = dataOut.groupList
1487 1505 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1488 1506
1489 1507 for l in range(len(pairs_acf)):
1490 1508 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1491
1509
1492 1510 for l in range(len(pairs_ccf)):
1493 1511 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1494
1512
1495 1513 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1496 1514 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1497 1515 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1498 1516 return
1499
1517
1500 1518 # def __getPairsAutoCorr(self, pairsList, nChannels):
1501 #
1519 #
1502 1520 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1503 #
1504 # for l in range(len(pairsList)):
1521 #
1522 # for l in range(len(pairsList)):
1505 1523 # firstChannel = pairsList[l][0]
1506 1524 # secondChannel = pairsList[l][1]
1507 #
1508 # #Obteniendo pares de Autocorrelacion
1525 #
1526 # #Obteniendo pares de Autocorrelacion
1509 1527 # if firstChannel == secondChannel:
1510 1528 # pairsAutoCorr[firstChannel] = int(l)
1511 #
1529 #
1512 1530 # pairsAutoCorr = pairsAutoCorr.astype(int)
1513 #
1531 #
1514 1532 # pairsCrossCorr = range(len(pairsList))
1515 1533 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1516 #
1534 #
1517 1535 # return pairsAutoCorr, pairsCrossCorr
1518
1536
1519 1537 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1520
1538
1521 1539 lag0 = data_acf.shape[1]/2
1522 1540 #Funcion de Autocorrelacion
1523 1541 mean_acf = stats.nanmean(data_acf, axis = 0)
1524
1542
1525 1543 #Obtencion Indice de TauCross
1526 1544 ind_ccf = data_ccf.argmax(axis = 1)
1527 1545 #Obtencion Indice de TauAuto
1528 1546 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1529 1547 ccf_lag0 = data_ccf[:,lag0,:]
1530
1548
1531 1549 for i in range(ccf_lag0.shape[0]):
1532 1550 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1533
1551
1534 1552 #Obtencion de TauCross y TauAuto
1535 1553 tau_ccf = lagRange[ind_ccf]
1536 1554 tau_acf = lagRange[ind_acf]
1537
1555
1538 1556 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1539
1557
1540 1558 tau_ccf[Nan1,Nan2] = numpy.nan
1541 1559 tau_acf[Nan1,Nan2] = numpy.nan
1542 1560 tau = numpy.vstack((tau_ccf,tau_acf))
1543
1561
1544 1562 return tau
1545
1563
1546 1564 def __calculateLag1Phase(self, data, lagTRange):
1547 1565 data1 = stats.nanmean(data, axis = 0)
1548 1566 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1549 1567
1550 1568 phase = numpy.angle(data1[lag1,:])
1551
1569
1552 1570 return phase
1553
1571
1554 1572 class SpectralFitting(Operation):
1555 1573 '''
1556 1574 Function GetMoments()
1557
1575
1558 1576 Input:
1559 1577 Output:
1560 1578 Variables modified:
1561 1579 '''
1562
1563 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1564
1565
1580
1581 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1582
1583
1566 1584 if path != None:
1567 1585 sys.path.append(path)
1568 1586 self.dataOut.library = importlib.import_module(file)
1569
1587
1570 1588 #To be inserted as a parameter
1571 1589 groupArray = numpy.array(groupList)
1572 # groupArray = numpy.array([[0,1],[2,3]])
1590 # groupArray = numpy.array([[0,1],[2,3]])
1573 1591 self.dataOut.groupList = groupArray
1574
1592
1575 1593 nGroups = groupArray.shape[0]
1576 1594 nChannels = self.dataIn.nChannels
1577 1595 nHeights=self.dataIn.heightList.size
1578
1596
1579 1597 #Parameters Array
1580 1598 self.dataOut.data_param = None
1581
1599
1582 1600 #Set constants
1583 1601 constants = self.dataOut.library.setConstants(self.dataIn)
1584 1602 self.dataOut.constants = constants
1585 1603 M = self.dataIn.normFactor
1586 1604 N = self.dataIn.nFFTPoints
1587 1605 ippSeconds = self.dataIn.ippSeconds
1588 1606 K = self.dataIn.nIncohInt
1589 1607 pairsArray = numpy.array(self.dataIn.pairsList)
1590
1608
1591 1609 #List of possible combinations
1592 1610 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1593 1611 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1594
1612
1595 1613 if getSNR:
1596 1614 listChannels = groupArray.reshape((groupArray.size))
1597 1615 listChannels.sort()
1598 1616 noise = self.dataIn.getNoise()
1599 1617 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1600
1601 for i in range(nGroups):
1618
1619 for i in range(nGroups):
1602 1620 coord = groupArray[i,:]
1603
1621
1604 1622 #Input data array
1605 1623 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1606 1624 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1607
1625
1608 1626 #Cross Spectra data array for Covariance Matrixes
1609 1627 ind = 0
1610 1628 for pairs in listComb:
1611 1629 pairsSel = numpy.array([coord[x],coord[y]])
1612 1630 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1613 1631 ind += 1
1614 1632 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1615 1633 dataCross = dataCross**2/K
1616
1634
1617 1635 for h in range(nHeights):
1618
1636
1619 1637 #Input
1620 1638 d = data[:,h]
1621 1639
1622 1640 #Covariance Matrix
1623 1641 D = numpy.diag(d**2/K)
1624 1642 ind = 0
1625 1643 for pairs in listComb:
1626 1644 #Coordinates in Covariance Matrix
1627 x = pairs[0]
1645 x = pairs[0]
1628 1646 y = pairs[1]
1629 1647 #Channel Index
1630 1648 S12 = dataCross[ind,:,h]
1631 1649 D12 = numpy.diag(S12)
1632 1650 #Completing Covariance Matrix with Cross Spectras
1633 1651 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1634 1652 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1635 1653 ind += 1
1636 1654 Dinv=numpy.linalg.inv(D)
1637 1655 L=numpy.linalg.cholesky(Dinv)
1638 1656 LT=L.T
1639 1657
1640 1658 dp = numpy.dot(LT,d)
1641
1659
1642 1660 #Initial values
1643 1661 data_spc = self.dataIn.data_spc[coord,:,h]
1644
1662
1645 1663 if (h>0)and(error1[3]<5):
1646 1664 p0 = self.dataOut.data_param[i,:,h-1]
1647 1665 else:
1648 1666 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1649
1667
1650 1668 try:
1651 1669 #Least Squares
1652 1670 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1653 1671 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1654 1672 #Chi square error
1655 1673 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1656 1674 #Error with Jacobian
1657 1675 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1658 1676 except:
1659 1677 minp = p0*numpy.nan
1660 1678 error0 = numpy.nan
1661 1679 error1 = p0*numpy.nan
1662
1680
1663 1681 #Save
1664 1682 if self.dataOut.data_param is None:
1665 1683 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1666 1684 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1667
1685
1668 1686 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1669 1687 self.dataOut.data_param[i,:,h] = minp
1670 1688 return
1671
1689
1672 1690 def __residFunction(self, p, dp, LT, constants):
1673 1691
1674 1692 fm = self.dataOut.library.modelFunction(p, constants)
1675 1693 fmp=numpy.dot(LT,fm)
1676
1694
1677 1695 return dp-fmp
1678 1696
1679 1697 def __getSNR(self, z, noise):
1680
1698
1681 1699 avg = numpy.average(z, axis=1)
1682 1700 SNR = (avg.T-noise)/noise
1683 1701 SNR = SNR.T
1684 1702 return SNR
1685
1703
1686 1704 def __chisq(p,chindex,hindex):
1687 1705 #similar to Resid but calculates CHI**2
1688 1706 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1689 1707 dp=numpy.dot(LT,d)
1690 1708 fmp=numpy.dot(LT,fm)
1691 1709 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1692 1710 return chisq
1693
1711
1694 1712 class WindProfiler(Operation):
1695
1713
1696 1714 __isConfig = False
1697
1715
1698 1716 __initime = None
1699 1717 __lastdatatime = None
1700 1718 __integrationtime = None
1701
1719
1702 1720 __buffer = None
1703
1721
1704 1722 __dataReady = False
1705
1723
1706 1724 __firstdata = None
1707
1725
1708 1726 n = None
1709
1710 def __init__(self):
1727
1728 def __init__(self):
1711 1729 Operation.__init__(self)
1712
1730
1713 1731 def __calculateCosDir(self, elev, azim):
1714 1732 zen = (90 - elev)*numpy.pi/180
1715 1733 azim = azim*numpy.pi/180
1716 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1734 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1717 1735 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1718
1736
1719 1737 signX = numpy.sign(numpy.cos(azim))
1720 1738 signY = numpy.sign(numpy.sin(azim))
1721
1739
1722 1740 cosDirX = numpy.copysign(cosDirX, signX)
1723 1741 cosDirY = numpy.copysign(cosDirY, signY)
1724 1742 return cosDirX, cosDirY
1725
1743
1726 1744 def __calculateAngles(self, theta_x, theta_y, azimuth):
1727
1745
1728 1746 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1729 1747 zenith_arr = numpy.arccos(dir_cosw)
1730 1748 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1731
1749
1732 1750 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1733 1751 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1734
1752
1735 1753 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1736 1754
1737 1755 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1738
1739 #
1756
1757 #
1740 1758 if horOnly:
1741 1759 A = numpy.c_[dir_cosu,dir_cosv]
1742 1760 else:
1743 1761 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1744 1762 A = numpy.asmatrix(A)
1745 1763 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1746 1764
1747 1765 return A1
1748 1766
1749 1767 def __correctValues(self, heiRang, phi, velRadial, SNR):
1750 1768 listPhi = phi.tolist()
1751 1769 maxid = listPhi.index(max(listPhi))
1752 1770 minid = listPhi.index(min(listPhi))
1753
1754 rango = list(range(len(phi)))
1771
1772 rango = list(range(len(phi)))
1755 1773 # rango = numpy.delete(rango,maxid)
1756
1774
1757 1775 heiRang1 = heiRang*math.cos(phi[maxid])
1758 1776 heiRangAux = heiRang*math.cos(phi[minid])
1759 1777 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1760 1778 heiRang1 = numpy.delete(heiRang1,indOut)
1761
1779
1762 1780 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1763 1781 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1764
1782
1765 1783 for i in rango:
1766 1784 x = heiRang*math.cos(phi[i])
1767 1785 y1 = velRadial[i,:]
1768 1786 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1769
1787
1770 1788 x1 = heiRang1
1771 1789 y11 = f1(x1)
1772
1790
1773 1791 y2 = SNR[i,:]
1774 1792 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1775 1793 y21 = f2(x1)
1776
1794
1777 1795 velRadial1[i,:] = y11
1778 1796 SNR1[i,:] = y21
1779
1797
1780 1798 return heiRang1, velRadial1, SNR1
1781 1799
1782 1800 def __calculateVelUVW(self, A, velRadial):
1783
1801
1784 1802 #Operacion Matricial
1785 1803 # velUVW = numpy.zeros((velRadial.shape[1],3))
1786 1804 # for ind in range(velRadial.shape[1]):
1787 1805 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1788 1806 # velUVW = velUVW.transpose()
1789 1807 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1790 1808 velUVW[:,:] = numpy.dot(A,velRadial)
1791
1792
1809
1810
1793 1811 return velUVW
1794
1812
1795 1813 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1796
1814
1797 1815 def techniqueDBS(self, kwargs):
1798 1816 """
1799 1817 Function that implements Doppler Beam Swinging (DBS) technique.
1800
1818
1801 1819 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1802 1820 Direction correction (if necessary), Ranges and SNR
1803
1821
1804 1822 Output: Winds estimation (Zonal, Meridional and Vertical)
1805
1823
1806 1824 Parameters affected: Winds, height range, SNR
1807 1825 """
1808 1826 velRadial0 = kwargs['velRadial']
1809 1827 heiRang = kwargs['heightList']
1810 1828 SNR0 = kwargs['SNR']
1811
1829
1812 1830 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1813 1831 theta_x = numpy.array(kwargs['dirCosx'])
1814 1832 theta_y = numpy.array(kwargs['dirCosy'])
1815 1833 else:
1816 1834 elev = numpy.array(kwargs['elevation'])
1817 1835 azim = numpy.array(kwargs['azimuth'])
1818 1836 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1819 azimuth = kwargs['correctAzimuth']
1837 azimuth = kwargs['correctAzimuth']
1820 1838 if 'horizontalOnly' in kwargs:
1821 1839 horizontalOnly = kwargs['horizontalOnly']
1822 1840 else: horizontalOnly = False
1823 1841 if 'correctFactor' in kwargs:
1824 1842 correctFactor = kwargs['correctFactor']
1825 1843 else: correctFactor = 1
1826 1844 if 'channelList' in kwargs:
1827 1845 channelList = kwargs['channelList']
1828 1846 if len(channelList) == 2:
1829 1847 horizontalOnly = True
1830 1848 arrayChannel = numpy.array(channelList)
1831 1849 param = param[arrayChannel,:,:]
1832 1850 theta_x = theta_x[arrayChannel]
1833 1851 theta_y = theta_y[arrayChannel]
1834
1835 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1836 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1852
1853 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1854 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1837 1855 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1838
1856
1839 1857 #Calculo de Componentes de la velocidad con DBS
1840 1858 winds = self.__calculateVelUVW(A,velRadial1)
1841
1859
1842 1860 return winds, heiRang1, SNR1
1843
1861
1844 1862 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1845
1863
1846 1864 nPairs = len(pairs_ccf)
1847 1865 posx = numpy.asarray(posx)
1848 1866 posy = numpy.asarray(posy)
1849
1867
1850 1868 #Rotacion Inversa para alinear con el azimuth
1851 1869 if azimuth!= None:
1852 1870 azimuth = azimuth*math.pi/180
1853 1871 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1854 1872 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1855 1873 else:
1856 1874 posx1 = posx
1857 1875 posy1 = posy
1858
1876
1859 1877 #Calculo de Distancias
1860 1878 distx = numpy.zeros(nPairs)
1861 1879 disty = numpy.zeros(nPairs)
1862 1880 dist = numpy.zeros(nPairs)
1863 1881 ang = numpy.zeros(nPairs)
1864
1882
1865 1883 for i in range(nPairs):
1866 1884 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1867 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1885 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1868 1886 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1869 1887 ang[i] = numpy.arctan2(disty[i],distx[i])
1870
1888
1871 1889 return distx, disty, dist, ang
1872 #Calculo de Matrices
1890 #Calculo de Matrices
1873 1891 # nPairs = len(pairs)
1874 1892 # ang1 = numpy.zeros((nPairs, 2, 1))
1875 1893 # dist1 = numpy.zeros((nPairs, 2, 1))
1876 #
1894 #
1877 1895 # for j in range(nPairs):
1878 1896 # dist1[j,0,0] = dist[pairs[j][0]]
1879 1897 # dist1[j,1,0] = dist[pairs[j][1]]
1880 1898 # ang1[j,0,0] = ang[pairs[j][0]]
1881 1899 # ang1[j,1,0] = ang[pairs[j][1]]
1882 #
1900 #
1883 1901 # return distx,disty, dist1,ang1
1884 1902
1885
1903
1886 1904 def __calculateVelVer(self, phase, lagTRange, _lambda):
1887 1905
1888 1906 Ts = lagTRange[1] - lagTRange[0]
1889 1907 velW = -_lambda*phase/(4*math.pi*Ts)
1890
1908
1891 1909 return velW
1892
1910
1893 1911 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1894 1912 nPairs = tau1.shape[0]
1895 1913 nHeights = tau1.shape[1]
1896 vel = numpy.zeros((nPairs,3,nHeights))
1914 vel = numpy.zeros((nPairs,3,nHeights))
1897 1915 dist1 = numpy.reshape(dist, (dist.size,1))
1898
1916
1899 1917 angCos = numpy.cos(ang)
1900 1918 angSin = numpy.sin(ang)
1901
1902 vel0 = dist1*tau1/(2*tau2**2)
1919
1920 vel0 = dist1*tau1/(2*tau2**2)
1903 1921 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1904 1922 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1905
1923
1906 1924 ind = numpy.where(numpy.isinf(vel))
1907 1925 vel[ind] = numpy.nan
1908
1926
1909 1927 return vel
1910
1928
1911 1929 # def __getPairsAutoCorr(self, pairsList, nChannels):
1912 #
1930 #
1913 1931 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1914 #
1915 # for l in range(len(pairsList)):
1932 #
1933 # for l in range(len(pairsList)):
1916 1934 # firstChannel = pairsList[l][0]
1917 1935 # secondChannel = pairsList[l][1]
1918 #
1919 # #Obteniendo pares de Autocorrelacion
1936 #
1937 # #Obteniendo pares de Autocorrelacion
1920 1938 # if firstChannel == secondChannel:
1921 1939 # pairsAutoCorr[firstChannel] = int(l)
1922 #
1940 #
1923 1941 # pairsAutoCorr = pairsAutoCorr.astype(int)
1924 #
1942 #
1925 1943 # pairsCrossCorr = range(len(pairsList))
1926 1944 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1927 #
1945 #
1928 1946 # return pairsAutoCorr, pairsCrossCorr
1929
1947
1930 1948 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1931 1949 def techniqueSA(self, kwargs):
1932
1933 """
1950
1951 """
1934 1952 Function that implements Spaced Antenna (SA) technique.
1935
1953
1936 1954 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1937 1955 Direction correction (if necessary), Ranges and SNR
1938
1956
1939 1957 Output: Winds estimation (Zonal, Meridional and Vertical)
1940
1958
1941 1959 Parameters affected: Winds
1942 1960 """
1943 1961 position_x = kwargs['positionX']
1944 1962 position_y = kwargs['positionY']
1945 1963 azimuth = kwargs['azimuth']
1946
1964
1947 1965 if 'correctFactor' in kwargs:
1948 1966 correctFactor = kwargs['correctFactor']
1949 1967 else:
1950 1968 correctFactor = 1
1951
1969
1952 1970 groupList = kwargs['groupList']
1953 1971 pairs_ccf = groupList[1]
1954 1972 tau = kwargs['tau']
1955 1973 _lambda = kwargs['_lambda']
1956
1974
1957 1975 #Cross Correlation pairs obtained
1958 1976 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1959 1977 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1960 1978 # pairsSelArray = numpy.array(pairsSelected)
1961 1979 # pairs = []
1962 #
1980 #
1963 1981 # #Wind estimation pairs obtained
1964 1982 # for i in range(pairsSelArray.shape[0]/2):
1965 1983 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1966 1984 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1967 1985 # pairs.append((ind1,ind2))
1968
1986
1969 1987 indtau = tau.shape[0]/2
1970 1988 tau1 = tau[:indtau,:]
1971 1989 tau2 = tau[indtau:-1,:]
1972 1990 # tau1 = tau1[pairs,:]
1973 1991 # tau2 = tau2[pairs,:]
1974 1992 phase1 = tau[-1,:]
1975
1993
1976 1994 #---------------------------------------------------------------------
1977 #Metodo Directo
1995 #Metodo Directo
1978 1996 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1979 1997 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1980 1998 winds = stats.nanmean(winds, axis=0)
1981 1999 #---------------------------------------------------------------------
1982 2000 #Metodo General
1983 2001 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1984 2002 # #Calculo Coeficientes de Funcion de Correlacion
1985 2003 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1986 2004 # #Calculo de Velocidades
1987 2005 # winds = self.calculateVelUV(F,G,A,B,H)
1988 2006
1989 2007 #---------------------------------------------------------------------
1990 2008 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1991 2009 winds = correctFactor*winds
1992 2010 return winds
1993
2011
1994 2012 def __checkTime(self, currentTime, paramInterval, outputInterval):
1995
2013
1996 2014 dataTime = currentTime + paramInterval
1997 2015 deltaTime = dataTime - self.__initime
1998
2016
1999 2017 if deltaTime >= outputInterval or deltaTime < 0:
2000 2018 self.__dataReady = True
2001 return
2002
2019 return
2020
2003 2021 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
2004 2022 '''
2005 2023 Function that implements winds estimation technique with detected meteors.
2006
2024
2007 2025 Input: Detected meteors, Minimum meteor quantity to wind estimation
2008
2026
2009 2027 Output: Winds estimation (Zonal and Meridional)
2010
2028
2011 2029 Parameters affected: Winds
2012 '''
2030 '''
2013 2031 #Settings
2014 2032 nInt = (heightMax - heightMin)/2
2015 2033 nInt = int(nInt)
2016 winds = numpy.zeros((2,nInt))*numpy.nan
2017
2034 winds = numpy.zeros((2,nInt))*numpy.nan
2035
2018 2036 #Filter errors
2019 2037 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
2020 2038 finalMeteor = arrayMeteor[error,:]
2021
2039
2022 2040 #Meteor Histogram
2023 2041 finalHeights = finalMeteor[:,2]
2024 2042 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
2025 2043 nMeteorsPerI = hist[0]
2026 2044 heightPerI = hist[1]
2027
2045
2028 2046 #Sort of meteors
2029 2047 indSort = finalHeights.argsort()
2030 2048 finalMeteor2 = finalMeteor[indSort,:]
2031
2049
2032 2050 # Calculating winds
2033 2051 ind1 = 0
2034 ind2 = 0
2035
2052 ind2 = 0
2053
2036 2054 for i in range(nInt):
2037 2055 nMet = nMeteorsPerI[i]
2038 2056 ind1 = ind2
2039 2057 ind2 = ind1 + nMet
2040
2058
2041 2059 meteorAux = finalMeteor2[ind1:ind2,:]
2042
2060
2043 2061 if meteorAux.shape[0] >= meteorThresh:
2044 2062 vel = meteorAux[:, 6]
2045 2063 zen = meteorAux[:, 4]*numpy.pi/180
2046 2064 azim = meteorAux[:, 3]*numpy.pi/180
2047
2065
2048 2066 n = numpy.cos(zen)
2049 2067 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
2050 2068 # l = m*numpy.tan(azim)
2051 2069 l = numpy.sin(zen)*numpy.sin(azim)
2052 2070 m = numpy.sin(zen)*numpy.cos(azim)
2053
2071
2054 2072 A = numpy.vstack((l, m)).transpose()
2055 2073 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
2056 2074 windsAux = numpy.dot(A1, vel)
2057
2075
2058 2076 winds[0,i] = windsAux[0]
2059 2077 winds[1,i] = windsAux[1]
2060
2078
2061 2079 return winds, heightPerI[:-1]
2062
2080
2063 2081 def techniqueNSM_SA(self, **kwargs):
2064 2082 metArray = kwargs['metArray']
2065 2083 heightList = kwargs['heightList']
2066 2084 timeList = kwargs['timeList']
2067
2085
2068 2086 rx_location = kwargs['rx_location']
2069 2087 groupList = kwargs['groupList']
2070 2088 azimuth = kwargs['azimuth']
2071 2089 dfactor = kwargs['dfactor']
2072 2090 k = kwargs['k']
2073
2091
2074 2092 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
2075 2093 d = dist*dfactor
2076 2094 #Phase calculation
2077 2095 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2078
2096
2079 2097 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2080
2098
2081 2099 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2082 2100 azimuth1 = azimuth1*numpy.pi/180
2083
2101
2084 2102 for i in range(heightList.size):
2085 2103 h = heightList[i]
2086 2104 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2087 2105 metHeight = metArray1[indH,:]
2088 2106 if metHeight.shape[0] >= 2:
2089 2107 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2090 2108 iazim = metHeight[:,1].astype(int)
2091 2109 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2092 2110 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2093 2111 A = numpy.asmatrix(A)
2094 2112 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2095 2113 velHor = numpy.dot(A1,velAux)
2096
2114
2097 2115 velEst[i,:] = numpy.squeeze(velHor)
2098 2116 return velEst
2099
2117
2100 2118 def __getPhaseSlope(self, metArray, heightList, timeList):
2101 2119 meteorList = []
2102 2120 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2103 2121 #Putting back together the meteor matrix
2104 2122 utctime = metArray[:,0]
2105 2123 uniqueTime = numpy.unique(utctime)
2106
2124
2107 2125 phaseDerThresh = 0.5
2108 2126 ippSeconds = timeList[1] - timeList[0]
2109 2127 sec = numpy.where(timeList>1)[0][0]
2110 2128 nPairs = metArray.shape[1] - 6
2111 2129 nHeights = len(heightList)
2112
2130
2113 2131 for t in uniqueTime:
2114 2132 metArray1 = metArray[utctime==t,:]
2115 2133 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2116 2134 tmet = metArray1[:,1].astype(int)
2117 2135 hmet = metArray1[:,2].astype(int)
2118
2136
2119 2137 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2120 2138 metPhase[:,:] = numpy.nan
2121 2139 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2122
2140
2123 2141 #Delete short trails
2124 2142 metBool = ~numpy.isnan(metPhase[0,:,:])
2125 2143 heightVect = numpy.sum(metBool, axis = 1)
2126 2144 metBool[heightVect<sec,:] = False
2127 2145 metPhase[:,heightVect<sec,:] = numpy.nan
2128
2146
2129 2147 #Derivative
2130 2148 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2131 2149 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2132 2150 metPhase[phDerAux] = numpy.nan
2133
2151
2134 2152 #--------------------------METEOR DETECTION -----------------------------------------
2135 2153 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2136
2154
2137 2155 for p in numpy.arange(nPairs):
2138 2156 phase = metPhase[p,:,:]
2139 2157 phDer = metDer[p,:,:]
2140
2158
2141 2159 for h in indMet:
2142 2160 height = heightList[h]
2143 2161 phase1 = phase[h,:] #82
2144 2162 phDer1 = phDer[h,:]
2145
2163
2146 2164 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2147
2165
2148 2166 indValid = numpy.where(~numpy.isnan(phase1))[0]
2149 2167 initMet = indValid[0]
2150 2168 endMet = 0
2151
2169
2152 2170 for i in range(len(indValid)-1):
2153
2171
2154 2172 #Time difference
2155 2173 inow = indValid[i]
2156 2174 inext = indValid[i+1]
2157 2175 idiff = inext - inow
2158 2176 #Phase difference
2159 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2160
2177 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2178
2161 2179 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2162 2180 sizeTrail = inow - initMet + 1
2163 2181 if sizeTrail>3*sec: #Too short meteors
2164 2182 x = numpy.arange(initMet,inow+1)*ippSeconds
2165 2183 y = phase1[initMet:inow+1]
2166 2184 ynnan = ~numpy.isnan(y)
2167 2185 x = x[ynnan]
2168 2186 y = y[ynnan]
2169 2187 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2170 2188 ylin = x*slope + intercept
2171 2189 rsq = r_value**2
2172 2190 if rsq > 0.5:
2173 2191 vel = slope#*height*1000/(k*d)
2174 2192 estAux = numpy.array([utctime,p,height, vel, rsq])
2175 2193 meteorList.append(estAux)
2176 initMet = inext
2194 initMet = inext
2177 2195 metArray2 = numpy.array(meteorList)
2178
2196
2179 2197 return metArray2
2180
2198
2181 2199 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2182
2200
2183 2201 azimuth1 = numpy.zeros(len(pairslist))
2184 2202 dist = numpy.zeros(len(pairslist))
2185
2203
2186 2204 for i in range(len(rx_location)):
2187 2205 ch0 = pairslist[i][0]
2188 2206 ch1 = pairslist[i][1]
2189
2207
2190 2208 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2191 2209 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2192 2210 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2193 2211 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2194
2212
2195 2213 azimuth1 -= azimuth0
2196 2214 return azimuth1, dist
2197
2215
2198 2216 def techniqueNSM_DBS(self, **kwargs):
2199 2217 metArray = kwargs['metArray']
2200 2218 heightList = kwargs['heightList']
2201 timeList = kwargs['timeList']
2219 timeList = kwargs['timeList']
2202 2220 azimuth = kwargs['azimuth']
2203 2221 theta_x = numpy.array(kwargs['theta_x'])
2204 2222 theta_y = numpy.array(kwargs['theta_y'])
2205
2223
2206 2224 utctime = metArray[:,0]
2207 2225 cmet = metArray[:,1].astype(int)
2208 2226 hmet = metArray[:,3].astype(int)
2209 2227 SNRmet = metArray[:,4]
2210 2228 vmet = metArray[:,5]
2211 2229 spcmet = metArray[:,6]
2212
2230
2213 2231 nChan = numpy.max(cmet) + 1
2214 2232 nHeights = len(heightList)
2215 2233
2216 2234 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2217 2235 hmet = heightList[hmet]
2218 2236 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2219 2237
2220 2238 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2221 2239
2222 2240 for i in range(nHeights - 1):
2223 2241 hmin = heightList[i]
2224 2242 hmax = heightList[i + 1]
2225 2243
2226 2244 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2227 2245 indthisH = numpy.where(thisH)
2228
2246
2229 2247 if numpy.size(indthisH) > 3:
2230
2248
2231 2249 vel_aux = vmet[thisH]
2232 2250 chan_aux = cmet[thisH]
2233 2251 cosu_aux = dir_cosu[chan_aux]
2234 2252 cosv_aux = dir_cosv[chan_aux]
2235 2253 cosw_aux = dir_cosw[chan_aux]
2236
2237 nch = numpy.size(numpy.unique(chan_aux))
2254
2255 nch = numpy.size(numpy.unique(chan_aux))
2238 2256 if nch > 1:
2239 2257 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2240 2258 velEst[i,:] = numpy.dot(A,vel_aux)
2241
2259
2242 2260 return velEst
2243 2261
2244 2262 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2245 2263
2246 2264 param = dataOut.data_param
2247 2265 if dataOut.abscissaList != None:
2248 2266 absc = dataOut.abscissaList[:-1]
2249 2267 # noise = dataOut.noise
2250 2268 heightList = dataOut.heightList
2251 2269 SNR = dataOut.data_SNR
2252
2270
2253 2271 if technique == 'DBS':
2254
2255 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2272
2273 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2256 2274 kwargs['heightList'] = heightList
2257 2275 kwargs['SNR'] = SNR
2258
2276
2259 2277 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
2260 2278 dataOut.utctimeInit = dataOut.utctime
2261 2279 dataOut.outputInterval = dataOut.paramInterval
2262
2280
2263 2281 elif technique == 'SA':
2264
2282
2265 2283 #Parameters
2266 2284 # position_x = kwargs['positionX']
2267 2285 # position_y = kwargs['positionY']
2268 2286 # azimuth = kwargs['azimuth']
2269 #
2287 #
2270 2288 # if kwargs.has_key('crosspairsList'):
2271 2289 # pairs = kwargs['crosspairsList']
2272 2290 # else:
2273 # pairs = None
2274 #
2291 # pairs = None
2292 #
2275 2293 # if kwargs.has_key('correctFactor'):
2276 2294 # correctFactor = kwargs['correctFactor']
2277 2295 # else:
2278 2296 # correctFactor = 1
2279
2297
2280 2298 # tau = dataOut.data_param
2281 2299 # _lambda = dataOut.C/dataOut.frequency
2282 2300 # pairsList = dataOut.groupList
2283 2301 # nChannels = dataOut.nChannels
2284
2302
2285 2303 kwargs['groupList'] = dataOut.groupList
2286 2304 kwargs['tau'] = dataOut.data_param
2287 2305 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2288 2306 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2289 2307 dataOut.data_output = self.techniqueSA(kwargs)
2290 2308 dataOut.utctimeInit = dataOut.utctime
2291 2309 dataOut.outputInterval = dataOut.timeInterval
2292
2293 elif technique == 'Meteors':
2310
2311 elif technique == 'Meteors':
2294 2312 dataOut.flagNoData = True
2295 2313 self.__dataReady = False
2296
2314
2297 2315 if 'nHours' in kwargs:
2298 2316 nHours = kwargs['nHours']
2299 else:
2317 else:
2300 2318 nHours = 1
2301
2319
2302 2320 if 'meteorsPerBin' in kwargs:
2303 2321 meteorThresh = kwargs['meteorsPerBin']
2304 2322 else:
2305 2323 meteorThresh = 6
2306
2324
2307 2325 if 'hmin' in kwargs:
2308 2326 hmin = kwargs['hmin']
2309 2327 else: hmin = 70
2310 2328 if 'hmax' in kwargs:
2311 2329 hmax = kwargs['hmax']
2312 2330 else: hmax = 110
2313
2331
2314 2332 dataOut.outputInterval = nHours*3600
2315
2333
2316 2334 if self.__isConfig == False:
2317 2335 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2318 2336 #Get Initial LTC time
2319 2337 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2320 2338 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2321 2339
2322 2340 self.__isConfig = True
2323
2341
2324 2342 if self.__buffer is None:
2325 2343 self.__buffer = dataOut.data_param
2326 2344 self.__firstdata = copy.copy(dataOut)
2327 2345
2328 2346 else:
2329 2347 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2330
2348
2331 2349 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2332
2350
2333 2351 if self.__dataReady:
2334 2352 dataOut.utctimeInit = self.__initime
2335
2353
2336 2354 self.__initime += dataOut.outputInterval #to erase time offset
2337
2355
2338 2356 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2339 2357 dataOut.flagNoData = False
2340 2358 self.__buffer = None
2341
2359
2342 2360 elif technique == 'Meteors1':
2343 2361 dataOut.flagNoData = True
2344 2362 self.__dataReady = False
2345
2363
2346 2364 if 'nMins' in kwargs:
2347 2365 nMins = kwargs['nMins']
2348 2366 else: nMins = 20
2349 2367 if 'rx_location' in kwargs:
2350 2368 rx_location = kwargs['rx_location']
2351 2369 else: rx_location = [(0,1),(1,1),(1,0)]
2352 2370 if 'azimuth' in kwargs:
2353 2371 azimuth = kwargs['azimuth']
2354 2372 else: azimuth = 51.06
2355 2373 if 'dfactor' in kwargs:
2356 2374 dfactor = kwargs['dfactor']
2357 2375 if 'mode' in kwargs:
2358 2376 mode = kwargs['mode']
2359 2377 if 'theta_x' in kwargs:
2360 theta_x = kwargs['theta_x']
2378 theta_x = kwargs['theta_x']
2361 2379 if 'theta_y' in kwargs:
2362 2380 theta_y = kwargs['theta_y']
2363 2381 else: mode = 'SA'
2364 2382
2365 2383 #Borrar luego esto
2366 2384 if dataOut.groupList is None:
2367 2385 dataOut.groupList = [(0,1),(0,2),(1,2)]
2368 2386 groupList = dataOut.groupList
2369 2387 C = 3e8
2370 2388 freq = 50e6
2371 2389 lamb = C/freq
2372 2390 k = 2*numpy.pi/lamb
2373
2391
2374 2392 timeList = dataOut.abscissaList
2375 2393 heightList = dataOut.heightList
2376
2394
2377 2395 if self.__isConfig == False:
2378 2396 dataOut.outputInterval = nMins*60
2379 2397 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2380 2398 #Get Initial LTC time
2381 2399 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2382 2400 minuteAux = initime.minute
2383 2401 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2384 2402 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2385 2403
2386 2404 self.__isConfig = True
2387
2405
2388 2406 if self.__buffer is None:
2389 2407 self.__buffer = dataOut.data_param
2390 2408 self.__firstdata = copy.copy(dataOut)
2391 2409
2392 2410 else:
2393 2411 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2394
2412
2395 2413 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2396
2414
2397 2415 if self.__dataReady:
2398 2416 dataOut.utctimeInit = self.__initime
2399 2417 self.__initime += dataOut.outputInterval #to erase time offset
2400
2418
2401 2419 metArray = self.__buffer
2402 2420 if mode == 'SA':
2403 2421 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2404 2422 elif mode == 'DBS':
2405 2423 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2406 2424 dataOut.data_output = dataOut.data_output.T
2407 2425 dataOut.flagNoData = False
2408 2426 self.__buffer = None
2409 2427
2410 2428 return
2411
2429
2412 2430 class EWDriftsEstimation(Operation):
2413
2414 def __init__(self):
2415 Operation.__init__(self)
2416
2431
2432 def __init__(self):
2433 Operation.__init__(self)
2434
2417 2435 def __correctValues(self, heiRang, phi, velRadial, SNR):
2418 2436 listPhi = phi.tolist()
2419 2437 maxid = listPhi.index(max(listPhi))
2420 2438 minid = listPhi.index(min(listPhi))
2421
2422 rango = list(range(len(phi)))
2439
2440 rango = list(range(len(phi)))
2423 2441 # rango = numpy.delete(rango,maxid)
2424
2442
2425 2443 heiRang1 = heiRang*math.cos(phi[maxid])
2426 2444 heiRangAux = heiRang*math.cos(phi[minid])
2427 2445 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2428 2446 heiRang1 = numpy.delete(heiRang1,indOut)
2429
2447
2430 2448 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2431 2449 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2432
2450
2433 2451 for i in rango:
2434 2452 x = heiRang*math.cos(phi[i])
2435 2453 y1 = velRadial[i,:]
2436 2454 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2437
2455
2438 2456 x1 = heiRang1
2439 2457 y11 = f1(x1)
2440
2458
2441 2459 y2 = SNR[i,:]
2442 2460 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2443 2461 y21 = f2(x1)
2444
2462
2445 2463 velRadial1[i,:] = y11
2446 2464 SNR1[i,:] = y21
2447
2465
2448 2466 return heiRang1, velRadial1, SNR1
2449 2467
2450 2468 def run(self, dataOut, zenith, zenithCorrection):
2451 2469 heiRang = dataOut.heightList
2452 2470 velRadial = dataOut.data_param[:,3,:]
2453 2471 SNR = dataOut.data_SNR
2454
2472
2455 2473 zenith = numpy.array(zenith)
2456 zenith -= zenithCorrection
2474 zenith -= zenithCorrection
2457 2475 zenith *= numpy.pi/180
2458
2476
2459 2477 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2460
2478
2461 2479 alp = zenith[0]
2462 2480 bet = zenith[1]
2463
2481
2464 2482 w_w = velRadial1[0,:]
2465 2483 w_e = velRadial1[1,:]
2466
2467 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2468 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2469
2484
2485 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2486 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2487
2470 2488 winds = numpy.vstack((u,w))
2471
2489
2472 2490 dataOut.heightList = heiRang1
2473 2491 dataOut.data_output = winds
2474 2492 dataOut.data_SNR = SNR1
2475
2493
2476 2494 dataOut.utctimeInit = dataOut.utctime
2477 2495 dataOut.outputInterval = dataOut.timeInterval
2478 2496 return
2479 2497
2480 2498 #--------------- Non Specular Meteor ----------------
2481 2499
2482 2500 class NonSpecularMeteorDetection(Operation):
2483 2501
2484 2502 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2485 2503 data_acf = dataOut.data_pre[0]
2486 2504 data_ccf = dataOut.data_pre[1]
2487 2505 pairsList = dataOut.groupList[1]
2488
2506
2489 2507 lamb = dataOut.C/dataOut.frequency
2490 2508 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2491 2509 paramInterval = dataOut.paramInterval
2492
2510
2493 2511 nChannels = data_acf.shape[0]
2494 2512 nLags = data_acf.shape[1]
2495 2513 nProfiles = data_acf.shape[2]
2496 2514 nHeights = dataOut.nHeights
2497 2515 nCohInt = dataOut.nCohInt
2498 2516 sec = numpy.round(nProfiles/dataOut.paramInterval)
2499 2517 heightList = dataOut.heightList
2500 2518 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2501 2519 utctime = dataOut.utctime
2502
2520
2503 2521 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2504 2522
2505 2523 #------------------------ SNR --------------------------------------
2506 2524 power = data_acf[:,0,:,:].real
2507 2525 noise = numpy.zeros(nChannels)
2508 2526 SNR = numpy.zeros(power.shape)
2509 2527 for i in range(nChannels):
2510 2528 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2511 2529 SNR[i] = (power[i]-noise[i])/noise[i]
2512 2530 SNRm = numpy.nanmean(SNR, axis = 0)
2513 2531 SNRdB = 10*numpy.log10(SNR)
2514
2532
2515 2533 if mode == 'SA':
2516 2534 dataOut.groupList = dataOut.groupList[1]
2517 2535 nPairs = data_ccf.shape[0]
2518 2536 #---------------------- Coherence and Phase --------------------------
2519 2537 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2520 2538 # phase1 = numpy.copy(phase)
2521 2539 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2522
2540
2523 2541 for p in range(nPairs):
2524 2542 ch0 = pairsList[p][0]
2525 2543 ch1 = pairsList[p][1]
2526 2544 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2527 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2528 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2529 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2530 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2545 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2546 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2547 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2548 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2531 2549 coh = numpy.nanmax(coh1, axis = 0)
2532 2550 # struc = numpy.ones((5,1))
2533 2551 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2534 2552 #---------------------- Radial Velocity ----------------------------
2535 2553 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2536 2554 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2537
2555
2538 2556 if allData:
2539 2557 boolMetFin = ~numpy.isnan(SNRm)
2540 2558 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2541 2559 else:
2542 2560 #------------------------ Meteor mask ---------------------------------
2543 2561 # #SNR mask
2544 2562 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2545 #
2563 #
2546 2564 # #Erase small objects
2547 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2548 #
2565 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2566 #
2549 2567 # auxEEJ = numpy.sum(boolMet1,axis=0)
2550 2568 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2551 2569 # indEEJ = numpy.where(indOver)[0]
2552 2570 # indNEEJ = numpy.where(~indOver)[0]
2553 #
2571 #
2554 2572 # boolMetFin = boolMet1
2555 #
2573 #
2556 2574 # if indEEJ.size > 0:
2557 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2558 #
2575 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2576 #
2559 2577 # boolMet2 = coh > cohThresh
2560 2578 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2561 #
2579 #
2562 2580 # #Final Meteor mask
2563 2581 # boolMetFin = boolMet1|boolMet2
2564
2582
2565 2583 #Coherence mask
2566 2584 boolMet1 = coh > 0.75
2567 2585 struc = numpy.ones((30,1))
2568 2586 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2569
2587
2570 2588 #Derivative mask
2571 2589 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2572 2590 boolMet2 = derPhase < 0.2
2573 2591 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2574 2592 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2575 2593 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2576 2594 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2577 2595 # #Final mask
2578 2596 # boolMetFin = boolMet2
2579 2597 boolMetFin = boolMet1&boolMet2
2580 2598 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2581 2599 #Creating data_param
2582 2600 coordMet = numpy.where(boolMetFin)
2583 2601
2584 2602 tmet = coordMet[0]
2585 2603 hmet = coordMet[1]
2586
2604
2587 2605 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2588 2606 data_param[:,0] = utctime
2589 2607 data_param[:,1] = tmet
2590 2608 data_param[:,2] = hmet
2591 2609 data_param[:,3] = SNRm[tmet,hmet]
2592 2610 data_param[:,4] = velRad[tmet,hmet]
2593 2611 data_param[:,5] = coh[tmet,hmet]
2594 2612 data_param[:,6:] = phase[:,tmet,hmet].T
2595
2613
2596 2614 elif mode == 'DBS':
2597 2615 dataOut.groupList = numpy.arange(nChannels)
2598 2616
2599 2617 #Radial Velocities
2600 2618 phase = numpy.angle(data_acf[:,1,:,:])
2601 2619 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2602 2620 velRad = phase*lamb/(4*numpy.pi*tSamp)
2603
2621
2604 2622 #Spectral width
2605 2623 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2606 2624 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2607 2625 acf1 = data_acf[:,1,:,:]
2608 2626 acf2 = data_acf[:,2,:,:]
2609 2627
2610 2628 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2611 2629 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2612 2630 if allData:
2613 2631 boolMetFin = ~numpy.isnan(SNRdB)
2614 2632 else:
2615 2633 #SNR
2616 2634 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2617 2635 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2618
2636
2619 2637 #Radial velocity
2620 2638 boolMet2 = numpy.abs(velRad) < 20
2621 2639 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2622
2640
2623 2641 #Spectral Width
2624 2642 boolMet3 = spcWidth < 30
2625 2643 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2626 2644 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2627 2645 boolMetFin = boolMet1&boolMet2&boolMet3
2628
2646
2629 2647 #Creating data_param
2630 2648 coordMet = numpy.where(boolMetFin)
2631 2649
2632 2650 cmet = coordMet[0]
2633 2651 tmet = coordMet[1]
2634 2652 hmet = coordMet[2]
2635
2653
2636 2654 data_param = numpy.zeros((tmet.size, 7))
2637 2655 data_param[:,0] = utctime
2638 2656 data_param[:,1] = cmet
2639 2657 data_param[:,2] = tmet
2640 2658 data_param[:,3] = hmet
2641 2659 data_param[:,4] = SNR[cmet,tmet,hmet].T
2642 2660 data_param[:,5] = velRad[cmet,tmet,hmet].T
2643 2661 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2644
2662
2645 2663 # self.dataOut.data_param = data_int
2646 2664 if len(data_param) == 0:
2647 2665 dataOut.flagNoData = True
2648 2666 else:
2649 2667 dataOut.data_param = data_param
2650 2668
2651 2669 def __erase_small(self, binArray, threshX, threshY):
2652 2670 labarray, numfeat = ndimage.measurements.label(binArray)
2653 2671 binArray1 = numpy.copy(binArray)
2654
2672
2655 2673 for i in range(1,numfeat + 1):
2656 2674 auxBin = (labarray==i)
2657 2675 auxSize = auxBin.sum()
2658
2676
2659 2677 x,y = numpy.where(auxBin)
2660 2678 widthX = x.max() - x.min()
2661 2679 widthY = y.max() - y.min()
2662
2680
2663 2681 #width X: 3 seg -> 12.5*3
2664 #width Y:
2665
2682 #width Y:
2683
2666 2684 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2667 2685 binArray1[auxBin] = False
2668
2686
2669 2687 return binArray1
2670 2688
2671 2689 #--------------- Specular Meteor ----------------
2672 2690
2673 2691 class SMDetection(Operation):
2674 2692 '''
2675 2693 Function DetectMeteors()
2676 2694 Project developed with paper:
2677 2695 HOLDSWORTH ET AL. 2004
2678
2696
2679 2697 Input:
2680 2698 self.dataOut.data_pre
2681
2699
2682 2700 centerReceiverIndex: From the channels, which is the center receiver
2683
2701
2684 2702 hei_ref: Height reference for the Beacon signal extraction
2685 2703 tauindex:
2686 2704 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2687
2705
2688 2706 cohDetection: Whether to user Coherent detection or not
2689 2707 cohDet_timeStep: Coherent Detection calculation time step
2690 2708 cohDet_thresh: Coherent Detection phase threshold to correct phases
2691
2709
2692 2710 noise_timeStep: Noise calculation time step
2693 2711 noise_multiple: Noise multiple to define signal threshold
2694
2712
2695 2713 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2696 2714 multDet_rangeLimit: Multiple Detection Removal range limit in km
2697
2715
2698 2716 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2699 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2700
2717 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2718
2701 2719 hmin: Minimum Height of the meteor to use it in the further wind estimations
2702 2720 hmax: Maximum Height of the meteor to use it in the further wind estimations
2703 2721 azimuth: Azimuth angle correction
2704
2722
2705 2723 Affected:
2706 2724 self.dataOut.data_param
2707
2725
2708 2726 Rejection Criteria (Errors):
2709 2727 0: No error; analysis OK
2710 2728 1: SNR < SNR threshold
2711 2729 2: angle of arrival (AOA) ambiguously determined
2712 2730 3: AOA estimate not feasible
2713 2731 4: Large difference in AOAs obtained from different antenna baselines
2714 2732 5: echo at start or end of time series
2715 2733 6: echo less than 5 examples long; too short for analysis
2716 2734 7: echo rise exceeds 0.3s
2717 2735 8: echo decay time less than twice rise time
2718 2736 9: large power level before echo
2719 2737 10: large power level after echo
2720 2738 11: poor fit to amplitude for estimation of decay time
2721 2739 12: poor fit to CCF phase variation for estimation of radial drift velocity
2722 2740 13: height unresolvable echo: not valid height within 70 to 110 km
2723 2741 14: height ambiguous echo: more then one possible height within 70 to 110 km
2724 2742 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2725 2743 16: oscilatory echo, indicating event most likely not an underdense echo
2726
2744
2727 2745 17: phase difference in meteor Reestimation
2728
2746
2729 2747 Data Storage:
2730 2748 Meteors for Wind Estimation (8):
2731 2749 Utc Time | Range Height
2732 2750 Azimuth Zenith errorCosDir
2733 2751 VelRad errorVelRad
2734 2752 Phase0 Phase1 Phase2 Phase3
2735 2753 TypeError
2736
2737 '''
2738
2754
2755 '''
2756
2739 2757 def run(self, dataOut, hei_ref = None, tauindex = 0,
2740 2758 phaseOffsets = None,
2741 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2759 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2742 2760 noise_timeStep = 4, noise_multiple = 4,
2743 2761 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2744 2762 phaseThresh = 20, SNRThresh = 5,
2745 2763 hmin = 50, hmax=150, azimuth = 0,
2746 2764 channelPositions = None) :
2747
2748
2765
2766
2749 2767 #Getting Pairslist
2750 2768 if channelPositions is None:
2751 2769 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2752 2770 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2753 2771 meteorOps = SMOperations()
2754 2772 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2755 2773 heiRang = dataOut.getHeiRange()
2756 2774 #Get Beacon signal - No Beacon signal anymore
2757 2775 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2758 #
2776 #
2759 2777 # if hei_ref != None:
2760 2778 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2761 #
2762
2763
2779 #
2780
2781
2764 2782 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2765 2783 # see if the user put in pre defined phase shifts
2766 2784 voltsPShift = dataOut.data_pre.copy()
2767
2785
2768 2786 # if predefinedPhaseShifts != None:
2769 2787 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2770 #
2788 #
2771 2789 # # elif beaconPhaseShifts:
2772 2790 # # #get hardware phase shifts using beacon signal
2773 2791 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2774 2792 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2775 #
2793 #
2776 2794 # else:
2777 # hardwarePhaseShifts = numpy.zeros(5)
2778 #
2795 # hardwarePhaseShifts = numpy.zeros(5)
2796 #
2779 2797 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2780 2798 # for i in range(self.dataOut.data_pre.shape[0]):
2781 2799 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2782 2800
2783 2801 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2784
2802
2785 2803 #Remove DC
2786 2804 voltsDC = numpy.mean(voltsPShift,1)
2787 2805 voltsDC = numpy.mean(voltsDC,1)
2788 2806 for i in range(voltsDC.shape[0]):
2789 2807 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2790
2791 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2808
2809 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2792 2810 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2793
2811
2794 2812 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2795 2813 #Coherent Detection
2796 2814 if cohDetection:
2797 2815 #use coherent detection to get the net power
2798 2816 cohDet_thresh = cohDet_thresh*numpy.pi/180
2799 2817 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2800
2818
2801 2819 #Non-coherent detection!
2802 2820 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2803 2821 #********** END OF COH/NON-COH POWER CALCULATION**********************
2804
2822
2805 2823 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2806 2824 #Get noise
2807 2825 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2808 2826 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2809 2827 #Get signal threshold
2810 2828 signalThresh = noise_multiple*noise
2811 2829 #Meteor echoes detection
2812 2830 listMeteors = self.__findMeteors(powerNet, signalThresh)
2813 2831 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2814
2832
2815 2833 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2816 2834 #Parameters
2817 2835 heiRange = dataOut.getHeiRange()
2818 2836 rangeInterval = heiRange[1] - heiRange[0]
2819 2837 rangeLimit = multDet_rangeLimit/rangeInterval
2820 2838 timeLimit = multDet_timeLimit/dataOut.timeInterval
2821 2839 #Multiple detection removals
2822 2840 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2823 2841 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2824
2842
2825 2843 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2826 2844 #Parameters
2827 2845 phaseThresh = phaseThresh*numpy.pi/180
2828 2846 thresh = [phaseThresh, noise_multiple, SNRThresh]
2829 2847 #Meteor reestimation (Errors N 1, 6, 12, 17)
2830 2848 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2831 2849 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2832 2850 #Estimation of decay times (Errors N 7, 8, 11)
2833 2851 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2834 2852 #******************* END OF METEOR REESTIMATION *******************
2835
2853
2836 2854 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2837 2855 #Calculating Radial Velocity (Error N 15)
2838 2856 radialStdThresh = 10
2839 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2857 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2840 2858
2841 2859 if len(listMeteors4) > 0:
2842 2860 #Setting New Array
2843 2861 date = dataOut.utctime
2844 2862 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2845
2863
2846 2864 #Correcting phase offset
2847 2865 if phaseOffsets != None:
2848 2866 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2849 2867 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2850
2868
2851 2869 #Second Pairslist
2852 2870 pairsList = []
2853 2871 pairx = (0,1)
2854 2872 pairy = (2,3)
2855 2873 pairsList.append(pairx)
2856 2874 pairsList.append(pairy)
2857
2875
2858 2876 jph = numpy.array([0,0,0,0])
2859 2877 h = (hmin,hmax)
2860 2878 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2861
2879
2862 2880 # #Calculate AOA (Error N 3, 4)
2863 2881 # #JONES ET AL. 1998
2864 2882 # error = arrayParameters[:,-1]
2865 2883 # AOAthresh = numpy.pi/8
2866 2884 # phases = -arrayParameters[:,9:13]
2867 2885 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2868 #
2886 #
2869 2887 # #Calculate Heights (Error N 13 and 14)
2870 2888 # error = arrayParameters[:,-1]
2871 2889 # Ranges = arrayParameters[:,2]
2872 2890 # zenith = arrayParameters[:,5]
2873 2891 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2874 2892 # error = arrayParameters[:,-1]
2875 2893 #********************* END OF PARAMETERS CALCULATION **************************
2876
2877 #***************************+ PASS DATA TO NEXT STEP **********************
2894
2895 #***************************+ PASS DATA TO NEXT STEP **********************
2878 2896 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2879 2897 dataOut.data_param = arrayParameters
2880
2898
2881 2899 if arrayParameters is None:
2882 2900 dataOut.flagNoData = True
2883 2901 else:
2884 2902 dataOut.flagNoData = True
2885
2903
2886 2904 return
2887
2905
2888 2906 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2889
2907
2890 2908 minIndex = min(newheis[0])
2891 2909 maxIndex = max(newheis[0])
2892
2910
2893 2911 voltage = voltage0[:,:,minIndex:maxIndex+1]
2894 2912 nLength = voltage.shape[1]/n
2895 2913 nMin = 0
2896 2914 nMax = 0
2897 2915 phaseOffset = numpy.zeros((len(pairslist),n))
2898
2916
2899 2917 for i in range(n):
2900 2918 nMax += nLength
2901 2919 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2902 2920 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2903 phaseOffset[:,i] = phaseCCF.transpose()
2921 phaseOffset[:,i] = phaseCCF.transpose()
2904 2922 nMin = nMax
2905 2923 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2906
2924
2907 2925 #Remove Outliers
2908 2926 factor = 2
2909 2927 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2910 2928 dw = numpy.std(wt,axis = 1)
2911 2929 dw = dw.reshape((dw.size,1))
2912 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2930 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2913 2931 phaseOffset[ind] = numpy.nan
2914 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2915
2932 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2933
2916 2934 return phaseOffset
2917
2935
2918 2936 def __shiftPhase(self, data, phaseShift):
2919 2937 #this will shift the phase of a complex number
2920 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2938 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2921 2939 return dataShifted
2922
2940
2923 2941 def __estimatePhaseDifference(self, array, pairslist):
2924 2942 nChannel = array.shape[0]
2925 2943 nHeights = array.shape[2]
2926 2944 numPairs = len(pairslist)
2927 2945 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2928 2946 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2929
2947
2930 2948 #Correct phases
2931 2949 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2932 2950 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2933
2934 if indDer[0].shape[0] > 0:
2951
2952 if indDer[0].shape[0] > 0:
2935 2953 for i in range(indDer[0].shape[0]):
2936 2954 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2937 2955 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2938
2956
2939 2957 # for j in range(numSides):
2940 2958 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2941 2959 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2942 #
2960 #
2943 2961 #Linear
2944 2962 phaseInt = numpy.zeros((numPairs,1))
2945 2963 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2946 2964 for j in range(numPairs):
2947 2965 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2948 2966 phaseInt[j] = fit[1]
2949 2967 #Phase Differences
2950 2968 phaseDiff = phaseInt - phaseCCF[:,2,:]
2951 2969 phaseArrival = phaseInt.reshape(phaseInt.size)
2952
2970
2953 2971 #Dealias
2954 2972 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2955 2973 # indAlias = numpy.where(phaseArrival > numpy.pi)
2956 2974 # phaseArrival[indAlias] -= 2*numpy.pi
2957 2975 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2958 2976 # phaseArrival[indAlias] += 2*numpy.pi
2959
2977
2960 2978 return phaseDiff, phaseArrival
2961
2979
2962 2980 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2963 2981 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2964 2982 #find the phase shifts of each channel over 1 second intervals
2965 2983 #only look at ranges below the beacon signal
2966 2984 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2967 2985 numBlocks = int(volts.shape[1]/numProfPerBlock)
2968 2986 numHeights = volts.shape[2]
2969 2987 nChannel = volts.shape[0]
2970 2988 voltsCohDet = volts.copy()
2971
2989
2972 2990 pairsarray = numpy.array(pairslist)
2973 2991 indSides = pairsarray[:,1]
2974 2992 # indSides = numpy.array(range(nChannel))
2975 2993 # indSides = numpy.delete(indSides, indCenter)
2976 #
2994 #
2977 2995 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2978 2996 listBlocks = numpy.array_split(volts, numBlocks, 1)
2979
2997
2980 2998 startInd = 0
2981 2999 endInd = 0
2982
3000
2983 3001 for i in range(numBlocks):
2984 3002 startInd = endInd
2985 endInd = endInd + listBlocks[i].shape[1]
2986
3003 endInd = endInd + listBlocks[i].shape[1]
3004
2987 3005 arrayBlock = listBlocks[i]
2988 3006 # arrayBlockCenter = listCenter[i]
2989
3007
2990 3008 #Estimate the Phase Difference
2991 3009 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2992 3010 #Phase Difference RMS
2993 3011 arrayPhaseRMS = numpy.abs(phaseDiff)
2994 3012 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2995 3013 indPhase = numpy.where(phaseRMSaux==4)
2996 3014 #Shifting
2997 3015 if indPhase[0].shape[0] > 0:
2998 3016 for j in range(indSides.size):
2999 3017 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
3000 3018 voltsCohDet[:,startInd:endInd,:] = arrayBlock
3001
3019
3002 3020 return voltsCohDet
3003
3021
3004 3022 def __calculateCCF(self, volts, pairslist ,laglist):
3005
3023
3006 3024 nHeights = volts.shape[2]
3007 nPoints = volts.shape[1]
3025 nPoints = volts.shape[1]
3008 3026 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
3009
3027
3010 3028 for i in range(len(pairslist)):
3011 3029 volts1 = volts[pairslist[i][0]]
3012 volts2 = volts[pairslist[i][1]]
3013
3030 volts2 = volts[pairslist[i][1]]
3031
3014 3032 for t in range(len(laglist)):
3015 idxT = laglist[t]
3033 idxT = laglist[t]
3016 3034 if idxT >= 0:
3017 3035 vStacked = numpy.vstack((volts2[idxT:,:],
3018 3036 numpy.zeros((idxT, nHeights),dtype='complex')))
3019 3037 else:
3020 3038 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
3021 3039 volts2[:(nPoints + idxT),:]))
3022 3040 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
3023
3041
3024 3042 vStacked = None
3025 3043 return voltsCCF
3026
3044
3027 3045 def __getNoise(self, power, timeSegment, timeInterval):
3028 3046 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
3029 3047 numBlocks = int(power.shape[0]/numProfPerBlock)
3030 3048 numHeights = power.shape[1]
3031 3049
3032 3050 listPower = numpy.array_split(power, numBlocks, 0)
3033 3051 noise = numpy.zeros((power.shape[0], power.shape[1]))
3034 3052 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
3035
3053
3036 3054 startInd = 0
3037 3055 endInd = 0
3038
3056
3039 3057 for i in range(numBlocks): #split por canal
3040 3058 startInd = endInd
3041 endInd = endInd + listPower[i].shape[0]
3042
3059 endInd = endInd + listPower[i].shape[0]
3060
3043 3061 arrayBlock = listPower[i]
3044 3062 noiseAux = numpy.mean(arrayBlock, 0)
3045 3063 # noiseAux = numpy.median(noiseAux)
3046 3064 # noiseAux = numpy.mean(arrayBlock)
3047 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
3048
3065 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
3066
3049 3067 noiseAux1 = numpy.mean(arrayBlock)
3050 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
3051
3068 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
3069
3052 3070 return noise, noise1
3053
3071
3054 3072 def __findMeteors(self, power, thresh):
3055 3073 nProf = power.shape[0]
3056 3074 nHeights = power.shape[1]
3057 3075 listMeteors = []
3058
3076
3059 3077 for i in range(nHeights):
3060 3078 powerAux = power[:,i]
3061 3079 threshAux = thresh[:,i]
3062
3080
3063 3081 indUPthresh = numpy.where(powerAux > threshAux)[0]
3064 3082 indDNthresh = numpy.where(powerAux <= threshAux)[0]
3065
3083
3066 3084 j = 0
3067
3085
3068 3086 while (j < indUPthresh.size - 2):
3069 3087 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
3070 3088 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
3071 3089 indDNthresh = indDNthresh[indDNAux]
3072
3090
3073 3091 if (indDNthresh.size > 0):
3074 3092 indEnd = indDNthresh[0] - 1
3075 3093 indInit = indUPthresh[j]
3076
3094
3077 3095 meteor = powerAux[indInit:indEnd + 1]
3078 3096 indPeak = meteor.argmax() + indInit
3079 3097 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3080
3098
3081 3099 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3082 3100 j = numpy.where(indUPthresh == indEnd)[0] + 1
3083 3101 else: j+=1
3084 3102 else: j+=1
3085
3103
3086 3104 return listMeteors
3087
3105
3088 3106 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3089
3090 arrayMeteors = numpy.asarray(listMeteors)
3107
3108 arrayMeteors = numpy.asarray(listMeteors)
3091 3109 listMeteors1 = []
3092
3110
3093 3111 while arrayMeteors.shape[0] > 0:
3094 3112 FLAs = arrayMeteors[:,4]
3095 3113 maxFLA = FLAs.argmax()
3096 3114 listMeteors1.append(arrayMeteors[maxFLA,:])
3097
3115
3098 3116 MeteorInitTime = arrayMeteors[maxFLA,1]
3099 3117 MeteorEndTime = arrayMeteors[maxFLA,3]
3100 3118 MeteorHeight = arrayMeteors[maxFLA,0]
3101
3119
3102 3120 #Check neighborhood
3103 3121 maxHeightIndex = MeteorHeight + rangeLimit
3104 3122 minHeightIndex = MeteorHeight - rangeLimit
3105 3123 minTimeIndex = MeteorInitTime - timeLimit
3106 3124 maxTimeIndex = MeteorEndTime + timeLimit
3107
3125
3108 3126 #Check Heights
3109 3127 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3110 3128 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3111 3129 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3112
3130
3113 3131 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3114
3132
3115 3133 return listMeteors1
3116
3134
3117 3135 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3118 3136 numHeights = volts.shape[2]
3119 3137 nChannel = volts.shape[0]
3120
3138
3121 3139 thresholdPhase = thresh[0]
3122 3140 thresholdNoise = thresh[1]
3123 3141 thresholdDB = float(thresh[2])
3124
3142
3125 3143 thresholdDB1 = 10**(thresholdDB/10)
3126 3144 pairsarray = numpy.array(pairslist)
3127 3145 indSides = pairsarray[:,1]
3128
3146
3129 3147 pairslist1 = list(pairslist)
3130 3148 pairslist1.append((0,1))
3131 3149 pairslist1.append((3,4))
3132 3150
3133 3151 listMeteors1 = []
3134 3152 listPowerSeries = []
3135 3153 listVoltageSeries = []
3136 3154 #volts has the war data
3137
3155
3138 3156 if frequency == 30e6:
3139 3157 timeLag = 45*10**-3
3140 3158 else:
3141 3159 timeLag = 15*10**-3
3142 3160 lag = numpy.ceil(timeLag/timeInterval)
3143
3161
3144 3162 for i in range(len(listMeteors)):
3145
3163
3146 3164 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3147 3165 meteorAux = numpy.zeros(16)
3148
3166
3149 3167 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3150 3168 mHeight = listMeteors[i][0]
3151 3169 mStart = listMeteors[i][1]
3152 3170 mPeak = listMeteors[i][2]
3153 3171 mEnd = listMeteors[i][3]
3154
3172
3155 3173 #get the volt data between the start and end times of the meteor
3156 3174 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3157 3175 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3158
3176
3159 3177 #3.6. Phase Difference estimation
3160 3178 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3161
3179
3162 3180 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3163 3181 #meteorVolts0.- all Channels, all Profiles
3164 3182 meteorVolts0 = volts[:,:,mHeight]
3165 3183 meteorThresh = noise[:,mHeight]*thresholdNoise
3166 3184 meteorNoise = noise[:,mHeight]
3167 3185 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3168 3186 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3169
3187
3170 3188 #Times reestimation
3171 3189 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3172 3190 if mStart1.size > 0:
3173 3191 mStart1 = mStart1[-1] + 1
3174
3175 else:
3192
3193 else:
3176 3194 mStart1 = mPeak
3177
3195
3178 3196 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3179 3197 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3180 3198 if mEndDecayTime1.size == 0:
3181 3199 mEndDecayTime1 = powerNet0.size
3182 3200 else:
3183 3201 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3184 3202 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3185
3203
3186 3204 #meteorVolts1.- all Channels, from start to end
3187 3205 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3188 3206 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3189 3207 if meteorVolts2.shape[1] == 0:
3190 3208 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3191 3209 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3192 3210 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3193 3211 ##################### END PARAMETERS REESTIMATION #########################
3194
3212
3195 3213 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3196 3214 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3197 if meteorVolts2.shape[1] > 0:
3215 if meteorVolts2.shape[1] > 0:
3198 3216 #Phase Difference re-estimation
3199 3217 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3200 3218 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3201 3219 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3202 3220 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3203 3221 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3204
3222
3205 3223 #Phase Difference RMS
3206 3224 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3207 3225 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3208 3226 #Data from Meteor
3209 3227 mPeak1 = powerNet1.argmax() + mStart1
3210 3228 mPeakPower1 = powerNet1.max()
3211 3229 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3212 3230 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3213 3231 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3214 3232 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3215 3233 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3216 3234 #Vectorize
3217 3235 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3218 3236 meteorAux[7:11] = phaseDiffint[0:4]
3219
3237
3220 3238 #Rejection Criterions
3221 3239 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3222 3240 meteorAux[-1] = 17
3223 3241 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3224 3242 meteorAux[-1] = 1
3225
3226
3227 else:
3243
3244
3245 else:
3228 3246 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3229 3247 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3230 3248 PowerSeries = 0
3231
3249
3232 3250 listMeteors1.append(meteorAux)
3233 3251 listPowerSeries.append(PowerSeries)
3234 3252 listVoltageSeries.append(meteorVolts1)
3235
3236 return listMeteors1, listPowerSeries, listVoltageSeries
3237
3253
3254 return listMeteors1, listPowerSeries, listVoltageSeries
3255
3238 3256 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3239
3257
3240 3258 threshError = 10
3241 3259 #Depending if it is 30 or 50 MHz
3242 3260 if frequency == 30e6:
3243 3261 timeLag = 45*10**-3
3244 3262 else:
3245 3263 timeLag = 15*10**-3
3246 3264 lag = numpy.ceil(timeLag/timeInterval)
3247
3265
3248 3266 listMeteors1 = []
3249
3267
3250 3268 for i in range(len(listMeteors)):
3251 3269 meteorPower = listPower[i]
3252 3270 meteorAux = listMeteors[i]
3253
3271
3254 3272 if meteorAux[-1] == 0:
3255 3273
3256 try:
3274 try:
3257 3275 indmax = meteorPower.argmax()
3258 3276 indlag = indmax + lag
3259
3277
3260 3278 y = meteorPower[indlag:]
3261 3279 x = numpy.arange(0, y.size)*timeLag
3262
3280
3263 3281 #first guess
3264 3282 a = y[0]
3265 3283 tau = timeLag
3266 3284 #exponential fit
3267 3285 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3268 3286 y1 = self.__exponential_function(x, *popt)
3269 3287 #error estimation
3270 3288 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3271
3289
3272 3290 decayTime = popt[1]
3273 3291 riseTime = indmax*timeInterval
3274 3292 meteorAux[11:13] = [decayTime, error]
3275
3293
3276 3294 #Table items 7, 8 and 11
3277 3295 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3278 meteorAux[-1] = 7
3296 meteorAux[-1] = 7
3279 3297 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3280 3298 meteorAux[-1] = 8
3281 3299 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3282 meteorAux[-1] = 11
3283
3284
3300 meteorAux[-1] = 11
3301
3302
3285 3303 except:
3286 meteorAux[-1] = 11
3287
3288
3304 meteorAux[-1] = 11
3305
3306
3289 3307 listMeteors1.append(meteorAux)
3290
3308
3291 3309 return listMeteors1
3292 3310
3293 3311 #Exponential Function
3294 3312
3295 3313 def __exponential_function(self, x, a, tau):
3296 3314 y = a*numpy.exp(-x/tau)
3297 3315 return y
3298
3316
3299 3317 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3300
3318
3301 3319 pairslist1 = list(pairslist)
3302 3320 pairslist1.append((0,1))
3303 3321 pairslist1.append((3,4))
3304 3322 numPairs = len(pairslist1)
3305 3323 #Time Lag
3306 3324 timeLag = 45*10**-3
3307 3325 c = 3e8
3308 3326 lag = numpy.ceil(timeLag/timeInterval)
3309 3327 freq = 30e6
3310
3328
3311 3329 listMeteors1 = []
3312
3330
3313 3331 for i in range(len(listMeteors)):
3314 3332 meteorAux = listMeteors[i]
3315 3333 if meteorAux[-1] == 0:
3316 3334 mStart = listMeteors[i][1]
3317 mPeak = listMeteors[i][2]
3335 mPeak = listMeteors[i][2]
3318 3336 mLag = mPeak - mStart + lag
3319
3337
3320 3338 #get the volt data between the start and end times of the meteor
3321 3339 meteorVolts = listVolts[i]
3322 3340 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3323 3341
3324 3342 #Get CCF
3325 3343 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3326
3344
3327 3345 #Method 2
3328 3346 slopes = numpy.zeros(numPairs)
3329 3347 time = numpy.array([-2,-1,1,2])*timeInterval
3330 3348 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3331
3349
3332 3350 #Correct phases
3333 3351 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3334 3352 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3335
3336 if indDer[0].shape[0] > 0:
3353
3354 if indDer[0].shape[0] > 0:
3337 3355 for i in range(indDer[0].shape[0]):
3338 3356 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3339 3357 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3340 3358
3341 3359 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3342 3360 for j in range(numPairs):
3343 3361 fit = stats.linregress(time, angAllCCF[j,:])
3344 3362 slopes[j] = fit[0]
3345
3363
3346 3364 #Remove Outlier
3347 3365 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3348 3366 # slopes = numpy.delete(slopes,indOut)
3349 3367 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3350 3368 # slopes = numpy.delete(slopes,indOut)
3351
3369
3352 3370 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3353 3371 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3354 3372 meteorAux[-2] = radialError
3355 3373 meteorAux[-3] = radialVelocity
3356
3374
3357 3375 #Setting Error
3358 3376 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3359 if numpy.abs(radialVelocity) > 200:
3377 if numpy.abs(radialVelocity) > 200:
3360 3378 meteorAux[-1] = 15
3361 3379 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3362 3380 elif radialError > radialStdThresh:
3363 3381 meteorAux[-1] = 12
3364
3382
3365 3383 listMeteors1.append(meteorAux)
3366 3384 return listMeteors1
3367
3385
3368 3386 def __setNewArrays(self, listMeteors, date, heiRang):
3369
3387
3370 3388 #New arrays
3371 3389 arrayMeteors = numpy.array(listMeteors)
3372 3390 arrayParameters = numpy.zeros((len(listMeteors), 13))
3373
3391
3374 3392 #Date inclusion
3375 3393 # date = re.findall(r'\((.*?)\)', date)
3376 3394 # date = date[0].split(',')
3377 3395 # date = map(int, date)
3378 #
3396 #
3379 3397 # if len(date)<6:
3380 3398 # date.append(0)
3381 #
3399 #
3382 3400 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3383 3401 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3384 3402 arrayDate = numpy.tile(date, (len(listMeteors)))
3385
3403
3386 3404 #Meteor array
3387 3405 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3388 3406 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3389
3407
3390 3408 #Parameters Array
3391 3409 arrayParameters[:,0] = arrayDate #Date
3392 3410 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3393 3411 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3394 3412 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3395 3413 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3396 3414
3397
3415
3398 3416 return arrayParameters
3399
3417
3400 3418 class CorrectSMPhases(Operation):
3401
3419
3402 3420 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3403
3421
3404 3422 arrayParameters = dataOut.data_param
3405 3423 pairsList = []
3406 3424 pairx = (0,1)
3407 3425 pairy = (2,3)
3408 3426 pairsList.append(pairx)
3409 3427 pairsList.append(pairy)
3410 3428 jph = numpy.zeros(4)
3411
3429
3412 3430 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3413 3431 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3414 3432 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3415
3433
3416 3434 meteorOps = SMOperations()
3417 3435 if channelPositions is None:
3418 3436 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3419 3437 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3420
3438
3421 3439 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3422 3440 h = (hmin,hmax)
3423
3441
3424 3442 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3425
3443
3426 3444 dataOut.data_param = arrayParameters
3427 3445 return
3428 3446
3429 3447 class SMPhaseCalibration(Operation):
3430
3448
3431 3449 __buffer = None
3432 3450
3433 3451 __initime = None
3434 3452
3435 3453 __dataReady = False
3436
3454
3437 3455 __isConfig = False
3438
3456
3439 3457 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3440
3458
3441 3459 dataTime = currentTime + paramInterval
3442 3460 deltaTime = dataTime - initTime
3443
3461
3444 3462 if deltaTime >= outputInterval or deltaTime < 0:
3445 3463 return True
3446
3464
3447 3465 return False
3448
3466
3449 3467 def __getGammas(self, pairs, d, phases):
3450 3468 gammas = numpy.zeros(2)
3451
3469
3452 3470 for i in range(len(pairs)):
3453
3471
3454 3472 pairi = pairs[i]
3455 3473
3456 3474 phip3 = phases[:,pairi[0]]
3457 3475 d3 = d[pairi[0]]
3458 3476 phip2 = phases[:,pairi[1]]
3459 3477 d2 = d[pairi[1]]
3460 3478 #Calculating gamma
3461 3479 # jdcos = alp1/(k*d1)
3462 3480 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3463 3481 jgamma = -phip2*d3/d2 - phip3
3464 3482 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3465 3483 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3466 3484 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3467
3485
3468 3486 #Revised distribution
3469 3487 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3470 3488
3471 3489 #Histogram
3472 3490 nBins = 64
3473 3491 rmin = -0.5*numpy.pi
3474 3492 rmax = 0.5*numpy.pi
3475 3493 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3476
3494
3477 3495 meteorsY = phaseHisto[0]
3478 3496 phasesX = phaseHisto[1][:-1]
3479 3497 width = phasesX[1] - phasesX[0]
3480 3498 phasesX += width/2
3481
3499
3482 3500 #Gaussian aproximation
3483 3501 bpeak = meteorsY.argmax()
3484 3502 peak = meteorsY.max()
3485 3503 jmin = bpeak - 5
3486 3504 jmax = bpeak + 5 + 1
3487
3505
3488 3506 if jmin<0:
3489 3507 jmin = 0
3490 3508 jmax = 6
3491 3509 elif jmax > meteorsY.size:
3492 3510 jmin = meteorsY.size - 6
3493 3511 jmax = meteorsY.size
3494
3512
3495 3513 x0 = numpy.array([peak,bpeak,50])
3496 3514 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3497
3515
3498 3516 #Gammas
3499 3517 gammas[i] = coeff[0][1]
3500
3518
3501 3519 return gammas
3502
3520
3503 3521 def __residualFunction(self, coeffs, y, t):
3504
3522
3505 3523 return y - self.__gauss_function(t, coeffs)
3506 3524
3507 3525 def __gauss_function(self, t, coeffs):
3508
3526
3509 3527 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3510 3528
3511 3529 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3512 3530 meteorOps = SMOperations()
3513 3531 nchan = 4
3514 3532 pairx = pairsList[0] #x es 0
3515 3533 pairy = pairsList[1] #y es 1
3516 3534 center_xangle = 0
3517 3535 center_yangle = 0
3518 3536 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3519 3537 ntimes = len(range_angle)
3520 3538
3521 3539 nstepsx = 20
3522 3540 nstepsy = 20
3523 3541
3524 3542 for iz in range(ntimes):
3525 3543 min_xangle = -range_angle[iz]/2 + center_xangle
3526 3544 max_xangle = range_angle[iz]/2 + center_xangle
3527 3545 min_yangle = -range_angle[iz]/2 + center_yangle
3528 3546 max_yangle = range_angle[iz]/2 + center_yangle
3529
3547
3530 3548 inc_x = (max_xangle-min_xangle)/nstepsx
3531 3549 inc_y = (max_yangle-min_yangle)/nstepsy
3532
3550
3533 3551 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3534 3552 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3535 3553 penalty = numpy.zeros((nstepsx,nstepsy))
3536 3554 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3537 3555 jph = numpy.zeros(nchan)
3538
3556
3539 3557 # Iterations looking for the offset
3540 3558 for iy in range(int(nstepsy)):
3541 3559 for ix in range(int(nstepsx)):
3542 3560 d3 = d[pairsList[1][0]]
3543 3561 d2 = d[pairsList[1][1]]
3544 3562 d5 = d[pairsList[0][0]]
3545 3563 d4 = d[pairsList[0][1]]
3546
3564
3547 3565 alp2 = alpha_y[iy] #gamma 1
3548 alp4 = alpha_x[ix] #gamma 0
3549
3566 alp4 = alpha_x[ix] #gamma 0
3567
3550 3568 alp3 = -alp2*d3/d2 - gammas[1]
3551 3569 alp5 = -alp4*d5/d4 - gammas[0]
3552 3570 # jph[pairy[1]] = alpha_y[iy]
3553 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3554
3571 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3572
3555 3573 # jph[pairx[1]] = alpha_x[ix]
3556 3574 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3557 3575 jph[pairsList[0][1]] = alp4
3558 3576 jph[pairsList[0][0]] = alp5
3559 3577 jph[pairsList[1][0]] = alp3
3560 jph[pairsList[1][1]] = alp2
3578 jph[pairsList[1][1]] = alp2
3561 3579 jph_array[:,ix,iy] = jph
3562 3580 # d = [2.0,2.5,2.5,2.0]
3563 #falta chequear si va a leer bien los meteoros
3581 #falta chequear si va a leer bien los meteoros
3564 3582 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3565 3583 error = meteorsArray1[:,-1]
3566 3584 ind1 = numpy.where(error==0)[0]
3567 3585 penalty[ix,iy] = ind1.size
3568
3586
3569 3587 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3570 3588 phOffset = jph_array[:,i,j]
3571
3589
3572 3590 center_xangle = phOffset[pairx[1]]
3573 3591 center_yangle = phOffset[pairy[1]]
3574
3592
3575 3593 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3576 phOffset = phOffset*180/numpy.pi
3594 phOffset = phOffset*180/numpy.pi
3577 3595 return phOffset
3578
3579
3596
3597
3580 3598 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3581
3599
3582 3600 dataOut.flagNoData = True
3583 self.__dataReady = False
3601 self.__dataReady = False
3584 3602 dataOut.outputInterval = nHours*3600
3585
3603
3586 3604 if self.__isConfig == False:
3587 3605 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3588 3606 #Get Initial LTC time
3589 3607 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3590 3608 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3591 3609
3592 3610 self.__isConfig = True
3593
3611
3594 3612 if self.__buffer is None:
3595 3613 self.__buffer = dataOut.data_param.copy()
3596 3614
3597 3615 else:
3598 3616 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3599
3617
3600 3618 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3601
3619
3602 3620 if self.__dataReady:
3603 3621 dataOut.utctimeInit = self.__initime
3604 3622 self.__initime += dataOut.outputInterval #to erase time offset
3605
3623
3606 3624 freq = dataOut.frequency
3607 3625 c = dataOut.C #m/s
3608 3626 lamb = c/freq
3609 3627 k = 2*numpy.pi/lamb
3610 3628 azimuth = 0
3611 3629 h = (hmin, hmax)
3612 3630 # pairs = ((0,1),(2,3)) #Estrella
3613 3631 # pairs = ((1,0),(2,3)) #T
3614 3632
3615 3633 if channelPositions is None:
3616 3634 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3617 3635 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3618 3636 meteorOps = SMOperations()
3619 3637 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3620 3638
3621 3639 #Checking correct order of pairs
3622 3640 pairs = []
3623 3641 if distances[1] > distances[0]:
3624 3642 pairs.append((1,0))
3625 3643 else:
3626 3644 pairs.append((0,1))
3627
3645
3628 3646 if distances[3] > distances[2]:
3629 3647 pairs.append((3,2))
3630 3648 else:
3631 3649 pairs.append((2,3))
3632 3650 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3633
3651
3634 3652 meteorsArray = self.__buffer
3635 3653 error = meteorsArray[:,-1]
3636 3654 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3637 3655 ind1 = numpy.where(boolError)[0]
3638 3656 meteorsArray = meteorsArray[ind1,:]
3639 3657 meteorsArray[:,-1] = 0
3640 3658 phases = meteorsArray[:,8:12]
3641
3659
3642 3660 #Calculate Gammas
3643 3661 gammas = self.__getGammas(pairs, distances, phases)
3644 3662 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3645 3663 #Calculate Phases
3646 3664 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3647 3665 phasesOff = phasesOff.reshape((1,phasesOff.size))
3648 3666 dataOut.data_output = -phasesOff
3649 3667 dataOut.flagNoData = False
3650 3668 self.__buffer = None
3651
3652
3669
3670
3653 3671 return
3654
3672
3655 3673 class SMOperations():
3656
3674
3657 3675 def __init__(self):
3658
3676
3659 3677 return
3660
3678
3661 3679 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3662
3680
3663 3681 arrayParameters = arrayParameters0.copy()
3664 3682 hmin = h[0]
3665 3683 hmax = h[1]
3666
3684
3667 3685 #Calculate AOA (Error N 3, 4)
3668 3686 #JONES ET AL. 1998
3669 3687 AOAthresh = numpy.pi/8
3670 3688 error = arrayParameters[:,-1]
3671 3689 phases = -arrayParameters[:,8:12] + jph
3672 3690 # phases = numpy.unwrap(phases)
3673 3691 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3674
3692
3675 3693 #Calculate Heights (Error N 13 and 14)
3676 3694 error = arrayParameters[:,-1]
3677 3695 Ranges = arrayParameters[:,1]
3678 3696 zenith = arrayParameters[:,4]
3679 3697 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3680
3698
3681 3699 #----------------------- Get Final data ------------------------------------
3682 3700 # error = arrayParameters[:,-1]
3683 3701 # ind1 = numpy.where(error==0)[0]
3684 3702 # arrayParameters = arrayParameters[ind1,:]
3685
3703
3686 3704 return arrayParameters
3687
3705
3688 3706 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3689
3707
3690 3708 arrayAOA = numpy.zeros((phases.shape[0],3))
3691 3709 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3692
3710
3693 3711 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3694 3712 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3695 3713 arrayAOA[:,2] = cosDirError
3696
3714
3697 3715 azimuthAngle = arrayAOA[:,0]
3698 3716 zenithAngle = arrayAOA[:,1]
3699
3717
3700 3718 #Setting Error
3701 3719 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3702 3720 error[indError] = 0
3703 3721 #Number 3: AOA not fesible
3704 3722 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3705 error[indInvalid] = 3
3723 error[indInvalid] = 3
3706 3724 #Number 4: Large difference in AOAs obtained from different antenna baselines
3707 3725 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3708 error[indInvalid] = 4
3726 error[indInvalid] = 4
3709 3727 return arrayAOA, error
3710
3728
3711 3729 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3712
3730
3713 3731 #Initializing some variables
3714 3732 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3715 3733 ang_aux = ang_aux.reshape(1,ang_aux.size)
3716
3734
3717 3735 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3718 3736 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3719
3720
3737
3738
3721 3739 for i in range(2):
3722 3740 ph0 = arrayPhase[:,pairsList[i][0]]
3723 3741 ph1 = arrayPhase[:,pairsList[i][1]]
3724 3742 d0 = distances[pairsList[i][0]]
3725 3743 d1 = distances[pairsList[i][1]]
3726
3727 ph0_aux = ph0 + ph1
3744
3745 ph0_aux = ph0 + ph1
3728 3746 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3729 3747 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3730 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3748 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3731 3749 #First Estimation
3732 3750 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3733
3751
3734 3752 #Most-Accurate Second Estimation
3735 3753 phi1_aux = ph0 - ph1
3736 3754 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3737 3755 #Direction Cosine 1
3738 3756 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3739
3757
3740 3758 #Searching the correct Direction Cosine
3741 3759 cosdir0_aux = cosdir0[:,i]
3742 3760 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3743 3761 #Minimum Distance
3744 3762 cosDiff = (cosdir1 - cosdir0_aux)**2
3745 3763 indcos = cosDiff.argmin(axis = 1)
3746 3764 #Saving Value obtained
3747 3765 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3748
3766
3749 3767 return cosdir0, cosdir
3750
3768
3751 3769 def __calculateAOA(self, cosdir, azimuth):
3752 3770 cosdirX = cosdir[:,0]
3753 3771 cosdirY = cosdir[:,1]
3754
3772
3755 3773 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3756 3774 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3757 3775 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3758
3776
3759 3777 return angles
3760
3778
3761 3779 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3762
3780
3763 3781 Ramb = 375 #Ramb = c/(2*PRF)
3764 3782 Re = 6371 #Earth Radius
3765 3783 heights = numpy.zeros(Ranges.shape)
3766
3784
3767 3785 R_aux = numpy.array([0,1,2])*Ramb
3768 3786 R_aux = R_aux.reshape(1,R_aux.size)
3769 3787
3770 3788 Ranges = Ranges.reshape(Ranges.size,1)
3771
3789
3772 3790 Ri = Ranges + R_aux
3773 3791 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3774
3792
3775 3793 #Check if there is a height between 70 and 110 km
3776 3794 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3777 3795 ind_h = numpy.where(h_bool == 1)[0]
3778
3796
3779 3797 hCorr = hi[ind_h, :]
3780 3798 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3781
3799
3782 3800 hCorr = hi[ind_hCorr][:len(ind_h)]
3783 3801 heights[ind_h] = hCorr
3784
3802
3785 3803 #Setting Error
3786 3804 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3787 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3805 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3788 3806 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3789 3807 error[indError] = 0
3790 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3808 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3791 3809 error[indInvalid2] = 14
3792 3810 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3793 error[indInvalid1] = 13
3794
3811 error[indInvalid1] = 13
3812
3795 3813 return heights, error
3796
3814
3797 3815 def getPhasePairs(self, channelPositions):
3798 3816 chanPos = numpy.array(channelPositions)
3799 3817 listOper = list(itertools.combinations(list(range(5)),2))
3800
3818
3801 3819 distances = numpy.zeros(4)
3802 3820 axisX = []
3803 3821 axisY = []
3804 3822 distX = numpy.zeros(3)
3805 3823 distY = numpy.zeros(3)
3806 3824 ix = 0
3807 3825 iy = 0
3808
3826
3809 3827 pairX = numpy.zeros((2,2))
3810 3828 pairY = numpy.zeros((2,2))
3811
3829
3812 3830 for i in range(len(listOper)):
3813 3831 pairi = listOper[i]
3814
3832
3815 3833 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3816
3834
3817 3835 if posDif[0] == 0:
3818 3836 axisY.append(pairi)
3819 3837 distY[iy] = posDif[1]
3820 3838 iy += 1
3821 3839 elif posDif[1] == 0:
3822 3840 axisX.append(pairi)
3823 3841 distX[ix] = posDif[0]
3824 3842 ix += 1
3825
3843
3826 3844 for i in range(2):
3827 3845 if i==0:
3828 3846 dist0 = distX
3829 3847 axis0 = axisX
3830 3848 else:
3831 3849 dist0 = distY
3832 3850 axis0 = axisY
3833
3851
3834 3852 side = numpy.argsort(dist0)[:-1]
3835 3853 axis0 = numpy.array(axis0)[side,:]
3836 3854 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3837 3855 axis1 = numpy.unique(numpy.reshape(axis0,4))
3838 3856 side = axis1[axis1 != chanC]
3839 3857 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3840 3858 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3841 if diff1<0:
3859 if diff1<0:
3842 3860 chan2 = side[0]
3843 3861 d2 = numpy.abs(diff1)
3844 3862 chan1 = side[1]
3845 3863 d1 = numpy.abs(diff2)
3846 3864 else:
3847 3865 chan2 = side[1]
3848 3866 d2 = numpy.abs(diff2)
3849 3867 chan1 = side[0]
3850 3868 d1 = numpy.abs(diff1)
3851
3869
3852 3870 if i==0:
3853 3871 chanCX = chanC
3854 3872 chan1X = chan1
3855 3873 chan2X = chan2
3856 3874 distances[0:2] = numpy.array([d1,d2])
3857 3875 else:
3858 3876 chanCY = chanC
3859 3877 chan1Y = chan1
3860 3878 chan2Y = chan2
3861 3879 distances[2:4] = numpy.array([d1,d2])
3862 3880 # axisXsides = numpy.reshape(axisX[ix,:],4)
3863 #
3881 #
3864 3882 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3865 3883 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3866 #
3884 #
3867 3885 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3868 3886 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3869 3887 # channel25X = int(pairX[0,ind25X])
3870 3888 # channel20X = int(pairX[1,ind20X])
3871 3889 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3872 3890 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3873 3891 # channel25Y = int(pairY[0,ind25Y])
3874 3892 # channel20Y = int(pairY[1,ind20Y])
3875
3893
3876 3894 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3877 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3878
3895 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3896
3879 3897 return pairslist, distances
3880 3898 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3881 #
3899 #
3882 3900 # arrayAOA = numpy.zeros((phases.shape[0],3))
3883 3901 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3884 #
3902 #
3885 3903 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3886 3904 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3887 3905 # arrayAOA[:,2] = cosDirError
3888 #
3906 #
3889 3907 # azimuthAngle = arrayAOA[:,0]
3890 3908 # zenithAngle = arrayAOA[:,1]
3891 #
3909 #
3892 3910 # #Setting Error
3893 3911 # #Number 3: AOA not fesible
3894 3912 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3895 # error[indInvalid] = 3
3913 # error[indInvalid] = 3
3896 3914 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3897 3915 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3898 # error[indInvalid] = 4
3916 # error[indInvalid] = 4
3899 3917 # return arrayAOA, error
3900 #
3918 #
3901 3919 # def __getDirectionCosines(self, arrayPhase, pairsList):
3902 #
3920 #
3903 3921 # #Initializing some variables
3904 3922 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3905 3923 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3906 #
3924 #
3907 3925 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3908 3926 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3909 #
3910 #
3927 #
3928 #
3911 3929 # for i in range(2):
3912 3930 # #First Estimation
3913 3931 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3914 3932 # #Dealias
3915 3933 # indcsi = numpy.where(phi0_aux > numpy.pi)
3916 # phi0_aux[indcsi] -= 2*numpy.pi
3934 # phi0_aux[indcsi] -= 2*numpy.pi
3917 3935 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3918 # phi0_aux[indcsi] += 2*numpy.pi
3936 # phi0_aux[indcsi] += 2*numpy.pi
3919 3937 # #Direction Cosine 0
3920 3938 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3921 #
3939 #
3922 3940 # #Most-Accurate Second Estimation
3923 3941 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3924 3942 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3925 3943 # #Direction Cosine 1
3926 3944 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3927 #
3945 #
3928 3946 # #Searching the correct Direction Cosine
3929 3947 # cosdir0_aux = cosdir0[:,i]
3930 3948 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3931 3949 # #Minimum Distance
3932 3950 # cosDiff = (cosdir1 - cosdir0_aux)**2
3933 3951 # indcos = cosDiff.argmin(axis = 1)
3934 3952 # #Saving Value obtained
3935 3953 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3936 #
3954 #
3937 3955 # return cosdir0, cosdir
3938 #
3956 #
3939 3957 # def __calculateAOA(self, cosdir, azimuth):
3940 3958 # cosdirX = cosdir[:,0]
3941 3959 # cosdirY = cosdir[:,1]
3942 #
3960 #
3943 3961 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3944 3962 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3945 3963 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3946 #
3964 #
3947 3965 # return angles
3948 #
3966 #
3949 3967 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3950 #
3968 #
3951 3969 # Ramb = 375 #Ramb = c/(2*PRF)
3952 3970 # Re = 6371 #Earth Radius
3953 3971 # heights = numpy.zeros(Ranges.shape)
3954 #
3972 #
3955 3973 # R_aux = numpy.array([0,1,2])*Ramb
3956 3974 # R_aux = R_aux.reshape(1,R_aux.size)
3957 #
3975 #
3958 3976 # Ranges = Ranges.reshape(Ranges.size,1)
3959 #
3977 #
3960 3978 # Ri = Ranges + R_aux
3961 3979 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3962 #
3980 #
3963 3981 # #Check if there is a height between 70 and 110 km
3964 3982 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3965 3983 # ind_h = numpy.where(h_bool == 1)[0]
3966 #
3984 #
3967 3985 # hCorr = hi[ind_h, :]
3968 3986 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3969 #
3970 # hCorr = hi[ind_hCorr]
3987 #
3988 # hCorr = hi[ind_hCorr]
3971 3989 # heights[ind_h] = hCorr
3972 #
3990 #
3973 3991 # #Setting Error
3974 3992 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3975 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3976 #
3977 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3993 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3994 #
3995 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3978 3996 # error[indInvalid2] = 14
3979 3997 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3980 # error[indInvalid1] = 13
3981 #
3982 # return heights, error
3983 No newline at end of file
3998 # error[indInvalid1] = 13
3999 #
4000 # return heights, error
@@ -1,1056 +1,1260
1 1 import itertools
2 2
3 3 import numpy
4 4
5 5 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
6 6 from schainpy.model.data.jrodata import Spectra
7 7 from schainpy.model.data.jrodata import hildebrand_sekhon
8 8 from schainpy.utils import log
9 9
10 10 @MPDecorator
11 11 class SpectraProc(ProcessingUnit):
12 12
13 13
14 14 def __init__(self):
15 15
16 16 ProcessingUnit.__init__(self)
17 17
18 18 self.buffer = None
19 19 self.firstdatatime = None
20 20 self.profIndex = 0
21 21 self.dataOut = Spectra()
22 22 self.id_min = None
23 23 self.id_max = None
24 24 self.setupReq = False #Agregar a todas las unidades de proc
25 25
26 26 def __updateSpecFromVoltage(self):
27 27
28 28 self.dataOut.timeZone = self.dataIn.timeZone
29 29 self.dataOut.dstFlag = self.dataIn.dstFlag
30 30 self.dataOut.errorCount = self.dataIn.errorCount
31 31 self.dataOut.useLocalTime = self.dataIn.useLocalTime
32 32 try:
33 33 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
34 34 except:
35 35 pass
36 36 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
37 37 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
38 38 self.dataOut.channelList = self.dataIn.channelList
39 39 self.dataOut.heightList = self.dataIn.heightList
40 40 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
41 41
42 42 self.dataOut.nBaud = self.dataIn.nBaud
43 43 self.dataOut.nCode = self.dataIn.nCode
44 44 self.dataOut.code = self.dataIn.code
45 45 self.dataOut.nProfiles = self.dataOut.nFFTPoints
46 46
47 47 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
48 48 self.dataOut.utctime = self.firstdatatime
49 49 # asumo q la data esta decodificada
50 50 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
51 51 # asumo q la data esta sin flip
52 52 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
53 53 self.dataOut.flagShiftFFT = False
54 54
55 55 self.dataOut.nCohInt = self.dataIn.nCohInt
56 56 self.dataOut.nIncohInt = 1
57 57
58 58 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
59 59
60 60 self.dataOut.frequency = self.dataIn.frequency
61 61 self.dataOut.realtime = self.dataIn.realtime
62 62
63 63 self.dataOut.azimuth = self.dataIn.azimuth
64 64 self.dataOut.zenith = self.dataIn.zenith
65 65
66 66 self.dataOut.beam.codeList = self.dataIn.beam.codeList
67 67 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
68 68 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
69 69
70 70 def __getFft(self):
71 71 """
72 72 Convierte valores de Voltaje a Spectra
73 73
74 74 Affected:
75 75 self.dataOut.data_spc
76 76 self.dataOut.data_cspc
77 77 self.dataOut.data_dc
78 78 self.dataOut.heightList
79 79 self.profIndex
80 80 self.buffer
81 81 self.dataOut.flagNoData
82 82 """
83 83 fft_volt = numpy.fft.fft(
84 84 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
85 85 fft_volt = fft_volt.astype(numpy.dtype('complex'))
86 86 dc = fft_volt[:, 0, :]
87 87
88 88 # calculo de self-spectra
89 89 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
90 90 spc = fft_volt * numpy.conjugate(fft_volt)
91 91 spc = spc.real
92 92
93 93 blocksize = 0
94 94 blocksize += dc.size
95 95 blocksize += spc.size
96 96
97 #print("spc :",spc.shape)
98 data_wr = None
99 if self.dataOut.flagWR:
100 data_wr = fft_volt
101 blocksize = fft_volt.size
102
97 103 cspc = None
98 104 pairIndex = 0
99 105 if self.dataOut.pairsList != None:
100 106 # calculo de cross-spectra
101 107 cspc = numpy.zeros(
102 108 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
103 109 for pair in self.dataOut.pairsList:
104 110 if pair[0] not in self.dataOut.channelList:
105 111 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
106 112 str(pair), str(self.dataOut.channelList)))
107 113 if pair[1] not in self.dataOut.channelList:
108 114 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
109 115 str(pair), str(self.dataOut.channelList)))
110 116
111 117 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
112 118 numpy.conjugate(fft_volt[pair[1], :, :])
113 119 pairIndex += 1
114 120 blocksize += cspc.size
115 121
116 self.dataOut.data_spc = spc
117 self.dataOut.data_cspc = cspc
118 self.dataOut.data_dc = dc
119 self.dataOut.blockSize = blocksize
122 self.dataOut.data_spc = spc
123 self.dataOut.data_cspc = cspc
124 self.dataOut.data_wr = data_wr
125 self.dataOut.data_dc = dc
126 self.dataOut.blockSize = blocksize
120 127 self.dataOut.flagShiftFFT = False
121 128
122 def run(self, nProfiles=None, nFFTPoints=None, pairsList=[], ippFactor=None, shift_fft=False):
129 def run(self, nProfiles=None, nFFTPoints=None, pairsList=[], ippFactor=None, shift_fft=False,flagWR= 0):
130
131 self.dataOut.flagWR = flagWR
123 132
124 133 if self.dataIn.type == "Spectra":
125 134 self.dataOut.copy(self.dataIn)
135
126 136 if shift_fft:
127 137 #desplaza a la derecha en el eje 2 determinadas posiciones
128 138 shift = int(self.dataOut.nFFTPoints/2)
129 139 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
130 140
131 141 if self.dataOut.data_cspc is not None:
132 142 #desplaza a la derecha en el eje 2 determinadas posiciones
133 143 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
134 144
135 145 return True
136 146
137 147 if self.dataIn.type == "Voltage":
138
148 #print("VOLTAGE INPUT SPECTRA")
139 149 self.dataOut.flagNoData = True
140 150
141 151 if nFFTPoints == None:
142 152 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
143 153
144 154 if nProfiles == None:
145 155 nProfiles = nFFTPoints
146 156
147 157 if ippFactor == None:
148 158 ippFactor = 1
149 159
150 160 self.dataOut.ippFactor = ippFactor
151 161
152 162 self.dataOut.nFFTPoints = nFFTPoints
153 163 self.dataOut.pairsList = pairsList
154 164
155 165 if self.buffer is None:
156 166 self.buffer = numpy.zeros((self.dataIn.nChannels,
157 167 nProfiles,
158 168 self.dataIn.nHeights),
159 169 dtype='complex')
170 #print("buffer :",self.buffer.shape)
160 171
161 172 if self.dataIn.flagDataAsBlock:
162 173 nVoltProfiles = self.dataIn.data.shape[1]
163 174
164 175 if nVoltProfiles == nProfiles:
165 176 self.buffer = self.dataIn.data.copy()
166 177 self.profIndex = nVoltProfiles
167 178
168 179 elif nVoltProfiles < nProfiles:
169 180
170 181 if self.profIndex == 0:
171 182 self.id_min = 0
172 183 self.id_max = nVoltProfiles
173 184
174 185 self.buffer[:, self.id_min:self.id_max,
175 186 :] = self.dataIn.data
176 187 self.profIndex += nVoltProfiles
177 188 self.id_min += nVoltProfiles
178 189 self.id_max += nVoltProfiles
179 190 else:
180 191 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
181 192 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
182 193 self.dataOut.flagNoData = True
183 194 return 0
184 195 else:
196 #print("Spectra ",self.profIndex)
185 197 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
186 198 self.profIndex += 1
187 199
188 200 if self.firstdatatime == None:
189 201 self.firstdatatime = self.dataIn.utctime
190 202
191 203 if self.profIndex == nProfiles:
192 204 self.__updateSpecFromVoltage()
193 205 self.__getFft()
206 #print(" DATAOUT SHAPE SPEC",self.dataOut.data_spc.shape)
194 207
195 208 self.dataOut.flagNoData = False
196 209 self.firstdatatime = None
197 210 self.profIndex = 0
198 211
199 212 return True
200 213
201 214 raise ValueError("The type of input object '%s' is not valid" % (
202 215 self.dataIn.type))
203 216
204 217 def __selectPairs(self, pairsList):
205 218
206 219 if not pairsList:
207 220 return
208 221
209 222 pairs = []
210 223 pairsIndex = []
211 224
212 225 for pair in pairsList:
213 226 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
214 227 continue
215 228 pairs.append(pair)
216 229 pairsIndex.append(pairs.index(pair))
217 230
218 231 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
219 232 self.dataOut.pairsList = pairs
220 233
221 234 return
222 235
223 236 def __selectPairsByChannel(self, channelList=None):
224 237
225 238 if channelList == None:
226 239 return
227 240
228 241 pairsIndexListSelected = []
229 242 for pairIndex in self.dataOut.pairsIndexList:
230 243 # First pair
231 244 if self.dataOut.pairsList[pairIndex][0] not in channelList:
232 245 continue
233 246 # Second pair
234 247 if self.dataOut.pairsList[pairIndex][1] not in channelList:
235 248 continue
236 249
237 250 pairsIndexListSelected.append(pairIndex)
238 251
239 252 if not pairsIndexListSelected:
240 253 self.dataOut.data_cspc = None
241 254 self.dataOut.pairsList = []
242 255 return
243 256
244 257 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
245 258 self.dataOut.pairsList = [self.dataOut.pairsList[i]
246 259 for i in pairsIndexListSelected]
247 260
248 261 return
249 262
250 263 def selectChannels(self, channelList):
251 264
252 265 channelIndexList = []
253 266
254 267 for channel in channelList:
255 268 if channel not in self.dataOut.channelList:
256 269 raise ValueError("Error selecting channels, Channel %d is not valid.\nAvailable channels = %s" % (
257 270 channel, str(self.dataOut.channelList)))
258 271
259 272 index = self.dataOut.channelList.index(channel)
260 273 channelIndexList.append(index)
261 274
262 275 self.selectChannelsByIndex(channelIndexList)
263 276
264 277 def selectChannelsByIndex(self, channelIndexList):
265 278 """
266 279 Selecciona un bloque de datos en base a canales segun el channelIndexList
267 280
268 281 Input:
269 282 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
270 283
271 284 Affected:
272 285 self.dataOut.data_spc
273 286 self.dataOut.channelIndexList
274 287 self.dataOut.nChannels
275 288
276 289 Return:
277 290 None
278 291 """
279 292
280 293 for channelIndex in channelIndexList:
281 294 if channelIndex not in self.dataOut.channelIndexList:
282 295 raise ValueError("Error selecting channels: The value %d in channelIndexList is not valid.\nAvailable channel indexes = " % (
283 296 channelIndex, self.dataOut.channelIndexList))
284 297
285 298 data_spc = self.dataOut.data_spc[channelIndexList, :]
286 299 data_dc = self.dataOut.data_dc[channelIndexList, :]
287 300
288 301 self.dataOut.data_spc = data_spc
289 302 self.dataOut.data_dc = data_dc
290 303
291 304 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
292 305 self.dataOut.channelList = range(len(channelIndexList))
293 306 self.__selectPairsByChannel(channelIndexList)
294
307
295 308 return 1
296
297
309
310
298 311 def selectFFTs(self, minFFT, maxFFT ):
299 312 """
300 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
313 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
301 314 minFFT<= FFT <= maxFFT
302 315 """
303
316
304 317 if (minFFT > maxFFT):
305 318 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
306 319
307 320 if (minFFT < self.dataOut.getFreqRange()[0]):
308 321 minFFT = self.dataOut.getFreqRange()[0]
309 322
310 323 if (maxFFT > self.dataOut.getFreqRange()[-1]):
311 324 maxFFT = self.dataOut.getFreqRange()[-1]
312 325
313 326 minIndex = 0
314 327 maxIndex = 0
315 328 FFTs = self.dataOut.getFreqRange()
316 329
317 330 inda = numpy.where(FFTs >= minFFT)
318 331 indb = numpy.where(FFTs <= maxFFT)
319 332
320 333 try:
321 334 minIndex = inda[0][0]
322 335 except:
323 336 minIndex = 0
324 337
325 338 try:
326 339 maxIndex = indb[0][-1]
327 340 except:
328 341 maxIndex = len(FFTs)
329 342
330 343 self.selectFFTsByIndex(minIndex, maxIndex)
331 344
332 345 return 1
333
334
346
347
335 348 def setH0(self, h0, deltaHeight = None):
336
349
337 350 if not deltaHeight:
338 351 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
339
352
340 353 nHeights = self.dataOut.nHeights
341
354
342 355 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
343
356
344 357 self.dataOut.heightList = newHeiRange
345
346
358
359
347 360 def selectHeights(self, minHei, maxHei):
348 361 """
349 362 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
350 363 minHei <= height <= maxHei
351 364
352 365 Input:
353 366 minHei : valor minimo de altura a considerar
354 367 maxHei : valor maximo de altura a considerar
355 368
356 369 Affected:
357 370 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
358 371
359 372 Return:
360 373 1 si el metodo se ejecuto con exito caso contrario devuelve 0
361 374 """
362 375
363
376
364 377 if (minHei > maxHei):
365 378 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei))
366 379
367 380 if (minHei < self.dataOut.heightList[0]):
368 381 minHei = self.dataOut.heightList[0]
369 382
370 383 if (maxHei > self.dataOut.heightList[-1]):
371 384 maxHei = self.dataOut.heightList[-1]
372 385
373 386 minIndex = 0
374 387 maxIndex = 0
375 388 heights = self.dataOut.heightList
376 389
377 390 inda = numpy.where(heights >= minHei)
378 391 indb = numpy.where(heights <= maxHei)
379 392
380 393 try:
381 394 minIndex = inda[0][0]
382 395 except:
383 396 minIndex = 0
384 397
385 398 try:
386 399 maxIndex = indb[0][-1]
387 400 except:
388 401 maxIndex = len(heights)
389 402
390 403 self.selectHeightsByIndex(minIndex, maxIndex)
391
404
392 405
393 406 return 1
394 407
395 408 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
396 409 newheis = numpy.where(
397 410 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
398 411
399 412 if hei_ref != None:
400 413 newheis = numpy.where(self.dataOut.heightList > hei_ref)
401 414
402 415 minIndex = min(newheis[0])
403 416 maxIndex = max(newheis[0])
404 417 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
405 418 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
406 419
407 420 # determina indices
408 421 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
409 422 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
410 423 avg_dB = 10 * \
411 424 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
412 425 beacon_dB = numpy.sort(avg_dB)[-nheis:]
413 426 beacon_heiIndexList = []
414 427 for val in avg_dB.tolist():
415 428 if val >= beacon_dB[0]:
416 429 beacon_heiIndexList.append(avg_dB.tolist().index(val))
417 430
418 431 #data_spc = data_spc[:,:,beacon_heiIndexList]
419 432 data_cspc = None
420 433 if self.dataOut.data_cspc is not None:
421 434 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
422 435 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
423 436
424 437 data_dc = None
425 438 if self.dataOut.data_dc is not None:
426 439 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
427 440 #data_dc = data_dc[:,beacon_heiIndexList]
428 441
429 442 self.dataOut.data_spc = data_spc
430 443 self.dataOut.data_cspc = data_cspc
431 444 self.dataOut.data_dc = data_dc
432 445 self.dataOut.heightList = heightList
433 446 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
434 447
435 448 return 1
436 449
437 450 def selectFFTsByIndex(self, minIndex, maxIndex):
438 451 """
439
452
440 453 """
441 454
442 455 if (minIndex < 0) or (minIndex > maxIndex):
443 456 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
444 457
445 458 if (maxIndex >= self.dataOut.nProfiles):
446 459 maxIndex = self.dataOut.nProfiles-1
447 460
448 461 #Spectra
449 462 data_spc = self.dataOut.data_spc[:,minIndex:maxIndex+1,:]
450 463
451 464 data_cspc = None
452 465 if self.dataOut.data_cspc is not None:
453 466 data_cspc = self.dataOut.data_cspc[:,minIndex:maxIndex+1,:]
454 467
455 468 data_dc = None
456 469 if self.dataOut.data_dc is not None:
457 470 data_dc = self.dataOut.data_dc[minIndex:maxIndex+1,:]
458 471
459 472 self.dataOut.data_spc = data_spc
460 473 self.dataOut.data_cspc = data_cspc
461 474 self.dataOut.data_dc = data_dc
462
475
463 476 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
464 477 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
465 478 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
466 479
467 480 return 1
468 481
469 482
470 483
471 484 def selectHeightsByIndex(self, minIndex, maxIndex):
472 485 """
473 486 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
474 487 minIndex <= index <= maxIndex
475 488
476 489 Input:
477 490 minIndex : valor de indice minimo de altura a considerar
478 491 maxIndex : valor de indice maximo de altura a considerar
479 492
480 493 Affected:
481 494 self.dataOut.data_spc
482 495 self.dataOut.data_cspc
483 496 self.dataOut.data_dc
484 497 self.dataOut.heightList
485 498
486 499 Return:
487 500 1 si el metodo se ejecuto con exito caso contrario devuelve 0
488 501 """
489 502
490 503 if (minIndex < 0) or (minIndex > maxIndex):
491 504 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (
492 505 minIndex, maxIndex))
493 506
494 507 if (maxIndex >= self.dataOut.nHeights):
495 508 maxIndex = self.dataOut.nHeights - 1
496 509
497 510 # Spectra
498 511 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
499 512
500 513 data_cspc = None
501 514 if self.dataOut.data_cspc is not None:
502 515 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
503 516
504 517 data_dc = None
505 518 if self.dataOut.data_dc is not None:
506 519 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
507 520
508 521 self.dataOut.data_spc = data_spc
509 522 self.dataOut.data_cspc = data_cspc
510 523 self.dataOut.data_dc = data_dc
511 524
512 525 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
513 526
514 527 return 1
515 528
516 529 def removeDC(self, mode=2):
517 530 jspectra = self.dataOut.data_spc
518 531 jcspectra = self.dataOut.data_cspc
519 532
520 533 num_chan = jspectra.shape[0]
521 534 num_hei = jspectra.shape[2]
522 535
523 536 if jcspectra is not None:
524 537 jcspectraExist = True
525 538 num_pairs = jcspectra.shape[0]
526 539 else:
527 540 jcspectraExist = False
528 541
529 542 freq_dc = int(jspectra.shape[1] / 2)
530 543 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
531 544 ind_vel = ind_vel.astype(int)
532 545
533 546 if ind_vel[0] < 0:
534 547 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
535 548
536 549 if mode == 1:
537 550 jspectra[:, freq_dc, :] = (
538 551 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
539 552
540 553 if jcspectraExist:
541 554 jcspectra[:, freq_dc, :] = (
542 555 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
543 556
544 557 if mode == 2:
545 558
546 559 vel = numpy.array([-2, -1, 1, 2])
547 560 xx = numpy.zeros([4, 4])
548 561
549 562 for fil in range(4):
550 563 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
551 564
552 565 xx_inv = numpy.linalg.inv(xx)
553 566 xx_aux = xx_inv[0, :]
554 567
555 for ich in range(num_chan):
568 for ich in range(num_chan):
556 569 yy = jspectra[ich, ind_vel, :]
557 570 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
558 571
559 572 junkid = jspectra[ich, freq_dc, :] <= 0
560 573 cjunkid = sum(junkid)
561 574
562 575 if cjunkid.any():
563 576 jspectra[ich, freq_dc, junkid.nonzero()] = (
564 577 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
565 578
566 579 if jcspectraExist:
567 580 for ip in range(num_pairs):
568 581 yy = jcspectra[ip, ind_vel, :]
569 582 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
570 583
571 584 self.dataOut.data_spc = jspectra
572 585 self.dataOut.data_cspc = jcspectra
573 586
574 587 return 1
575 588
576 589 def removeInterference2(self):
577
590
578 591 cspc = self.dataOut.data_cspc
579 592 spc = self.dataOut.data_spc
580 Heights = numpy.arange(cspc.shape[2])
593 Heights = numpy.arange(cspc.shape[2])
581 594 realCspc = numpy.abs(cspc)
582
595
583 596 for i in range(cspc.shape[0]):
584 597 LinePower= numpy.sum(realCspc[i], axis=0)
585 598 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
586 599 SelectedHeights = Heights[ numpy.where( LinePower < Threshold ) ]
587 600 InterferenceSum = numpy.sum( realCspc[i,:,SelectedHeights], axis=0 )
588 601 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
589 602 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
590
591
603
604
592 605 InterferenceRange = numpy.where( ([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
593 606 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
594 607 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
595 608 cspc[i,InterferenceRange,:] = numpy.NaN
596
597
598
609
610
611
599 612 self.dataOut.data_cspc = cspc
600
613
601 614 def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None):
602 615
603 616 jspectra = self.dataOut.data_spc
604 617 jcspectra = self.dataOut.data_cspc
605 618 jnoise = self.dataOut.getNoise()
606 619 num_incoh = self.dataOut.nIncohInt
607 620
608 621 num_channel = jspectra.shape[0]
609 622 num_prof = jspectra.shape[1]
610 623 num_hei = jspectra.shape[2]
611 624
612 625 # hei_interf
613 626 if hei_interf is None:
614 627 count_hei = int(num_hei / 2)
615 628 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
616 629 hei_interf = numpy.asarray(hei_interf)[0]
617 630 # nhei_interf
618 631 if (nhei_interf == None):
619 632 nhei_interf = 5
620 633 if (nhei_interf < 1):
621 634 nhei_interf = 1
622 635 if (nhei_interf > count_hei):
623 636 nhei_interf = count_hei
624 637 if (offhei_interf == None):
625 638 offhei_interf = 0
626 639
627 640 ind_hei = list(range(num_hei))
628 641 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
629 642 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
630 643 mask_prof = numpy.asarray(list(range(num_prof)))
631 644 num_mask_prof = mask_prof.size
632 645 comp_mask_prof = [0, num_prof / 2]
633 646
634 647 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
635 648 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
636 649 jnoise = numpy.nan
637 650 noise_exist = jnoise[0] < numpy.Inf
638 651
639 652 # Subrutina de Remocion de la Interferencia
640 653 for ich in range(num_channel):
641 654 # Se ordena los espectros segun su potencia (menor a mayor)
642 655 power = jspectra[ich, mask_prof, :]
643 656 power = power[:, hei_interf]
644 657 power = power.sum(axis=0)
645 658 psort = power.ravel().argsort()
646 659
647 660 # Se estima la interferencia promedio en los Espectros de Potencia empleando
648 661 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
649 662 offhei_interf, nhei_interf + offhei_interf))]]]
650 663
651 664 if noise_exist:
652 665 # tmp_noise = jnoise[ich] / num_prof
653 666 tmp_noise = jnoise[ich]
654 667 junkspc_interf = junkspc_interf - tmp_noise
655 668 #junkspc_interf[:,comp_mask_prof] = 0
656 669
657 670 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
658 671 jspc_interf = jspc_interf.transpose()
659 672 # Calculando el espectro de interferencia promedio
660 673 noiseid = numpy.where(
661 674 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
662 675 noiseid = noiseid[0]
663 676 cnoiseid = noiseid.size
664 677 interfid = numpy.where(
665 678 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
666 679 interfid = interfid[0]
667 680 cinterfid = interfid.size
668 681
669 682 if (cnoiseid > 0):
670 683 jspc_interf[noiseid] = 0
671 684
672 685 # Expandiendo los perfiles a limpiar
673 686 if (cinterfid > 0):
674 687 new_interfid = (
675 688 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
676 689 new_interfid = numpy.asarray(new_interfid)
677 690 new_interfid = {x for x in new_interfid}
678 691 new_interfid = numpy.array(list(new_interfid))
679 692 new_cinterfid = new_interfid.size
680 693 else:
681 694 new_cinterfid = 0
682 695
683 696 for ip in range(new_cinterfid):
684 697 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
685 698 jspc_interf[new_interfid[ip]
686 699 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
687 700
688 701 jspectra[ich, :, ind_hei] = jspectra[ich, :,
689 702 ind_hei] - jspc_interf # Corregir indices
690 703
691 704 # Removiendo la interferencia del punto de mayor interferencia
692 705 ListAux = jspc_interf[mask_prof].tolist()
693 706 maxid = ListAux.index(max(ListAux))
694 707
695 708 if cinterfid > 0:
696 709 for ip in range(cinterfid * (interf == 2) - 1):
697 710 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
698 711 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
699 712 cind = len(ind)
700 713
701 714 if (cind > 0):
702 715 jspectra[ich, interfid[ip], ind] = tmp_noise * \
703 716 (1 + (numpy.random.uniform(cind) - 0.5) /
704 717 numpy.sqrt(num_incoh))
705 718
706 719 ind = numpy.array([-2, -1, 1, 2])
707 720 xx = numpy.zeros([4, 4])
708 721
709 722 for id1 in range(4):
710 723 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
711 724
712 725 xx_inv = numpy.linalg.inv(xx)
713 726 xx = xx_inv[:, 0]
714 727 ind = (ind + maxid + num_mask_prof) % num_mask_prof
715 728 yy = jspectra[ich, mask_prof[ind], :]
716 729 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
717 730 yy.transpose(), xx)
718 731
719 732 indAux = (jspectra[ich, :, :] < tmp_noise *
720 733 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
721 734 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
722 735 (1 - 1 / numpy.sqrt(num_incoh))
723 736
724 737 # Remocion de Interferencia en el Cross Spectra
725 738 if jcspectra is None:
726 739 return jspectra, jcspectra
727 740 num_pairs = int(jcspectra.size / (num_prof * num_hei))
728 741 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
729 742
730 743 for ip in range(num_pairs):
731 744
732 745 #-------------------------------------------
733 746
734 747 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
735 748 cspower = cspower[:, hei_interf]
736 749 cspower = cspower.sum(axis=0)
737 750
738 751 cspsort = cspower.ravel().argsort()
739 752 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
740 753 offhei_interf, nhei_interf + offhei_interf))]]]
741 754 junkcspc_interf = junkcspc_interf.transpose()
742 755 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
743 756
744 757 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
745 758
746 759 median_real = int(numpy.median(numpy.real(
747 760 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
748 761 median_imag = int(numpy.median(numpy.imag(
749 762 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
750 763 comp_mask_prof = [int(e) for e in comp_mask_prof]
751 764 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
752 765 median_real, median_imag)
753 766
754 767 for iprof in range(num_prof):
755 768 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
756 769 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
757 770
758 771 # Removiendo la Interferencia
759 772 jcspectra[ip, :, ind_hei] = jcspectra[ip,
760 773 :, ind_hei] - jcspc_interf
761 774
762 775 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
763 776 maxid = ListAux.index(max(ListAux))
764 777
765 778 ind = numpy.array([-2, -1, 1, 2])
766 779 xx = numpy.zeros([4, 4])
767 780
768 781 for id1 in range(4):
769 782 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
770 783
771 784 xx_inv = numpy.linalg.inv(xx)
772 785 xx = xx_inv[:, 0]
773 786
774 787 ind = (ind + maxid + num_mask_prof) % num_mask_prof
775 788 yy = jcspectra[ip, mask_prof[ind], :]
776 789 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
777 790
778 791 # Guardar Resultados
779 792 self.dataOut.data_spc = jspectra
780 793 self.dataOut.data_cspc = jcspectra
781 794
782 795 return 1
783 796
784 797 def setRadarFrequency(self, frequency=None):
785 798
786 799 if frequency != None:
787 800 self.dataOut.frequency = frequency
788 801
789 802 return 1
790 803
791 804 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
792 805 # validacion de rango
793 806 if minHei == None:
794 807 minHei = self.dataOut.heightList[0]
795 808
796 809 if maxHei == None:
797 810 maxHei = self.dataOut.heightList[-1]
798 811
799 812 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
800 813 print('minHei: %.2f is out of the heights range' % (minHei))
801 814 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
802 815 minHei = self.dataOut.heightList[0]
803 816
804 817 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
805 818 print('maxHei: %.2f is out of the heights range' % (maxHei))
806 819 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
807 820 maxHei = self.dataOut.heightList[-1]
808 821
809 822 # validacion de velocidades
810 823 velrange = self.dataOut.getVelRange(1)
811 824
812 825 if minVel == None:
813 826 minVel = velrange[0]
814 827
815 828 if maxVel == None:
816 829 maxVel = velrange[-1]
817 830
818 831 if (minVel < velrange[0]) or (minVel > maxVel):
819 832 print('minVel: %.2f is out of the velocity range' % (minVel))
820 833 print('minVel is setting to %.2f' % (velrange[0]))
821 834 minVel = velrange[0]
822 835
823 836 if (maxVel > velrange[-1]) or (maxVel < minVel):
824 837 print('maxVel: %.2f is out of the velocity range' % (maxVel))
825 838 print('maxVel is setting to %.2f' % (velrange[-1]))
826 839 maxVel = velrange[-1]
827 840
828 841 # seleccion de indices para rango
829 842 minIndex = 0
830 843 maxIndex = 0
831 844 heights = self.dataOut.heightList
832 845
833 846 inda = numpy.where(heights >= minHei)
834 847 indb = numpy.where(heights <= maxHei)
835 848
836 849 try:
837 850 minIndex = inda[0][0]
838 851 except:
839 852 minIndex = 0
840 853
841 854 try:
842 855 maxIndex = indb[0][-1]
843 856 except:
844 857 maxIndex = len(heights)
845 858
846 859 if (minIndex < 0) or (minIndex > maxIndex):
847 860 raise ValueError("some value in (%d,%d) is not valid" % (
848 861 minIndex, maxIndex))
849 862
850 863 if (maxIndex >= self.dataOut.nHeights):
851 864 maxIndex = self.dataOut.nHeights - 1
852 865
853 866 # seleccion de indices para velocidades
854 867 indminvel = numpy.where(velrange >= minVel)
855 868 indmaxvel = numpy.where(velrange <= maxVel)
856 869 try:
857 870 minIndexVel = indminvel[0][0]
858 871 except:
859 872 minIndexVel = 0
860 873
861 874 try:
862 875 maxIndexVel = indmaxvel[0][-1]
863 876 except:
864 877 maxIndexVel = len(velrange)
865 878
866 879 # seleccion del espectro
867 880 data_spc = self.dataOut.data_spc[:,
868 881 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
869 882 # estimacion de ruido
870 883 noise = numpy.zeros(self.dataOut.nChannels)
871 884
872 885 for channel in range(self.dataOut.nChannels):
873 886 daux = data_spc[channel, :, :]
874 887 noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt)
875 888
876 889 self.dataOut.noise_estimation = noise.copy()
877 890
878 891 return 1
879 892
880 893
881 894 class IncohInt(Operation):
882 895
883 896 __profIndex = 0
884 897 __withOverapping = False
885 898
886 899 __byTime = False
887 900 __initime = None
888 901 __lastdatatime = None
889 902 __integrationtime = None
890 903
891 904 __buffer_spc = None
892 905 __buffer_cspc = None
893 906 __buffer_dc = None
894 907
895 908 __dataReady = False
896 909
897 910 __timeInterval = None
898 911
899 912 n = None
900 913
901 914 def __init__(self):
902 915
903 916 Operation.__init__(self)
904 917
905 918 def setup(self, n=None, timeInterval=None, overlapping=False):
906 919 """
907 920 Set the parameters of the integration class.
908 921
909 922 Inputs:
910 923
911 924 n : Number of coherent integrations
912 925 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
913 926 overlapping :
914 927
915 928 """
916 929
917 930 self.__initime = None
918 931 self.__lastdatatime = 0
919 932
920 933 self.__buffer_spc = 0
921 934 self.__buffer_cspc = 0
922 935 self.__buffer_dc = 0
923 936
924 937 self.__profIndex = 0
925 938 self.__dataReady = False
926 939 self.__byTime = False
927 940
928 941 if n is None and timeInterval is None:
929 942 raise ValueError("n or timeInterval should be specified ...")
930 943
931 944 if n is not None:
932 945 self.n = int(n)
933 946 else:
934
947
935 948 self.__integrationtime = int(timeInterval)
936 949 self.n = None
937 950 self.__byTime = True
938 951
939 952 def putData(self, data_spc, data_cspc, data_dc):
940 953 """
941 954 Add a profile to the __buffer_spc and increase in one the __profileIndex
942 955
943 956 """
957 print("profIndex: ",self.__profIndex)
958 print("data_spc.shape: ",data_spc.shape)
959 print("data_spc.shape: ",data_spc[0,0,:])
944 960
945 961 self.__buffer_spc += data_spc
946 962
947 963 if data_cspc is None:
948 964 self.__buffer_cspc = None
949 965 else:
950 966 self.__buffer_cspc += data_cspc
951 967
952 968 if data_dc is None:
953 969 self.__buffer_dc = None
954 970 else:
955 971 self.__buffer_dc += data_dc
956 972
957 973 self.__profIndex += 1
958 974
959 975 return
960 976
961 977 def pushData(self):
962 978 """
963 979 Return the sum of the last profiles and the profiles used in the sum.
964 980
965 981 Affected:
966 982
967 983 self.__profileIndex
968 984
969 985 """
970 986
971 987 data_spc = self.__buffer_spc
972 988 data_cspc = self.__buffer_cspc
973 989 data_dc = self.__buffer_dc
974 990 n = self.__profIndex
975 991
976 992 self.__buffer_spc = 0
977 993 self.__buffer_cspc = 0
978 994 self.__buffer_dc = 0
979 995 self.__profIndex = 0
980 996
981 997 return data_spc, data_cspc, data_dc, n
982 998
983 999 def byProfiles(self, *args):
984 1000
985 1001 self.__dataReady = False
986 1002 avgdata_spc = None
987 1003 avgdata_cspc = None
988 1004 avgdata_dc = None
989 1005
990 1006 self.putData(*args)
991 1007
992 1008 if self.__profIndex == self.n:
993 1009
994 1010 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
995 1011 self.n = n
996 1012 self.__dataReady = True
997 1013
998 1014 return avgdata_spc, avgdata_cspc, avgdata_dc
999 1015
1000 1016 def byTime(self, datatime, *args):
1001 1017
1002 1018 self.__dataReady = False
1003 1019 avgdata_spc = None
1004 1020 avgdata_cspc = None
1005 1021 avgdata_dc = None
1006 1022
1007 1023 self.putData(*args)
1008 1024
1009 1025 if (datatime - self.__initime) >= self.__integrationtime:
1010 1026 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1011 1027 self.n = n
1012 1028 self.__dataReady = True
1013 1029
1014 1030 return avgdata_spc, avgdata_cspc, avgdata_dc
1015 1031
1016 1032 def integrate(self, datatime, *args):
1017 1033
1018 1034 if self.__profIndex == 0:
1019 1035 self.__initime = datatime
1020 1036
1021 1037 if self.__byTime:
1022 1038 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
1023 1039 datatime, *args)
1024 1040 else:
1025 1041 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
1026 1042
1027 1043 if not self.__dataReady:
1028 1044 return None, None, None, None
1029 1045
1030 1046 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
1031 1047
1032 1048 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
1033 1049 if n == 1:
1034 1050 return
1035
1051
1036 1052 dataOut.flagNoData = True
1037 1053
1038 1054 if not self.isConfig:
1039 1055 self.setup(n, timeInterval, overlapping)
1040 1056 self.isConfig = True
1041 1057
1042 1058 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
1043 1059 dataOut.data_spc,
1044 1060 dataOut.data_cspc,
1045 1061 dataOut.data_dc)
1046 1062
1047 1063 if self.__dataReady:
1048 1064
1049 1065 dataOut.data_spc = avgdata_spc
1050 1066 dataOut.data_cspc = avgdata_cspc
1051 dataOut.data_dc = avgdata_dc
1067 dataOut.data_dc = avgdata_dc
1052 1068 dataOut.nIncohInt *= self.n
1053 1069 dataOut.utctime = avgdatatime
1054 1070 dataOut.flagNoData = False
1055 1071
1056 return dataOut No newline at end of file
1072 return dataOut
1073
1074
1075 class PulsePair(Operation):
1076 isConfig = False
1077 __profIndex = 0
1078 __profIndex2 = 0
1079 __initime = None
1080 __lastdatatime = None
1081 __buffer = None
1082 __buffer2 = []
1083 __buffer3 = None
1084 __dataReady = False
1085 n = None
1086
1087 __nch =0
1088 __nProf =0
1089 __nHeis =0
1090
1091 def __init__(self,**kwargs):
1092 Operation.__init__(self,**kwargs)
1093
1094 def setup(self,dataOut,n =None, m = None):
1095
1096 self.__initime = None
1097 self.__lastdatatime = 0
1098 self.__buffer = 0
1099 self.__bufferV = 0
1100 #self.__buffer2 = []
1101 self.__buffer3 = 0
1102 self.__dataReady = False
1103 self.__profIndex = 0
1104 self.__profIndex2 = 0
1105 self.count = 0
1106
1107
1108 self.__nch = dataOut.nChannels
1109 self.__nHeis = dataOut.nHeights
1110 self.__nProf = dataOut.nProfiles
1111 self.__nFFT = dataOut.nFFTPoints
1112 #print("Valores de Ch,Samples,Perfiles,nFFT",self.__nch,self.__nHeis,self.__nProf, self.__nFFT)
1113 #print("EL VALOR DE n es:",n)
1114 if n == None:
1115 raise ValueError("n Should be specified.")
1116
1117 if n != None:
1118 if n<2:
1119 raise ValueError("n Should be greather than 2 ")
1120 self.n = n
1121 if m == None:
1122 m = n
1123 if m != None:
1124 if m<2:
1125 raise ValueError("n Should be greather than 2 ")
1126
1127 self.m = m
1128 self.__buffer2 = numpy.zeros((self.__nch,self.m,self.__nHeis))
1129 self.__bufferV2 = numpy.zeros((self.__nch,self.m,self.__nHeis))
1130
1131
1132
1133 def putData(self,data):
1134 #print("###################################################")
1135 '''
1136 data_tmp = numpy.zeros(self.__nch,self.n,self.__nHeis, dtype= complex)
1137 if self.count < self.__nProf:
1138
1139 for i in range(self.n):
1140 data_tmp[:,i,:] = data[:,i+self.count,:]
1141
1142 self.__buffer = data_tmp*numpy.conjugate(data_tmp)
1143
1144
1145 #####self.__buffer = data*numpy.conjugate(data)
1146 #####self.__bufferV = data[:,(self.__nProf-1):,:]*numpy.conjugate(data[:,1:,:])
1147
1148 #self.__buffer2.append(numpy.conjugate(data))
1149
1150 #####self.__profIndex = data.shape[1]
1151 self.count = self.count + self.n -1
1152 self.__profIndex = self.n
1153 '''
1154 self.__buffer = data*numpy.conjugate(data)
1155 self.__bufferV = data[:,(self.__nProf-1):,:]*numpy.conjugate(data[:,1:,:])
1156 self.__profIndex = self.n
1157 return
1158
1159 def pushData(self):
1160
1161 data_I = numpy.zeros((self.__nch,self.__nHeis))
1162 data_IV = numpy.zeros((self.__nch,self.__nHeis))
1163
1164 for i in range(self.__nch):
1165 data_I[i,:] = numpy.sum(numpy.sum(self.__buffer[i],axis=0),axis=0)/self.n
1166 data_IV[i,:] = numpy.sum(numpy.sum(self.__bufferV[i],axis=0),axis=0)/(self.n-1)
1167
1168 n = self.__profIndex
1169 ####data_intensity = numpy.sum(numpy.sum(self.__buffer,axis=0),axis=0)/self.n
1170 #print("data_intensity push data",data_intensity.shape)
1171 #data_velocity = self.__buffer3/(self.n-1)
1172 ####n = self.__profIndex
1173
1174 self.__buffer = 0
1175 self.__buffer3 = 0
1176 self.__profIndex = 0
1177
1178 #return data_intensity,data_velocity,n
1179 return data_I,data_IV,n
1180
1181 def pulsePairbyProfiles(self,data):
1182 self.__dataReady = False
1183 data_intensity = None
1184 data_velocity = None
1185
1186 self.putData(data)
1187
1188 if self.__profIndex == self.n:
1189 #data_intensity,data_velocity,n = self.pushData()
1190 data_intensity,data_velocity,n = self.pushData()
1191 #print(data_intensity.shape)
1192 #print("self.__profIndex2", self.__profIndex2)
1193 if self.__profIndex2 == 0:
1194 #print("PRIMERA VEZ")
1195 #print("self.__buffer2",self.__buffer2)
1196 for i in range(self.__nch):
1197 self.__buffer2[i][self.__profIndex2] = data_intensity[i]
1198 self.__bufferV2[i][self.__profIndex2] = data_velocity[i]
1199 self.__profIndex2 += 1
1200 return None,None
1201
1202 if self.__profIndex2 > 0:
1203 for i in range(self.__nch):
1204 self.__buffer2[i][self.__profIndex2] = data_intensity[i]
1205 self.__bufferV2[i][self.__profIndex2] = data_velocity[i]
1206 #print("Dentro del bucle",self.__buffer2)
1207 self.__profIndex2 += 1
1208 if self.__profIndex2 == self.m :
1209 data_i = self.__buffer2
1210 data_v = self.__bufferV2
1211 #print(data_i.shape)
1212 self.__dataReady = True
1213 self.__profIndex2 = 0
1214 self.__buffer2 = numpy.zeros((self.__nch,self.m,self.__nHeis))
1215 self.__bufferV2 = numpy.zeros((self.__nch,self.m,self.__nHeis))
1216 return data_i,data_v
1217 return None,None
1218
1219 def pulsePairOp(self,data,datatime=None):
1220 if self.__initime == None:
1221 self.__initime = datatime
1222
1223 data_intensity,data_velocity = self.pulsePairbyProfiles(data)
1224 self.__lastdatatime = datatime
1225
1226 if data_intensity is None:
1227 return None,None,None
1228
1229 avgdatatime = self.__initime
1230 self.__initime = datatime
1231
1232 return data_intensity,data_velocity,avgdatatime
1233
1234 def run(self,dataOut,n =None,m=None):
1235
1236 if not self.isConfig:
1237 self.setup(dataOut = dataOut, n = n, m = m)
1238 self.isConfig = True
1239
1240 data_intensity,data_velocity,avgdatatime = self.pulsePairOp(dataOut.data_wr,dataOut.utctime)
1241 dataOut.flagNoData = True
1242
1243 if self.__dataReady:
1244 #print(" DATA " , data_intensity.shape)
1245 #dataOut.data = numpy.array([data_intensity])#aqui amigo revisa
1246 #tmp = numpy.zeros([1,data_intensity.shape[0],data_intensity.shape[1]])
1247 #tmp[0] = data_intensity
1248 dataOut.data = data_intensity
1249 dataOut.data_velocity = data_velocity
1250 #dataOut.data = tmp
1251 #print(" DATA " , dataOut.data.shape)
1252 dataOut.nIncohInt *= self.n
1253 dataOut.nProfiles = self.m
1254 dataOut.nFFTPoints = self.m
1255 #dataOut.data_intensity = data_intensity
1256 dataOut.PRFbyAngle = self.n
1257 dataOut.utctime = avgdatatime
1258 dataOut.flagNoData = False
1259 #####print("TIEMPO: ",dataOut.utctime)
1260 return dataOut
@@ -1,1328 +1,1623
1 1 import sys
2 2 import numpy
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
6 6 from schainpy.utils import log
7 7 from time import time
8 8
9 9
10 10 @MPDecorator
11 class VoltageProc(ProcessingUnit):
12
11 class VoltageProc(ProcessingUnit):
12
13 13 def __init__(self):
14 14
15 15 ProcessingUnit.__init__(self)
16 16
17 17 self.dataOut = Voltage()
18 18 self.flip = 1
19 19 self.setupReq = False
20 20
21 21 def run(self):
22 22
23 23 if self.dataIn.type == 'AMISR':
24 24 self.__updateObjFromAmisrInput()
25 25
26 26 if self.dataIn.type == 'Voltage':
27 27 self.dataOut.copy(self.dataIn)
28 28
29 29 # self.dataOut.copy(self.dataIn)
30 30
31 31 def __updateObjFromAmisrInput(self):
32 32
33 33 self.dataOut.timeZone = self.dataIn.timeZone
34 34 self.dataOut.dstFlag = self.dataIn.dstFlag
35 35 self.dataOut.errorCount = self.dataIn.errorCount
36 36 self.dataOut.useLocalTime = self.dataIn.useLocalTime
37 37
38 38 self.dataOut.flagNoData = self.dataIn.flagNoData
39 39 self.dataOut.data = self.dataIn.data
40 40 self.dataOut.utctime = self.dataIn.utctime
41 41 self.dataOut.channelList = self.dataIn.channelList
42 42 #self.dataOut.timeInterval = self.dataIn.timeInterval
43 43 self.dataOut.heightList = self.dataIn.heightList
44 44 self.dataOut.nProfiles = self.dataIn.nProfiles
45 45
46 46 self.dataOut.nCohInt = self.dataIn.nCohInt
47 47 self.dataOut.ippSeconds = self.dataIn.ippSeconds
48 48 self.dataOut.frequency = self.dataIn.frequency
49 49
50 50 self.dataOut.azimuth = self.dataIn.azimuth
51 51 self.dataOut.zenith = self.dataIn.zenith
52 52
53 53 self.dataOut.beam.codeList = self.dataIn.beam.codeList
54 54 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
55 55 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
56 56 #
57 57 # pass#
58 58 #
59 59 # def init(self):
60 60 #
61 61 #
62 62 # if self.dataIn.type == 'AMISR':
63 63 # self.__updateObjFromAmisrInput()
64 64 #
65 65 # if self.dataIn.type == 'Voltage':
66 66 # self.dataOut.copy(self.dataIn)
67 67 # # No necesita copiar en cada init() los atributos de dataIn
68 68 # # la copia deberia hacerse por cada nuevo bloque de datos
69 69
70 70 def selectChannels(self, channelList):
71 71
72 72 channelIndexList = []
73 73
74 74 for channel in channelList:
75 75 if channel not in self.dataOut.channelList:
76 76 raise ValueError("Channel %d is not in %s" %(channel, str(self.dataOut.channelList)))
77 77
78 78 index = self.dataOut.channelList.index(channel)
79 79 channelIndexList.append(index)
80 80
81 81 self.selectChannelsByIndex(channelIndexList)
82 82
83 83 def selectChannelsByIndex(self, channelIndexList):
84 84 """
85 85 Selecciona un bloque de datos en base a canales segun el channelIndexList
86 86
87 87 Input:
88 88 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
89 89
90 90 Affected:
91 91 self.dataOut.data
92 92 self.dataOut.channelIndexList
93 93 self.dataOut.nChannels
94 94 self.dataOut.m_ProcessingHeader.totalSpectra
95 95 self.dataOut.systemHeaderObj.numChannels
96 96 self.dataOut.m_ProcessingHeader.blockSize
97 97
98 98 Return:
99 99 None
100 100 """
101 101
102 102 for channelIndex in channelIndexList:
103 103 if channelIndex not in self.dataOut.channelIndexList:
104 104 print(channelIndexList)
105 105 raise ValueError("The value %d in channelIndexList is not valid" %channelIndex)
106 106
107 107 if self.dataOut.flagDataAsBlock:
108 108 """
109 109 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
110 110 """
111 111 data = self.dataOut.data[channelIndexList,:,:]
112 112 else:
113 113 data = self.dataOut.data[channelIndexList,:]
114 114
115 115 self.dataOut.data = data
116 116 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
117 117 self.dataOut.channelList = range(len(channelIndexList))
118
118
119 119 return 1
120 120
121 121 def selectHeights(self, minHei=None, maxHei=None):
122 122 """
123 123 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
124 124 minHei <= height <= maxHei
125 125
126 126 Input:
127 127 minHei : valor minimo de altura a considerar
128 128 maxHei : valor maximo de altura a considerar
129 129
130 130 Affected:
131 131 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
132 132
133 133 Return:
134 134 1 si el metodo se ejecuto con exito caso contrario devuelve 0
135 135 """
136 136
137 137 if minHei == None:
138 138 minHei = self.dataOut.heightList[0]
139 139
140 140 if maxHei == None:
141 141 maxHei = self.dataOut.heightList[-1]
142 142
143 143 if (minHei < self.dataOut.heightList[0]):
144 144 minHei = self.dataOut.heightList[0]
145 145
146 146 if (maxHei > self.dataOut.heightList[-1]):
147 147 maxHei = self.dataOut.heightList[-1]
148 148
149 149 minIndex = 0
150 150 maxIndex = 0
151 151 heights = self.dataOut.heightList
152 152
153 153 inda = numpy.where(heights >= minHei)
154 154 indb = numpy.where(heights <= maxHei)
155 155
156 156 try:
157 157 minIndex = inda[0][0]
158 158 except:
159 159 minIndex = 0
160 160
161 161 try:
162 162 maxIndex = indb[0][-1]
163 163 except:
164 164 maxIndex = len(heights)
165 165
166 166 self.selectHeightsByIndex(minIndex, maxIndex)
167 167
168 168 return 1
169 169
170 170
171 171 def selectHeightsByIndex(self, minIndex, maxIndex):
172 172 """
173 173 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
174 174 minIndex <= index <= maxIndex
175 175
176 176 Input:
177 177 minIndex : valor de indice minimo de altura a considerar
178 178 maxIndex : valor de indice maximo de altura a considerar
179 179
180 180 Affected:
181 181 self.dataOut.data
182 182 self.dataOut.heightList
183 183
184 184 Return:
185 185 1 si el metodo se ejecuto con exito caso contrario devuelve 0
186 186 """
187 187
188 188 if (minIndex < 0) or (minIndex > maxIndex):
189 189 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
190 190
191 191 if (maxIndex >= self.dataOut.nHeights):
192 192 maxIndex = self.dataOut.nHeights
193 193
194 194 #voltage
195 195 if self.dataOut.flagDataAsBlock:
196 196 """
197 197 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
198 198 """
199 199 data = self.dataOut.data[:,:, minIndex:maxIndex]
200 200 else:
201 201 data = self.dataOut.data[:, minIndex:maxIndex]
202 202
203 203 # firstHeight = self.dataOut.heightList[minIndex]
204 204
205 205 self.dataOut.data = data
206 206 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
207 207
208 208 if self.dataOut.nHeights <= 1:
209 209 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights))
210 210
211 211 return 1
212 212
213 213
214 214 def filterByHeights(self, window):
215 215
216 216 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
217 217
218 218 if window == None:
219 219 window = (self.dataOut.radarControllerHeaderObj.txA/self.dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
220 220
221 221 newdelta = deltaHeight * window
222 222 r = self.dataOut.nHeights % window
223 223 newheights = (self.dataOut.nHeights-r)/window
224 224
225 225 if newheights <= 1:
226 226 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(self.dataOut.nHeights, window))
227 227
228 228 if self.dataOut.flagDataAsBlock:
229 229 """
230 230 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
231 231 """
232 buffer = self.dataOut.data[:, :, 0:int(self.dataOut.nHeights-r)]
232 buffer = self.dataOut.data[:, :, 0:int(self.dataOut.nHeights-r)]
233 233 buffer = buffer.reshape(self.dataOut.nChannels, self.dataOut.nProfiles, int(self.dataOut.nHeights/window), window)
234 234 buffer = numpy.sum(buffer,3)
235 235
236 236 else:
237 237 buffer = self.dataOut.data[:,0:int(self.dataOut.nHeights-r)]
238 238 buffer = buffer.reshape(self.dataOut.nChannels,int(self.dataOut.nHeights/window),int(window))
239 239 buffer = numpy.sum(buffer,2)
240 240
241 241 self.dataOut.data = buffer
242 242 self.dataOut.heightList = self.dataOut.heightList[0] + numpy.arange( newheights )*newdelta
243 243 self.dataOut.windowOfFilter = window
244 244
245 245 def setH0(self, h0, deltaHeight = None):
246 246
247 247 if not deltaHeight:
248 248 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
249 249
250 250 nHeights = self.dataOut.nHeights
251 251
252 252 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
253 253
254 254 self.dataOut.heightList = newHeiRange
255 255
256 256 def deFlip(self, channelList = []):
257 257
258 258 data = self.dataOut.data.copy()
259 259
260 260 if self.dataOut.flagDataAsBlock:
261 261 flip = self.flip
262 262 profileList = list(range(self.dataOut.nProfiles))
263 263
264 264 if not channelList:
265 265 for thisProfile in profileList:
266 266 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
267 267 flip *= -1.0
268 268 else:
269 269 for thisChannel in channelList:
270 270 if thisChannel not in self.dataOut.channelList:
271 271 continue
272 272
273 273 for thisProfile in profileList:
274 274 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
275 275 flip *= -1.0
276 276
277 277 self.flip = flip
278 278
279 279 else:
280 280 if not channelList:
281 281 data[:,:] = data[:,:]*self.flip
282 282 else:
283 283 for thisChannel in channelList:
284 284 if thisChannel not in self.dataOut.channelList:
285 285 continue
286 286
287 287 data[thisChannel,:] = data[thisChannel,:]*self.flip
288 288
289 289 self.flip *= -1.
290 290
291 291 self.dataOut.data = data
292 292
293 293 def setRadarFrequency(self, frequency=None):
294 294
295 295 if frequency != None:
296 296 self.dataOut.frequency = frequency
297 297
298 298 return 1
299 299
300 300 def interpolateHeights(self, topLim, botLim):
301 301 #69 al 72 para julia
302 302 #82-84 para meteoros
303 303 if len(numpy.shape(self.dataOut.data))==2:
304 304 sampInterp = (self.dataOut.data[:,botLim-1] + self.dataOut.data[:,topLim+1])/2
305 305 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
306 306 #self.dataOut.data[:,botLim:limSup+1] = sampInterp
307 307 self.dataOut.data[:,botLim:topLim+1] = sampInterp
308 308 else:
309 309 nHeights = self.dataOut.data.shape[2]
310 310 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
311 311 y = self.dataOut.data[:,:,list(range(botLim))+list(range(topLim+1,nHeights))]
312 312 f = interpolate.interp1d(x, y, axis = 2)
313 313 xnew = numpy.arange(botLim,topLim+1)
314 314 ynew = f(xnew)
315 315
316 316 self.dataOut.data[:,:,botLim:topLim+1] = ynew
317 317
318 318 # import collections
319 319
320 320 class CohInt(Operation):
321 321
322 322 isConfig = False
323 323 __profIndex = 0
324 324 __byTime = False
325 325 __initime = None
326 326 __lastdatatime = None
327 327 __integrationtime = None
328 328 __buffer = None
329 329 __bufferStride = []
330 330 __dataReady = False
331 331 __profIndexStride = 0
332 332 __dataToPutStride = False
333 333 n = None
334 334
335 335 def __init__(self, **kwargs):
336 336
337 337 Operation.__init__(self, **kwargs)
338 338
339 339 # self.isConfig = False
340 340
341 341 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
342 342 """
343 343 Set the parameters of the integration class.
344 344
345 345 Inputs:
346 346
347 347 n : Number of coherent integrations
348 348 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
349 349 overlapping :
350 350 """
351 351
352 352 self.__initime = None
353 353 self.__lastdatatime = 0
354 354 self.__buffer = None
355 355 self.__dataReady = False
356 356 self.byblock = byblock
357 357 self.stride = stride
358 358
359 359 if n == None and timeInterval == None:
360 360 raise ValueError("n or timeInterval should be specified ...")
361 361
362 362 if n != None:
363 363 self.n = n
364 364 self.__byTime = False
365 365 else:
366 366 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
367 367 self.n = 9999
368 368 self.__byTime = True
369 369
370 370 if overlapping:
371 371 self.__withOverlapping = True
372 372 self.__buffer = None
373 373 else:
374 374 self.__withOverlapping = False
375 375 self.__buffer = 0
376 376
377 377 self.__profIndex = 0
378 378
379 379 def putData(self, data):
380 380
381 381 """
382 382 Add a profile to the __buffer and increase in one the __profileIndex
383 383
384 384 """
385 385
386 386 if not self.__withOverlapping:
387 print("inside over")
387 388 self.__buffer += data.copy()
388 389 self.__profIndex += 1
389 390 return
390 391
391 392 #Overlapping data
392 393 nChannels, nHeis = data.shape
394 print("show me the light",data.shape)
393 395 data = numpy.reshape(data, (1, nChannels, nHeis))
394
396 print(data.shape)
395 397 #If the buffer is empty then it takes the data value
396 398 if self.__buffer is None:
397 399 self.__buffer = data
398 400 self.__profIndex += 1
399 401 return
400 402
401 403 #If the buffer length is lower than n then stakcing the data value
402 404 if self.__profIndex < self.n:
403 405 self.__buffer = numpy.vstack((self.__buffer, data))
404 406 self.__profIndex += 1
405 407 return
406 408
407 409 #If the buffer length is equal to n then replacing the last buffer value with the data value
408 410 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
409 411 self.__buffer[self.n-1] = data
410 412 self.__profIndex = self.n
411 413 return
412 414
413 415
414 416 def pushData(self):
415 417 """
416 418 Return the sum of the last profiles and the profiles used in the sum.
417 419
418 420 Affected:
419 421
420 422 self.__profileIndex
421 423
422 424 """
423 425
424 426 if not self.__withOverlapping:
427 #print("ahora que fue")
425 428 data = self.__buffer
426 429 n = self.__profIndex
427 430
428 431 self.__buffer = 0
429 432 self.__profIndex = 0
430 433
431 434 return data, n
432 435
436 #print("cual funciona")
433 437 #Integration with Overlapping
434 438 data = numpy.sum(self.__buffer, axis=0)
435 439 # print data
436 440 # raise
437 441 n = self.__profIndex
438 442
439 443 return data, n
440 444
441 445 def byProfiles(self, data):
442 446
443 447 self.__dataReady = False
444 448 avgdata = None
445 449 # n = None
446 450 # print data
447 451 # raise
452 #print("beforeputdata")
448 453 self.putData(data)
449 454
450 455 if self.__profIndex == self.n:
451 456 avgdata, n = self.pushData()
452 457 self.__dataReady = True
453 458
454 459 return avgdata
455 460
456 461 def byTime(self, data, datatime):
457 462
458 463 self.__dataReady = False
459 464 avgdata = None
460 465 n = None
461 466
462 467 self.putData(data)
463 468
464 469 if (datatime - self.__initime) >= self.__integrationtime:
465 470 avgdata, n = self.pushData()
466 471 self.n = n
467 472 self.__dataReady = True
468 473
469 474 return avgdata
470 475
471 476 def integrateByStride(self, data, datatime):
472 477 # print data
473 478 if self.__profIndex == 0:
474 479 self.__buffer = [[data.copy(), datatime]]
475 480 else:
476 481 self.__buffer.append([data.copy(),datatime])
477 482 self.__profIndex += 1
478 483 self.__dataReady = False
479 484
480 485 if self.__profIndex == self.n * self.stride :
481 486 self.__dataToPutStride = True
482 487 self.__profIndexStride = 0
483 488 self.__profIndex = 0
484 489 self.__bufferStride = []
485 490 for i in range(self.stride):
486 491 current = self.__buffer[i::self.stride]
487 492 data = numpy.sum([t[0] for t in current], axis=0)
488 493 avgdatatime = numpy.average([t[1] for t in current])
489 494 # print data
490 495 self.__bufferStride.append((data, avgdatatime))
491 496
492 497 if self.__dataToPutStride:
493 498 self.__dataReady = True
494 499 self.__profIndexStride += 1
495 500 if self.__profIndexStride == self.stride:
496 501 self.__dataToPutStride = False
497 502 # print self.__bufferStride[self.__profIndexStride - 1]
498 503 # raise
499 504 return self.__bufferStride[self.__profIndexStride - 1]
500
501
505
506
502 507 return None, None
503 508
504 509 def integrate(self, data, datatime=None):
505 510
506 511 if self.__initime == None:
507 512 self.__initime = datatime
508 513
509 514 if self.__byTime:
510 515 avgdata = self.byTime(data, datatime)
511 516 else:
512 517 avgdata = self.byProfiles(data)
513 518
514 519
515 520 self.__lastdatatime = datatime
516 521
517 522 if avgdata is None:
518 523 return None, None
519 524
520 525 avgdatatime = self.__initime
521 526
522 527 deltatime = datatime - self.__lastdatatime
523
528
524 529 if not self.__withOverlapping:
525 530 self.__initime = datatime
526 531 else:
527 532 self.__initime += deltatime
528 533
529 534 return avgdata, avgdatatime
530 535
531 536 def integrateByBlock(self, dataOut):
532 537
533 538 times = int(dataOut.data.shape[1]/self.n)
534 539 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
535 540
536 541 id_min = 0
537 542 id_max = self.n
538 543
539 544 for i in range(times):
540 545 junk = dataOut.data[:,id_min:id_max,:]
541 546 avgdata[:,i,:] = junk.sum(axis=1)
542 547 id_min += self.n
543 548 id_max += self.n
544 549
545 550 timeInterval = dataOut.ippSeconds*self.n
546 551 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
547 552 self.__dataReady = True
548 553 return avgdata, avgdatatime
549
554
550 555 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
551 556
552 557 if not self.isConfig:
553 558 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
554 559 self.isConfig = True
555 560
556 561 if dataOut.flagDataAsBlock:
557 562 """
558 563 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
559 564 """
560 565 avgdata, avgdatatime = self.integrateByBlock(dataOut)
561 566 dataOut.nProfiles /= self.n
562 567 else:
563 if stride is None:
568 if stride is None:
564 569 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
565 570 else:
566 571 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
567 572
568
573
569 574 # dataOut.timeInterval *= n
570 575 dataOut.flagNoData = True
571 576
572 577 if self.__dataReady:
573 578 dataOut.data = avgdata
574 579 dataOut.nCohInt *= self.n
575 580 dataOut.utctime = avgdatatime
576 581 # print avgdata, avgdatatime
577 582 # raise
578 583 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
579 584 dataOut.flagNoData = False
580 585 return dataOut
581 586
582 587 class Decoder(Operation):
583 588
584 589 isConfig = False
585 590 __profIndex = 0
586 591
587 592 code = None
588 593
589 594 nCode = None
590 595 nBaud = None
591 596
592 597 def __init__(self, **kwargs):
593 598
594 599 Operation.__init__(self, **kwargs)
595 600
596 601 self.times = None
597 602 self.osamp = None
598 603 # self.__setValues = False
599 604 self.isConfig = False
600 605 self.setupReq = False
601 606 def setup(self, code, osamp, dataOut):
602 607
603 608 self.__profIndex = 0
604 609
605 610 self.code = code
606 611
607 612 self.nCode = len(code)
608 613 self.nBaud = len(code[0])
609 614
610 615 if (osamp != None) and (osamp >1):
611 616 self.osamp = osamp
612 617 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
613 618 self.nBaud = self.nBaud*self.osamp
614 619
615 620 self.__nChannels = dataOut.nChannels
616 621 self.__nProfiles = dataOut.nProfiles
617 622 self.__nHeis = dataOut.nHeights
618 623
619 624 if self.__nHeis < self.nBaud:
620 625 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
621 626
622 627 #Frequency
623 628 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
624 629
625 630 __codeBuffer[:,0:self.nBaud] = self.code
626 631
627 632 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
628 633
629 634 if dataOut.flagDataAsBlock:
630 635
631 636 self.ndatadec = self.__nHeis #- self.nBaud + 1
632 637
633 638 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
634 639
635 640 else:
636 641
637 642 #Time
638 643 self.ndatadec = self.__nHeis #- self.nBaud + 1
639 644
640 645 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
641 646
642 647 def __convolutionInFreq(self, data):
643 648
644 649 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
645 650
646 651 fft_data = numpy.fft.fft(data, axis=1)
647 652
648 653 conv = fft_data*fft_code
649 654
650 655 data = numpy.fft.ifft(conv,axis=1)
651 656
652 657 return data
653 658
654 659 def __convolutionInFreqOpt(self, data):
655 660
656 661 raise NotImplementedError
657 662
658 663 def __convolutionInTime(self, data):
659 664
660 665 code = self.code[self.__profIndex]
661 666 for i in range(self.__nChannels):
662 667 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
663 668
664 669 return self.datadecTime
665 670
666 671 def __convolutionByBlockInTime(self, data):
667 672
668 673 repetitions = int(self.__nProfiles / self.nCode)
669 674 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
670 675 junk = junk.flatten()
671 676 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
672 677 profilesList = range(self.__nProfiles)
673
674 for i in range(self.__nChannels):
675 for j in profilesList:
676 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
677 return self.datadecTime
678
679 for i in range(self.__nChannels):
680 for j in profilesList:
681 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
682 return self.datadecTime
678 683
679 684 def __convolutionByBlockInFreq(self, data):
680 685
681 686 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
682 687
683 688
684 689 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
685 690
686 691 fft_data = numpy.fft.fft(data, axis=2)
687 692
688 693 conv = fft_data*fft_code
689 694
690 695 data = numpy.fft.ifft(conv,axis=2)
691 696
692 697 return data
693 698
694
699
695 700 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
696 701
697 702 if dataOut.flagDecodeData:
698 703 print("This data is already decoded, recoding again ...")
699 704
700 705 if not self.isConfig:
701 706
702 707 if code is None:
703 708 if dataOut.code is None:
704 709 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
705 710
706 711 code = dataOut.code
707 712 else:
708 713 code = numpy.array(code).reshape(nCode,nBaud)
709 714 self.setup(code, osamp, dataOut)
710 715
711 716 self.isConfig = True
712 717
713 718 if mode == 3:
714 719 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
715 720
716 721 if times != None:
717 722 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
718 723
719 724 if self.code is None:
720 725 print("Fail decoding: Code is not defined.")
721 726 return
722 727
723 728 self.__nProfiles = dataOut.nProfiles
724 729 datadec = None
725
730
726 731 if mode == 3:
727 732 mode = 0
728 733
729 734 if dataOut.flagDataAsBlock:
730 735 """
731 736 Decoding when data have been read as block,
732 737 """
733 738
734 739 if mode == 0:
735 740 datadec = self.__convolutionByBlockInTime(dataOut.data)
736 741 if mode == 1:
737 742 datadec = self.__convolutionByBlockInFreq(dataOut.data)
738 743 else:
739 744 """
740 745 Decoding when data have been read profile by profile
741 746 """
742 747 if mode == 0:
743 748 datadec = self.__convolutionInTime(dataOut.data)
744 749
745 750 if mode == 1:
746 751 datadec = self.__convolutionInFreq(dataOut.data)
747 752
748 753 if mode == 2:
749 754 datadec = self.__convolutionInFreqOpt(dataOut.data)
750 755
751 756 if datadec is None:
752 757 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
753 758
754 759 dataOut.code = self.code
755 760 dataOut.nCode = self.nCode
756 761 dataOut.nBaud = self.nBaud
757 762
758 763 dataOut.data = datadec
759 764
760 765 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
761 766
762 767 dataOut.flagDecodeData = True #asumo q la data esta decodificada
763 768
764 769 if self.__profIndex == self.nCode-1:
765 770 self.__profIndex = 0
766 771 return dataOut
767 772
768 773 self.__profIndex += 1
769 774
770 775 return dataOut
771 776 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
772 777
773 778
774 779 class ProfileConcat(Operation):
775 780
776 781 isConfig = False
777 782 buffer = None
778 783
779 784 def __init__(self, **kwargs):
780 785
781 786 Operation.__init__(self, **kwargs)
782 787 self.profileIndex = 0
783 788
784 789 def reset(self):
785 790 self.buffer = numpy.zeros_like(self.buffer)
786 791 self.start_index = 0
787 792 self.times = 1
788 793
789 794 def setup(self, data, m, n=1):
790 795 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
791 796 self.nHeights = data.shape[1]#.nHeights
792 797 self.start_index = 0
793 798 self.times = 1
794 799
795 800 def concat(self, data):
796 801
797 802 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
798 803 self.start_index = self.start_index + self.nHeights
799 804
800 805 def run(self, dataOut, m):
801 806 dataOut.flagNoData = True
802 807
803 808 if not self.isConfig:
804 809 self.setup(dataOut.data, m, 1)
805 810 self.isConfig = True
806 811
807 812 if dataOut.flagDataAsBlock:
808 813 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
809 814
810 815 else:
811 816 self.concat(dataOut.data)
812 817 self.times += 1
813 818 if self.times > m:
814 819 dataOut.data = self.buffer
815 820 self.reset()
816 821 dataOut.flagNoData = False
817 822 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
818 823 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
819 824 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
820 825 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
821 826 dataOut.ippSeconds *= m
822 827 return dataOut
823 828
824 829 class ProfileSelector(Operation):
825 830
826 831 profileIndex = None
827 832 # Tamanho total de los perfiles
828 833 nProfiles = None
829 834
830 835 def __init__(self, **kwargs):
831 836
832 837 Operation.__init__(self, **kwargs)
833 838 self.profileIndex = 0
834 839
835 840 def incProfileIndex(self):
836 841
837 842 self.profileIndex += 1
838 843
839 844 if self.profileIndex >= self.nProfiles:
840 845 self.profileIndex = 0
841 846
842 847 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
843 848
844 849 if profileIndex < minIndex:
845 850 return False
846 851
847 852 if profileIndex > maxIndex:
848 853 return False
849 854
850 855 return True
851 856
852 857 def isThisProfileInList(self, profileIndex, profileList):
853 858
854 859 if profileIndex not in profileList:
855 860 return False
856 861
857 862 return True
858 863
859 864 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
860 865
861 866 """
862 867 ProfileSelector:
863 868
864 869 Inputs:
865 870 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
866 871
867 872 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
868 873
869 874 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
870 875
871 876 """
872 877
873 878 if rangeList is not None:
874 879 if type(rangeList[0]) not in (tuple, list):
875 880 rangeList = [rangeList]
876 881
877 882 dataOut.flagNoData = True
878 883
879 884 if dataOut.flagDataAsBlock:
880 885 """
881 886 data dimension = [nChannels, nProfiles, nHeis]
882 887 """
883 888 if profileList != None:
884 889 dataOut.data = dataOut.data[:,profileList,:]
885 890
886 891 if profileRangeList != None:
887 892 minIndex = profileRangeList[0]
888 893 maxIndex = profileRangeList[1]
889 894 profileList = list(range(minIndex, maxIndex+1))
890 895
891 896 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
892 897
893 898 if rangeList != None:
894 899
895 900 profileList = []
896 901
897 902 for thisRange in rangeList:
898 903 minIndex = thisRange[0]
899 904 maxIndex = thisRange[1]
900 905
901 906 profileList.extend(list(range(minIndex, maxIndex+1)))
902 907
903 908 dataOut.data = dataOut.data[:,profileList,:]
904 909
905 910 dataOut.nProfiles = len(profileList)
906 911 dataOut.profileIndex = dataOut.nProfiles - 1
907 912 dataOut.flagNoData = False
908 913
909 914 return dataOut
910 915
911 916 """
912 917 data dimension = [nChannels, nHeis]
913 918 """
914 919
915 920 if profileList != None:
916 921
917 922 if self.isThisProfileInList(dataOut.profileIndex, profileList):
918 923
919 924 self.nProfiles = len(profileList)
920 925 dataOut.nProfiles = self.nProfiles
921 926 dataOut.profileIndex = self.profileIndex
922 927 dataOut.flagNoData = False
923 928
924 929 self.incProfileIndex()
925 930 return dataOut
926 931
927 932 if profileRangeList != None:
928 933
929 934 minIndex = profileRangeList[0]
930 935 maxIndex = profileRangeList[1]
931 936
932 937 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
933 938
934 939 self.nProfiles = maxIndex - minIndex + 1
935 940 dataOut.nProfiles = self.nProfiles
936 941 dataOut.profileIndex = self.profileIndex
937 942 dataOut.flagNoData = False
938 943
939 944 self.incProfileIndex()
940 945 return dataOut
941 946
942 947 if rangeList != None:
943 948
944 949 nProfiles = 0
945 950
946 951 for thisRange in rangeList:
947 952 minIndex = thisRange[0]
948 953 maxIndex = thisRange[1]
949 954
950 955 nProfiles += maxIndex - minIndex + 1
951 956
952 957 for thisRange in rangeList:
953 958
954 959 minIndex = thisRange[0]
955 960 maxIndex = thisRange[1]
956 961
957 962 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
958 963
959 964 self.nProfiles = nProfiles
960 965 dataOut.nProfiles = self.nProfiles
961 966 dataOut.profileIndex = self.profileIndex
962 967 dataOut.flagNoData = False
963 968
964 969 self.incProfileIndex()
965 970
966 971 break
967 972
968 973 return dataOut
969 974
970 975
971 976 if beam != None: #beam is only for AMISR data
972 977 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
973 978 dataOut.flagNoData = False
974 979 dataOut.profileIndex = self.profileIndex
975 980
976 981 self.incProfileIndex()
977 982
978 983 return dataOut
979 984
980 985 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
981 986
982 987 #return False
983 988 return dataOut
984 989
985 990 class Reshaper(Operation):
986 991
987 992 def __init__(self, **kwargs):
988 993
989 994 Operation.__init__(self, **kwargs)
990 995
991 996 self.__buffer = None
992 997 self.__nitems = 0
993 998
994 999 def __appendProfile(self, dataOut, nTxs):
995 1000
996 1001 if self.__buffer is None:
997 1002 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
998 1003 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
999 1004
1000 1005 ini = dataOut.nHeights * self.__nitems
1001 1006 end = ini + dataOut.nHeights
1002 1007
1003 1008 self.__buffer[:, ini:end] = dataOut.data
1004 1009
1005 1010 self.__nitems += 1
1006 1011
1007 1012 return int(self.__nitems*nTxs)
1008 1013
1009 1014 def __getBuffer(self):
1010 1015
1011 1016 if self.__nitems == int(1./self.__nTxs):
1012 1017
1013 1018 self.__nitems = 0
1014 1019
1015 1020 return self.__buffer.copy()
1016 1021
1017 1022 return None
1018 1023
1019 1024 def __checkInputs(self, dataOut, shape, nTxs):
1020 1025
1021 1026 if shape is None and nTxs is None:
1022 1027 raise ValueError("Reshaper: shape of factor should be defined")
1023 1028
1024 1029 if nTxs:
1025 1030 if nTxs < 0:
1026 1031 raise ValueError("nTxs should be greater than 0")
1027 1032
1028 1033 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1029 1034 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
1030 1035
1031 1036 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1032 1037
1033 1038 return shape, nTxs
1034 1039
1035 1040 if len(shape) != 2 and len(shape) != 3:
1036 1041 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))
1037 1042
1038 1043 if len(shape) == 2:
1039 1044 shape_tuple = [dataOut.nChannels]
1040 1045 shape_tuple.extend(shape)
1041 1046 else:
1042 1047 shape_tuple = list(shape)
1043 1048
1044 1049 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1045 1050
1046 1051 return shape_tuple, nTxs
1047 1052
1048 1053 def run(self, dataOut, shape=None, nTxs=None):
1049 1054
1050 1055 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1051 1056
1052 1057 dataOut.flagNoData = True
1053 1058 profileIndex = None
1054 1059
1055 1060 if dataOut.flagDataAsBlock:
1056 1061
1057 1062 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1058 1063 dataOut.flagNoData = False
1059 1064
1060 1065 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1061 1066
1062 1067 else:
1063 1068
1064 1069 if self.__nTxs < 1:
1065 1070
1066 1071 self.__appendProfile(dataOut, self.__nTxs)
1067 1072 new_data = self.__getBuffer()
1068 1073
1069 1074 if new_data is not None:
1070 1075 dataOut.data = new_data
1071 1076 dataOut.flagNoData = False
1072 1077
1073 1078 profileIndex = dataOut.profileIndex*nTxs
1074 1079
1075 1080 else:
1076 1081 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
1077 1082
1078 1083 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1079 1084
1080 1085 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1081 1086
1082 1087 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1083 1088
1084 1089 dataOut.profileIndex = profileIndex
1085 1090
1086 1091 dataOut.ippSeconds /= self.__nTxs
1087 1092
1088 1093 return dataOut
1089 1094
1090 1095 class SplitProfiles(Operation):
1091 1096
1092 1097 def __init__(self, **kwargs):
1093 1098
1094 1099 Operation.__init__(self, **kwargs)
1095 1100
1096 1101 def run(self, dataOut, n):
1097 1102
1098 1103 dataOut.flagNoData = True
1099 1104 profileIndex = None
1100 1105
1101 1106 if dataOut.flagDataAsBlock:
1102 1107
1103 1108 #nchannels, nprofiles, nsamples
1104 1109 shape = dataOut.data.shape
1105 1110
1106 1111 if shape[2] % n != 0:
1107 1112 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1108
1113
1109 1114 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1110
1115
1111 1116 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1112 1117 dataOut.flagNoData = False
1113 1118
1114 1119 profileIndex = int(dataOut.nProfiles/n) - 1
1115 1120
1116 1121 else:
1117 1122
1118 1123 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
1119 1124
1120 1125 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1121 1126
1122 1127 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1123 1128
1124 1129 dataOut.nProfiles = int(dataOut.nProfiles*n)
1125 1130
1126 1131 dataOut.profileIndex = profileIndex
1127 1132
1128 1133 dataOut.ippSeconds /= n
1129 1134
1130 1135 return dataOut
1131 1136
1132 1137 class CombineProfiles(Operation):
1133 1138 def __init__(self, **kwargs):
1134 1139
1135 1140 Operation.__init__(self, **kwargs)
1136 1141
1137 1142 self.__remData = None
1138 1143 self.__profileIndex = 0
1139 1144
1140 1145 def run(self, dataOut, n):
1141 1146
1142 1147 dataOut.flagNoData = True
1143 1148 profileIndex = None
1144 1149
1145 1150 if dataOut.flagDataAsBlock:
1146 1151
1147 1152 #nchannels, nprofiles, nsamples
1148 1153 shape = dataOut.data.shape
1149 1154 new_shape = shape[0], shape[1]/n, shape[2]*n
1150 1155
1151 1156 if shape[1] % n != 0:
1152 1157 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
1153 1158
1154 1159 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1155 1160 dataOut.flagNoData = False
1156 1161
1157 1162 profileIndex = int(dataOut.nProfiles*n) - 1
1158 1163
1159 1164 else:
1160 1165
1161 1166 #nchannels, nsamples
1162 1167 if self.__remData is None:
1163 1168 newData = dataOut.data
1164 1169 else:
1165 1170 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1166 1171
1167 1172 self.__profileIndex += 1
1168 1173
1169 1174 if self.__profileIndex < n:
1170 1175 self.__remData = newData
1171 1176 #continue
1172 1177 return
1173 1178
1174 1179 self.__profileIndex = 0
1175 1180 self.__remData = None
1176 1181
1177 1182 dataOut.data = newData
1178 1183 dataOut.flagNoData = False
1179 1184
1180 1185 profileIndex = dataOut.profileIndex/n
1181 1186
1182 1187
1183 1188 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1184 1189
1185 1190 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1186 1191
1187 1192 dataOut.nProfiles = int(dataOut.nProfiles/n)
1188 1193
1189 1194 dataOut.profileIndex = profileIndex
1190 1195
1191 1196 dataOut.ippSeconds *= n
1192 1197
1193 1198 return dataOut
1199
1200
1201
1202 class CreateBlockVoltage(Operation):
1203
1204 isConfig = False
1205 __Index = 0
1206 bufferShape = None
1207 buffer = None
1208 firstdatatime = None
1209
1210 def __init__(self,**kwargs):
1211 Operation.__init__(self,**kwargs)
1212 self.isConfig = False
1213 self.__Index = 0
1214 self.firstdatatime = None
1215
1216 def setup(self,dataOut, m = None ):
1217 '''
1218 m= Numero perfiles
1219 '''
1220 #print("CONFIGURANDO CBV")
1221 self.__nChannels = dataOut.nChannels
1222 self.__nHeis = dataOut.nHeights
1223 shape = dataOut.data.shape #nchannels, nprofiles, nsamples
1224 #print("input nChannels",self.__nChannels)
1225 #print("input nHeis",self.__nHeis)
1226 #print("SETUP CREATE BLOCK VOLTAGE")
1227 #print("input Shape",shape)
1228 #print("dataOut.nProfiles",dataOut.nProfiles)
1229 numberSamples = self.__nHeis
1230 numberProfile = int(m)
1231 dataOut.nProfiles = numberProfile
1232 #print("new numberProfile",numberProfile)
1233 #print("new numberSamples",numberSamples)
1234
1235 self.bufferShape = shape[0], numberProfile, numberSamples # nchannels,nprofiles,nsamples
1236 self.buffer = numpy.zeros((self.bufferShape))
1237 self.bufferVel = numpy.zeros((self.bufferShape))
1238
1239 def run(self, dataOut, m=None):
1240 #print("RUN")
1241 dataOut.flagNoData = True
1242 dataOut.flagDataAsBlock = False
1243 #print("BLOCK INDEX ",self.__Index)
1244
1245 if not self.isConfig:
1246 self.setup(dataOut, m= m)
1247 self.isConfig = True
1248 if self.__Index < m:
1249 #print("PROFINDEX BLOCK CBV",self.__Index)
1250 self.buffer[:,self.__Index,:] = dataOut.data
1251 self.bufferVel[:,self.__Index,:] = dataOut.data_velocity
1252 self.__Index += 1
1253 dataOut.flagNoData = True
1254
1255 if self.firstdatatime == None:
1256 self.firstdatatime = dataOut.utctime
1257
1258 if self.__Index == m:
1259 #print("**********************************************")
1260 #print("self.buffer.shape ",self.buffer.shape)
1261 #print("##############",self.firstdatatime)
1262 ##print("*********************************************")
1263 ##print("*********************************************")
1264 ##print("******* nProfiles *******", dataOut.nProfiles)
1265 ##print("*********************************************")
1266 ##print("*********************************************")
1267 dataOut.data = self.buffer
1268 dataOut.data_velocity = self.bufferVel
1269 dataOut.utctime = self.firstdatatime
1270 dataOut.nProfiles = m
1271 self.firstdatatime = None
1272 dataOut.flagNoData = False
1273 dataOut.flagDataAsBlock = True
1274 self.__Index = 0
1275 dataOut.identifierWR = True
1276 return dataOut
1277
1278 class PulsePairVoltage(Operation):
1279 '''
1280 Function PulsePair(Signal Power, Velocity)
1281 The real component of Lag[0] provides Intensity Information
1282 The imag component of Lag[1] Phase provides Velocity Information
1283
1284 Configuration Parameters:
1285 nPRF = Number of Several PRF
1286 theta = Degree Azimuth angel Boundaries
1287
1288 Input:
1289 self.dataOut
1290 lag[N]
1291 Affected:
1292 self.dataOut.spc
1293 '''
1294 isConfig = False
1295 __profIndex = 0
1296 __initime = None
1297 __lastdatatime = None
1298 __buffer = None
1299 __buffer2 = []
1300 __buffer3 = None
1301 __dataReady = False
1302 n = None
1303 __nch = 0
1304 __nHeis = 0
1305
1306 def __init__(self,**kwargs):
1307 Operation.__init__(self,**kwargs)
1308
1309 def setup(self, dataOut, n = None ):
1310 '''
1311 n= Numero de PRF's de entrada
1312 '''
1313 self.__initime = None
1314 self.__lastdatatime = 0
1315 self.__dataReady = False
1316 self.__buffer = 0
1317 self.__buffer2 = []
1318 self.__buffer3 = 0
1319 self.__profIndex = 0
1320
1321 self.__nch = dataOut.nChannels
1322 self.__nHeis = dataOut.nHeights
1323
1324 print("ELVALOR DE n es:", n)
1325 if n == None:
1326 raise ValueError("n should be specified.")
1327
1328 if n != None:
1329 if n<2:
1330 raise ValueError("n should be greater than 2")
1331
1332 self.n = n
1333 self.__nProf = n
1334 '''
1335 if overlapping:
1336 self.__withOverlapping = True
1337 self.__buffer = None
1338
1339 else:
1340 #print ("estoy sin __withO")
1341 self.__withOverlapping = False
1342 self.__buffer = 0
1343 self.__buffer2 = []
1344 self.__buffer3 = 0
1345 '''
1346
1347 def putData(self,data):
1348 '''
1349 Add a profile to he __buffer and increase in one the __profiel Index
1350 '''
1351 #print("self.__profIndex :",self.__profIndex)
1352 self.__buffer += data*numpy.conjugate(data)
1353 self.__buffer2.append(numpy.conjugate(data))
1354 if self.__profIndex > 0:
1355 self.__buffer3 += self.__buffer2[self.__profIndex-1]*data
1356 self.__profIndex += 1
1357 return
1358 '''
1359 if not self.__withOverlapping:
1360 #print("Putdata inside over")
1361 self.__buffer += data* numpy.conjugate(data)
1362 self.__buffer2.append(numpy.conjugate(data))
1363
1364 if self.__profIndex >0:
1365 self.__buffer3 += self.__buffer2[self.__profIndex-1]*data
1366 self.__profIndex += 1
1367 return
1368
1369 if self.__buffer is None:
1370 #print("aqui bro")
1371 self.__buffer = data* numpy.conjugate(data)
1372 self.__buffer2.append(numpy.conjugate(data))
1373 self.__profIndex += 1
1374
1375 return
1376
1377 if self.__profIndex < self.n:
1378 self.__buffer = numpy.vstack(self.__buffer,data* numpy.conjugate(data))
1379 self.__buffer2.append(numpy.conjugate(data))
1380
1381 if self.__profIndex == 1:
1382 self.__buffer3 = self.__buffer2[self.__profIndex -1] * data
1383 else:
1384 self.__buffer3 = numpy.vstack(self.__buffer3, self.__buffer2[self.profIndex-1]*data)
1385
1386 self.__profIndex += 1
1387 return
1388 '''
1389
1390 def pushData(self):
1391 '''
1392 Return the PULSEPAIR and the profiles used in the operation
1393 Affected : self.__profileIndex
1394 '''
1395 #print("************************************************")
1396 #print("push data int vel n")
1397 data_intensity = self.__buffer/self.n
1398 data_velocity = self.__buffer3/(self.n-1)
1399 n = self.__profIndex
1400
1401 self.__buffer = 0
1402 self.__buffer2 = []
1403 self.__buffer3 = 0
1404 self.__profIndex = 0
1405
1406 return data_intensity, data_velocity,n
1407 '''
1408 if not self.__withOverlapping:
1409 #print("ahora que fue")
1410 data_intensity = self.__buffer/self.n
1411 data_velocity = self.__buffer3/(self.n-1)
1412 n = self.__profIndex
1413
1414 self.__buffer = 0
1415 self.__buffer2 = []
1416 self.__buffer3 = 0
1417 self.__profIndex = 0
1418 return data_intensity, data_velocity,n
1419
1420 data_intensity = numpy.sum(self.__buffer,axis = 0)
1421 data_velocity = numpy.sum(self.__buffer3,axis = 0)
1422 n = self.__profIndex
1423 #self.__buffer = 0
1424 #self.__buffer2 = []
1425 #self.__buffer3 = 0
1426 #self.__profIndex = 0
1427 return data_intensity, data_velocity,n
1428 '''
1429
1430 def pulsePairbyProfiles(self,data):
1431
1432 self.__dataReady = False
1433 data_intensity = None
1434 data_velocity = None
1435 #print("beforeputada")
1436 self.putData(data)
1437 #print("ProfileIndex:",self.__profIndex)
1438 if self.__profIndex == self.n:
1439 data_intensity, data_velocity, n = self.pushData()
1440 self.__dataReady = True
1441 #print("-----------------------------------------------")
1442 #print("data_intensity",data_intensity.shape,"data_velocity",data_velocity.shape)
1443 return data_intensity, data_velocity
1444
1445 def pulsePairOp(self, data, datatime= None):
1446
1447 if self.__initime == None:
1448 self.__initime = datatime
1449
1450 data_intensity, data_velocity = self.pulsePairbyProfiles(data)
1451 self.__lastdatatime = datatime
1452
1453 if data_intensity is None:
1454 return None, None, None
1455
1456 avgdatatime = self.__initime
1457 deltatime = datatime - self.__lastdatatime
1458 self.__initime = datatime
1459 '''
1460 if not self.__withOverlapping:
1461 self.__initime = datatime
1462 else:
1463 self.__initime += deltatime
1464 '''
1465 return data_intensity, data_velocity, avgdatatime
1466
1467 def run(self, dataOut,n = None, overlapping= False,**kwargs):
1468
1469 if not self.isConfig:
1470 self.setup(dataOut = dataOut, n = n , **kwargs)
1471 self.isConfig = True
1472 #print("*******************")
1473 #print("print Shape input data:",dataOut.data.shape)
1474 data_intensity, data_velocity, avgdatatime = self.pulsePairOp(dataOut.data, dataOut.utctime)
1475 dataOut.flagNoData = True
1476
1477 if self.__dataReady:
1478 #print("#------------------------------------------------------")
1479 #print("data_ready",data_intensity.shape)
1480 dataOut.data = data_intensity #valor para plotear RTI
1481 dataOut.nCohInt *= self.n
1482 dataOut.data_intensity = data_intensity #valor para intensidad
1483 dataOut.data_velocity = data_velocity #valor para velocidad
1484 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1485 dataOut.utctime = avgdatatime
1486 dataOut.flagNoData = False
1487 return dataOut
1488
1194 1489 # import collections
1195 1490 # from scipy.stats import mode
1196 1491 #
1197 1492 # class Synchronize(Operation):
1198 1493 #
1199 1494 # isConfig = False
1200 1495 # __profIndex = 0
1201 1496 #
1202 1497 # def __init__(self, **kwargs):
1203 1498 #
1204 1499 # Operation.__init__(self, **kwargs)
1205 1500 # # self.isConfig = False
1206 1501 # self.__powBuffer = None
1207 1502 # self.__startIndex = 0
1208 1503 # self.__pulseFound = False
1209 1504 #
1210 1505 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1211 1506 #
1212 1507 # #Read data
1213 1508 #
1214 1509 # powerdB = dataOut.getPower(channel = channel)
1215 1510 # noisedB = dataOut.getNoise(channel = channel)[0]
1216 1511 #
1217 1512 # self.__powBuffer.extend(powerdB.flatten())
1218 1513 #
1219 1514 # dataArray = numpy.array(self.__powBuffer)
1220 1515 #
1221 1516 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1222 1517 #
1223 1518 # maxValue = numpy.nanmax(filteredPower)
1224 1519 #
1225 1520 # if maxValue < noisedB + 10:
1226 1521 # #No se encuentra ningun pulso de transmision
1227 1522 # return None
1228 1523 #
1229 1524 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1230 1525 #
1231 1526 # if len(maxValuesIndex) < 2:
1232 1527 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1233 1528 # return None
1234 1529 #
1235 1530 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1236 1531 #
1237 1532 # #Seleccionar solo valores con un espaciamiento de nSamples
1238 1533 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1239 1534 #
1240 1535 # if len(pulseIndex) < 2:
1241 1536 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1242 1537 # return None
1243 1538 #
1244 1539 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1245 1540 #
1246 1541 # #remover senales que se distancien menos de 10 unidades o muestras
1247 1542 # #(No deberian existir IPP menor a 10 unidades)
1248 1543 #
1249 1544 # realIndex = numpy.where(spacing > 10 )[0]
1250 1545 #
1251 1546 # if len(realIndex) < 2:
1252 1547 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1253 1548 # return None
1254 1549 #
1255 1550 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1256 1551 # realPulseIndex = pulseIndex[realIndex]
1257 1552 #
1258 1553 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1259 1554 #
1260 1555 # print "IPP = %d samples" %period
1261 1556 #
1262 1557 # self.__newNSamples = dataOut.nHeights #int(period)
1263 1558 # self.__startIndex = int(realPulseIndex[0])
1264 1559 #
1265 1560 # return 1
1266 1561 #
1267 1562 #
1268 1563 # def setup(self, nSamples, nChannels, buffer_size = 4):
1269 1564 #
1270 1565 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1271 1566 # maxlen = buffer_size*nSamples)
1272 1567 #
1273 1568 # bufferList = []
1274 1569 #
1275 1570 # for i in range(nChannels):
1276 1571 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1277 1572 # maxlen = buffer_size*nSamples)
1278 1573 #
1279 1574 # bufferList.append(bufferByChannel)
1280 1575 #
1281 1576 # self.__nSamples = nSamples
1282 1577 # self.__nChannels = nChannels
1283 1578 # self.__bufferList = bufferList
1284 1579 #
1285 1580 # def run(self, dataOut, channel = 0):
1286 1581 #
1287 1582 # if not self.isConfig:
1288 1583 # nSamples = dataOut.nHeights
1289 1584 # nChannels = dataOut.nChannels
1290 1585 # self.setup(nSamples, nChannels)
1291 1586 # self.isConfig = True
1292 1587 #
1293 1588 # #Append new data to internal buffer
1294 1589 # for thisChannel in range(self.__nChannels):
1295 1590 # bufferByChannel = self.__bufferList[thisChannel]
1296 1591 # bufferByChannel.extend(dataOut.data[thisChannel])
1297 1592 #
1298 1593 # if self.__pulseFound:
1299 1594 # self.__startIndex -= self.__nSamples
1300 1595 #
1301 1596 # #Finding Tx Pulse
1302 1597 # if not self.__pulseFound:
1303 1598 # indexFound = self.__findTxPulse(dataOut, channel)
1304 1599 #
1305 1600 # if indexFound == None:
1306 1601 # dataOut.flagNoData = True
1307 1602 # return
1308 1603 #
1309 1604 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1310 1605 # self.__pulseFound = True
1311 1606 # self.__startIndex = indexFound
1312 1607 #
1313 1608 # #If pulse was found ...
1314 1609 # for thisChannel in range(self.__nChannels):
1315 1610 # bufferByChannel = self.__bufferList[thisChannel]
1316 1611 # #print self.__startIndex
1317 1612 # x = numpy.array(bufferByChannel)
1318 1613 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1319 1614 #
1320 1615 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1321 1616 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1322 1617 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1323 1618 #
1324 1619 # dataOut.data = self.__arrayBuffer
1325 1620 #
1326 1621 # self.__startIndex += self.__newNSamples
1327 1622 #
1328 1623 # return
@@ -1,183 +1,203
1 1 #!python
2 2 '''
3 3 '''
4 4
5 5 import os, sys
6 6 import datetime
7 7 import time
8 8
9 9 #path = os.path.dirname(os.getcwd())
10 10 #path = os.path.dirname(path)
11 11 #sys.path.insert(0, path)
12 12
13 13 from schainpy.controller import Project
14 14
15 15 desc = "USRP_test"
16 16 filename = "USRP_processing.xml"
17 17 controllerObj = Project()
18 18 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
19 19
20 20 ############## USED TO PLOT IQ VOLTAGE, POWER AND SPECTRA #############
21 21
22 22 #######################################################################
23 23 ######PATH DE LECTURA, ESCRITURA, GRAFICOS Y ENVIO WEB#################
24 24 #######################################################################
25 25 #path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman'
26 26
27 27
28 path = '/home/soporte/data_hdf5' #### with clock 35.16 db noise
29
30 figpath = '/home/soporte/data_hdf5_imag'
28 #path = '/home/soporte/data_hdf5' #### with clock 35.16 db noise
29 path = '/home/alex/WEATHER_DATA/DATA'
30 figpath = '/home/alex/WEATHER_DATA/DATA/pic'
31 #figpath = '/home/soporte/data_hdf5_imag'
31 32 #remotefolder = "/home/wmaster/graficos"
32 33 #######################################################################
33 34 ################# RANGO DE PLOTEO######################################
34 35 #######################################################################
35 36 dBmin = '30'
36 37 dBmax = '60'
37 38 xmin = '0'
38 39 xmax ='24'
39 40 ymin = '0'
40 41 ymax = '600'
41 42 #######################################################################
42 43 ########################FECHA##########################################
43 44 #######################################################################
44 45 str = datetime.date.today()
45 46 today = str.strftime("%Y/%m/%d")
46 47 str2 = str - datetime.timedelta(days=1)
47 48 yesterday = str2.strftime("%Y/%m/%d")
48 49 #######################################################################
49 50 ######################## UNIDAD DE LECTURA#############################
50 51 #######################################################################
51 52 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
52 53 path=path,
53 54 startDate="2019/01/01",#today,
54 55 endDate="2109/12/30",#today,
55 56 startTime='00:00:00',
56 57 endTime='23:59:59',
57 58 delay=0,
58 59 #set=0,
59 60 online=0,
60 61 walk=1,
61 62 ippKm = 1000)
62 63
63 64 opObj11 = readUnitConfObj.addOperation(name='printInfo')
64 65 opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
65 66 #######################################################################
66 67 ################ OPERACIONES DOMINIO DEL TIEMPO########################
67 68 #######################################################################
68 69
69 70 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
70 71 #
71 72 # codigo64='1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,1,0,1,1,1,0,0,0,1,0,'+\
72 73 # '1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1'
73 74
74 75 #opObj11 = procUnitConfObjA.addOperation(name='setRadarFrequency')
75 76 #opObj11.addParameter(name='frequency', value='30e6', format='float')
76 77
77 78 #opObj10 = procUnitConfObjA.addOperation(name='Scope', optype='external')
78 79 #opObj10.addParameter(name='id', value='10', format='int')
79 80 ##opObj10.addParameter(name='xmin', value='0', format='int')
80 81 ##opObj10.addParameter(name='xmax', value='50', format='int')
81 82 #opObj10.addParameter(name='type', value='iq')
82 83 #opObj10.addParameter(name='ymin', value='-5000', format='int')
83 84 ##opObj10.addParameter(name='ymax', value='8500', format='int')
84 85
85 86 #opObj10 = procUnitConfObjA.addOperation(name='setH0')
86 87 #opObj10.addParameter(name='h0', value='-5000', format='float')
87 88
88 89 #opObj11 = procUnitConfObjA.addOperation(name='filterByHeights')
89 90 #opObj11.addParameter(name='window', value='1', format='int')
90 91
91 92 #codigo='1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,1,1,1,-1,-1,-1'
92 93 #opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other')
93 94 #opObj11.addParameter(name='code', value=codigo, format='floatlist')
94 95 #opObj11.addParameter(name='nCode', value='1', format='int')
95 96 #opObj11.addParameter(name='nBaud', value='28', format='int')
96 97
97 98 #opObj11 = procUnitConfObjA.addOperation(name='CohInt', optype='other')
98 #opObj11.addParameter(name='n', value='100', format='int')
99 #opObj11.addParameter(name='n', value='10', format='int')
100
101
102 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
103 opObj11.addParameter(name='n', value='10', format='int')
104
105 opObj11 = procUnitConfObjA.addOperation(name='CreateBlockVoltage', optype='other')
106 opObj11.addParameter(name='m', value='16', format='int')
107
108 procUnitConfObj2 = controllerObj.addProcUnit(datatype='ParametersProc', inputId=procUnitConfObjA.getId())
99 109
110 #Not used because the RGB data is obtained directly from the HF Reader.
111 #opObj21 = procUnitConfObj2.addOperation(name='GetRGBData')
112
113 opObj21 = procUnitConfObj2.addOperation(name='ParamWriter', optype='external')
114 opObj21.addParameter(name='path', value=figpath+'/NEWData')
115 opObj21.addParameter(name='blocksPerFile', value='1', format='int')
116 opObj21.addParameter(name='metadataList',value='heightList',format='list')
117 opObj21.addParameter(name='dataList',value='data_intensity',format='list')
118
119 '''
100 120 #######################################################################
101 121 ########## OPERACIONES DOMINIO DE LA FRECUENCIA########################
102 122 #######################################################################
103 123 procUnitConfObjSousySpectra = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
104 procUnitConfObjSousySpectra.addParameter(name='nFFTPoints', value='100', format='int')
105 procUnitConfObjSousySpectra.addParameter(name='nProfiles', value='100', format='int')
124 procUnitConfObjSousySpectra.addParameter(name='nFFTPoints', value='16', format='int')
125 procUnitConfObjSousySpectra.addParameter(name='nProfiles', value='16', format='int')
106 126 #procUnitConfObjSousySpectra.addParameter(name='pairsList', value='(0,0),(1,1),(0,1)', format='pairsList')
107 127
108 128 #opObj13 = procUnitConfObjSousySpectra.addOperation(name='removeDC')
109 129 #opObj13.addParameter(name='mode', value='2', format='int')
110 130
111 131 #opObj11 = procUnitConfObjSousySpectra.addOperation(name='IncohInt', optype='other')
112 132 #opObj11.addParameter(name='n', value='60', format='float')
113 133 #######################################################################
114 134 ########## PLOTEO DOMINIO DE LA FRECUENCIA#############################
115 135 #######################################################################
116 136 #SpectraPlot
117 137
118 138 opObj11 = procUnitConfObjSousySpectra.addOperation(name='SpectraPlot', optype='external')
119 139 opObj11.addParameter(name='id', value='1', format='int')
120 140 opObj11.addParameter(name='wintitle', value='Spectra', format='str')
121 141 #opObj11.addParameter(name='xmin', value=-0.01, format='float')
122 142 #opObj11.addParameter(name='xmax', value=0.01, format='float')
123 143 #opObj11.addParameter(name='zmin', value=dBmin, format='int')
124 144 #opObj11.addParameter(name='zmax', value=dBmax, format='int')
125 145 #opObj11.addParameter(name='ymin', value=ymin, format='int')
126 146 #opObj11.addParameter(name='ymax', value=ymax, format='int')
127 147 opObj11.addParameter(name='showprofile', value='1', format='int')
128 148 opObj11.addParameter(name='save', value=figpath, format='str')
129 149 opObj11.addParameter(name='save_period', value=10, format='int')
130 150
131 151
132 152 #RTIPLOT
133 153
134 154 opObj11 = procUnitConfObjSousySpectra.addOperation(name='RTIPlot', optype='external')
135 155 opObj11.addParameter(name='id', value='2', format='int')
136 156 opObj11.addParameter(name='wintitle', value='RTIPlot', format='str')
137 157 #opObj11.addParameter(name='zmin', value=dBmin, format='int')
138 158 #opObj11.addParameter(name='zmax', value=dBmax, format='int')
139 159 #opObj11.addParameter(name='ymin', value=ymin, format='int')
140 160 #opObj11.addParameter(name='ymax', value=ymax, format='int')
141 161 opObj11.addParameter(name='xmin', value=0, format='int')
142 162 opObj11.addParameter(name='xmax', value=23, format='int')
143 163
144 164 opObj11.addParameter(name='showprofile', value='1', format='int')
145 165 opObj11.addParameter(name='save', value=figpath, format='str')
146 166 opObj11.addParameter(name='save_period', value=10, format='int')
147 167
148 168
149 169 # opObj11 = procUnitConfObjSousySpectra.addOperation(name='CrossSpectraPlot', optype='other')
150 170 # opObj11.addParameter(name='id', value='3', format='int')
151 171 # opObj11.addParameter(name='wintitle', value='CrossSpectraPlot', format='str')
152 172 # opObj11.addParameter(name='ymin', value=ymin, format='int')
153 173 # opObj11.addParameter(name='ymax', value=ymax, format='int')
154 174 # opObj11.addParameter(name='phase_cmap', value='jet', format='str')
155 175 # opObj11.addParameter(name='zmin', value=dBmin, format='int')
156 176 # opObj11.addParameter(name='zmax', value=dBmax, format='int')
157 177 # opObj11.addParameter(name='figpath', value=figures_path, format='str')
158 178 # opObj11.addParameter(name='save', value=0, format='bool')
159 179 # opObj11.addParameter(name='pairsList', value='(0,1)', format='pairsList')
160 180 # #
161 181 # opObj11 = procUnitConfObjSousySpectra.addOperation(name='CoherenceMap', optype='other')
162 182 # opObj11.addParameter(name='id', value='4', format='int')
163 183 # opObj11.addParameter(name='wintitle', value='Coherence', format='str')
164 184 # opObj11.addParameter(name='phase_cmap', value='jet', format='str')
165 185 # opObj11.addParameter(name='xmin', value=xmin, format='float')
166 186 # opObj11.addParameter(name='xmax', value=xmax, format='float')
167 187 # opObj11.addParameter(name='figpath', value=figures_path, format='str')
168 188 # opObj11.addParameter(name='save', value=0, format='bool')
169 189 # opObj11.addParameter(name='pairsList', value='(0,1)', format='pairsList')
170 190 #
171 191 #######################################################################
172 192 ############### UNIDAD DE ESCRITURA ###################################
173 193 #######################################################################
174 194 #opObj11 = procUnitConfObjSousySpectra.addOperation(name='SpectraWriter', optype='other')
175 195 #opObj11.addParameter(name='path', value=wr_path)
176 196 #opObj11.addParameter(name='blocksPerFile', value='50', format='int')
197 '''
177 198 print ("Escribiendo el archivo XML")
178 199 print ("Leyendo el archivo XML")
179 200
180 201
181 202
182 203 controllerObj.start()
183
General Comments 0
You need to be logged in to leave comments. Login now