##// END OF EJS Templates
Fix publish and plots operations issue #929
Juan C. Espinoza -
r1062:8048843f4edf
parent child
Show More
@@ -1,1220 +1,1220
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
11 11 from jroheaderIO import SystemHeader, RadarControllerHeader
12 12 from schainpy import cSchain
13 13
14 14
15 15 def getNumpyDtype(dataTypeCode):
16 16
17 17 if dataTypeCode == 0:
18 18 numpyDtype = numpy.dtype([('real','<i1'),('imag','<i1')])
19 19 elif dataTypeCode == 1:
20 20 numpyDtype = numpy.dtype([('real','<i2'),('imag','<i2')])
21 21 elif dataTypeCode == 2:
22 22 numpyDtype = numpy.dtype([('real','<i4'),('imag','<i4')])
23 23 elif dataTypeCode == 3:
24 24 numpyDtype = numpy.dtype([('real','<i8'),('imag','<i8')])
25 25 elif dataTypeCode == 4:
26 26 numpyDtype = numpy.dtype([('real','<f4'),('imag','<f4')])
27 27 elif dataTypeCode == 5:
28 28 numpyDtype = numpy.dtype([('real','<f8'),('imag','<f8')])
29 29 else:
30 30 raise ValueError, 'dataTypeCode was not defined'
31 31
32 32 return numpyDtype
33 33
34 34 def getDataTypeCode(numpyDtype):
35 35
36 36 if numpyDtype == numpy.dtype([('real','<i1'),('imag','<i1')]):
37 37 datatype = 0
38 38 elif numpyDtype == numpy.dtype([('real','<i2'),('imag','<i2')]):
39 39 datatype = 1
40 40 elif numpyDtype == numpy.dtype([('real','<i4'),('imag','<i4')]):
41 41 datatype = 2
42 42 elif numpyDtype == numpy.dtype([('real','<i8'),('imag','<i8')]):
43 43 datatype = 3
44 44 elif numpyDtype == numpy.dtype([('real','<f4'),('imag','<f4')]):
45 45 datatype = 4
46 46 elif numpyDtype == numpy.dtype([('real','<f8'),('imag','<f8')]):
47 47 datatype = 5
48 48 else:
49 49 datatype = None
50 50
51 51 return datatype
52 52
53 53 def hildebrand_sekhon(data, navg):
54 54 """
55 55 This method is for the objective determination of the noise level in Doppler spectra. This
56 56 implementation technique is based on the fact that the standard deviation of the spectral
57 57 densities is equal to the mean spectral density for white Gaussian noise
58 58
59 59 Inputs:
60 60 Data : heights
61 61 navg : numbers of averages
62 62
63 63 Return:
64 64 -1 : any error
65 65 anoise : noise's level
66 66 """
67 67
68 68 sortdata = numpy.sort(data, axis=None)
69 69 # lenOfData = len(sortdata)
70 70 # nums_min = lenOfData*0.2
71 71 #
72 72 # if nums_min <= 5:
73 73 # nums_min = 5
74 74 #
75 75 # sump = 0.
76 76 #
77 77 # sumq = 0.
78 78 #
79 79 # j = 0
80 80 #
81 81 # cont = 1
82 82 #
83 83 # while((cont==1)and(j<lenOfData)):
84 84 #
85 85 # sump += sortdata[j]
86 86 #
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 return cSchain.hildebrand_sekhon(sortdata, navg)
104 104
105 105
106 106 class Beam:
107 107
108 108 def __init__(self):
109 109 self.codeList = []
110 110 self.azimuthList = []
111 111 self.zenithList = []
112 112
113 113 class GenericData(object):
114 114
115 115 flagNoData = True
116 116
117 117 def copy(self, inputObj=None):
118 118
119 119 if inputObj == None:
120 120 return copy.deepcopy(self)
121 121
122 122 for key in inputObj.__dict__.keys():
123 123
124 124 attribute = inputObj.__dict__[key]
125 125
126 126 #If this attribute is a tuple or list
127 127 if type(inputObj.__dict__[key]) in (tuple, list):
128 128 self.__dict__[key] = attribute[:]
129 129 continue
130 130
131 131 #If this attribute is another object or instance
132 132 if hasattr(attribute, '__dict__'):
133 133 self.__dict__[key] = attribute.copy()
134 134 continue
135 135
136 136 self.__dict__[key] = inputObj.__dict__[key]
137 137
138 138 def deepcopy(self):
139 139
140 140 return copy.deepcopy(self)
141 141
142 142 def isEmpty(self):
143 143
144 144 return self.flagNoData
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
153 153 radarControllerHeaderObj = RadarControllerHeader()
154 154
155 155 # data = None
156 156
157 157 type = None
158 158
159 159 datatype = None #dtype but in string
160 160
161 161 # dtype = None
162 162
163 163 # nChannels = None
164 164
165 165 # nHeights = None
166 166
167 167 nProfiles = None
168 168
169 169 heightList = None
170 170
171 171 channelList = None
172 172
173 173 flagDiscontinuousBlock = False
174 174
175 175 useLocalTime = False
176 176
177 177 utctime = None
178 178
179 179 timeZone = None
180 180
181 181 dstFlag = None
182 182
183 183 errorCount = None
184 184
185 185 blocksize = None
186 186
187 187 # nCode = None
188 188 #
189 189 # nBaud = None
190 190 #
191 191 # code = None
192 192
193 193 flagDecodeData = False #asumo q la data no esta decodificada
194 194
195 195 flagDeflipData = False #asumo q la data no esta sin flip
196 196
197 197 flagShiftFFT = False
198 198
199 199 # ippSeconds = None
200 200
201 201 # timeInterval = None
202 202
203 203 nCohInt = None
204 204
205 205 # noise = None
206 206
207 207 windowOfFilter = 1
208 208
209 209 #Speed of ligth
210 210 C = 3e8
211 211
212 212 frequency = 49.92e6
213 213
214 214 realtime = False
215 215
216 216 beacon_heiIndexList = None
217 217
218 218 last_block = None
219 219
220 220 blocknow = None
221 221
222 222 azimuth = None
223 223
224 224 zenith = None
225 225
226 226 beam = Beam()
227 227
228 228 profileIndex = None
229 229
230 230 def getNoise(self):
231 231
232 232 raise NotImplementedError
233 233
234 234 def getNChannels(self):
235 235
236 236 return len(self.channelList)
237 237
238 238 def getChannelIndexList(self):
239 239
240 240 return range(self.nChannels)
241 241
242 242 def getNHeights(self):
243 243
244 244 return len(self.heightList)
245 245
246 246 def getHeiRange(self, extrapoints=0):
247 247
248 248 heis = self.heightList
249 249 # deltah = self.heightList[1] - self.heightList[0]
250 250 #
251 251 # heis.append(self.heightList[-1])
252 252
253 253 return heis
254 254
255 255 def getDeltaH(self):
256 256
257 257 delta = self.heightList[1] - self.heightList[0]
258 258
259 259 return delta
260 260
261 261 def getltctime(self):
262 262
263 263 if self.useLocalTime:
264 264 return self.utctime - self.timeZone*60
265 265
266 266 return self.utctime
267 267
268 268 def getDatatime(self):
269 269
270 270 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
271 271 return datatimeValue
272 272
273 273 def getTimeRange(self):
274 274
275 275 datatime = []
276 276
277 277 datatime.append(self.ltctime)
278 278 datatime.append(self.ltctime + self.timeInterval+1)
279 279
280 280 datatime = numpy.array(datatime)
281 281
282 282 return datatime
283 283
284 284 def getFmaxTimeResponse(self):
285 285
286 286 period = (10**-6)*self.getDeltaH()/(0.15)
287 287
288 288 PRF = 1./(period * self.nCohInt)
289 289
290 290 fmax = PRF
291 291
292 292 return fmax
293 293
294 294 def getFmax(self):
295 295
296 296 PRF = 1./(self.ippSeconds * self.nCohInt)
297 297
298 298 fmax = PRF
299 299
300 300 return fmax
301 301
302 302 def getVmax(self):
303 303
304 304 _lambda = self.C/self.frequency
305 305
306 306 vmax = self.getFmax() * _lambda/2
307 307
308 308 return vmax
309 309
310 310 def get_ippSeconds(self):
311 311 '''
312 312 '''
313 313 return self.radarControllerHeaderObj.ippSeconds
314 314
315 315 def set_ippSeconds(self, ippSeconds):
316 316 '''
317 317 '''
318 318
319 319 self.radarControllerHeaderObj.ippSeconds = ippSeconds
320 320
321 321 return
322 322
323 323 def get_dtype(self):
324 324 '''
325 325 '''
326 326 return getNumpyDtype(self.datatype)
327 327
328 328 def set_dtype(self, numpyDtype):
329 329 '''
330 330 '''
331 331
332 332 self.datatype = getDataTypeCode(numpyDtype)
333 333
334 334 def get_code(self):
335 335 '''
336 336 '''
337 337 return self.radarControllerHeaderObj.code
338 338
339 339 def set_code(self, code):
340 340 '''
341 341 '''
342 342 self.radarControllerHeaderObj.code = code
343 343
344 344 return
345 345
346 346 def get_ncode(self):
347 347 '''
348 348 '''
349 349 return self.radarControllerHeaderObj.nCode
350 350
351 351 def set_ncode(self, nCode):
352 352 '''
353 353 '''
354 354 self.radarControllerHeaderObj.nCode = nCode
355 355
356 356 return
357 357
358 358 def get_nbaud(self):
359 359 '''
360 360 '''
361 361 return self.radarControllerHeaderObj.nBaud
362 362
363 363 def set_nbaud(self, nBaud):
364 364 '''
365 365 '''
366 366 self.radarControllerHeaderObj.nBaud = nBaud
367 367
368 368 return
369 369
370 370 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
371 371 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
372 372 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
373 373 #noise = property(getNoise, "I'm the 'nHeights' property.")
374 374 datatime = property(getDatatime, "I'm the 'datatime' property")
375 375 ltctime = property(getltctime, "I'm the 'ltctime' property")
376 376 ippSeconds = property(get_ippSeconds, set_ippSeconds)
377 377 dtype = property(get_dtype, set_dtype)
378 378 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
379 379 code = property(get_code, set_code)
380 380 nCode = property(get_ncode, set_ncode)
381 381 nBaud = property(get_nbaud, set_nbaud)
382 382
383 383 class Voltage(JROData):
384 384
385 385 #data es un numpy array de 2 dmensiones (canales, alturas)
386 386 data = None
387 387
388 388 def __init__(self):
389 389 '''
390 390 Constructor
391 391 '''
392 392
393 393 self.useLocalTime = True
394 394
395 395 self.radarControllerHeaderObj = RadarControllerHeader()
396 396
397 397 self.systemHeaderObj = SystemHeader()
398 398
399 399 self.type = "Voltage"
400 400
401 401 self.data = None
402 402
403 403 # self.dtype = None
404 404
405 405 # self.nChannels = 0
406 406
407 407 # self.nHeights = 0
408 408
409 409 self.nProfiles = None
410 410
411 411 self.heightList = None
412 412
413 413 self.channelList = None
414 414
415 415 # self.channelIndexList = None
416 416
417 417 self.flagNoData = True
418 418
419 419 self.flagDiscontinuousBlock = False
420 420
421 421 self.utctime = None
422 422
423 423 self.timeZone = None
424 424
425 425 self.dstFlag = None
426 426
427 427 self.errorCount = None
428 428
429 429 self.nCohInt = None
430 430
431 431 self.blocksize = None
432 432
433 433 self.flagDecodeData = False #asumo q la data no esta decodificada
434 434
435 435 self.flagDeflipData = False #asumo q la data no esta sin flip
436 436
437 437 self.flagShiftFFT = False
438 438
439 439 self.flagDataAsBlock = False #Asumo que la data es leida perfil a perfil
440 440
441 441 self.profileIndex = 0
442 442
443 443 def getNoisebyHildebrand(self, channel = None):
444 444 """
445 445 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
446 446
447 447 Return:
448 448 noiselevel
449 449 """
450 450
451 451 if channel != None:
452 452 data = self.data[channel]
453 453 nChannels = 1
454 454 else:
455 455 data = self.data
456 456 nChannels = self.nChannels
457 457
458 458 noise = numpy.zeros(nChannels)
459 459 power = data * numpy.conjugate(data)
460 460
461 461 for thisChannel in range(nChannels):
462 462 if nChannels == 1:
463 463 daux = power[:].real
464 464 else:
465 465 daux = power[thisChannel,:].real
466 466 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
467 467
468 468 return noise
469 469
470 470 def getNoise(self, type = 1, channel = None):
471 471
472 472 if type == 1:
473 473 noise = self.getNoisebyHildebrand(channel)
474 474
475 475 return noise
476 476
477 477 def getPower(self, channel = None):
478 478
479 479 if channel != None:
480 480 data = self.data[channel]
481 481 else:
482 482 data = self.data
483 483
484 484 power = data * numpy.conjugate(data)
485 485 powerdB = 10*numpy.log10(power.real)
486 486 powerdB = numpy.squeeze(powerdB)
487 487
488 488 return powerdB
489 489
490 490 def getTimeInterval(self):
491 491
492 492 timeInterval = self.ippSeconds * self.nCohInt
493 493
494 494 return timeInterval
495 495
496 496 noise = property(getNoise, "I'm the 'nHeights' property.")
497 497 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
498 498
499 499 class Spectra(JROData):
500 500
501 501 #data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
502 502 data_spc = None
503 503
504 504 #data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
505 505 data_cspc = None
506 506
507 507 #data dc es un numpy array de 2 dmensiones (canales, alturas)
508 508 data_dc = None
509 509
510 510 #data power
511 511 data_pwr = None
512 512
513 513 nFFTPoints = None
514 514
515 515 # nPairs = None
516 516
517 517 pairsList = None
518 518
519 519 nIncohInt = None
520 520
521 521 wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia
522 522
523 523 nCohInt = None #se requiere para determinar el valor de timeInterval
524 524
525 525 ippFactor = None
526 526
527 527 profileIndex = 0
528 528
529 529 plotting = "spectra"
530 530
531 531 def __init__(self):
532 532 '''
533 533 Constructor
534 534 '''
535 535
536 536 self.useLocalTime = True
537 537
538 538 self.radarControllerHeaderObj = RadarControllerHeader()
539 539
540 540 self.systemHeaderObj = SystemHeader()
541 541
542 542 self.type = "Spectra"
543 543
544 544 # self.data = None
545 545
546 546 # self.dtype = None
547 547
548 548 # self.nChannels = 0
549 549
550 550 # self.nHeights = 0
551 551
552 552 self.nProfiles = None
553 553
554 554 self.heightList = None
555 555
556 556 self.channelList = None
557 557
558 558 # self.channelIndexList = None
559 559
560 560 self.pairsList = None
561 561
562 562 self.flagNoData = True
563 563
564 564 self.flagDiscontinuousBlock = False
565 565
566 566 self.utctime = None
567 567
568 568 self.nCohInt = None
569 569
570 570 self.nIncohInt = None
571 571
572 572 self.blocksize = None
573 573
574 574 self.nFFTPoints = None
575 575
576 576 self.wavelength = None
577 577
578 578 self.flagDecodeData = False #asumo q la data no esta decodificada
579 579
580 580 self.flagDeflipData = False #asumo q la data no esta sin flip
581 581
582 582 self.flagShiftFFT = False
583 583
584 584 self.ippFactor = 1
585 585
586 586 #self.noise = None
587 587
588 588 self.beacon_heiIndexList = []
589 589
590 590 self.noise_estimation = None
591 591
592 592
593 593 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
594 594 """
595 595 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
596 596
597 597 Return:
598 598 noiselevel
599 599 """
600 600
601 601 noise = numpy.zeros(self.nChannels)
602 602
603 603 for channel in range(self.nChannels):
604 604 daux = self.data_spc[channel,xmin_index:xmax_index,ymin_index:ymax_index]
605 605 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
606 606
607 607 return noise
608 608
609 609 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
610 610
611 611 if self.noise_estimation is not None:
612 612 return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py
613 613 else:
614 614 noise = self.getNoisebyHildebrand(xmin_index, xmax_index, ymin_index, ymax_index)
615 615 return noise
616 616
617 617 def getFreqRangeTimeResponse(self, extrapoints=0):
618 618
619 619 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints*self.ippFactor)
620 620 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
621 621
622 622 return freqrange
623 623
624 624 def getAcfRange(self, extrapoints=0):
625 625
626 626 deltafreq = 10./(self.getFmax() / (self.nFFTPoints*self.ippFactor))
627 627 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
628 628
629 629 return freqrange
630 630
631 631 def getFreqRange(self, extrapoints=0):
632 632
633 633 deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor)
634 634 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
635 635
636 636 return freqrange
637 637
638 638 def getVelRange(self, extrapoints=0):
639 639
640 640 deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor)
641 641 velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) #- deltav/2
642 642
643 643 return velrange
644 644
645 645 def getNPairs(self):
646 646
647 647 return len(self.pairsList)
648 648
649 649 def getPairsIndexList(self):
650 650
651 651 return range(self.nPairs)
652 652
653 653 def getNormFactor(self):
654 654
655 655 pwcode = 1
656 656
657 657 if self.flagDecodeData:
658 658 pwcode = numpy.sum(self.code[0]**2)
659 659 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
660 660 normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
661 661
662 662 return normFactor
663 663
664 664 def getFlagCspc(self):
665 665
666 666 if self.data_cspc is None:
667 667 return True
668 668
669 669 return False
670 670
671 671 def getFlagDc(self):
672 672
673 673 if self.data_dc is None:
674 674 return True
675 675
676 676 return False
677 677
678 678 def getTimeInterval(self):
679 679
680 680 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles
681 681
682 682 return timeInterval
683 683
684 684 def getPower(self):
685 685
686 686 factor = self.normFactor
687 687 z = self.data_spc/factor
688 688 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
689 689 avg = numpy.average(z, axis=1)
690 690
691 691 return 10*numpy.log10(avg)
692 692
693 693 def getCoherence(self, pairsList=None, phase=False):
694 694
695 695 z = []
696 696 if pairsList is None:
697 697 pairsIndexList = self.pairsIndexList
698 698 else:
699 699 pairsIndexList = []
700 700 for pair in pairsList:
701 701 if pair not in self.pairsList:
702 702 raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair)
703 pairsIndexList.append(self.pairsList.index(pair))
703 pairsIndexList.append(self.pairsList.index(pair))
704 704 for i in range(len(pairsIndexList)):
705 705 pair = self.pairsList[pairsIndexList[i]]
706 706 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
707 707 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
708 708 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
709 709 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
710 710 if phase:
711 711 data = numpy.arctan2(avgcoherenceComplex.imag,
712 712 avgcoherenceComplex.real)*180/numpy.pi
713 713 else:
714 714 data = numpy.abs(avgcoherenceComplex)
715 715
716 716 z.append(data)
717 717
718 718 return numpy.array(z)
719 719
720 720 def setValue(self, value):
721 721
722 722 print "This property should not be initialized"
723 723
724 724 return
725 725
726 726 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
727 727 pairsIndexList = property(getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
728 728 normFactor = property(getNormFactor, setValue, "I'm the 'getNormFactor' property.")
729 729 flag_cspc = property(getFlagCspc, setValue)
730 730 flag_dc = property(getFlagDc, setValue)
731 731 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
732 732 timeInterval = property(getTimeInterval, setValue, "I'm the 'timeInterval' property")
733 733
734 734 class SpectraHeis(Spectra):
735 735
736 736 data_spc = None
737 737
738 738 data_cspc = None
739 739
740 740 data_dc = None
741 741
742 742 nFFTPoints = None
743 743
744 744 # nPairs = None
745 745
746 746 pairsList = None
747 747
748 748 nCohInt = None
749 749
750 750 nIncohInt = None
751 751
752 752 def __init__(self):
753 753
754 754 self.radarControllerHeaderObj = RadarControllerHeader()
755 755
756 756 self.systemHeaderObj = SystemHeader()
757 757
758 758 self.type = "SpectraHeis"
759 759
760 760 # self.dtype = None
761 761
762 762 # self.nChannels = 0
763 763
764 764 # self.nHeights = 0
765 765
766 766 self.nProfiles = None
767 767
768 768 self.heightList = None
769 769
770 770 self.channelList = None
771 771
772 772 # self.channelIndexList = None
773 773
774 774 self.flagNoData = True
775 775
776 776 self.flagDiscontinuousBlock = False
777 777
778 778 # self.nPairs = 0
779 779
780 780 self.utctime = None
781 781
782 782 self.blocksize = None
783 783
784 784 self.profileIndex = 0
785 785
786 786 self.nCohInt = 1
787 787
788 788 self.nIncohInt = 1
789 789
790 790 def getNormFactor(self):
791 791 pwcode = 1
792 792 if self.flagDecodeData:
793 793 pwcode = numpy.sum(self.code[0]**2)
794 794
795 795 normFactor = self.nIncohInt*self.nCohInt*pwcode
796 796
797 797 return normFactor
798 798
799 799 def getTimeInterval(self):
800 800
801 801 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
802 802
803 803 return timeInterval
804 804
805 805 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
806 806 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
807 807
808 808 class Fits(JROData):
809 809
810 810 heightList = None
811 811
812 812 channelList = None
813 813
814 814 flagNoData = True
815 815
816 816 flagDiscontinuousBlock = False
817 817
818 818 useLocalTime = False
819 819
820 820 utctime = None
821 821
822 822 timeZone = None
823 823
824 824 # ippSeconds = None
825 825
826 826 # timeInterval = None
827 827
828 828 nCohInt = None
829 829
830 830 nIncohInt = None
831 831
832 832 noise = None
833 833
834 834 windowOfFilter = 1
835 835
836 836 #Speed of ligth
837 837 C = 3e8
838 838
839 839 frequency = 49.92e6
840 840
841 841 realtime = False
842 842
843 843
844 844 def __init__(self):
845 845
846 846 self.type = "Fits"
847 847
848 848 self.nProfiles = None
849 849
850 850 self.heightList = None
851 851
852 852 self.channelList = None
853 853
854 854 # self.channelIndexList = None
855 855
856 856 self.flagNoData = True
857 857
858 858 self.utctime = None
859 859
860 860 self.nCohInt = 1
861 861
862 862 self.nIncohInt = 1
863 863
864 864 self.useLocalTime = True
865 865
866 866 self.profileIndex = 0
867 867
868 868 # self.utctime = None
869 869 # self.timeZone = None
870 870 # self.ltctime = None
871 871 # self.timeInterval = None
872 872 # self.header = None
873 873 # self.data_header = None
874 874 # self.data = None
875 875 # self.datatime = None
876 876 # self.flagNoData = False
877 877 # self.expName = ''
878 878 # self.nChannels = None
879 879 # self.nSamples = None
880 880 # self.dataBlocksPerFile = None
881 881 # self.comments = ''
882 882 #
883 883
884 884
885 885 def getltctime(self):
886 886
887 887 if self.useLocalTime:
888 888 return self.utctime - self.timeZone*60
889 889
890 890 return self.utctime
891 891
892 892 def getDatatime(self):
893 893
894 894 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
895 895 return datatime
896 896
897 897 def getTimeRange(self):
898 898
899 899 datatime = []
900 900
901 901 datatime.append(self.ltctime)
902 902 datatime.append(self.ltctime + self.timeInterval)
903 903
904 904 datatime = numpy.array(datatime)
905 905
906 906 return datatime
907 907
908 908 def getHeiRange(self):
909 909
910 910 heis = self.heightList
911 911
912 912 return heis
913 913
914 914 def getNHeights(self):
915 915
916 916 return len(self.heightList)
917 917
918 918 def getNChannels(self):
919 919
920 920 return len(self.channelList)
921 921
922 922 def getChannelIndexList(self):
923 923
924 924 return range(self.nChannels)
925 925
926 926 def getNoise(self, type = 1):
927 927
928 928 #noise = numpy.zeros(self.nChannels)
929 929
930 930 if type == 1:
931 931 noise = self.getNoisebyHildebrand()
932 932
933 933 if type == 2:
934 934 noise = self.getNoisebySort()
935 935
936 936 if type == 3:
937 937 noise = self.getNoisebyWindow()
938 938
939 939 return noise
940 940
941 941 def getTimeInterval(self):
942 942
943 943 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
944 944
945 945 return timeInterval
946 946
947 947 datatime = property(getDatatime, "I'm the 'datatime' property")
948 948 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
949 949 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
950 950 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
951 951 noise = property(getNoise, "I'm the 'nHeights' property.")
952 952
953 953 ltctime = property(getltctime, "I'm the 'ltctime' property")
954 954 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
955 955
956 956
957 957 class Correlation(JROData):
958 958
959 959 noise = None
960 960
961 961 SNR = None
962 962
963 963 #--------------------------------------------------
964 964
965 965 mode = None
966 966
967 967 split = False
968 968
969 969 data_cf = None
970 970
971 971 lags = None
972 972
973 973 lagRange = None
974 974
975 975 pairsList = None
976 976
977 977 normFactor = None
978 978
979 979 #--------------------------------------------------
980 980
981 981 # calculateVelocity = None
982 982
983 983 nLags = None
984 984
985 985 nPairs = None
986 986
987 987 nAvg = None
988 988
989 989
990 990 def __init__(self):
991 991 '''
992 992 Constructor
993 993 '''
994 994 self.radarControllerHeaderObj = RadarControllerHeader()
995 995
996 996 self.systemHeaderObj = SystemHeader()
997 997
998 998 self.type = "Correlation"
999 999
1000 1000 self.data = None
1001 1001
1002 1002 self.dtype = None
1003 1003
1004 1004 self.nProfiles = None
1005 1005
1006 1006 self.heightList = None
1007 1007
1008 1008 self.channelList = None
1009 1009
1010 1010 self.flagNoData = True
1011 1011
1012 1012 self.flagDiscontinuousBlock = False
1013 1013
1014 1014 self.utctime = None
1015 1015
1016 1016 self.timeZone = None
1017 1017
1018 1018 self.dstFlag = None
1019 1019
1020 1020 self.errorCount = None
1021 1021
1022 1022 self.blocksize = None
1023 1023
1024 1024 self.flagDecodeData = False #asumo q la data no esta decodificada
1025 1025
1026 1026 self.flagDeflipData = False #asumo q la data no esta sin flip
1027 1027
1028 1028 self.pairsList = None
1029 1029
1030 1030 self.nPoints = None
1031 1031
1032 1032 def getPairsList(self):
1033 1033
1034 1034 return self.pairsList
1035 1035
1036 1036 def getNoise(self, mode = 2):
1037 1037
1038 1038 indR = numpy.where(self.lagR == 0)[0][0]
1039 1039 indT = numpy.where(self.lagT == 0)[0][0]
1040 1040
1041 1041 jspectra0 = self.data_corr[:,:,indR,:]
1042 1042 jspectra = copy.copy(jspectra0)
1043 1043
1044 1044 num_chan = jspectra.shape[0]
1045 1045 num_hei = jspectra.shape[2]
1046 1046
1047 1047 freq_dc = jspectra.shape[1]/2
1048 1048 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
1049 1049
1050 1050 if ind_vel[0]<0:
1051 1051 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
1052 1052
1053 1053 if mode == 1:
1054 1054 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
1055 1055
1056 1056 if mode == 2:
1057 1057
1058 1058 vel = numpy.array([-2,-1,1,2])
1059 1059 xx = numpy.zeros([4,4])
1060 1060
1061 1061 for fil in range(4):
1062 1062 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
1063 1063
1064 1064 xx_inv = numpy.linalg.inv(xx)
1065 1065 xx_aux = xx_inv[0,:]
1066 1066
1067 1067 for ich in range(num_chan):
1068 1068 yy = jspectra[ich,ind_vel,:]
1069 1069 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
1070 1070
1071 1071 junkid = jspectra[ich,freq_dc,:]<=0
1072 1072 cjunkid = sum(junkid)
1073 1073
1074 1074 if cjunkid.any():
1075 1075 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
1076 1076
1077 1077 noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:]
1078 1078
1079 1079 return noise
1080 1080
1081 1081 def getTimeInterval(self):
1082 1082
1083 1083 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1084 1084
1085 1085 return timeInterval
1086 1086
1087 1087 def splitFunctions(self):
1088 1088
1089 1089 pairsList = self.pairsList
1090 1090 ccf_pairs = []
1091 1091 acf_pairs = []
1092 1092 ccf_ind = []
1093 1093 acf_ind = []
1094 1094 for l in range(len(pairsList)):
1095 1095 chan0 = pairsList[l][0]
1096 1096 chan1 = pairsList[l][1]
1097 1097
1098 1098 #Obteniendo pares de Autocorrelacion
1099 1099 if chan0 == chan1:
1100 1100 acf_pairs.append(chan0)
1101 1101 acf_ind.append(l)
1102 1102 else:
1103 1103 ccf_pairs.append(pairsList[l])
1104 1104 ccf_ind.append(l)
1105 1105
1106 1106 data_acf = self.data_cf[acf_ind]
1107 1107 data_ccf = self.data_cf[ccf_ind]
1108 1108
1109 1109 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1110 1110
1111 1111 def getNormFactor(self):
1112 1112 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1113 1113 acf_pairs = numpy.array(acf_pairs)
1114 1114 normFactor = numpy.zeros((self.nPairs,self.nHeights))
1115 1115
1116 1116 for p in range(self.nPairs):
1117 1117 pair = self.pairsList[p]
1118 1118
1119 1119 ch0 = pair[0]
1120 1120 ch1 = pair[1]
1121 1121
1122 1122 ch0_max = numpy.max(data_acf[acf_pairs==ch0,:,:], axis=1)
1123 1123 ch1_max = numpy.max(data_acf[acf_pairs==ch1,:,:], axis=1)
1124 1124 normFactor[p,:] = numpy.sqrt(ch0_max*ch1_max)
1125 1125
1126 1126 return normFactor
1127 1127
1128 1128 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1129 1129 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1130 1130
1131 1131 class Parameters(Spectra):
1132 1132
1133 1133 experimentInfo = None #Information about the experiment
1134 1134
1135 1135 #Information from previous data
1136 1136
1137 1137 inputUnit = None #Type of data to be processed
1138 1138
1139 1139 operation = None #Type of operation to parametrize
1140 1140
1141 1141 #normFactor = None #Normalization Factor
1142 1142
1143 1143 groupList = None #List of Pairs, Groups, etc
1144 1144
1145 1145 #Parameters
1146 1146
1147 1147 data_param = None #Parameters obtained
1148 1148
1149 1149 data_pre = None #Data Pre Parametrization
1150 1150
1151 1151 data_SNR = None #Signal to Noise Ratio
1152 1152
1153 1153 # heightRange = None #Heights
1154 1154
1155 1155 abscissaList = None #Abscissa, can be velocities, lags or time
1156 1156
1157 1157 # noise = None #Noise Potency
1158 1158
1159 1159 utctimeInit = None #Initial UTC time
1160 1160
1161 1161 paramInterval = None #Time interval to calculate Parameters in seconds
1162 1162
1163 1163 useLocalTime = True
1164 1164
1165 1165 #Fitting
1166 1166
1167 1167 data_error = None #Error of the estimation
1168 1168
1169 1169 constants = None
1170 1170
1171 1171 library = None
1172 1172
1173 1173 #Output signal
1174 1174
1175 1175 outputInterval = None #Time interval to calculate output signal in seconds
1176 1176
1177 1177 data_output = None #Out signal
1178 1178
1179 1179 nAvg = None
1180 1180
1181 1181 noise_estimation = None
1182 1182
1183 1183
1184 1184 def __init__(self):
1185 1185 '''
1186 1186 Constructor
1187 1187 '''
1188 1188 self.radarControllerHeaderObj = RadarControllerHeader()
1189 1189
1190 1190 self.systemHeaderObj = SystemHeader()
1191 1191
1192 1192 self.type = "Parameters"
1193 1193
1194 1194 def getTimeRange1(self, interval):
1195 1195
1196 1196 datatime = []
1197 1197
1198 1198 if self.useLocalTime:
1199 1199 time1 = self.utctimeInit - self.timeZone*60
1200 1200 else:
1201 1201 time1 = self.utctimeInit
1202 1202
1203 1203 datatime.append(time1)
1204 1204 datatime.append(time1 + interval)
1205 1205 datatime = numpy.array(datatime)
1206 1206
1207 1207 return datatime
1208 1208
1209 1209 def getTimeInterval(self):
1210 1210
1211 1211 if hasattr(self, 'timeInterval1'):
1212 1212 return self.timeInterval1
1213 1213 else:
1214 1214 return self.paramInterval
1215 1215
1216 1216 def getNoise(self):
1217 1217
1218 1218 return self.spc_noise
1219 1219
1220 1220 timeInterval = property(getTimeInterval)
This diff has been collapsed as it changes many lines, (1208 lines changed) Show them Hide them
@@ -1,964 +1,782
1 1
2 2 import os
3 import zmq
4 3 import time
5 import numpy
4 import glob
6 5 import datetime
7 import numpy as np
6 from multiprocessing import Process
7
8 import zmq
9 import numpy
8 10 import matplotlib
9 import glob
10 matplotlib.use('TkAgg')
11 11 import matplotlib.pyplot as plt
12 12 from mpl_toolkits.axes_grid1 import make_axes_locatable
13 from matplotlib.ticker import FuncFormatter, LinearLocator
14 from multiprocessing import Process
13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
15 14
16 15 from schainpy.model.proc.jroproc_base import Operation
17
18 plt.ion()
16 from schainpy.utils import log
19 17
20 18 func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M'))
21 fromtimestamp = lambda x, mintime : (datetime.datetime.utcfromtimestamp(mintime).replace(hour=(x + 5), minute=0) - d1970).total_seconds()
22 19
20 d1970 = datetime.datetime(1970, 1, 1)
23 21
24 d1970 = datetime.datetime(1970,1,1)
25 22
26 23 class PlotData(Operation, Process):
24 '''
25 Base class for Schain plotting operations
26 '''
27 27
28 28 CODE = 'Figure'
29 29 colormap = 'jro'
30 bgcolor = 'white'
30 31 CONFLATE = False
31 32 __MAXNUMX = 80
32 33 __missing = 1E30
33 34
34 35 def __init__(self, **kwargs):
35 36
36 37 Operation.__init__(self, plot=True, **kwargs)
37 38 Process.__init__(self)
38 39 self.kwargs['code'] = self.CODE
39 40 self.mp = False
40 self.dataOut = None
41 self.isConfig = False
42 self.figure = None
41 self.data = None
42 self.isConfig = False
43 self.figures = []
43 44 self.axes = []
45 self.cb_axes = []
44 46 self.localtime = kwargs.pop('localtime', True)
45 47 self.show = kwargs.get('show', True)
46 48 self.save = kwargs.get('save', False)
47 49 self.colormap = kwargs.get('colormap', self.colormap)
48 50 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
49 51 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
50 self.showprofile = kwargs.get('showprofile', True)
51 self.title = kwargs.get('wintitle', '')
52 self.colormaps = kwargs.get('colormaps', None)
53 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
54 self.showprofile = kwargs.get('showprofile', False)
55 self.title = kwargs.get('wintitle', self.CODE.upper())
56 self.cb_label = kwargs.get('cb_label', None)
57 self.cb_labels = kwargs.get('cb_labels', None)
52 58 self.xaxis = kwargs.get('xaxis', 'frequency')
53 59 self.zmin = kwargs.get('zmin', None)
54 60 self.zmax = kwargs.get('zmax', None)
61 self.zlimits = kwargs.get('zlimits', None)
55 62 self.xmin = kwargs.get('xmin', None)
63 if self.xmin is not None:
64 self.xmin += 5
56 65 self.xmax = kwargs.get('xmax', None)
57 66 self.xrange = kwargs.get('xrange', 24)
58 67 self.ymin = kwargs.get('ymin', None)
59 68 self.ymax = kwargs.get('ymax', None)
60 self.__MAXNUMY = kwargs.get('decimation', 5000)
61 self.throttle_value = 5
62 self.times = []
63 #self.interactive = self.kwargs['parent']
69 self.xlabel = kwargs.get('xlabel', None)
70 self.__MAXNUMY = kwargs.get('decimation', 100)
71 self.showSNR = kwargs.get('showSNR', False)
72 self.oneFigure = kwargs.get('oneFigure', True)
73 self.width = kwargs.get('width', None)
74 self.height = kwargs.get('height', None)
75 self.colorbar = kwargs.get('colorbar', True)
76 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
77 self.titles = ['' for __ in range(16)]
78
79 def __setup(self):
80 '''
81 Common setup for all figures, here figures and axes are created
82 '''
83
84 self.setup()
85
86 if self.width is None:
87 self.width = 8
64 88
89 self.figures = []
90 self.axes = []
91 self.cb_axes = []
92 self.pf_axes = []
93 self.cmaps = []
94
95 size = '15%' if self.ncols==1 else '30%'
96 pad = '4%' if self.ncols==1 else '8%'
97
98 if self.oneFigure:
99 if self.height is None:
100 self.height = 1.4*self.nrows + 1
101 fig = plt.figure(figsize=(self.width, self.height),
102 edgecolor='k',
103 facecolor='w')
104 self.figures.append(fig)
105 for n in range(self.nplots):
106 ax = fig.add_subplot(self.nrows, self.ncols, n+1)
107 ax.tick_params(labelsize=8)
108 ax.firsttime = True
109 self.axes.append(ax)
110 if self.showprofile:
111 cax = self.__add_axes(ax, size=size, pad=pad)
112 cax.tick_params(labelsize=8)
113 self.pf_axes.append(cax)
114 else:
115 if self.height is None:
116 self.height = 3
117 for n in range(self.nplots):
118 fig = plt.figure(figsize=(self.width, self.height),
119 edgecolor='k',
120 facecolor='w')
121 ax = fig.add_subplot(1, 1, 1)
122 ax.tick_params(labelsize=8)
123 ax.firsttime = True
124 self.figures.append(fig)
125 self.axes.append(ax)
126 if self.showprofile:
127 cax = self.__add_axes(ax, size=size, pad=pad)
128 cax.tick_params(labelsize=8)
129 self.pf_axes.append(cax)
130
131 for n in range(self.nrows):
132 if self.colormaps is not None:
133 cmap = plt.get_cmap(self.colormaps[n])
134 else:
135 cmap = plt.get_cmap(self.colormap)
136 cmap.set_bad(self.bgcolor, 1.)
137 self.cmaps.append(cmap)
138
139 def __add_axes(self, ax, size='30%', pad='8%'):
65 140 '''
66 this new parameter is created to plot data from varius channels at different figures
67 1. crear una lista de figuras donde se puedan plotear las figuras,
68 2. dar las opciones de configuracion a cada figura, estas opciones son iguales para ambas figuras
69 3. probar?
141 Add new axes to the given figure
70 142 '''
71 self.ind_plt_ch = kwargs.get('ind_plt_ch', False)
72 self.figurelist = None
143 divider = make_axes_locatable(ax)
144 nax = divider.new_horizontal(size=size, pad=pad)
145 ax.figure.add_axes(nax)
146 return nax
73 147
74 148
75 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
149 def setup(self):
150 '''
151 This method should be implemented in the child class, the following
152 attributes should be set:
153
154 self.nrows: number of rows
155 self.ncols: number of cols
156 self.nplots: number of plots (channels or pairs)
157 self.ylabel: label for Y axes
158 self.titles: list of axes title
159
160 '''
161 raise(NotImplementedError, 'Implement this method in child class')
76 162
163 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
164 '''
165 Create a masked array for missing data
166 '''
77 167 if x_buffer.shape[0] < 2:
78 168 return x_buffer, y_buffer, z_buffer
79 169
80 170 deltas = x_buffer[1:] - x_buffer[0:-1]
81 x_median = np.median(deltas)
171 x_median = numpy.median(deltas)
82 172
83 index = np.where(deltas > 5*x_median)
173 index = numpy.where(deltas > 5*x_median)
84 174
85 175 if len(index[0]) != 0:
86 176 z_buffer[::, index[0], ::] = self.__missing
87 z_buffer = np.ma.masked_inside(z_buffer,
177 z_buffer = numpy.ma.masked_inside(z_buffer,
88 178 0.99*self.__missing,
89 179 1.01*self.__missing)
90 180
91 181 return x_buffer, y_buffer, z_buffer
92 182
93 183 def decimate(self):
94 184
95 185 # dx = int(len(self.x)/self.__MAXNUMX) + 1
96 186 dy = int(len(self.y)/self.__MAXNUMY) + 1
97 187
98 188 # x = self.x[::dx]
99 189 x = self.x
100 190 y = self.y[::dy]
101 191 z = self.z[::, ::, ::dy]
102
192
103 193 return x, y, z
104 194
105 '''
106 JM:
107 elimana las otras imagenes generadas debido a que lso workers no llegan en orden y le pueden
108 poner otro tiempo a la figura q no necesariamente es el ultimo.
109 Solo se realiza cuando termina la imagen.
110 Problemas:
195 def format(self):
196 '''
197 Set min and max values, labels, ticks and titles
198 '''
111 199
112 File "/home/ci-81/workspace/schainv2.3/schainpy/model/graphics/jroplot_data.py", line 145, in __plot
113 for n, eachfigure in enumerate(self.figurelist):
114 TypeError: 'NoneType' object is not iterable
200 if self.xmin is None:
201 xmin = self.min_time
202 else:
203 if self.xaxis is 'time':
204 dt = datetime.datetime.fromtimestamp(self.min_time)
205 xmin = (datetime.datetime.combine(dt.date(),
206 datetime.time(int(self.xmin), 0, 0))-d1970).total_seconds()
207 else:
208 xmin = self.xmin
115 209
116 '''
117 def deleteanotherfiles(self):
118 figurenames=[]
119 if self.figurelist != None:
120 for n, eachfigure in enumerate(self.figurelist):
121 #add specific name for each channel in channelList
122 ghostfigname = os.path.join(self.save, '{}_{}_{}'.format(self.titles[n].replace(' ',''),self.CODE,
123 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d')))
124 figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n].replace(' ',''),self.CODE,
125 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
126
127 for ghostfigure in glob.glob(ghostfigname+'*'): #ghostfigure will adopt all posible names of figures
128 if ghostfigure != figname:
129 os.remove(ghostfigure)
130 print 'Removing GhostFigures:' , figname
131 else :
132 '''Erasing ghost images for just on******************'''
133 ghostfigname = os.path.join(self.save, '{}_{}'.format(self.CODE,datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d')))
134 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
135 for ghostfigure in glob.glob(ghostfigname+'*'): #ghostfigure will adopt all posible names of figures
136 if ghostfigure != figname:
137 os.remove(ghostfigure)
138 print 'Removing GhostFigures:' , figname
210 if self.xmax is None:
211 xmax = xmin+self.xrange*60*60
212 else:
213 if self.xaxis is 'time':
214 dt = datetime.datetime.fromtimestamp(self.min_time)
215 xmax = (datetime.datetime.combine(dt.date(),
216 datetime.time(int(self.xmax), 0, 0))-d1970).total_seconds()
217 else:
218 xmax = self.xmax
219
220 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
221 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
222
223 ystep = 200 if ymax>= 800 else 100 if ymax>=400 else 50 if ymax>=200 else 20
224
225 for n, ax in enumerate(self.axes):
226 if ax.firsttime:
227 ax.set_facecolor(self.bgcolor)
228 ax.yaxis.set_major_locator(MultipleLocator(ystep))
229 if self.xaxis is 'time':
230 ax.xaxis.set_major_formatter(FuncFormatter(func))
231 ax.xaxis.set_major_locator(LinearLocator(9))
232 if self.xlabel is not None:
233 ax.set_xlabel(self.xlabel)
234 ax.set_ylabel(self.ylabel)
235 ax.firsttime = False
236 if self.showprofile:
237 self.pf_axes[n].set_ylim(ymin, ymax)
238 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
239 self.pf_axes[n].set_xlabel('dB')
240 self.pf_axes[n].grid(b=True, axis='x')
241 [tick.set_visible(False) for tick in self.pf_axes[n].get_yticklabels()]
242 if self.colorbar:
243 cb = plt.colorbar(ax.plt, ax=ax, pad=0.02)
244 cb.ax.tick_params(labelsize=8)
245 if self.cb_label:
246 cb.set_label(self.cb_label, size=8)
247 elif self.cb_labels:
248 cb.set_label(self.cb_labels[n], size=8)
249
250 ax.set_title('{} - {} UTC'.format(
251 self.titles[n],
252 datetime.datetime.fromtimestamp(self.max_time).strftime('%H:%M:%S')),
253 size=8)
254 ax.set_xlim(xmin, xmax)
255 ax.set_ylim(ymin, ymax)
256
139 257
140 258 def __plot(self):
141
142 print 'plotting...{}'.format(self.CODE)
143 if self.ind_plt_ch is False : #standard
259 '''
260 '''
261 log.success('Plotting', self.name)
262
263 self.plot()
264 self.format()
265
266 for n, fig in enumerate(self.figures):
267 if self.nrows == 0 or self.nplots == 0:
268 log.warning('No data', self.name)
269 continue
144 270 if self.show:
145 self.figure.show()
146 self.plot()
147 plt.tight_layout()
148 self.figure.canvas.manager.set_window_title('{} {} - {}'.format(self.title, self.CODE.upper(),
149 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
150 else :
151 print 'len(self.figurelist): ',len(self.figurelist)
152 for n, eachfigure in enumerate(self.figurelist):
153 if self.show:
154 eachfigure.show()
155
156 self.plot()
157 eachfigure.tight_layout() # ajuste de cada subplot
158 eachfigure.canvas.manager.set_window_title('{} {} - {}'.format(self.title[n], self.CODE.upper(),
159 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
160
161 # if self.save:
162 # if self.ind_plt_ch is False : #standard
163 # figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
164 # datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
165 # print 'Saving figure: {}'.format(figname)
166 # self.figure.savefig(figname)
167 # else :
168 # for n, eachfigure in enumerate(self.figurelist):
169 # #add specific name for each channel in channelList
170 # figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n],self.CODE,
171 # datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
172 #
173 # print 'Saving figure: {}'.format(figname)
174 # eachfigure.savefig(figname)
175
176 if self.ind_plt_ch is False :
177 self.figure.canvas.draw()
178 else :
179 for eachfigure in self.figurelist:
180 eachfigure.canvas.draw()
181
182 if self.save:
183 if self.ind_plt_ch is False : #standard
184 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
185 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
271 fig.show()
272
273 fig.tight_layout()
274 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
275 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
276 # fig.canvas.draw()
277
278 if self.save and self.data.ended:
279 channels = range(self.nrows)
280 if self.oneFigure:
281 label = ''
282 else:
283 label = '_{}'.format(channels[n])
284 figname = os.path.join(
285 self.save,
286 '{}{}_{}.png'.format(
287 self.CODE,
288 label,
289 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')
290 )
291 )
186 292 print 'Saving figure: {}'.format(figname)
187 self.figure.savefig(figname)
188 else :
189 for n, eachfigure in enumerate(self.figurelist):
190 #add specific name for each channel in channelList
191 figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n].replace(' ',''),self.CODE,
192 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
193
194 print 'Saving figure: {}'.format(figname)
195 eachfigure.savefig(figname)
196
293 fig.savefig(figname)
197 294
198 295 def plot(self):
199
200 print 'plotting...{}'.format(self.CODE.upper())
201 return
296 '''
297 '''
298 raise(NotImplementedError, 'Implement this method in child class')
202 299
203 300 def run(self):
204 301
205 print '[Starting] {}'.format(self.name)
302 log.success('Starting', self.name)
206 303
207 304 context = zmq.Context()
208 305 receiver = context.socket(zmq.SUB)
209 306 receiver.setsockopt(zmq.SUBSCRIBE, '')
210 307 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
211 308
212 309 if 'server' in self.kwargs['parent']:
213 310 receiver.connect('ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
214 311 else:
215 receiver.connect("ipc:///tmp/zmq.plots")
216
217 seconds_passed = 0
312 receiver.connect("ipc:///tmp/zmq.plots")
218 313
219 314 while True:
220 315 try:
221 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)#flags=zmq.NOBLOCK
222 self.started = self.data['STARTED']
223 self.dataOut = self.data['dataOut']
224
225 if (len(self.times) < len(self.data['times']) and not self.started and self.data['ENDED']):
226 continue
227
228 self.times = self.data['times']
229 self.times.sort()
230 self.throttle_value = self.data['throttle']
231 self.min_time = self.times[0]
232 self.max_time = self.times[-1]
316 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
317
318 self.min_time = self.data.times[0]
319 self.max_time = self.data.times[-1]
233 320
234 321 if self.isConfig is False:
235 print 'setting up'
236 self.setup()
322 self.__setup()
237 323 self.isConfig = True
238 self.__plot()
239
240 if self.data['ENDED'] is True:
241 print '********GRAPHIC ENDED********'
242 self.ended = True
243 self.isConfig = False
244 self.__plot()
245 self.deleteanotherfiles() #CLPDG
246 elif seconds_passed >= self.data['throttle']:
247 print 'passed', seconds_passed
248 self.__plot()
249 seconds_passed = 0
324
325 self.__plot()
250 326
251 327 except zmq.Again as e:
252 print 'Waiting for data...'
253 plt.pause(2)
254 seconds_passed += 2
328 log.log('Waiting for data...')
329 if self.data:
330 plt.pause(self.data.throttle)
331 else:
332 time.sleep(2)
255 333
256 334 def close(self):
257 if self.dataOut:
335 if self.data:
258 336 self.__plot()
259 337
260 338
261 339 class PlotSpectraData(PlotData):
340 '''
341 Plot for Spectra data
342 '''
262 343
263 344 CODE = 'spc'
264 colormap = 'jro'
265 CONFLATE = False
345 colormap = 'jro'
266 346
267 347 def setup(self):
268
269 ncolspan = 1
270 colspan = 1
271 self.ncols = int(numpy.sqrt(self.dataOut.nChannels)+0.9)
272 self.nrows = int(self.dataOut.nChannels*1./self.ncols + 0.9)
273 self.width = 3.6*self.ncols
274 self.height = 3.2*self.nrows
275 if self.showprofile:
276 ncolspan = 3
277 colspan = 2
278 self.width += 1.2*self.ncols
348 self.nplots = len(self.data.channels)
349 self.ncols = int(numpy.sqrt(self.nplots)+ 0.9)
350 self.nrows = int((1.0*self.nplots/self.ncols) + 0.9)
351 self.width = 3.4*self.ncols
352 self.height = 3*self.nrows
353 self.cb_label = 'dB'
354 if self.showprofile:
355 self.width += 0.8*self.ncols
279 356
280 357 self.ylabel = 'Range [Km]'
281 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
282
283 if self.figure is None:
284 self.figure = plt.figure(figsize=(self.width, self.height),
285 edgecolor='k',
286 facecolor='w')
287 else:
288 self.figure.clf()
289
290 n = 0
291 for y in range(self.nrows):
292 for x in range(self.ncols):
293 if n >= self.dataOut.nChannels:
294 break
295 ax = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan), 1, colspan)
296 if self.showprofile:
297 ax.ax_profile = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan+colspan), 1, 1)
298
299 ax.firsttime = True
300 self.axes.append(ax)
301 n += 1
302 358
303 359 def plot(self):
304
305 360 if self.xaxis == "frequency":
306 x = self.dataOut.getFreqRange(1)/1000.
307 xlabel = "Frequency (kHz)"
361 x = self.data.xrange[0]
362 self.xlabel = "Frequency (kHz)"
308 363 elif self.xaxis == "time":
309 x = self.dataOut.getAcfRange(1)
310 xlabel = "Time (ms)"
364 x = self.data.xrange[1]
365 self.xlabel = "Time (ms)"
311 366 else:
312 x = self.dataOut.getVelRange(1)
313 xlabel = "Velocity (m/s)"
367 x = self.data.xrange[2]
368 self.xlabel = "Velocity (m/s)"
369
370 if self.CODE == 'spc_mean':
371 x = self.data.xrange[2]
372 self.xlabel = "Velocity (m/s)"
314 373
315 y = self.dataOut.getHeiRange()
316 z = self.data[self.CODE]
374 self.titles = []
317 375
376 y = self.data.heights
377 self.y = y
378 z = self.data['spc']
379
318 380 for n, ax in enumerate(self.axes):
381 noise = self.data['noise'][n][-1]
382 if self.CODE == 'spc_mean':
383 mean = self.data['mean'][n][-1]
319 384 if ax.firsttime:
320 self.xmax = self.xmax if self.xmax else np.nanmax(x)
385 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
321 386 self.xmin = self.xmin if self.xmin else -self.xmax
322 self.ymin = self.ymin if self.ymin else np.nanmin(y)
323 self.ymax = self.ymax if self.ymax else np.nanmax(y)
324 self.zmin = self.zmin if self.zmin else np.nanmin(z)
325 self.zmax = self.zmax if self.zmax else np.nanmax(z)
326 ax.plot = ax.pcolormesh(x, y, z[n].T,
327 vmin=self.zmin,
328 vmax=self.zmax,
329 cmap=plt.get_cmap(self.colormap)
330 )
331 divider = make_axes_locatable(ax)
332 cax = divider.new_horizontal(size='3%', pad=0.05)
333 self.figure.add_axes(cax)
334 plt.colorbar(ax.plot, cax)
335
336 ax.set_xlim(self.xmin, self.xmax)
337 ax.set_ylim(self.ymin, self.ymax)
338
339 ax.set_ylabel(self.ylabel)
340 ax.set_xlabel(xlabel)
341
342 ax.firsttime = False
387 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
388 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
389 ax.plt = ax.pcolormesh(x, y, z[n].T,
390 vmin=self.zmin,
391 vmax=self.zmax,
392 cmap=plt.get_cmap(self.colormap)
393 )
343 394
344 395 if self.showprofile:
345 ax.plot_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
346 ax.ax_profile.set_xlim(self.zmin, self.zmax)
347 ax.ax_profile.set_ylim(self.ymin, self.ymax)
348 ax.ax_profile.set_xlabel('dB')
349 ax.ax_profile.grid(b=True, axis='x')
350 ax.plot_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
351 color="k", linestyle="dashed", lw=2)[0]
352 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
396 ax.plt_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], y)[0]
397 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
398 color="k", linestyle="dashed", lw=1)[0]
399 if self.CODE == 'spc_mean':
400 ax.plt_mean = ax.plot(mean, y, color='k')[0]
353 401 else:
354 ax.plot.set_array(z[n].T.ravel())
402 ax.plt.set_array(z[n].T.ravel())
355 403 if self.showprofile:
356 ax.plot_profile.set_data(self.data['rti'][self.max_time][n], y)
357 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
404 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
405 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
406 if self.CODE == 'spc_mean':
407 ax.plt_mean.set_data(mean, y)
358 408
359 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
360 size=8)
409 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
361 410 self.saveTime = self.max_time
362 411
363 412
364 413 class PlotCrossSpectraData(PlotData):
365 414
366 415 CODE = 'cspc'
367 416 zmin_coh = None
368 417 zmax_coh = None
369 418 zmin_phase = None
370 zmax_phase = None
371 CONFLATE = False
419 zmax_phase = None
372 420
373 421 def setup(self):
374 422
375 ncolspan = 1
376 colspan = 1
377 self.ncols = 2
378 self.nrows = self.dataOut.nPairs
379 self.width = 3.6*self.ncols
380 self.height = 3.2*self.nrows
381
423 self.ncols = 4
424 self.nrows = len(self.data.pairs)
425 self.nplots = self.nrows*4
426 self.width = 3.4*self.ncols
427 self.height = 3*self.nrows
382 428 self.ylabel = 'Range [Km]'
383 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
384
385 if self.figure is None:
386 self.figure = plt.figure(figsize=(self.width, self.height),
387 edgecolor='k',
388 facecolor='w')
389 else:
390 self.figure.clf()
391
392 for y in range(self.nrows):
393 for x in range(self.ncols):
394 ax = plt.subplot2grid((self.nrows, self.ncols), (y, x), 1, 1)
395 ax.firsttime = True
396 self.axes.append(ax)
429 self.showprofile = False
397 430
398 431 def plot(self):
399 432
400 433 if self.xaxis == "frequency":
401 x = self.dataOut.getFreqRange(1)/1000.
402 xlabel = "Frequency (kHz)"
434 x = self.data.xrange[0]
435 self.xlabel = "Frequency (kHz)"
403 436 elif self.xaxis == "time":
404 x = self.dataOut.getAcfRange(1)
405 xlabel = "Time (ms)"
437 x = self.data.xrange[1]
438 self.xlabel = "Time (ms)"
406 439 else:
407 x = self.dataOut.getVelRange(1)
408 xlabel = "Velocity (m/s)"
440 x = self.data.xrange[2]
441 self.xlabel = "Velocity (m/s)"
442
443 self.titles = []
409 444
410 y = self.dataOut.getHeiRange()
411 z_coh = self.data['cspc_coh']
412 z_phase = self.data['cspc_phase']
445 y = self.data.heights
446 self.y = y
447 spc = self.data['spc']
448 cspc = self.data['cspc']
413 449
414 450 for n in range(self.nrows):
415 ax = self.axes[2*n]
416 ax1 = self.axes[2*n+1]
451 noise = self.data['noise'][n][-1]
452 pair = self.data.pairs[n]
453 ax = self.axes[4*n]
454 ax3 = self.axes[4*n+3]
417 455 if ax.firsttime:
418 self.xmax = self.xmax if self.xmax else np.nanmax(x)
456 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
419 457 self.xmin = self.xmin if self.xmin else -self.xmax
420 self.ymin = self.ymin if self.ymin else np.nanmin(y)
421 self.ymax = self.ymax if self.ymax else np.nanmax(y)
422 self.zmin_coh = self.zmin_coh if self.zmin_coh else 0.0
423 self.zmax_coh = self.zmax_coh if self.zmax_coh else 1.0
424 self.zmin_phase = self.zmin_phase if self.zmin_phase else -180
425 self.zmax_phase = self.zmax_phase if self.zmax_phase else 180
426
427 ax.plot = ax.pcolormesh(x, y, z_coh[n].T,
428 vmin=self.zmin_coh,
429 vmax=self.zmax_coh,
430 cmap=plt.get_cmap(self.colormap_coh)
431 )
432 divider = make_axes_locatable(ax)
433 cax = divider.new_horizontal(size='3%', pad=0.05)
434 self.figure.add_axes(cax)
435 plt.colorbar(ax.plot, cax)
436
437 ax.set_xlim(self.xmin, self.xmax)
438 ax.set_ylim(self.ymin, self.ymax)
439
440 ax.set_ylabel(self.ylabel)
441 ax.set_xlabel(xlabel)
442 ax.firsttime = False
443
444 ax1.plot = ax1.pcolormesh(x, y, z_phase[n].T,
445 vmin=self.zmin_phase,
446 vmax=self.zmax_phase,
447 cmap=plt.get_cmap(self.colormap_phase)
448 )
449 divider = make_axes_locatable(ax1)
450 cax = divider.new_horizontal(size='3%', pad=0.05)
451 self.figure.add_axes(cax)
452 plt.colorbar(ax1.plot, cax)
453
454 ax1.set_xlim(self.xmin, self.xmax)
455 ax1.set_ylim(self.ymin, self.ymax)
456
457 ax1.set_ylabel(self.ylabel)
458 ax1.set_xlabel(xlabel)
459 ax1.firsttime = False
458 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
459 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
460 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
461 vmin=self.zmin,
462 vmax=self.zmax,
463 cmap=plt.get_cmap(self.colormap)
464 )
460 465 else:
461 ax.plot.set_array(z_coh[n].T.ravel())
462 ax1.plot.set_array(z_phase[n].T.ravel())
463
464 ax.set_title('Coherence Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
465 ax1.set_title('Phase Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
466 self.saveTime = self.max_time
467
466 ax.plt.set_array(spc[pair[0]].T.ravel())
467 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
468 468
469 class PlotSpectraMeanData(PlotSpectraData):
470
471 CODE = 'spc_mean'
472 colormap = 'jet'
473
474 def plot(self):
475
476 if self.xaxis == "frequency":
477 x = self.dataOut.getFreqRange(1)/1000.
478 xlabel = "Frequency (kHz)"
479 elif self.xaxis == "time":
480 x = self.dataOut.getAcfRange(1)
481 xlabel = "Time (ms)"
482 else:
483 x = self.dataOut.getVelRange(1)
484 xlabel = "Velocity (m/s)"
485
486 y = self.dataOut.getHeiRange()
487 z = self.data['spc']
488 mean = self.data['mean'][self.max_time]
489
490 for n, ax in enumerate(self.axes):
491
492 if ax.firsttime:
493 self.xmax = self.xmax if self.xmax else np.nanmax(x)
494 self.xmin = self.xmin if self.xmin else -self.xmax
495 self.ymin = self.ymin if self.ymin else np.nanmin(y)
496 self.ymax = self.ymax if self.ymax else np.nanmax(y)
497 self.zmin = self.zmin if self.zmin else np.nanmin(z)
498 self.zmax = self.zmax if self.zmax else np.nanmax(z)
499 ax.plt = ax.pcolormesh(x, y, z[n].T,
469 ax = self.axes[4*n+1]
470 if ax.firsttime:
471 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
500 472 vmin=self.zmin,
501 473 vmax=self.zmax,
502 474 cmap=plt.get_cmap(self.colormap)
503 475 )
504 ax.plt_dop = ax.plot(mean[n], y,
505 color='k')[0]
506
507 divider = make_axes_locatable(ax)
508 cax = divider.new_horizontal(size='3%', pad=0.05)
509 self.figure.add_axes(cax)
510 plt.colorbar(ax.plt, cax)
511
512 ax.set_xlim(self.xmin, self.xmax)
513 ax.set_ylim(self.ymin, self.ymax)
514
515 ax.set_ylabel(self.ylabel)
516 ax.set_xlabel(xlabel)
517
518 ax.firsttime = False
519
520 if self.showprofile:
521 ax.plt_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
522 ax.ax_profile.set_xlim(self.zmin, self.zmax)
523 ax.ax_profile.set_ylim(self.ymin, self.ymax)
524 ax.ax_profile.set_xlabel('dB')
525 ax.ax_profile.grid(b=True, axis='x')
526 ax.plt_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
527 color="k", linestyle="dashed", lw=2)[0]
528 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
529 476 else:
530 ax.plt.set_array(z[n].T.ravel())
531 ax.plt_dop.set_data(mean[n], y)
532 if self.showprofile:
533 ax.plt_profile.set_data(self.data['rti'][self.max_time][n], y)
534 ax.plt_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
477 ax.plt.set_array(spc[pair[1]].T.ravel())
478 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
479
480 out = cspc[n]/numpy.sqrt(spc[pair[0]]*spc[pair[1]])
481 coh = numpy.abs(out)
482 phase = numpy.arctan2(out.imag, out.real)*180/numpy.pi
483
484 ax = self.axes[4*n+2]
485 if ax.firsttime:
486 ax.plt = ax.pcolormesh(x, y, coh.T,
487 vmin=0,
488 vmax=1,
489 cmap=plt.get_cmap(self.colormap_coh)
490 )
491 else:
492 ax.plt.set_array(coh.T.ravel())
493 self.titles.append('Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
535 494
536 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
537 size=8)
495 ax = self.axes[4*n+3]
496 if ax.firsttime:
497 ax.plt = ax.pcolormesh(x, y, phase.T,
498 vmin=-180,
499 vmax=180,
500 cmap=plt.get_cmap(self.colormap_phase)
501 )
502 else:
503 ax.plt.set_array(phase.T.ravel())
504 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
505
538 506 self.saveTime = self.max_time
539 507
540 508
509 class PlotSpectraMeanData(PlotSpectraData):
510 '''
511 Plot for Spectra and Mean
512 '''
513 CODE = 'spc_mean'
514 colormap = 'jro'
515
516
541 517 class PlotRTIData(PlotData):
518 '''
519 Plot for RTI data
520 '''
542 521
543 522 CODE = 'rti'
544 523 colormap = 'jro'
545 524
546 525 def setup(self):
547 self.ncols = 1
548 self.nrows = self.dataOut.nChannels
549 self.width = 10
550 #TODO : arreglar la altura de la figura, esta hardcodeada.
551 #Se arreglo, testear!
552 if self.ind_plt_ch:
553 self.height = 3.2#*self.nrows if self.nrows<6 else 12
554 else:
555 self.height = 2.2*self.nrows if self.nrows<6 else 12
556
557 '''
558 if self.nrows==1:
559 self.height += 1
560 '''
526 self.xaxis = 'time'
527 self.ncols = 1
528 self.nrows = len(self.data.channels)
529 self.nplots = len(self.data.channels)
561 530 self.ylabel = 'Range [Km]'
562 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
563
564 '''
565 Logica:
566 1) Si la variable ind_plt_ch es True, va a crear mas de 1 figura
567 2) guardamos "Figures" en una lista y "axes" en otra, quizas se deberia guardar el
568 axis dentro de "Figures" como un diccionario.
569 '''
570 if self.ind_plt_ch is False: #standard mode
571
572 if self.figure is None: #solo para la priemra vez
573 self.figure = plt.figure(figsize=(self.width, self.height),
574 edgecolor='k',
575 facecolor='w')
576 else:
577 self.figure.clf()
578 self.axes = []
579
580
581 for n in range(self.nrows):
582 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
583 #ax = self.figure(n+1)
584 ax.firsttime = True
585 self.axes.append(ax)
586
587 else : #append one figure foreach channel in channelList
588 if self.figurelist == None:
589 self.figurelist = []
590 for n in range(self.nrows):
591 self.figure = plt.figure(figsize=(self.width, self.height),
592 edgecolor='k',
593 facecolor='w')
594 #add always one subplot
595 self.figurelist.append(self.figure)
596
597 else : # cada dia nuevo limpia el axes, pero mantiene el figure
598 for eachfigure in self.figurelist:
599 eachfigure.clf() # eliminaria todas las figuras de la lista?
600 self.axes = []
601
602 for eachfigure in self.figurelist:
603 ax = eachfigure.add_subplot(1,1,1) #solo 1 axis por figura
604 #ax = self.figure(n+1)
605 ax.firsttime = True
606 #Cada figura tiene un distinto puntero
607 self.axes.append(ax)
608 #plt.close(eachfigure)
609
531 self.cb_label = 'dB'
532 self.titles = ['{} Channel {}'.format(self.CODE.upper(), x) for x in range(self.nrows)]
610 533
611 534 def plot(self):
535 self.x = self.data.times
536 self.y = self.data.heights
537 self.z = self.data[self.CODE]
538 self.z = numpy.ma.masked_invalid(self.z)
612 539
613 if self.ind_plt_ch is False: #standard mode
614 self.x = np.array(self.times)
615 self.y = self.dataOut.getHeiRange()
616 self.z = []
617
618 for ch in range(self.nrows):
619 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
620
621 self.z = np.array(self.z)
622 for n, ax in enumerate(self.axes):
623 x, y, z = self.fill_gaps(*self.decimate())
624 if self.xmin is None:
625 xmin = self.min_time
626 else:
627 xmin = fromtimestamp(int(self.xmin), self.min_time)
628 if self.xmax is None:
629 xmax = xmin + self.xrange*60*60
630 else:
631 xmax = xmin + (self.xmax - self.xmin) * 60 * 60
632 self.zmin = self.zmin if self.zmin else np.min(self.z)
633 self.zmax = self.zmax if self.zmax else np.max(self.z)
634 if ax.firsttime:
635 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
636 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
637 plot = ax.pcolormesh(x, y, z[n].T,
638 vmin=self.zmin,
639 vmax=self.zmax,
640 cmap=plt.get_cmap(self.colormap)
641 )
642 divider = make_axes_locatable(ax)
643 cax = divider.new_horizontal(size='2%', pad=0.05)
644 self.figure.add_axes(cax)
645 plt.colorbar(plot, cax)
646 ax.set_ylim(self.ymin, self.ymax)
647 ax.xaxis.set_major_formatter(FuncFormatter(func))
648 ax.xaxis.set_major_locator(LinearLocator(6))
649 ax.set_ylabel(self.ylabel)
650 # if self.xmin is None:
651 # xmin = self.min_time
652 # else:
653 # xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
654 # datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
655
656 ax.set_xlim(xmin, xmax)
657 ax.firsttime = False
658 else:
659 ax.collections.remove(ax.collections[0])
660 ax.set_xlim(xmin, xmax)
661 plot = ax.pcolormesh(x, y, z[n].T,
662 vmin=self.zmin,
663 vmax=self.zmax,
664 cmap=plt.get_cmap(self.colormap)
665 )
666 ax.set_title('{} {}'.format(self.titles[n],
667 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
668 size=8)
669
670 self.saveTime = self.min_time
671 else :
672 self.x = np.array(self.times)
673 self.y = self.dataOut.getHeiRange()
674 self.z = []
675
676 for ch in range(self.nrows):
677 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
678
679 self.z = np.array(self.z)
680 for n, eachfigure in enumerate(self.figurelist): #estaba ax in axes
681
682 x, y, z = self.fill_gaps(*self.decimate())
683 xmin = self.min_time
684 xmax = xmin+self.xrange*60*60
685 self.zmin = self.zmin if self.zmin else np.min(self.z)
686 self.zmax = self.zmax if self.zmax else np.max(self.z)
687 if self.axes[n].firsttime:
688 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
689 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
690 plot = self.axes[n].pcolormesh(x, y, z[n].T,
691 vmin=self.zmin,
692 vmax=self.zmax,
693 cmap=plt.get_cmap(self.colormap)
694 )
695 divider = make_axes_locatable(self.axes[n])
696 cax = divider.new_horizontal(size='2%', pad=0.05)
697 eachfigure.add_axes(cax)
698 #self.figure2.add_axes(cax)
699 plt.colorbar(plot, cax)
700 self.axes[n].set_ylim(self.ymin, self.ymax)
701
702 self.axes[n].xaxis.set_major_formatter(FuncFormatter(func))
703 self.axes[n].xaxis.set_major_locator(LinearLocator(6))
704
705 self.axes[n].set_ylabel(self.ylabel)
706
707 if self.xmin is None:
708 xmin = self.min_time
709 else:
710 xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
711 datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
712
713 self.axes[n].set_xlim(xmin, xmax)
714 self.axes[n].firsttime = False
715 else:
716 self.axes[n].collections.remove(self.axes[n].collections[0])
717 self.axes[n].set_xlim(xmin, xmax)
718 plot = self.axes[n].pcolormesh(x, y, z[n].T,
719 vmin=self.zmin,
720 vmax=self.zmax,
721 cmap=plt.get_cmap(self.colormap)
722 )
723 self.axes[n].set_title('{} {}'.format(self.titles[n],
724 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
725 size=8)
540 for n, ax in enumerate(self.axes):
541 x, y, z = self.fill_gaps(*self.decimate())
542 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
543 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
544 if ax.firsttime:
545 ax.plt = ax.pcolormesh(x, y, z[n].T,
546 vmin=self.zmin,
547 vmax=self.zmax,
548 cmap=plt.get_cmap(self.colormap)
549 )
550 if self.showprofile:
551 ax.plot_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], self.y)[0]
552 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
553 color="k", linestyle="dashed", lw=1)[0]
554 else:
555 ax.collections.remove(ax.collections[0])
556 ax.plt = ax.pcolormesh(x, y, z[n].T,
557 vmin=self.zmin,
558 vmax=self.zmax,
559 cmap=plt.get_cmap(self.colormap)
560 )
561 if self.showprofile:
562 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
563 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y)
726 564
727 self.saveTime = self.min_time
565 self.saveTime = self.min_time
728 566
729 567
730 568 class PlotCOHData(PlotRTIData):
569 '''
570 Plot for Coherence data
571 '''
731 572
732 573 CODE = 'coh'
733 574
734 575 def setup(self):
735
576 self.xaxis = 'time'
736 577 self.ncols = 1
737 self.nrows = self.dataOut.nPairs
738 self.width = 10
739 self.height = 2.2*self.nrows if self.nrows<6 else 12
740 self.ind_plt_ch = False #just for coherence and phase
741 if self.nrows==1:
742 self.height += 1
743 self.ylabel = 'Range [Km]'
744 self.titles = ['{} Ch{} * Ch{}'.format(self.CODE.upper(), x[0], x[1]) for x in self.dataOut.pairsList]
745
746 if self.figure is None:
747 self.figure = plt.figure(figsize=(self.width, self.height),
748 edgecolor='k',
749 facecolor='w')
578 self.nrows = len(self.data.pairs)
579 self.nplots = len(self.data.pairs)
580 self.ylabel = 'Range [Km]'
581 if self.CODE == 'coh':
582 self.cb_label = ''
583 self.titles = ['Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
750 584 else:
751 self.figure.clf()
752 self.axes = []
585 self.cb_label = 'Degrees'
586 self.titles = ['Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
753 587
754 for n in range(self.nrows):
755 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
756 ax.firsttime = True
757 self.axes.append(ax)
588
589 class PlotPHASEData(PlotCOHData):
590 '''
591 Plot for Phase map data
592 '''
593
594 CODE = 'phase'
595 colormap = 'seismic'
758 596
759 597
760 598 class PlotNoiseData(PlotData):
599 '''
600 Plot for noise
601 '''
602
761 603 CODE = 'noise'
762 604
763 605 def setup(self):
764
606 self.xaxis = 'time'
765 607 self.ncols = 1
766 608 self.nrows = 1
767 self.width = 10
768 self.height = 3.2
609 self.nplots = 1
769 610 self.ylabel = 'Intensity [dB]'
770 611 self.titles = ['Noise']
771
772 if self.figure is None:
773 self.figure = plt.figure(figsize=(self.width, self.height),
774 edgecolor='k',
775 facecolor='w')
776 else:
777 self.figure.clf()
778 self.axes = []
779
780 self.ax = self.figure.add_subplot(self.nrows, self.ncols, 1)
781 self.ax.firsttime = True
612 self.colorbar = False
782 613
783 614 def plot(self):
784 615
785 x = self.times
616 x = self.data.times
786 617 xmin = self.min_time
787 618 xmax = xmin+self.xrange*60*60
788 if self.ax.firsttime:
789 for ch in self.dataOut.channelList:
790 y = [self.data[self.CODE][t][ch] for t in self.times]
791 self.ax.plot(x, y, lw=1, label='Ch{}'.format(ch))
792 self.ax.firsttime = False
793 self.ax.xaxis.set_major_formatter(FuncFormatter(func))
794 self.ax.xaxis.set_major_locator(LinearLocator(6))
795 self.ax.set_ylabel(self.ylabel)
619 Y = self.data[self.CODE]
620
621 if self.axes[0].firsttime:
622 for ch in self.data.channels:
623 y = Y[ch]
624 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
796 625 plt.legend()
797 626 else:
798 for ch in self.dataOut.channelList:
799 y = [self.data[self.CODE][t][ch] for t in self.times]
800 self.ax.lines[ch].set_data(x, y)
801
802 self.ax.set_xlim(xmin, xmax)
803 self.ax.set_ylim(min(y)-5, max(y)+5)
627 for ch in self.data.channels:
628 y = Y[ch]
629 self.axes[0].lines[ch].set_data(x, y)
630
631 self.ymin = numpy.nanmin(Y) - 5
632 self.ymax = numpy.nanmax(Y) + 5
804 633 self.saveTime = self.min_time
805 634
806 635
807 class PlotWindProfilerData(PlotRTIData):
808
809 CODE = 'wind'
810 colormap = 'seismic'
811
812 def setup(self):
813 self.ncols = 1
814 self.nrows = self.dataOut.data_output.shape[0]
815 self.width = 10
816 self.height = 2.2*self.nrows
817 self.ylabel = 'Height [Km]'
818 self.titles = ['Zonal Wind' ,'Meridional Wind', 'Vertical Wind']
819 self.clabels = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
820 self.windFactor = [1, 1, 100]
821
822 if self.figure is None:
823 self.figure = plt.figure(figsize=(self.width, self.height),
824 edgecolor='k',
825 facecolor='w')
826 else:
827 self.figure.clf()
828 self.axes = []
829
830 for n in range(self.nrows):
831 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
832 ax.firsttime = True
833 self.axes.append(ax)
834
835 def plot(self):
836
837 self.x = np.array(self.times)
838 self.y = self.dataOut.heightList
839 self.z = []
840
841 for ch in range(self.nrows):
842 self.z.append([self.data['output'][t][ch] for t in self.times])
843
844 self.z = np.array(self.z)
845 self.z = numpy.ma.masked_invalid(self.z)
846
847 cmap=plt.get_cmap(self.colormap)
848 cmap.set_bad('black', 1.)
849
850 for n, ax in enumerate(self.axes):
851 x, y, z = self.fill_gaps(*self.decimate())
852 xmin = self.min_time
853 xmax = xmin+self.xrange*60*60
854 if ax.firsttime:
855 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
856 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
857 self.zmax = self.zmax if self.zmax else numpy.nanmax(abs(self.z[:-1, :]))
858 self.zmin = self.zmin if self.zmin else -self.zmax
859
860 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
861 vmin=self.zmin,
862 vmax=self.zmax,
863 cmap=cmap
864 )
865 divider = make_axes_locatable(ax)
866 cax = divider.new_horizontal(size='2%', pad=0.05)
867 self.figure.add_axes(cax)
868 cb = plt.colorbar(plot, cax)
869 cb.set_label(self.clabels[n])
870 ax.set_ylim(self.ymin, self.ymax)
871
872 ax.xaxis.set_major_formatter(FuncFormatter(func))
873 ax.xaxis.set_major_locator(LinearLocator(6))
874
875 ax.set_ylabel(self.ylabel)
876
877 ax.set_xlim(xmin, xmax)
878 ax.firsttime = False
879 else:
880 ax.collections.remove(ax.collections[0])
881 ax.set_xlim(xmin, xmax)
882 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
883 vmin=self.zmin,
884 vmax=self.zmax,
885 cmap=plt.get_cmap(self.colormap)
886 )
887 ax.set_title('{} {}'.format(self.titles[n],
888 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
889 size=8)
890
891 self.saveTime = self.min_time
892
893
894 636 class PlotSNRData(PlotRTIData):
637 '''
638 Plot for SNR Data
639 '''
640
895 641 CODE = 'snr'
896 642 colormap = 'jet'
897 643
644
898 645 class PlotDOPData(PlotRTIData):
646 '''
647 Plot for DOPPLER Data
648 '''
649
899 650 CODE = 'dop'
900 651 colormap = 'jet'
901 652
902 653
903 class PlotPHASEData(PlotCOHData):
904 CODE = 'phase'
905 colormap = 'seismic'
906
907
908 654 class PlotSkyMapData(PlotData):
655 '''
656 Plot for meteors detection data
657 '''
909 658
910 659 CODE = 'met'
911 660
912 661 def setup(self):
913 662
914 663 self.ncols = 1
915 664 self.nrows = 1
916 665 self.width = 7.2
917 666 self.height = 7.2
918 667
919 668 self.xlabel = 'Zonal Zenith Angle (deg)'
920 669 self.ylabel = 'Meridional Zenith Angle (deg)'
921 670
922 671 if self.figure is None:
923 672 self.figure = plt.figure(figsize=(self.width, self.height),
924 673 edgecolor='k',
925 674 facecolor='w')
926 675 else:
927 676 self.figure.clf()
928 677
929 678 self.ax = plt.subplot2grid((self.nrows, self.ncols), (0, 0), 1, 1, polar=True)
930 679 self.ax.firsttime = True
931 680
932 681
933 682 def plot(self):
934 683
935 arrayParameters = np.concatenate([self.data['param'][t] for t in self.times])
684 arrayParameters = numpy.concatenate([self.data['param'][t] for t in self.data.times])
936 685 error = arrayParameters[:,-1]
937 686 indValid = numpy.where(error == 0)[0]
938 687 finalMeteor = arrayParameters[indValid,:]
939 688 finalAzimuth = finalMeteor[:,3]
940 689 finalZenith = finalMeteor[:,4]
941 690
942 691 x = finalAzimuth*numpy.pi/180
943 692 y = finalZenith
944 693
945 694 if self.ax.firsttime:
946 695 self.ax.plot = self.ax.plot(x, y, 'bo', markersize=5)[0]
947 696 self.ax.set_ylim(0,90)
948 697 self.ax.set_yticks(numpy.arange(0,90,20))
949 698 self.ax.set_xlabel(self.xlabel)
950 699 self.ax.set_ylabel(self.ylabel)
951 700 self.ax.yaxis.labelpad = 40
952 701 self.ax.firsttime = False
953 702 else:
954 703 self.ax.plot.set_data(x, y)
955 704
956 705
957 706 dt1 = datetime.datetime.fromtimestamp(self.min_time).strftime('%y/%m/%d %H:%M:%S')
958 707 dt2 = datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')
959 708 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
960 709 dt2,
961 710 len(x))
962 711 self.ax.set_title(title, size=8)
963 712
964 713 self.saveTime = self.max_time
714
715 class PlotParamData(PlotRTIData):
716 '''
717 Plot for data_param object
718 '''
719
720 CODE = 'param'
721 colormap = 'seismic'
722
723 def setup(self):
724 self.xaxis = 'time'
725 self.ncols = 1
726 self.nrows = self.data.shape(self.CODE)[0]
727 self.nplots = self.nrows
728 if self.showSNR:
729 self.nrows += 1
730
731 self.ylabel = 'Height [Km]'
732 self.titles = self.data.parameters \
733 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
734 if self.showSNR:
735 self.titles.append('SNR')
736
737 def plot(self):
738 self.data.normalize_heights()
739 self.x = self.data.times
740 self.y = self.data.heights
741 if self.showSNR:
742 self.z = numpy.concatenate(
743 (self.data[self.CODE], self.data['snr'])
744 )
745 else:
746 self.z = self.data[self.CODE]
747
748 self.z = numpy.ma.masked_invalid(self.z)
749
750 for n, ax in enumerate(self.axes):
751
752 x, y, z = self.fill_gaps(*self.decimate())
753
754 if ax.firsttime:
755 if self.zlimits is not None:
756 self.zmin, self.zmax = self.zlimits[n]
757 self.zmax = self.zmax if self.zmax is not None else numpy.nanmax(abs(self.z[:-1, :]))
758 self.zmin = self.zmin if self.zmin is not None else -self.zmax
759 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
760 vmin=self.zmin,
761 vmax=self.zmax,
762 cmap=self.cmaps[n]
763 )
764 else:
765 if self.zlimits is not None:
766 self.zmin, self.zmax = self.zlimits[n]
767 ax.collections.remove(ax.collections[0])
768 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
769 vmin=self.zmin,
770 vmax=self.zmax,
771 cmap=self.cmaps[n]
772 )
773
774 self.saveTime = self.min_time
775
776 class PlotOuputData(PlotParamData):
777 '''
778 Plot data_output object
779 '''
780
781 CODE = 'output'
782 colormap = 'seismic' No newline at end of file
This diff has been collapsed as it changes many lines, (2660 lines changed) Show them Hide them
@@ -1,2805 +1,4045
1 1 import numpy
2 2 import math
3 3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 5 import re
5 6 import datetime
6 7 import copy
7 8 import sys
8 9 import importlib
9 10 import itertools
10
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
13 import copy_reg
14 import cPickle
15 import types
16 from functools import partial
17 import time
18 #from sklearn.cluster import KMeans
19
20 import matplotlib.pyplot as plt
21
22 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
11 23 from jroproc_base import ProcessingUnit, Operation
12 24 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
25 from scipy import asarray as ar,exp
26 from scipy.optimize import curve_fit
13 27
28 import warnings
29 from numpy import NaN
30 from scipy.optimize.optimize import OptimizeWarning
31 warnings.filterwarnings('ignore')
14 32
15 class ParametersProc(ProcessingUnit):
16 33
34 SPEED_OF_LIGHT = 299792458
35
36
37 '''solving pickling issue'''
38
39 def _pickle_method(method):
40 func_name = method.im_func.__name__
41 obj = method.im_self
42 cls = method.im_class
43 return _unpickle_method, (func_name, obj, cls)
44
45 def _unpickle_method(func_name, obj, cls):
46 for cls in cls.mro():
47 try:
48 func = cls.__dict__[func_name]
49 except KeyError:
50 pass
51 else:
52 break
53 return func.__get__(obj, cls)
54
55 class ParametersProc(ProcessingUnit):
56
17 57 nSeconds = None
18 58
19 59 def __init__(self):
20 60 ProcessingUnit.__init__(self)
21
61
22 62 # self.objectDict = {}
23 63 self.buffer = None
24 64 self.firstdatatime = None
25 65 self.profIndex = 0
26 66 self.dataOut = Parameters()
27
67
28 68 def __updateObjFromInput(self):
29
69
30 70 self.dataOut.inputUnit = self.dataIn.type
31
71
32 72 self.dataOut.timeZone = self.dataIn.timeZone
33 73 self.dataOut.dstFlag = self.dataIn.dstFlag
34 74 self.dataOut.errorCount = self.dataIn.errorCount
35 75 self.dataOut.useLocalTime = self.dataIn.useLocalTime
36
76
37 77 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
38 78 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
39 79 self.dataOut.channelList = self.dataIn.channelList
40 80 self.dataOut.heightList = self.dataIn.heightList
41 81 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
42 82 # self.dataOut.nHeights = self.dataIn.nHeights
43 83 # self.dataOut.nChannels = self.dataIn.nChannels
44 84 self.dataOut.nBaud = self.dataIn.nBaud
45 85 self.dataOut.nCode = self.dataIn.nCode
46 86 self.dataOut.code = self.dataIn.code
47 87 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
48 88 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
49 89 # self.dataOut.utctime = self.firstdatatime
50 90 self.dataOut.utctime = self.dataIn.utctime
51 91 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
52 92 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
53 93 self.dataOut.nCohInt = self.dataIn.nCohInt
54 94 # self.dataOut.nIncohInt = 1
55 95 self.dataOut.ippSeconds = self.dataIn.ippSeconds
56 96 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
57 97 self.dataOut.timeInterval1 = self.dataIn.timeInterval
58 self.dataOut.heightList = self.dataIn.getHeiRange()
98 self.dataOut.heightList = self.dataIn.getHeiRange()
59 99 self.dataOut.frequency = self.dataIn.frequency
60 #self.dataOut.noise = self.dataIn.noise
61
100 # self.dataOut.noise = self.dataIn.noise
101
62 102 def run(self):
63
103
64 104 #---------------------- Voltage Data ---------------------------
65
105
66 106 if self.dataIn.type == "Voltage":
67 107
68 108 self.__updateObjFromInput()
69 109 self.dataOut.data_pre = self.dataIn.data.copy()
70 110 self.dataOut.flagNoData = False
71 111 self.dataOut.utctimeInit = self.dataIn.utctime
72 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
112 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
73 113 return
74
114
75 115 #---------------------- Spectra Data ---------------------------
76
116
77 117 if self.dataIn.type == "Spectra":
78 118
79 119 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
80 120 self.dataOut.data_spc = self.dataIn.data_spc
81 121 self.dataOut.data_cspc = self.dataIn.data_cspc
82 122 self.dataOut.nProfiles = self.dataIn.nProfiles
83 123 self.dataOut.nIncohInt = self.dataIn.nIncohInt
84 124 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
85 125 self.dataOut.ippFactor = self.dataIn.ippFactor
86 #self.dataOut.normFactor = self.dataIn.getNormFactor()
87 self.dataOut.pairsList = self.dataIn.pairsList
88 self.dataOut.groupList = self.dataIn.pairsList
89 126 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
127 self.dataOut.spc_noise = self.dataIn.getNoise()
128 self.dataOut.spc_range = (self.dataIn.getFreqRange(1)/1000. , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
129 self.dataOut.pairsList = self.dataIn.pairsList
130 self.dataOut.groupList = self.dataIn.pairsList
90 131 self.dataOut.flagNoData = False
91
132
133 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
134 self.dataOut.ChanDist = self.dataIn.ChanDist
135 else: self.dataOut.ChanDist = None
136
137 if hasattr(self.dataIn, 'VelRange'): #Velocities range
138 self.dataOut.VelRange = self.dataIn.VelRange
139 else: self.dataOut.VelRange = None
140
141 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
142 self.dataOut.RadarConst = self.dataIn.RadarConst
143
144 if hasattr(self.dataIn, 'NPW'): #NPW
145 self.dataOut.NPW = self.dataIn.NPW
146
147 if hasattr(self.dataIn, 'COFA'): #COFA
148 self.dataOut.COFA = self.dataIn.COFA
149
150
151
92 152 #---------------------- Correlation Data ---------------------------
93
153
94 154 if self.dataIn.type == "Correlation":
95 155 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
96
156
97 157 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
98 158 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
99 159 self.dataOut.groupList = (acf_pairs, ccf_pairs)
100
160
101 161 self.dataOut.abscissaList = self.dataIn.lagRange
102 162 self.dataOut.noise = self.dataIn.noise
103 163 self.dataOut.data_SNR = self.dataIn.SNR
104 164 self.dataOut.flagNoData = False
105 165 self.dataOut.nAvg = self.dataIn.nAvg
106
166
107 167 #---------------------- Parameters Data ---------------------------
108
168
109 169 if self.dataIn.type == "Parameters":
110 170 self.dataOut.copy(self.dataIn)
111 self.dataOut.utctimeInit = self.dataIn.utctime
112 171 self.dataOut.flagNoData = False
113
172
114 173 return True
115
174
116 175 self.__updateObjFromInput()
117 176 self.dataOut.utctimeInit = self.dataIn.utctime
118 177 self.dataOut.paramInterval = self.dataIn.timeInterval
119
178
120 179 return
121 180
122 class SpectralMoments(Operation):
123 181
182 def target(tups):
183
184 obj, args = tups
185 #print 'TARGETTT', obj, args
186 return obj.FitGau(args)
187
188 class GaussianFit(Operation):
189
124 190 '''
125 Function SpectralMoments()
191 Function that fit of one and two generalized gaussians (gg) based
192 on the PSD shape across an "power band" identified from a cumsum of
193 the measured spectrum - noise.
194
195 Input:
196 self.dataOut.data_pre : SelfSpectra
197
198 Output:
199 self.dataOut.GauSPC : SPC_ch1, SPC_ch2
200
201 '''
202 def __init__(self, **kwargs):
203 Operation.__init__(self, **kwargs)
204 self.i=0
205
206
207 def run(self, dataOut, num_intg=7, pnoise=1., vel_arr=None, SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
208 """This routine will find a couple of generalized Gaussians to a power spectrum
209 input: spc
210 output:
211 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
212 """
213
214 self.spc = dataOut.data_pre[0].copy()
215
216
217 print 'SelfSpectra Shape', numpy.asarray(self.spc).shape
218
219
220 #plt.figure(50)
221 #plt.subplot(121)
222 #plt.plot(self.spc,'k',label='spc(66)')
223 #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
224 #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
225 #plt.plot(xFrec,FitGauss,'yo:',label='fit')
226 #plt.legend()
227 #plt.title('DATOS A ALTURA DE 7500 METROS')
228 #plt.show()
229
230 self.Num_Hei = self.spc.shape[2]
231 #self.Num_Bin = len(self.spc)
232 self.Num_Bin = self.spc.shape[1]
233 self.Num_Chn = self.spc.shape[0]
234
235 Vrange = dataOut.abscissaList
236
237 #print 'self.spc2', numpy.asarray(self.spc).shape
238
239 GauSPC = numpy.empty([2,self.Num_Bin,self.Num_Hei])
240 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
241 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
242 SPC_ch1[:] = numpy.NaN
243 SPC_ch2[:] = numpy.NaN
126 244
127 Calculates moments (power, mean, standard deviation) and SNR of the signal
245
246 start_time = time.time()
247
248 noise_ = dataOut.spc_noise[0].copy()
249
250
251
252 pool = Pool(processes=self.Num_Chn)
253 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
254 objs = [self for __ in range(self.Num_Chn)]
255 attrs = zip(objs, args)
256 gauSPC = pool.map(target, attrs)
257 dataOut.GauSPC = numpy.asarray(gauSPC)
258 # ret = []
259 # for n in range(self.Num_Chn):
260 # self.FitGau(args[n])
261 # dataOut.GauSPC = ret
262
263
264
265 # for ch in range(self.Num_Chn):
266 #
267 # for ht in range(self.Num_Hei):
268 # #print (numpy.asarray(self.spc).shape)
269 # spc = numpy.asarray(self.spc)[ch,:,ht]
270 #
271 # #############################################
272 # # normalizing spc and noise
273 # # This part differs from gg1
274 # spc_norm_max = max(spc)
275 # spc = spc / spc_norm_max
276 # pnoise = pnoise / spc_norm_max
277 # #############################################
278 #
279 # if abs(vel_arr[0])<15.0: # this switch is for spectra collected with different length IPP's
280 # fatspectra=1.0
281 # else:
282 # fatspectra=0.5
283 #
284 # wnoise = noise_ / spc_norm_max
285 # #print 'wnoise', noise_, dataOut.spc_noise[0], wnoise
286 # #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
287 # #if wnoise>1.1*pnoise: # to be tested later
288 # # wnoise=pnoise
289 # noisebl=wnoise*0.9; noisebh=wnoise*1.1
290 # spc=spc-wnoise
291 #
292 # minx=numpy.argmin(spc)
293 # spcs=numpy.roll(spc,-minx)
294 # cum=numpy.cumsum(spcs)
295 # tot_noise=wnoise * self.Num_Bin #64;
296 # #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
297 # #snr=tot_signal/tot_noise
298 # #snr=cum[-1]/tot_noise
299 #
300 # #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
301 #
302 # snr = sum(spcs)/tot_noise
303 # snrdB=10.*numpy.log10(snr)
304 #
305 # #if snrdB < -9 :
306 # # snrdB = numpy.NaN
307 # # continue
308 #
309 # #print 'snr',snrdB # , sum(spcs) , tot_noise
310 #
311 #
312 # #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
313 # # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
314 #
315 # cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
316 # cumlo=cummax*epsi;
317 # cumhi=cummax*(1-epsi)
318 # powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
319 #
320 # #if len(powerindex)==1:
321 # ##return [numpy.mod(powerindex[0]+minx,64),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
322 # #return [numpy.mod(powerindex[0]+minx, self.Num_Bin ),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
323 # #elif len(powerindex)<4*fatspectra:
324 # #return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
325 #
326 # if len(powerindex) < 1:# case for powerindex 0
327 # continue
328 # powerlo=powerindex[0]
329 # powerhi=powerindex[-1]
330 # powerwidth=powerhi-powerlo
331 #
332 # firstpeak=powerlo+powerwidth/10.# first gaussian energy location
333 # secondpeak=powerhi-powerwidth/10.#second gaussian energy location
334 # midpeak=(firstpeak+secondpeak)/2.
335 # firstamp=spcs[int(firstpeak)]
336 # secondamp=spcs[int(secondpeak)]
337 # midamp=spcs[int(midpeak)]
338 # #x=numpy.spc.shape[1]
339 #
340 # #x=numpy.arange(64)
341 # x=numpy.arange( self.Num_Bin )
342 # y_data=spc+wnoise
343 #
344 # # single gaussian
345 # #shift0=numpy.mod(midpeak+minx,64)
346 # shift0=numpy.mod(midpeak+minx, self.Num_Bin )
347 # width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
348 # power0=2.
349 # amplitude0=midamp
350 # state0=[shift0,width0,amplitude0,power0,wnoise]
351 # #bnds=((0,63),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
352 # bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
353 # #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(0.1,0.5))
354 # # bnds = range of fft, power width, amplitude, power, noise
355 # lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
356 #
357 # chiSq1=lsq1[1];
358 # jack1= self.y_jacobian1(x,lsq1[0])
359 #
360 #
361 # try:
362 # sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
363 # except:
364 # std1=32.; sigmas1=numpy.ones(5)
365 # else:
366 # std1=sigmas1[0]
367 #
368 #
369 # if fatspectra<1.0 and powerwidth<4:
370 # choice=0
371 # Amplitude0=lsq1[0][2]
372 # shift0=lsq1[0][0]
373 # width0=lsq1[0][1]
374 # p0=lsq1[0][3]
375 # Amplitude1=0.
376 # shift1=0.
377 # width1=0.
378 # p1=0.
379 # noise=lsq1[0][4]
380 # #return (numpy.array([shift0,width0,Amplitude0,p0]),
381 # # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
382 #
383 # # two gaussians
384 # #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
385 # shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
386 # shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
387 # width0=powerwidth/6.;
388 # width1=width0
389 # power0=2.;
390 # power1=power0
391 # amplitude0=firstamp;
392 # amplitude1=secondamp
393 # state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
394 # #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
395 # 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))
396 # #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))
397 #
398 # lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
399 #
400 #
401 # chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
402 #
403 #
404 # try:
405 # sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
406 # except:
407 # std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
408 # else:
409 # std2a=sigmas2[0]; std2b=sigmas2[4]
410 #
411 #
412 #
413 # 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)
414 #
415 # if snrdB>-9: # when SNR is strong pick the peak with least shift (LOS velocity) error
416 # if oneG:
417 # choice=0
418 # else:
419 # w1=lsq2[0][1]; w2=lsq2[0][5]
420 # a1=lsq2[0][2]; a2=lsq2[0][6]
421 # p1=lsq2[0][3]; p2=lsq2[0][7]
422 # s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1; s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
423 # gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
424 #
425 # if gp1>gp2:
426 # if a1>0.7*a2:
427 # choice=1
428 # else:
429 # choice=2
430 # elif gp2>gp1:
431 # if a2>0.7*a1:
432 # choice=2
433 # else:
434 # choice=1
435 # else:
436 # choice=numpy.argmax([a1,a2])+1
437 # #else:
438 # #choice=argmin([std2a,std2b])+1
439 #
440 # else: # with low SNR go to the most energetic peak
441 # choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
442 #
443 # #print 'choice',choice
444 #
445 # if choice==0: # pick the single gaussian fit
446 # Amplitude0=lsq1[0][2]
447 # shift0=lsq1[0][0]
448 # width0=lsq1[0][1]
449 # p0=lsq1[0][3]
450 # Amplitude1=0.
451 # shift1=0.
452 # width1=0.
453 # p1=0.
454 # noise=lsq1[0][4]
455 # elif choice==1: # take the first one of the 2 gaussians fitted
456 # Amplitude0 = lsq2[0][2]
457 # shift0 = lsq2[0][0]
458 # width0 = lsq2[0][1]
459 # p0 = lsq2[0][3]
460 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
461 # shift1 = lsq2[0][4] # This is 0 in gg1
462 # width1 = lsq2[0][5] # This is 0 in gg1
463 # p1 = lsq2[0][7] # This is 0 in gg1
464 # noise = lsq2[0][8]
465 # else: # the second one
466 # Amplitude0 = lsq2[0][6]
467 # shift0 = lsq2[0][4]
468 # width0 = lsq2[0][5]
469 # p0 = lsq2[0][7]
470 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
471 # shift1 = lsq2[0][0] # This is 0 in gg1
472 # width1 = lsq2[0][1] # This is 0 in gg1
473 # p1 = lsq2[0][3] # This is 0 in gg1
474 # noise = lsq2[0][8]
475 #
476 # #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
477 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
478 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
479 # #print 'SPC_ch1.shape',SPC_ch1.shape
480 # #print 'SPC_ch2.shape',SPC_ch2.shape
481 # #dataOut.data_param = SPC_ch1
482 # GauSPC[0] = SPC_ch1
483 # GauSPC[1] = SPC_ch2
484
485 # #plt.gcf().clear()
486 # plt.figure(50+self.i)
487 # self.i=self.i+1
488 # #plt.subplot(121)
489 # plt.plot(self.spc,'k')#,label='spc(66)')
490 # plt.plot(SPC_ch1[ch,ht],'b')#,label='gg1')
491 # #plt.plot(SPC_ch2,'r')#,label='gg2')
492 # #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
493 # #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
494 # #plt.plot(xFrec,FitGauss,'yo:',label='fit')
495 # plt.legend()
496 # plt.title('DATOS A ALTURA DE 7500 METROS')
497 # plt.show()
498 # print 'shift0', shift0
499 # print 'Amplitude0', Amplitude0
500 # print 'width0', width0
501 # print 'p0', p0
502 # print '========================'
503 # print 'shift1', shift1
504 # print 'Amplitude1', Amplitude1
505 # print 'width1', width1
506 # print 'p1', p1
507 # print 'noise', noise
508 # print 's_noise', wnoise
509
510 print '========================================================'
511 print 'total_time: ', time.time()-start_time
512
513 # re-normalizing spc and noise
514 # This part differs from gg1
515
516
517
518 ''' Parameters:
519 1. Amplitude
520 2. Shift
521 3. Width
522 4. Power
523 '''
524
525
526 ###############################################################################
527 def FitGau(self, X):
528
529 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
530 #print 'VARSSSS', ch, pnoise, noise, num_intg
531
532 #print 'HEIGHTS', self.Num_Hei
533
534 GauSPC = []
535 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
536 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
537 SPC_ch1[:] = 0#numpy.NaN
538 SPC_ch2[:] = 0#numpy.NaN
539
540
541
542 for ht in range(self.Num_Hei):
543 #print (numpy.asarray(self.spc).shape)
544
545 #print 'TTTTT', ch , ht
546 #print self.spc.shape
547
548
549 spc = numpy.asarray(self.spc)[ch,:,ht]
550
551 #############################################
552 # normalizing spc and noise
553 # This part differs from gg1
554 spc_norm_max = max(spc)
555 spc = spc / spc_norm_max
556 pnoise = pnoise / spc_norm_max
557 #############################################
558
559 fatspectra=1.0
560
561 wnoise = noise_ / spc_norm_max
562 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
563 #if wnoise>1.1*pnoise: # to be tested later
564 # wnoise=pnoise
565 noisebl=wnoise*0.9; noisebh=wnoise*1.1
566 spc=spc-wnoise
567 # print 'wnoise', noise_[0], spc_norm_max, wnoise
568 minx=numpy.argmin(spc)
569 spcs=numpy.roll(spc,-minx)
570 cum=numpy.cumsum(spcs)
571 tot_noise=wnoise * self.Num_Bin #64;
572 #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
573 #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
574 #snr=tot_signal/tot_noise
575 #snr=cum[-1]/tot_noise
576 snr = sum(spcs)/tot_noise
577 snrdB=10.*numpy.log10(snr)
578
579 if snrdB < SNRlimit :
580 snr = numpy.NaN
581 SPC_ch1[:,ht] = 0#numpy.NaN
582 SPC_ch1[:,ht] = 0#numpy.NaN
583 GauSPC = (SPC_ch1,SPC_ch2)
584 continue
585 #print 'snr',snrdB #, sum(spcs) , tot_noise
586
587
588
589 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
590 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
591
592 cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
593 cumlo=cummax*epsi;
594 cumhi=cummax*(1-epsi)
595 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
596
597
598 if len(powerindex) < 1:# case for powerindex 0
599 continue
600 powerlo=powerindex[0]
601 powerhi=powerindex[-1]
602 powerwidth=powerhi-powerlo
603
604 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
605 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
606 midpeak=(firstpeak+secondpeak)/2.
607 firstamp=spcs[int(firstpeak)]
608 secondamp=spcs[int(secondpeak)]
609 midamp=spcs[int(midpeak)]
610
611 x=numpy.arange( self.Num_Bin )
612 y_data=spc+wnoise
613
614 # single gaussian
615 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
616 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
617 power0=2.
618 amplitude0=midamp
619 state0=[shift0,width0,amplitude0,power0,wnoise]
620 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
621 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
622
623 chiSq1=lsq1[1];
624 jack1= self.y_jacobian1(x,lsq1[0])
625
626
627 try:
628 sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
629 except:
630 std1=32.; sigmas1=numpy.ones(5)
631 else:
632 std1=sigmas1[0]
633
634
635 if fatspectra<1.0 and powerwidth<4:
636 choice=0
637 Amplitude0=lsq1[0][2]
638 shift0=lsq1[0][0]
639 width0=lsq1[0][1]
640 p0=lsq1[0][3]
641 Amplitude1=0.
642 shift1=0.
643 width1=0.
644 p1=0.
645 noise=lsq1[0][4]
646 #return (numpy.array([shift0,width0,Amplitude0,p0]),
647 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
648
649 # two gaussians
650 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
651 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
652 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
653 width0=powerwidth/6.;
654 width1=width0
655 power0=2.;
656 power1=power0
657 amplitude0=firstamp;
658 amplitude1=secondamp
659 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
660 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
661 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))
662 #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))
663
664 lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
665
666
667 chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
668
669
670 try:
671 sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
672 except:
673 std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
674 else:
675 std2a=sigmas2[0]; std2b=sigmas2[4]
676
677
678
679 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)
680
681 if snrdB>-6: # when SNR is strong pick the peak with least shift (LOS velocity) error
682 if oneG:
683 choice=0
684 else:
685 w1=lsq2[0][1]; w2=lsq2[0][5]
686 a1=lsq2[0][2]; a2=lsq2[0][6]
687 p1=lsq2[0][3]; p2=lsq2[0][7]
688 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
689 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
690 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
691
692 if gp1>gp2:
693 if a1>0.7*a2:
694 choice=1
695 else:
696 choice=2
697 elif gp2>gp1:
698 if a2>0.7*a1:
699 choice=2
700 else:
701 choice=1
702 else:
703 choice=numpy.argmax([a1,a2])+1
704 #else:
705 #choice=argmin([std2a,std2b])+1
706
707 else: # with low SNR go to the most energetic peak
708 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
709
710
711 shift0=lsq2[0][0]; vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
712 shift1=lsq2[0][4]; vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
713
714 max_vel = 20
715
716 #first peak will be 0, second peak will be 1
717 if vel0 > 0 and vel0 < max_vel : #first peak is in the correct range
718 shift0=lsq2[0][0]
719 width0=lsq2[0][1]
720 Amplitude0=lsq2[0][2]
721 p0=lsq2[0][3]
722
723 shift1=lsq2[0][4]
724 width1=lsq2[0][5]
725 Amplitude1=lsq2[0][6]
726 p1=lsq2[0][7]
727 noise=lsq2[0][8]
728 else:
729 shift1=lsq2[0][0]
730 width1=lsq2[0][1]
731 Amplitude1=lsq2[0][2]
732 p1=lsq2[0][3]
733
734 shift0=lsq2[0][4]
735 width0=lsq2[0][5]
736 Amplitude0=lsq2[0][6]
737 p0=lsq2[0][7]
738 noise=lsq2[0][8]
739
740 if Amplitude0<0.1: # in case the peak is noise
741 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
742 if Amplitude1<0.1:
743 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
744
745
746 # if choice==0: # pick the single gaussian fit
747 # Amplitude0=lsq1[0][2]
748 # shift0=lsq1[0][0]
749 # width0=lsq1[0][1]
750 # p0=lsq1[0][3]
751 # Amplitude1=0.
752 # shift1=0.
753 # width1=0.
754 # p1=0.
755 # noise=lsq1[0][4]
756 # elif choice==1: # take the first one of the 2 gaussians fitted
757 # Amplitude0 = lsq2[0][2]
758 # shift0 = lsq2[0][0]
759 # width0 = lsq2[0][1]
760 # p0 = lsq2[0][3]
761 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
762 # shift1 = lsq2[0][4] # This is 0 in gg1
763 # width1 = lsq2[0][5] # This is 0 in gg1
764 # p1 = lsq2[0][7] # This is 0 in gg1
765 # noise = lsq2[0][8]
766 # else: # the second one
767 # Amplitude0 = lsq2[0][6]
768 # shift0 = lsq2[0][4]
769 # width0 = lsq2[0][5]
770 # p0 = lsq2[0][7]
771 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
772 # shift1 = lsq2[0][0] # This is 0 in gg1
773 # width1 = lsq2[0][1] # This is 0 in gg1
774 # p1 = lsq2[0][3] # This is 0 in gg1
775 # noise = lsq2[0][8]
776
777 #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
778 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
779 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
780 #print 'SPC_ch1.shape',SPC_ch1.shape
781 #print 'SPC_ch2.shape',SPC_ch2.shape
782 #dataOut.data_param = SPC_ch1
783 GauSPC = (SPC_ch1,SPC_ch2)
784 #GauSPC[1] = SPC_ch2
785
786 # print 'shift0', shift0
787 # print 'Amplitude0', Amplitude0
788 # print 'width0', width0
789 # print 'p0', p0
790 # print '========================'
791 # print 'shift1', shift1
792 # print 'Amplitude1', Amplitude1
793 # print 'width1', width1
794 # print 'p1', p1
795 # print 'noise', noise
796 # print 's_noise', wnoise
797
798 return GauSPC
799
800
801 def y_jacobian1(self,x,state): # This function is for further analysis of generalized Gaussians, it is not too importan for the signal discrimination.
802 y_model=self.y_model1(x,state)
803 s0,w0,a0,p0,n=state
804 e0=((x-s0)/w0)**2;
805
806 e0u=((x-s0-self.Num_Bin)/w0)**2;
807
808 e0d=((x-s0+self.Num_Bin)/w0)**2
809 m0=numpy.exp(-0.5*e0**(p0/2.));
810 m0u=numpy.exp(-0.5*e0u**(p0/2.));
811 m0d=numpy.exp(-0.5*e0d**(p0/2.))
812 JA=m0+m0u+m0d
813 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
814
815 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
816
817 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
818 jack1=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,1./y_model])
819 return jack1.T
820
821 def y_jacobian2(self,x,state):
822 y_model=self.y_model2(x,state)
823 s0,w0,a0,p0,s1,w1,a1,p1,n=state
824 e0=((x-s0)/w0)**2;
825
826 e0u=((x-s0- self.Num_Bin )/w0)**2;
827
828 e0d=((x-s0+ self.Num_Bin )/w0)**2
829 e1=((x-s1)/w1)**2;
830
831 e1u=((x-s1- self.Num_Bin )/w1)**2;
832
833 e1d=((x-s1+ self.Num_Bin )/w1)**2
834 m0=numpy.exp(-0.5*e0**(p0/2.));
835 m0u=numpy.exp(-0.5*e0u**(p0/2.));
836 m0d=numpy.exp(-0.5*e0d**(p0/2.))
837 m1=numpy.exp(-0.5*e1**(p1/2.));
838 m1u=numpy.exp(-0.5*e1u**(p1/2.));
839 m1d=numpy.exp(-0.5*e1d**(p1/2.))
840 JA=m0+m0u+m0d
841 JA1=m1+m1u+m1d
842 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
843 JP1=(-1/4.)*a1*m1*e1**(p1/2.)*numpy.log(e1)+(-1/4.)*a1*m1u*e1u**(p1/2.)*numpy.log(e1u)+(-1/4.)*a1*m1d*e1d**(p1/2.)*numpy.log(e1d)
844
845 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
846
847 JS1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)
848
849 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
850
851 JW1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)**2+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)**2+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)**2
852 jack2=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,JS1/y_model,JW1/y_model,JA1/y_model,JP1/y_model,1./y_model])
853 return jack2.T
854
855 def y_model1(self,x,state):
856 shift0,width0,amplitude0,power0,noise=state
857 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
858
859 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
860
861 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
862 return model0+model0u+model0d+noise
863
864 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
865 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
866 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
867
868 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
869
870 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
871 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
872
873 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
874
875 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
876 return model0+model0u+model0d+model1+model1u+model1d+noise
877
878 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.
128 879
129 Type of dataIn: Spectra
880 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
881
882 def misfit2(self,state,y_data,x,num_intg):
883 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
884
130 885
131 Configuration Parameters:
886 class PrecipitationProc(Operation):
887
888 '''
889 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
890
891 Input:
892 self.dataOut.data_pre : SelfSpectra
893
894 Output:
895
896 self.dataOut.data_output : Reflectivity factor, rainfall Rate
897
898
899 Parameters affected:
900 '''
901
902
903 def run(self, dataOut, radar=None, Pt=None, Gt=None, Gr=None, Lambda=None, aL=None,
904 tauW=None, ThetaT=None, ThetaR=None, Km = 0.93, Altitude=None):
905
906 self.spc = dataOut.data_pre[0].copy()
907 self.Num_Hei = self.spc.shape[2]
908 self.Num_Bin = self.spc.shape[1]
909 self.Num_Chn = self.spc.shape[0]
910
911 Velrange = dataOut.abscissaList
912
913 if radar == "MIRA35C" :
914
915 Ze = self.dBZeMODE2(dataOut)
916
917 else:
918
919 self.Pt = Pt
920 self.Gt = Gt
921 self.Gr = Gr
922 self.Lambda = Lambda
923 self.aL = aL
924 self.tauW = tauW
925 self.ThetaT = ThetaT
926 self.ThetaR = ThetaR
927
928 RadarConstant = GetRadarConstant()
929 SPCmean = numpy.mean(self.spc,0)
930 ETA = numpy.zeros(self.Num_Hei)
931 Pr = numpy.sum(SPCmean,0)
932
933 #for R in range(self.Num_Hei):
934 # ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
935
936 D_range = numpy.zeros(self.Num_Hei)
937 EqSec = numpy.zeros(self.Num_Hei)
938 del_V = numpy.zeros(self.Num_Hei)
939
940 for R in range(self.Num_Hei):
941 ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
942
943 h = R + Altitude #Range from ground to radar pulse altitude
944 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
945
946 D_range[R] = numpy.log( (9.65 - (Velrange[R]/del_V[R])) / 10.3 ) / -0.6 #Range of Diameter of drops related to velocity
947 SIGMA[R] = numpy.pi**5 / Lambda**4 * Km * D_range[R]**6 #Equivalent Section of drops (sigma)
948
949 N_dist[R] = ETA[R] / SIGMA[R]
950
951 Ze = (ETA * Lambda**4) / (numpy.pi * Km)
952 Z = numpy.sum( N_dist * D_range**6 )
953 RR = 6*10**-4*numpy.pi * numpy.sum( D_range**3 * N_dist * Velrange ) #Rainfall rate
954
955
956 RR = (Ze/200)**(1/1.6)
957 dBRR = 10*numpy.log10(RR)
958
959 dBZe = 10*numpy.log10(Ze)
960 dataOut.data_output = Ze
961 dataOut.data_param = numpy.ones([2,self.Num_Hei])
962 dataOut.channelList = [0,1]
963 print 'channelList', dataOut.channelList
964 dataOut.data_param[0]=dBZe
965 dataOut.data_param[1]=dBRR
966 print 'RR SHAPE', dBRR.shape
967 print 'Ze SHAPE', dBZe.shape
968 print 'dataOut.data_param SHAPE', dataOut.data_param.shape
969
970
971 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
972
973 NPW = dataOut.NPW
974 COFA = dataOut.COFA
975
976 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
977 RadarConst = dataOut.RadarConst
978 #frequency = 34.85*10**9
979
980 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
981 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
982
983 ETA = numpy.sum(SNR,1)
984 print 'ETA' , ETA
985 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
986
987 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
988
989 for r in range(self.Num_Hei):
990
991 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
992 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
993
994 return Ze
995
996 def GetRadarConstant(self):
997
998 """
999 Constants:
1000
1001 Pt: Transmission Power dB
1002 Gt: Transmission Gain dB
1003 Gr: Reception Gain dB
1004 Lambda: Wavelenght m
1005 aL: Attenuation loses dB
1006 tauW: Width of transmission pulse s
1007 ThetaT: Transmission antenna bean angle rad
1008 ThetaR: Reception antenna beam angle rad
1009
1010 """
1011 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1012 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1013 RadarConstant = Numerator / Denominator
1014
1015 return RadarConstant
1016
1017
1018
1019 class FullSpectralAnalysis(Operation):
1020
1021 """
1022 Function that implements Full Spectral Analisys technique.
1023
1024 Input:
1025 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
1026 self.dataOut.groupList : Pairlist of channels
1027 self.dataOut.ChanDist : Physical distance between receivers
1028
1029
1030 Output:
1031
1032 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
1033
1034
1035 Parameters affected: Winds, height range, SNR
1036
1037 """
1038 def run(self, dataOut, E01=None, E02=None, E12=None, N01=None, N02=None, N12=None, SNRlimit=7):
1039
1040 spc = dataOut.data_pre[0].copy()
1041 cspc = dataOut.data_pre[1].copy()
1042
1043 nChannel = spc.shape[0]
1044 nProfiles = spc.shape[1]
1045 nHeights = spc.shape[2]
1046
1047 pairsList = dataOut.groupList
1048 if dataOut.ChanDist is not None :
1049 ChanDist = dataOut.ChanDist
1050 else:
1051 ChanDist = numpy.array([[E01, N01],[E02,N02],[E12,N12]])
1052
1053 #print 'ChanDist', ChanDist
1054
1055 if dataOut.VelRange is not None:
1056 VelRange= dataOut.VelRange
1057 else:
1058 VelRange= dataOut.abscissaList
1059
1060 ySamples=numpy.ones([nChannel,nProfiles])
1061 phase=numpy.ones([nChannel,nProfiles])
1062 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
1063 coherence=numpy.ones([nChannel,nProfiles])
1064 PhaseSlope=numpy.ones(nChannel)
1065 PhaseInter=numpy.ones(nChannel)
1066 dataSNR = dataOut.data_SNR
1067
1068
1069
1070 data = dataOut.data_pre
1071 noise = dataOut.noise
1072 print 'noise',noise
1073 #SNRdB = 10*numpy.log10(dataOut.data_SNR)
1074
1075 FirstMoment = numpy.average(dataOut.data_param[:,1,:],0)
1076 #SNRdBMean = []
132 1077
1078
1079 #for j in range(nHeights):
1080 # FirstMoment = numpy.append(FirstMoment,numpy.mean([dataOut.data_param[0,1,j],dataOut.data_param[1,1,j],dataOut.data_param[2,1,j]]))
1081 # SNRdBMean = numpy.append(SNRdBMean,numpy.mean([SNRdB[0,j],SNRdB[1,j],SNRdB[2,j]]))
1082
1083 data_output=numpy.ones([3,spc.shape[2]])*numpy.NaN
1084
1085 velocityX=[]
1086 velocityY=[]
1087 velocityV=[]
1088
1089 dbSNR = 10*numpy.log10(dataSNR)
1090 dbSNR = numpy.average(dbSNR,0)
1091 for Height in range(nHeights):
1092
1093 [Vzon,Vmer,Vver, GaussCenter]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR[Height], SNRlimit)
1094
1095 if abs(Vzon)<100. and abs(Vzon)> 0.:
1096 velocityX=numpy.append(velocityX, Vzon)#Vmag
1097
1098 else:
1099 print 'Vzon',Vzon
1100 velocityX=numpy.append(velocityX, numpy.NaN)
1101
1102 if abs(Vmer)<100. and abs(Vmer) > 0.:
1103 velocityY=numpy.append(velocityY, Vmer)#Vang
1104
1105 else:
1106 print 'Vmer',Vmer
1107 velocityY=numpy.append(velocityY, numpy.NaN)
1108
1109 if dbSNR[Height] > SNRlimit:
1110 velocityV=numpy.append(velocityV, FirstMoment[Height])
1111 else:
1112 velocityV=numpy.append(velocityV, numpy.NaN)
1113 #FirstMoment[Height]= numpy.NaN
1114 # if SNRdBMean[Height] <12:
1115 # FirstMoment[Height] = numpy.NaN
1116 # velocityX[Height] = numpy.NaN
1117 # velocityY[Height] = numpy.NaN
1118
1119
1120 data_output[0]=numpy.array(velocityX)
1121 data_output[1]=numpy.array(velocityY)
1122 data_output[2]=-velocityV#FirstMoment
1123
1124 print ' '
1125 #print 'FirstMoment'
1126 #print FirstMoment
1127 print 'velocityX',data_output[0]
1128 print ' '
1129 print 'velocityY',data_output[1]
1130 #print numpy.array(velocityY)
1131 print ' '
1132 #print 'SNR'
1133 #print 10*numpy.log10(dataOut.data_SNR)
1134 #print numpy.shape(10*numpy.log10(dataOut.data_SNR))
1135 print ' '
1136
1137
1138 dataOut.data_output=data_output
1139 return
1140
1141
1142 def moving_average(self,x, N=2):
1143 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1144
1145 def gaus(self,xSamples,a,x0,sigma):
1146 return a*numpy.exp(-(xSamples-x0)**2/(2*sigma**2))
1147
1148 def Find(self,x,value):
1149 for index in range(len(x)):
1150 if x[index]==value:
1151 return index
1152
1153 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR, SNRlimit):
1154
1155 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
1156 phase=numpy.ones([spc.shape[0],spc.shape[1]])
1157 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
1158 coherence=numpy.ones([spc.shape[0],spc.shape[1]])
1159 PhaseSlope=numpy.ones(spc.shape[0])
1160 PhaseInter=numpy.ones(spc.shape[0])
1161 xFrec=VelRange
1162
1163 '''Getting Eij and Nij'''
1164
1165 E01=ChanDist[0][0]
1166 N01=ChanDist[0][1]
1167
1168 E02=ChanDist[1][0]
1169 N02=ChanDist[1][1]
1170
1171 E12=ChanDist[2][0]
1172 N12=ChanDist[2][1]
1173
1174 z = spc.copy()
1175 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1176
1177 for i in range(spc.shape[0]):
1178
1179 '''****** Line of Data SPC ******'''
1180 zline=z[i,:,Height]
1181
1182 '''****** SPC is normalized ******'''
1183 FactNorm= (zline.copy()-noise[i]) / numpy.sum(zline.copy())
1184 FactNorm= FactNorm/numpy.sum(FactNorm)
1185
1186 SmoothSPC=self.moving_average(FactNorm,N=3)
1187
1188 xSamples = ar(range(len(SmoothSPC)))
1189 ySamples[i] = SmoothSPC
1190
1191 #dbSNR=10*numpy.log10(dataSNR)
1192 print ' '
1193 print ' '
1194 print ' '
1195
1196 #print 'dataSNR', dbSNR.shape, dbSNR[0,40:120]
1197 print 'SmoothSPC', SmoothSPC.shape, SmoothSPC[0:20]
1198 print 'noise',noise
1199 print 'zline',zline.shape, zline[0:20]
1200 print 'FactNorm',FactNorm.shape, FactNorm[0:20]
1201 print 'FactNorm suma', numpy.sum(FactNorm)
1202
1203 for i in range(spc.shape[0]):
1204
1205 '''****** Line of Data CSPC ******'''
1206 cspcLine=cspc[i,:,Height].copy()
1207
1208 '''****** CSPC is normalized ******'''
1209 chan_index0 = pairsList[i][0]
1210 chan_index1 = pairsList[i][1]
1211 CSPCFactor= abs(numpy.sum(ySamples[chan_index0]) * numpy.sum(ySamples[chan_index1])) #
1212
1213 CSPCNorm = (cspcLine.copy() -noise[i]) / numpy.sqrt(CSPCFactor)
1214
1215 CSPCSamples[i] = CSPCNorm
1216 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
1217
1218 coherence[i]= self.moving_average(coherence[i],N=2)
1219
1220 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
1221
1222 print 'cspcLine', cspcLine.shape, cspcLine[0:20]
1223 print 'CSPCFactor', CSPCFactor#, CSPCFactor[0:20]
1224 print numpy.sum(ySamples[chan_index0]), numpy.sum(ySamples[chan_index1]), -noise[i]
1225 print 'CSPCNorm', CSPCNorm.shape, CSPCNorm[0:20]
1226 print 'CSPCNorm suma', numpy.sum(CSPCNorm)
1227 print 'CSPCSamples', CSPCSamples.shape, CSPCSamples[0,0:20]
1228
1229 '''****** Getting fij width ******'''
1230
1231 yMean=[]
1232 yMean2=[]
1233
1234 for j in range(len(ySamples[1])):
1235 yMean=numpy.append(yMean,numpy.mean([ySamples[0,j],ySamples[1,j],ySamples[2,j]]))
1236
1237 '''******* Getting fitting Gaussian ******'''
1238 meanGauss=sum(xSamples*yMean) / len(xSamples)
1239 sigma=sum(yMean*(xSamples-meanGauss)**2) / len(xSamples)
1240
1241 print '****************************'
1242 print 'len(xSamples): ',len(xSamples)
1243 print 'yMean: ', yMean.shape, yMean[0:20]
1244 print 'ySamples', ySamples.shape, ySamples[0,0:20]
1245 print 'xSamples: ',xSamples.shape, xSamples[0:20]
1246
1247 print 'meanGauss',meanGauss
1248 print 'sigma',sigma
1249
1250 #if (abs(meanGauss/sigma**2) > 0.0001) : #0.000000001):
1251 if dbSNR > SNRlimit :
1252 try:
1253 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=[1,meanGauss,sigma])
1254
1255 if numpy.amax(popt)>numpy.amax(yMean)*0.3:
1256 FitGauss=self.gaus(xSamples,*popt)
1257
1258 else:
1259 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1260 print 'Verificador: Dentro', Height
1261 except :#RuntimeError:
1262 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1263
1264
1265 else:
1266 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1267
1268 Maximun=numpy.amax(yMean)
1269 eMinus1=Maximun*numpy.exp(-1)#*0.8
1270
1271 HWpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1)))
1272 HalfWidth= xFrec[HWpos]
1273 GCpos=self.Find(FitGauss, numpy.amax(FitGauss))
1274 Vpos=self.Find(FactNorm, numpy.amax(FactNorm))
1275
1276 #Vpos=FirstMoment[]
1277
1278 '''****** Getting Fij ******'''
1279
1280 GaussCenter=xFrec[GCpos]
1281 if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0):
1282 Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001
1283 else:
1284 Fij=abs(GaussCenter-HalfWidth)+0.0000001
1285
1286 '''****** Getting Frecuency range of significant data ******'''
1287
1288 Rangpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10)))
1289
1290 if Rangpos<GCpos:
1291 Range=numpy.array([Rangpos,2*GCpos-Rangpos])
1292 elif Rangpos< ( len(xFrec)- len(xFrec)*0.1):
1293 Range=numpy.array([2*GCpos-Rangpos,Rangpos])
1294 else:
1295 Range = numpy.array([0,0])
1296
1297 print ' '
1298 print 'GCpos',GCpos, ( len(xFrec)- len(xFrec)*0.1)
1299 print 'Rangpos',Rangpos
1300 print 'RANGE: ', Range
1301 FrecRange=xFrec[Range[0]:Range[1]]
1302
1303 '''****** Getting SCPC Slope ******'''
1304
1305 for i in range(spc.shape[0]):
1306
1307 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.5:
1308 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1309
1310 print 'FrecRange', len(FrecRange) , FrecRange
1311 print 'PhaseRange', len(PhaseRange), PhaseRange
1312 print ' '
1313 if len(FrecRange) == len(PhaseRange):
1314 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange,PhaseRange)
1315 PhaseSlope[i]=slope
1316 PhaseInter[i]=intercept
1317 else:
1318 PhaseSlope[i]=0
1319 PhaseInter[i]=0
1320 else:
1321 PhaseSlope[i]=0
1322 PhaseInter[i]=0
1323
1324 '''Getting constant C'''
1325 cC=(Fij*numpy.pi)**2
1326
1327 '''****** Getting constants F and G ******'''
1328 MijEijNij=numpy.array([[E02,N02], [E12,N12]])
1329 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1330 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1331 MijResults=numpy.array([MijResult0,MijResult1])
1332 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1333
1334 '''****** Getting constants A, B and H ******'''
1335 W01=numpy.amax(coherence[0])
1336 W02=numpy.amax(coherence[1])
1337 W12=numpy.amax(coherence[2])
1338
1339 WijResult0=((cF*E01+cG*N01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1340 WijResult1=((cF*E02+cG*N02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1341 WijResult2=((cF*E12+cG*N12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1342
1343 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1344
1345 WijEijNij=numpy.array([ [E01**2, N01**2, 2*E01*N01] , [E02**2, N02**2, 2*E02*N02] , [E12**2, N12**2, 2*E12*N12] ])
1346 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1347
1348 VxVy=numpy.array([[cA,cH],[cH,cB]])
1349
1350 VxVyResults=numpy.array([-cF,-cG])
1351 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1352
1353 Vzon = Vy
1354 Vmer = Vx
1355 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
1356 Vang=numpy.arctan2(Vmer,Vzon)
1357 Vver=xFrec[Vpos]
1358 print 'vzon y vmer', Vzon, Vmer
1359 return Vzon, Vmer, Vver, GaussCenter
1360
1361 class SpectralMoments(Operation):
1362
1363 '''
1364 Function SpectralMoments()
1365
1366 Calculates moments (power, mean, standard deviation) and SNR of the signal
1367
1368 Type of dataIn: Spectra
1369
1370 Configuration Parameters:
1371
133 1372 dirCosx : Cosine director in X axis
134 1373 dirCosy : Cosine director in Y axis
135
1374
136 1375 elevation :
137 1376 azimuth :
138
1377
139 1378 Input:
140 channelList : simple channel list to select e.g. [2,3,7]
1379 channelList : simple channel list to select e.g. [2,3,7]
141 1380 self.dataOut.data_pre : Spectral data
142 1381 self.dataOut.abscissaList : List of frequencies
143 1382 self.dataOut.noise : Noise level per channel
144
1383
145 1384 Affected:
146 1385 self.dataOut.data_param : Parameters per channel
147 1386 self.dataOut.data_SNR : SNR per channel
148
1387
149 1388 '''
150
1389
151 1390 def run(self, dataOut):
152
1391
153 1392 #dataOut.data_pre = dataOut.data_pre[0]
154 1393 data = dataOut.data_pre[0]
155 1394 absc = dataOut.abscissaList[:-1]
156 1395 noise = dataOut.noise
157 1396 nChannel = data.shape[0]
158 1397 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
159
1398
160 1399 for ind in range(nChannel):
161 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:], absc, noise[ind])
162
1400 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1401
163 1402 dataOut.data_param = data_param[:,1:,:]
164 1403 dataOut.data_SNR = data_param[:,0]
165 1404 dataOut.data_DOP = data_param[:,1]
166 1405 dataOut.data_MEAN = data_param[:,2]
167 1406 dataOut.data_STD = data_param[:,3]
168 1407 return
169
170 def __calculateMoments(self, oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
171
172 if (nicoh is None): nicoh = 1
173 if (graph is None): graph = 0
174 if (smooth is None): smooth = 0
1408
1409 def __calculateMoments(self, oldspec, oldfreq, n0,
1410 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1411
1412 if (nicoh == None): nicoh = 1
1413 if (graph == None): graph = 0
1414 if (smooth == None): smooth = 0
175 1415 elif (self.smooth < 3): smooth = 0
176 1416
177 if (type1 is None): type1 = 0
178 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
179 if (snrth is None): snrth = -3
180 if (dc is None): dc = 0
181 if (aliasing is None): aliasing = 0
182 if (oldfd is None): oldfd = 0
183 if (wwauto is None): wwauto = 0
184
1417 if (type1 == None): type1 = 0
1418 if (fwindow == None): fwindow = numpy.zeros(oldfreq.size) + 1
1419 if (snrth == None): snrth = -3
1420 if (dc == None): dc = 0
1421 if (aliasing == None): aliasing = 0
1422 if (oldfd == None): oldfd = 0
1423 if (wwauto == None): wwauto = 0
1424
185 1425 if (n0 < 1.e-20): n0 = 1.e-20
186
1426
187 1427 freq = oldfreq
188 1428 vec_power = numpy.zeros(oldspec.shape[1])
189 1429 vec_fd = numpy.zeros(oldspec.shape[1])
190 1430 vec_w = numpy.zeros(oldspec.shape[1])
191 1431 vec_snr = numpy.zeros(oldspec.shape[1])
192 1432
193 1433 for ind in range(oldspec.shape[1]):
194
1434
195 1435 spec = oldspec[:,ind]
196 1436 aux = spec*fwindow
197 1437 max_spec = aux.max()
198 1438 m = list(aux).index(max_spec)
199
200 #Smooth
1439
1440 #Smooth
201 1441 if (smooth == 0): spec2 = spec
202 1442 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
203
1443
204 1444 # Calculo de Momentos
205 1445 bb = spec2[range(m,spec2.size)]
206 1446 bb = (bb<n0).nonzero()
207 1447 bb = bb[0]
208
1448
209 1449 ss = spec2[range(0,m + 1)]
210 1450 ss = (ss<n0).nonzero()
211 1451 ss = ss[0]
212
1452
213 1453 if (bb.size == 0):
214 1454 bb0 = spec.size - 1 - m
215 else:
1455 else:
216 1456 bb0 = bb[0] - 1
217 1457 if (bb0 < 0):
218 1458 bb0 = 0
219
1459
220 1460 if (ss.size == 0): ss1 = 1
221 1461 else: ss1 = max(ss) + 1
222
1462
223 1463 if (ss1 > m): ss1 = m
224
225 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
1464
1465 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
226 1466 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
227 1467 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
228 1468 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
229 snr = (spec2.mean()-n0)/n0
230
231 if (snr < 1.e-20) :
1469 snr = (spec2.mean()-n0)/n0
1470
1471 if (snr < 1.e-20) :
232 1472 snr = 1.e-20
233
1473
234 1474 vec_power[ind] = power
235 1475 vec_fd[ind] = fd
236 1476 vec_w[ind] = w
237 1477 vec_snr[ind] = snr
238
1478
239 1479 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
240 1480 return moments
241
1481
242 1482 #------------------ Get SA Parameters --------------------------
243
1483
244 1484 def GetSAParameters(self):
245 1485 #SA en frecuencia
246 1486 pairslist = self.dataOut.groupList
247 1487 num_pairs = len(pairslist)
248
1488
249 1489 vel = self.dataOut.abscissaList
250 spectra = self.dataOut.data_pre[0]
251 cspectra = self.dataOut.data_pre[1]
252 delta_v = vel[1] - vel[0]
253
1490 spectra = self.dataOut.data_pre
1491 cspectra = self.dataIn.data_cspc
1492 delta_v = vel[1] - vel[0]
1493
254 1494 #Calculating the power spectrum
255 1495 spc_pow = numpy.sum(spectra, 3)*delta_v
256 1496 #Normalizing Spectra
257 1497 norm_spectra = spectra/spc_pow
258 1498 #Calculating the norm_spectra at peak
259 max_spectra = numpy.max(norm_spectra, 3)
260
1499 max_spectra = numpy.max(norm_spectra, 3)
1500
261 1501 #Normalizing Cross Spectra
262 1502 norm_cspectra = numpy.zeros(cspectra.shape)
263
1503
264 1504 for i in range(num_chan):
265 1505 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
266
1506
267 1507 max_cspectra = numpy.max(norm_cspectra,2)
268 1508 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
269
1509
270 1510 for i in range(num_pairs):
271 1511 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
272 1512 #------------------- Get Lags ----------------------------------
273
1513
274 1514 class SALags(Operation):
275 1515 '''
276 1516 Function GetMoments()
277 1517
278 1518 Input:
279 1519 self.dataOut.data_pre
280 1520 self.dataOut.abscissaList
281 1521 self.dataOut.noise
282 1522 self.dataOut.normFactor
283 1523 self.dataOut.data_SNR
284 1524 self.dataOut.groupList
285 1525 self.dataOut.nChannels
286
1526
287 1527 Affected:
288 1528 self.dataOut.data_param
289
1529
290 1530 '''
291 def run(self, dataOut):
1531 def run(self, dataOut):
292 1532 data_acf = dataOut.data_pre[0]
293 1533 data_ccf = dataOut.data_pre[1]
294 1534 normFactor_acf = dataOut.normFactor[0]
295 1535 normFactor_ccf = dataOut.normFactor[1]
296 1536 pairs_acf = dataOut.groupList[0]
297 1537 pairs_ccf = dataOut.groupList[1]
298
1538
299 1539 nHeights = dataOut.nHeights
300 1540 absc = dataOut.abscissaList
301 1541 noise = dataOut.noise
302 1542 SNR = dataOut.data_SNR
303 1543 nChannels = dataOut.nChannels
304 1544 # pairsList = dataOut.groupList
305 1545 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
306 1546
307 1547 for l in range(len(pairs_acf)):
308 1548 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
309
1549
310 1550 for l in range(len(pairs_ccf)):
311 1551 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
312
1552
313 1553 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
314 1554 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
315 1555 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
316 1556 return
317
1557
318 1558 # def __getPairsAutoCorr(self, pairsList, nChannels):
319 #
1559 #
320 1560 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
321 #
322 # for l in range(len(pairsList)):
1561 #
1562 # for l in range(len(pairsList)):
323 1563 # firstChannel = pairsList[l][0]
324 1564 # secondChannel = pairsList[l][1]
325 #
326 # #Obteniendo pares de Autocorrelacion
1565 #
1566 # #Obteniendo pares de Autocorrelacion
327 1567 # if firstChannel == secondChannel:
328 1568 # pairsAutoCorr[firstChannel] = int(l)
329 #
1569 #
330 1570 # pairsAutoCorr = pairsAutoCorr.astype(int)
331 #
1571 #
332 1572 # pairsCrossCorr = range(len(pairsList))
333 1573 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
334 #
1574 #
335 1575 # return pairsAutoCorr, pairsCrossCorr
336
1576
337 1577 def __calculateTaus(self, data_acf, data_ccf, lagRange):
338
1578
339 1579 lag0 = data_acf.shape[1]/2
340 1580 #Funcion de Autocorrelacion
341 1581 mean_acf = stats.nanmean(data_acf, axis = 0)
342
1582
343 1583 #Obtencion Indice de TauCross
344 1584 ind_ccf = data_ccf.argmax(axis = 1)
345 1585 #Obtencion Indice de TauAuto
346 1586 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
347 1587 ccf_lag0 = data_ccf[:,lag0,:]
348
1588
349 1589 for i in range(ccf_lag0.shape[0]):
350 1590 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
351
1591
352 1592 #Obtencion de TauCross y TauAuto
353 1593 tau_ccf = lagRange[ind_ccf]
354 1594 tau_acf = lagRange[ind_acf]
355
1595
356 1596 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
357
1597
358 1598 tau_ccf[Nan1,Nan2] = numpy.nan
359 1599 tau_acf[Nan1,Nan2] = numpy.nan
360 1600 tau = numpy.vstack((tau_ccf,tau_acf))
361
1601
362 1602 return tau
363
1603
364 1604 def __calculateLag1Phase(self, data, lagTRange):
365 1605 data1 = stats.nanmean(data, axis = 0)
366 1606 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
367 1607
368 1608 phase = numpy.angle(data1[lag1,:])
369
1609
370 1610 return phase
371
1611
372 1612 class SpectralFitting(Operation):
373 1613 '''
374 1614 Function GetMoments()
375
1615
376 1616 Input:
377 1617 Output:
378 1618 Variables modified:
379 1619 '''
380
381 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
382
383
1620
1621 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1622
1623
384 1624 if path != None:
385 1625 sys.path.append(path)
386 1626 self.dataOut.library = importlib.import_module(file)
387
1627
388 1628 #To be inserted as a parameter
389 1629 groupArray = numpy.array(groupList)
390 # groupArray = numpy.array([[0,1],[2,3]])
1630 # groupArray = numpy.array([[0,1],[2,3]])
391 1631 self.dataOut.groupList = groupArray
392
1632
393 1633 nGroups = groupArray.shape[0]
394 1634 nChannels = self.dataIn.nChannels
395 1635 nHeights=self.dataIn.heightList.size
396
1636
397 1637 #Parameters Array
398 1638 self.dataOut.data_param = None
399
1639
400 1640 #Set constants
401 1641 constants = self.dataOut.library.setConstants(self.dataIn)
402 1642 self.dataOut.constants = constants
403 1643 M = self.dataIn.normFactor
404 1644 N = self.dataIn.nFFTPoints
405 1645 ippSeconds = self.dataIn.ippSeconds
406 1646 K = self.dataIn.nIncohInt
407 1647 pairsArray = numpy.array(self.dataIn.pairsList)
408
1648
409 1649 #List of possible combinations
410 1650 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
411 1651 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
412
1652
413 1653 if getSNR:
414 1654 listChannels = groupArray.reshape((groupArray.size))
415 1655 listChannels.sort()
416 1656 noise = self.dataIn.getNoise()
417 1657 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
418
419 for i in range(nGroups):
1658
1659 for i in range(nGroups):
420 1660 coord = groupArray[i,:]
421
1661
422 1662 #Input data array
423 1663 data = self.dataIn.data_spc[coord,:,:]/(M*N)
424 1664 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
425
1665
426 1666 #Cross Spectra data array for Covariance Matrixes
427 1667 ind = 0
428 1668 for pairs in listComb:
429 1669 pairsSel = numpy.array([coord[x],coord[y]])
430 1670 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
431 1671 ind += 1
432 1672 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
433 1673 dataCross = dataCross**2/K
434
1674
435 1675 for h in range(nHeights):
436 1676 # print self.dataOut.heightList[h]
437
1677
438 1678 #Input
439 1679 d = data[:,h]
440 1680
441 1681 #Covariance Matrix
442 1682 D = numpy.diag(d**2/K)
443 1683 ind = 0
444 1684 for pairs in listComb:
445 1685 #Coordinates in Covariance Matrix
446 x = pairs[0]
1686 x = pairs[0]
447 1687 y = pairs[1]
448 1688 #Channel Index
449 1689 S12 = dataCross[ind,:,h]
450 1690 D12 = numpy.diag(S12)
451 1691 #Completing Covariance Matrix with Cross Spectras
452 1692 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
453 1693 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
454 1694 ind += 1
455 1695 Dinv=numpy.linalg.inv(D)
456 1696 L=numpy.linalg.cholesky(Dinv)
457 1697 LT=L.T
458 1698
459 1699 dp = numpy.dot(LT,d)
460
1700
461 1701 #Initial values
462 1702 data_spc = self.dataIn.data_spc[coord,:,h]
463
1703
464 1704 if (h>0)and(error1[3]<5):
465 1705 p0 = self.dataOut.data_param[i,:,h-1]
466 1706 else:
467 1707 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
468
1708
469 1709 try:
470 1710 #Least Squares
471 1711 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
472 1712 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
473 1713 #Chi square error
474 1714 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
475 1715 #Error with Jacobian
476 1716 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
477 1717 except:
478 1718 minp = p0*numpy.nan
479 1719 error0 = numpy.nan
480 1720 error1 = p0*numpy.nan
481
1721
482 1722 #Save
483 if self.dataOut.data_param is None:
1723 if self.dataOut.data_param == None:
484 1724 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
485 1725 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
486
1726
487 1727 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
488 1728 self.dataOut.data_param[i,:,h] = minp
489 1729 return
490
1730
491 1731 def __residFunction(self, p, dp, LT, constants):
492 1732
493 1733 fm = self.dataOut.library.modelFunction(p, constants)
494 1734 fmp=numpy.dot(LT,fm)
495
1735
496 1736 return dp-fmp
497 1737
498 1738 def __getSNR(self, z, noise):
499
1739
500 1740 avg = numpy.average(z, axis=1)
501 1741 SNR = (avg.T-noise)/noise
502 1742 SNR = SNR.T
503 1743 return SNR
504
1744
505 1745 def __chisq(p,chindex,hindex):
506 1746 #similar to Resid but calculates CHI**2
507 1747 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
508 1748 dp=numpy.dot(LT,d)
509 1749 fmp=numpy.dot(LT,fm)
510 1750 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
511 1751 return chisq
512
1752
513 1753 class WindProfiler(Operation):
514
1754
515 1755 __isConfig = False
516
1756
517 1757 __initime = None
518 1758 __lastdatatime = None
519 1759 __integrationtime = None
520
1760
521 1761 __buffer = None
522
1762
523 1763 __dataReady = False
524
1764
525 1765 __firstdata = None
526
1766
527 1767 n = None
528
1768
1769 def __init__(self):
1770 Operation.__init__(self)
1771
529 1772 def __calculateCosDir(self, elev, azim):
530 1773 zen = (90 - elev)*numpy.pi/180
531 1774 azim = azim*numpy.pi/180
532 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1775 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
533 1776 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
534
1777
535 1778 signX = numpy.sign(numpy.cos(azim))
536 1779 signY = numpy.sign(numpy.sin(azim))
537
1780
538 1781 cosDirX = numpy.copysign(cosDirX, signX)
539 1782 cosDirY = numpy.copysign(cosDirY, signY)
540 1783 return cosDirX, cosDirY
541
1784
542 1785 def __calculateAngles(self, theta_x, theta_y, azimuth):
543
1786
544 1787 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
545 1788 zenith_arr = numpy.arccos(dir_cosw)
546 1789 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
547
1790
548 1791 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
549 1792 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
550
1793
551 1794 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
552 1795
553 1796 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
554
555 #
1797
1798 #
556 1799 if horOnly:
557 1800 A = numpy.c_[dir_cosu,dir_cosv]
558 1801 else:
559 1802 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
560 1803 A = numpy.asmatrix(A)
561 1804 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
562 1805
563 1806 return A1
564 1807
565 1808 def __correctValues(self, heiRang, phi, velRadial, SNR):
566 1809 listPhi = phi.tolist()
567 1810 maxid = listPhi.index(max(listPhi))
568 1811 minid = listPhi.index(min(listPhi))
569
570 rango = range(len(phi))
1812
1813 rango = range(len(phi))
571 1814 # rango = numpy.delete(rango,maxid)
572
1815
573 1816 heiRang1 = heiRang*math.cos(phi[maxid])
574 1817 heiRangAux = heiRang*math.cos(phi[minid])
575 1818 indOut = (heiRang1 < heiRangAux[0]).nonzero()
576 1819 heiRang1 = numpy.delete(heiRang1,indOut)
577
1820
578 1821 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
579 1822 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
580
1823
581 1824 for i in rango:
582 1825 x = heiRang*math.cos(phi[i])
583 1826 y1 = velRadial[i,:]
584 1827 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
585
1828
586 1829 x1 = heiRang1
587 1830 y11 = f1(x1)
588
1831
589 1832 y2 = SNR[i,:]
590 1833 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
591 1834 y21 = f2(x1)
592
1835
593 1836 velRadial1[i,:] = y11
594 1837 SNR1[i,:] = y21
595
1838
596 1839 return heiRang1, velRadial1, SNR1
597 1840
598 1841 def __calculateVelUVW(self, A, velRadial):
599
1842
600 1843 #Operacion Matricial
601 1844 # velUVW = numpy.zeros((velRadial.shape[1],3))
602 1845 # for ind in range(velRadial.shape[1]):
603 1846 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
604 1847 # velUVW = velUVW.transpose()
605 1848 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
606 1849 velUVW[:,:] = numpy.dot(A,velRadial)
607
608
1850
1851
609 1852 return velUVW
610
1853
611 1854 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
612
1855
613 1856 def techniqueDBS(self, kwargs):
614 1857 """
615 1858 Function that implements Doppler Beam Swinging (DBS) technique.
616
1859
617 1860 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
618 1861 Direction correction (if necessary), Ranges and SNR
619
1862
620 1863 Output: Winds estimation (Zonal, Meridional and Vertical)
621
1864
622 1865 Parameters affected: Winds, height range, SNR
623 1866 """
624 1867 velRadial0 = kwargs['velRadial']
625 1868 heiRang = kwargs['heightList']
626 1869 SNR0 = kwargs['SNR']
627
1870
628 1871 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
629 1872 theta_x = numpy.array(kwargs['dirCosx'])
630 1873 theta_y = numpy.array(kwargs['dirCosy'])
631 1874 else:
632 1875 elev = numpy.array(kwargs['elevation'])
633 1876 azim = numpy.array(kwargs['azimuth'])
634 1877 theta_x, theta_y = self.__calculateCosDir(elev, azim)
635 azimuth = kwargs['correctAzimuth']
1878 azimuth = kwargs['correctAzimuth']
636 1879 if kwargs.has_key('horizontalOnly'):
637 1880 horizontalOnly = kwargs['horizontalOnly']
638 1881 else: horizontalOnly = False
639 1882 if kwargs.has_key('correctFactor'):
640 1883 correctFactor = kwargs['correctFactor']
641 1884 else: correctFactor = 1
642 1885 if kwargs.has_key('channelList'):
643 1886 channelList = kwargs['channelList']
644 1887 if len(channelList) == 2:
645 1888 horizontalOnly = True
646 1889 arrayChannel = numpy.array(channelList)
647 1890 param = param[arrayChannel,:,:]
648 1891 theta_x = theta_x[arrayChannel]
649 1892 theta_y = theta_y[arrayChannel]
650
651 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
652 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1893
1894 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1895 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
653 1896 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
654
1897
655 1898 #Calculo de Componentes de la velocidad con DBS
656 1899 winds = self.__calculateVelUVW(A,velRadial1)
657
1900
658 1901 return winds, heiRang1, SNR1
659
1902
660 1903 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
661
1904
662 1905 nPairs = len(pairs_ccf)
663 1906 posx = numpy.asarray(posx)
664 1907 posy = numpy.asarray(posy)
665
1908
666 1909 #Rotacion Inversa para alinear con el azimuth
667 1910 if azimuth!= None:
668 1911 azimuth = azimuth*math.pi/180
669 1912 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
670 1913 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
671 1914 else:
672 1915 posx1 = posx
673 1916 posy1 = posy
674
1917
675 1918 #Calculo de Distancias
676 1919 distx = numpy.zeros(nPairs)
677 1920 disty = numpy.zeros(nPairs)
678 1921 dist = numpy.zeros(nPairs)
679 1922 ang = numpy.zeros(nPairs)
680
1923
681 1924 for i in range(nPairs):
682 1925 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
683 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1926 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
684 1927 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
685 1928 ang[i] = numpy.arctan2(disty[i],distx[i])
686
1929
687 1930 return distx, disty, dist, ang
688 #Calculo de Matrices
1931 #Calculo de Matrices
689 1932 # nPairs = len(pairs)
690 1933 # ang1 = numpy.zeros((nPairs, 2, 1))
691 1934 # dist1 = numpy.zeros((nPairs, 2, 1))
692 #
1935 #
693 1936 # for j in range(nPairs):
694 1937 # dist1[j,0,0] = dist[pairs[j][0]]
695 1938 # dist1[j,1,0] = dist[pairs[j][1]]
696 1939 # ang1[j,0,0] = ang[pairs[j][0]]
697 1940 # ang1[j,1,0] = ang[pairs[j][1]]
698 #
1941 #
699 1942 # return distx,disty, dist1,ang1
700 1943
701
1944
702 1945 def __calculateVelVer(self, phase, lagTRange, _lambda):
703 1946
704 1947 Ts = lagTRange[1] - lagTRange[0]
705 1948 velW = -_lambda*phase/(4*math.pi*Ts)
706
1949
707 1950 return velW
708
1951
709 1952 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
710 1953 nPairs = tau1.shape[0]
711 1954 nHeights = tau1.shape[1]
712 vel = numpy.zeros((nPairs,3,nHeights))
1955 vel = numpy.zeros((nPairs,3,nHeights))
713 1956 dist1 = numpy.reshape(dist, (dist.size,1))
714
1957
715 1958 angCos = numpy.cos(ang)
716 1959 angSin = numpy.sin(ang)
717
718 vel0 = dist1*tau1/(2*tau2**2)
1960
1961 vel0 = dist1*tau1/(2*tau2**2)
719 1962 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
720 1963 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
721
1964
722 1965 ind = numpy.where(numpy.isinf(vel))
723 1966 vel[ind] = numpy.nan
724
1967
725 1968 return vel
726
1969
727 1970 # def __getPairsAutoCorr(self, pairsList, nChannels):
728 #
1971 #
729 1972 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
730 #
731 # for l in range(len(pairsList)):
1973 #
1974 # for l in range(len(pairsList)):
732 1975 # firstChannel = pairsList[l][0]
733 1976 # secondChannel = pairsList[l][1]
734 #
735 # #Obteniendo pares de Autocorrelacion
1977 #
1978 # #Obteniendo pares de Autocorrelacion
736 1979 # if firstChannel == secondChannel:
737 1980 # pairsAutoCorr[firstChannel] = int(l)
738 #
1981 #
739 1982 # pairsAutoCorr = pairsAutoCorr.astype(int)
740 #
1983 #
741 1984 # pairsCrossCorr = range(len(pairsList))
742 1985 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
743 #
1986 #
744 1987 # return pairsAutoCorr, pairsCrossCorr
745
1988
746 1989 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
747 1990 def techniqueSA(self, kwargs):
748
749 """
1991
1992 """
750 1993 Function that implements Spaced Antenna (SA) technique.
751
1994
752 1995 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
753 1996 Direction correction (if necessary), Ranges and SNR
754
1997
755 1998 Output: Winds estimation (Zonal, Meridional and Vertical)
756
1999
757 2000 Parameters affected: Winds
758 2001 """
759 2002 position_x = kwargs['positionX']
760 2003 position_y = kwargs['positionY']
761 2004 azimuth = kwargs['azimuth']
762
2005
763 2006 if kwargs.has_key('correctFactor'):
764 2007 correctFactor = kwargs['correctFactor']
765 2008 else:
766 2009 correctFactor = 1
767
2010
768 2011 groupList = kwargs['groupList']
769 2012 pairs_ccf = groupList[1]
770 2013 tau = kwargs['tau']
771 2014 _lambda = kwargs['_lambda']
772
2015
773 2016 #Cross Correlation pairs obtained
774 2017 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
775 2018 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
776 2019 # pairsSelArray = numpy.array(pairsSelected)
777 2020 # pairs = []
778 #
2021 #
779 2022 # #Wind estimation pairs obtained
780 2023 # for i in range(pairsSelArray.shape[0]/2):
781 2024 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
782 2025 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
783 2026 # pairs.append((ind1,ind2))
784
2027
785 2028 indtau = tau.shape[0]/2
786 2029 tau1 = tau[:indtau,:]
787 2030 tau2 = tau[indtau:-1,:]
788 2031 # tau1 = tau1[pairs,:]
789 2032 # tau2 = tau2[pairs,:]
790 2033 phase1 = tau[-1,:]
791
2034
792 2035 #---------------------------------------------------------------------
793 #Metodo Directo
2036 #Metodo Directo
794 2037 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
795 2038 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
796 2039 winds = stats.nanmean(winds, axis=0)
797 2040 #---------------------------------------------------------------------
798 2041 #Metodo General
799 2042 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
800 2043 # #Calculo Coeficientes de Funcion de Correlacion
801 2044 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
802 2045 # #Calculo de Velocidades
803 2046 # winds = self.calculateVelUV(F,G,A,B,H)
804 2047
805 2048 #---------------------------------------------------------------------
806 2049 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
807 2050 winds = correctFactor*winds
808 2051 return winds
809
2052
810 2053 def __checkTime(self, currentTime, paramInterval, outputInterval):
811
2054
812 2055 dataTime = currentTime + paramInterval
813 2056 deltaTime = dataTime - self.__initime
814
2057
815 2058 if deltaTime >= outputInterval or deltaTime < 0:
816 2059 self.__dataReady = True
817 return
818
819 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax, binkm=2):
2060 return
2061
2062 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
820 2063 '''
821 2064 Function that implements winds estimation technique with detected meteors.
822
2065
823 2066 Input: Detected meteors, Minimum meteor quantity to wind estimation
824
2067
825 2068 Output: Winds estimation (Zonal and Meridional)
826
2069
827 2070 Parameters affected: Winds
828 '''
829 # print arrayMeteor.shape
2071 '''
2072 # print arrayMeteor.shape
830 2073 #Settings
831 nInt = (heightMax - heightMin)/binkm
2074 nInt = (heightMax - heightMin)/2
832 2075 # print nInt
833 2076 nInt = int(nInt)
834 2077 # print nInt
835 winds = numpy.zeros((2,nInt))*numpy.nan
836
2078 winds = numpy.zeros((2,nInt))*numpy.nan
2079
837 2080 #Filter errors
838 2081 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
839 2082 finalMeteor = arrayMeteor[error,:]
840
2083
841 2084 #Meteor Histogram
842 2085 finalHeights = finalMeteor[:,2]
843 2086 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
844 2087 nMeteorsPerI = hist[0]
845 2088 heightPerI = hist[1]
846
2089
847 2090 #Sort of meteors
848 2091 indSort = finalHeights.argsort()
849 2092 finalMeteor2 = finalMeteor[indSort,:]
850
2093
851 2094 # Calculating winds
852 2095 ind1 = 0
853 ind2 = 0
854
2096 ind2 = 0
2097
855 2098 for i in range(nInt):
856 2099 nMet = nMeteorsPerI[i]
857 2100 ind1 = ind2
858 2101 ind2 = ind1 + nMet
859
2102
860 2103 meteorAux = finalMeteor2[ind1:ind2,:]
861
2104
862 2105 if meteorAux.shape[0] >= meteorThresh:
863 2106 vel = meteorAux[:, 6]
864 2107 zen = meteorAux[:, 4]*numpy.pi/180
865 2108 azim = meteorAux[:, 3]*numpy.pi/180
866
2109
867 2110 n = numpy.cos(zen)
868 2111 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
869 2112 # l = m*numpy.tan(azim)
870 2113 l = numpy.sin(zen)*numpy.sin(azim)
871 2114 m = numpy.sin(zen)*numpy.cos(azim)
872
2115
873 2116 A = numpy.vstack((l, m)).transpose()
874 2117 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
875 2118 windsAux = numpy.dot(A1, vel)
876
2119
877 2120 winds[0,i] = windsAux[0]
878 2121 winds[1,i] = windsAux[1]
879
2122
880 2123 return winds, heightPerI[:-1]
881
2124
882 2125 def techniqueNSM_SA(self, **kwargs):
883 2126 metArray = kwargs['metArray']
884 2127 heightList = kwargs['heightList']
885 2128 timeList = kwargs['timeList']
886
2129
887 2130 rx_location = kwargs['rx_location']
888 2131 groupList = kwargs['groupList']
889 2132 azimuth = kwargs['azimuth']
890 2133 dfactor = kwargs['dfactor']
891 2134 k = kwargs['k']
892
2135
893 2136 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
894 2137 d = dist*dfactor
895 2138 #Phase calculation
896 2139 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
897
2140
898 2141 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
899
2142
900 2143 velEst = numpy.zeros((heightList.size,2))*numpy.nan
901 2144 azimuth1 = azimuth1*numpy.pi/180
902
2145
903 2146 for i in range(heightList.size):
904 2147 h = heightList[i]
905 2148 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
906 2149 metHeight = metArray1[indH,:]
907 2150 if metHeight.shape[0] >= 2:
908 2151 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
909 2152 iazim = metHeight[:,1].astype(int)
910 2153 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
911 2154 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
912 2155 A = numpy.asmatrix(A)
913 2156 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
914 2157 velHor = numpy.dot(A1,velAux)
915
2158
916 2159 velEst[i,:] = numpy.squeeze(velHor)
917 2160 return velEst
918
2161
919 2162 def __getPhaseSlope(self, metArray, heightList, timeList):
920 2163 meteorList = []
921 2164 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
922 2165 #Putting back together the meteor matrix
923 2166 utctime = metArray[:,0]
924 2167 uniqueTime = numpy.unique(utctime)
925
2168
926 2169 phaseDerThresh = 0.5
927 2170 ippSeconds = timeList[1] - timeList[0]
928 2171 sec = numpy.where(timeList>1)[0][0]
929 2172 nPairs = metArray.shape[1] - 6
930 2173 nHeights = len(heightList)
931
2174
932 2175 for t in uniqueTime:
933 2176 metArray1 = metArray[utctime==t,:]
934 2177 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
935 2178 tmet = metArray1[:,1].astype(int)
936 2179 hmet = metArray1[:,2].astype(int)
937
2180
938 2181 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
939 2182 metPhase[:,:] = numpy.nan
940 2183 metPhase[:,hmet,tmet] = metArray1[:,6:].T
941
2184
942 2185 #Delete short trails
943 2186 metBool = ~numpy.isnan(metPhase[0,:,:])
944 2187 heightVect = numpy.sum(metBool, axis = 1)
945 2188 metBool[heightVect<sec,:] = False
946 2189 metPhase[:,heightVect<sec,:] = numpy.nan
947
2190
948 2191 #Derivative
949 2192 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
950 2193 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
951 2194 metPhase[phDerAux] = numpy.nan
952
2195
953 2196 #--------------------------METEOR DETECTION -----------------------------------------
954 2197 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
955
2198
956 2199 for p in numpy.arange(nPairs):
957 2200 phase = metPhase[p,:,:]
958 2201 phDer = metDer[p,:,:]
959
2202
960 2203 for h in indMet:
961 2204 height = heightList[h]
962 2205 phase1 = phase[h,:] #82
963 2206 phDer1 = phDer[h,:]
964
2207
965 2208 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
966
2209
967 2210 indValid = numpy.where(~numpy.isnan(phase1))[0]
968 2211 initMet = indValid[0]
969 2212 endMet = 0
970
2213
971 2214 for i in range(len(indValid)-1):
972
2215
973 2216 #Time difference
974 2217 inow = indValid[i]
975 2218 inext = indValid[i+1]
976 2219 idiff = inext - inow
977 2220 #Phase difference
978 phDiff = numpy.abs(phase1[inext] - phase1[inow])
979
2221 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2222
980 2223 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
981 2224 sizeTrail = inow - initMet + 1
982 2225 if sizeTrail>3*sec: #Too short meteors
983 2226 x = numpy.arange(initMet,inow+1)*ippSeconds
984 2227 y = phase1[initMet:inow+1]
985 2228 ynnan = ~numpy.isnan(y)
986 2229 x = x[ynnan]
987 2230 y = y[ynnan]
988 2231 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
989 2232 ylin = x*slope + intercept
990 2233 rsq = r_value**2
991 2234 if rsq > 0.5:
992 2235 vel = slope#*height*1000/(k*d)
993 2236 estAux = numpy.array([utctime,p,height, vel, rsq])
994 2237 meteorList.append(estAux)
995 initMet = inext
2238 initMet = inext
996 2239 metArray2 = numpy.array(meteorList)
997
2240
998 2241 return metArray2
999
2242
1000 2243 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
1001
2244
1002 2245 azimuth1 = numpy.zeros(len(pairslist))
1003 2246 dist = numpy.zeros(len(pairslist))
1004
2247
1005 2248 for i in range(len(rx_location)):
1006 2249 ch0 = pairslist[i][0]
1007 2250 ch1 = pairslist[i][1]
1008
2251
1009 2252 diffX = rx_location[ch0][0] - rx_location[ch1][0]
1010 2253 diffY = rx_location[ch0][1] - rx_location[ch1][1]
1011 2254 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
1012 2255 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
1013
2256
1014 2257 azimuth1 -= azimuth0
1015 2258 return azimuth1, dist
1016
2259
1017 2260 def techniqueNSM_DBS(self, **kwargs):
1018 2261 metArray = kwargs['metArray']
1019 2262 heightList = kwargs['heightList']
1020 2263 timeList = kwargs['timeList']
1021 2264 azimuth = kwargs['azimuth']
1022 2265 theta_x = numpy.array(kwargs['theta_x'])
1023 2266 theta_y = numpy.array(kwargs['theta_y'])
1024 2267
1025 2268 utctime = metArray[:,0]
1026 2269 cmet = metArray[:,1].astype(int)
1027 2270 hmet = metArray[:,3].astype(int)
1028 2271 SNRmet = metArray[:,4]
1029 2272 vmet = metArray[:,5]
1030 2273 spcmet = metArray[:,6]
1031 2274
1032 2275 nChan = numpy.max(cmet) + 1
1033 2276 nHeights = len(heightList)
1034 2277
1035 2278 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1036 2279 hmet = heightList[hmet]
1037 2280 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
1038 2281
1039 2282 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1040 2283
1041 2284 for i in range(nHeights - 1):
1042 2285 hmin = heightList[i]
1043 2286 hmax = heightList[i + 1]
1044 2287
1045 2288 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
1046 2289 indthisH = numpy.where(thisH)
1047 2290
1048 2291 if numpy.size(indthisH) > 3:
1049 2292
1050 2293 vel_aux = vmet[thisH]
1051 2294 chan_aux = cmet[thisH]
1052 2295 cosu_aux = dir_cosu[chan_aux]
1053 2296 cosv_aux = dir_cosv[chan_aux]
1054 2297 cosw_aux = dir_cosw[chan_aux]
1055 2298
1056 2299 nch = numpy.size(numpy.unique(chan_aux))
1057 2300 if nch > 1:
1058 2301 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
1059 2302 velEst[i,:] = numpy.dot(A,vel_aux)
1060 2303
1061 2304 return velEst
1062 2305
1063 2306 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
1064 2307
1065 2308 param = dataOut.data_param
1066 2309 if dataOut.abscissaList != None:
1067 2310 absc = dataOut.abscissaList[:-1]
1068 2311 # noise = dataOut.noise
1069 2312 heightList = dataOut.heightList
1070 2313 SNR = dataOut.data_SNR
1071
2314
1072 2315 if technique == 'DBS':
1073
1074 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2316
2317 kwargs['velRadial'] = param[:,1,:] #Radial velocity
1075 2318 kwargs['heightList'] = heightList
1076 2319 kwargs['SNR'] = SNR
1077
2320
1078 2321 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
1079 2322 dataOut.utctimeInit = dataOut.utctime
1080 2323 dataOut.outputInterval = dataOut.paramInterval
1081
2324
1082 2325 elif technique == 'SA':
1083
2326
1084 2327 #Parameters
1085 2328 # position_x = kwargs['positionX']
1086 2329 # position_y = kwargs['positionY']
1087 2330 # azimuth = kwargs['azimuth']
1088 #
2331 #
1089 2332 # if kwargs.has_key('crosspairsList'):
1090 2333 # pairs = kwargs['crosspairsList']
1091 2334 # else:
1092 # pairs = None
1093 #
2335 # pairs = None
2336 #
1094 2337 # if kwargs.has_key('correctFactor'):
1095 2338 # correctFactor = kwargs['correctFactor']
1096 2339 # else:
1097 2340 # correctFactor = 1
1098
2341
1099 2342 # tau = dataOut.data_param
1100 2343 # _lambda = dataOut.C/dataOut.frequency
1101 2344 # pairsList = dataOut.groupList
1102 2345 # nChannels = dataOut.nChannels
1103
2346
1104 2347 kwargs['groupList'] = dataOut.groupList
1105 2348 kwargs['tau'] = dataOut.data_param
1106 2349 kwargs['_lambda'] = dataOut.C/dataOut.frequency
1107 2350 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1108 2351 dataOut.data_output = self.techniqueSA(kwargs)
1109 2352 dataOut.utctimeInit = dataOut.utctime
1110 2353 dataOut.outputInterval = dataOut.timeInterval
1111
1112 elif technique == 'Meteors':
2354
2355 elif technique == 'Meteors':
1113 2356 dataOut.flagNoData = True
1114 2357 self.__dataReady = False
1115
2358
1116 2359 if kwargs.has_key('nHours'):
1117 2360 nHours = kwargs['nHours']
1118 else:
2361 else:
1119 2362 nHours = 1
1120
2363
1121 2364 if kwargs.has_key('meteorsPerBin'):
1122 2365 meteorThresh = kwargs['meteorsPerBin']
1123 2366 else:
1124 2367 meteorThresh = 6
1125
2368
1126 2369 if kwargs.has_key('hmin'):
1127 2370 hmin = kwargs['hmin']
1128 2371 else: hmin = 70
1129 2372 if kwargs.has_key('hmax'):
1130 2373 hmax = kwargs['hmax']
1131 2374 else: hmax = 110
1132
1133 if kwargs.has_key('BinKm'):
1134 binkm = kwargs['BinKm']
1135 else:
1136 binkm = 2
1137
2375
1138 2376 dataOut.outputInterval = nHours*3600
1139
2377
1140 2378 if self.__isConfig == False:
1141 2379 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1142 2380 #Get Initial LTC time
1143 2381 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1144 2382 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1145 2383
1146 2384 self.__isConfig = True
1147
1148 if self.__buffer is None:
2385
2386 if self.__buffer == None:
1149 2387 self.__buffer = dataOut.data_param
1150 2388 self.__firstdata = copy.copy(dataOut)
1151 2389
1152 2390 else:
1153 2391 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1154
2392
1155 2393 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1156
2394
1157 2395 if self.__dataReady:
1158 2396 dataOut.utctimeInit = self.__initime
1159
2397
1160 2398 self.__initime += dataOut.outputInterval #to erase time offset
1161
1162 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax, binkm)
2399
2400 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
1163 2401 dataOut.flagNoData = False
1164 2402 self.__buffer = None
1165
2403
1166 2404 elif technique == 'Meteors1':
1167 2405 dataOut.flagNoData = True
1168 2406 self.__dataReady = False
1169
2407
1170 2408 if kwargs.has_key('nMins'):
1171 2409 nMins = kwargs['nMins']
1172 2410 else: nMins = 20
1173 2411 if kwargs.has_key('rx_location'):
1174 2412 rx_location = kwargs['rx_location']
1175 2413 else: rx_location = [(0,1),(1,1),(1,0)]
1176 2414 if kwargs.has_key('azimuth'):
1177 2415 azimuth = kwargs['azimuth']
1178 2416 else: azimuth = 51.06
1179 2417 if kwargs.has_key('dfactor'):
1180 2418 dfactor = kwargs['dfactor']
1181 2419 if kwargs.has_key('mode'):
1182 2420 mode = kwargs['mode']
1183 2421 if kwargs.has_key('theta_x'):
1184 2422 theta_x = kwargs['theta_x']
1185 2423 if kwargs.has_key('theta_y'):
1186 2424 theta_y = kwargs['theta_y']
1187 2425 else: mode = 'SA'
1188 2426
1189 2427 #Borrar luego esto
1190 if dataOut.groupList is None:
2428 if dataOut.groupList == None:
1191 2429 dataOut.groupList = [(0,1),(0,2),(1,2)]
1192 2430 groupList = dataOut.groupList
1193 2431 C = 3e8
1194 2432 freq = 50e6
1195 2433 lamb = C/freq
1196 2434 k = 2*numpy.pi/lamb
1197
2435
1198 2436 timeList = dataOut.abscissaList
1199 2437 heightList = dataOut.heightList
1200
2438
1201 2439 if self.__isConfig == False:
1202 2440 dataOut.outputInterval = nMins*60
1203 2441 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1204 2442 #Get Initial LTC time
1205 2443 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
1206 2444 minuteAux = initime.minute
1207 2445 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
1208 2446 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1209 2447
1210 2448 self.__isConfig = True
1211
1212 if self.__buffer is None:
2449
2450 if self.__buffer == None:
1213 2451 self.__buffer = dataOut.data_param
1214 2452 self.__firstdata = copy.copy(dataOut)
1215 2453
1216 2454 else:
1217 2455 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1218
2456
1219 2457 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1220
2458
1221 2459 if self.__dataReady:
1222 2460 dataOut.utctimeInit = self.__initime
1223 2461 self.__initime += dataOut.outputInterval #to erase time offset
1224
2462
1225 2463 metArray = self.__buffer
1226 2464 if mode == 'SA':
1227 2465 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
1228 2466 elif mode == 'DBS':
1229 2467 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
1230 2468 dataOut.data_output = dataOut.data_output.T
1231 2469 dataOut.flagNoData = False
1232 2470 self.__buffer = None
1233 2471
1234 2472 return
1235
2473
1236 2474 class EWDriftsEstimation(Operation):
1237
1238
2475
2476 def __init__(self):
2477 Operation.__init__(self)
2478
1239 2479 def __correctValues(self, heiRang, phi, velRadial, SNR):
1240 2480 listPhi = phi.tolist()
1241 2481 maxid = listPhi.index(max(listPhi))
1242 2482 minid = listPhi.index(min(listPhi))
1243
1244 rango = range(len(phi))
2483
2484 rango = range(len(phi))
1245 2485 # rango = numpy.delete(rango,maxid)
1246
2486
1247 2487 heiRang1 = heiRang*math.cos(phi[maxid])
1248 2488 heiRangAux = heiRang*math.cos(phi[minid])
1249 2489 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1250 2490 heiRang1 = numpy.delete(heiRang1,indOut)
1251
2491
1252 2492 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1253 2493 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1254
2494
1255 2495 for i in rango:
1256 2496 x = heiRang*math.cos(phi[i])
1257 2497 y1 = velRadial[i,:]
1258 2498 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1259
2499
1260 2500 x1 = heiRang1
1261 2501 y11 = f1(x1)
1262
2502
1263 2503 y2 = SNR[i,:]
1264 2504 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1265 2505 y21 = f2(x1)
1266
2506
1267 2507 velRadial1[i,:] = y11
1268 2508 SNR1[i,:] = y21
1269
2509
1270 2510 return heiRang1, velRadial1, SNR1
1271 2511
1272 2512 def run(self, dataOut, zenith, zenithCorrection):
1273 2513 heiRang = dataOut.heightList
1274 2514 velRadial = dataOut.data_param[:,3,:]
1275 2515 SNR = dataOut.data_SNR
1276
2516
1277 2517 zenith = numpy.array(zenith)
1278 zenith -= zenithCorrection
2518 zenith -= zenithCorrection
1279 2519 zenith *= numpy.pi/180
1280
2520
1281 2521 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
1282
2522
1283 2523 alp = zenith[0]
1284 2524 bet = zenith[1]
1285
2525
1286 2526 w_w = velRadial1[0,:]
1287 2527 w_e = velRadial1[1,:]
1288
1289 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
1290 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
1291
2528
2529 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2530 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2531
1292 2532 winds = numpy.vstack((u,w))
1293
2533
1294 2534 dataOut.heightList = heiRang1
1295 2535 dataOut.data_output = winds
1296 2536 dataOut.data_SNR = SNR1
1297
2537
1298 2538 dataOut.utctimeInit = dataOut.utctime
1299 2539 dataOut.outputInterval = dataOut.timeInterval
1300 2540 return
1301 2541
1302 2542 #--------------- Non Specular Meteor ----------------
1303 2543
1304 2544 class NonSpecularMeteorDetection(Operation):
1305 2545
1306 2546 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
1307 2547 data_acf = dataOut.data_pre[0]
1308 2548 data_ccf = dataOut.data_pre[1]
1309 2549 pairsList = dataOut.groupList[1]
1310 2550
1311 2551 lamb = dataOut.C/dataOut.frequency
1312 2552 tSamp = dataOut.ippSeconds*dataOut.nCohInt
1313 2553 paramInterval = dataOut.paramInterval
1314 2554
1315 2555 nChannels = data_acf.shape[0]
1316 2556 nLags = data_acf.shape[1]
1317 2557 nProfiles = data_acf.shape[2]
1318 2558 nHeights = dataOut.nHeights
1319 2559 nCohInt = dataOut.nCohInt
1320 2560 sec = numpy.round(nProfiles/dataOut.paramInterval)
1321 2561 heightList = dataOut.heightList
1322 2562 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
1323 2563 utctime = dataOut.utctime
1324 2564
1325 2565 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
1326 2566
1327 2567 #------------------------ SNR --------------------------------------
1328 2568 power = data_acf[:,0,:,:].real
1329 2569 noise = numpy.zeros(nChannels)
1330 2570 SNR = numpy.zeros(power.shape)
1331 2571 for i in range(nChannels):
1332 2572 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
1333 2573 SNR[i] = (power[i]-noise[i])/noise[i]
1334 2574 SNRm = numpy.nanmean(SNR, axis = 0)
1335 2575 SNRdB = 10*numpy.log10(SNR)
1336
2576
1337 2577 if mode == 'SA':
1338 2578 dataOut.groupList = dataOut.groupList[1]
1339 2579 nPairs = data_ccf.shape[0]
1340 2580 #---------------------- Coherence and Phase --------------------------
1341 2581 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
1342 2582 # phase1 = numpy.copy(phase)
1343 2583 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
1344
2584
1345 2585 for p in range(nPairs):
1346 2586 ch0 = pairsList[p][0]
1347 2587 ch1 = pairsList[p][1]
1348 2588 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
1349 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
1350 # phase1[p,:,:] = numpy.angle(ccf) #median filter
1351 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
1352 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2589 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2590 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2591 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2592 # coh1[p,:,:] = numpy.abs(ccf) #median filter
1353 2593 coh = numpy.nanmax(coh1, axis = 0)
1354 2594 # struc = numpy.ones((5,1))
1355 2595 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
1356 2596 #---------------------- Radial Velocity ----------------------------
1357 2597 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
1358 2598 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
1359
2599
1360 2600 if allData:
1361 2601 boolMetFin = ~numpy.isnan(SNRm)
1362 2602 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1363 2603 else:
1364 2604 #------------------------ Meteor mask ---------------------------------
1365 2605 # #SNR mask
1366 2606 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
1367 #
2607 #
1368 2608 # #Erase small objects
1369 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
1370 #
2609 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2610 #
1371 2611 # auxEEJ = numpy.sum(boolMet1,axis=0)
1372 2612 # indOver = auxEEJ>nProfiles*0.8 #Use this later
1373 2613 # indEEJ = numpy.where(indOver)[0]
1374 2614 # indNEEJ = numpy.where(~indOver)[0]
1375 #
2615 #
1376 2616 # boolMetFin = boolMet1
1377 #
2617 #
1378 2618 # if indEEJ.size > 0:
1379 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
1380 #
2619 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2620 #
1381 2621 # boolMet2 = coh > cohThresh
1382 2622 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
1383 #
2623 #
1384 2624 # #Final Meteor mask
1385 2625 # boolMetFin = boolMet1|boolMet2
1386
2626
1387 2627 #Coherence mask
1388 2628 boolMet1 = coh > 0.75
1389 2629 struc = numpy.ones((30,1))
1390 2630 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
1391
2631
1392 2632 #Derivative mask
1393 2633 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
1394 2634 boolMet2 = derPhase < 0.2
1395 2635 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
1396 2636 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
1397 2637 boolMet2 = ndimage.median_filter(boolMet2,size=5)
1398 2638 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
1399 2639 # #Final mask
1400 2640 # boolMetFin = boolMet2
1401 2641 boolMetFin = boolMet1&boolMet2
1402 2642 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
1403 2643 #Creating data_param
1404 2644 coordMet = numpy.where(boolMetFin)
1405 2645
1406 2646 tmet = coordMet[0]
1407 2647 hmet = coordMet[1]
1408
2648
1409 2649 data_param = numpy.zeros((tmet.size, 6 + nPairs))
1410 2650 data_param[:,0] = utctime
1411 2651 data_param[:,1] = tmet
1412 2652 data_param[:,2] = hmet
1413 2653 data_param[:,3] = SNRm[tmet,hmet]
1414 2654 data_param[:,4] = velRad[tmet,hmet]
1415 2655 data_param[:,5] = coh[tmet,hmet]
1416 2656 data_param[:,6:] = phase[:,tmet,hmet].T
1417
2657
1418 2658 elif mode == 'DBS':
1419 2659 dataOut.groupList = numpy.arange(nChannels)
1420 2660
1421 2661 #Radial Velocities
1422 2662 phase = numpy.angle(data_acf[:,1,:,:])
1423 2663 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
1424 2664 velRad = phase*lamb/(4*numpy.pi*tSamp)
1425
2665
1426 2666 #Spectral width
1427 2667 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
1428 2668 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
1429 2669 acf1 = data_acf[:,1,:,:]
1430 2670 acf2 = data_acf[:,2,:,:]
1431 2671
1432 2672 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
1433 2673 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
1434 2674 if allData:
1435 2675 boolMetFin = ~numpy.isnan(SNRdB)
1436 2676 else:
1437 2677 #SNR
1438 2678 boolMet1 = (SNRdB>SNRthresh) #SNR mask
1439 2679 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
1440
2680
1441 2681 #Radial velocity
1442 2682 boolMet2 = numpy.abs(velRad) < 20
1443 2683 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
1444
2684
1445 2685 #Spectral Width
1446 2686 boolMet3 = spcWidth < 30
1447 2687 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
1448 2688 # boolMetFin = self.__erase_small(boolMet1, 10,5)
1449 2689 boolMetFin = boolMet1&boolMet2&boolMet3
1450
2690
1451 2691 #Creating data_param
1452 2692 coordMet = numpy.where(boolMetFin)
1453 2693
1454 2694 cmet = coordMet[0]
1455 2695 tmet = coordMet[1]
1456 2696 hmet = coordMet[2]
1457
2697
1458 2698 data_param = numpy.zeros((tmet.size, 7))
1459 2699 data_param[:,0] = utctime
1460 2700 data_param[:,1] = cmet
1461 2701 data_param[:,2] = tmet
1462 2702 data_param[:,3] = hmet
1463 2703 data_param[:,4] = SNR[cmet,tmet,hmet].T
1464 2704 data_param[:,5] = velRad[cmet,tmet,hmet].T
1465 2705 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
1466
2706
1467 2707 # self.dataOut.data_param = data_int
1468 2708 if len(data_param) == 0:
1469 2709 dataOut.flagNoData = True
1470 2710 else:
1471 2711 dataOut.data_param = data_param
1472 2712
1473 2713 def __erase_small(self, binArray, threshX, threshY):
1474 2714 labarray, numfeat = ndimage.measurements.label(binArray)
1475 2715 binArray1 = numpy.copy(binArray)
1476
2716
1477 2717 for i in range(1,numfeat + 1):
1478 2718 auxBin = (labarray==i)
1479 2719 auxSize = auxBin.sum()
1480
2720
1481 2721 x,y = numpy.where(auxBin)
1482 2722 widthX = x.max() - x.min()
1483 2723 widthY = y.max() - y.min()
1484
2724
1485 2725 #width X: 3 seg -> 12.5*3
1486 #width Y:
1487
2726 #width Y:
2727
1488 2728 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
1489 2729 binArray1[auxBin] = False
1490
2730
1491 2731 return binArray1
1492 2732
1493 2733 #--------------- Specular Meteor ----------------
1494 2734
1495 2735 class SMDetection(Operation):
1496 2736 '''
1497 2737 Function DetectMeteors()
1498 2738 Project developed with paper:
1499 2739 HOLDSWORTH ET AL. 2004
1500
2740
1501 2741 Input:
1502 2742 self.dataOut.data_pre
1503
2743
1504 2744 centerReceiverIndex: From the channels, which is the center receiver
1505
2745
1506 2746 hei_ref: Height reference for the Beacon signal extraction
1507 2747 tauindex:
1508 2748 predefinedPhaseShifts: Predefined phase offset for the voltge signals
1509
2749
1510 2750 cohDetection: Whether to user Coherent detection or not
1511 2751 cohDet_timeStep: Coherent Detection calculation time step
1512 2752 cohDet_thresh: Coherent Detection phase threshold to correct phases
1513
2753
1514 2754 noise_timeStep: Noise calculation time step
1515 2755 noise_multiple: Noise multiple to define signal threshold
1516
2756
1517 2757 multDet_timeLimit: Multiple Detection Removal time limit in seconds
1518 2758 multDet_rangeLimit: Multiple Detection Removal range limit in km
1519
2759
1520 2760 phaseThresh: Maximum phase difference between receiver to be consider a meteor
1521 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
1522
2761 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2762
1523 2763 hmin: Minimum Height of the meteor to use it in the further wind estimations
1524 2764 hmax: Maximum Height of the meteor to use it in the further wind estimations
1525 2765 azimuth: Azimuth angle correction
1526
2766
1527 2767 Affected:
1528 2768 self.dataOut.data_param
1529
2769
1530 2770 Rejection Criteria (Errors):
1531 2771 0: No error; analysis OK
1532 2772 1: SNR < SNR threshold
1533 2773 2: angle of arrival (AOA) ambiguously determined
1534 2774 3: AOA estimate not feasible
1535 2775 4: Large difference in AOAs obtained from different antenna baselines
1536 2776 5: echo at start or end of time series
1537 2777 6: echo less than 5 examples long; too short for analysis
1538 2778 7: echo rise exceeds 0.3s
1539 2779 8: echo decay time less than twice rise time
1540 2780 9: large power level before echo
1541 2781 10: large power level after echo
1542 2782 11: poor fit to amplitude for estimation of decay time
1543 2783 12: poor fit to CCF phase variation for estimation of radial drift velocity
1544 2784 13: height unresolvable echo: not valid height within 70 to 110 km
1545 2785 14: height ambiguous echo: more then one possible height within 70 to 110 km
1546 2786 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
1547 2787 16: oscilatory echo, indicating event most likely not an underdense echo
1548
2788
1549 2789 17: phase difference in meteor Reestimation
1550
2790
1551 2791 Data Storage:
1552 2792 Meteors for Wind Estimation (8):
1553 2793 Utc Time | Range Height
1554 2794 Azimuth Zenith errorCosDir
1555 2795 VelRad errorVelRad
1556 2796 Phase0 Phase1 Phase2 Phase3
1557 2797 TypeError
1558
1559 '''
1560
2798
2799 '''
2800
1561 2801 def run(self, dataOut, hei_ref = None, tauindex = 0,
1562 2802 phaseOffsets = None,
1563 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2803 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
1564 2804 noise_timeStep = 4, noise_multiple = 4,
1565 2805 multDet_timeLimit = 1, multDet_rangeLimit = 3,
1566 2806 phaseThresh = 20, SNRThresh = 5,
1567 2807 hmin = 50, hmax=150, azimuth = 0,
1568 2808 channelPositions = None) :
1569
1570
2809
2810
1571 2811 #Getting Pairslist
1572 if channelPositions is None:
2812 if channelPositions == None:
1573 2813 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
1574 2814 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
1575 2815 meteorOps = SMOperations()
1576 2816 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
1577 2817 heiRang = dataOut.getHeiRange()
1578 2818 #Get Beacon signal - No Beacon signal anymore
1579 2819 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
1580 #
2820 #
1581 2821 # if hei_ref != None:
1582 2822 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
1583 #
1584
1585
2823 #
2824
2825
1586 2826 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
1587 2827 # see if the user put in pre defined phase shifts
1588 2828 voltsPShift = dataOut.data_pre.copy()
1589
2829
1590 2830 # if predefinedPhaseShifts != None:
1591 2831 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
1592 #
2832 #
1593 2833 # # elif beaconPhaseShifts:
1594 2834 # # #get hardware phase shifts using beacon signal
1595 2835 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
1596 2836 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
1597 #
2837 #
1598 2838 # else:
1599 # hardwarePhaseShifts = numpy.zeros(5)
1600 #
2839 # hardwarePhaseShifts = numpy.zeros(5)
2840 #
1601 2841 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
1602 2842 # for i in range(self.dataOut.data_pre.shape[0]):
1603 2843 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
1604 2844
1605 2845 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
1606
2846
1607 2847 #Remove DC
1608 2848 voltsDC = numpy.mean(voltsPShift,1)
1609 2849 voltsDC = numpy.mean(voltsDC,1)
1610 2850 for i in range(voltsDC.shape[0]):
1611 2851 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
1612
1613 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2852
2853 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
1614 2854 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
1615
2855
1616 2856 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
1617 2857 #Coherent Detection
1618 2858 if cohDetection:
1619 2859 #use coherent detection to get the net power
1620 2860 cohDet_thresh = cohDet_thresh*numpy.pi/180
1621 2861 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
1622
2862
1623 2863 #Non-coherent detection!
1624 2864 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
1625 2865 #********** END OF COH/NON-COH POWER CALCULATION**********************
1626
2866
1627 2867 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
1628 2868 #Get noise
1629 2869 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
1630 2870 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
1631 2871 #Get signal threshold
1632 2872 signalThresh = noise_multiple*noise
1633 2873 #Meteor echoes detection
1634 2874 listMeteors = self.__findMeteors(powerNet, signalThresh)
1635 2875 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
1636
2876
1637 2877 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
1638 2878 #Parameters
1639 2879 heiRange = dataOut.getHeiRange()
1640 2880 rangeInterval = heiRange[1] - heiRange[0]
1641 2881 rangeLimit = multDet_rangeLimit/rangeInterval
1642 2882 timeLimit = multDet_timeLimit/dataOut.timeInterval
1643 2883 #Multiple detection removals
1644 2884 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
1645 2885 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
1646
2886
1647 2887 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
1648 2888 #Parameters
1649 2889 phaseThresh = phaseThresh*numpy.pi/180
1650 2890 thresh = [phaseThresh, noise_multiple, SNRThresh]
1651 2891 #Meteor reestimation (Errors N 1, 6, 12, 17)
1652 2892 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
1653 2893 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
1654 2894 #Estimation of decay times (Errors N 7, 8, 11)
1655 2895 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
1656 2896 #******************* END OF METEOR REESTIMATION *******************
1657
2897
1658 2898 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
1659 2899 #Calculating Radial Velocity (Error N 15)
1660 2900 radialStdThresh = 10
1661 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2901 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
1662 2902
1663 2903 if len(listMeteors4) > 0:
1664 2904 #Setting New Array
1665 2905 date = dataOut.utctime
1666 2906 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
1667
2907
1668 2908 #Correcting phase offset
1669 2909 if phaseOffsets != None:
1670 2910 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
1671 2911 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
1672
2912
1673 2913 #Second Pairslist
1674 2914 pairsList = []
1675 2915 pairx = (0,1)
1676 2916 pairy = (2,3)
1677 2917 pairsList.append(pairx)
1678 2918 pairsList.append(pairy)
1679
2919
1680 2920 jph = numpy.array([0,0,0,0])
1681 2921 h = (hmin,hmax)
1682 2922 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
1683
2923
1684 2924 # #Calculate AOA (Error N 3, 4)
1685 2925 # #JONES ET AL. 1998
1686 2926 # error = arrayParameters[:,-1]
1687 2927 # AOAthresh = numpy.pi/8
1688 2928 # phases = -arrayParameters[:,9:13]
1689 2929 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
1690 #
2930 #
1691 2931 # #Calculate Heights (Error N 13 and 14)
1692 2932 # error = arrayParameters[:,-1]
1693 2933 # Ranges = arrayParameters[:,2]
1694 2934 # zenith = arrayParameters[:,5]
1695 2935 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
1696 2936 # error = arrayParameters[:,-1]
1697 2937 #********************* END OF PARAMETERS CALCULATION **************************
1698
1699 #***************************+ PASS DATA TO NEXT STEP **********************
2938
2939 #***************************+ PASS DATA TO NEXT STEP **********************
1700 2940 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
1701 2941 dataOut.data_param = arrayParameters
1702
1703 if arrayParameters is None:
2942
2943 if arrayParameters == None:
1704 2944 dataOut.flagNoData = True
1705 2945 else:
1706 2946 dataOut.flagNoData = True
1707
2947
1708 2948 return
1709
2949
1710 2950 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
1711
2951
1712 2952 minIndex = min(newheis[0])
1713 2953 maxIndex = max(newheis[0])
1714
2954
1715 2955 voltage = voltage0[:,:,minIndex:maxIndex+1]
1716 2956 nLength = voltage.shape[1]/n
1717 2957 nMin = 0
1718 2958 nMax = 0
1719 2959 phaseOffset = numpy.zeros((len(pairslist),n))
1720
2960
1721 2961 for i in range(n):
1722 2962 nMax += nLength
1723 2963 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
1724 2964 phaseCCF = numpy.mean(phaseCCF, axis = 2)
1725 phaseOffset[:,i] = phaseCCF.transpose()
2965 phaseOffset[:,i] = phaseCCF.transpose()
1726 2966 nMin = nMax
1727 2967 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
1728
2968
1729 2969 #Remove Outliers
1730 2970 factor = 2
1731 2971 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
1732 2972 dw = numpy.std(wt,axis = 1)
1733 2973 dw = dw.reshape((dw.size,1))
1734 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2974 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
1735 2975 phaseOffset[ind] = numpy.nan
1736 phaseOffset = stats.nanmean(phaseOffset, axis=1)
1737
2976 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2977
1738 2978 return phaseOffset
1739
2979
1740 2980 def __shiftPhase(self, data, phaseShift):
1741 2981 #this will shift the phase of a complex number
1742 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2982 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
1743 2983 return dataShifted
1744
2984
1745 2985 def __estimatePhaseDifference(self, array, pairslist):
1746 2986 nChannel = array.shape[0]
1747 2987 nHeights = array.shape[2]
1748 2988 numPairs = len(pairslist)
1749 2989 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
1750 2990 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
1751
2991
1752 2992 #Correct phases
1753 2993 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
1754 2994 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
1755
1756 if indDer[0].shape[0] > 0:
2995
2996 if indDer[0].shape[0] > 0:
1757 2997 for i in range(indDer[0].shape[0]):
1758 2998 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
1759 2999 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
1760
3000
1761 3001 # for j in range(numSides):
1762 3002 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
1763 3003 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
1764 #
3004 #
1765 3005 #Linear
1766 3006 phaseInt = numpy.zeros((numPairs,1))
1767 3007 angAllCCF = phaseCCF[:,[0,1,3,4],0]
1768 3008 for j in range(numPairs):
1769 3009 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
1770 3010 phaseInt[j] = fit[1]
1771 3011 #Phase Differences
1772 3012 phaseDiff = phaseInt - phaseCCF[:,2,:]
1773 3013 phaseArrival = phaseInt.reshape(phaseInt.size)
1774
3014
1775 3015 #Dealias
1776 3016 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
1777 3017 # indAlias = numpy.where(phaseArrival > numpy.pi)
1778 3018 # phaseArrival[indAlias] -= 2*numpy.pi
1779 3019 # indAlias = numpy.where(phaseArrival < -numpy.pi)
1780 3020 # phaseArrival[indAlias] += 2*numpy.pi
1781
3021
1782 3022 return phaseDiff, phaseArrival
1783
3023
1784 3024 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
1785 3025 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
1786 3026 #find the phase shifts of each channel over 1 second intervals
1787 3027 #only look at ranges below the beacon signal
1788 3028 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1789 3029 numBlocks = int(volts.shape[1]/numProfPerBlock)
1790 3030 numHeights = volts.shape[2]
1791 3031 nChannel = volts.shape[0]
1792 3032 voltsCohDet = volts.copy()
1793
3033
1794 3034 pairsarray = numpy.array(pairslist)
1795 3035 indSides = pairsarray[:,1]
1796 3036 # indSides = numpy.array(range(nChannel))
1797 3037 # indSides = numpy.delete(indSides, indCenter)
1798 #
3038 #
1799 3039 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
1800 3040 listBlocks = numpy.array_split(volts, numBlocks, 1)
1801
3041
1802 3042 startInd = 0
1803 3043 endInd = 0
1804
3044
1805 3045 for i in range(numBlocks):
1806 3046 startInd = endInd
1807 endInd = endInd + listBlocks[i].shape[1]
1808
3047 endInd = endInd + listBlocks[i].shape[1]
3048
1809 3049 arrayBlock = listBlocks[i]
1810 3050 # arrayBlockCenter = listCenter[i]
1811
3051
1812 3052 #Estimate the Phase Difference
1813 3053 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
1814 3054 #Phase Difference RMS
1815 3055 arrayPhaseRMS = numpy.abs(phaseDiff)
1816 3056 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
1817 3057 indPhase = numpy.where(phaseRMSaux==4)
1818 3058 #Shifting
1819 3059 if indPhase[0].shape[0] > 0:
1820 3060 for j in range(indSides.size):
1821 3061 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
1822 3062 voltsCohDet[:,startInd:endInd,:] = arrayBlock
1823
3063
1824 3064 return voltsCohDet
1825
3065
1826 3066 def __calculateCCF(self, volts, pairslist ,laglist):
1827
3067
1828 3068 nHeights = volts.shape[2]
1829 nPoints = volts.shape[1]
3069 nPoints = volts.shape[1]
1830 3070 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
1831
3071
1832 3072 for i in range(len(pairslist)):
1833 3073 volts1 = volts[pairslist[i][0]]
1834 volts2 = volts[pairslist[i][1]]
1835
3074 volts2 = volts[pairslist[i][1]]
3075
1836 3076 for t in range(len(laglist)):
1837 idxT = laglist[t]
3077 idxT = laglist[t]
1838 3078 if idxT >= 0:
1839 3079 vStacked = numpy.vstack((volts2[idxT:,:],
1840 3080 numpy.zeros((idxT, nHeights),dtype='complex')))
1841 3081 else:
1842 3082 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
1843 3083 volts2[:(nPoints + idxT),:]))
1844 3084 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
1845
3085
1846 3086 vStacked = None
1847 3087 return voltsCCF
1848
3088
1849 3089 def __getNoise(self, power, timeSegment, timeInterval):
1850 3090 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
1851 3091 numBlocks = int(power.shape[0]/numProfPerBlock)
1852 3092 numHeights = power.shape[1]
1853 3093
1854 3094 listPower = numpy.array_split(power, numBlocks, 0)
1855 3095 noise = numpy.zeros((power.shape[0], power.shape[1]))
1856 3096 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
1857
3097
1858 3098 startInd = 0
1859 3099 endInd = 0
1860
3100
1861 3101 for i in range(numBlocks): #split por canal
1862 3102 startInd = endInd
1863 endInd = endInd + listPower[i].shape[0]
1864
3103 endInd = endInd + listPower[i].shape[0]
3104
1865 3105 arrayBlock = listPower[i]
1866 3106 noiseAux = numpy.mean(arrayBlock, 0)
1867 3107 # noiseAux = numpy.median(noiseAux)
1868 3108 # noiseAux = numpy.mean(arrayBlock)
1869 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
1870
3109 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
3110
1871 3111 noiseAux1 = numpy.mean(arrayBlock)
1872 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
1873
3112 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
3113
1874 3114 return noise, noise1
1875
3115
1876 3116 def __findMeteors(self, power, thresh):
1877 3117 nProf = power.shape[0]
1878 3118 nHeights = power.shape[1]
1879 3119 listMeteors = []
1880
3120
1881 3121 for i in range(nHeights):
1882 3122 powerAux = power[:,i]
1883 3123 threshAux = thresh[:,i]
1884
3124
1885 3125 indUPthresh = numpy.where(powerAux > threshAux)[0]
1886 3126 indDNthresh = numpy.where(powerAux <= threshAux)[0]
1887
3127
1888 3128 j = 0
1889
3129
1890 3130 while (j < indUPthresh.size - 2):
1891 3131 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
1892 3132 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
1893 3133 indDNthresh = indDNthresh[indDNAux]
1894
3134
1895 3135 if (indDNthresh.size > 0):
1896 3136 indEnd = indDNthresh[0] - 1
1897 indInit = indUPthresh[j] if isinstance(indUPthresh[j], (int, float)) else indUPthresh[j][0] ##CHECK!!!!
1898
3137 indInit = indUPthresh[j]
3138
1899 3139 meteor = powerAux[indInit:indEnd + 1]
1900 3140 indPeak = meteor.argmax() + indInit
1901 3141 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
1902
3142
1903 3143 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
1904 3144 j = numpy.where(indUPthresh == indEnd)[0] + 1
1905 3145 else: j+=1
1906 3146 else: j+=1
1907
3147
1908 3148 return listMeteors
1909
3149
1910 3150 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
1911
1912 arrayMeteors = numpy.asarray(listMeteors)
3151
3152 arrayMeteors = numpy.asarray(listMeteors)
1913 3153 listMeteors1 = []
1914
3154
1915 3155 while arrayMeteors.shape[0] > 0:
1916 3156 FLAs = arrayMeteors[:,4]
1917 3157 maxFLA = FLAs.argmax()
1918 3158 listMeteors1.append(arrayMeteors[maxFLA,:])
1919
3159
1920 3160 MeteorInitTime = arrayMeteors[maxFLA,1]
1921 3161 MeteorEndTime = arrayMeteors[maxFLA,3]
1922 3162 MeteorHeight = arrayMeteors[maxFLA,0]
1923
3163
1924 3164 #Check neighborhood
1925 3165 maxHeightIndex = MeteorHeight + rangeLimit
1926 3166 minHeightIndex = MeteorHeight - rangeLimit
1927 3167 minTimeIndex = MeteorInitTime - timeLimit
1928 3168 maxTimeIndex = MeteorEndTime + timeLimit
1929
3169
1930 3170 #Check Heights
1931 3171 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
1932 3172 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
1933 3173 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
1934
3174
1935 3175 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
1936
3176
1937 3177 return listMeteors1
1938
3178
1939 3179 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
1940 3180 numHeights = volts.shape[2]
1941 3181 nChannel = volts.shape[0]
1942
3182
1943 3183 thresholdPhase = thresh[0]
1944 3184 thresholdNoise = thresh[1]
1945 3185 thresholdDB = float(thresh[2])
1946
3186
1947 3187 thresholdDB1 = 10**(thresholdDB/10)
1948 3188 pairsarray = numpy.array(pairslist)
1949 3189 indSides = pairsarray[:,1]
1950
3190
1951 3191 pairslist1 = list(pairslist)
1952 pairslist1.append((0,4))
1953 pairslist1.append((1,3))
3192 pairslist1.append((0,1))
3193 pairslist1.append((3,4))
1954 3194
1955 3195 listMeteors1 = []
1956 3196 listPowerSeries = []
1957 3197 listVoltageSeries = []
1958 3198 #volts has the war data
1959
1960 if frequency == 30.175e6:
3199
3200 if frequency == 30e6:
1961 3201 timeLag = 45*10**-3
1962 3202 else:
1963 3203 timeLag = 15*10**-3
1964 lag = int(numpy.ceil(timeLag/timeInterval))
1965
3204 lag = numpy.ceil(timeLag/timeInterval)
3205
1966 3206 for i in range(len(listMeteors)):
1967
3207
1968 3208 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
1969 3209 meteorAux = numpy.zeros(16)
1970
3210
1971 3211 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
1972 mHeight = int(listMeteors[i][0])
1973 mStart = int(listMeteors[i][1])
1974 mPeak = int(listMeteors[i][2])
1975 mEnd = int(listMeteors[i][3])
1976
3212 mHeight = listMeteors[i][0]
3213 mStart = listMeteors[i][1]
3214 mPeak = listMeteors[i][2]
3215 mEnd = listMeteors[i][3]
3216
1977 3217 #get the volt data between the start and end times of the meteor
1978 3218 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
1979 3219 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
1980
3220
1981 3221 #3.6. Phase Difference estimation
1982 3222 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
1983
3223
1984 3224 #3.7. Phase difference removal & meteor start, peak and end times reestimated
1985 3225 #meteorVolts0.- all Channels, all Profiles
1986 3226 meteorVolts0 = volts[:,:,mHeight]
1987 3227 meteorThresh = noise[:,mHeight]*thresholdNoise
1988 3228 meteorNoise = noise[:,mHeight]
1989 3229 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
1990 3230 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
1991
3231
1992 3232 #Times reestimation
1993 3233 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
1994 3234 if mStart1.size > 0:
1995 mStart1 = mStart1[-1] + 1
1996
1997 else:
3235 mStart1 = mStart1[-1] + 1
3236
3237 else:
1998 3238 mStart1 = mPeak
1999
3239
2000 3240 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
2001 3241 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
2002 3242 if mEndDecayTime1.size == 0:
2003 3243 mEndDecayTime1 = powerNet0.size
2004 3244 else:
2005 3245 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
2006 3246 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
2007
3247
2008 3248 #meteorVolts1.- all Channels, from start to end
2009 3249 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
2010 3250 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
2011 3251 if meteorVolts2.shape[1] == 0:
2012 3252 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
2013 3253 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
2014 3254 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
2015 3255 ##################### END PARAMETERS REESTIMATION #########################
2016
3256
2017 3257 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
2018 3258 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
2019 if meteorVolts2.shape[1] > 0:
3259 if meteorVolts2.shape[1] > 0:
2020 3260 #Phase Difference re-estimation
2021 3261 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
2022 3262 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
2023 3263 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
2024 3264 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
2025 3265 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
2026
3266
2027 3267 #Phase Difference RMS
2028 3268 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
2029 3269 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
2030 3270 #Data from Meteor
2031 3271 mPeak1 = powerNet1.argmax() + mStart1
2032 3272 mPeakPower1 = powerNet1.max()
2033 3273 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
2034 3274 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
2035 3275 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
2036 3276 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
2037 3277 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
2038 3278 #Vectorize
2039 3279 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
2040 3280 meteorAux[7:11] = phaseDiffint[0:4]
2041
3281
2042 3282 #Rejection Criterions
2043 3283 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
2044 3284 meteorAux[-1] = 17
2045 3285 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
2046 3286 meteorAux[-1] = 1
2047
2048
2049 else:
3287
3288
3289 else:
2050 3290 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
2051 3291 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
2052 3292 PowerSeries = 0
2053
3293
2054 3294 listMeteors1.append(meteorAux)
2055 3295 listPowerSeries.append(PowerSeries)
2056 3296 listVoltageSeries.append(meteorVolts1)
2057
2058 return listMeteors1, listPowerSeries, listVoltageSeries
2059
3297
3298 return listMeteors1, listPowerSeries, listVoltageSeries
3299
2060 3300 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
2061
3301
2062 3302 threshError = 10
2063 3303 #Depending if it is 30 or 50 MHz
2064 if frequency == 30.175e6:
3304 if frequency == 30e6:
2065 3305 timeLag = 45*10**-3
2066 3306 else:
2067 3307 timeLag = 15*10**-3
2068 lag = int(numpy.ceil(timeLag/timeInterval))
2069
3308 lag = numpy.ceil(timeLag/timeInterval)
3309
2070 3310 listMeteors1 = []
2071
3311
2072 3312 for i in range(len(listMeteors)):
2073 3313 meteorPower = listPower[i]
2074 3314 meteorAux = listMeteors[i]
2075
3315
2076 3316 if meteorAux[-1] == 0:
2077 3317
2078 try:
3318 try:
2079 3319 indmax = meteorPower.argmax()
2080 3320 indlag = indmax + lag
2081
3321
2082 3322 y = meteorPower[indlag:]
2083 3323 x = numpy.arange(0, y.size)*timeLag
2084
3324
2085 3325 #first guess
2086 3326 a = y[0]
2087 3327 tau = timeLag
2088 3328 #exponential fit
2089 3329 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
2090 3330 y1 = self.__exponential_function(x, *popt)
2091 3331 #error estimation
2092 3332 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
2093
3333
2094 3334 decayTime = popt[1]
2095 3335 riseTime = indmax*timeInterval
2096 3336 meteorAux[11:13] = [decayTime, error]
2097
3337
2098 3338 #Table items 7, 8 and 11
2099 3339 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
2100 meteorAux[-1] = 7
3340 meteorAux[-1] = 7
2101 3341 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
2102 3342 meteorAux[-1] = 8
2103 3343 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
2104 meteorAux[-1] = 11
2105
2106
3344 meteorAux[-1] = 11
3345
3346
2107 3347 except:
2108 meteorAux[-1] = 11
2109
2110
3348 meteorAux[-1] = 11
3349
3350
2111 3351 listMeteors1.append(meteorAux)
2112
3352
2113 3353 return listMeteors1
2114 3354
2115 3355 #Exponential Function
2116 3356
2117 3357 def __exponential_function(self, x, a, tau):
2118 3358 y = a*numpy.exp(-x/tau)
2119 3359 return y
2120
3360
2121 3361 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
2122
3362
2123 3363 pairslist1 = list(pairslist)
2124 pairslist1.append((0,4))
2125 pairslist1.append((1,3))
3364 pairslist1.append((0,1))
3365 pairslist1.append((3,4))
2126 3366 numPairs = len(pairslist1)
2127 3367 #Time Lag
2128 3368 timeLag = 45*10**-3
2129 3369 c = 3e8
2130 3370 lag = numpy.ceil(timeLag/timeInterval)
2131 freq = 30.175e6
2132
3371 freq = 30e6
3372
2133 3373 listMeteors1 = []
2134
3374
2135 3375 for i in range(len(listMeteors)):
2136 3376 meteorAux = listMeteors[i]
2137 3377 if meteorAux[-1] == 0:
2138 3378 mStart = listMeteors[i][1]
2139 mPeak = listMeteors[i][2]
3379 mPeak = listMeteors[i][2]
2140 3380 mLag = mPeak - mStart + lag
2141
3381
2142 3382 #get the volt data between the start and end times of the meteor
2143 3383 meteorVolts = listVolts[i]
2144 3384 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
2145 3385
2146 3386 #Get CCF
2147 3387 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
2148
3388
2149 3389 #Method 2
2150 3390 slopes = numpy.zeros(numPairs)
2151 3391 time = numpy.array([-2,-1,1,2])*timeInterval
2152 angAllCCF = numpy.angle(allCCFs[:,[0,4,2,3],0])
2153
3392 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3393
2154 3394 #Correct phases
2155 3395 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
2156 3396 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2157
2158 if indDer[0].shape[0] > 0:
3397
3398 if indDer[0].shape[0] > 0:
2159 3399 for i in range(indDer[0].shape[0]):
2160 3400 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
2161 3401 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
2162 3402
2163 3403 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
2164 3404 for j in range(numPairs):
2165 3405 fit = stats.linregress(time, angAllCCF[j,:])
2166 3406 slopes[j] = fit[0]
2167
3407
2168 3408 #Remove Outlier
2169 3409 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2170 3410 # slopes = numpy.delete(slopes,indOut)
2171 3411 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
2172 3412 # slopes = numpy.delete(slopes,indOut)
2173
3413
2174 3414 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
2175 3415 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
2176 3416 meteorAux[-2] = radialError
2177 3417 meteorAux[-3] = radialVelocity
2178
3418
2179 3419 #Setting Error
2180 3420 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
2181 if numpy.abs(radialVelocity) > 200:
3421 if numpy.abs(radialVelocity) > 200:
2182 3422 meteorAux[-1] = 15
2183 3423 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
2184 3424 elif radialError > radialStdThresh:
2185 3425 meteorAux[-1] = 12
2186
3426
2187 3427 listMeteors1.append(meteorAux)
2188 3428 return listMeteors1
2189
3429
2190 3430 def __setNewArrays(self, listMeteors, date, heiRang):
2191
3431
2192 3432 #New arrays
2193 3433 arrayMeteors = numpy.array(listMeteors)
2194 3434 arrayParameters = numpy.zeros((len(listMeteors), 13))
2195
3435
2196 3436 #Date inclusion
2197 3437 # date = re.findall(r'\((.*?)\)', date)
2198 3438 # date = date[0].split(',')
2199 3439 # date = map(int, date)
2200 #
3440 #
2201 3441 # if len(date)<6:
2202 3442 # date.append(0)
2203 #
3443 #
2204 3444 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
2205 3445 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
2206 3446 arrayDate = numpy.tile(date, (len(listMeteors)))
2207
3447
2208 3448 #Meteor array
2209 3449 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
2210 3450 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
2211
3451
2212 3452 #Parameters Array
2213 3453 arrayParameters[:,0] = arrayDate #Date
2214 3454 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
2215 3455 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
2216 3456 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
2217 3457 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
2218 3458
2219
3459
2220 3460 return arrayParameters
2221
3461
2222 3462 class CorrectSMPhases(Operation):
2223
3463
2224 3464 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
2225
3465
2226 3466 arrayParameters = dataOut.data_param
2227 3467 pairsList = []
2228 3468 pairx = (0,1)
2229 3469 pairy = (2,3)
2230 3470 pairsList.append(pairx)
2231 3471 pairsList.append(pairy)
2232 3472 jph = numpy.zeros(4)
2233
3473
2234 3474 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2235 3475 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2236 3476 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
2237
3477
2238 3478 meteorOps = SMOperations()
2239 if channelPositions is None:
3479 if channelPositions == None:
2240 3480 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2241 3481 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2242
3482
2243 3483 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2244 3484 h = (hmin,hmax)
2245
3485
2246 3486 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2247
3487
2248 3488 dataOut.data_param = arrayParameters
2249 3489 return
2250 3490
2251 3491 class SMPhaseCalibration(Operation):
2252
3492
2253 3493 __buffer = None
2254 3494
2255 3495 __initime = None
2256 3496
2257 3497 __dataReady = False
2258
3498
2259 3499 __isConfig = False
2260
3500
2261 3501 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
2262
3502
2263 3503 dataTime = currentTime + paramInterval
2264 3504 deltaTime = dataTime - initTime
2265
3505
2266 3506 if deltaTime >= outputInterval or deltaTime < 0:
2267 3507 return True
2268
3508
2269 3509 return False
2270
3510
2271 3511 def __getGammas(self, pairs, d, phases):
2272 3512 gammas = numpy.zeros(2)
2273
3513
2274 3514 for i in range(len(pairs)):
2275
3515
2276 3516 pairi = pairs[i]
2277 3517
2278 3518 phip3 = phases[:,pairi[0]]
2279 3519 d3 = d[pairi[0]]
2280 3520 phip2 = phases[:,pairi[1]]
2281 3521 d2 = d[pairi[1]]
2282 3522 #Calculating gamma
2283 3523 # jdcos = alp1/(k*d1)
2284 3524 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
2285 3525 jgamma = -phip2*d3/d2 - phip3
2286 3526 jgamma = numpy.angle(numpy.exp(1j*jgamma))
2287 3527 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
2288 3528 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
2289
3529
2290 3530 #Revised distribution
2291 3531 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
2292 3532
2293 3533 #Histogram
2294 3534 nBins = 64
2295 3535 rmin = -0.5*numpy.pi
2296 3536 rmax = 0.5*numpy.pi
2297 3537 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
2298
3538
2299 3539 meteorsY = phaseHisto[0]
2300 3540 phasesX = phaseHisto[1][:-1]
2301 3541 width = phasesX[1] - phasesX[0]
2302 3542 phasesX += width/2
2303
3543
2304 3544 #Gaussian aproximation
2305 3545 bpeak = meteorsY.argmax()
2306 3546 peak = meteorsY.max()
2307 3547 jmin = bpeak - 5
2308 3548 jmax = bpeak + 5 + 1
2309
3549
2310 3550 if jmin<0:
2311 3551 jmin = 0
2312 3552 jmax = 6
2313 3553 elif jmax > meteorsY.size:
2314 3554 jmin = meteorsY.size - 6
2315 3555 jmax = meteorsY.size
2316
3556
2317 3557 x0 = numpy.array([peak,bpeak,50])
2318 3558 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
2319
3559
2320 3560 #Gammas
2321 3561 gammas[i] = coeff[0][1]
2322
3562
2323 3563 return gammas
2324
3564
2325 3565 def __residualFunction(self, coeffs, y, t):
2326
3566
2327 3567 return y - self.__gauss_function(t, coeffs)
2328 3568
2329 3569 def __gauss_function(self, t, coeffs):
2330
3570
2331 3571 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
2332 3572
2333 3573 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
2334 3574 meteorOps = SMOperations()
2335 3575 nchan = 4
2336 3576 pairx = pairsList[0] #x es 0
2337 3577 pairy = pairsList[1] #y es 1
2338 3578 center_xangle = 0
2339 3579 center_yangle = 0
2340 3580 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
2341 3581 ntimes = len(range_angle)
2342 3582
2343 3583 nstepsx = 20
2344 3584 nstepsy = 20
2345 3585
2346 3586 for iz in range(ntimes):
2347 3587 min_xangle = -range_angle[iz]/2 + center_xangle
2348 3588 max_xangle = range_angle[iz]/2 + center_xangle
2349 3589 min_yangle = -range_angle[iz]/2 + center_yangle
2350 3590 max_yangle = range_angle[iz]/2 + center_yangle
2351
3591
2352 3592 inc_x = (max_xangle-min_xangle)/nstepsx
2353 3593 inc_y = (max_yangle-min_yangle)/nstepsy
2354
3594
2355 3595 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
2356 3596 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
2357 3597 penalty = numpy.zeros((nstepsx,nstepsy))
2358 3598 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
2359 3599 jph = numpy.zeros(nchan)
2360
3600
2361 3601 # Iterations looking for the offset
2362 3602 for iy in range(int(nstepsy)):
2363 3603 for ix in range(int(nstepsx)):
2364 3604 d3 = d[pairsList[1][0]]
2365 3605 d2 = d[pairsList[1][1]]
2366 3606 d5 = d[pairsList[0][0]]
2367 3607 d4 = d[pairsList[0][1]]
2368 3608
2369 3609 alp2 = alpha_y[iy] #gamma 1
2370 3610 alp4 = alpha_x[ix] #gamma 0
2371 3611
2372 3612 alp3 = -alp2*d3/d2 - gammas[1]
2373 3613 alp5 = -alp4*d5/d4 - gammas[0]
2374 3614 # jph[pairy[1]] = alpha_y[iy]
2375 3615 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
2376 3616
2377 3617 # jph[pairx[1]] = alpha_x[ix]
2378 3618 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
2379 3619 jph[pairsList[0][1]] = alp4
2380 3620 jph[pairsList[0][0]] = alp5
2381 3621 jph[pairsList[1][0]] = alp3
2382 3622 jph[pairsList[1][1]] = alp2
2383 3623 jph_array[:,ix,iy] = jph
2384 3624 # d = [2.0,2.5,2.5,2.0]
2385 3625 #falta chequear si va a leer bien los meteoros
2386 3626 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
2387 3627 error = meteorsArray1[:,-1]
2388 3628 ind1 = numpy.where(error==0)[0]
2389 3629 penalty[ix,iy] = ind1.size
2390
3630
2391 3631 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
2392 3632 phOffset = jph_array[:,i,j]
2393
3633
2394 3634 center_xangle = phOffset[pairx[1]]
2395 3635 center_yangle = phOffset[pairy[1]]
2396
3636
2397 3637 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
2398 phOffset = phOffset*180/numpy.pi
3638 phOffset = phOffset*180/numpy.pi
2399 3639 return phOffset
2400
2401
3640
3641
2402 3642 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
2403
3643
2404 3644 dataOut.flagNoData = True
2405 self.__dataReady = False
3645 self.__dataReady = False
2406 3646 dataOut.outputInterval = nHours*3600
2407
3647
2408 3648 if self.__isConfig == False:
2409 3649 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2410 3650 #Get Initial LTC time
2411 3651 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2412 3652 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2413 3653
2414 3654 self.__isConfig = True
2415
2416 if self.__buffer is None:
3655
3656 if self.__buffer == None:
2417 3657 self.__buffer = dataOut.data_param.copy()
2418 3658
2419 3659 else:
2420 3660 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2421
3661
2422 3662 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2423
3663
2424 3664 if self.__dataReady:
2425 3665 dataOut.utctimeInit = self.__initime
2426 3666 self.__initime += dataOut.outputInterval #to erase time offset
2427
3667
2428 3668 freq = dataOut.frequency
2429 3669 c = dataOut.C #m/s
2430 3670 lamb = c/freq
2431 3671 k = 2*numpy.pi/lamb
2432 3672 azimuth = 0
2433 3673 h = (hmin, hmax)
2434 3674 # pairs = ((0,1),(2,3)) #Estrella
2435 3675 # pairs = ((1,0),(2,3)) #T
2436 3676
2437 3677 if channelPositions is None:
2438 3678 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2439 3679 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2440 3680 meteorOps = SMOperations()
2441 3681 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2442 3682
2443 3683 #Checking correct order of pairs
2444 3684 pairs = []
2445 3685 if distances[1] > distances[0]:
2446 3686 pairs.append((1,0))
2447 3687 else:
2448 3688 pairs.append((0,1))
2449 3689
2450 3690 if distances[3] > distances[2]:
2451 3691 pairs.append((3,2))
2452 3692 else:
2453 3693 pairs.append((2,3))
2454 3694 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
2455
3695
2456 3696 meteorsArray = self.__buffer
2457 3697 error = meteorsArray[:,-1]
2458 3698 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
2459 3699 ind1 = numpy.where(boolError)[0]
2460 3700 meteorsArray = meteorsArray[ind1,:]
2461 3701 meteorsArray[:,-1] = 0
2462 3702 phases = meteorsArray[:,8:12]
2463
3703
2464 3704 #Calculate Gammas
2465 3705 gammas = self.__getGammas(pairs, distances, phases)
2466 3706 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
2467 3707 #Calculate Phases
2468 3708 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
2469 3709 phasesOff = phasesOff.reshape((1,phasesOff.size))
2470 3710 dataOut.data_output = -phasesOff
2471 3711 dataOut.flagNoData = False
2472 dataOut.channelList = pairslist0
2473 3712 self.__buffer = None
2474
2475
3713
3714
2476 3715 return
2477
3716
2478 3717 class SMOperations():
2479
3718
2480 3719 def __init__(self):
2481
3720
2482 3721 return
2483
3722
2484 3723 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
2485
3724
2486 3725 arrayParameters = arrayParameters0.copy()
2487 3726 hmin = h[0]
2488 3727 hmax = h[1]
2489
3728
2490 3729 #Calculate AOA (Error N 3, 4)
2491 3730 #JONES ET AL. 1998
2492 3731 AOAthresh = numpy.pi/8
2493 3732 error = arrayParameters[:,-1]
2494 3733 phases = -arrayParameters[:,8:12] + jph
2495 3734 # phases = numpy.unwrap(phases)
2496 3735 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
2497
3736
2498 3737 #Calculate Heights (Error N 13 and 14)
2499 3738 error = arrayParameters[:,-1]
2500 3739 Ranges = arrayParameters[:,1]
2501 3740 zenith = arrayParameters[:,4]
2502 3741 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
2503
3742
2504 3743 #----------------------- Get Final data ------------------------------------
2505 3744 # error = arrayParameters[:,-1]
2506 3745 # ind1 = numpy.where(error==0)[0]
2507 3746 # arrayParameters = arrayParameters[ind1,:]
2508
3747
2509 3748 return arrayParameters
2510
3749
2511 3750 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
2512
3751
2513 3752 arrayAOA = numpy.zeros((phases.shape[0],3))
2514 3753 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
2515
3754
2516 3755 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2517 3756 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2518 3757 arrayAOA[:,2] = cosDirError
2519
3758
2520 3759 azimuthAngle = arrayAOA[:,0]
2521 3760 zenithAngle = arrayAOA[:,1]
2522
3761
2523 3762 #Setting Error
2524 3763 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
2525 3764 error[indError] = 0
2526 3765 #Number 3: AOA not fesible
2527 3766 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2528 error[indInvalid] = 3
3767 error[indInvalid] = 3
2529 3768 #Number 4: Large difference in AOAs obtained from different antenna baselines
2530 3769 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2531 error[indInvalid] = 4
3770 error[indInvalid] = 4
2532 3771 return arrayAOA, error
2533
3772
2534 3773 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
2535
3774
2536 3775 #Initializing some variables
2537 3776 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2538 3777 ang_aux = ang_aux.reshape(1,ang_aux.size)
2539
3778
2540 3779 cosdir = numpy.zeros((arrayPhase.shape[0],2))
2541 3780 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2542
2543
3781
3782
2544 3783 for i in range(2):
2545 3784 ph0 = arrayPhase[:,pairsList[i][0]]
2546 3785 ph1 = arrayPhase[:,pairsList[i][1]]
2547 3786 d0 = distances[pairsList[i][0]]
2548 3787 d1 = distances[pairsList[i][1]]
2549
2550 ph0_aux = ph0 + ph1
3788
3789 ph0_aux = ph0 + ph1
2551 3790 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
2552 3791 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
2553 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3792 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
2554 3793 #First Estimation
2555 3794 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
2556
3795
2557 3796 #Most-Accurate Second Estimation
2558 3797 phi1_aux = ph0 - ph1
2559 3798 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2560 3799 #Direction Cosine 1
2561 3800 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
2562
3801
2563 3802 #Searching the correct Direction Cosine
2564 3803 cosdir0_aux = cosdir0[:,i]
2565 3804 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2566 3805 #Minimum Distance
2567 3806 cosDiff = (cosdir1 - cosdir0_aux)**2
2568 3807 indcos = cosDiff.argmin(axis = 1)
2569 3808 #Saving Value obtained
2570 3809 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2571
3810
2572 3811 return cosdir0, cosdir
2573
3812
2574 3813 def __calculateAOA(self, cosdir, azimuth):
2575 3814 cosdirX = cosdir[:,0]
2576 3815 cosdirY = cosdir[:,1]
2577
3816
2578 3817 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2579 3818 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
2580 3819 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2581
3820
2582 3821 return angles
2583
3822
2584 3823 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2585
3824
2586 3825 Ramb = 375 #Ramb = c/(2*PRF)
2587 3826 Re = 6371 #Earth Radius
2588 3827 heights = numpy.zeros(Ranges.shape)
2589
3828
2590 3829 R_aux = numpy.array([0,1,2])*Ramb
2591 3830 R_aux = R_aux.reshape(1,R_aux.size)
2592 3831
2593 3832 Ranges = Ranges.reshape(Ranges.size,1)
2594
3833
2595 3834 Ri = Ranges + R_aux
2596 3835 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2597
3836
2598 3837 #Check if there is a height between 70 and 110 km
2599 3838 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2600 3839 ind_h = numpy.where(h_bool == 1)[0]
2601
3840
2602 3841 hCorr = hi[ind_h, :]
2603 3842 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2604 3843
2605 3844 hCorr = hi[ind_hCorr][:len(ind_h)]
2606 3845 heights[ind_h] = hCorr
2607
3846
2608 3847 #Setting Error
2609 3848 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2610 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3849 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2611 3850 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
2612 3851 error[indError] = 0
2613 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3852 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2614 3853 error[indInvalid2] = 14
2615 3854 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2616 error[indInvalid1] = 13
2617
3855 error[indInvalid1] = 13
3856
2618 3857 return heights, error
2619
3858
2620 3859 def getPhasePairs(self, channelPositions):
2621 3860 chanPos = numpy.array(channelPositions)
2622 3861 listOper = list(itertools.combinations(range(5),2))
2623
3862
2624 3863 distances = numpy.zeros(4)
2625 3864 axisX = []
2626 3865 axisY = []
2627 3866 distX = numpy.zeros(3)
2628 3867 distY = numpy.zeros(3)
2629 3868 ix = 0
2630 3869 iy = 0
2631
3870
2632 3871 pairX = numpy.zeros((2,2))
2633 3872 pairY = numpy.zeros((2,2))
2634
3873
2635 3874 for i in range(len(listOper)):
2636 3875 pairi = listOper[i]
2637
3876
2638 3877 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
2639
3878
2640 3879 if posDif[0] == 0:
2641 3880 axisY.append(pairi)
2642 3881 distY[iy] = posDif[1]
2643 3882 iy += 1
2644 3883 elif posDif[1] == 0:
2645 3884 axisX.append(pairi)
2646 3885 distX[ix] = posDif[0]
2647 3886 ix += 1
2648
3887
2649 3888 for i in range(2):
2650 3889 if i==0:
2651 3890 dist0 = distX
2652 3891 axis0 = axisX
2653 3892 else:
2654 3893 dist0 = distY
2655 3894 axis0 = axisY
2656
3895
2657 3896 side = numpy.argsort(dist0)[:-1]
2658 3897 axis0 = numpy.array(axis0)[side,:]
2659 3898 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
2660 3899 axis1 = numpy.unique(numpy.reshape(axis0,4))
2661 3900 side = axis1[axis1 != chanC]
2662 3901 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
2663 3902 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
2664 if diff1<0:
3903 if diff1<0:
2665 3904 chan2 = side[0]
2666 3905 d2 = numpy.abs(diff1)
2667 3906 chan1 = side[1]
2668 3907 d1 = numpy.abs(diff2)
2669 3908 else:
2670 3909 chan2 = side[1]
2671 3910 d2 = numpy.abs(diff2)
2672 3911 chan1 = side[0]
2673 3912 d1 = numpy.abs(diff1)
2674
3913
2675 3914 if i==0:
2676 3915 chanCX = chanC
2677 3916 chan1X = chan1
2678 3917 chan2X = chan2
2679 3918 distances[0:2] = numpy.array([d1,d2])
2680 3919 else:
2681 3920 chanCY = chanC
2682 3921 chan1Y = chan1
2683 3922 chan2Y = chan2
2684 3923 distances[2:4] = numpy.array([d1,d2])
2685 3924 # axisXsides = numpy.reshape(axisX[ix,:],4)
2686 #
3925 #
2687 3926 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
2688 3927 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
2689 #
3928 #
2690 3929 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
2691 3930 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
2692 3931 # channel25X = int(pairX[0,ind25X])
2693 3932 # channel20X = int(pairX[1,ind20X])
2694 3933 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
2695 3934 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
2696 3935 # channel25Y = int(pairY[0,ind25Y])
2697 3936 # channel20Y = int(pairY[1,ind20Y])
2698
3937
2699 3938 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
2700 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
2701
3939 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3940
2702 3941 return pairslist, distances
2703 3942 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
2704 #
3943 #
2705 3944 # arrayAOA = numpy.zeros((phases.shape[0],3))
2706 3945 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
2707 #
3946 #
2708 3947 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
2709 3948 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
2710 3949 # arrayAOA[:,2] = cosDirError
2711 #
3950 #
2712 3951 # azimuthAngle = arrayAOA[:,0]
2713 3952 # zenithAngle = arrayAOA[:,1]
2714 #
3953 #
2715 3954 # #Setting Error
2716 3955 # #Number 3: AOA not fesible
2717 3956 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
2718 # error[indInvalid] = 3
3957 # error[indInvalid] = 3
2719 3958 # #Number 4: Large difference in AOAs obtained from different antenna baselines
2720 3959 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
2721 # error[indInvalid] = 4
3960 # error[indInvalid] = 4
2722 3961 # return arrayAOA, error
2723 #
3962 #
2724 3963 # def __getDirectionCosines(self, arrayPhase, pairsList):
2725 #
3964 #
2726 3965 # #Initializing some variables
2727 3966 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
2728 3967 # ang_aux = ang_aux.reshape(1,ang_aux.size)
2729 #
3968 #
2730 3969 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
2731 3970 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
2732 #
2733 #
3971 #
3972 #
2734 3973 # for i in range(2):
2735 3974 # #First Estimation
2736 3975 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
2737 3976 # #Dealias
2738 3977 # indcsi = numpy.where(phi0_aux > numpy.pi)
2739 # phi0_aux[indcsi] -= 2*numpy.pi
3978 # phi0_aux[indcsi] -= 2*numpy.pi
2740 3979 # indcsi = numpy.where(phi0_aux < -numpy.pi)
2741 # phi0_aux[indcsi] += 2*numpy.pi
3980 # phi0_aux[indcsi] += 2*numpy.pi
2742 3981 # #Direction Cosine 0
2743 3982 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
2744 #
3983 #
2745 3984 # #Most-Accurate Second Estimation
2746 3985 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
2747 3986 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
2748 3987 # #Direction Cosine 1
2749 3988 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
2750 #
3989 #
2751 3990 # #Searching the correct Direction Cosine
2752 3991 # cosdir0_aux = cosdir0[:,i]
2753 3992 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
2754 3993 # #Minimum Distance
2755 3994 # cosDiff = (cosdir1 - cosdir0_aux)**2
2756 3995 # indcos = cosDiff.argmin(axis = 1)
2757 3996 # #Saving Value obtained
2758 3997 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
2759 #
3998 #
2760 3999 # return cosdir0, cosdir
2761 #
4000 #
2762 4001 # def __calculateAOA(self, cosdir, azimuth):
2763 4002 # cosdirX = cosdir[:,0]
2764 4003 # cosdirY = cosdir[:,1]
2765 #
4004 #
2766 4005 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
2767 4006 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
2768 4007 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
2769 #
4008 #
2770 4009 # return angles
2771 #
4010 #
2772 4011 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
2773 #
4012 #
2774 4013 # Ramb = 375 #Ramb = c/(2*PRF)
2775 4014 # Re = 6371 #Earth Radius
2776 4015 # heights = numpy.zeros(Ranges.shape)
2777 #
4016 #
2778 4017 # R_aux = numpy.array([0,1,2])*Ramb
2779 4018 # R_aux = R_aux.reshape(1,R_aux.size)
2780 #
4019 #
2781 4020 # Ranges = Ranges.reshape(Ranges.size,1)
2782 #
4021 #
2783 4022 # Ri = Ranges + R_aux
2784 4023 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
2785 #
4024 #
2786 4025 # #Check if there is a height between 70 and 110 km
2787 4026 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
2788 4027 # ind_h = numpy.where(h_bool == 1)[0]
2789 #
4028 #
2790 4029 # hCorr = hi[ind_h, :]
2791 4030 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
2792 #
2793 # hCorr = hi[ind_hCorr]
4031 #
4032 # hCorr = hi[ind_hCorr]
2794 4033 # heights[ind_h] = hCorr
2795 #
4034 #
2796 4035 # #Setting Error
2797 4036 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
2798 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
2799 #
2800 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
4037 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
4038 #
4039 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
2801 4040 # error[indInvalid2] = 14
2802 4041 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
2803 # error[indInvalid1] = 13
2804 #
2805 # return heights, error
4042 # error[indInvalid1] = 13
4043 #
4044 # return heights, error
4045 No newline at end of file
@@ -1,904 +1,903
1 import itertools
2
1 3 import numpy
2 4
3 5 from jroproc_base import ProcessingUnit, Operation
4 6 from schainpy.model.data.jrodata import Spectra
5 7 from schainpy.model.data.jrodata import hildebrand_sekhon
6 8
7 9 class SpectraProc(ProcessingUnit):
8 10
9 11 def __init__(self, **kwargs):
10 12
11 13 ProcessingUnit.__init__(self, **kwargs)
12 14
13 15 self.buffer = None
14 16 self.firstdatatime = None
15 17 self.profIndex = 0
16 18 self.dataOut = Spectra()
17 19 self.id_min = None
18 20 self.id_max = None
19 21
20 22 def __updateSpecFromVoltage(self):
21 23
22 24 self.dataOut.timeZone = self.dataIn.timeZone
23 25 self.dataOut.dstFlag = self.dataIn.dstFlag
24 26 self.dataOut.errorCount = self.dataIn.errorCount
25 27 self.dataOut.useLocalTime = self.dataIn.useLocalTime
26 28
27 29 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
28 30 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
29 31 self.dataOut.channelList = self.dataIn.channelList
30 32 self.dataOut.heightList = self.dataIn.heightList
31 33 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
32 34
33 35 self.dataOut.nBaud = self.dataIn.nBaud
34 36 self.dataOut.nCode = self.dataIn.nCode
35 37 self.dataOut.code = self.dataIn.code
36 38 self.dataOut.nProfiles = self.dataOut.nFFTPoints
37 39
38 40 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
39 41 self.dataOut.utctime = self.firstdatatime
40 42 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
41 43 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
42 44 self.dataOut.flagShiftFFT = False
43 45
44 46 self.dataOut.nCohInt = self.dataIn.nCohInt
45 47 self.dataOut.nIncohInt = 1
46 48
47 49 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
48 50
49 51 self.dataOut.frequency = self.dataIn.frequency
50 52 self.dataOut.realtime = self.dataIn.realtime
51 53
52 54 self.dataOut.azimuth = self.dataIn.azimuth
53 55 self.dataOut.zenith = self.dataIn.zenith
54 56
55 57 self.dataOut.beam.codeList = self.dataIn.beam.codeList
56 58 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
57 59 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
58 60
59 61 def __getFft(self):
60 62 """
61 63 Convierte valores de Voltaje a Spectra
62 64
63 65 Affected:
64 66 self.dataOut.data_spc
65 67 self.dataOut.data_cspc
66 68 self.dataOut.data_dc
67 69 self.dataOut.heightList
68 70 self.profIndex
69 71 self.buffer
70 72 self.dataOut.flagNoData
71 73 """
72 74 fft_volt = numpy.fft.fft(self.buffer,n=self.dataOut.nFFTPoints,axis=1)
73 75 fft_volt = fft_volt.astype(numpy.dtype('complex'))
74 76 dc = fft_volt[:,0,:]
75 77
76 78 #calculo de self-spectra
77 79 fft_volt = numpy.fft.fftshift(fft_volt,axes=(1,))
78 80 spc = fft_volt * numpy.conjugate(fft_volt)
79 81 spc = spc.real
80 82
81 83 blocksize = 0
82 84 blocksize += dc.size
83 85 blocksize += spc.size
84 86
85 87 cspc = None
86 88 pairIndex = 0
87 89 if self.dataOut.pairsList != None:
88 90 #calculo de cross-spectra
89 91 cspc = numpy.zeros((self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
90 92 for pair in self.dataOut.pairsList:
91 93 if pair[0] not in self.dataOut.channelList:
92 94 raise ValueError, "Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" %(str(pair), str(self.dataOut.channelList))
93 95 if pair[1] not in self.dataOut.channelList:
94 96 raise ValueError, "Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" %(str(pair), str(self.dataOut.channelList))
95 97
96 98 cspc[pairIndex,:,:] = fft_volt[pair[0],:,:] * numpy.conjugate(fft_volt[pair[1],:,:])
97 99 pairIndex += 1
98 100 blocksize += cspc.size
99 101
100 102 self.dataOut.data_spc = spc
101 103 self.dataOut.data_cspc = cspc
102 104 self.dataOut.data_dc = dc
103 105 self.dataOut.blockSize = blocksize
104 106 self.dataOut.flagShiftFFT = True
105 107
106 108 def run(self, nProfiles=None, nFFTPoints=None, pairsList=[], ippFactor=None):
107 109
108 110 self.dataOut.flagNoData = True
109 111
110 112 if self.dataIn.type == "Spectra":
111 113 self.dataOut.copy(self.dataIn)
112 # self.__selectPairs(pairsList)
114 if not pairsList:
115 pairsList = itertools.combinations(self.dataOut.channelList, 2)
116 if self.dataOut.data_cspc is not None:
117 self.__selectPairs(pairsList)
113 118 return True
114 119
115 120 if self.dataIn.type == "Voltage":
116 121
117 122 if nFFTPoints == None:
118 123 raise ValueError, "This SpectraProc.run() need nFFTPoints input variable"
119 124
120 125 if nProfiles == None:
121 126 nProfiles = nFFTPoints
122 127
123 128 if ippFactor == None:
124 129 ippFactor = 1
125 130
126 131 self.dataOut.ippFactor = ippFactor
127 132
128 133 self.dataOut.nFFTPoints = nFFTPoints
129 134 self.dataOut.pairsList = pairsList
130 135
131 136 if self.buffer is None:
132 137 self.buffer = numpy.zeros( (self.dataIn.nChannels,
133 138 nProfiles,
134 139 self.dataIn.nHeights),
135 140 dtype='complex')
136 141
137 142 if self.dataIn.flagDataAsBlock:
138 143 #data dimension: [nChannels, nProfiles, nSamples]
139 144 nVoltProfiles = self.dataIn.data.shape[1]
140 145 # nVoltProfiles = self.dataIn.nProfiles
141 146
142 147 if nVoltProfiles == nProfiles:
143 148 self.buffer = self.dataIn.data.copy()
144 149 self.profIndex = nVoltProfiles
145 150
146 151 elif nVoltProfiles < nProfiles:
147 152
148 153 if self.profIndex == 0:
149 154 self.id_min = 0
150 155 self.id_max = nVoltProfiles
151 156
152 157 self.buffer[:,self.id_min:self.id_max,:] = self.dataIn.data
153 158 self.profIndex += nVoltProfiles
154 159 self.id_min += nVoltProfiles
155 160 self.id_max += nVoltProfiles
156 161 else:
157 162 raise ValueError, "The type object %s has %d profiles, it should just has %d profiles"%(self.dataIn.type,self.dataIn.data.shape[1],nProfiles)
158 163 self.dataOut.flagNoData = True
159 164 return 0
160 165 else:
161 166 self.buffer[:,self.profIndex,:] = self.dataIn.data.copy()
162 167 self.profIndex += 1
163 168
164 169 if self.firstdatatime == None:
165 170 self.firstdatatime = self.dataIn.utctime
166 171
167 172 if self.profIndex == nProfiles:
168 173 self.__updateSpecFromVoltage()
169 174 self.__getFft()
170 175
171 176 self.dataOut.flagNoData = False
172 177 self.firstdatatime = None
173 178 self.profIndex = 0
174 179
175 180 return True
176 181
177 182 raise ValueError, "The type of input object '%s' is not valid"%(self.dataIn.type)
178 183
179 184 def __selectPairs(self, pairsList):
180 185
181 if channelList == None:
186 if not pairsList:
182 187 return
183 188
184 pairsIndexListSelected = []
185
186 for thisPair in pairsList:
189 pairs = []
190 pairsIndex = []
187 191
188 if thisPair not in self.dataOut.pairsList:
192 for pair in pairsList:
193 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
189 194 continue
190
191 pairIndex = self.dataOut.pairsList.index(thisPair)
192
193 pairsIndexListSelected.append(pairIndex)
194
195 if not pairsIndexListSelected:
196 self.dataOut.data_cspc = None
197 self.dataOut.pairsList = []
198 return
199
200 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
201 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
195 pairs.append(pair)
196 pairsIndex.append(pairs.index(pair))
197
198 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
199 self.dataOut.pairsList = pairs
200 self.dataOut.pairsIndexList = pairsIndex
202 201
203 202 return
204 203
205 204 def __selectPairsByChannel(self, channelList=None):
206 205
207 206 if channelList == None:
208 207 return
209 208
210 209 pairsIndexListSelected = []
211 210 for pairIndex in self.dataOut.pairsIndexList:
212 211 #First pair
213 212 if self.dataOut.pairsList[pairIndex][0] not in channelList:
214 213 continue
215 214 #Second pair
216 215 if self.dataOut.pairsList[pairIndex][1] not in channelList:
217 216 continue
218 217
219 218 pairsIndexListSelected.append(pairIndex)
220 219
221 220 if not pairsIndexListSelected:
222 221 self.dataOut.data_cspc = None
223 222 self.dataOut.pairsList = []
224 223 return
225 224
226 225 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
227 226 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
228 227
229 228 return
230 229
231 230 def selectChannels(self, channelList):
232 231
233 232 channelIndexList = []
234 233
235 234 for channel in channelList:
236 235 if channel not in self.dataOut.channelList:
237 236 raise ValueError, "Error selecting channels, Channel %d is not valid.\nAvailable channels = %s" %(channel, str(self.dataOut.channelList))
238 237
239 238 index = self.dataOut.channelList.index(channel)
240 239 channelIndexList.append(index)
241 240
242 241 self.selectChannelsByIndex(channelIndexList)
243 242
244 243 def selectChannelsByIndex(self, channelIndexList):
245 244 """
246 245 Selecciona un bloque de datos en base a canales segun el channelIndexList
247 246
248 247 Input:
249 248 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
250 249
251 250 Affected:
252 251 self.dataOut.data_spc
253 252 self.dataOut.channelIndexList
254 253 self.dataOut.nChannels
255 254
256 255 Return:
257 256 None
258 257 """
259 258
260 259 for channelIndex in channelIndexList:
261 260 if channelIndex not in self.dataOut.channelIndexList:
262 261 raise ValueError, "Error selecting channels: The value %d in channelIndexList is not valid.\nAvailable channel indexes = " %(channelIndex, self.dataOut.channelIndexList)
263 262
264 263 # nChannels = len(channelIndexList)
265 264
266 265 data_spc = self.dataOut.data_spc[channelIndexList,:]
267 266 data_dc = self.dataOut.data_dc[channelIndexList,:]
268 267
269 268 self.dataOut.data_spc = data_spc
270 269 self.dataOut.data_dc = data_dc
271 270
272 271 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
273 272 # self.dataOut.nChannels = nChannels
274 273
275 274 self.__selectPairsByChannel(self.dataOut.channelList)
276 275
277 276 return 1
278 277
279 278 def selectHeights(self, minHei, maxHei):
280 279 """
281 280 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
282 281 minHei <= height <= maxHei
283 282
284 283 Input:
285 284 minHei : valor minimo de altura a considerar
286 285 maxHei : valor maximo de altura a considerar
287 286
288 287 Affected:
289 288 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
290 289
291 290 Return:
292 291 1 si el metodo se ejecuto con exito caso contrario devuelve 0
293 292 """
294 293
295 294 if (minHei > maxHei):
296 295 raise ValueError, "Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei)
297 296
298 297 if (minHei < self.dataOut.heightList[0]):
299 298 minHei = self.dataOut.heightList[0]
300 299
301 300 if (maxHei > self.dataOut.heightList[-1]):
302 301 maxHei = self.dataOut.heightList[-1]
303 302
304 303 minIndex = 0
305 304 maxIndex = 0
306 305 heights = self.dataOut.heightList
307 306
308 307 inda = numpy.where(heights >= minHei)
309 308 indb = numpy.where(heights <= maxHei)
310 309
311 310 try:
312 311 minIndex = inda[0][0]
313 312 except:
314 313 minIndex = 0
315 314
316 315 try:
317 316 maxIndex = indb[0][-1]
318 317 except:
319 318 maxIndex = len(heights)
320 319
321 320 self.selectHeightsByIndex(minIndex, maxIndex)
322 321
323 322 return 1
324 323
325 324 def getBeaconSignal(self, tauindex = 0, channelindex = 0, hei_ref=None):
326 325 newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
327 326
328 327 if hei_ref != None:
329 328 newheis = numpy.where(self.dataOut.heightList>hei_ref)
330 329
331 330 minIndex = min(newheis[0])
332 331 maxIndex = max(newheis[0])
333 332 data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1]
334 333 heightList = self.dataOut.heightList[minIndex:maxIndex+1]
335 334
336 335 # determina indices
337 336 nheis = int(self.dataOut.radarControllerHeaderObj.txB/(self.dataOut.heightList[1]-self.dataOut.heightList[0]))
338 337 avg_dB = 10*numpy.log10(numpy.sum(data_spc[channelindex,:,:],axis=0))
339 338 beacon_dB = numpy.sort(avg_dB)[-nheis:]
340 339 beacon_heiIndexList = []
341 340 for val in avg_dB.tolist():
342 341 if val >= beacon_dB[0]:
343 342 beacon_heiIndexList.append(avg_dB.tolist().index(val))
344 343
345 344 #data_spc = data_spc[:,:,beacon_heiIndexList]
346 345 data_cspc = None
347 346 if self.dataOut.data_cspc is not None:
348 347 data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1]
349 348 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
350 349
351 350 data_dc = None
352 351 if self.dataOut.data_dc is not None:
353 352 data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1]
354 353 #data_dc = data_dc[:,beacon_heiIndexList]
355 354
356 355 self.dataOut.data_spc = data_spc
357 356 self.dataOut.data_cspc = data_cspc
358 357 self.dataOut.data_dc = data_dc
359 358 self.dataOut.heightList = heightList
360 359 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
361 360
362 361 return 1
363 362
364 363
365 364 def selectHeightsByIndex(self, minIndex, maxIndex):
366 365 """
367 366 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
368 367 minIndex <= index <= maxIndex
369 368
370 369 Input:
371 370 minIndex : valor de indice minimo de altura a considerar
372 371 maxIndex : valor de indice maximo de altura a considerar
373 372
374 373 Affected:
375 374 self.dataOut.data_spc
376 375 self.dataOut.data_cspc
377 376 self.dataOut.data_dc
378 377 self.dataOut.heightList
379 378
380 379 Return:
381 380 1 si el metodo se ejecuto con exito caso contrario devuelve 0
382 381 """
383 382
384 383 if (minIndex < 0) or (minIndex > maxIndex):
385 384 raise ValueError, "Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex)
386 385
387 386 if (maxIndex >= self.dataOut.nHeights):
388 387 maxIndex = self.dataOut.nHeights-1
389 388
390 389 #Spectra
391 390 data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1]
392 391
393 392 data_cspc = None
394 393 if self.dataOut.data_cspc is not None:
395 394 data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1]
396 395
397 396 data_dc = None
398 397 if self.dataOut.data_dc is not None:
399 398 data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1]
400 399
401 400 self.dataOut.data_spc = data_spc
402 401 self.dataOut.data_cspc = data_cspc
403 402 self.dataOut.data_dc = data_dc
404 403
405 404 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex+1]
406 405
407 406 return 1
408 407
409 408 def removeDC(self, mode = 2):
410 409 jspectra = self.dataOut.data_spc
411 410 jcspectra = self.dataOut.data_cspc
412 411
413 412
414 413 num_chan = jspectra.shape[0]
415 414 num_hei = jspectra.shape[2]
416 415
417 416 if jcspectra is not None:
418 417 jcspectraExist = True
419 418 num_pairs = jcspectra.shape[0]
420 419 else: jcspectraExist = False
421 420
422 421 freq_dc = jspectra.shape[1]/2
423 422 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
424 423
425 424 if ind_vel[0]<0:
426 425 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
427 426
428 427 if mode == 1:
429 428 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
430 429
431 430 if jcspectraExist:
432 431 jcspectra[:,freq_dc,:] = (jcspectra[:,ind_vel[1],:] + jcspectra[:,ind_vel[2],:])/2
433 432
434 433 if mode == 2:
435 434
436 435 vel = numpy.array([-2,-1,1,2])
437 436 xx = numpy.zeros([4,4])
438 437
439 438 for fil in range(4):
440 439 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
441 440
442 441 xx_inv = numpy.linalg.inv(xx)
443 442 xx_aux = xx_inv[0,:]
444 443
445 444 for ich in range(num_chan):
446 445 yy = jspectra[ich,ind_vel,:]
447 446 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
448 447
449 448 junkid = jspectra[ich,freq_dc,:]<=0
450 449 cjunkid = sum(junkid)
451 450
452 451 if cjunkid.any():
453 452 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
454 453
455 454 if jcspectraExist:
456 455 for ip in range(num_pairs):
457 456 yy = jcspectra[ip,ind_vel,:]
458 457 jcspectra[ip,freq_dc,:] = numpy.dot(xx_aux,yy)
459 458
460 459
461 460 self.dataOut.data_spc = jspectra
462 461 self.dataOut.data_cspc = jcspectra
463 462
464 463 return 1
465 464
466 465 def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None):
467 466
468 467 jspectra = self.dataOut.data_spc
469 468 jcspectra = self.dataOut.data_cspc
470 469 jnoise = self.dataOut.getNoise()
471 470 num_incoh = self.dataOut.nIncohInt
472 471
473 472 num_channel = jspectra.shape[0]
474 473 num_prof = jspectra.shape[1]
475 474 num_hei = jspectra.shape[2]
476 475
477 476 #hei_interf
478 477 if hei_interf is None:
479 478 count_hei = num_hei/2 #Como es entero no importa
480 479 hei_interf = numpy.asmatrix(range(count_hei)) + num_hei - count_hei
481 480 hei_interf = numpy.asarray(hei_interf)[0]
482 481 #nhei_interf
483 482 if (nhei_interf == None):
484 483 nhei_interf = 5
485 484 if (nhei_interf < 1):
486 485 nhei_interf = 1
487 486 if (nhei_interf > count_hei):
488 487 nhei_interf = count_hei
489 488 if (offhei_interf == None):
490 489 offhei_interf = 0
491 490
492 491 ind_hei = range(num_hei)
493 492 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
494 493 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
495 494 mask_prof = numpy.asarray(range(num_prof))
496 495 num_mask_prof = mask_prof.size
497 496 comp_mask_prof = [0, num_prof/2]
498 497
499 498
500 499 #noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
501 500 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
502 501 jnoise = numpy.nan
503 502 noise_exist = jnoise[0] < numpy.Inf
504 503
505 504 #Subrutina de Remocion de la Interferencia
506 505 for ich in range(num_channel):
507 506 #Se ordena los espectros segun su potencia (menor a mayor)
508 507 power = jspectra[ich,mask_prof,:]
509 508 power = power[:,hei_interf]
510 509 power = power.sum(axis = 0)
511 510 psort = power.ravel().argsort()
512 511
513 512 #Se estima la interferencia promedio en los Espectros de Potencia empleando
514 513 junkspc_interf = jspectra[ich,:,hei_interf[psort[range(offhei_interf, nhei_interf + offhei_interf)]]]
515 514
516 515 if noise_exist:
517 516 # tmp_noise = jnoise[ich] / num_prof
518 517 tmp_noise = jnoise[ich]
519 518 junkspc_interf = junkspc_interf - tmp_noise
520 519 #junkspc_interf[:,comp_mask_prof] = 0
521 520
522 521 jspc_interf = junkspc_interf.sum(axis = 0) / nhei_interf
523 522 jspc_interf = jspc_interf.transpose()
524 523 #Calculando el espectro de interferencia promedio
525 524 noiseid = numpy.where(jspc_interf <= tmp_noise/ numpy.sqrt(num_incoh))
526 525 noiseid = noiseid[0]
527 526 cnoiseid = noiseid.size
528 527 interfid = numpy.where(jspc_interf > tmp_noise/ numpy.sqrt(num_incoh))
529 528 interfid = interfid[0]
530 529 cinterfid = interfid.size
531 530
532 531 if (cnoiseid > 0): jspc_interf[noiseid] = 0
533 532
534 533 #Expandiendo los perfiles a limpiar
535 534 if (cinterfid > 0):
536 535 new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof)%num_prof
537 536 new_interfid = numpy.asarray(new_interfid)
538 537 new_interfid = {x for x in new_interfid}
539 538 new_interfid = numpy.array(list(new_interfid))
540 539 new_cinterfid = new_interfid.size
541 540 else: new_cinterfid = 0
542 541
543 542 for ip in range(new_cinterfid):
544 543 ind = junkspc_interf[:,new_interfid[ip]].ravel().argsort()
545 544 jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf/2],new_interfid[ip]]
546 545
547 546
548 547 jspectra[ich,:,ind_hei] = jspectra[ich,:,ind_hei] - jspc_interf #Corregir indices
549 548
550 549 #Removiendo la interferencia del punto de mayor interferencia
551 550 ListAux = jspc_interf[mask_prof].tolist()
552 551 maxid = ListAux.index(max(ListAux))
553 552
554 553
555 554 if cinterfid > 0:
556 555 for ip in range(cinterfid*(interf == 2) - 1):
557 556 ind = (jspectra[ich,interfid[ip],:] < tmp_noise*(1 + 1/numpy.sqrt(num_incoh))).nonzero()
558 557 cind = len(ind)
559 558
560 559 if (cind > 0):
561 560 jspectra[ich,interfid[ip],ind] = tmp_noise*(1 + (numpy.random.uniform(cind) - 0.5)/numpy.sqrt(num_incoh))
562 561
563 562 ind = numpy.array([-2,-1,1,2])
564 563 xx = numpy.zeros([4,4])
565 564
566 565 for id1 in range(4):
567 566 xx[:,id1] = ind[id1]**numpy.asarray(range(4))
568 567
569 568 xx_inv = numpy.linalg.inv(xx)
570 569 xx = xx_inv[:,0]
571 570 ind = (ind + maxid + num_mask_prof)%num_mask_prof
572 571 yy = jspectra[ich,mask_prof[ind],:]
573 572 jspectra[ich,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx)
574 573
575 574
576 575 indAux = (jspectra[ich,:,:] < tmp_noise*(1-1/numpy.sqrt(num_incoh))).nonzero()
577 576 jspectra[ich,indAux[0],indAux[1]] = tmp_noise * (1 - 1/numpy.sqrt(num_incoh))
578 577
579 578 #Remocion de Interferencia en el Cross Spectra
580 579 if jcspectra is None: return jspectra, jcspectra
581 580 num_pairs = jcspectra.size/(num_prof*num_hei)
582 581 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
583 582
584 583 for ip in range(num_pairs):
585 584
586 585 #-------------------------------------------
587 586
588 587 cspower = numpy.abs(jcspectra[ip,mask_prof,:])
589 588 cspower = cspower[:,hei_interf]
590 589 cspower = cspower.sum(axis = 0)
591 590
592 591 cspsort = cspower.ravel().argsort()
593 592 junkcspc_interf = jcspectra[ip,:,hei_interf[cspsort[range(offhei_interf, nhei_interf + offhei_interf)]]]
594 593 junkcspc_interf = junkcspc_interf.transpose()
595 594 jcspc_interf = junkcspc_interf.sum(axis = 1)/nhei_interf
596 595
597 596 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
598 597
599 598 median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:]))
600 599 median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:]))
601 600 junkcspc_interf[comp_mask_prof,:] = numpy.complex(median_real, median_imag)
602 601
603 602 for iprof in range(num_prof):
604 603 ind = numpy.abs(junkcspc_interf[iprof,:]).ravel().argsort()
605 604 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf/2]]
606 605
607 606 #Removiendo la Interferencia
608 607 jcspectra[ip,:,ind_hei] = jcspectra[ip,:,ind_hei] - jcspc_interf
609 608
610 609 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
611 610 maxid = ListAux.index(max(ListAux))
612 611
613 612 ind = numpy.array([-2,-1,1,2])
614 613 xx = numpy.zeros([4,4])
615 614
616 615 for id1 in range(4):
617 616 xx[:,id1] = ind[id1]**numpy.asarray(range(4))
618 617
619 618 xx_inv = numpy.linalg.inv(xx)
620 619 xx = xx_inv[:,0]
621 620
622 621 ind = (ind + maxid + num_mask_prof)%num_mask_prof
623 622 yy = jcspectra[ip,mask_prof[ind],:]
624 623 jcspectra[ip,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx)
625 624
626 625 #Guardar Resultados
627 626 self.dataOut.data_spc = jspectra
628 627 self.dataOut.data_cspc = jcspectra
629 628
630 629 return 1
631 630
632 631 def setRadarFrequency(self, frequency=None):
633 632
634 633 if frequency != None:
635 634 self.dataOut.frequency = frequency
636 635
637 636 return 1
638 637
639 638 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
640 639 #validacion de rango
641 640 if minHei == None:
642 641 minHei = self.dataOut.heightList[0]
643 642
644 643 if maxHei == None:
645 644 maxHei = self.dataOut.heightList[-1]
646 645
647 646 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
648 647 print 'minHei: %.2f is out of the heights range'%(minHei)
649 648 print 'minHei is setting to %.2f'%(self.dataOut.heightList[0])
650 649 minHei = self.dataOut.heightList[0]
651 650
652 651 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
653 652 print 'maxHei: %.2f is out of the heights range'%(maxHei)
654 653 print 'maxHei is setting to %.2f'%(self.dataOut.heightList[-1])
655 654 maxHei = self.dataOut.heightList[-1]
656 655
657 656 # validacion de velocidades
658 657 velrange = self.dataOut.getVelRange(1)
659 658
660 659 if minVel == None:
661 660 minVel = velrange[0]
662 661
663 662 if maxVel == None:
664 663 maxVel = velrange[-1]
665 664
666 665 if (minVel < velrange[0]) or (minVel > maxVel):
667 666 print 'minVel: %.2f is out of the velocity range'%(minVel)
668 667 print 'minVel is setting to %.2f'%(velrange[0])
669 668 minVel = velrange[0]
670 669
671 670 if (maxVel > velrange[-1]) or (maxVel < minVel):
672 671 print 'maxVel: %.2f is out of the velocity range'%(maxVel)
673 672 print 'maxVel is setting to %.2f'%(velrange[-1])
674 673 maxVel = velrange[-1]
675 674
676 675 # seleccion de indices para rango
677 676 minIndex = 0
678 677 maxIndex = 0
679 678 heights = self.dataOut.heightList
680 679
681 680 inda = numpy.where(heights >= minHei)
682 681 indb = numpy.where(heights <= maxHei)
683 682
684 683 try:
685 684 minIndex = inda[0][0]
686 685 except:
687 686 minIndex = 0
688 687
689 688 try:
690 689 maxIndex = indb[0][-1]
691 690 except:
692 691 maxIndex = len(heights)
693 692
694 693 if (minIndex < 0) or (minIndex > maxIndex):
695 694 raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex)
696 695
697 696 if (maxIndex >= self.dataOut.nHeights):
698 697 maxIndex = self.dataOut.nHeights-1
699 698
700 699 # seleccion de indices para velocidades
701 700 indminvel = numpy.where(velrange >= minVel)
702 701 indmaxvel = numpy.where(velrange <= maxVel)
703 702 try:
704 703 minIndexVel = indminvel[0][0]
705 704 except:
706 705 minIndexVel = 0
707 706
708 707 try:
709 708 maxIndexVel = indmaxvel[0][-1]
710 709 except:
711 710 maxIndexVel = len(velrange)
712 711
713 712 #seleccion del espectro
714 713 data_spc = self.dataOut.data_spc[:,minIndexVel:maxIndexVel+1,minIndex:maxIndex+1]
715 714 #estimacion de ruido
716 715 noise = numpy.zeros(self.dataOut.nChannels)
717 716
718 717 for channel in range(self.dataOut.nChannels):
719 718 daux = data_spc[channel,:,:]
720 719 noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt)
721 720
722 721 self.dataOut.noise_estimation = noise.copy()
723 722
724 723 return 1
725 724
726 725 class IncohInt(Operation):
727 726
728 727
729 728 __profIndex = 0
730 729 __withOverapping = False
731 730
732 731 __byTime = False
733 732 __initime = None
734 733 __lastdatatime = None
735 734 __integrationtime = None
736 735
737 736 __buffer_spc = None
738 737 __buffer_cspc = None
739 738 __buffer_dc = None
740 739
741 740 __dataReady = False
742 741
743 742 __timeInterval = None
744 743
745 744 n = None
746 745
747 746
748 747
749 748 def __init__(self, **kwargs):
750 749
751 750 Operation.__init__(self, **kwargs)
752 751 # self.isConfig = False
753 752
754 753 def setup(self, n=None, timeInterval=None, overlapping=False):
755 754 """
756 755 Set the parameters of the integration class.
757 756
758 757 Inputs:
759 758
760 759 n : Number of coherent integrations
761 760 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
762 761 overlapping :
763 762
764 763 """
765 764
766 765 self.__initime = None
767 766 self.__lastdatatime = 0
768 767
769 768 self.__buffer_spc = 0
770 769 self.__buffer_cspc = 0
771 770 self.__buffer_dc = 0
772 771
773 772 self.__profIndex = 0
774 773 self.__dataReady = False
775 774 self.__byTime = False
776 775
777 776 if n is None and timeInterval is None:
778 777 raise ValueError, "n or timeInterval should be specified ..."
779 778
780 779 if n is not None:
781 780 self.n = int(n)
782 781 else:
783 782 self.__integrationtime = int(timeInterval) #if (type(timeInterval)!=integer) -> change this line
784 783 self.n = None
785 784 self.__byTime = True
786 785
787 786 def putData(self, data_spc, data_cspc, data_dc):
788 787
789 788 """
790 789 Add a profile to the __buffer_spc and increase in one the __profileIndex
791 790
792 791 """
793 792
794 793 self.__buffer_spc += data_spc
795 794
796 795 if data_cspc is None:
797 796 self.__buffer_cspc = None
798 797 else:
799 798 self.__buffer_cspc += data_cspc
800 799
801 800 if data_dc is None:
802 801 self.__buffer_dc = None
803 802 else:
804 803 self.__buffer_dc += data_dc
805 804
806 805 self.__profIndex += 1
807 806
808 807 return
809 808
810 809 def pushData(self):
811 810 """
812 811 Return the sum of the last profiles and the profiles used in the sum.
813 812
814 813 Affected:
815 814
816 815 self.__profileIndex
817 816
818 817 """
819 818
820 819 data_spc = self.__buffer_spc
821 820 data_cspc = self.__buffer_cspc
822 821 data_dc = self.__buffer_dc
823 822 n = self.__profIndex
824 823
825 824 self.__buffer_spc = 0
826 825 self.__buffer_cspc = 0
827 826 self.__buffer_dc = 0
828 827 self.__profIndex = 0
829 828
830 829 return data_spc, data_cspc, data_dc, n
831 830
832 831 def byProfiles(self, *args):
833 832
834 833 self.__dataReady = False
835 834 avgdata_spc = None
836 835 avgdata_cspc = None
837 836 avgdata_dc = None
838 837
839 838 self.putData(*args)
840 839
841 840 if self.__profIndex == self.n:
842 841
843 842 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
844 843 self.n = n
845 844 self.__dataReady = True
846 845
847 846 return avgdata_spc, avgdata_cspc, avgdata_dc
848 847
849 848 def byTime(self, datatime, *args):
850 849
851 850 self.__dataReady = False
852 851 avgdata_spc = None
853 852 avgdata_cspc = None
854 853 avgdata_dc = None
855 854
856 855 self.putData(*args)
857 856
858 857 if (datatime - self.__initime) >= self.__integrationtime:
859 858 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
860 859 self.n = n
861 860 self.__dataReady = True
862 861
863 862 return avgdata_spc, avgdata_cspc, avgdata_dc
864 863
865 864 def integrate(self, datatime, *args):
866 865
867 866 if self.__profIndex == 0:
868 867 self.__initime = datatime
869 868
870 869 if self.__byTime:
871 870 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(datatime, *args)
872 871 else:
873 872 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
874 873
875 874 if not self.__dataReady:
876 875 return None, None, None, None
877 876
878 877 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
879 878
880 879 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
881 880
882 881 if n==1:
883 882 return
884 883
885 884 dataOut.flagNoData = True
886 885
887 886 if not self.isConfig:
888 887 self.setup(n, timeInterval, overlapping)
889 888 self.isConfig = True
890 889
891 890 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
892 891 dataOut.data_spc,
893 892 dataOut.data_cspc,
894 893 dataOut.data_dc)
895 894
896 895 if self.__dataReady:
897 896
898 897 dataOut.data_spc = avgdata_spc
899 898 dataOut.data_cspc = avgdata_cspc
900 899 dataOut.data_dc = avgdata_dc
901 900
902 901 dataOut.nIncohInt *= self.n
903 902 dataOut.utctime = avgdatatime
904 903 dataOut.flagNoData = False
@@ -1,501 +1,604
1 1 '''
2 2 @author: Juan C. Espinoza
3 3 '''
4 4
5 5 import time
6 6 import json
7 7 import numpy
8 8 import paho.mqtt.client as mqtt
9 9 import zmq
10 10 import datetime
11 11 from zmq.utils.monitor import recv_monitor_message
12 12 from functools import wraps
13 13 from threading import Thread
14 14 from multiprocessing import Process
15 15
16 16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 17 from schainpy.model.data.jrodata import JROData
18 from schainpy.utils import log
18 19
19 20 MAXNUMX = 100
20 21 MAXNUMY = 100
21 22
22 23 class PrettyFloat(float):
23 24 def __repr__(self):
24 25 return '%.2f' % self
25 26
26 27 def roundFloats(obj):
27 28 if isinstance(obj, list):
28 29 return map(roundFloats, obj)
29 30 elif isinstance(obj, float):
30 31 return round(obj, 2)
31 32
32 33 def decimate(z, MAXNUMY):
33 # dx = int(len(self.x)/self.__MAXNUMX) + 1
34
35 34 dy = int(len(z[0])/MAXNUMY) + 1
36 35
37 36 return z[::, ::dy]
38 37
39 38 class throttle(object):
40 """Decorator that prevents a function from being called more than once every
39 '''
40 Decorator that prevents a function from being called more than once every
41 41 time period.
42 42 To create a function that cannot be called more than once a minute, but
43 43 will sleep until it can be called:
44 44 @throttle(minutes=1)
45 45 def foo():
46 46 pass
47 47
48 48 for i in range(10):
49 49 foo()
50 50 print "This function has run %s times." % i
51 """
51 '''
52 52
53 53 def __init__(self, seconds=0, minutes=0, hours=0):
54 54 self.throttle_period = datetime.timedelta(
55 55 seconds=seconds, minutes=minutes, hours=hours
56 56 )
57 57
58 58 self.time_of_last_call = datetime.datetime.min
59 59
60 60 def __call__(self, fn):
61 61 @wraps(fn)
62 62 def wrapper(*args, **kwargs):
63 63 now = datetime.datetime.now()
64 64 time_since_last_call = now - self.time_of_last_call
65 65 time_left = self.throttle_period - time_since_last_call
66 66
67 67 if time_left > datetime.timedelta(seconds=0):
68 68 return
69 69
70 70 self.time_of_last_call = datetime.datetime.now()
71 71 return fn(*args, **kwargs)
72 72
73 73 return wrapper
74 74
75 class Data(object):
76 '''
77 Object to hold data to be plotted
78 '''
79
80 def __init__(self, plottypes, throttle_value):
81 self.plottypes = plottypes
82 self.throttle = throttle_value
83 self.ended = False
84 self.__times = []
85
86 def __str__(self):
87 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
88 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
89
90 def __len__(self):
91 return len(self.__times)
92
93 def __getitem__(self, key):
94 if key not in self.data:
95 raise KeyError(log.error('Missing key: {}'.format(key)))
96
97 if 'spc' in key:
98 ret = self.data[key]
99 else:
100 ret = numpy.array([self.data[key][x] for x in self.times])
101 if ret.ndim > 1:
102 ret = numpy.swapaxes(ret, 0, 1)
103 return ret
104
105 def setup(self):
106 '''
107 Configure object
108 '''
109
110 self.ended = False
111 self.data = {}
112 self.__times = []
113 self.__heights = []
114 self.__all_heights = set()
115 for plot in self.plottypes:
116 self.data[plot] = {}
117
118 def shape(self, key):
119 '''
120 Get the shape of the one-element data for the given key
121 '''
122
123 if len(self.data[key]):
124 if 'spc' in key:
125 return self.data[key].shape
126 return self.data[key][self.__times[0]].shape
127 return (0,)
128
129 def update(self, dataOut):
130 '''
131 Update data object with new dataOut
132 '''
133
134 tm = dataOut.utctime
135 if tm in self.__times:
136 return
137
138 self.parameters = getattr(dataOut, 'parameters', [])
139 self.pairs = dataOut.pairsList
140 self.channels = dataOut.channelList
141 self.xrange = (dataOut.getFreqRange(1)/1000. , dataOut.getAcfRange(1) , dataOut.getVelRange(1))
142 self.interval = dataOut.getTimeInterval()
143 self.__heights.append(dataOut.heightList)
144 self.__all_heights.update(dataOut.heightList)
145 self.__times.append(tm)
146
147 for plot in self.plottypes:
148 if plot == 'spc':
149 z = dataOut.data_spc/dataOut.normFactor
150 self.data[plot] = 10*numpy.log10(z)
151 if plot == 'cspc':
152 self.data[plot] = dataOut.data_cspc
153 if plot == 'noise':
154 self.data[plot][tm] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
155 if plot == 'rti':
156 self.data[plot][tm] = dataOut.getPower()
157 if plot == 'snr_db':
158 self.data['snr'][tm] = dataOut.data_SNR
159 if plot == 'snr':
160 self.data[plot][tm] = 10*numpy.log10(dataOut.data_SNR)
161 if plot == 'dop':
162 self.data[plot][tm] = 10*numpy.log10(dataOut.data_DOP)
163 if plot == 'mean':
164 self.data[plot][tm] = dataOut.data_MEAN
165 if plot == 'std':
166 self.data[plot][tm] = dataOut.data_STD
167 if plot == 'coh':
168 self.data[plot][tm] = dataOut.getCoherence()
169 if plot == 'phase':
170 self.data[plot][tm] = dataOut.getCoherence(phase=True)
171 if plot == 'output':
172 self.data[plot][tm] = dataOut.data_output
173 if plot == 'param':
174 self.data[plot][tm] = dataOut.data_param
175
176 def normalize_heights(self):
177 '''
178 Ensure same-dimension of the data for different heighList
179 '''
180
181 H = numpy.array(list(self.__all_heights))
182 H.sort()
183 for key in self.data:
184 shape = self.shape(key)[:-1] + H.shape
185 for tm, obj in self.data[key].items():
186 h = self.__heights[self.__times.index(tm)]
187 if H.size == h.size:
188 continue
189 index = numpy.where(numpy.in1d(H, h))[0]
190 dummy = numpy.zeros(shape) + numpy.nan
191 if len(shape) == 2:
192 dummy[:, index] = obj
193 else:
194 dummy[index] = obj
195 self.data[key][tm] = dummy
196
197 self.__heights = [H for tm in self.__times]
198
199 def jsonify(self, decimate=False):
200 '''
201 Convert data to json
202 '''
203
204 ret = {}
205 tm = self.times[-1]
206
207 for key, value in self.data:
208 if key in ('spc', 'cspc'):
209 ret[key] = roundFloats(self.data[key].to_list())
210 else:
211 ret[key] = roundFloats(self.data[key][tm].to_list())
212
213 ret['timestamp'] = tm
214 ret['interval'] = self.interval
215
216 @property
217 def times(self):
218 '''
219 Return the list of times of the current data
220 '''
221
222 ret = numpy.array(self.__times)
223 ret.sort()
224 return ret
225
226 @property
227 def heights(self):
228 '''
229 Return the list of heights of the current data
230 '''
231
232 return numpy.array(self.__heights[-1])
75 233
76 234 class PublishData(Operation):
77 """Clase publish."""
235 '''
236 Operation to send data over zmq.
237 '''
78 238
79 239 def __init__(self, **kwargs):
80 240 """Inicio."""
81 241 Operation.__init__(self, **kwargs)
82 242 self.isConfig = False
83 243 self.client = None
84 244 self.zeromq = None
85 245 self.mqtt = None
86 246
87 247 def on_disconnect(self, client, userdata, rc):
88 248 if rc != 0:
89 print("Unexpected disconnection.")
249 log.warning('Unexpected disconnection.')
90 250 self.connect()
91 251
92 252 def connect(self):
93 print 'trying to connect'
253 log.warning('trying to connect')
94 254 try:
95 255 self.client.connect(
96 256 host=self.host,
97 257 port=self.port,
98 258 keepalive=60*10,
99 259 bind_address='')
100 260 self.client.loop_start()
101 261 # self.client.publish(
102 262 # self.topic + 'SETUP',
103 263 # json.dumps(setup),
104 264 # retain=True
105 265 # )
106 266 except:
107 print "MQTT Conection error."
267 log.error('MQTT Conection error.')
108 268 self.client = False
109 269
110 270 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
111 271 self.counter = 0
112 272 self.topic = kwargs.get('topic', 'schain')
113 273 self.delay = kwargs.get('delay', 0)
114 274 self.plottype = kwargs.get('plottype', 'spectra')
115 275 self.host = kwargs.get('host', "10.10.10.82")
116 276 self.port = kwargs.get('port', 3000)
117 277 self.clientId = clientId
118 278 self.cnt = 0
119 279 self.zeromq = zeromq
120 280 self.mqtt = kwargs.get('plottype', 0)
121 281 self.client = None
122 self.verbose = verbose
123 self.dataOut.firstdata = True
282 self.verbose = verbose
124 283 setup = []
125 284 if mqtt is 1:
126 285 self.client = mqtt.Client(
127 286 client_id=self.clientId + self.topic + 'SCHAIN',
128 287 clean_session=True)
129 288 self.client.on_disconnect = self.on_disconnect
130 289 self.connect()
131 290 for plot in self.plottype:
132 291 setup.append({
133 292 'plot': plot,
134 293 'topic': self.topic + plot,
135 294 'title': getattr(self, plot + '_' + 'title', False),
136 295 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
137 296 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
138 297 'xrange': getattr(self, plot + '_' + 'xrange', False),
139 298 'yrange': getattr(self, plot + '_' + 'yrange', False),
140 299 'zrange': getattr(self, plot + '_' + 'zrange', False),
141 300 })
142 301 if zeromq is 1:
143 302 context = zmq.Context()
144 303 self.zmq_socket = context.socket(zmq.PUSH)
145 304 server = kwargs.get('server', 'zmq.pipe')
146 305
147 306 if 'tcp://' in server:
148 307 address = server
149 308 else:
150 309 address = 'ipc:///tmp/%s' % server
151 310
152 311 self.zmq_socket.connect(address)
153 312 time.sleep(1)
154 313
155 314
156 315 def publish_data(self):
157 316 self.dataOut.finished = False
158 317 if self.mqtt is 1:
159 318 yData = self.dataOut.heightList[:2].tolist()
160 319 if self.plottype == 'spectra':
161 320 data = getattr(self.dataOut, 'data_spc')
162 321 z = data/self.dataOut.normFactor
163 322 zdB = 10*numpy.log10(z)
164 323 xlen, ylen = zdB[0].shape
165 324 dx = int(xlen/MAXNUMX) + 1
166 325 dy = int(ylen/MAXNUMY) + 1
167 326 Z = [0 for i in self.dataOut.channelList]
168 327 for i in self.dataOut.channelList:
169 328 Z[i] = zdB[i][::dx, ::dy].tolist()
170 329 payload = {
171 330 'timestamp': self.dataOut.utctime,
172 331 'data': roundFloats(Z),
173 332 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
174 333 'interval': self.dataOut.getTimeInterval(),
175 334 'type': self.plottype,
176 335 'yData': yData
177 336 }
178 # print payload
179 337
180 338 elif self.plottype in ('rti', 'power'):
181 339 data = getattr(self.dataOut, 'data_spc')
182 340 z = data/self.dataOut.normFactor
183 341 avg = numpy.average(z, axis=1)
184 342 avgdB = 10*numpy.log10(avg)
185 343 xlen, ylen = z[0].shape
186 344 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
187 345 AVG = [0 for i in self.dataOut.channelList]
188 346 for i in self.dataOut.channelList:
189 347 AVG[i] = avgdB[i][::dy].tolist()
190 348 payload = {
191 349 'timestamp': self.dataOut.utctime,
192 350 'data': roundFloats(AVG),
193 351 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
194 352 'interval': self.dataOut.getTimeInterval(),
195 353 'type': self.plottype,
196 354 'yData': yData
197 355 }
198 356 elif self.plottype == 'noise':
199 357 noise = self.dataOut.getNoise()/self.dataOut.normFactor
200 358 noisedB = 10*numpy.log10(noise)
201 359 payload = {
202 360 'timestamp': self.dataOut.utctime,
203 361 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
204 362 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
205 363 'interval': self.dataOut.getTimeInterval(),
206 364 'type': self.plottype,
207 365 'yData': yData
208 366 }
209 367 elif self.plottype == 'snr':
210 368 data = getattr(self.dataOut, 'data_SNR')
211 369 avgdB = 10*numpy.log10(data)
212 370
213 371 ylen = data[0].size
214 372 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
215 373 AVG = [0 for i in self.dataOut.channelList]
216 374 for i in self.dataOut.channelList:
217 375 AVG[i] = avgdB[i][::dy].tolist()
218 376 payload = {
219 377 'timestamp': self.dataOut.utctime,
220 378 'data': roundFloats(AVG),
221 379 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
222 380 'type': self.plottype,
223 381 'yData': yData
224 382 }
225 383 else:
226 384 print "Tipo de grafico invalido"
227 385 payload = {
228 386 'data': 'None',
229 387 'timestamp': 'None',
230 388 'type': None
231 389 }
232 # print 'Publishing data to {}'.format(self.host)
390
233 391 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
234 392
235 393 if self.zeromq is 1:
236 394 if self.verbose:
237 print '[Sending] {} - {}'.format(self.dataOut.type, self.dataOut.datatime)
395 log.log(
396 '{} - {}'.format(self.dataOut.type, self.dataOut.datatime),
397 'Sending'
398 )
238 399 self.zmq_socket.send_pyobj(self.dataOut)
239 self.dataOut.firstdata = False
240
241 400
242 401 def run(self, dataOut, **kwargs):
243 402 self.dataOut = dataOut
244 403 if not self.isConfig:
245 404 self.setup(**kwargs)
246 405 self.isConfig = True
247 406
248 407 self.publish_data()
249 408 time.sleep(self.delay)
250 409
251 410 def close(self):
252 411 if self.zeromq is 1:
253 412 self.dataOut.finished = True
254 413 self.zmq_socket.send_pyobj(self.dataOut)
414 time.sleep(0.1)
255 415 self.zmq_socket.close()
256 416 if self.client:
257 417 self.client.loop_stop()
258 418 self.client.disconnect()
259 419
260 420
261 421 class ReceiverData(ProcessingUnit):
262 422
263 423 def __init__(self, **kwargs):
264 424
265 425 ProcessingUnit.__init__(self, **kwargs)
266 426
267 427 self.isConfig = False
268 428 server = kwargs.get('server', 'zmq.pipe')
269 429 if 'tcp://' in server:
270 430 address = server
271 431 else:
272 432 address = 'ipc:///tmp/%s' % server
273 433
274 434 self.address = address
275 435 self.dataOut = JROData()
276 436
277 437 def setup(self):
278 438
279 439 self.context = zmq.Context()
280 440 self.receiver = self.context.socket(zmq.PULL)
281 441 self.receiver.bind(self.address)
282 442 time.sleep(0.5)
283 print '[Starting] ReceiverData from {}'.format(self.address)
443 log.success('ReceiverData from {}'.format(self.address))
284 444
285 445
286 446 def run(self):
287 447
288 448 if not self.isConfig:
289 449 self.setup()
290 450 self.isConfig = True
291 451
292 452 self.dataOut = self.receiver.recv_pyobj()
293 print '[Receiving] {} - {}'.format(self.dataOut.type,
294 self.dataOut.datatime.ctime())
453 log.log('{} - {}'.format(self.dataOut.type,
454 self.dataOut.datatime.ctime(),),
455 'Receiving')
295 456
296 457
297 458 class PlotterReceiver(ProcessingUnit, Process):
298 459
299 460 throttle_value = 5
300 461
301 462 def __init__(self, **kwargs):
302 463
303 464 ProcessingUnit.__init__(self, **kwargs)
304 465 Process.__init__(self)
305 466 self.mp = False
306 467 self.isConfig = False
307 468 self.isWebConfig = False
308 self.plottypes = []
309 469 self.connections = 0
310 470 server = kwargs.get('server', 'zmq.pipe')
311 471 plot_server = kwargs.get('plot_server', 'zmq.web')
312 472 if 'tcp://' in server:
313 473 address = server
314 474 else:
315 475 address = 'ipc:///tmp/%s' % server
316 476
317 477 if 'tcp://' in plot_server:
318 478 plot_address = plot_server
319 479 else:
320 480 plot_address = 'ipc:///tmp/%s' % plot_server
321 481
322 482 self.address = address
323 483 self.plot_address = plot_address
324 484 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
325 485 self.realtime = kwargs.get('realtime', False)
326 486 self.throttle_value = kwargs.get('throttle', 5)
327 487 self.sendData = self.initThrottle(self.throttle_value)
488 self.dates = []
328 489 self.setup()
329 490
330 491 def setup(self):
331 492
332 self.data = {}
333 self.data['times'] = []
334 for plottype in self.plottypes:
335 self.data[plottype] = {}
336 self.data['noise'] = {}
337 self.data['throttle'] = self.throttle_value
338 self.data['ENDED'] = False
339 self.isConfig = True
340 self.data_web = {}
493 self.data = Data(self.plottypes, self.throttle_value)
494 self.isConfig = True
341 495
342 496 def event_monitor(self, monitor):
343 497
344 498 events = {}
345 499
346 500 for name in dir(zmq):
347 501 if name.startswith('EVENT_'):
348 502 value = getattr(zmq, name)
349 503 events[value] = name
350 504
351 505 while monitor.poll():
352 506 evt = recv_monitor_message(monitor)
353 507 if evt['event'] == 32:
354 508 self.connections += 1
355 509 if evt['event'] == 512:
356 510 pass
357 if self.connections == 0 and self.started is True:
358 self.ended = True
359 511
360 512 evt.update({'description': events[evt['event']]})
361 513
362 514 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
363 515 break
364 516 monitor.close()
365 print("event monitor thread done!")
517 print('event monitor thread done!')
366 518
367 519 def initThrottle(self, throttle_value):
368 520
369 521 @throttle(seconds=throttle_value)
370 522 def sendDataThrottled(fn_sender, data):
371 523 fn_sender(data)
372 524
373 525 return sendDataThrottled
374 526
375
376 527 def send(self, data):
377 # print '[sending] data=%s size=%s' % (data.keys(), len(data['times']))
528 log.success('Sending {}'.format(data), self.name)
378 529 self.sender.send_pyobj(data)
379 530
380
381 def update(self):
382 t = self.dataOut.utctime
383
384 if t in self.data['times']:
385 return
386
387 self.data['times'].append(t)
388 self.data['dataOut'] = self.dataOut
389
390 for plottype in self.plottypes:
391 if plottype == 'spc':
392 z = self.dataOut.data_spc/self.dataOut.normFactor
393 self.data[plottype] = 10*numpy.log10(z)
394 self.data['noise'][t] = 10*numpy.log10(self.dataOut.getNoise()/self.dataOut.normFactor)
395 if plottype == 'cspc':
396 jcoherence = self.dataOut.data_cspc/numpy.sqrt(self.dataOut.data_spc*self.dataOut.data_spc)
397 self.data['cspc_coh'] = numpy.abs(jcoherence)
398 self.data['cspc_phase'] = numpy.arctan2(jcoherence.imag, jcoherence.real)*180/numpy.pi
399 if plottype == 'rti':
400 self.data[plottype][t] = self.dataOut.getPower()
401 if plottype == 'snr':
402 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_SNR)
403 if plottype == 'dop':
404 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_DOP)
405 if plottype == 'mean':
406 self.data[plottype][t] = self.dataOut.data_MEAN
407 if plottype == 'std':
408 self.data[plottype][t] = self.dataOut.data_STD
409 if plottype == 'coh':
410 self.data[plottype][t] = self.dataOut.getCoherence()
411 if plottype == 'phase':
412 self.data[plottype][t] = self.dataOut.getCoherence(phase=True)
413 if plottype == 'output':
414 self.data[plottype][t] = self.dataOut.data_output
415 if plottype == 'param':
416 self.data[plottype][t] = self.dataOut.data_param
417 if self.realtime:
418 self.data_web['timestamp'] = t
419 if plottype == 'spc':
420 self.data_web[plottype] = roundFloats(decimate(self.data[plottype]).tolist())
421 elif plottype == 'cspc':
422 self.data_web['cspc_coh'] = roundFloats(decimate(self.data['cspc_coh']).tolist())
423 self.data_web['cspc_phase'] = roundFloats(decimate(self.data['cspc_phase']).tolist())
424 elif plottype == 'noise':
425 self.data_web['noise'] = roundFloats(self.data['noise'][t].tolist())
426 else:
427 self.data_web[plottype] = roundFloats(decimate(self.data[plottype][t]).tolist())
428 self.data_web['interval'] = self.dataOut.getTimeInterval()
429 self.data_web['type'] = plottype
430
431 531 def run(self):
432 532
433 print '[Starting] {} from {}'.format(self.name, self.address)
533 log.success(
534 'Starting from {}'.format(self.address),
535 self.name
536 )
434 537
435 538 self.context = zmq.Context()
436 539 self.receiver = self.context.socket(zmq.PULL)
437 540 self.receiver.bind(self.address)
438 541 monitor = self.receiver.get_monitor_socket()
439 542 self.sender = self.context.socket(zmq.PUB)
440 543 if self.realtime:
441 544 self.sender_web = self.context.socket(zmq.PUB)
442 545 self.sender_web.connect(self.plot_address)
443 546 time.sleep(1)
444 547
445 548 if 'server' in self.kwargs:
446 549 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
447 550 else:
448 551 self.sender.bind("ipc:///tmp/zmq.plots")
449 552
450 time.sleep(3)
553 time.sleep(2)
451 554
452 555 t = Thread(target=self.event_monitor, args=(monitor,))
453 556 t.start()
454 557
455 558 while True:
456 self.dataOut = self.receiver.recv_pyobj()
457 # print '[Receiving] {} - {}'.format(self.dataOut.type,
458 # self.dataOut.datatime.ctime())
459
460 self.update()
559 dataOut = self.receiver.recv_pyobj()
560 dt = datetime.datetime.fromtimestamp(dataOut.utctime).date()
561 sended = False
562 if dt not in self.dates:
563 if self.data:
564 self.data.ended = True
565 self.send(self.data)
566 sended = True
567 self.data.setup()
568 self.dates.append(dt)
461 569
462 if self.dataOut.firstdata is True:
463 self.data['STARTED'] = True
570 self.data.update(dataOut)
464 571
465 if self.dataOut.finished is True:
466 self.send(self.data)
572 if dataOut.finished is True:
467 573 self.connections -= 1
468 if self.connections == 0 and self.started:
469 self.ended = True
470 self.data['ENDED'] = True
574 if self.connections == 0 and dt in self.dates:
575 self.data.ended = True
471 576 self.send(self.data)
472 self.setup()
473 self.started = False
577 self.data.setup()
474 578 else:
475 579 if self.realtime:
476 580 self.send(self.data)
477 self.sender_web.send_string(json.dumps(self.data_web))
581 # self.sender_web.send_string(self.data.jsonify())
478 582 else:
479 self.sendData(self.send, self.data)
480 self.started = True
583 if not sended:
584 self.sendData(self.send, self.data)
481 585
482 self.data['STARTED'] = False
483 586 return
484 587
485 588 def sendToWeb(self):
486 589
487 590 if not self.isWebConfig:
488 591 context = zmq.Context()
489 592 sender_web_config = context.socket(zmq.PUB)
490 593 if 'tcp://' in self.plot_address:
491 594 dum, address, port = self.plot_address.split(':')
492 595 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
493 596 else:
494 597 conf_address = self.plot_address + '.config'
495 598 sender_web_config.bind(conf_address)
496 599 time.sleep(1)
497 600 for kwargs in self.operationKwargs.values():
498 601 if 'plot' in kwargs:
499 print '[Sending] Config data to web for {}'.format(kwargs['code'].upper())
602 log.success('[Sending] Config data to web for {}'.format(kwargs['code'].upper()))
500 603 sender_web_config.send_string(json.dumps(kwargs))
501 self.isWebConfig = True
604 self.isWebConfig = True No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now