##// END OF EJS Templates
Fix SpectralMoments Plot
Juan C. Espinoza -
r1207:15feaa6e0b57
parent child
Show More
@@ -1,1353 +1,1358
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 5 '''
6 6
7 7 import copy
8 8 import numpy
9 9 import datetime
10 10 import json
11 11
12 12 from schainpy.utils import log
13 13 from .jroheaderIO import SystemHeader, RadarControllerHeader
14 14
15 15
16 16 def getNumpyDtype(dataTypeCode):
17 17
18 18 if dataTypeCode == 0:
19 19 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
20 20 elif dataTypeCode == 1:
21 21 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
22 22 elif dataTypeCode == 2:
23 23 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
24 24 elif dataTypeCode == 3:
25 25 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
26 26 elif dataTypeCode == 4:
27 27 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
28 28 elif dataTypeCode == 5:
29 29 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
30 30 else:
31 31 raise ValueError('dataTypeCode was not defined')
32 32
33 33 return numpyDtype
34 34
35 35
36 36 def getDataTypeCode(numpyDtype):
37 37
38 38 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
39 39 datatype = 0
40 40 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
41 41 datatype = 1
42 42 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
43 43 datatype = 2
44 44 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
45 45 datatype = 3
46 46 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
47 47 datatype = 4
48 48 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
49 49 datatype = 5
50 50 else:
51 51 datatype = None
52 52
53 53 return datatype
54 54
55 55
56 56 def hildebrand_sekhon(data, navg):
57 57 """
58 58 This method is for the objective determination of the noise level in Doppler spectra. This
59 59 implementation technique is based on the fact that the standard deviation of the spectral
60 60 densities is equal to the mean spectral density for white Gaussian noise
61 61
62 62 Inputs:
63 63 Data : heights
64 64 navg : numbers of averages
65 65
66 66 Return:
67 67 mean : noise's level
68 68 """
69 69
70 70 sortdata = numpy.sort(data, axis=None)
71 71 lenOfData = len(sortdata)
72 72 nums_min = lenOfData*0.2
73 73
74 74 if nums_min <= 5:
75 75
76 76 nums_min = 5
77 77
78 78 sump = 0.
79 79 sumq = 0.
80 80
81 81 j = 0
82 82 cont = 1
83 83
84 84 while((cont == 1)and(j < lenOfData)):
85 85
86 86 sump += sortdata[j]
87 87 sumq += sortdata[j]**2
88 88
89 89 if j > nums_min:
90 90 rtest = float(j)/(j-1) + 1.0/navg
91 91 if ((sumq*j) > (rtest*sump**2)):
92 92 j = j - 1
93 93 sump = sump - sortdata[j]
94 94 sumq = sumq - sortdata[j]**2
95 95 cont = 0
96 96
97 97 j += 1
98 98
99 99 lnoise = sump / j
100 100
101 101 return lnoise
102 102
103 103
104 104 class Beam:
105 105
106 106 def __init__(self):
107 107 self.codeList = []
108 108 self.azimuthList = []
109 109 self.zenithList = []
110 110
111 111
112 112 class GenericData(object):
113 113
114 114 flagNoData = True
115 115
116 116 def copy(self, inputObj=None):
117 117
118 118 if inputObj == None:
119 119 return copy.deepcopy(self)
120 120
121 121 for key in list(inputObj.__dict__.keys()):
122 122
123 123 attribute = inputObj.__dict__[key]
124 124
125 125 # If this attribute is a tuple or list
126 126 if type(inputObj.__dict__[key]) in (tuple, list):
127 127 self.__dict__[key] = attribute[:]
128 128 continue
129 129
130 130 # If this attribute is another object or instance
131 131 if hasattr(attribute, '__dict__'):
132 132 self.__dict__[key] = attribute.copy()
133 133 continue
134 134
135 135 self.__dict__[key] = inputObj.__dict__[key]
136 136
137 137 def deepcopy(self):
138 138
139 139 return copy.deepcopy(self)
140 140
141 141 def isEmpty(self):
142 142
143 143 return self.flagNoData
144 144
145 145
146 146 class JROData(GenericData):
147 147
148 148 # m_BasicHeader = BasicHeader()
149 149 # m_ProcessingHeader = ProcessingHeader()
150 150
151 151 systemHeaderObj = SystemHeader()
152 152 radarControllerHeaderObj = RadarControllerHeader()
153 153 # data = None
154 154 type = None
155 155 datatype = None # dtype but in string
156 156 # dtype = None
157 157 # nChannels = None
158 158 # nHeights = None
159 159 nProfiles = None
160 160 heightList = None
161 161 channelList = None
162 162 flagDiscontinuousBlock = False
163 163 useLocalTime = False
164 164 utctime = None
165 165 timeZone = None
166 166 dstFlag = None
167 167 errorCount = None
168 168 blocksize = None
169 169 # nCode = None
170 170 # nBaud = None
171 171 # code = None
172 172 flagDecodeData = False # asumo q la data no esta decodificada
173 173 flagDeflipData = False # asumo q la data no esta sin flip
174 174 flagShiftFFT = False
175 175 # ippSeconds = None
176 176 # timeInterval = None
177 177 nCohInt = None
178 178 # noise = None
179 179 windowOfFilter = 1
180 180 # Speed of ligth
181 181 C = 3e8
182 182 frequency = 49.92e6
183 183 realtime = False
184 184 beacon_heiIndexList = None
185 185 last_block = None
186 186 blocknow = None
187 187 azimuth = None
188 188 zenith = None
189 189 beam = Beam()
190 190 profileIndex = None
191 191 error = None
192 192 data = None
193 193 nmodes = None
194 194
195 195 def __str__(self):
196 196
197 197 return '{} - {}'.format(self.type, self.getDatatime())
198 198
199 199 def getNoise(self):
200 200
201 201 raise NotImplementedError
202 202
203 203 def getNChannels(self):
204 204
205 205 return len(self.channelList)
206 206
207 207 def getChannelIndexList(self):
208 208
209 209 return list(range(self.nChannels))
210 210
211 211 def getNHeights(self):
212 212
213 213 return len(self.heightList)
214 214
215 215 def getHeiRange(self, extrapoints=0):
216 216
217 217 heis = self.heightList
218 218 # deltah = self.heightList[1] - self.heightList[0]
219 219 #
220 220 # heis.append(self.heightList[-1])
221 221
222 222 return heis
223 223
224 224 def getDeltaH(self):
225 225
226 226 delta = self.heightList[1] - self.heightList[0]
227 227
228 228 return delta
229 229
230 230 def getltctime(self):
231 231
232 232 if self.useLocalTime:
233 233 return self.utctime - self.timeZone * 60
234 234
235 235 return self.utctime
236 236
237 237 def getDatatime(self):
238 238
239 239 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
240 240 return datatimeValue
241 241
242 242 def getTimeRange(self):
243 243
244 244 datatime = []
245 245
246 246 datatime.append(self.ltctime)
247 247 datatime.append(self.ltctime + self.timeInterval + 1)
248 248
249 249 datatime = numpy.array(datatime)
250 250
251 251 return datatime
252 252
253 253 def getFmaxTimeResponse(self):
254 254
255 255 period = (10**-6) * self.getDeltaH() / (0.15)
256 256
257 257 PRF = 1. / (period * self.nCohInt)
258 258
259 259 fmax = PRF
260 260
261 261 return fmax
262 262
263 263 def getFmax(self):
264 264 PRF = 1. / (self.ippSeconds * self.nCohInt)
265 265
266 266 fmax = PRF
267 267 return fmax
268 268
269 269 def getVmax(self):
270 270
271 271 _lambda = self.C / self.frequency
272 272
273 273 vmax = self.getFmax() * _lambda / 2
274 274
275 275 return vmax
276 276
277 277 def get_ippSeconds(self):
278 278 '''
279 279 '''
280 280 return self.radarControllerHeaderObj.ippSeconds
281 281
282 282 def set_ippSeconds(self, ippSeconds):
283 283 '''
284 284 '''
285 285
286 286 self.radarControllerHeaderObj.ippSeconds = ippSeconds
287 287
288 288 return
289 289
290 290 def get_dtype(self):
291 291 '''
292 292 '''
293 293 return getNumpyDtype(self.datatype)
294 294
295 295 def set_dtype(self, numpyDtype):
296 296 '''
297 297 '''
298 298
299 299 self.datatype = getDataTypeCode(numpyDtype)
300 300
301 301 def get_code(self):
302 302 '''
303 303 '''
304 304 return self.radarControllerHeaderObj.code
305 305
306 306 def set_code(self, code):
307 307 '''
308 308 '''
309 309 self.radarControllerHeaderObj.code = code
310 310
311 311 return
312 312
313 313 def get_ncode(self):
314 314 '''
315 315 '''
316 316 return self.radarControllerHeaderObj.nCode
317 317
318 318 def set_ncode(self, nCode):
319 319 '''
320 320 '''
321 321 self.radarControllerHeaderObj.nCode = nCode
322 322
323 323 return
324 324
325 325 def get_nbaud(self):
326 326 '''
327 327 '''
328 328 return self.radarControllerHeaderObj.nBaud
329 329
330 330 def set_nbaud(self, nBaud):
331 331 '''
332 332 '''
333 333 self.radarControllerHeaderObj.nBaud = nBaud
334 334
335 335 return
336 336
337 337 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
338 338 channelIndexList = property(
339 339 getChannelIndexList, "I'm the 'channelIndexList' property.")
340 340 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
341 341 #noise = property(getNoise, "I'm the 'nHeights' property.")
342 342 datatime = property(getDatatime, "I'm the 'datatime' property")
343 343 ltctime = property(getltctime, "I'm the 'ltctime' property")
344 344 ippSeconds = property(get_ippSeconds, set_ippSeconds)
345 345 dtype = property(get_dtype, set_dtype)
346 346 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
347 347 code = property(get_code, set_code)
348 348 nCode = property(get_ncode, set_ncode)
349 349 nBaud = property(get_nbaud, set_nbaud)
350 350
351 351
352 352 class Voltage(JROData):
353 353
354 354 # data es un numpy array de 2 dmensiones (canales, alturas)
355 355 data = None
356 356
357 357 def __init__(self):
358 358 '''
359 359 Constructor
360 360 '''
361 361
362 362 self.useLocalTime = True
363 363 self.radarControllerHeaderObj = RadarControllerHeader()
364 364 self.systemHeaderObj = SystemHeader()
365 365 self.type = "Voltage"
366 366 self.data = None
367 367 # self.dtype = None
368 368 # self.nChannels = 0
369 369 # self.nHeights = 0
370 370 self.nProfiles = None
371 371 self.heightList = None
372 372 self.channelList = None
373 373 # self.channelIndexList = None
374 374 self.flagNoData = True
375 375 self.flagDiscontinuousBlock = False
376 376 self.utctime = None
377 377 self.timeZone = None
378 378 self.dstFlag = None
379 379 self.errorCount = None
380 380 self.nCohInt = None
381 381 self.blocksize = None
382 382 self.flagDecodeData = False # asumo q la data no esta decodificada
383 383 self.flagDeflipData = False # asumo q la data no esta sin flip
384 384 self.flagShiftFFT = False
385 385 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
386 386 self.profileIndex = 0
387 387
388 388 def getNoisebyHildebrand(self, channel=None):
389 389 """
390 390 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
391 391
392 392 Return:
393 393 noiselevel
394 394 """
395 395
396 396 if channel != None:
397 397 data = self.data[channel]
398 398 nChannels = 1
399 399 else:
400 400 data = self.data
401 401 nChannels = self.nChannels
402 402
403 403 noise = numpy.zeros(nChannels)
404 404 power = data * numpy.conjugate(data)
405 405
406 406 for thisChannel in range(nChannels):
407 407 if nChannels == 1:
408 408 daux = power[:].real
409 409 else:
410 410 daux = power[thisChannel, :].real
411 411 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
412 412
413 413 return noise
414 414
415 415 def getNoise(self, type=1, channel=None):
416 416
417 417 if type == 1:
418 418 noise = self.getNoisebyHildebrand(channel)
419 419
420 420 return noise
421 421
422 422 def getPower(self, channel=None):
423 423
424 424 if channel != None:
425 425 data = self.data[channel]
426 426 else:
427 427 data = self.data
428 428
429 429 power = data * numpy.conjugate(data)
430 430 powerdB = 10 * numpy.log10(power.real)
431 431 powerdB = numpy.squeeze(powerdB)
432 432
433 433 return powerdB
434 434
435 435 def getTimeInterval(self):
436 436
437 437 timeInterval = self.ippSeconds * self.nCohInt
438 438
439 439 return timeInterval
440 440
441 441 noise = property(getNoise, "I'm the 'nHeights' property.")
442 442 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
443 443
444 444
445 445 class Spectra(JROData):
446 446
447 447 # data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
448 448 data_spc = None
449 449 # data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
450 450 data_cspc = None
451 451 # data dc es un numpy array de 2 dmensiones (canales, alturas)
452 452 data_dc = None
453 453 # data power
454 454 data_pwr = None
455 455 nFFTPoints = None
456 456 # nPairs = None
457 457 pairsList = None
458 458 nIncohInt = None
459 459 wavelength = None # Necesario para cacular el rango de velocidad desde la frecuencia
460 460 nCohInt = None # se requiere para determinar el valor de timeInterval
461 461 ippFactor = None
462 462 profileIndex = 0
463 463 plotting = "spectra"
464 464
465 465 def __init__(self):
466 466 '''
467 467 Constructor
468 468 '''
469 469
470 470 self.useLocalTime = True
471 471 self.radarControllerHeaderObj = RadarControllerHeader()
472 472 self.systemHeaderObj = SystemHeader()
473 473 self.type = "Spectra"
474 474 # self.data = None
475 475 # self.dtype = None
476 476 # self.nChannels = 0
477 477 # self.nHeights = 0
478 478 self.nProfiles = None
479 479 self.heightList = None
480 480 self.channelList = None
481 481 # self.channelIndexList = None
482 482 self.pairsList = None
483 483 self.flagNoData = True
484 484 self.flagDiscontinuousBlock = False
485 485 self.utctime = None
486 486 self.nCohInt = None
487 487 self.nIncohInt = None
488 488 self.blocksize = None
489 489 self.nFFTPoints = None
490 490 self.wavelength = None
491 491 self.flagDecodeData = False # asumo q la data no esta decodificada
492 492 self.flagDeflipData = False # asumo q la data no esta sin flip
493 493 self.flagShiftFFT = False
494 494 self.ippFactor = 1
495 495 #self.noise = None
496 496 self.beacon_heiIndexList = []
497 497 self.noise_estimation = None
498 498
499 499 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
500 500 """
501 501 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
502 502
503 503 Return:
504 504 noiselevel
505 505 """
506 506
507 507 noise = numpy.zeros(self.nChannels)
508 508
509 509 for channel in range(self.nChannels):
510 510 daux = self.data_spc[channel,
511 511 xmin_index:xmax_index, ymin_index:ymax_index]
512 512 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
513 513
514 514 return noise
515 515
516 516 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
517 517
518 518 if self.noise_estimation is not None:
519 519 # this was estimated by getNoise Operation defined in jroproc_spectra.py
520 520 return self.noise_estimation
521 521 else:
522 522 noise = self.getNoisebyHildebrand(
523 523 xmin_index, xmax_index, ymin_index, ymax_index)
524 524 return noise
525 525
526 526 def getFreqRangeTimeResponse(self, extrapoints=0):
527 527
528 528 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
529 529 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
530 530
531 531 return freqrange
532 532
533 533 def getAcfRange(self, extrapoints=0):
534 534
535 535 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
536 536 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
537 537
538 538 return freqrange
539 539
540 540 def getFreqRange(self, extrapoints=0):
541 541
542 542 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
543 543 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
544 544
545 545 return freqrange
546 546
547 547 def getVelRange(self, extrapoints=0):
548 548
549 549 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
550 550 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
551 551
552 552 if self.nmodes:
553 553 return velrange/self.nmodes
554 554 else:
555 555 return velrange
556 556
557 557 def getNPairs(self):
558 558
559 559 return len(self.pairsList)
560 560
561 561 def getPairsIndexList(self):
562 562
563 563 return list(range(self.nPairs))
564 564
565 565 def getNormFactor(self):
566 566
567 567 pwcode = 1
568 568
569 569 if self.flagDecodeData:
570 570 pwcode = numpy.sum(self.code[0]**2)
571 571 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
572 572 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
573 573
574 574 return normFactor
575 575
576 576 def getFlagCspc(self):
577 577
578 578 if self.data_cspc is None:
579 579 return True
580 580
581 581 return False
582 582
583 583 def getFlagDc(self):
584 584
585 585 if self.data_dc is None:
586 586 return True
587 587
588 588 return False
589 589
590 590 def getTimeInterval(self):
591 591
592 592 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
593 593
594 594 return timeInterval
595 595
596 596 def getPower(self):
597 597
598 598 factor = self.normFactor
599 599 z = self.data_spc / factor
600 600 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
601 601 avg = numpy.average(z, axis=1)
602 602
603 603 return 10 * numpy.log10(avg)
604 604
605 605 def getCoherence(self, pairsList=None, phase=False):
606 606
607 607 z = []
608 608 if pairsList is None:
609 609 pairsIndexList = self.pairsIndexList
610 610 else:
611 611 pairsIndexList = []
612 612 for pair in pairsList:
613 613 if pair not in self.pairsList:
614 614 raise ValueError("Pair %s is not in dataOut.pairsList" % (
615 615 pair))
616 616 pairsIndexList.append(self.pairsList.index(pair))
617 617 for i in range(len(pairsIndexList)):
618 618 pair = self.pairsList[pairsIndexList[i]]
619 619 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
620 620 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
621 621 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
622 622 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
623 623 if phase:
624 624 data = numpy.arctan2(avgcoherenceComplex.imag,
625 625 avgcoherenceComplex.real) * 180 / numpy.pi
626 626 else:
627 627 data = numpy.abs(avgcoherenceComplex)
628 628
629 629 z.append(data)
630 630
631 631 return numpy.array(z)
632 632
633 633 def setValue(self, value):
634 634
635 635 print("This property should not be initialized")
636 636
637 637 return
638 638
639 639 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
640 640 pairsIndexList = property(
641 641 getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
642 642 normFactor = property(getNormFactor, setValue,
643 643 "I'm the 'getNormFactor' property.")
644 644 flag_cspc = property(getFlagCspc, setValue)
645 645 flag_dc = property(getFlagDc, setValue)
646 646 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
647 647 timeInterval = property(getTimeInterval, setValue,
648 648 "I'm the 'timeInterval' property")
649 649
650 650
651 651 class SpectraHeis(Spectra):
652 652
653 653 data_spc = None
654 654 data_cspc = None
655 655 data_dc = None
656 656 nFFTPoints = None
657 657 # nPairs = None
658 658 pairsList = None
659 659 nCohInt = None
660 660 nIncohInt = None
661 661
662 662 def __init__(self):
663 663
664 664 self.radarControllerHeaderObj = RadarControllerHeader()
665 665
666 666 self.systemHeaderObj = SystemHeader()
667 667
668 668 self.type = "SpectraHeis"
669 669
670 670 # self.dtype = None
671 671
672 672 # self.nChannels = 0
673 673
674 674 # self.nHeights = 0
675 675
676 676 self.nProfiles = None
677 677
678 678 self.heightList = None
679 679
680 680 self.channelList = None
681 681
682 682 # self.channelIndexList = None
683 683
684 684 self.flagNoData = True
685 685
686 686 self.flagDiscontinuousBlock = False
687 687
688 688 # self.nPairs = 0
689 689
690 690 self.utctime = None
691 691
692 692 self.blocksize = None
693 693
694 694 self.profileIndex = 0
695 695
696 696 self.nCohInt = 1
697 697
698 698 self.nIncohInt = 1
699 699
700 700 def getNormFactor(self):
701 701 pwcode = 1
702 702 if self.flagDecodeData:
703 703 pwcode = numpy.sum(self.code[0]**2)
704 704
705 705 normFactor = self.nIncohInt * self.nCohInt * pwcode
706 706
707 707 return normFactor
708 708
709 709 def getTimeInterval(self):
710 710
711 711 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
712 712
713 713 return timeInterval
714 714
715 715 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
716 716 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
717 717
718 718
719 719 class Fits(JROData):
720 720
721 721 heightList = None
722 722 channelList = None
723 723 flagNoData = True
724 724 flagDiscontinuousBlock = False
725 725 useLocalTime = False
726 726 utctime = None
727 727 timeZone = None
728 728 # ippSeconds = None
729 729 # timeInterval = None
730 730 nCohInt = None
731 731 nIncohInt = None
732 732 noise = None
733 733 windowOfFilter = 1
734 734 # Speed of ligth
735 735 C = 3e8
736 736 frequency = 49.92e6
737 737 realtime = False
738 738
739 739 def __init__(self):
740 740
741 741 self.type = "Fits"
742 742
743 743 self.nProfiles = None
744 744
745 745 self.heightList = None
746 746
747 747 self.channelList = None
748 748
749 749 # self.channelIndexList = None
750 750
751 751 self.flagNoData = True
752 752
753 753 self.utctime = None
754 754
755 755 self.nCohInt = 1
756 756
757 757 self.nIncohInt = 1
758 758
759 759 self.useLocalTime = True
760 760
761 761 self.profileIndex = 0
762 762
763 763 # self.utctime = None
764 764 # self.timeZone = None
765 765 # self.ltctime = None
766 766 # self.timeInterval = None
767 767 # self.header = None
768 768 # self.data_header = None
769 769 # self.data = None
770 770 # self.datatime = None
771 771 # self.flagNoData = False
772 772 # self.expName = ''
773 773 # self.nChannels = None
774 774 # self.nSamples = None
775 775 # self.dataBlocksPerFile = None
776 776 # self.comments = ''
777 777 #
778 778
779 779 def getltctime(self):
780 780
781 781 if self.useLocalTime:
782 782 return self.utctime - self.timeZone * 60
783 783
784 784 return self.utctime
785 785
786 786 def getDatatime(self):
787 787
788 788 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
789 789 return datatime
790 790
791 791 def getTimeRange(self):
792 792
793 793 datatime = []
794 794
795 795 datatime.append(self.ltctime)
796 796 datatime.append(self.ltctime + self.timeInterval)
797 797
798 798 datatime = numpy.array(datatime)
799 799
800 800 return datatime
801 801
802 802 def getHeiRange(self):
803 803
804 804 heis = self.heightList
805 805
806 806 return heis
807 807
808 808 def getNHeights(self):
809 809
810 810 return len(self.heightList)
811 811
812 812 def getNChannels(self):
813 813
814 814 return len(self.channelList)
815 815
816 816 def getChannelIndexList(self):
817 817
818 818 return list(range(self.nChannels))
819 819
820 820 def getNoise(self, type=1):
821 821
822 822 #noise = numpy.zeros(self.nChannels)
823 823
824 824 if type == 1:
825 825 noise = self.getNoisebyHildebrand()
826 826
827 827 if type == 2:
828 828 noise = self.getNoisebySort()
829 829
830 830 if type == 3:
831 831 noise = self.getNoisebyWindow()
832 832
833 833 return noise
834 834
835 835 def getTimeInterval(self):
836 836
837 837 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
838 838
839 839 return timeInterval
840 840
841 841 def get_ippSeconds(self):
842 842 '''
843 843 '''
844 844 return self.ipp_sec
845 845
846 846
847 847 datatime = property(getDatatime, "I'm the 'datatime' property")
848 848 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
849 849 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
850 850 channelIndexList = property(
851 851 getChannelIndexList, "I'm the 'channelIndexList' property.")
852 852 noise = property(getNoise, "I'm the 'nHeights' property.")
853 853
854 854 ltctime = property(getltctime, "I'm the 'ltctime' property")
855 855 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
856 856 ippSeconds = property(get_ippSeconds, '')
857 857
858 858 class Correlation(JROData):
859 859
860 860 noise = None
861 861 SNR = None
862 862 #--------------------------------------------------
863 863 mode = None
864 864 split = False
865 865 data_cf = None
866 866 lags = None
867 867 lagRange = None
868 868 pairsList = None
869 869 normFactor = None
870 870 #--------------------------------------------------
871 871 # calculateVelocity = None
872 872 nLags = None
873 873 nPairs = None
874 874 nAvg = None
875 875
876 876 def __init__(self):
877 877 '''
878 878 Constructor
879 879 '''
880 880 self.radarControllerHeaderObj = RadarControllerHeader()
881 881
882 882 self.systemHeaderObj = SystemHeader()
883 883
884 884 self.type = "Correlation"
885 885
886 886 self.data = None
887 887
888 888 self.dtype = None
889 889
890 890 self.nProfiles = None
891 891
892 892 self.heightList = None
893 893
894 894 self.channelList = None
895 895
896 896 self.flagNoData = True
897 897
898 898 self.flagDiscontinuousBlock = False
899 899
900 900 self.utctime = None
901 901
902 902 self.timeZone = None
903 903
904 904 self.dstFlag = None
905 905
906 906 self.errorCount = None
907 907
908 908 self.blocksize = None
909 909
910 910 self.flagDecodeData = False # asumo q la data no esta decodificada
911 911
912 912 self.flagDeflipData = False # asumo q la data no esta sin flip
913 913
914 914 self.pairsList = None
915 915
916 916 self.nPoints = None
917 917
918 918 def getPairsList(self):
919 919
920 920 return self.pairsList
921 921
922 922 def getNoise(self, mode=2):
923 923
924 924 indR = numpy.where(self.lagR == 0)[0][0]
925 925 indT = numpy.where(self.lagT == 0)[0][0]
926 926
927 927 jspectra0 = self.data_corr[:, :, indR, :]
928 928 jspectra = copy.copy(jspectra0)
929 929
930 930 num_chan = jspectra.shape[0]
931 931 num_hei = jspectra.shape[2]
932 932
933 933 freq_dc = jspectra.shape[1] / 2
934 934 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
935 935
936 936 if ind_vel[0] < 0:
937 937 ind_vel[list(range(0, 1))] = ind_vel[list(
938 938 range(0, 1))] + self.num_prof
939 939
940 940 if mode == 1:
941 941 jspectra[:, freq_dc, :] = (
942 942 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
943 943
944 944 if mode == 2:
945 945
946 946 vel = numpy.array([-2, -1, 1, 2])
947 947 xx = numpy.zeros([4, 4])
948 948
949 949 for fil in range(4):
950 950 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
951 951
952 952 xx_inv = numpy.linalg.inv(xx)
953 953 xx_aux = xx_inv[0, :]
954 954
955 955 for ich in range(num_chan):
956 956 yy = jspectra[ich, ind_vel, :]
957 957 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
958 958
959 959 junkid = jspectra[ich, freq_dc, :] <= 0
960 960 cjunkid = sum(junkid)
961 961
962 962 if cjunkid.any():
963 963 jspectra[ich, freq_dc, junkid.nonzero()] = (
964 964 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
965 965
966 966 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
967 967
968 968 return noise
969 969
970 970 def getTimeInterval(self):
971 971
972 972 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
973 973
974 974 return timeInterval
975 975
976 976 def splitFunctions(self):
977 977
978 978 pairsList = self.pairsList
979 979 ccf_pairs = []
980 980 acf_pairs = []
981 981 ccf_ind = []
982 982 acf_ind = []
983 983 for l in range(len(pairsList)):
984 984 chan0 = pairsList[l][0]
985 985 chan1 = pairsList[l][1]
986 986
987 987 # Obteniendo pares de Autocorrelacion
988 988 if chan0 == chan1:
989 989 acf_pairs.append(chan0)
990 990 acf_ind.append(l)
991 991 else:
992 992 ccf_pairs.append(pairsList[l])
993 993 ccf_ind.append(l)
994 994
995 995 data_acf = self.data_cf[acf_ind]
996 996 data_ccf = self.data_cf[ccf_ind]
997 997
998 998 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
999 999
1000 1000 def getNormFactor(self):
1001 1001 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1002 1002 acf_pairs = numpy.array(acf_pairs)
1003 1003 normFactor = numpy.zeros((self.nPairs, self.nHeights))
1004 1004
1005 1005 for p in range(self.nPairs):
1006 1006 pair = self.pairsList[p]
1007 1007
1008 1008 ch0 = pair[0]
1009 1009 ch1 = pair[1]
1010 1010
1011 1011 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
1012 1012 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
1013 1013 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
1014 1014
1015 1015 return normFactor
1016 1016
1017 1017 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1018 1018 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1019 1019
1020 1020
1021 1021 class Parameters(Spectra):
1022 1022
1023 1023 experimentInfo = None # Information about the experiment
1024 1024 # Information from previous data
1025 1025 inputUnit = None # Type of data to be processed
1026 1026 operation = None # Type of operation to parametrize
1027 1027 # normFactor = None #Normalization Factor
1028 1028 groupList = None # List of Pairs, Groups, etc
1029 1029 # Parameters
1030 1030 data_param = None # Parameters obtained
1031 1031 data_pre = None # Data Pre Parametrization
1032 1032 data_SNR = None # Signal to Noise Ratio
1033 1033 # heightRange = None #Heights
1034 1034 abscissaList = None # Abscissa, can be velocities, lags or time
1035 1035 # noise = None #Noise Potency
1036 1036 utctimeInit = None # Initial UTC time
1037 1037 paramInterval = None # Time interval to calculate Parameters in seconds
1038 1038 useLocalTime = True
1039 1039 # Fitting
1040 1040 data_error = None # Error of the estimation
1041 1041 constants = None
1042 1042 library = None
1043 1043 # Output signal
1044 1044 outputInterval = None # Time interval to calculate output signal in seconds
1045 1045 data_output = None # Out signal
1046 1046 nAvg = None
1047 1047 noise_estimation = None
1048 1048 GauSPC = None # Fit gaussian SPC
1049 1049
1050 1050 def __init__(self):
1051 1051 '''
1052 1052 Constructor
1053 1053 '''
1054 1054 self.radarControllerHeaderObj = RadarControllerHeader()
1055 1055
1056 1056 self.systemHeaderObj = SystemHeader()
1057 1057
1058 1058 self.type = "Parameters"
1059 1059
1060 1060 def getTimeRange1(self, interval):
1061 1061
1062 1062 datatime = []
1063 1063
1064 1064 if self.useLocalTime:
1065 1065 time1 = self.utctimeInit - self.timeZone * 60
1066 1066 else:
1067 1067 time1 = self.utctimeInit
1068 1068
1069 1069 datatime.append(time1)
1070 1070 datatime.append(time1 + interval)
1071 1071 datatime = numpy.array(datatime)
1072 1072
1073 1073 return datatime
1074 1074
1075 1075 def getTimeInterval(self):
1076 1076
1077 1077 if hasattr(self, 'timeInterval1'):
1078 1078 return self.timeInterval1
1079 1079 else:
1080 1080 return self.paramInterval
1081 1081
1082 1082 def setValue(self, value):
1083 1083
1084 1084 print("This property should not be initialized")
1085 1085
1086 1086 return
1087 1087
1088 1088 def getNoise(self):
1089 1089
1090 1090 return self.spc_noise
1091 1091
1092 1092 timeInterval = property(getTimeInterval)
1093 1093 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
1094 1094
1095 1095
1096 1096 class PlotterData(object):
1097 1097 '''
1098 1098 Object to hold data to be plotted
1099 1099 '''
1100 1100
1101 1101 MAXNUMX = 100
1102 1102 MAXNUMY = 100
1103 1103
1104 1104 def __init__(self, code, throttle_value, exp_code, buffering=True):
1105 1105
1106 1106 self.throttle = throttle_value
1107 1107 self.exp_code = exp_code
1108 1108 self.buffering = buffering
1109 1109 self.ready = False
1110 1110 self.localtime = False
1111 1111 self.data = {}
1112 1112 self.meta = {}
1113 1113 self.__times = []
1114 1114 self.__heights = []
1115 1115
1116 1116 if 'snr' in code:
1117 1117 self.plottypes = ['snr']
1118 1118 elif code == 'spc':
1119 1119 self.plottypes = ['spc', 'noise', 'rti']
1120 1120 elif code == 'rti':
1121 1121 self.plottypes = ['noise', 'rti']
1122 1122 else:
1123 1123 self.plottypes = [code]
1124 1124
1125 1125 for plot in self.plottypes:
1126 1126 self.data[plot] = {}
1127 1127
1128 1128 def __str__(self):
1129 1129 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1130 1130 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
1131 1131
1132 1132 def __len__(self):
1133 1133 return len(self.__times)
1134 1134
1135 1135 def __getitem__(self, key):
1136 1136
1137 1137 if key not in self.data:
1138 1138 raise KeyError(log.error('Missing key: {}'.format(key)))
1139 1139 if 'spc' in key or not self.buffering:
1140 1140 ret = self.data[key]
1141 1141 elif 'scope' in key:
1142 1142 ret = numpy.array(self.data[key][float(self.tm)])
1143 1143 else:
1144 1144 ret = numpy.array([self.data[key][x] for x in self.times])
1145 1145 if ret.ndim > 1:
1146 1146 ret = numpy.swapaxes(ret, 0, 1)
1147 1147 return ret
1148 1148
1149 1149 def __contains__(self, key):
1150 1150 return key in self.data
1151 1151
1152 1152 def setup(self):
1153 1153 '''
1154 1154 Configure object
1155 1155 '''
1156 1156
1157 1157 self.type = ''
1158 1158 self.ready = False
1159 1159 self.data = {}
1160 1160 self.__times = []
1161 1161 self.__heights = []
1162 1162 self.__all_heights = set()
1163 1163 for plot in self.plottypes:
1164 1164 if 'snr' in plot:
1165 1165 plot = 'snr'
1166 elif 'spc_moments' == plot:
1167 plot = 'moments'
1166 1168 self.data[plot] = {}
1167 1169
1168 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data:
1170 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data:
1169 1171 self.data['noise'] = {}
1170 1172 if 'noise' not in self.plottypes:
1171 1173 self.plottypes.append('noise')
1172 1174
1173 1175 def shape(self, key):
1174 1176 '''
1175 1177 Get the shape of the one-element data for the given key
1176 1178 '''
1177 1179
1178 1180 if len(self.data[key]):
1179 1181 if 'spc' in key or not self.buffering:
1180 1182 return self.data[key].shape
1181 1183 return self.data[key][self.__times[0]].shape
1182 1184 return (0,)
1183 1185
1184 1186 def update(self, dataOut, tm):
1185 1187 '''
1186 1188 Update data object with new dataOut
1187 1189 '''
1188 1190
1189 1191 if tm in self.__times:
1190 1192 return
1191 1193 self.profileIndex = dataOut.profileIndex
1192 1194 self.tm = tm
1193 1195 self.type = dataOut.type
1194 1196 self.parameters = getattr(dataOut, 'parameters', [])
1195 1197 if hasattr(dataOut, 'pairsList'):
1196 1198 self.pairs = dataOut.pairsList
1197 1199 if hasattr(dataOut, 'meta'):
1198 1200 self.meta = dataOut.meta
1199 1201 self.channels = dataOut.channelList
1200 1202 self.interval = dataOut.getTimeInterval()
1201 1203 self.localtime = dataOut.useLocalTime
1202 if 'spc' in self.plottypes or 'cspc' in self.plottypes:
1204 if 'spc' in self.plottypes or 'cspc' in self.plottypes or 'spc_moments' in self.plottypes:
1203 1205 self.xrange = (dataOut.getFreqRange(1)/1000.,
1204 1206 dataOut.getAcfRange(1), dataOut.getVelRange(1))
1205 1207 self.factor = dataOut.normFactor
1206 1208 self.__heights.append(dataOut.heightList)
1207 1209 self.__all_heights.update(dataOut.heightList)
1208 1210 self.__times.append(tm)
1209 1211
1210 1212 for plot in self.plottypes:
1211 if plot == 'spc':
1213 if plot in ('spc', 'spc_moments'):
1212 1214 z = dataOut.data_spc/dataOut.normFactor
1213 1215 buffer = 10*numpy.log10(z)
1214 1216 if plot == 'cspc':
1215 1217 z = dataOut.data_spc/dataOut.normFactor
1216 1218 buffer = (dataOut.data_spc, dataOut.data_cspc)
1217 1219 if plot == 'noise':
1218 1220 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
1219 1221 if plot == 'rti':
1220 1222 buffer = dataOut.getPower()
1221 1223 if plot == 'snr_db':
1222 1224 buffer = dataOut.data_SNR
1223 1225 if plot == 'snr':
1224 1226 buffer = 10*numpy.log10(dataOut.data_SNR)
1225 1227 if plot == 'dop':
1226 1228 buffer = 10*numpy.log10(dataOut.data_DOP)
1227 1229 if plot == 'mean':
1228 1230 buffer = dataOut.data_MEAN
1229 1231 if plot == 'std':
1230 1232 buffer = dataOut.data_STD
1231 1233 if plot == 'coh':
1232 1234 buffer = dataOut.getCoherence()
1233 1235 if plot == 'phase':
1234 1236 buffer = dataOut.getCoherence(phase=True)
1235 1237 if plot == 'output':
1236 1238 buffer = dataOut.data_output
1237 1239 if plot == 'param':
1238 1240 buffer = dataOut.data_param
1239 1241 if plot == 'scope':
1240 1242 buffer = dataOut.data
1241 1243 self.flagDataAsBlock = dataOut.flagDataAsBlock
1242 1244 self.nProfiles = dataOut.nProfiles
1243 1245
1244 1246 if plot == 'spc':
1245 1247 self.data[plot] = buffer
1246 1248 elif plot == 'cspc':
1247 1249 self.data['spc'] = buffer[0]
1248 1250 self.data['cspc'] = buffer[1]
1251 elif plot == 'spc_moments':
1252 self.data['spc'] = buffer
1253 self.data['moments'][tm] = dataOut.moments
1249 1254 else:
1250 1255 if self.buffering:
1251 1256 self.data[plot][tm] = buffer
1252 1257 else:
1253 1258 self.data[plot] = buffer
1254 1259
1255 1260 def normalize_heights(self):
1256 1261 '''
1257 1262 Ensure same-dimension of the data for different heighList
1258 1263 '''
1259 1264
1260 1265 H = numpy.array(list(self.__all_heights))
1261 1266 H.sort()
1262 1267 for key in self.data:
1263 1268 shape = self.shape(key)[:-1] + H.shape
1264 1269 for tm, obj in list(self.data[key].items()):
1265 1270 h = self.__heights[self.__times.index(tm)]
1266 1271 if H.size == h.size:
1267 1272 continue
1268 1273 index = numpy.where(numpy.in1d(H, h))[0]
1269 1274 dummy = numpy.zeros(shape) + numpy.nan
1270 1275 if len(shape) == 2:
1271 1276 dummy[:, index] = obj
1272 1277 else:
1273 1278 dummy[index] = obj
1274 1279 self.data[key][tm] = dummy
1275 1280
1276 1281 self.__heights = [H for tm in self.__times]
1277 1282
1278 1283 def jsonify(self, decimate=False):
1279 1284 '''
1280 1285 Convert data to json
1281 1286 '''
1282 1287
1283 1288 data = {}
1284 1289 tm = self.times[-1]
1285 1290 dy = int(self.heights.size/self.MAXNUMY) + 1
1286 1291 for key in self.data:
1287 1292 if key in ('spc', 'cspc') or not self.buffering:
1288 1293 dx = int(self.data[key].shape[1]/self.MAXNUMX) + 1
1289 1294 data[key] = self.roundFloats(
1290 1295 self.data[key][::, ::dx, ::dy].tolist())
1291 1296 else:
1292 1297 data[key] = self.roundFloats(self.data[key][tm].tolist())
1293 1298
1294 1299 ret = {'data': data}
1295 1300 ret['exp_code'] = self.exp_code
1296 1301 ret['time'] = float(tm)
1297 1302 ret['interval'] = float(self.interval)
1298 1303 ret['localtime'] = self.localtime
1299 1304 ret['yrange'] = self.roundFloats(self.heights[::dy].tolist())
1300 1305 if 'spc' in self.data or 'cspc' in self.data:
1301 1306 ret['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1302 1307 else:
1303 1308 ret['xrange'] = []
1304 1309 if hasattr(self, 'pairs'):
1305 1310 ret['pairs'] = [(int(p[0]), int(p[1])) for p in self.pairs]
1306 1311 else:
1307 1312 ret['pairs'] = []
1308 1313
1309 1314 for key, value in list(self.meta.items()):
1310 1315 ret[key] = value
1311 1316
1312 1317 return json.dumps(ret)
1313 1318
1314 1319 @property
1315 1320 def times(self):
1316 1321 '''
1317 1322 Return the list of times of the current data
1318 1323 '''
1319 1324
1320 1325 ret = numpy.array(self.__times)
1321 1326 ret.sort()
1322 1327 return ret
1323 1328
1324 1329 @property
1325 1330 def min_time(self):
1326 1331 '''
1327 1332 Return the minimun time value
1328 1333 '''
1329 1334
1330 1335 return self.times[0]
1331 1336
1332 1337 @property
1333 1338 def max_time(self):
1334 1339 '''
1335 1340 Return the maximun time value
1336 1341 '''
1337 1342
1338 1343 return self.times[-1]
1339 1344
1340 1345 @property
1341 1346 def heights(self):
1342 1347 '''
1343 1348 Return the list of heights of the current data
1344 1349 '''
1345 1350
1346 1351 return numpy.array(self.__heights[-1])
1347 1352
1348 1353 @staticmethod
1349 1354 def roundFloats(obj):
1350 1355 if isinstance(obj, list):
1351 1356 return list(map(PlotterData.roundFloats, obj))
1352 1357 elif isinstance(obj, float):
1353 1358 return round(obj, 2)
@@ -1,748 +1,747
1 1 '''
2 2 New Plots Operations
3 3
4 4 @author: juan.espinoza@jro.igp.gob.pe
5 5 '''
6 6
7 7
8 8 import time
9 9 import datetime
10 10 import numpy
11 11
12 12 from schainpy.model.graphics.jroplot_base import Plot, plt
13 13 from schainpy.utils import log
14 14
15 15 EARTH_RADIUS = 6.3710e3
16 16
17 17
18 18 def ll2xy(lat1, lon1, lat2, lon2):
19 19
20 20 p = 0.017453292519943295
21 21 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
22 22 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
23 23 r = 12742 * numpy.arcsin(numpy.sqrt(a))
24 24 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
25 25 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
26 26 theta = -theta + numpy.pi/2
27 27 return r*numpy.cos(theta), r*numpy.sin(theta)
28 28
29 29
30 30 def km2deg(km):
31 31 '''
32 32 Convert distance in km to degrees
33 33 '''
34 34
35 35 return numpy.rad2deg(km/EARTH_RADIUS)
36 36
37 37
38 38 class SpectraPlot(Plot):
39 39 '''
40 40 Plot for Spectra data
41 41 '''
42 42
43 43 CODE = 'spc'
44 44 colormap = 'jro'
45 45
46 46 def setup(self):
47 47 self.nplots = len(self.data.channels)
48 48 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
49 49 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
50 50 self.width = 3.4 * self.ncols
51 51 self.height = 3 * self.nrows
52 52 self.cb_label = 'dB'
53 53 if self.showprofile:
54 54 self.width += 0.8 * self.ncols
55 55
56 56 self.ylabel = 'Range [km]'
57 57
58 58 def plot(self):
59 59 if self.xaxis == "frequency":
60 60 x = self.data.xrange[0]
61 61 self.xlabel = "Frequency (kHz)"
62 62 elif self.xaxis == "time":
63 63 x = self.data.xrange[1]
64 64 self.xlabel = "Time (ms)"
65 65 else:
66 66 x = self.data.xrange[2]
67 67 self.xlabel = "Velocity (m/s)"
68 68
69 if self.CODE == 'spc_mean':
69 if self.CODE == 'spc_moments':
70 70 x = self.data.xrange[2]
71 71 self.xlabel = "Velocity (m/s)"
72 72
73 73 self.titles = []
74 74
75 75 y = self.data.heights
76 76 self.y = y
77 77 z = self.data['spc']
78 78
79 79 for n, ax in enumerate(self.axes):
80 80 noise = self.data['noise'][n][-1]
81 if self.CODE == 'spc_mean':
82 mean = self.data['mean'][n][-1]
81 if self.CODE == 'spc_moments':
82 mean = self.data['moments'][n, :, 1, :][-1]
83 83 if ax.firsttime:
84 84 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
85 85 self.xmin = self.xmin if self.xmin else -self.xmax
86 86 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
87 87 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
88 88 ax.plt = ax.pcolormesh(x, y, z[n].T,
89 89 vmin=self.zmin,
90 90 vmax=self.zmax,
91 91 cmap=plt.get_cmap(self.colormap)
92 92 )
93 93
94 94 if self.showprofile:
95 95 ax.plt_profile = self.pf_axes[n].plot(
96 96 self.data['rti'][n][-1], y)[0]
97 97 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
98 98 color="k", linestyle="dashed", lw=1)[0]
99 if self.CODE == 'spc_mean':
99 if self.CODE == 'spc_moments':
100 100 ax.plt_mean = ax.plot(mean, y, color='k')[0]
101 101 else:
102 102 ax.plt.set_array(z[n].T.ravel())
103 103 if self.showprofile:
104 104 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
105 105 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
106 if self.CODE == 'spc_mean':
106 if self.CODE == 'spc_moments':
107 107 ax.plt_mean.set_data(mean, y)
108
109 108 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
110 109
111 110
112 111 class CrossSpectraPlot(Plot):
113 112
114 113 CODE = 'cspc'
115 114 colormap = 'jet'
116 115 zmin_coh = None
117 116 zmax_coh = None
118 117 zmin_phase = None
119 118 zmax_phase = None
120 119
121 120 def setup(self):
122 121
123 122 self.ncols = 4
124 123 self.nrows = len(self.data.pairs)
125 124 self.nplots = self.nrows * 4
126 125 self.width = 3.4 * self.ncols
127 126 self.height = 3 * self.nrows
128 127 self.ylabel = 'Range [km]'
129 128 self.showprofile = False
130 129
131 130 def plot(self):
132 131
133 132 if self.xaxis == "frequency":
134 133 x = self.data.xrange[0]
135 134 self.xlabel = "Frequency (kHz)"
136 135 elif self.xaxis == "time":
137 136 x = self.data.xrange[1]
138 137 self.xlabel = "Time (ms)"
139 138 else:
140 139 x = self.data.xrange[2]
141 140 self.xlabel = "Velocity (m/s)"
142 141
143 142 self.titles = []
144 143
145 144 y = self.data.heights
146 145 self.y = y
147 146 spc = self.data['spc']
148 147 cspc = self.data['cspc']
149 148
150 149 for n in range(self.nrows):
151 150 noise = self.data['noise'][n][-1]
152 151 pair = self.data.pairs[n]
153 152 ax = self.axes[4 * n]
154 153 spc0 = 10.*numpy.log10(spc[pair[0]]/self.data.factor)
155 154 if ax.firsttime:
156 155 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
157 156 self.xmin = self.xmin if self.xmin else -self.xmax
158 157 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
159 158 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
160 159 ax.plt = ax.pcolormesh(x , y , spc0.T,
161 160 vmin=self.zmin,
162 161 vmax=self.zmax,
163 162 cmap=plt.get_cmap(self.colormap)
164 163 )
165 164 else:
166 165 ax.plt.set_array(spc0.T.ravel())
167 166 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise))
168 167
169 168 ax = self.axes[4 * n + 1]
170 169 spc1 = 10.*numpy.log10(spc[pair[1]]/self.data.factor)
171 170 if ax.firsttime:
172 171 ax.plt = ax.pcolormesh(x , y, spc1.T,
173 172 vmin=self.zmin,
174 173 vmax=self.zmax,
175 174 cmap=plt.get_cmap(self.colormap)
176 175 )
177 176 else:
178 177 ax.plt.set_array(spc1.T.ravel())
179 178 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise))
180 179
181 180 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
182 181 coh = numpy.abs(out)
183 182 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
184 183
185 184 ax = self.axes[4 * n + 2]
186 185 if ax.firsttime:
187 186 ax.plt = ax.pcolormesh(x, y, coh.T,
188 187 vmin=0,
189 188 vmax=1,
190 189 cmap=plt.get_cmap(self.colormap_coh)
191 190 )
192 191 else:
193 192 ax.plt.set_array(coh.T.ravel())
194 193 self.titles.append(
195 194 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
196 195
197 196 ax = self.axes[4 * n + 3]
198 197 if ax.firsttime:
199 198 ax.plt = ax.pcolormesh(x, y, phase.T,
200 199 vmin=-180,
201 200 vmax=180,
202 201 cmap=plt.get_cmap(self.colormap_phase)
203 202 )
204 203 else:
205 204 ax.plt.set_array(phase.T.ravel())
206 205 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
207 206
208 207
209 class SpectraMeanPlot(SpectraPlot):
208 class SpectralMomentsPlot(SpectraPlot):
210 209 '''
211 Plot for Spectra and Mean
210 Plot for Spectral Moments
212 211 '''
213 CODE = 'spc_mean'
212 CODE = 'spc_moments'
214 213 colormap = 'jro'
215 214
216 215
217 216 class RTIPlot(Plot):
218 217 '''
219 218 Plot for RTI data
220 219 '''
221 220
222 221 CODE = 'rti'
223 222 colormap = 'jro'
224 223
225 224 def setup(self):
226 225 self.xaxis = 'time'
227 226 self.ncols = 1
228 227 self.nrows = len(self.data.channels)
229 228 self.nplots = len(self.data.channels)
230 229 self.ylabel = 'Range [km]'
231 230 self.cb_label = 'dB'
232 231 self.titles = ['{} Channel {}'.format(
233 232 self.CODE.upper(), x) for x in range(self.nrows)]
234 233
235 234 def plot(self):
236 235 self.x = self.data.times
237 236 self.y = self.data.heights
238 237 self.z = self.data[self.CODE]
239 238 self.z = numpy.ma.masked_invalid(self.z)
240 239
241 240 if self.decimation is None:
242 241 x, y, z = self.fill_gaps(self.x, self.y, self.z)
243 242 else:
244 243 x, y, z = self.fill_gaps(*self.decimate())
245 244
246 245 for n, ax in enumerate(self.axes):
247 246 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
248 247 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
249 248 if ax.firsttime:
250 249 ax.plt = ax.pcolormesh(x, y, z[n].T,
251 250 vmin=self.zmin,
252 251 vmax=self.zmax,
253 252 cmap=plt.get_cmap(self.colormap)
254 253 )
255 254 if self.showprofile:
256 255 ax.plot_profile = self.pf_axes[n].plot(
257 256 self.data['rti'][n][-1], self.y)[0]
258 257 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
259 258 color="k", linestyle="dashed", lw=1)[0]
260 259 else:
261 260 ax.collections.remove(ax.collections[0])
262 261 ax.plt = ax.pcolormesh(x, y, z[n].T,
263 262 vmin=self.zmin,
264 263 vmax=self.zmax,
265 264 cmap=plt.get_cmap(self.colormap)
266 265 )
267 266 if self.showprofile:
268 267 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
269 268 ax.plot_noise.set_data(numpy.repeat(
270 269 self.data['noise'][n][-1], len(self.y)), self.y)
271 270
272 271
273 272 class CoherencePlot(RTIPlot):
274 273 '''
275 274 Plot for Coherence data
276 275 '''
277 276
278 277 CODE = 'coh'
279 278
280 279 def setup(self):
281 280 self.xaxis = 'time'
282 281 self.ncols = 1
283 282 self.nrows = len(self.data.pairs)
284 283 self.nplots = len(self.data.pairs)
285 284 self.ylabel = 'Range [km]'
286 285 if self.CODE == 'coh':
287 286 self.cb_label = ''
288 287 self.titles = [
289 288 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
290 289 else:
291 290 self.cb_label = 'Degrees'
292 291 self.titles = [
293 292 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
294 293
295 294
296 295 class PhasePlot(CoherencePlot):
297 296 '''
298 297 Plot for Phase map data
299 298 '''
300 299
301 300 CODE = 'phase'
302 301 colormap = 'seismic'
303 302
304 303
305 304 class NoisePlot(Plot):
306 305 '''
307 306 Plot for noise
308 307 '''
309 308
310 309 CODE = 'noise'
311 310
312 311 def setup(self):
313 312 self.xaxis = 'time'
314 313 self.ncols = 1
315 314 self.nrows = 1
316 315 self.nplots = 1
317 316 self.ylabel = 'Intensity [dB]'
318 317 self.titles = ['Noise']
319 318 self.colorbar = False
320 319
321 320 def plot(self):
322 321
323 322 x = self.data.times
324 323 xmin = self.data.min_time
325 324 xmax = xmin + self.xrange * 60 * 60
326 325 Y = self.data[self.CODE]
327 326
328 327 if self.axes[0].firsttime:
329 328 for ch in self.data.channels:
330 329 y = Y[ch]
331 330 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
332 331 plt.legend()
333 332 else:
334 333 for ch in self.data.channels:
335 334 y = Y[ch]
336 335 self.axes[0].lines[ch].set_data(x, y)
337 336
338 337 self.ymin = numpy.nanmin(Y) - 5
339 338 self.ymax = numpy.nanmax(Y) + 5
340 339
341 340
342 341 class SnrPlot(RTIPlot):
343 342 '''
344 343 Plot for SNR Data
345 344 '''
346 345
347 346 CODE = 'snr'
348 347 colormap = 'jet'
349 348
350 349
351 350 class DopplerPlot(RTIPlot):
352 351 '''
353 352 Plot for DOPPLER Data
354 353 '''
355 354
356 355 CODE = 'dop'
357 356 colormap = 'jet'
358 357
359 358
360 359 class SkyMapPlot(Plot):
361 360 '''
362 361 Plot for meteors detection data
363 362 '''
364 363
365 364 CODE = 'param'
366 365
367 366 def setup(self):
368 367
369 368 self.ncols = 1
370 369 self.nrows = 1
371 370 self.width = 7.2
372 371 self.height = 7.2
373 372 self.nplots = 1
374 373 self.xlabel = 'Zonal Zenith Angle (deg)'
375 374 self.ylabel = 'Meridional Zenith Angle (deg)'
376 375 self.polar = True
377 376 self.ymin = -180
378 377 self.ymax = 180
379 378 self.colorbar = False
380 379
381 380 def plot(self):
382 381
383 382 arrayParameters = numpy.concatenate(self.data['param'])
384 383 error = arrayParameters[:, -1]
385 384 indValid = numpy.where(error == 0)[0]
386 385 finalMeteor = arrayParameters[indValid, :]
387 386 finalAzimuth = finalMeteor[:, 3]
388 387 finalZenith = finalMeteor[:, 4]
389 388
390 389 x = finalAzimuth * numpy.pi / 180
391 390 y = finalZenith
392 391
393 392 ax = self.axes[0]
394 393
395 394 if ax.firsttime:
396 395 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
397 396 else:
398 397 ax.plot.set_data(x, y)
399 398
400 399 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
401 400 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
402 401 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
403 402 dt2,
404 403 len(x))
405 404 self.titles[0] = title
406 405
407 406
408 407 class ParametersPlot(RTIPlot):
409 408 '''
410 409 Plot for data_param object
411 410 '''
412 411
413 412 CODE = 'param'
414 413 colormap = 'seismic'
415 414
416 415 def setup(self):
417 416 self.xaxis = 'time'
418 417 self.ncols = 1
419 418 self.nrows = self.data.shape(self.CODE)[0]
420 419 self.nplots = self.nrows
421 420 if self.showSNR:
422 421 self.nrows += 1
423 422 self.nplots += 1
424 423
425 424 self.ylabel = 'Height [km]'
426 425 if not self.titles:
427 426 self.titles = self.data.parameters \
428 427 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
429 428 if self.showSNR:
430 429 self.titles.append('SNR')
431 430
432 431 def plot(self):
433 432 self.data.normalize_heights()
434 433 self.x = self.data.times
435 434 self.y = self.data.heights
436 435 if self.showSNR:
437 436 self.z = numpy.concatenate(
438 437 (self.data[self.CODE], self.data['snr'])
439 438 )
440 439 else:
441 440 self.z = self.data[self.CODE]
442 441
443 442 self.z = numpy.ma.masked_invalid(self.z)
444 443
445 444 if self.decimation is None:
446 445 x, y, z = self.fill_gaps(self.x, self.y, self.z)
447 446 else:
448 447 x, y, z = self.fill_gaps(*self.decimate())
449 448
450 449 for n, ax in enumerate(self.axes):
451 450
452 451 self.zmax = self.zmax if self.zmax is not None else numpy.max(
453 452 self.z[n])
454 453 self.zmin = self.zmin if self.zmin is not None else numpy.min(
455 454 self.z[n])
456 455
457 456 if ax.firsttime:
458 457 if self.zlimits is not None:
459 458 self.zmin, self.zmax = self.zlimits[n]
460 459
461 460 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
462 461 vmin=self.zmin,
463 462 vmax=self.zmax,
464 463 cmap=self.cmaps[n]
465 464 )
466 465 else:
467 466 if self.zlimits is not None:
468 467 self.zmin, self.zmax = self.zlimits[n]
469 468 ax.collections.remove(ax.collections[0])
470 469 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
471 470 vmin=self.zmin,
472 471 vmax=self.zmax,
473 472 cmap=self.cmaps[n]
474 473 )
475 474
476 475
477 476 class OutputPlot(ParametersPlot):
478 477 '''
479 478 Plot data_output object
480 479 '''
481 480
482 481 CODE = 'output'
483 482 colormap = 'seismic'
484 483
485 484
486 485 class PolarMapPlot(Plot):
487 486 '''
488 487 Plot for weather radar
489 488 '''
490 489
491 490 CODE = 'param'
492 491 colormap = 'seismic'
493 492
494 493 def setup(self):
495 494 self.ncols = 1
496 495 self.nrows = 1
497 496 self.width = 9
498 497 self.height = 8
499 498 self.mode = self.data.meta['mode']
500 499 if self.channels is not None:
501 500 self.nplots = len(self.channels)
502 501 self.nrows = len(self.channels)
503 502 else:
504 503 self.nplots = self.data.shape(self.CODE)[0]
505 504 self.nrows = self.nplots
506 505 self.channels = list(range(self.nplots))
507 506 if self.mode == 'E':
508 507 self.xlabel = 'Longitude'
509 508 self.ylabel = 'Latitude'
510 509 else:
511 510 self.xlabel = 'Range (km)'
512 511 self.ylabel = 'Height (km)'
513 512 self.bgcolor = 'white'
514 513 self.cb_labels = self.data.meta['units']
515 514 self.lat = self.data.meta['latitude']
516 515 self.lon = self.data.meta['longitude']
517 516 self.xmin, self.xmax = float(
518 517 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
519 518 self.ymin, self.ymax = float(
520 519 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
521 520 # self.polar = True
522 521
523 522 def plot(self):
524 523
525 524 for n, ax in enumerate(self.axes):
526 525 data = self.data['param'][self.channels[n]]
527 526
528 527 zeniths = numpy.linspace(
529 528 0, self.data.meta['max_range'], data.shape[1])
530 529 if self.mode == 'E':
531 530 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
532 531 r, theta = numpy.meshgrid(zeniths, azimuths)
533 532 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
534 533 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
535 534 x = km2deg(x) + self.lon
536 535 y = km2deg(y) + self.lat
537 536 else:
538 537 azimuths = numpy.radians(self.data.heights)
539 538 r, theta = numpy.meshgrid(zeniths, azimuths)
540 539 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
541 540 self.y = zeniths
542 541
543 542 if ax.firsttime:
544 543 if self.zlimits is not None:
545 544 self.zmin, self.zmax = self.zlimits[n]
546 545 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
547 546 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
548 547 vmin=self.zmin,
549 548 vmax=self.zmax,
550 549 cmap=self.cmaps[n])
551 550 else:
552 551 if self.zlimits is not None:
553 552 self.zmin, self.zmax = self.zlimits[n]
554 553 ax.collections.remove(ax.collections[0])
555 554 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
556 555 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
557 556 vmin=self.zmin,
558 557 vmax=self.zmax,
559 558 cmap=self.cmaps[n])
560 559
561 560 if self.mode == 'A':
562 561 continue
563 562
564 563 # plot district names
565 564 f = open('/data/workspace/schain_scripts/distrito.csv')
566 565 for line in f:
567 566 label, lon, lat = [s.strip() for s in line.split(',') if s]
568 567 lat = float(lat)
569 568 lon = float(lon)
570 569 # ax.plot(lon, lat, '.b', ms=2)
571 570 ax.text(lon, lat, label.decode('utf8'), ha='center',
572 571 va='bottom', size='8', color='black')
573 572
574 573 # plot limites
575 574 limites = []
576 575 tmp = []
577 576 for line in open('/data/workspace/schain_scripts/lima.csv'):
578 577 if '#' in line:
579 578 if tmp:
580 579 limites.append(tmp)
581 580 tmp = []
582 581 continue
583 582 values = line.strip().split(',')
584 583 tmp.append((float(values[0]), float(values[1])))
585 584 for points in limites:
586 585 ax.add_patch(
587 586 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
588 587
589 588 # plot Cuencas
590 589 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
591 590 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
592 591 values = [line.strip().split(',') for line in f]
593 592 points = [(float(s[0]), float(s[1])) for s in values]
594 593 ax.add_patch(Polygon(points, ec='b', fc='none'))
595 594
596 595 # plot grid
597 596 for r in (15, 30, 45, 60):
598 597 ax.add_artist(plt.Circle((self.lon, self.lat),
599 598 km2deg(r), color='0.6', fill=False, lw=0.2))
600 599 ax.text(
601 600 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
602 601 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
603 602 '{}km'.format(r),
604 603 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
605 604
606 605 if self.mode == 'E':
607 606 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
608 607 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
609 608 else:
610 609 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
611 610 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
612 611
613 612 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
614 613 self.titles = ['{} {}'.format(
615 614 self.data.parameters[x], title) for x in self.channels]
616 615
617 616 class ScopePlot(Plot):
618 617
619 618 '''
620 619 Plot for Scope
621 620 '''
622 621
623 622 CODE = 'scope'
624 623
625 624 def setup(self):
626 625
627 626 self.xaxis = 'Range (Km)'
628 627 self.ncols = 1
629 628 self.nrows = 1
630 629 self.nplots = 1
631 630 self.ylabel = 'Intensity [dB]'
632 631 self.titles = ['Scope']
633 632 self.colorbar = False
634 633 colspan = 3
635 634 rowspan = 1
636 635
637 636 def plot_iq(self, x, y, channelIndexList, thisDatetime, wintitle):
638 637
639 638 yreal = y[channelIndexList,:].real
640 639 yimag = y[channelIndexList,:].imag
641 640 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
642 641 self.xlabel = "Range (Km)"
643 642 self.ylabel = "Intensity - IQ"
644 643
645 644 self.y = yreal
646 645 self.x = x
647 646 self.xmin = min(x)
648 647 self.xmax = max(x)
649 648
650 649
651 650 self.titles[0] = title
652 651
653 652 for i,ax in enumerate(self.axes):
654 653 title = "Channel %d" %(i)
655 654 if ax.firsttime:
656 655 ax.plt_r = ax.plot(x, yreal[i,:], color='b')[0]
657 656 ax.plt_i = ax.plot(x, yimag[i,:], color='r')[0]
658 657 else:
659 658 #pass
660 659 ax.plt_r.set_data(x, yreal[i,:])
661 660 ax.plt_i.set_data(x, yimag[i,:])
662 661
663 662 def plot_power(self, x, y, channelIndexList, thisDatetime, wintitle):
664 663 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
665 664 yreal = y.real
666 665 self.y = yreal
667 666 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
668 667 self.xlabel = "Range (Km)"
669 668 self.ylabel = "Intensity"
670 669 self.xmin = min(x)
671 670 self.xmax = max(x)
672 671
673 672
674 673 self.titles[0] = title
675 674
676 675 for i,ax in enumerate(self.axes):
677 676 title = "Channel %d" %(i)
678 677
679 678 ychannel = yreal[i,:]
680 679
681 680 if ax.firsttime:
682 681 ax.plt_r = ax.plot(x, ychannel)[0]
683 682 else:
684 683 #pass
685 684 ax.plt_r.set_data(x, ychannel)
686 685
687 686
688 687 def plot(self):
689 688
690 689 if self.channels:
691 690 channels = self.channels
692 691 else:
693 692 channels = self.data.channels
694 693
695 694
696 695
697 696 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
698 697
699 698 scope = self.data['scope']
700 699
701 700
702 701 if self.data.flagDataAsBlock:
703 702
704 703 for i in range(self.data.nProfiles):
705 704
706 705 wintitle1 = " [Profile = %d] " %i
707 706
708 707 if self.type == "power":
709 708 self.plot_power(self.data.heights,
710 709 scope[:,i,:],
711 710 channels,
712 711 thisDatetime,
713 712 wintitle1
714 713 )
715 714
716 715 if self.type == "iq":
717 716 self.plot_iq(self.data.heights,
718 717 scope[:,i,:],
719 718 channels,
720 719 thisDatetime,
721 720 wintitle1
722 721 )
723 722
724 723
725 724
726 725
727 726
728 727 else:
729 728 wintitle = " [Profile = %d] " %self.data.profileIndex
730 729
731 730 if self.type == "power":
732 731 self.plot_power(self.data.heights,
733 732 scope,
734 733 channels,
735 734 thisDatetime,
736 735 wintitle
737 736 )
738 737
739 738 if self.type == "iq":
740 739 self.plot_iq(self.data.heights,
741 740 scope,
742 741 channels,
743 742 thisDatetime,
744 743 wintitle
745 744 )
746 745
747 746
748 747 No newline at end of file
@@ -1,2394 +1,2394
1 1 import os
2 2 import datetime
3 3 import numpy
4 4 import inspect
5 5 from .figure import Figure, isRealtime, isTimeInHourRange
6 6 from .plotting_codes import *
7 7 from schainpy.model.proc.jroproc_base import MPDecorator
8 8 from schainpy.utils import log
9 9
10 10 class ParamLine_(Figure):
11 11
12 12 isConfig = None
13 13
14 14 def __init__(self):
15 15
16 16 self.isConfig = False
17 17 self.WIDTH = 300
18 18 self.HEIGHT = 200
19 19 self.counter_imagwr = 0
20 20
21 21 def getSubplots(self):
22 22
23 23 nrow = self.nplots
24 24 ncol = 3
25 25 return nrow, ncol
26 26
27 27 def setup(self, id, nplots, wintitle, show):
28 28
29 29 self.nplots = nplots
30 30
31 31 self.createFigure(id=id,
32 32 wintitle=wintitle,
33 33 show=show)
34 34
35 35 nrow,ncol = self.getSubplots()
36 36 colspan = 3
37 37 rowspan = 1
38 38
39 39 for i in range(nplots):
40 40 self.addAxes(nrow, ncol, i, 0, colspan, rowspan)
41 41
42 42 def plot_iq(self, x, y, id, channelIndexList, thisDatetime, wintitle, show, xmin, xmax, ymin, ymax):
43 43 yreal = y[channelIndexList,:].real
44 44 yimag = y[channelIndexList,:].imag
45 45
46 46 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
47 47 xlabel = "Range (Km)"
48 48 ylabel = "Intensity - IQ"
49 49
50 50 if not self.isConfig:
51 51 nplots = len(channelIndexList)
52 52
53 53 self.setup(id=id,
54 54 nplots=nplots,
55 55 wintitle='',
56 56 show=show)
57 57
58 58 if xmin == None: xmin = numpy.nanmin(x)
59 59 if xmax == None: xmax = numpy.nanmax(x)
60 60 if ymin == None: ymin = min(numpy.nanmin(yreal),numpy.nanmin(yimag))
61 61 if ymax == None: ymax = max(numpy.nanmax(yreal),numpy.nanmax(yimag))
62 62
63 63 self.isConfig = True
64 64
65 65 self.setWinTitle(title)
66 66
67 67 for i in range(len(self.axesList)):
68 68 title = "Channel %d" %(i)
69 69 axes = self.axesList[i]
70 70
71 71 axes.pline(x, yreal[i,:],
72 72 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
73 73 xlabel=xlabel, ylabel=ylabel, title=title)
74 74
75 75 axes.addpline(x, yimag[i,:], idline=1, color="red", linestyle="solid", lw=2)
76 76
77 77 def plot_power(self, x, y, id, channelIndexList, thisDatetime, wintitle, show, xmin, xmax, ymin, ymax):
78 78 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
79 79 yreal = y.real
80 80
81 81 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
82 82 xlabel = "Range (Km)"
83 83 ylabel = "Intensity"
84 84
85 85 if not self.isConfig:
86 86 nplots = len(channelIndexList)
87 87
88 88 self.setup(id=id,
89 89 nplots=nplots,
90 90 wintitle='',
91 91 show=show)
92 92
93 93 if xmin == None: xmin = numpy.nanmin(x)
94 94 if xmax == None: xmax = numpy.nanmax(x)
95 95 if ymin == None: ymin = numpy.nanmin(yreal)
96 96 if ymax == None: ymax = numpy.nanmax(yreal)
97 97
98 98 self.isConfig = True
99 99
100 100 self.setWinTitle(title)
101 101
102 102 for i in range(len(self.axesList)):
103 103 title = "Channel %d" %(i)
104 104 axes = self.axesList[i]
105 105 ychannel = yreal[i,:]
106 106 axes.pline(x, ychannel,
107 107 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
108 108 xlabel=xlabel, ylabel=ylabel, title=title)
109 109
110 110
111 111 def run(self, dataOut, id, wintitle="", channelList=None,
112 112 xmin=None, xmax=None, ymin=None, ymax=None, save=False,
113 113 figpath='./', figfile=None, show=True, wr_period=1,
114 114 ftp=False, server=None, folder=None, username=None, password=None):
115 115
116 116 """
117 117
118 118 Input:
119 119 dataOut :
120 120 id :
121 121 wintitle :
122 122 channelList :
123 123 xmin : None,
124 124 xmax : None,
125 125 ymin : None,
126 126 ymax : None,
127 127 """
128 128
129 129 if channelList == None:
130 130 channelIndexList = dataOut.channelIndexList
131 131 else:
132 132 channelIndexList = []
133 133 for channel in channelList:
134 134 if channel not in dataOut.channelList:
135 135 raise ValueError("Channel %d is not in dataOut.channelList" % channel)
136 136 channelIndexList.append(dataOut.channelList.index(channel))
137 137
138 138 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
139 139
140 140 y = dataOut.RR
141 141
142 142 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
143 143 xlabel = "Range (Km)"
144 144 ylabel = "Intensity"
145 145
146 146 if not self.isConfig:
147 147 nplots = len(channelIndexList)
148 148
149 149 self.setup(id=id,
150 150 nplots=nplots,
151 151 wintitle='',
152 152 show=show)
153 153
154 154 if xmin == None: xmin = numpy.nanmin(x)
155 155 if xmax == None: xmax = numpy.nanmax(x)
156 156 if ymin == None: ymin = numpy.nanmin(y)
157 157 if ymax == None: ymax = numpy.nanmax(y)
158 158
159 159 self.isConfig = True
160 160
161 161 self.setWinTitle(title)
162 162
163 163 for i in range(len(self.axesList)):
164 164 title = "Channel %d" %(i)
165 165 axes = self.axesList[i]
166 166 ychannel = y[i,:]
167 167 axes.pline(x, ychannel,
168 168 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
169 169 xlabel=xlabel, ylabel=ylabel, title=title)
170 170
171 171
172 172 self.draw()
173 173
174 174 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S") + "_" + str(dataOut.profileIndex)
175 175 figfile = self.getFilename(name = str_datetime)
176 176
177 177 self.save(figpath=figpath,
178 178 figfile=figfile,
179 179 save=save,
180 180 ftp=ftp,
181 181 wr_period=wr_period,
182 182 thisDatetime=thisDatetime)
183 183
184 184
185 185
186 186 class SpcParamPlot_(Figure):
187 187
188 188 isConfig = None
189 189 __nsubplots = None
190 190
191 191 WIDTHPROF = None
192 192 HEIGHTPROF = None
193 193 PREFIX = 'SpcParam'
194 194
195 195 def __init__(self, **kwargs):
196 196 Figure.__init__(self, **kwargs)
197 197 self.isConfig = False
198 198 self.__nsubplots = 1
199 199
200 200 self.WIDTH = 250
201 201 self.HEIGHT = 250
202 202 self.WIDTHPROF = 120
203 203 self.HEIGHTPROF = 0
204 204 self.counter_imagwr = 0
205 205
206 206 self.PLOT_CODE = SPEC_CODE
207 207
208 208 self.FTP_WEI = None
209 209 self.EXP_CODE = None
210 210 self.SUB_EXP_CODE = None
211 211 self.PLOT_POS = None
212 212
213 213 self.__xfilter_ena = False
214 214 self.__yfilter_ena = False
215 215
216 216 def getSubplots(self):
217 217
218 218 ncol = int(numpy.sqrt(self.nplots)+0.9)
219 219 nrow = int(self.nplots*1./ncol + 0.9)
220 220
221 221 return nrow, ncol
222 222
223 223 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
224 224
225 225 self.__showprofile = showprofile
226 226 self.nplots = nplots
227 227
228 228 ncolspan = 1
229 229 colspan = 1
230 230 if showprofile:
231 231 ncolspan = 3
232 232 colspan = 2
233 233 self.__nsubplots = 2
234 234
235 235 self.createFigure(id = id,
236 236 wintitle = wintitle,
237 237 widthplot = self.WIDTH + self.WIDTHPROF,
238 238 heightplot = self.HEIGHT + self.HEIGHTPROF,
239 239 show=show)
240 240
241 241 nrow, ncol = self.getSubplots()
242 242
243 243 counter = 0
244 244 for y in range(nrow):
245 245 for x in range(ncol):
246 246
247 247 if counter >= self.nplots:
248 248 break
249 249
250 250 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
251 251
252 252 if showprofile:
253 253 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
254 254
255 255 counter += 1
256 256
257 257 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
258 258 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
259 259 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
260 260 server=None, folder=None, username=None, password=None,
261 261 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
262 262 xaxis="frequency", colormap='jet', normFactor=None , Selector = 0):
263 263
264 264 """
265 265
266 266 Input:
267 267 dataOut :
268 268 id :
269 269 wintitle :
270 270 channelList :
271 271 showProfile :
272 272 xmin : None,
273 273 xmax : None,
274 274 ymin : None,
275 275 ymax : None,
276 276 zmin : None,
277 277 zmax : None
278 278 """
279 279 if realtime:
280 280 if not(isRealtime(utcdatatime = dataOut.utctime)):
281 281 print('Skipping this plot function')
282 282 return
283 283
284 284 if channelList == None:
285 285 channelIndexList = dataOut.channelIndexList
286 286 else:
287 287 channelIndexList = []
288 288 for channel in channelList:
289 289 if channel not in dataOut.channelList:
290 290 raise ValueError("Channel %d is not in dataOut.channelList" %channel)
291 291 channelIndexList.append(dataOut.channelList.index(channel))
292 292
293 # if normFactor is None:
294 # factor = dataOut.normFactor
295 # else:
296 # factor = normFactor
293 # if normFactor is None:
294 # factor = dataOut.normFactor
295 # else:
296 # factor = normFactor
297 297 if xaxis == "frequency":
298 298 x = dataOut.spcparam_range[0]
299 299 xlabel = "Frequency (kHz)"
300 300
301 301 elif xaxis == "time":
302 302 x = dataOut.spcparam_range[1]
303 303 xlabel = "Time (ms)"
304 304
305 305 else:
306 306 x = dataOut.spcparam_range[2]
307 307 xlabel = "Velocity (m/s)"
308 308
309 309 ylabel = "Range (km)"
310 310
311 311 y = dataOut.getHeiRange()
312 312
313 313 z = dataOut.SPCparam[Selector] /1966080.0#/ dataOut.normFactor#GauSelector] #dataOut.data_spc/factor
314 314 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
315 315 zdB = 10*numpy.log10(z)
316 316
317 317 avg = numpy.average(z, axis=1)
318 318 avgdB = 10*numpy.log10(avg)
319 319
320 320 noise = dataOut.spc_noise
321 321 noisedB = 10*numpy.log10(noise)
322 322
323 323 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
324 324 title = wintitle + " Spectra"
325 325 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
326 326 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
327 327
328 328 if not self.isConfig:
329 329
330 330 nplots = len(channelIndexList)
331 331
332 332 self.setup(id=id,
333 333 nplots=nplots,
334 334 wintitle=wintitle,
335 335 showprofile=showprofile,
336 336 show=show)
337 337
338 338 if xmin == None: xmin = numpy.nanmin(x)
339 339 if xmax == None: xmax = numpy.nanmax(x)
340 340 if ymin == None: ymin = numpy.nanmin(y)
341 341 if ymax == None: ymax = numpy.nanmax(y)
342 342 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
343 343 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
344 344
345 345 self.FTP_WEI = ftp_wei
346 346 self.EXP_CODE = exp_code
347 347 self.SUB_EXP_CODE = sub_exp_code
348 348 self.PLOT_POS = plot_pos
349 349
350 350 self.isConfig = True
351 351
352 352 self.setWinTitle(title)
353 353
354 354 for i in range(self.nplots):
355 355 index = channelIndexList[i]
356 356 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
357 357 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime)
358 358 if len(dataOut.beam.codeList) != 0:
359 359 title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime)
360 360
361 361 axes = self.axesList[i*self.__nsubplots]
362 362 axes.pcolor(x, y, zdB[index,:,:],
363 363 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
364 364 xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap,
365 365 ticksize=9, cblabel='')
366 366
367 367 if self.__showprofile:
368 368 axes = self.axesList[i*self.__nsubplots +1]
369 369 axes.pline(avgdB[index,:], y,
370 370 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
371 371 xlabel='dB', ylabel='', title='',
372 372 ytick_visible=False,
373 373 grid='x')
374 374
375 375 noiseline = numpy.repeat(noisedB[index], len(y))
376 376 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
377 377
378 378 self.draw()
379 379
380 380 if figfile == None:
381 381 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
382 382 name = str_datetime
383 383 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
384 384 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
385 385 figfile = self.getFilename(name)
386 386
387 387 self.save(figpath=figpath,
388 388 figfile=figfile,
389 389 save=save,
390 390 ftp=ftp,
391 391 wr_period=wr_period,
392 392 thisDatetime=thisDatetime)
393 393
394 394
395 395
396 396 class MomentsPlot_(Figure):
397 397
398 398 isConfig = None
399 399 __nsubplots = None
400 400
401 401 WIDTHPROF = None
402 402 HEIGHTPROF = None
403 403 PREFIX = 'prm'
404 404 def __init__(self):
405 405 Figure.__init__(self)
406 406 self.isConfig = False
407 407 self.__nsubplots = 1
408 408
409 409 self.WIDTH = 280
410 410 self.HEIGHT = 250
411 411 self.WIDTHPROF = 120
412 412 self.HEIGHTPROF = 0
413 413 self.counter_imagwr = 0
414 414
415 415 self.PLOT_CODE = MOMENTS_CODE
416 416
417 417 self.FTP_WEI = None
418 418 self.EXP_CODE = None
419 419 self.SUB_EXP_CODE = None
420 420 self.PLOT_POS = None
421 421
422 422 def getSubplots(self):
423 423
424 424 ncol = int(numpy.sqrt(self.nplots)+0.9)
425 425 nrow = int(self.nplots*1./ncol + 0.9)
426 426
427 427 return nrow, ncol
428 428
429 429 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
430 430
431 431 self.__showprofile = showprofile
432 432 self.nplots = nplots
433 433
434 434 ncolspan = 1
435 435 colspan = 1
436 436 if showprofile:
437 437 ncolspan = 3
438 438 colspan = 2
439 439 self.__nsubplots = 2
440 440
441 441 self.createFigure(id = id,
442 442 wintitle = wintitle,
443 443 widthplot = self.WIDTH + self.WIDTHPROF,
444 444 heightplot = self.HEIGHT + self.HEIGHTPROF,
445 445 show=show)
446 446
447 447 nrow, ncol = self.getSubplots()
448 448
449 449 counter = 0
450 450 for y in range(nrow):
451 451 for x in range(ncol):
452 452
453 453 if counter >= self.nplots:
454 454 break
455 455
456 456 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
457 457
458 458 if showprofile:
459 459 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
460 460
461 461 counter += 1
462 462
463 463 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
464 464 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
465 465 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
466 466 server=None, folder=None, username=None, password=None,
467 467 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
468 468
469 469 """
470 470
471 471 Input:
472 472 dataOut :
473 473 id :
474 474 wintitle :
475 475 channelList :
476 476 showProfile :
477 477 xmin : None,
478 478 xmax : None,
479 479 ymin : None,
480 480 ymax : None,
481 481 zmin : None,
482 482 zmax : None
483 483 """
484 484
485 485 if dataOut.flagNoData:
486 486 return None
487 487
488 488 if realtime:
489 489 if not(isRealtime(utcdatatime = dataOut.utctime)):
490 490 print('Skipping this plot function')
491 491 return
492 492
493 493 if channelList == None:
494 494 channelIndexList = dataOut.channelIndexList
495 495 else:
496 496 channelIndexList = []
497 497 for channel in channelList:
498 498 if channel not in dataOut.channelList:
499 499 raise ValueError("Channel %d is not in dataOut.channelList")
500 500 channelIndexList.append(dataOut.channelList.index(channel))
501 501
502 502 factor = dataOut.normFactor
503 503 x = dataOut.abscissaList
504 504 y = dataOut.heightList
505 505
506 506 z = dataOut.data_pre[channelIndexList,:,:]/factor
507 507 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
508 508 avg = numpy.average(z, axis=1)
509 509 noise = dataOut.noise/factor
510 510
511 511 zdB = 10*numpy.log10(z)
512 512 avgdB = 10*numpy.log10(avg)
513 513 noisedB = 10*numpy.log10(noise)
514 514
515 515 #thisDatetime = dataOut.datatime
516 516 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
517 517 title = wintitle + " Parameters"
518 518 xlabel = "Velocity (m/s)"
519 519 ylabel = "Range (Km)"
520 520
521 521 update_figfile = False
522 522
523 523 if not self.isConfig:
524 524
525 525 nplots = len(channelIndexList)
526 526
527 527 self.setup(id=id,
528 528 nplots=nplots,
529 529 wintitle=wintitle,
530 530 showprofile=showprofile,
531 531 show=show)
532 532
533 533 if xmin == None: xmin = numpy.nanmin(x)
534 534 if xmax == None: xmax = numpy.nanmax(x)
535 535 if ymin == None: ymin = numpy.nanmin(y)
536 536 if ymax == None: ymax = numpy.nanmax(y)
537 537 if zmin == None: zmin = numpy.nanmin(avgdB)*0.9
538 538 if zmax == None: zmax = numpy.nanmax(avgdB)*0.9
539 539
540 540 self.FTP_WEI = ftp_wei
541 541 self.EXP_CODE = exp_code
542 542 self.SUB_EXP_CODE = sub_exp_code
543 543 self.PLOT_POS = plot_pos
544 544
545 545 self.isConfig = True
546 546 update_figfile = True
547 547
548 548 self.setWinTitle(title)
549 549
550 550 for i in range(self.nplots):
551 551 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
552 552 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[i], noisedB[i], str_datetime)
553 553 axes = self.axesList[i*self.__nsubplots]
554 554 axes.pcolor(x, y, zdB[i,:,:],
555 555 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
556 556 xlabel=xlabel, ylabel=ylabel, title=title,
557 557 ticksize=9, cblabel='')
558 558 #Mean Line
559 559 mean = dataOut.data_param[i, 1, :]
560 560 axes.addpline(mean, y, idline=0, color="black", linestyle="solid", lw=1)
561 561
562 562 if self.__showprofile:
563 563 axes = self.axesList[i*self.__nsubplots +1]
564 564 axes.pline(avgdB[i], y,
565 565 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
566 566 xlabel='dB', ylabel='', title='',
567 567 ytick_visible=False,
568 568 grid='x')
569 569
570 570 noiseline = numpy.repeat(noisedB[i], len(y))
571 571 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
572 572
573 573 self.draw()
574 574
575 575 self.save(figpath=figpath,
576 576 figfile=figfile,
577 577 save=save,
578 578 ftp=ftp,
579 579 wr_period=wr_period,
580 580 thisDatetime=thisDatetime)
581 581
582 582
583 583 class SkyMapPlot_(Figure):
584 584
585 585 __isConfig = None
586 586 __nsubplots = None
587 587
588 588 WIDTHPROF = None
589 589 HEIGHTPROF = None
590 590 PREFIX = 'mmap'
591 591
592 592 def __init__(self, **kwargs):
593 593 Figure.__init__(self, **kwargs)
594 594 self.isConfig = False
595 595 self.__nsubplots = 1
596 596
597 # self.WIDTH = 280
598 # self.HEIGHT = 250
597 # self.WIDTH = 280
598 # self.HEIGHT = 250
599 599 self.WIDTH = 600
600 600 self.HEIGHT = 600
601 601 self.WIDTHPROF = 120
602 602 self.HEIGHTPROF = 0
603 603 self.counter_imagwr = 0
604 604
605 605 self.PLOT_CODE = MSKYMAP_CODE
606 606
607 607 self.FTP_WEI = None
608 608 self.EXP_CODE = None
609 609 self.SUB_EXP_CODE = None
610 610 self.PLOT_POS = None
611 611
612 612 def getSubplots(self):
613 613
614 614 ncol = int(numpy.sqrt(self.nplots)+0.9)
615 615 nrow = int(self.nplots*1./ncol + 0.9)
616 616
617 617 return nrow, ncol
618 618
619 619 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
620 620
621 621 self.__showprofile = showprofile
622 622 self.nplots = nplots
623 623
624 624 ncolspan = 1
625 625 colspan = 1
626 626
627 627 self.createFigure(id = id,
628 628 wintitle = wintitle,
629 629 widthplot = self.WIDTH, #+ self.WIDTHPROF,
630 630 heightplot = self.HEIGHT,# + self.HEIGHTPROF,
631 631 show=show)
632 632
633 633 nrow, ncol = 1,1
634 634 counter = 0
635 635 x = 0
636 636 y = 0
637 637 self.addAxes(1, 1, 0, 0, 1, 1, True)
638 638
639 639 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
640 640 tmin=0, tmax=24, timerange=None,
641 641 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
642 642 server=None, folder=None, username=None, password=None,
643 643 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
644 644
645 645 """
646 646
647 647 Input:
648 648 dataOut :
649 649 id :
650 650 wintitle :
651 651 channelList :
652 652 showProfile :
653 653 xmin : None,
654 654 xmax : None,
655 655 ymin : None,
656 656 ymax : None,
657 657 zmin : None,
658 658 zmax : None
659 659 """
660 660
661 661 arrayParameters = dataOut.data_param
662 662 error = arrayParameters[:,-1]
663 663 indValid = numpy.where(error == 0)[0]
664 664 finalMeteor = arrayParameters[indValid,:]
665 665 finalAzimuth = finalMeteor[:,3]
666 666 finalZenith = finalMeteor[:,4]
667 667
668 668 x = finalAzimuth*numpy.pi/180
669 669 y = finalZenith
670 670 x1 = [dataOut.ltctime, dataOut.ltctime]
671 671
672 672 #thisDatetime = dataOut.datatime
673 673 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
674 674 title = wintitle + " Parameters"
675 675 xlabel = "Zonal Zenith Angle (deg) "
676 676 ylabel = "Meridional Zenith Angle (deg)"
677 677 update_figfile = False
678 678
679 679 if not self.isConfig:
680 680
681 681 nplots = 1
682 682
683 683 self.setup(id=id,
684 684 nplots=nplots,
685 685 wintitle=wintitle,
686 686 showprofile=showprofile,
687 687 show=show)
688 688
689 689 if self.xmin is None and self.xmax is None:
690 690 self.xmin, self.xmax = self.getTimeLim(x1, tmin, tmax, timerange)
691 691
692 692 if timerange != None:
693 693 self.timerange = timerange
694 694 else:
695 695 self.timerange = self.xmax - self.xmin
696 696
697 697 self.FTP_WEI = ftp_wei
698 698 self.EXP_CODE = exp_code
699 699 self.SUB_EXP_CODE = sub_exp_code
700 700 self.PLOT_POS = plot_pos
701 701 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
702 702 self.firstdate = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
703 703 self.isConfig = True
704 704 update_figfile = True
705 705
706 706 self.setWinTitle(title)
707 707
708 708 i = 0
709 709 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
710 710
711 711 axes = self.axesList[i*self.__nsubplots]
712 712 nevents = axes.x_buffer.shape[0] + x.shape[0]
713 713 title = "Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n" %(self.firstdate,str_datetime,nevents)
714 714 axes.polar(x, y,
715 715 title=title, xlabel=xlabel, ylabel=ylabel,
716 716 ticksize=9, cblabel='')
717 717
718 718 self.draw()
719 719
720 720 self.save(figpath=figpath,
721 721 figfile=figfile,
722 722 save=save,
723 723 ftp=ftp,
724 724 wr_period=wr_period,
725 725 thisDatetime=thisDatetime,
726 726 update_figfile=update_figfile)
727 727
728 728 if dataOut.ltctime >= self.xmax:
729 729 self.isConfigmagwr = wr_period
730 730 self.isConfig = False
731 731 update_figfile = True
732 732 axes.__firsttime = True
733 733 self.xmin += self.timerange
734 734 self.xmax += self.timerange
735 735
736 736
737 737
738 738 @MPDecorator
739 739 class WindProfilerPlot_(Figure):
740 740
741 741 __isConfig = None
742 742 __nsubplots = None
743 743
744 744 WIDTHPROF = None
745 745 HEIGHTPROF = None
746 746 PREFIX = 'wind'
747 747
748 748 def __init__(self):
749 749 Figure.__init__(self)
750 750 self.timerange = None
751 751 self.isConfig = False
752 752 self.__nsubplots = 1
753 753
754 754 self.WIDTH = 800
755 755 self.HEIGHT = 300
756 756 self.WIDTHPROF = 120
757 757 self.HEIGHTPROF = 0
758 758 self.counter_imagwr = 0
759 759
760 760 self.PLOT_CODE = WIND_CODE
761 761
762 762 self.FTP_WEI = None
763 763 self.EXP_CODE = None
764 764 self.SUB_EXP_CODE = None
765 765 self.PLOT_POS = None
766 766 self.tmin = None
767 767 self.tmax = None
768 768
769 769 self.xmin = None
770 770 self.xmax = None
771 771
772 772 self.figfile = None
773 773
774 774 def getSubplots(self):
775 775
776 776 ncol = 1
777 777 nrow = self.nplots
778 778
779 779 return nrow, ncol
780 780
781 781 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
782 782
783 783 self.__showprofile = showprofile
784 784 self.nplots = nplots
785 785
786 786 ncolspan = 1
787 787 colspan = 1
788 788
789 789 self.createFigure(id = id,
790 790 wintitle = wintitle,
791 791 widthplot = self.WIDTH + self.WIDTHPROF,
792 792 heightplot = self.HEIGHT + self.HEIGHTPROF,
793 793 show=show)
794 794
795 795 nrow, ncol = self.getSubplots()
796 796
797 797 counter = 0
798 798 for y in range(nrow):
799 799 if counter >= self.nplots:
800 800 break
801 801
802 802 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
803 803 counter += 1
804 804
805 805 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='False',
806 806 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
807 807 zmax_ver = None, zmin_ver = None, SNRmin = None, SNRmax = None,
808 808 timerange=None, SNRthresh = None,
809 809 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
810 810 server=None, folder=None, username=None, password=None,
811 811 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
812 812 """
813 813
814 814 Input:
815 815 dataOut :
816 816 id :
817 817 wintitle :
818 818 channelList :
819 819 showProfile :
820 820 xmin : None,
821 821 xmax : None,
822 822 ymin : None,
823 823 ymax : None,
824 824 zmin : None,
825 825 zmax : None
826 826 """
827 827
828 828 if dataOut.flagNoData:
829 829 return dataOut
830 830
831 # if timerange is not None:
832 # self.timerange = timerange
833 #
834 # tmin = None
835 # tmax = None
831 # if timerange is not None:
832 # self.timerange = timerange
833 #
834 # tmin = None
835 # tmax = None
836 836
837 837 x = dataOut.getTimeRange1(dataOut.paramInterval)
838 838 y = dataOut.heightList
839 839 z = dataOut.data_output.copy()
840 840 nplots = z.shape[0] #Number of wind dimensions estimated
841 841 nplotsw = nplots
842 842
843 843
844 844 #If there is a SNR function defined
845 845 if dataOut.data_SNR is not None:
846 846 nplots += 1
847 847 SNR = dataOut.data_SNR[0]
848 848 SNRavg = SNR#numpy.average(SNR, axis=0)
849 849
850 850 SNRdB = 10*numpy.log10(SNR)
851 851 SNRavgdB = 10*numpy.log10(SNRavg)
852 852
853 853 if SNRthresh == None:
854 854 SNRthresh = -5.0
855 855 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
856 856
857 857 for i in range(nplotsw):
858 858 z[i,ind] = numpy.nan
859 859
860 860 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
861 861 #thisDatetime = datetime.datetime.now()
862 862 title = wintitle + "Wind"
863 863 xlabel = ""
864 864 ylabel = "Height (km)"
865 865 update_figfile = False
866 866
867 867 if not self.isConfig:
868 868
869 869 self.setup(id=id,
870 870 nplots=nplots,
871 871 wintitle=wintitle,
872 872 showprofile=showprofile,
873 873 show=show)
874 874
875 875 if timerange is not None:
876 876 self.timerange = timerange
877 877
878 878 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
879 879
880 880 if ymin == None: ymin = numpy.nanmin(y)
881 881 if ymax == None: ymax = numpy.nanmax(y)
882 882
883 883 if zmax == None: zmax = numpy.nanmax(abs(z[list(range(2)),:]))
884 884 #if numpy.isnan(zmax): zmax = 50
885 885 if zmin == None: zmin = -zmax
886 886
887 887 if nplotsw == 3:
888 888 if zmax_ver == None: zmax_ver = numpy.nanmax(abs(z[2,:]))
889 889 if zmin_ver == None: zmin_ver = -zmax_ver
890 890
891 891 if dataOut.data_SNR is not None:
892 892 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
893 893 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
894 894
895 895
896 896 self.FTP_WEI = ftp_wei
897 897 self.EXP_CODE = exp_code
898 898 self.SUB_EXP_CODE = sub_exp_code
899 899 self.PLOT_POS = plot_pos
900 900
901 901 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
902 902 self.isConfig = True
903 903 self.figfile = figfile
904 904 update_figfile = True
905 905
906 906 self.setWinTitle(title)
907 907
908 908 if ((self.xmax - x[1]) < (x[1]-x[0])):
909 909 x[1] = self.xmax
910 910
911 911 strWind = ['Zonal', 'Meridional', 'Vertical']
912 912 strCb = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
913 913 zmaxVector = [zmax, zmax, zmax_ver]
914 914 zminVector = [zmin, zmin, zmin_ver]
915 915 windFactor = [1,1,100]
916 916
917 917 for i in range(nplotsw):
918 918
919 919 title = "%s Wind: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
920 920 axes = self.axesList[i*self.__nsubplots]
921 921
922 922 z1 = z[i,:].reshape((1,-1))*windFactor[i]
923 923
924 924 axes.pcolorbuffer(x, y, z1,
925 925 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
926 926 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
927 927 ticksize=9, cblabel=strCb[i], cbsize="1%", colormap="seismic" )
928 928
929 929 if dataOut.data_SNR is not None:
930 930 i += 1
931 931 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
932 932 axes = self.axesList[i*self.__nsubplots]
933 933 SNRavgdB = SNRavgdB.reshape((1,-1))
934 934 axes.pcolorbuffer(x, y, SNRavgdB,
935 935 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
936 936 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
937 937 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
938 938
939 939 self.draw()
940 940
941 941 self.save(figpath=figpath,
942 942 figfile=figfile,
943 943 save=save,
944 944 ftp=ftp,
945 945 wr_period=wr_period,
946 946 thisDatetime=thisDatetime,
947 947 update_figfile=update_figfile)
948 948
949 949 if dataOut.ltctime + dataOut.paramInterval >= self.xmax:
950 950 self.counter_imagwr = wr_period
951 951 self.isConfig = False
952 952 update_figfile = True
953 953
954 954 return dataOut
955 955
956 956 @MPDecorator
957 957 class ParametersPlot_(Figure):
958 958
959 959 __isConfig = None
960 960 __nsubplots = None
961 961
962 962 WIDTHPROF = None
963 963 HEIGHTPROF = None
964 964 PREFIX = 'param'
965 965
966 966 nplots = None
967 967 nchan = None
968 968
969 969 def __init__(self):#, **kwargs):
970 970 Figure.__init__(self)#, **kwargs)
971 971 self.timerange = None
972 972 self.isConfig = False
973 973 self.__nsubplots = 1
974 974
975 975 self.WIDTH = 300
976 976 self.HEIGHT = 550
977 977 self.WIDTHPROF = 120
978 978 self.HEIGHTPROF = 0
979 979 self.counter_imagwr = 0
980 980
981 981 self.PLOT_CODE = RTI_CODE
982 982
983 983 self.FTP_WEI = None
984 984 self.EXP_CODE = None
985 985 self.SUB_EXP_CODE = None
986 986 self.PLOT_POS = None
987 987 self.tmin = None
988 988 self.tmax = None
989 989
990 990 self.xmin = None
991 991 self.xmax = None
992 992
993 993 self.figfile = None
994 994
995 995 def getSubplots(self):
996 996
997 997 ncol = 1
998 998 nrow = self.nplots
999 999
1000 1000 return nrow, ncol
1001 1001
1002 1002 def setup(self, id, nplots, wintitle, show=True):
1003 1003
1004 1004 self.nplots = nplots
1005 1005
1006 1006 ncolspan = 1
1007 1007 colspan = 1
1008 1008
1009 1009 self.createFigure(id = id,
1010 1010 wintitle = wintitle,
1011 1011 widthplot = self.WIDTH + self.WIDTHPROF,
1012 1012 heightplot = self.HEIGHT + self.HEIGHTPROF,
1013 1013 show=show)
1014 1014
1015 1015 nrow, ncol = self.getSubplots()
1016 1016
1017 1017 counter = 0
1018 1018 for y in range(nrow):
1019 1019 for x in range(ncol):
1020 1020
1021 1021 if counter >= self.nplots:
1022 1022 break
1023 1023
1024 1024 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1025 1025
1026 1026 counter += 1
1027 1027
1028 1028 def run(self, dataOut, id, wintitle="", channelList=None, paramIndex = 0, colormap="jet",
1029 1029 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, timerange=None,
1030 1030 showSNR=False, SNRthresh = -numpy.inf, SNRmin=None, SNRmax=None,
1031 1031 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1032 1032 server=None, folder=None, username=None, password=None,
1033 1033 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, HEIGHT=None):
1034 1034 """
1035 1035
1036 1036 Input:
1037 1037 dataOut :
1038 1038 id :
1039 1039 wintitle :
1040 1040 channelList :
1041 1041 showProfile :
1042 1042 xmin : None,
1043 1043 xmax : None,
1044 1044 ymin : None,
1045 1045 ymax : None,
1046 1046 zmin : None,
1047 1047 zmax : None
1048 1048 """
1049 1049 if dataOut.flagNoData:
1050 1050 return dataOut
1051 1051
1052 1052
1053 1053 if HEIGHT is not None:
1054 1054 self.HEIGHT = HEIGHT
1055 1055
1056 1056
1057 1057 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1058 1058 return
1059 1059
1060 1060 if channelList == None:
1061 1061 channelIndexList = list(range(dataOut.data_param.shape[0]))
1062 1062 else:
1063 1063 channelIndexList = []
1064 1064 for channel in channelList:
1065 1065 if channel not in dataOut.channelList:
1066 1066 raise ValueError("Channel %d is not in dataOut.channelList")
1067 1067 channelIndexList.append(dataOut.channelList.index(channel))
1068 1068
1069 1069 x = dataOut.getTimeRange1(dataOut.paramInterval)
1070 1070 y = dataOut.getHeiRange()
1071 1071
1072 1072 if dataOut.data_param.ndim == 3:
1073 1073 z = dataOut.data_param[channelIndexList,paramIndex,:]
1074 1074 else:
1075 1075 z = dataOut.data_param[channelIndexList,:]
1076 1076
1077 1077 if showSNR:
1078 1078 #SNR data
1079 1079 SNRarray = dataOut.data_SNR[channelIndexList,:]
1080 1080 SNRdB = 10*numpy.log10(SNRarray)
1081 1081 ind = numpy.where(SNRdB < SNRthresh)
1082 1082 z[ind] = numpy.nan
1083 1083
1084 1084 thisDatetime = dataOut.datatime
1085 # thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1085 # thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1086 1086 title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
1087 1087 xlabel = ""
1088 1088 ylabel = "Range (km)"
1089 1089
1090 1090 update_figfile = False
1091 1091
1092 1092 if not self.isConfig:
1093 1093
1094 1094 nchan = len(channelIndexList)
1095 1095 self.nchan = nchan
1096 1096 self.plotFact = 1
1097 1097 nplots = nchan
1098 1098
1099 1099 if showSNR:
1100 1100 nplots = nchan*2
1101 1101 self.plotFact = 2
1102 1102 if SNRmin == None: SNRmin = numpy.nanmin(SNRdB)
1103 1103 if SNRmax == None: SNRmax = numpy.nanmax(SNRdB)
1104 1104
1105 1105 self.setup(id=id,
1106 1106 nplots=nplots,
1107 1107 wintitle=wintitle,
1108 1108 show=show)
1109 1109
1110 1110 if timerange != None:
1111 1111 self.timerange = timerange
1112 1112
1113 1113 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1114 1114
1115 1115 if ymin == None: ymin = numpy.nanmin(y)
1116 1116 if ymax == None: ymax = numpy.nanmax(y)
1117 1117 if zmin == None: zmin = numpy.nanmin(z)
1118 1118 if zmax == None: zmax = numpy.nanmax(z)
1119 1119
1120 1120 self.FTP_WEI = ftp_wei
1121 1121 self.EXP_CODE = exp_code
1122 1122 self.SUB_EXP_CODE = sub_exp_code
1123 1123 self.PLOT_POS = plot_pos
1124 1124
1125 1125 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1126 1126 self.isConfig = True
1127 1127 self.figfile = figfile
1128 1128 update_figfile = True
1129 1129
1130 1130 self.setWinTitle(title)
1131 1131
1132 # for i in range(self.nchan):
1133 # index = channelIndexList[i]
1134 # title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1135 # axes = self.axesList[i*self.plotFact]
1136 # z1 = z[i,:].reshape((1,-1))
1137 # axes.pcolorbuffer(x, y, z1,
1138 # xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1139 # xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1140 # ticksize=9, cblabel='', cbsize="1%",colormap=colormap)
1141 #
1142 # if showSNR:
1143 # title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1144 # axes = self.axesList[i*self.plotFact + 1]
1145 # SNRdB1 = SNRdB[i,:].reshape((1,-1))
1146 # axes.pcolorbuffer(x, y, SNRdB1,
1147 # xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1148 # xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1149 # ticksize=9, cblabel='', cbsize="1%",colormap='jet')
1132 # for i in range(self.nchan):
1133 # index = channelIndexList[i]
1134 # title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1135 # axes = self.axesList[i*self.plotFact]
1136 # z1 = z[i,:].reshape((1,-1))
1137 # axes.pcolorbuffer(x, y, z1,
1138 # xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1139 # xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1140 # ticksize=9, cblabel='', cbsize="1%",colormap=colormap)
1141 #
1142 # if showSNR:
1143 # title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1144 # axes = self.axesList[i*self.plotFact + 1]
1145 # SNRdB1 = SNRdB[i,:].reshape((1,-1))
1146 # axes.pcolorbuffer(x, y, SNRdB1,
1147 # xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1148 # xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1149 # ticksize=9, cblabel='', cbsize="1%",colormap='jet')
1150 1150
1151 1151 i=0
1152 1152 index = channelIndexList[i]
1153 1153 title = "Factor de reflectividad Z [dBZ]"
1154 1154 axes = self.axesList[i*self.plotFact]
1155 1155 z1 = z[i,:].reshape((1,-1))
1156 1156 axes.pcolorbuffer(x, y, z1,
1157 1157 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1158 1158 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1159 1159 ticksize=9, cblabel='', cbsize="1%",colormap=colormap)
1160 1160
1161 1161 if showSNR:
1162 1162 title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1163 1163 axes = self.axesList[i*self.plotFact + 1]
1164 1164 SNRdB1 = SNRdB[i,:].reshape((1,-1))
1165 1165 axes.pcolorbuffer(x, y, SNRdB1,
1166 1166 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1167 1167 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1168 1168 ticksize=9, cblabel='', cbsize="1%",colormap='jet')
1169 1169
1170 1170 i=1
1171 1171 index = channelIndexList[i]
1172 1172 title = "Velocidad vertical Doppler [m/s]"
1173 1173 axes = self.axesList[i*self.plotFact]
1174 1174 z1 = z[i,:].reshape((1,-1))
1175 1175 axes.pcolorbuffer(x, y, z1,
1176 1176 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=-10, zmax=10,
1177 1177 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1178 1178 ticksize=9, cblabel='', cbsize="1%",colormap='seismic_r')
1179 1179
1180 1180 if showSNR:
1181 1181 title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1182 1182 axes = self.axesList[i*self.plotFact + 1]
1183 1183 SNRdB1 = SNRdB[i,:].reshape((1,-1))
1184 1184 axes.pcolorbuffer(x, y, SNRdB1,
1185 1185 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1186 1186 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1187 1187 ticksize=9, cblabel='', cbsize="1%",colormap='jet')
1188 1188
1189 1189 i=2
1190 1190 index = channelIndexList[i]
1191 1191 title = "Intensidad de lluvia [mm/h]"
1192 1192 axes = self.axesList[i*self.plotFact]
1193 1193 z1 = z[i,:].reshape((1,-1))
1194 1194 axes.pcolorbuffer(x, y, z1,
1195 1195 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=0, zmax=40,
1196 1196 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1197 1197 ticksize=9, cblabel='', cbsize="1%",colormap='ocean_r')
1198 1198
1199 1199 if showSNR:
1200 1200 title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1201 1201 axes = self.axesList[i*self.plotFact + 1]
1202 1202 SNRdB1 = SNRdB[i,:].reshape((1,-1))
1203 1203 axes.pcolorbuffer(x, y, SNRdB1,
1204 1204 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1205 1205 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1206 1206 ticksize=9, cblabel='', cbsize="1%",colormap='jet')
1207 1207
1208 1208
1209 1209 self.draw()
1210 1210
1211 1211 if dataOut.ltctime >= self.xmax:
1212 1212 self.counter_imagwr = wr_period
1213 1213 self.isConfig = False
1214 1214 update_figfile = True
1215 1215
1216 1216 self.save(figpath=figpath,
1217 1217 figfile=figfile,
1218 1218 save=save,
1219 1219 ftp=ftp,
1220 1220 wr_period=wr_period,
1221 1221 thisDatetime=thisDatetime,
1222 1222 update_figfile=update_figfile)
1223 1223
1224 1224 return dataOut
1225 1225 @MPDecorator
1226 1226 class Parameters1Plot_(Figure):
1227 1227
1228 1228 __isConfig = None
1229 1229 __nsubplots = None
1230 1230
1231 1231 WIDTHPROF = None
1232 1232 HEIGHTPROF = None
1233 1233 PREFIX = 'prm'
1234 1234
1235 1235 def __init__(self):
1236 1236 Figure.__init__(self)
1237 1237 self.timerange = 2*60*60
1238 1238 self.isConfig = False
1239 1239 self.__nsubplots = 1
1240 1240
1241 1241 self.WIDTH = 800
1242 1242 self.HEIGHT = 180
1243 1243 self.WIDTHPROF = 120
1244 1244 self.HEIGHTPROF = 0
1245 1245 self.counter_imagwr = 0
1246 1246
1247 1247 self.PLOT_CODE = PARMS_CODE
1248 1248
1249 1249 self.FTP_WEI = None
1250 1250 self.EXP_CODE = None
1251 1251 self.SUB_EXP_CODE = None
1252 1252 self.PLOT_POS = None
1253 1253 self.tmin = None
1254 1254 self.tmax = None
1255 1255
1256 1256 self.xmin = None
1257 1257 self.xmax = None
1258 1258
1259 1259 self.figfile = None
1260 1260
1261 1261 def getSubplots(self):
1262 1262
1263 1263 ncol = 1
1264 1264 nrow = self.nplots
1265 1265
1266 1266 return nrow, ncol
1267 1267
1268 1268 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1269 1269
1270 1270 self.__showprofile = showprofile
1271 1271 self.nplots = nplots
1272 1272
1273 1273 ncolspan = 1
1274 1274 colspan = 1
1275 1275
1276 1276 self.createFigure(id = id,
1277 1277 wintitle = wintitle,
1278 1278 widthplot = self.WIDTH + self.WIDTHPROF,
1279 1279 heightplot = self.HEIGHT + self.HEIGHTPROF,
1280 1280 show=show)
1281 1281
1282 1282 nrow, ncol = self.getSubplots()
1283 1283
1284 1284 counter = 0
1285 1285 for y in range(nrow):
1286 1286 for x in range(ncol):
1287 1287
1288 1288 if counter >= self.nplots:
1289 1289 break
1290 1290
1291 1291 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1292 1292
1293 1293 if showprofile:
1294 1294 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
1295 1295
1296 1296 counter += 1
1297 1297
1298 1298 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
1299 1299 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,timerange=None,
1300 1300 parameterIndex = None, onlyPositive = False,
1301 1301 SNRthresh = -numpy.inf, SNR = True, SNRmin = None, SNRmax = None, onlySNR = False,
1302 1302 DOP = True,
1303 1303 zlabel = "", parameterName = "", parameterObject = "data_param",
1304 1304 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1305 1305 server=None, folder=None, username=None, password=None,
1306 1306 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1307 1307
1308 1308 """
1309 1309 Input:
1310 1310 dataOut :
1311 1311 id :
1312 1312 wintitle :
1313 1313 channelList :
1314 1314 showProfile :
1315 1315 xmin : None,
1316 1316 xmax : None,
1317 1317 ymin : None,
1318 1318 ymax : None,
1319 1319 zmin : None,
1320 1320 zmax : None
1321 1321 """
1322 1322 if dataOut.flagNoData:
1323 1323 return dataOut
1324 1324
1325 1325 data_param = getattr(dataOut, parameterObject)
1326 1326
1327 1327 if channelList == None:
1328 1328 channelIndexList = numpy.arange(data_param.shape[0])
1329 1329 else:
1330 1330 channelIndexList = numpy.array(channelList)
1331 1331
1332 1332 nchan = len(channelIndexList) #Number of channels being plotted
1333 1333
1334 1334 if nchan < 1:
1335 1335 return
1336 1336
1337 1337 nGraphsByChannel = 0
1338 1338
1339 1339 if SNR:
1340 1340 nGraphsByChannel += 1
1341 1341 if DOP:
1342 1342 nGraphsByChannel += 1
1343 1343
1344 1344 if nGraphsByChannel < 1:
1345 1345 return
1346 1346
1347 1347 nplots = nGraphsByChannel*nchan
1348 1348
1349 1349 if timerange is not None:
1350 1350 self.timerange = timerange
1351 1351
1352 1352 #tmin = None
1353 1353 #tmax = None
1354 1354 if parameterIndex == None:
1355 1355 parameterIndex = 1
1356 1356
1357 1357 x = dataOut.getTimeRange1(dataOut.paramInterval)
1358 1358 y = dataOut.heightList
1359 1359
1360 1360 if dataOut.data_param.ndim == 3:
1361 1361 z = dataOut.data_param[channelIndexList,parameterIndex,:]
1362 1362 else:
1363 1363 z = dataOut.data_param[channelIndexList,:]
1364 1364
1365 1365 if dataOut.data_SNR is not None:
1366 1366 if dataOut.data_SNR.ndim == 2:
1367 1367 SNRavg = numpy.average(dataOut.data_SNR, axis=0)
1368 1368 else:
1369 1369 SNRavg = dataOut.data_SNR
1370 1370 SNRdB = 10*numpy.log10(SNRavg)
1371 1371
1372 1372 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1373 1373 title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
1374 1374 xlabel = ""
1375 1375 ylabel = "Range (Km)"
1376 1376
1377 1377 if onlyPositive:
1378 1378 colormap = "jet"
1379 1379 zmin = 0
1380 1380 else: colormap = "RdBu_r"
1381 1381
1382 1382 if not self.isConfig:
1383 1383
1384 1384 self.setup(id=id,
1385 1385 nplots=nplots,
1386 1386 wintitle=wintitle,
1387 1387 showprofile=showprofile,
1388 1388 show=show)
1389 1389
1390 1390 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1391 1391
1392 1392 if ymin == None: ymin = numpy.nanmin(y)
1393 1393 if ymax == None: ymax = numpy.nanmax(y)
1394 1394 if zmin == None: zmin = numpy.nanmin(z)
1395 1395 if zmax == None: zmax = numpy.nanmax(z)
1396 1396
1397 1397 if SNR:
1398 1398 if SNRmin == None: SNRmin = numpy.nanmin(SNRdB)
1399 1399 if SNRmax == None: SNRmax = numpy.nanmax(SNRdB)
1400 1400
1401 1401 self.FTP_WEI = ftp_wei
1402 1402 self.EXP_CODE = exp_code
1403 1403 self.SUB_EXP_CODE = sub_exp_code
1404 1404 self.PLOT_POS = plot_pos
1405 1405
1406 1406 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1407 1407 self.isConfig = True
1408 1408 self.figfile = figfile
1409 1409
1410 1410 self.setWinTitle(title)
1411 1411
1412 1412 if ((self.xmax - x[1]) < (x[1]-x[0])):
1413 1413 x[1] = self.xmax
1414 1414
1415 1415 for i in range(nchan):
1416 1416
1417 1417 if (SNR and not onlySNR): j = 2*i
1418 1418 else: j = i
1419 1419
1420 1420 j = nGraphsByChannel*i
1421 1421
1422 1422 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1423 1423 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
1424 1424
1425 1425 if not onlySNR:
1426 1426 axes = self.axesList[j*self.__nsubplots]
1427 1427 z1 = z[i,:].reshape((1,-1))
1428 1428 axes.pcolorbuffer(x, y, z1,
1429 1429 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1430 1430 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap,
1431 1431 ticksize=9, cblabel=zlabel, cbsize="1%")
1432 1432
1433 1433 if DOP:
1434 1434 title = "%s Channel %d: %s" %(parameterName, channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1435 1435
1436 1436 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1437 1437 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
1438 1438 axes = self.axesList[j]
1439 1439 z1 = z[i,:].reshape((1,-1))
1440 1440 axes.pcolorbuffer(x, y, z1,
1441 1441 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1442 1442 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap,
1443 1443 ticksize=9, cblabel=zlabel, cbsize="1%")
1444 1444
1445 1445 if SNR:
1446 1446 title = "Channel %d Signal Noise Ratio (SNR): %s" %(channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1447 1447 axes = self.axesList[(j)*self.__nsubplots]
1448 1448 if not onlySNR:
1449 1449 axes = self.axesList[(j + 1)*self.__nsubplots]
1450 1450
1451 1451 axes = self.axesList[(j + nGraphsByChannel-1)]
1452 1452 z1 = SNRdB.reshape((1,-1))
1453 1453 axes.pcolorbuffer(x, y, z1,
1454 1454 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1455 1455 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap="jet",
1456 1456 ticksize=9, cblabel=zlabel, cbsize="1%")
1457 1457
1458 1458
1459 1459
1460 1460 self.draw()
1461 1461
1462 1462 if x[1] >= self.axesList[0].xmax:
1463 1463 self.counter_imagwr = wr_period
1464 1464 self.isConfig = False
1465 1465 self.figfile = None
1466 1466
1467 1467 self.save(figpath=figpath,
1468 1468 figfile=figfile,
1469 1469 save=save,
1470 1470 ftp=ftp,
1471 1471 wr_period=wr_period,
1472 1472 thisDatetime=thisDatetime,
1473 1473 update_figfile=False)
1474 1474 return dataOut
1475 1475
1476 1476 class SpectralFittingPlot_(Figure):
1477 1477
1478 1478 __isConfig = None
1479 1479 __nsubplots = None
1480 1480
1481 1481 WIDTHPROF = None
1482 1482 HEIGHTPROF = None
1483 1483 PREFIX = 'prm'
1484 1484
1485 1485
1486 1486 N = None
1487 1487 ippSeconds = None
1488 1488
1489 1489 def __init__(self, **kwargs):
1490 1490 Figure.__init__(self, **kwargs)
1491 1491 self.isConfig = False
1492 1492 self.__nsubplots = 1
1493 1493
1494 1494 self.PLOT_CODE = SPECFIT_CODE
1495 1495
1496 1496 self.WIDTH = 450
1497 1497 self.HEIGHT = 250
1498 1498 self.WIDTHPROF = 0
1499 1499 self.HEIGHTPROF = 0
1500 1500
1501 1501 def getSubplots(self):
1502 1502
1503 1503 ncol = int(numpy.sqrt(self.nplots)+0.9)
1504 1504 nrow = int(self.nplots*1./ncol + 0.9)
1505 1505
1506 1506 return nrow, ncol
1507 1507
1508 1508 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
1509 1509
1510 1510 showprofile = False
1511 1511 self.__showprofile = showprofile
1512 1512 self.nplots = nplots
1513 1513
1514 1514 ncolspan = 5
1515 1515 colspan = 4
1516 1516 if showprofile:
1517 1517 ncolspan = 5
1518 1518 colspan = 4
1519 1519 self.__nsubplots = 2
1520 1520
1521 1521 self.createFigure(id = id,
1522 1522 wintitle = wintitle,
1523 1523 widthplot = self.WIDTH + self.WIDTHPROF,
1524 1524 heightplot = self.HEIGHT + self.HEIGHTPROF,
1525 1525 show=show)
1526 1526
1527 1527 nrow, ncol = self.getSubplots()
1528 1528
1529 1529 counter = 0
1530 1530 for y in range(nrow):
1531 1531 for x in range(ncol):
1532 1532
1533 1533 if counter >= self.nplots:
1534 1534 break
1535 1535
1536 1536 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1537 1537
1538 1538 if showprofile:
1539 1539 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
1540 1540
1541 1541 counter += 1
1542 1542
1543 1543 def run(self, dataOut, id, cutHeight=None, fit=False, wintitle="", channelList=None, showprofile=True,
1544 1544 xmin=None, xmax=None, ymin=None, ymax=None,
1545 1545 save=False, figpath='./', figfile=None, show=True):
1546 1546
1547 1547 """
1548 1548
1549 1549 Input:
1550 1550 dataOut :
1551 1551 id :
1552 1552 wintitle :
1553 1553 channelList :
1554 1554 showProfile :
1555 1555 xmin : None,
1556 1556 xmax : None,
1557 1557 zmin : None,
1558 1558 zmax : None
1559 1559 """
1560 1560
1561 1561 if cutHeight==None:
1562 1562 h=270
1563 1563 heightindex = numpy.abs(cutHeight - dataOut.heightList).argmin()
1564 1564 cutHeight = dataOut.heightList[heightindex]
1565 1565
1566 1566 factor = dataOut.normFactor
1567 1567 x = dataOut.abscissaList[:-1]
1568 1568 #y = dataOut.getHeiRange()
1569 1569
1570 1570 z = dataOut.data_pre[:,:,heightindex]/factor
1571 1571 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1572 1572 avg = numpy.average(z, axis=1)
1573 1573 listChannels = z.shape[0]
1574 1574
1575 1575 #Reconstruct Function
1576 1576 if fit==True:
1577 1577 groupArray = dataOut.groupList
1578 1578 listChannels = groupArray.reshape((groupArray.size))
1579 1579 listChannels.sort()
1580 1580 spcFitLine = numpy.zeros(z.shape)
1581 1581 constants = dataOut.constants
1582 1582
1583 1583 nGroups = groupArray.shape[0]
1584 1584 nChannels = groupArray.shape[1]
1585 1585 nProfiles = z.shape[1]
1586 1586
1587 1587 for f in range(nGroups):
1588 1588 groupChann = groupArray[f,:]
1589 1589 p = dataOut.data_param[f,:,heightindex]
1590 # p = numpy.array([ 89.343967,0.14036615,0.17086219,18.89835291,1.58388365,1.55099167])
1590 # p = numpy.array([ 89.343967,0.14036615,0.17086219,18.89835291,1.58388365,1.55099167])
1591 1591 fitLineAux = dataOut.library.modelFunction(p, constants)*nProfiles
1592 1592 fitLineAux = fitLineAux.reshape((nChannels,nProfiles))
1593 1593 spcFitLine[groupChann,:] = fitLineAux
1594 # spcFitLine = spcFitLine/factor
1594 # spcFitLine = spcFitLine/factor
1595 1595
1596 1596 z = z[listChannels,:]
1597 1597 spcFitLine = spcFitLine[listChannels,:]
1598 1598 spcFitLinedB = 10*numpy.log10(spcFitLine)
1599 1599
1600 1600 zdB = 10*numpy.log10(z)
1601 1601 #thisDatetime = dataOut.datatime
1602 1602 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1603 1603 title = wintitle + " Doppler Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
1604 1604 xlabel = "Velocity (m/s)"
1605 1605 ylabel = "Spectrum"
1606 1606
1607 1607 if not self.isConfig:
1608 1608
1609 1609 nplots = listChannels.size
1610 1610
1611 1611 self.setup(id=id,
1612 1612 nplots=nplots,
1613 1613 wintitle=wintitle,
1614 1614 showprofile=showprofile,
1615 1615 show=show)
1616 1616
1617 1617 if xmin == None: xmin = numpy.nanmin(x)
1618 1618 if xmax == None: xmax = numpy.nanmax(x)
1619 1619 if ymin == None: ymin = numpy.nanmin(zdB)
1620 1620 if ymax == None: ymax = numpy.nanmax(zdB)+2
1621 1621
1622 1622 self.isConfig = True
1623 1623
1624 1624 self.setWinTitle(title)
1625 1625 for i in range(self.nplots):
1626 # title = "Channel %d: %4.2fdB" %(dataOut.channelList[i]+1, noisedB[i])
1626 # title = "Channel %d: %4.2fdB" %(dataOut.channelList[i]+1, noisedB[i])
1627 1627 title = "Height %4.1f km\nChannel %d:" %(cutHeight, listChannels[i])
1628 1628 axes = self.axesList[i*self.__nsubplots]
1629 1629 if fit == False:
1630 1630 axes.pline(x, zdB[i,:],
1631 1631 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1632 1632 xlabel=xlabel, ylabel=ylabel, title=title
1633 1633 )
1634 1634 if fit == True:
1635 1635 fitline=spcFitLinedB[i,:]
1636 1636 y=numpy.vstack([zdB[i,:],fitline] )
1637 1637 legendlabels=['Data','Fitting']
1638 1638 axes.pmultilineyaxis(x, y,
1639 1639 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1640 1640 xlabel=xlabel, ylabel=ylabel, title=title,
1641 1641 legendlabels=legendlabels, marker=None,
1642 1642 linestyle='solid', grid='both')
1643 1643
1644 1644 self.draw()
1645 1645
1646 1646 self.save(figpath=figpath,
1647 1647 figfile=figfile,
1648 1648 save=save,
1649 1649 ftp=ftp,
1650 1650 wr_period=wr_period,
1651 1651 thisDatetime=thisDatetime)
1652 1652
1653 1653
1654 1654 class EWDriftsPlot_(Figure):
1655 1655
1656 1656 __isConfig = None
1657 1657 __nsubplots = None
1658 1658
1659 1659 WIDTHPROF = None
1660 1660 HEIGHTPROF = None
1661 1661 PREFIX = 'drift'
1662 1662
1663 1663 def __init__(self, **kwargs):
1664 1664 Figure.__init__(self, **kwargs)
1665 1665 self.timerange = 2*60*60
1666 1666 self.isConfig = False
1667 1667 self.__nsubplots = 1
1668 1668
1669 1669 self.WIDTH = 800
1670 1670 self.HEIGHT = 150
1671 1671 self.WIDTHPROF = 120
1672 1672 self.HEIGHTPROF = 0
1673 1673 self.counter_imagwr = 0
1674 1674
1675 1675 self.PLOT_CODE = EWDRIFT_CODE
1676 1676
1677 1677 self.FTP_WEI = None
1678 1678 self.EXP_CODE = None
1679 1679 self.SUB_EXP_CODE = None
1680 1680 self.PLOT_POS = None
1681 1681 self.tmin = None
1682 1682 self.tmax = None
1683 1683
1684 1684 self.xmin = None
1685 1685 self.xmax = None
1686 1686
1687 1687 self.figfile = None
1688 1688
1689 1689 def getSubplots(self):
1690 1690
1691 1691 ncol = 1
1692 1692 nrow = self.nplots
1693 1693
1694 1694 return nrow, ncol
1695 1695
1696 1696 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1697 1697
1698 1698 self.__showprofile = showprofile
1699 1699 self.nplots = nplots
1700 1700
1701 1701 ncolspan = 1
1702 1702 colspan = 1
1703 1703
1704 1704 self.createFigure(id = id,
1705 1705 wintitle = wintitle,
1706 1706 widthplot = self.WIDTH + self.WIDTHPROF,
1707 1707 heightplot = self.HEIGHT + self.HEIGHTPROF,
1708 1708 show=show)
1709 1709
1710 1710 nrow, ncol = self.getSubplots()
1711 1711
1712 1712 counter = 0
1713 1713 for y in range(nrow):
1714 1714 if counter >= self.nplots:
1715 1715 break
1716 1716
1717 1717 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
1718 1718 counter += 1
1719 1719
1720 1720 def run(self, dataOut, id, wintitle="", channelList=None,
1721 1721 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
1722 1722 zmaxVertical = None, zminVertical = None, zmaxZonal = None, zminZonal = None,
1723 1723 timerange=None, SNRthresh = -numpy.inf, SNRmin = None, SNRmax = None, SNR_1 = False,
1724 1724 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1725 1725 server=None, folder=None, username=None, password=None,
1726 1726 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1727 1727 """
1728 1728
1729 1729 Input:
1730 1730 dataOut :
1731 1731 id :
1732 1732 wintitle :
1733 1733 channelList :
1734 1734 showProfile :
1735 1735 xmin : None,
1736 1736 xmax : None,
1737 1737 ymin : None,
1738 1738 ymax : None,
1739 1739 zmin : None,
1740 1740 zmax : None
1741 1741 """
1742 1742
1743 1743 if timerange is not None:
1744 1744 self.timerange = timerange
1745 1745
1746 1746 tmin = None
1747 1747 tmax = None
1748 1748
1749 1749 x = dataOut.getTimeRange1(dataOut.outputInterval)
1750 # y = dataOut.heightList
1750 # y = dataOut.heightList
1751 1751 y = dataOut.heightList
1752 1752
1753 1753 z = dataOut.data_output
1754 1754 nplots = z.shape[0] #Number of wind dimensions estimated
1755 1755 nplotsw = nplots
1756 1756
1757 1757 #If there is a SNR function defined
1758 1758 if dataOut.data_SNR is not None:
1759 1759 nplots += 1
1760 1760 SNR = dataOut.data_SNR
1761 1761
1762 1762 if SNR_1:
1763 1763 SNR += 1
1764 1764
1765 1765 SNRavg = numpy.average(SNR, axis=0)
1766 1766
1767 1767 SNRdB = 10*numpy.log10(SNR)
1768 1768 SNRavgdB = 10*numpy.log10(SNRavg)
1769 1769
1770 1770 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
1771 1771
1772 1772 for i in range(nplotsw):
1773 1773 z[i,ind] = numpy.nan
1774 1774
1775 1775
1776 1776 showprofile = False
1777 # thisDatetime = dataOut.datatime
1777 # thisDatetime = dataOut.datatime
1778 1778 thisDatetime = datetime.datetime.utcfromtimestamp(x[1])
1779 1779 title = wintitle + " EW Drifts"
1780 1780 xlabel = ""
1781 1781 ylabel = "Height (Km)"
1782 1782
1783 1783 if not self.isConfig:
1784 1784
1785 1785 self.setup(id=id,
1786 1786 nplots=nplots,
1787 1787 wintitle=wintitle,
1788 1788 showprofile=showprofile,
1789 1789 show=show)
1790 1790
1791 1791 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1792 1792
1793 1793 if ymin == None: ymin = numpy.nanmin(y)
1794 1794 if ymax == None: ymax = numpy.nanmax(y)
1795 1795
1796 1796 if zmaxZonal == None: zmaxZonal = numpy.nanmax(abs(z[0,:]))
1797 1797 if zminZonal == None: zminZonal = -zmaxZonal
1798 1798 if zmaxVertical == None: zmaxVertical = numpy.nanmax(abs(z[1,:]))
1799 1799 if zminVertical == None: zminVertical = -zmaxVertical
1800 1800
1801 1801 if dataOut.data_SNR is not None:
1802 1802 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
1803 1803 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
1804 1804
1805 1805 self.FTP_WEI = ftp_wei
1806 1806 self.EXP_CODE = exp_code
1807 1807 self.SUB_EXP_CODE = sub_exp_code
1808 1808 self.PLOT_POS = plot_pos
1809 1809
1810 1810 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1811 1811 self.isConfig = True
1812 1812
1813 1813
1814 1814 self.setWinTitle(title)
1815 1815
1816 1816 if ((self.xmax - x[1]) < (x[1]-x[0])):
1817 1817 x[1] = self.xmax
1818 1818
1819 1819 strWind = ['Zonal','Vertical']
1820 1820 strCb = 'Velocity (m/s)'
1821 1821 zmaxVector = [zmaxZonal, zmaxVertical]
1822 1822 zminVector = [zminZonal, zminVertical]
1823 1823
1824 1824 for i in range(nplotsw):
1825 1825
1826 1826 title = "%s Drifts: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1827 1827 axes = self.axesList[i*self.__nsubplots]
1828 1828
1829 1829 z1 = z[i,:].reshape((1,-1))
1830 1830
1831 1831 axes.pcolorbuffer(x, y, z1,
1832 1832 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
1833 1833 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1834 1834 ticksize=9, cblabel=strCb, cbsize="1%", colormap="RdBu_r")
1835 1835
1836 1836 if dataOut.data_SNR is not None:
1837 1837 i += 1
1838 1838 if SNR_1:
1839 1839 title = "Signal Noise Ratio + 1 (SNR+1): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1840 1840 else:
1841 1841 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1842 1842 axes = self.axesList[i*self.__nsubplots]
1843 1843 SNRavgdB = SNRavgdB.reshape((1,-1))
1844 1844
1845 1845 axes.pcolorbuffer(x, y, SNRavgdB,
1846 1846 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1847 1847 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1848 1848 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
1849 1849
1850 1850 self.draw()
1851 1851
1852 1852 if x[1] >= self.axesList[0].xmax:
1853 1853 self.counter_imagwr = wr_period
1854 1854 self.isConfig = False
1855 1855 self.figfile = None
1856 1856
1857 1857
1858 1858
1859 1859
1860 1860 class PhasePlot_(Figure):
1861 1861
1862 1862 __isConfig = None
1863 1863 __nsubplots = None
1864 1864
1865 1865 PREFIX = 'mphase'
1866 1866
1867 1867
1868 1868 def __init__(self, **kwargs):
1869 1869 Figure.__init__(self, **kwargs)
1870 1870 self.timerange = 24*60*60
1871 1871 self.isConfig = False
1872 1872 self.__nsubplots = 1
1873 1873 self.counter_imagwr = 0
1874 1874 self.WIDTH = 600
1875 1875 self.HEIGHT = 300
1876 1876 self.WIDTHPROF = 120
1877 1877 self.HEIGHTPROF = 0
1878 1878 self.xdata = None
1879 1879 self.ydata = None
1880 1880
1881 1881 self.PLOT_CODE = MPHASE_CODE
1882 1882
1883 1883 self.FTP_WEI = None
1884 1884 self.EXP_CODE = None
1885 1885 self.SUB_EXP_CODE = None
1886 1886 self.PLOT_POS = None
1887 1887
1888 1888
1889 1889 self.filename_phase = None
1890 1890
1891 1891 self.figfile = None
1892 1892
1893 1893 def getSubplots(self):
1894 1894
1895 1895 ncol = 1
1896 1896 nrow = 1
1897 1897
1898 1898 return nrow, ncol
1899 1899
1900 1900 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1901 1901
1902 1902 self.__showprofile = showprofile
1903 1903 self.nplots = nplots
1904 1904
1905 1905 ncolspan = 7
1906 1906 colspan = 6
1907 1907 self.__nsubplots = 2
1908 1908
1909 1909 self.createFigure(id = id,
1910 1910 wintitle = wintitle,
1911 1911 widthplot = self.WIDTH+self.WIDTHPROF,
1912 1912 heightplot = self.HEIGHT+self.HEIGHTPROF,
1913 1913 show=show)
1914 1914
1915 1915 nrow, ncol = self.getSubplots()
1916 1916
1917 1917 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1918 1918
1919 1919
1920 1920 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1921 1921 xmin=None, xmax=None, ymin=None, ymax=None,
1922 1922 timerange=None,
1923 1923 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1924 1924 server=None, folder=None, username=None, password=None,
1925 1925 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1926 1926
1927 1927
1928 1928 tmin = None
1929 1929 tmax = None
1930 1930 x = dataOut.getTimeRange1(dataOut.outputInterval)
1931 1931 y = dataOut.getHeiRange()
1932 1932
1933 1933
1934 1934 #thisDatetime = dataOut.datatime
1935 1935 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
1936 1936 title = wintitle + " Phase of Beacon Signal" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1937 1937 xlabel = "Local Time"
1938 1938 ylabel = "Phase"
1939 1939
1940 1940
1941 1941 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1942 1942 phase_beacon = dataOut.data_output
1943 1943 update_figfile = False
1944 1944
1945 1945 if not self.isConfig:
1946 1946
1947 1947 self.nplots = phase_beacon.size
1948 1948
1949 1949 self.setup(id=id,
1950 1950 nplots=self.nplots,
1951 1951 wintitle=wintitle,
1952 1952 showprofile=showprofile,
1953 1953 show=show)
1954 1954
1955 1955 if timerange is not None:
1956 1956 self.timerange = timerange
1957 1957
1958 1958 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1959 1959
1960 1960 if ymin == None: ymin = numpy.nanmin(phase_beacon) - 10.0
1961 1961 if ymax == None: ymax = numpy.nanmax(phase_beacon) + 10.0
1962 1962
1963 1963 self.FTP_WEI = ftp_wei
1964 1964 self.EXP_CODE = exp_code
1965 1965 self.SUB_EXP_CODE = sub_exp_code
1966 1966 self.PLOT_POS = plot_pos
1967 1967
1968 1968 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1969 1969 self.isConfig = True
1970 1970 self.figfile = figfile
1971 1971 self.xdata = numpy.array([])
1972 1972 self.ydata = numpy.array([])
1973 1973
1974 1974 #open file beacon phase
1975 1975 path = '%s%03d' %(self.PREFIX, self.id)
1976 1976 beacon_file = os.path.join(path,'%s.txt'%self.name)
1977 1977 self.filename_phase = os.path.join(figpath,beacon_file)
1978 1978 update_figfile = True
1979 1979
1980 1980
1981 1981 #store data beacon phase
1982 1982 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1983 1983
1984 1984 self.setWinTitle(title)
1985 1985
1986 1986
1987 1987 title = "Phase Offset %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1988 1988
1989 1989 legendlabels = ["phase %d"%(chan) for chan in numpy.arange(self.nplots)]
1990 1990
1991 1991 axes = self.axesList[0]
1992 1992
1993 1993 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1994 1994
1995 1995 if len(self.ydata)==0:
1996 1996 self.ydata = phase_beacon.reshape(-1,1)
1997 1997 else:
1998 1998 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1999 1999
2000 2000
2001 2001 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
2002 2002 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
2003 2003 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
2004 2004 XAxisAsTime=True, grid='both'
2005 2005 )
2006 2006
2007 2007 self.draw()
2008 2008
2009 2009 self.save(figpath=figpath,
2010 2010 figfile=figfile,
2011 2011 save=save,
2012 2012 ftp=ftp,
2013 2013 wr_period=wr_period,
2014 2014 thisDatetime=thisDatetime,
2015 2015 update_figfile=update_figfile)
2016 2016
2017 2017 if dataOut.ltctime + dataOut.outputInterval >= self.xmax:
2018 2018 self.counter_imagwr = wr_period
2019 2019 self.isConfig = False
2020 2020 update_figfile = True
2021 2021
2022 2022
2023 2023
2024 2024 class NSMeteorDetection1Plot_(Figure):
2025 2025
2026 2026 isConfig = None
2027 2027 __nsubplots = None
2028 2028
2029 2029 WIDTHPROF = None
2030 2030 HEIGHTPROF = None
2031 2031 PREFIX = 'nsm'
2032 2032
2033 2033 zminList = None
2034 2034 zmaxList = None
2035 2035 cmapList = None
2036 2036 titleList = None
2037 2037 nPairs = None
2038 2038 nChannels = None
2039 2039 nParam = None
2040 2040
2041 2041 def __init__(self, **kwargs):
2042 2042 Figure.__init__(self, **kwargs)
2043 2043 self.isConfig = False
2044 2044 self.__nsubplots = 1
2045 2045
2046 2046 self.WIDTH = 750
2047 2047 self.HEIGHT = 250
2048 2048 self.WIDTHPROF = 120
2049 2049 self.HEIGHTPROF = 0
2050 2050 self.counter_imagwr = 0
2051 2051
2052 2052 self.PLOT_CODE = SPEC_CODE
2053 2053
2054 2054 self.FTP_WEI = None
2055 2055 self.EXP_CODE = None
2056 2056 self.SUB_EXP_CODE = None
2057 2057 self.PLOT_POS = None
2058 2058
2059 2059 self.__xfilter_ena = False
2060 2060 self.__yfilter_ena = False
2061 2061
2062 2062 def getSubplots(self):
2063 2063
2064 2064 ncol = 3
2065 2065 nrow = int(numpy.ceil(self.nplots/3.0))
2066 2066
2067 2067 return nrow, ncol
2068 2068
2069 2069 def setup(self, id, nplots, wintitle, show=True):
2070 2070
2071 2071 self.nplots = nplots
2072 2072
2073 2073 ncolspan = 1
2074 2074 colspan = 1
2075 2075
2076 2076 self.createFigure(id = id,
2077 2077 wintitle = wintitle,
2078 2078 widthplot = self.WIDTH + self.WIDTHPROF,
2079 2079 heightplot = self.HEIGHT + self.HEIGHTPROF,
2080 2080 show=show)
2081 2081
2082 2082 nrow, ncol = self.getSubplots()
2083 2083
2084 2084 counter = 0
2085 2085 for y in range(nrow):
2086 2086 for x in range(ncol):
2087 2087
2088 2088 if counter >= self.nplots:
2089 2089 break
2090 2090
2091 2091 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
2092 2092
2093 2093 counter += 1
2094 2094
2095 2095 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
2096 2096 xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None,
2097 2097 vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA',
2098 2098 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
2099 2099 server=None, folder=None, username=None, password=None,
2100 2100 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
2101 2101 xaxis="frequency"):
2102 2102
2103 2103 """
2104 2104
2105 2105 Input:
2106 2106 dataOut :
2107 2107 id :
2108 2108 wintitle :
2109 2109 channelList :
2110 2110 showProfile :
2111 2111 xmin : None,
2112 2112 xmax : None,
2113 2113 ymin : None,
2114 2114 ymax : None,
2115 2115 zmin : None,
2116 2116 zmax : None
2117 2117 """
2118 2118 #SEPARAR EN DOS PLOTS
2119 2119 nParam = dataOut.data_param.shape[1] - 3
2120 2120
2121 2121 utctime = dataOut.data_param[0,0]
2122 2122 tmet = dataOut.data_param[:,1].astype(int)
2123 2123 hmet = dataOut.data_param[:,2].astype(int)
2124 2124
2125 2125 x = dataOut.abscissaList
2126 2126 y = dataOut.heightList
2127 2127
2128 2128 z = numpy.zeros((nParam, y.size, x.size - 1))
2129 2129 z[:,:] = numpy.nan
2130 2130 z[:,hmet,tmet] = dataOut.data_param[:,3:].T
2131 2131 z[0,:,:] = 10*numpy.log10(z[0,:,:])
2132 2132
2133 2133 xlabel = "Time (s)"
2134 2134 ylabel = "Range (km)"
2135 2135
2136 2136 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
2137 2137
2138 2138 if not self.isConfig:
2139 2139
2140 2140 nplots = nParam
2141 2141
2142 2142 self.setup(id=id,
2143 2143 nplots=nplots,
2144 2144 wintitle=wintitle,
2145 2145 show=show)
2146 2146
2147 2147 if xmin is None: xmin = numpy.nanmin(x)
2148 2148 if xmax is None: xmax = numpy.nanmax(x)
2149 2149 if ymin is None: ymin = numpy.nanmin(y)
2150 2150 if ymax is None: ymax = numpy.nanmax(y)
2151 2151 if SNRmin is None: SNRmin = numpy.nanmin(z[0,:])
2152 2152 if SNRmax is None: SNRmax = numpy.nanmax(z[0,:])
2153 2153 if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:]))
2154 2154 if vmin is None: vmin = -vmax
2155 2155 if wmin is None: wmin = 0
2156 2156 if wmax is None: wmax = 50
2157 2157
2158 2158 pairsList = dataOut.groupList
2159 2159 self.nPairs = len(dataOut.groupList)
2160 2160
2161 2161 zminList = [SNRmin, vmin, cmin] + [pmin]*self.nPairs
2162 2162 zmaxList = [SNRmax, vmax, cmax] + [pmax]*self.nPairs
2163 2163 titleList = ["SNR","Radial Velocity","Coherence"]
2164 2164 cmapList = ["jet","RdBu_r","jet"]
2165 2165
2166 2166 for i in range(self.nPairs):
2167 2167 strAux1 = "Phase Difference "+ str(pairsList[i][0]) + str(pairsList[i][1])
2168 2168 titleList = titleList + [strAux1]
2169 2169 cmapList = cmapList + ["RdBu_r"]
2170 2170
2171 2171 self.zminList = zminList
2172 2172 self.zmaxList = zmaxList
2173 2173 self.cmapList = cmapList
2174 2174 self.titleList = titleList
2175 2175
2176 2176 self.FTP_WEI = ftp_wei
2177 2177 self.EXP_CODE = exp_code
2178 2178 self.SUB_EXP_CODE = sub_exp_code
2179 2179 self.PLOT_POS = plot_pos
2180 2180
2181 2181 self.isConfig = True
2182 2182
2183 2183 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
2184 2184
2185 2185 for i in range(nParam):
2186 2186 title = self.titleList[i] + ": " +str_datetime
2187 2187 axes = self.axesList[i]
2188 2188 axes.pcolor(x, y, z[i,:].T,
2189 2189 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i],
2190 2190 xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='')
2191 2191 self.draw()
2192 2192
2193 2193 if figfile == None:
2194 2194 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
2195 2195 name = str_datetime
2196 2196 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
2197 2197 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
2198 2198 figfile = self.getFilename(name)
2199 2199
2200 2200 self.save(figpath=figpath,
2201 2201 figfile=figfile,
2202 2202 save=save,
2203 2203 ftp=ftp,
2204 2204 wr_period=wr_period,
2205 2205 thisDatetime=thisDatetime)
2206 2206
2207 2207
2208 2208 class NSMeteorDetection2Plot_(Figure):
2209 2209
2210 2210 isConfig = None
2211 2211 __nsubplots = None
2212 2212
2213 2213 WIDTHPROF = None
2214 2214 HEIGHTPROF = None
2215 2215 PREFIX = 'nsm'
2216 2216
2217 2217 zminList = None
2218 2218 zmaxList = None
2219 2219 cmapList = None
2220 2220 titleList = None
2221 2221 nPairs = None
2222 2222 nChannels = None
2223 2223 nParam = None
2224 2224
2225 2225 def __init__(self, **kwargs):
2226 2226 Figure.__init__(self, **kwargs)
2227 2227 self.isConfig = False
2228 2228 self.__nsubplots = 1
2229 2229
2230 2230 self.WIDTH = 750
2231 2231 self.HEIGHT = 250
2232 2232 self.WIDTHPROF = 120
2233 2233 self.HEIGHTPROF = 0
2234 2234 self.counter_imagwr = 0
2235 2235
2236 2236 self.PLOT_CODE = SPEC_CODE
2237 2237
2238 2238 self.FTP_WEI = None
2239 2239 self.EXP_CODE = None
2240 2240 self.SUB_EXP_CODE = None
2241 2241 self.PLOT_POS = None
2242 2242
2243 2243 self.__xfilter_ena = False
2244 2244 self.__yfilter_ena = False
2245 2245
2246 2246 def getSubplots(self):
2247 2247
2248 2248 ncol = 3
2249 2249 nrow = int(numpy.ceil(self.nplots/3.0))
2250 2250
2251 2251 return nrow, ncol
2252 2252
2253 2253 def setup(self, id, nplots, wintitle, show=True):
2254 2254
2255 2255 self.nplots = nplots
2256 2256
2257 2257 ncolspan = 1
2258 2258 colspan = 1
2259 2259
2260 2260 self.createFigure(id = id,
2261 2261 wintitle = wintitle,
2262 2262 widthplot = self.WIDTH + self.WIDTHPROF,
2263 2263 heightplot = self.HEIGHT + self.HEIGHTPROF,
2264 2264 show=show)
2265 2265
2266 2266 nrow, ncol = self.getSubplots()
2267 2267
2268 2268 counter = 0
2269 2269 for y in range(nrow):
2270 2270 for x in range(ncol):
2271 2271
2272 2272 if counter >= self.nplots:
2273 2273 break
2274 2274
2275 2275 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
2276 2276
2277 2277 counter += 1
2278 2278
2279 2279 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
2280 2280 xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None,
2281 2281 vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA',
2282 2282 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
2283 2283 server=None, folder=None, username=None, password=None,
2284 2284 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
2285 2285 xaxis="frequency"):
2286 2286
2287 2287 """
2288 2288
2289 2289 Input:
2290 2290 dataOut :
2291 2291 id :
2292 2292 wintitle :
2293 2293 channelList :
2294 2294 showProfile :
2295 2295 xmin : None,
2296 2296 xmax : None,
2297 2297 ymin : None,
2298 2298 ymax : None,
2299 2299 zmin : None,
2300 2300 zmax : None
2301 2301 """
2302 2302 #Rebuild matrix
2303 2303 utctime = dataOut.data_param[0,0]
2304 2304 cmet = dataOut.data_param[:,1].astype(int)
2305 2305 tmet = dataOut.data_param[:,2].astype(int)
2306 2306 hmet = dataOut.data_param[:,3].astype(int)
2307 2307
2308 2308 nParam = 3
2309 2309 nChan = len(dataOut.groupList)
2310 2310 x = dataOut.abscissaList
2311 2311 y = dataOut.heightList
2312 2312
2313 2313 z = numpy.full((nChan, nParam, y.size, x.size - 1),numpy.nan)
2314 2314 z[cmet,:,hmet,tmet] = dataOut.data_param[:,4:]
2315 2315 z[:,0,:,:] = 10*numpy.log10(z[:,0,:,:]) #logarithmic scale
2316 2316 z = numpy.reshape(z, (nChan*nParam, y.size, x.size-1))
2317 2317
2318 2318 xlabel = "Time (s)"
2319 2319 ylabel = "Range (km)"
2320 2320
2321 2321 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
2322 2322
2323 2323 if not self.isConfig:
2324 2324
2325 2325 nplots = nParam*nChan
2326 2326
2327 2327 self.setup(id=id,
2328 2328 nplots=nplots,
2329 2329 wintitle=wintitle,
2330 2330 show=show)
2331 2331
2332 2332 if xmin is None: xmin = numpy.nanmin(x)
2333 2333 if xmax is None: xmax = numpy.nanmax(x)
2334 2334 if ymin is None: ymin = numpy.nanmin(y)
2335 2335 if ymax is None: ymax = numpy.nanmax(y)
2336 2336 if SNRmin is None: SNRmin = numpy.nanmin(z[0,:])
2337 2337 if SNRmax is None: SNRmax = numpy.nanmax(z[0,:])
2338 2338 if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:]))
2339 2339 if vmin is None: vmin = -vmax
2340 2340 if wmin is None: wmin = 0
2341 2341 if wmax is None: wmax = 50
2342 2342
2343 2343 self.nChannels = nChan
2344 2344
2345 2345 zminList = []
2346 2346 zmaxList = []
2347 2347 titleList = []
2348 2348 cmapList = []
2349 2349 for i in range(self.nChannels):
2350 2350 strAux1 = "SNR Channel "+ str(i)
2351 2351 strAux2 = "Radial Velocity Channel "+ str(i)
2352 2352 strAux3 = "Spectral Width Channel "+ str(i)
2353 2353
2354 2354 titleList = titleList + [strAux1,strAux2,strAux3]
2355 2355 cmapList = cmapList + ["jet","RdBu_r","jet"]
2356 2356 zminList = zminList + [SNRmin,vmin,wmin]
2357 2357 zmaxList = zmaxList + [SNRmax,vmax,wmax]
2358 2358
2359 2359 self.zminList = zminList
2360 2360 self.zmaxList = zmaxList
2361 2361 self.cmapList = cmapList
2362 2362 self.titleList = titleList
2363 2363
2364 2364 self.FTP_WEI = ftp_wei
2365 2365 self.EXP_CODE = exp_code
2366 2366 self.SUB_EXP_CODE = sub_exp_code
2367 2367 self.PLOT_POS = plot_pos
2368 2368
2369 2369 self.isConfig = True
2370 2370
2371 2371 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
2372 2372
2373 2373 for i in range(self.nplots):
2374 2374 title = self.titleList[i] + ": " +str_datetime
2375 2375 axes = self.axesList[i]
2376 2376 axes.pcolor(x, y, z[i,:].T,
2377 2377 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i],
2378 2378 xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='')
2379 2379 self.draw()
2380 2380
2381 2381 if figfile == None:
2382 2382 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
2383 2383 name = str_datetime
2384 2384 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
2385 2385 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
2386 2386 figfile = self.getFilename(name)
2387 2387
2388 2388 self.save(figpath=figpath,
2389 2389 figfile=figfile,
2390 2390 save=save,
2391 2391 ftp=ftp,
2392 2392 wr_period=wr_period,
2393 2393 thisDatetime=thisDatetime)
2394 2394 No newline at end of file
@@ -1,1588 +1,1589
1 1 '''
2 2 Created on Jul 9, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9
10 10 from .figure import Figure, isRealtime, isTimeInHourRange
11 11 from .plotting_codes import *
12 12 from schainpy.model.proc.jroproc_base import MPDecorator
13 13
14 14 from schainpy.utils import log
15 15
16 16 @MPDecorator
17 17 class SpectraPlot_(Figure):
18 18
19 19 isConfig = None
20 20 __nsubplots = None
21 21
22 22 WIDTHPROF = None
23 23 HEIGHTPROF = None
24 24 PREFIX = 'spc'
25 25
26 26 def __init__(self):
27 27 Figure.__init__(self)
28 28 self.isConfig = False
29 29 self.__nsubplots = 1
30 30 self.WIDTH = 250
31 31 self.HEIGHT = 250
32 32 self.WIDTHPROF = 120
33 33 self.HEIGHTPROF = 0
34 34 self.counter_imagwr = 0
35 35
36 36 self.PLOT_CODE = SPEC_CODE
37 37
38 38 self.FTP_WEI = None
39 39 self.EXP_CODE = None
40 40 self.SUB_EXP_CODE = None
41 41 self.PLOT_POS = None
42 42
43 43 self.__xfilter_ena = False
44 44 self.__yfilter_ena = False
45 45
46 46 self.indice=1
47 47
48 48 def getSubplots(self):
49 49
50 50 ncol = int(numpy.sqrt(self.nplots)+0.9)
51 51 nrow = int(self.nplots*1./ncol + 0.9)
52 52
53 53 return nrow, ncol
54 54
55 55 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
56 56
57 57 self.__showprofile = showprofile
58 58 self.nplots = nplots
59 59
60 60 ncolspan = 1
61 61 colspan = 1
62 62 if showprofile:
63 63 ncolspan = 3
64 64 colspan = 2
65 65 self.__nsubplots = 2
66 66
67 67 self.createFigure(id = id,
68 68 wintitle = wintitle,
69 69 widthplot = self.WIDTH + self.WIDTHPROF,
70 70 heightplot = self.HEIGHT + self.HEIGHTPROF,
71 71 show=show)
72 72
73 73 nrow, ncol = self.getSubplots()
74 74
75 75 counter = 0
76 76 for y in range(nrow):
77 77 for x in range(ncol):
78 78
79 79 if counter >= self.nplots:
80 80 break
81 81
82 82 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
83 83
84 84 if showprofile:
85 85 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
86 86
87 87 counter += 1
88 88
89 89 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
90 90 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
91 91 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
92 92 server=None, folder=None, username=None, password=None,
93 93 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
94 94 xaxis="frequency", colormap='jet', normFactor=None):
95 95
96 96 """
97 97
98 98 Input:
99 99 dataOut :
100 100 id :
101 101 wintitle :
102 102 channelList :
103 103 showProfile :
104 104 xmin : None,
105 105 xmax : None,
106 106 ymin : None,
107 107 ymax : None,
108 108 zmin : None,
109 109 zmax : None
110 110 """
111 111 if dataOut.flagNoData:
112 112 return dataOut
113 113
114 114 if realtime:
115 115 if not(isRealtime(utcdatatime = dataOut.utctime)):
116 116 print('Skipping this plot function')
117 117 return
118 118
119 119 if channelList == None:
120 120 channelIndexList = dataOut.channelIndexList
121 121 else:
122 122 channelIndexList = []
123 123 for channel in channelList:
124 124 if channel not in dataOut.channelList:
125 125 raise ValueError("Channel %d is not in dataOut.channelList" %channel)
126 126 channelIndexList.append(dataOut.channelList.index(channel))
127 127
128 128 if normFactor is None:
129 129 factor = dataOut.normFactor
130 130 else:
131 131 factor = normFactor
132 132 if xaxis == "frequency":
133 133 x = dataOut.getFreqRange(1)/1000.
134 134 xlabel = "Frequency (kHz)"
135 135
136 136 elif xaxis == "time":
137 137 x = dataOut.getAcfRange(1)
138 138 xlabel = "Time (ms)"
139 139
140 140 else:
141 141 x = dataOut.getVelRange(1)
142 142 xlabel = "Velocity (m/s)"
143 143
144 144 ylabel = "Range (km)"
145 145
146 146 y = dataOut.getHeiRange()
147 147 z = dataOut.data_spc/factor
148 148 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
149 149 zdB = 10*numpy.log10(z)
150 150
151 151 avg = numpy.average(z, axis=1)
152 152 avgdB = 10*numpy.log10(avg)
153 153
154 154 noise = dataOut.getNoise()/factor
155 155 noisedB = 10*numpy.log10(noise)
156 156
157 157 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
158 158 title = wintitle + " Spectra"
159 159
160 160 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
161 161 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
162 162
163 163 if not self.isConfig:
164 164
165 165 nplots = len(channelIndexList)
166 166
167 167 self.setup(id=id,
168 168 nplots=nplots,
169 169 wintitle=wintitle,
170 170 showprofile=showprofile,
171 171 show=show)
172 172
173 173 if xmin == None: xmin = numpy.nanmin(x)
174 174 if xmax == None: xmax = numpy.nanmax(x)
175 175 if ymin == None: ymin = numpy.nanmin(y)
176 176 if ymax == None: ymax = numpy.nanmax(y)
177 177 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
178 178 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
179 179
180 180 self.FTP_WEI = ftp_wei
181 181 self.EXP_CODE = exp_code
182 182 self.SUB_EXP_CODE = sub_exp_code
183 183 self.PLOT_POS = plot_pos
184 184
185 185 self.isConfig = True
186 186
187 187 self.setWinTitle(title)
188 188
189 189 for i in range(self.nplots):
190 190 index = channelIndexList[i]
191 191 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
192 192 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime)
193 193 if len(dataOut.beam.codeList) != 0:
194 194 title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime)
195 195
196 196 axes = self.axesList[i*self.__nsubplots]
197 197 axes.pcolor(x, y, zdB[index,:,:],
198 198 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
199 199 xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap,
200 200 ticksize=9, cblabel='')
201 201
202 202 if self.__showprofile:
203 203 axes = self.axesList[i*self.__nsubplots +1]
204 204 axes.pline(avgdB[index,:], y,
205 205 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
206 206 xlabel='dB', ylabel='', title='',
207 207 ytick_visible=False,
208 208 grid='x')
209 209
210 210 noiseline = numpy.repeat(noisedB[index], len(y))
211 211 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
212 212
213 213 self.draw()
214 214
215 215 if figfile == None:
216 216 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
217 217 name = str_datetime
218 218 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
219 219 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
220 220 figfile = self.getFilename(name)
221 221
222 222 self.save(figpath=figpath,
223 223 figfile=figfile,
224 224 save=save,
225 225 ftp=ftp,
226 226 wr_period=wr_period,
227 227 thisDatetime=thisDatetime)
228 228
229 229
230 230 return dataOut
231
231 232 @MPDecorator
232 233 class CrossSpectraPlot_(Figure):
233 234
234 235 isConfig = None
235 236 __nsubplots = None
236 237
237 238 WIDTH = None
238 239 HEIGHT = None
239 240 WIDTHPROF = None
240 241 HEIGHTPROF = None
241 242 PREFIX = 'cspc'
242 243
243 244 def __init__(self):
244 245 Figure.__init__(self)
245 246 self.isConfig = False
246 247 self.__nsubplots = 4
247 248 self.counter_imagwr = 0
248 249 self.WIDTH = 250
249 250 self.HEIGHT = 250
250 251 self.WIDTHPROF = 0
251 252 self.HEIGHTPROF = 0
252 253
253 254 self.PLOT_CODE = CROSS_CODE
254 255 self.FTP_WEI = None
255 256 self.EXP_CODE = None
256 257 self.SUB_EXP_CODE = None
257 258 self.PLOT_POS = None
258 259
259 260 self.indice=0
260 261
261 262 def getSubplots(self):
262 263
263 264 ncol = 4
264 265 nrow = self.nplots
265 266
266 267 return nrow, ncol
267 268
268 269 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
269 270
270 271 self.__showprofile = showprofile
271 272 self.nplots = nplots
272 273
273 274 ncolspan = 1
274 275 colspan = 1
275 276
276 277 self.createFigure(id = id,
277 278 wintitle = wintitle,
278 279 widthplot = self.WIDTH + self.WIDTHPROF,
279 280 heightplot = self.HEIGHT + self.HEIGHTPROF,
280 281 show=True)
281 282
282 283 nrow, ncol = self.getSubplots()
283 284
284 285 counter = 0
285 286 for y in range(nrow):
286 287 for x in range(ncol):
287 288 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
288 289
289 290 counter += 1
290 291
291 292 def run(self, dataOut, id, wintitle="", pairsList=None,
292 293 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
293 294 coh_min=None, coh_max=None, phase_min=None, phase_max=None,
294 295 save=False, figpath='./', figfile=None, ftp=False, wr_period=1,
295 296 power_cmap='jet', coherence_cmap='jet', phase_cmap='RdBu_r', show=True,
296 297 server=None, folder=None, username=None, password=None,
297 298 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, normFactor=None,
298 299 xaxis='frequency'):
299 300
300 301 """
301 302
302 303 Input:
303 304 dataOut :
304 305 id :
305 306 wintitle :
306 307 channelList :
307 308 showProfile :
308 309 xmin : None,
309 310 xmax : None,
310 311 ymin : None,
311 312 ymax : None,
312 313 zmin : None,
313 314 zmax : None
314 315 """
315 316
316 317 if dataOut.flagNoData:
317 318 return dataOut
318 319
319 320 if pairsList == None:
320 321 pairsIndexList = dataOut.pairsIndexList
321 322 else:
322 323 pairsIndexList = []
323 324 for pair in pairsList:
324 325 if pair not in dataOut.pairsList:
325 326 raise ValueError("Pair %s is not in dataOut.pairsList" %str(pair))
326 327 pairsIndexList.append(dataOut.pairsList.index(pair))
327 328
328 329 if not pairsIndexList:
329 330 return
330 331
331 332 if len(pairsIndexList) > 4:
332 333 pairsIndexList = pairsIndexList[0:4]
333 334
334 335 if normFactor is None:
335 336 factor = dataOut.normFactor
336 337 else:
337 338 factor = normFactor
338 339 x = dataOut.getVelRange(1)
339 340 y = dataOut.getHeiRange()
340 341 z = dataOut.data_spc[:,:,:]/factor
341 342 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
342 343
343 344 noise = dataOut.noise/factor
344 345
345 346 zdB = 10*numpy.log10(z)
346 347 noisedB = 10*numpy.log10(noise)
347 348
348 349 if coh_min == None:
349 350 coh_min = 0.0
350 351 if coh_max == None:
351 352 coh_max = 1.0
352 353
353 354 if phase_min == None:
354 355 phase_min = -180
355 356 if phase_max == None:
356 357 phase_max = 180
357 358
358 359 #thisDatetime = dataOut.datatime
359 360 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
360 361 title = wintitle + " Cross-Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
361 # xlabel = "Velocity (m/s)"
362 # xlabel = "Velocity (m/s)"
362 363 ylabel = "Range (Km)"
363 364
364 365 if xaxis == "frequency":
365 366 x = dataOut.getFreqRange(1)/1000.
366 367 xlabel = "Frequency (kHz)"
367 368
368 369 elif xaxis == "time":
369 370 x = dataOut.getAcfRange(1)
370 371 xlabel = "Time (ms)"
371 372
372 373 else:
373 374 x = dataOut.getVelRange(1)
374 375 xlabel = "Velocity (m/s)"
375 376
376 377 if not self.isConfig:
377 378
378 379 nplots = len(pairsIndexList)
379 380
380 381 self.setup(id=id,
381 382 nplots=nplots,
382 383 wintitle=wintitle,
383 384 showprofile=False,
384 385 show=show)
385 386
386 387 avg = numpy.abs(numpy.average(z, axis=1))
387 388 avgdB = 10*numpy.log10(avg)
388 389
389 390 if xmin == None: xmin = numpy.nanmin(x)
390 391 if xmax == None: xmax = numpy.nanmax(x)
391 392 if ymin == None: ymin = numpy.nanmin(y)
392 393 if ymax == None: ymax = numpy.nanmax(y)
393 394 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
394 395 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
395 396
396 397 self.FTP_WEI = ftp_wei
397 398 self.EXP_CODE = exp_code
398 399 self.SUB_EXP_CODE = sub_exp_code
399 400 self.PLOT_POS = plot_pos
400 401
401 402 self.isConfig = True
402 403
403 404 self.setWinTitle(title)
404 405
405 406
406 407 for i in range(self.nplots):
407 408 pair = dataOut.pairsList[pairsIndexList[i]]
408 409
409 410 chan_index0 = dataOut.channelList.index(pair[0])
410 411 chan_index1 = dataOut.channelList.index(pair[1])
411 412
412 413 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
413 414 title = "Ch%d: %4.2fdB: %s" %(pair[0], noisedB[chan_index0], str_datetime)
414 415 zdB = 10.*numpy.log10(dataOut.data_spc[chan_index0,:,:]/factor)
415 416 axes0 = self.axesList[i*self.__nsubplots]
416 417 axes0.pcolor(x, y, zdB,
417 418 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
418 419 xlabel=xlabel, ylabel=ylabel, title=title,
419 420 ticksize=9, colormap=power_cmap, cblabel='')
420 421
421 422 title = "Ch%d: %4.2fdB: %s" %(pair[1], noisedB[chan_index1], str_datetime)
422 423 zdB = 10.*numpy.log10(dataOut.data_spc[chan_index1,:,:]/factor)
423 424 axes0 = self.axesList[i*self.__nsubplots+1]
424 425 axes0.pcolor(x, y, zdB,
425 426 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
426 427 xlabel=xlabel, ylabel=ylabel, title=title,
427 428 ticksize=9, colormap=power_cmap, cblabel='')
428 429
429 430 coherenceComplex = dataOut.data_cspc[pairsIndexList[i],:,:] / numpy.sqrt( dataOut.data_spc[chan_index0,:,:]*dataOut.data_spc[chan_index1,:,:] )
430 431 coherence = numpy.abs(coherenceComplex)
431 # phase = numpy.arctan(-1*coherenceComplex.imag/coherenceComplex.real)*180/numpy.pi
432 # phase = numpy.arctan(-1*coherenceComplex.imag/coherenceComplex.real)*180/numpy.pi
432 433 phase = numpy.arctan2(coherenceComplex.imag, coherenceComplex.real)*180/numpy.pi
433 434
434 435 title = "Coherence Ch%d * Ch%d" %(pair[0], pair[1])
435 436 axes0 = self.axesList[i*self.__nsubplots+2]
436 437 axes0.pcolor(x, y, coherence,
437 438 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=coh_min, zmax=coh_max,
438 439 xlabel=xlabel, ylabel=ylabel, title=title,
439 440 ticksize=9, colormap=coherence_cmap, cblabel='')
440 441
441 442 title = "Phase Ch%d * Ch%d" %(pair[0], pair[1])
442 443 axes0 = self.axesList[i*self.__nsubplots+3]
443 444 axes0.pcolor(x, y, phase,
444 445 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max,
445 446 xlabel=xlabel, ylabel=ylabel, title=title,
446 447 ticksize=9, colormap=phase_cmap, cblabel='')
447 448
448 449 self.draw()
449 450
450 451 self.save(figpath=figpath,
451 452 figfile=figfile,
452 453 save=save,
453 454 ftp=ftp,
454 455 wr_period=wr_period,
455 456 thisDatetime=thisDatetime)
456 457
457 458 return dataOut
458 459
459 460 @MPDecorator
460 461 class RTIPlot_(Figure):
461 462
462 463 __isConfig = None
463 464 __nsubplots = None
464 465
465 466 WIDTHPROF = None
466 467 HEIGHTPROF = None
467 468 PREFIX = 'rti'
468 469
469 470 def __init__(self):
470 471
471 472 Figure.__init__(self)
472 473 self.timerange = None
473 474 self.isConfig = False
474 475 self.__nsubplots = 1
475 476
476 477 self.WIDTH = 800
477 478 self.HEIGHT = 250
478 479 self.WIDTHPROF = 120
479 480 self.HEIGHTPROF = 0
480 481 self.counter_imagwr = 0
481 482
482 483 self.PLOT_CODE = RTI_CODE
483 484
484 485 self.FTP_WEI = None
485 486 self.EXP_CODE = None
486 487 self.SUB_EXP_CODE = None
487 488 self.PLOT_POS = None
488 489 self.tmin = None
489 490 self.tmax = None
490 491
491 492 self.xmin = None
492 493 self.xmax = None
493 494
494 495 self.figfile = None
495 496
496 497 def getSubplots(self):
497 498
498 499 ncol = 1
499 500 nrow = self.nplots
500 501
501 502 return nrow, ncol
502 503
503 504 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
504 505
505 506 self.__showprofile = showprofile
506 507 self.nplots = nplots
507 508
508 509 ncolspan = 1
509 510 colspan = 1
510 511 if showprofile:
511 512 ncolspan = 7
512 513 colspan = 6
513 514 self.__nsubplots = 2
514 515
515 516 self.createFigure(id = id,
516 517 wintitle = wintitle,
517 518 widthplot = self.WIDTH + self.WIDTHPROF,
518 519 heightplot = self.HEIGHT + self.HEIGHTPROF,
519 520 show=show)
520 521
521 522 nrow, ncol = self.getSubplots()
522 523
523 524 counter = 0
524 525 for y in range(nrow):
525 526 for x in range(ncol):
526 527
527 528 if counter >= self.nplots:
528 529 break
529 530
530 531 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
531 532
532 533 if showprofile:
533 534 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
534 535
535 536 counter += 1
536 537
537 538 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
538 539 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
539 540 timerange=None, colormap='jet',
540 541 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
541 542 server=None, folder=None, username=None, password=None,
542 543 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, normFactor=None, HEIGHT=None):
543 544
544 545 """
545 546
546 547 Input:
547 548 dataOut :
548 549 id :
549 550 wintitle :
550 551 channelList :
551 552 showProfile :
552 553 xmin : None,
553 554 xmax : None,
554 555 ymin : None,
555 556 ymax : None,
556 557 zmin : None,
557 558 zmax : None
558 559 """
559 560 if dataOut.flagNoData:
560 561 return dataOut
561 562
562 563 #colormap = kwargs.get('colormap', 'jet')
563 564 if HEIGHT is not None:
564 565 self.HEIGHT = HEIGHT
565 566
566 567 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
567 568 return
568 569
569 570 if channelList == None:
570 571 channelIndexList = dataOut.channelIndexList
571 572 else:
572 573 channelIndexList = []
573 574 for channel in channelList:
574 575 if channel not in dataOut.channelList:
575 576 raise ValueError("Channel %d is not in dataOut.channelList")
576 577 channelIndexList.append(dataOut.channelList.index(channel))
577 578
578 579 if normFactor is None:
579 580 factor = dataOut.normFactor
580 581 else:
581 582 factor = normFactor
582 583
583 584 #factor = dataOut.normFactor
584 585 x = dataOut.getTimeRange()
585 586 y = dataOut.getHeiRange()
586 587
587 588 z = dataOut.data_spc/factor
588 589 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
589 590 avg = numpy.average(z, axis=1)
590 591 avgdB = 10.*numpy.log10(avg)
591 592 # avgdB = dataOut.getPower()
592 593
593 594
594 595 thisDatetime = dataOut.datatime
595 596 #thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
596 597 title = wintitle + " RTI" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
597 598 xlabel = ""
598 599 ylabel = "Range (Km)"
599 600
600 601 update_figfile = False
601 602
602 603 if self.xmax is not None and dataOut.ltctime >= self.xmax: #yong
603 604 self.counter_imagwr = wr_period
604 605 self.isConfig = False
605 606 update_figfile = True
606 607
607 608 if not self.isConfig:
608 609
609 610 nplots = len(channelIndexList)
610 611
611 612 self.setup(id=id,
612 613 nplots=nplots,
613 614 wintitle=wintitle,
614 615 showprofile=showprofile,
615 616 show=show)
616 617
617 618 if timerange != None:
618 619 self.timerange = timerange
619 620
620 621 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
621 622
622 623 noise = dataOut.noise/factor
623 624 noisedB = 10*numpy.log10(noise)
624 625
625 626 if ymin == None: ymin = numpy.nanmin(y)
626 627 if ymax == None: ymax = numpy.nanmax(y)
627 628 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
628 629 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
629 630
630 631 self.FTP_WEI = ftp_wei
631 632 self.EXP_CODE = exp_code
632 633 self.SUB_EXP_CODE = sub_exp_code
633 634 self.PLOT_POS = plot_pos
634 635
635 636 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
636 637 self.isConfig = True
637 638 self.figfile = figfile
638 639 update_figfile = True
639 640
640 641 self.setWinTitle(title)
641 642
642 643 for i in range(self.nplots):
643 644 index = channelIndexList[i]
644 645 title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
645 646 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
646 647 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
647 648 axes = self.axesList[i*self.__nsubplots]
648 649 zdB = avgdB[index].reshape((1,-1))
649 650 axes.pcolorbuffer(x, y, zdB,
650 651 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
651 652 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
652 653 ticksize=9, cblabel='', cbsize="1%", colormap=colormap)
653 654
654 655 if self.__showprofile:
655 656 axes = self.axesList[i*self.__nsubplots +1]
656 657 axes.pline(avgdB[index], y,
657 658 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
658 659 xlabel='dB', ylabel='', title='',
659 660 ytick_visible=False,
660 661 grid='x')
661 662
662 663 self.draw()
663 664
664 665 self.save(figpath=figpath,
665 666 figfile=figfile,
666 667 save=save,
667 668 ftp=ftp,
668 669 wr_period=wr_period,
669 670 thisDatetime=thisDatetime,
670 671 update_figfile=update_figfile)
671 672 return dataOut
672 673
673 674 @MPDecorator
674 675 class CoherenceMap_(Figure):
675 676 isConfig = None
676 677 __nsubplots = None
677 678
678 679 WIDTHPROF = None
679 680 HEIGHTPROF = None
680 681 PREFIX = 'cmap'
681 682
682 683 def __init__(self):
683 684 Figure.__init__(self)
684 685 self.timerange = 2*60*60
685 686 self.isConfig = False
686 687 self.__nsubplots = 1
687 688
688 689 self.WIDTH = 800
689 690 self.HEIGHT = 180
690 691 self.WIDTHPROF = 120
691 692 self.HEIGHTPROF = 0
692 693 self.counter_imagwr = 0
693 694
694 695 self.PLOT_CODE = COH_CODE
695 696
696 697 self.FTP_WEI = None
697 698 self.EXP_CODE = None
698 699 self.SUB_EXP_CODE = None
699 700 self.PLOT_POS = None
700 701 self.counter_imagwr = 0
701 702
702 703 self.xmin = None
703 704 self.xmax = None
704 705
705 706 def getSubplots(self):
706 707 ncol = 1
707 708 nrow = self.nplots*2
708 709
709 710 return nrow, ncol
710 711
711 712 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
712 713 self.__showprofile = showprofile
713 714 self.nplots = nplots
714 715
715 716 ncolspan = 1
716 717 colspan = 1
717 718 if showprofile:
718 719 ncolspan = 7
719 720 colspan = 6
720 721 self.__nsubplots = 2
721 722
722 723 self.createFigure(id = id,
723 724 wintitle = wintitle,
724 725 widthplot = self.WIDTH + self.WIDTHPROF,
725 726 heightplot = self.HEIGHT + self.HEIGHTPROF,
726 727 show=True)
727 728
728 729 nrow, ncol = self.getSubplots()
729 730
730 731 for y in range(nrow):
731 732 for x in range(ncol):
732 733
733 734 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
734 735
735 736 if showprofile:
736 737 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
737 738
738 739 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
739 740 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
740 741 timerange=None, phase_min=None, phase_max=None,
741 742 save=False, figpath='./', figfile=None, ftp=False, wr_period=1,
742 743 coherence_cmap='jet', phase_cmap='RdBu_r', show=True,
743 744 server=None, folder=None, username=None, password=None,
744 745 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
745 746
746 747
747 748 if dataOut.flagNoData:
748 749 return dataOut
749 750
750 751 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
751 752 return
752 753
753 754 if pairsList == None:
754 755 pairsIndexList = dataOut.pairsIndexList
755 756 else:
756 757 pairsIndexList = []
757 758 for pair in pairsList:
758 759 if pair not in dataOut.pairsList:
759 760 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
760 761 pairsIndexList.append(dataOut.pairsList.index(pair))
761 762
762 763 if pairsIndexList == []:
763 764 return
764 765
765 766 if len(pairsIndexList) > 4:
766 767 pairsIndexList = pairsIndexList[0:4]
767 768
768 769 if phase_min == None:
769 770 phase_min = -180
770 771 if phase_max == None:
771 772 phase_max = 180
772 773
773 774 x = dataOut.getTimeRange()
774 775 y = dataOut.getHeiRange()
775 776
776 777 thisDatetime = dataOut.datatime
777 778
778 779 title = wintitle + " CoherenceMap" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
779 780 xlabel = ""
780 781 ylabel = "Range (Km)"
781 782 update_figfile = False
782 783
783 784 if not self.isConfig:
784 785 nplots = len(pairsIndexList)
785 786 self.setup(id=id,
786 787 nplots=nplots,
787 788 wintitle=wintitle,
788 789 showprofile=showprofile,
789 790 show=show)
790 791
791 792 if timerange != None:
792 793 self.timerange = timerange
793 794
794 795 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
795 796
796 797 if ymin == None: ymin = numpy.nanmin(y)
797 798 if ymax == None: ymax = numpy.nanmax(y)
798 799 if zmin == None: zmin = 0.
799 800 if zmax == None: zmax = 1.
800 801
801 802 self.FTP_WEI = ftp_wei
802 803 self.EXP_CODE = exp_code
803 804 self.SUB_EXP_CODE = sub_exp_code
804 805 self.PLOT_POS = plot_pos
805 806
806 807 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
807 808
808 809 self.isConfig = True
809 810 update_figfile = True
810 811
811 812 self.setWinTitle(title)
812 813
813 814 for i in range(self.nplots):
814 815
815 816 pair = dataOut.pairsList[pairsIndexList[i]]
816 817
817 818 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i],:,:],axis=0)
818 819 powa = numpy.average(dataOut.data_spc[pair[0],:,:],axis=0)
819 820 powb = numpy.average(dataOut.data_spc[pair[1],:,:],axis=0)
820 821
821 822
822 823 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
823 824 coherence = numpy.abs(avgcoherenceComplex)
824 825
825 826 z = coherence.reshape((1,-1))
826 827
827 828 counter = 0
828 829
829 830 title = "Coherence Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
830 831 axes = self.axesList[i*self.__nsubplots*2]
831 832 axes.pcolorbuffer(x, y, z,
832 833 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
833 834 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
834 835 ticksize=9, cblabel='', colormap=coherence_cmap, cbsize="1%")
835 836
836 837 if self.__showprofile:
837 838 counter += 1
838 839 axes = self.axesList[i*self.__nsubplots*2 + counter]
839 840 axes.pline(coherence, y,
840 841 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
841 842 xlabel='', ylabel='', title='', ticksize=7,
842 843 ytick_visible=False, nxticks=5,
843 844 grid='x')
844 845
845 846 counter += 1
846 847
847 848 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
848 849
849 850 z = phase.reshape((1,-1))
850 851
851 852 title = "Phase Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
852 853 axes = self.axesList[i*self.__nsubplots*2 + counter]
853 854 axes.pcolorbuffer(x, y, z,
854 855 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max,
855 856 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
856 857 ticksize=9, cblabel='', colormap=phase_cmap, cbsize="1%")
857 858
858 859 if self.__showprofile:
859 860 counter += 1
860 861 axes = self.axesList[i*self.__nsubplots*2 + counter]
861 862 axes.pline(phase, y,
862 863 xmin=phase_min, xmax=phase_max, ymin=ymin, ymax=ymax,
863 864 xlabel='', ylabel='', title='', ticksize=7,
864 865 ytick_visible=False, nxticks=4,
865 866 grid='x')
866 867
867 868 self.draw()
868 869
869 870 if dataOut.ltctime >= self.xmax:
870 871 self.counter_imagwr = wr_period
871 872 self.isConfig = False
872 873 update_figfile = True
873 874
874 875 self.save(figpath=figpath,
875 876 figfile=figfile,
876 877 save=save,
877 878 ftp=ftp,
878 879 wr_period=wr_period,
879 880 thisDatetime=thisDatetime,
880 881 update_figfile=update_figfile)
881 882
882 883 return dataOut
883 884
884 885 @MPDecorator
885 886 class PowerProfilePlot_(Figure):
886 887
887 888 isConfig = None
888 889 __nsubplots = None
889 890
890 891 WIDTHPROF = None
891 892 HEIGHTPROF = None
892 893 PREFIX = 'spcprofile'
893 894
894 895 def __init__(self):
895 896 Figure.__init__(self)
896 897 self.isConfig = False
897 898 self.__nsubplots = 1
898 899
899 900 self.PLOT_CODE = POWER_CODE
900 901
901 902 self.WIDTH = 300
902 903 self.HEIGHT = 500
903 904 self.counter_imagwr = 0
904 905
905 906 def getSubplots(self):
906 907 ncol = 1
907 908 nrow = 1
908 909
909 910 return nrow, ncol
910 911
911 912 def setup(self, id, nplots, wintitle, show):
912 913
913 914 self.nplots = nplots
914 915
915 916 ncolspan = 1
916 917 colspan = 1
917 918
918 919 self.createFigure(id = id,
919 920 wintitle = wintitle,
920 921 widthplot = self.WIDTH,
921 922 heightplot = self.HEIGHT,
922 923 show=show)
923 924
924 925 nrow, ncol = self.getSubplots()
925 926
926 927 counter = 0
927 928 for y in range(nrow):
928 929 for x in range(ncol):
929 930 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
930 931
931 932 def run(self, dataOut, id, wintitle="", channelList=None,
932 933 xmin=None, xmax=None, ymin=None, ymax=None,
933 934 save=False, figpath='./', figfile=None, show=True,
934 935 ftp=False, wr_period=1, server=None,
935 936 folder=None, username=None, password=None):
936 937
937 938 if dataOut.flagNoData:
938 939 return dataOut
939 940
940 941
941 942 if channelList == None:
942 943 channelIndexList = dataOut.channelIndexList
943 944 channelList = dataOut.channelList
944 945 else:
945 946 channelIndexList = []
946 947 for channel in channelList:
947 948 if channel not in dataOut.channelList:
948 949 raise ValueError("Channel %d is not in dataOut.channelList")
949 950 channelIndexList.append(dataOut.channelList.index(channel))
950 951
951 952 factor = dataOut.normFactor
952 953
953 954 y = dataOut.getHeiRange()
954 955
955 956 #for voltage
956 957 if dataOut.type == 'Voltage':
957 958 x = dataOut.data[channelIndexList,:] * numpy.conjugate(dataOut.data[channelIndexList,:])
958 959 x = x.real
959 960 x = numpy.where(numpy.isfinite(x), x, numpy.NAN)
960 961
961 962 #for spectra
962 963 if dataOut.type == 'Spectra':
963 964 x = dataOut.data_spc[channelIndexList,:,:]/factor
964 965 x = numpy.where(numpy.isfinite(x), x, numpy.NAN)
965 966 x = numpy.average(x, axis=1)
966 967
967 968
968 969 xdB = 10*numpy.log10(x)
969 970
970 971 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
971 972 title = wintitle + " Power Profile %s" %(thisDatetime.strftime("%d-%b-%Y"))
972 973 xlabel = "dB"
973 974 ylabel = "Range (Km)"
974 975
975 976 if not self.isConfig:
976 977
977 978 nplots = 1
978 979
979 980 self.setup(id=id,
980 981 nplots=nplots,
981 982 wintitle=wintitle,
982 983 show=show)
983 984
984 985 if ymin == None: ymin = numpy.nanmin(y)
985 986 if ymax == None: ymax = numpy.nanmax(y)
986 987 if xmin == None: xmin = numpy.nanmin(xdB)*0.9
987 988 if xmax == None: xmax = numpy.nanmax(xdB)*1.1
988 989
989 990 self.isConfig = True
990 991
991 992 self.setWinTitle(title)
992 993
993 994 title = "Power Profile: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
994 995 axes = self.axesList[0]
995 996
996 997 legendlabels = ["channel %d"%x for x in channelList]
997 998 axes.pmultiline(xdB, y,
998 999 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
999 1000 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels,
1000 1001 ytick_visible=True, nxticks=5,
1001 1002 grid='x')
1002 1003
1003 1004 self.draw()
1004 1005
1005 1006 self.save(figpath=figpath,
1006 1007 figfile=figfile,
1007 1008 save=save,
1008 1009 ftp=ftp,
1009 1010 wr_period=wr_period,
1010 1011 thisDatetime=thisDatetime)
1011 1012
1012 1013 return dataOut
1013 1014
1014 1015 @MPDecorator
1015 1016 class SpectraCutPlot_(Figure):
1016 1017
1017 1018 isConfig = None
1018 1019 __nsubplots = None
1019 1020
1020 1021 WIDTHPROF = None
1021 1022 HEIGHTPROF = None
1022 1023 PREFIX = 'spc_cut'
1023 1024
1024 1025 def __init__(self):
1025 1026 Figure.__init__(self)
1026 1027 self.isConfig = False
1027 1028 self.__nsubplots = 1
1028 1029
1029 1030 self.PLOT_CODE = POWER_CODE
1030 1031
1031 1032 self.WIDTH = 700
1032 1033 self.HEIGHT = 500
1033 1034 self.counter_imagwr = 0
1034 1035
1035 1036 def getSubplots(self):
1036 1037 ncol = 1
1037 1038 nrow = 1
1038 1039
1039 1040 return nrow, ncol
1040 1041
1041 1042 def setup(self, id, nplots, wintitle, show):
1042 1043
1043 1044 self.nplots = nplots
1044 1045
1045 1046 ncolspan = 1
1046 1047 colspan = 1
1047 1048
1048 1049 self.createFigure(id = id,
1049 1050 wintitle = wintitle,
1050 1051 widthplot = self.WIDTH,
1051 1052 heightplot = self.HEIGHT,
1052 1053 show=show)
1053 1054
1054 1055 nrow, ncol = self.getSubplots()
1055 1056
1056 1057 counter = 0
1057 1058 for y in range(nrow):
1058 1059 for x in range(ncol):
1059 1060 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1060 1061
1061 1062 def run(self, dataOut, id, wintitle="", channelList=None,
1062 1063 xmin=None, xmax=None, ymin=None, ymax=None,
1063 1064 save=False, figpath='./', figfile=None, show=True,
1064 1065 ftp=False, wr_period=1, server=None,
1065 1066 folder=None, username=None, password=None,
1066 1067 xaxis="frequency"):
1067 1068
1068 1069 if dataOut.flagNoData:
1069 1070 return dataOut
1070 1071
1071 1072 if channelList == None:
1072 1073 channelIndexList = dataOut.channelIndexList
1073 1074 channelList = dataOut.channelList
1074 1075 else:
1075 1076 channelIndexList = []
1076 1077 for channel in channelList:
1077 1078 if channel not in dataOut.channelList:
1078 1079 raise ValueError("Channel %d is not in dataOut.channelList")
1079 1080 channelIndexList.append(dataOut.channelList.index(channel))
1080 1081
1081 1082 factor = dataOut.normFactor
1082 1083
1083 1084 y = dataOut.getHeiRange()
1084 1085
1085 1086 z = dataOut.data_spc/factor
1086 1087 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1087 1088
1088 1089 hei_index = numpy.arange(25)*3 + 20
1089 1090
1090 1091 if xaxis == "frequency":
1091 1092 x = dataOut.getFreqRange()/1000.
1092 1093 zdB = 10*numpy.log10(z[0,:,hei_index])
1093 1094 xlabel = "Frequency (kHz)"
1094 1095 ylabel = "Power (dB)"
1095 1096
1096 1097 elif xaxis == "time":
1097 1098 x = dataOut.getAcfRange()
1098 1099 zdB = z[0,:,hei_index]
1099 1100 xlabel = "Time (ms)"
1100 1101 ylabel = "ACF"
1101 1102
1102 1103 else:
1103 1104 x = dataOut.getVelRange()
1104 1105 zdB = 10*numpy.log10(z[0,:,hei_index])
1105 1106 xlabel = "Velocity (m/s)"
1106 1107 ylabel = "Power (dB)"
1107 1108
1108 1109 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1109 1110 title = wintitle + " Range Cuts %s" %(thisDatetime.strftime("%d-%b-%Y"))
1110 1111
1111 1112 if not self.isConfig:
1112 1113
1113 1114 nplots = 1
1114 1115
1115 1116 self.setup(id=id,
1116 1117 nplots=nplots,
1117 1118 wintitle=wintitle,
1118 1119 show=show)
1119 1120
1120 1121 if xmin == None: xmin = numpy.nanmin(x)*0.9
1121 1122 if xmax == None: xmax = numpy.nanmax(x)*1.1
1122 1123 if ymin == None: ymin = numpy.nanmin(zdB)
1123 1124 if ymax == None: ymax = numpy.nanmax(zdB)
1124 1125
1125 1126 self.isConfig = True
1126 1127
1127 1128 self.setWinTitle(title)
1128 1129
1129 1130 title = "Spectra Cuts: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
1130 1131 axes = self.axesList[0]
1131 1132
1132 1133 legendlabels = ["Range = %dKm" %y[i] for i in hei_index]
1133 1134
1134 1135 axes.pmultilineyaxis( x, zdB,
1135 1136 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1136 1137 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels,
1137 1138 ytick_visible=True, nxticks=5,
1138 1139 grid='x')
1139 1140
1140 1141 self.draw()
1141 1142
1142 1143 self.save(figpath=figpath,
1143 1144 figfile=figfile,
1144 1145 save=save,
1145 1146 ftp=ftp,
1146 1147 wr_period=wr_period,
1147 1148 thisDatetime=thisDatetime)
1148 1149
1149 1150 return dataOut
1150 1151
1151 1152 @MPDecorator
1152 1153 class Noise_(Figure):
1153 1154
1154 1155 isConfig = None
1155 1156 __nsubplots = None
1156 1157
1157 1158 PREFIX = 'noise'
1158 1159
1159 1160
1160 1161 def __init__(self):
1161 1162 Figure.__init__(self)
1162 1163 self.timerange = 24*60*60
1163 1164 self.isConfig = False
1164 1165 self.__nsubplots = 1
1165 1166 self.counter_imagwr = 0
1166 1167 self.WIDTH = 800
1167 1168 self.HEIGHT = 400
1168 1169 self.WIDTHPROF = 120
1169 1170 self.HEIGHTPROF = 0
1170 1171 self.xdata = None
1171 1172 self.ydata = None
1172 1173
1173 1174 self.PLOT_CODE = NOISE_CODE
1174 1175
1175 1176 self.FTP_WEI = None
1176 1177 self.EXP_CODE = None
1177 1178 self.SUB_EXP_CODE = None
1178 1179 self.PLOT_POS = None
1179 1180 self.figfile = None
1180 1181
1181 1182 self.xmin = None
1182 1183 self.xmax = None
1183 1184
1184 1185 def getSubplots(self):
1185 1186
1186 1187 ncol = 1
1187 1188 nrow = 1
1188 1189
1189 1190 return nrow, ncol
1190 1191
1191 1192 def openfile(self, filename):
1192 1193 dirname = os.path.dirname(filename)
1193 1194
1194 1195 if not os.path.exists(dirname):
1195 1196 os.mkdir(dirname)
1196 1197
1197 1198 f = open(filename,'w+')
1198 1199 f.write('\n\n')
1199 1200 f.write('JICAMARCA RADIO OBSERVATORY - Noise \n')
1200 1201 f.write('DD MM YYYY HH MM SS Channel0 Channel1 Channel2 Channel3\n\n' )
1201 1202 f.close()
1202 1203
1203 1204 def save_data(self, filename_phase, data, data_datetime):
1204 1205
1205 1206 f=open(filename_phase,'a')
1206 1207
1207 1208 timetuple_data = data_datetime.timetuple()
1208 1209 day = str(timetuple_data.tm_mday)
1209 1210 month = str(timetuple_data.tm_mon)
1210 1211 year = str(timetuple_data.tm_year)
1211 1212 hour = str(timetuple_data.tm_hour)
1212 1213 minute = str(timetuple_data.tm_min)
1213 1214 second = str(timetuple_data.tm_sec)
1214 1215
1215 1216 data_msg = ''
1216 1217 for i in range(len(data)):
1217 1218 data_msg += str(data[i]) + ' '
1218 1219
1219 1220 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' ' + data_msg + '\n')
1220 1221 f.close()
1221 1222
1222 1223
1223 1224 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1224 1225
1225 1226 self.__showprofile = showprofile
1226 1227 self.nplots = nplots
1227 1228
1228 1229 ncolspan = 7
1229 1230 colspan = 6
1230 1231 self.__nsubplots = 2
1231 1232
1232 1233 self.createFigure(id = id,
1233 1234 wintitle = wintitle,
1234 1235 widthplot = self.WIDTH+self.WIDTHPROF,
1235 1236 heightplot = self.HEIGHT+self.HEIGHTPROF,
1236 1237 show=show)
1237 1238
1238 1239 nrow, ncol = self.getSubplots()
1239 1240
1240 1241 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1241 1242
1242 1243
1243 1244 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
1244 1245 xmin=None, xmax=None, ymin=None, ymax=None,
1245 1246 timerange=None,
1246 1247 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1247 1248 server=None, folder=None, username=None, password=None,
1248 1249 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1249 1250
1250 1251 if dataOut.flagNoData:
1251 1252 return dataOut
1252 1253
1253 1254 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1254 1255 return
1255 1256
1256 1257 if channelList == None:
1257 1258 channelIndexList = dataOut.channelIndexList
1258 1259 channelList = dataOut.channelList
1259 1260 else:
1260 1261 channelIndexList = []
1261 1262 for channel in channelList:
1262 1263 if channel not in dataOut.channelList:
1263 1264 raise ValueError("Channel %d is not in dataOut.channelList")
1264 1265 channelIndexList.append(dataOut.channelList.index(channel))
1265 1266
1266 1267 x = dataOut.getTimeRange()
1267 1268 #y = dataOut.getHeiRange()
1268 1269 factor = dataOut.normFactor
1269 1270 noise = dataOut.noise[channelIndexList]/factor
1270 1271 noisedB = 10*numpy.log10(noise)
1271 1272
1272 1273 thisDatetime = dataOut.datatime
1273 1274
1274 1275 title = wintitle + " Noise" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1275 1276 xlabel = ""
1276 1277 ylabel = "Intensity (dB)"
1277 1278 update_figfile = False
1278 1279
1279 1280 if not self.isConfig:
1280 1281
1281 1282 nplots = 1
1282 1283
1283 1284 self.setup(id=id,
1284 1285 nplots=nplots,
1285 1286 wintitle=wintitle,
1286 1287 showprofile=showprofile,
1287 1288 show=show)
1288 1289
1289 1290 if timerange != None:
1290 1291 self.timerange = timerange
1291 1292
1292 1293 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1293 1294
1294 1295 if ymin == None: ymin = numpy.floor(numpy.nanmin(noisedB)) - 10.0
1295 1296 if ymax == None: ymax = numpy.nanmax(noisedB) + 10.0
1296 1297
1297 1298 self.FTP_WEI = ftp_wei
1298 1299 self.EXP_CODE = exp_code
1299 1300 self.SUB_EXP_CODE = sub_exp_code
1300 1301 self.PLOT_POS = plot_pos
1301 1302
1302 1303
1303 1304 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1304 1305 self.isConfig = True
1305 1306 self.figfile = figfile
1306 1307 self.xdata = numpy.array([])
1307 1308 self.ydata = numpy.array([])
1308 1309
1309 1310 update_figfile = True
1310 1311
1311 1312 #open file beacon phase
1312 1313 path = '%s%03d' %(self.PREFIX, self.id)
1313 1314 noise_file = os.path.join(path,'%s.txt'%self.name)
1314 1315 self.filename_noise = os.path.join(figpath,noise_file)
1315 1316
1316 1317 self.setWinTitle(title)
1317 1318
1318 1319 title = "Noise %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1319 1320
1320 1321 legendlabels = ["channel %d"%(idchannel) for idchannel in channelList]
1321 1322 axes = self.axesList[0]
1322 1323
1323 1324 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1324 1325
1325 1326 if len(self.ydata)==0:
1326 1327 self.ydata = noisedB.reshape(-1,1)
1327 1328 else:
1328 1329 self.ydata = numpy.hstack((self.ydata, noisedB.reshape(-1,1)))
1329 1330
1330 1331
1331 1332 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1332 1333 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1333 1334 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1334 1335 XAxisAsTime=True, grid='both'
1335 1336 )
1336 1337
1337 1338 self.draw()
1338 1339
1339 1340 if dataOut.ltctime >= self.xmax:
1340 1341 self.counter_imagwr = wr_period
1341 1342 self.isConfig = False
1342 1343 update_figfile = True
1343 1344
1344 1345 self.save(figpath=figpath,
1345 1346 figfile=figfile,
1346 1347 save=save,
1347 1348 ftp=ftp,
1348 1349 wr_period=wr_period,
1349 1350 thisDatetime=thisDatetime,
1350 1351 update_figfile=update_figfile)
1351 1352
1352 1353 #store data beacon phase
1353 1354 if save:
1354 1355 self.save_data(self.filename_noise, noisedB, thisDatetime)
1355 1356
1356 1357 return dataOut
1357 1358
1358 1359 @MPDecorator
1359 1360 class BeaconPhase_(Figure):
1360 1361
1361 1362 __isConfig = None
1362 1363 __nsubplots = None
1363 1364
1364 1365 PREFIX = 'beacon_phase'
1365 1366
1366 1367 def __init__(self):
1367 1368 Figure.__init__(self)
1368 1369 self.timerange = 24*60*60
1369 1370 self.isConfig = False
1370 1371 self.__nsubplots = 1
1371 1372 self.counter_imagwr = 0
1372 1373 self.WIDTH = 800
1373 1374 self.HEIGHT = 400
1374 1375 self.WIDTHPROF = 120
1375 1376 self.HEIGHTPROF = 0
1376 1377 self.xdata = None
1377 1378 self.ydata = None
1378 1379
1379 1380 self.PLOT_CODE = BEACON_CODE
1380 1381
1381 1382 self.FTP_WEI = None
1382 1383 self.EXP_CODE = None
1383 1384 self.SUB_EXP_CODE = None
1384 1385 self.PLOT_POS = None
1385 1386
1386 1387 self.filename_phase = None
1387 1388
1388 1389 self.figfile = None
1389 1390
1390 1391 self.xmin = None
1391 1392 self.xmax = None
1392 1393
1393 1394 def getSubplots(self):
1394 1395
1395 1396 ncol = 1
1396 1397 nrow = 1
1397 1398
1398 1399 return nrow, ncol
1399 1400
1400 1401 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1401 1402
1402 1403 self.__showprofile = showprofile
1403 1404 self.nplots = nplots
1404 1405
1405 1406 ncolspan = 7
1406 1407 colspan = 6
1407 1408 self.__nsubplots = 2
1408 1409
1409 1410 self.createFigure(id = id,
1410 1411 wintitle = wintitle,
1411 1412 widthplot = self.WIDTH+self.WIDTHPROF,
1412 1413 heightplot = self.HEIGHT+self.HEIGHTPROF,
1413 1414 show=show)
1414 1415
1415 1416 nrow, ncol = self.getSubplots()
1416 1417
1417 1418 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1418 1419
1419 1420 def save_phase(self, filename_phase):
1420 1421 f = open(filename_phase,'w+')
1421 1422 f.write('\n\n')
1422 1423 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1423 1424 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1424 1425 f.close()
1425 1426
1426 1427 def save_data(self, filename_phase, data, data_datetime):
1427 1428 f=open(filename_phase,'a')
1428 1429 timetuple_data = data_datetime.timetuple()
1429 1430 day = str(timetuple_data.tm_mday)
1430 1431 month = str(timetuple_data.tm_mon)
1431 1432 year = str(timetuple_data.tm_year)
1432 1433 hour = str(timetuple_data.tm_hour)
1433 1434 minute = str(timetuple_data.tm_min)
1434 1435 second = str(timetuple_data.tm_sec)
1435 1436 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1436 1437 f.close()
1437 1438
1438 1439
1439 1440 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1440 1441 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1441 1442 timerange=None,
1442 1443 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1443 1444 server=None, folder=None, username=None, password=None,
1444 1445 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1445 1446
1446 1447 if dataOut.flagNoData:
1447 1448 return dataOut
1448 1449
1449 1450 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1450 1451 return
1451 1452
1452 1453 if pairsList == None:
1453 1454 pairsIndexList = dataOut.pairsIndexList[:10]
1454 1455 else:
1455 1456 pairsIndexList = []
1456 1457 for pair in pairsList:
1457 1458 if pair not in dataOut.pairsList:
1458 1459 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1459 1460 pairsIndexList.append(dataOut.pairsList.index(pair))
1460 1461
1461 1462 if pairsIndexList == []:
1462 1463 return
1463 1464
1464 # if len(pairsIndexList) > 4:
1465 # pairsIndexList = pairsIndexList[0:4]
1465 # if len(pairsIndexList) > 4:
1466 # pairsIndexList = pairsIndexList[0:4]
1466 1467
1467 1468 hmin_index = None
1468 1469 hmax_index = None
1469 1470
1470 1471 if hmin != None and hmax != None:
1471 1472 indexes = numpy.arange(dataOut.nHeights)
1472 1473 hmin_list = indexes[dataOut.heightList >= hmin]
1473 1474 hmax_list = indexes[dataOut.heightList <= hmax]
1474 1475
1475 1476 if hmin_list.any():
1476 1477 hmin_index = hmin_list[0]
1477 1478
1478 1479 if hmax_list.any():
1479 1480 hmax_index = hmax_list[-1]+1
1480 1481
1481 1482 x = dataOut.getTimeRange()
1482 1483 #y = dataOut.getHeiRange()
1483 1484
1484 1485
1485 1486 thisDatetime = dataOut.datatime
1486 1487
1487 1488 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1488 1489 xlabel = "Local Time"
1489 1490 ylabel = "Phase (degrees)"
1490 1491
1491 1492 update_figfile = False
1492 1493
1493 1494 nplots = len(pairsIndexList)
1494 1495 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1495 1496 phase_beacon = numpy.zeros(len(pairsIndexList))
1496 1497 for i in range(nplots):
1497 1498 pair = dataOut.pairsList[pairsIndexList[i]]
1498 1499 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1499 1500 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1500 1501 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1501 1502 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1502 1503 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1503 1504
1504 1505 if dataOut.beacon_heiIndexList:
1505 1506 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1506 1507 else:
1507 1508 phase_beacon[i] = numpy.average(phase)
1508 1509
1509 1510 if not self.isConfig:
1510 1511
1511 1512 nplots = len(pairsIndexList)
1512 1513
1513 1514 self.setup(id=id,
1514 1515 nplots=nplots,
1515 1516 wintitle=wintitle,
1516 1517 showprofile=showprofile,
1517 1518 show=show)
1518 1519
1519 1520 if timerange != None:
1520 1521 self.timerange = timerange
1521 1522
1522 1523 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1523 1524
1524 1525 if ymin == None: ymin = 0
1525 1526 if ymax == None: ymax = 360
1526 1527
1527 1528 self.FTP_WEI = ftp_wei
1528 1529 self.EXP_CODE = exp_code
1529 1530 self.SUB_EXP_CODE = sub_exp_code
1530 1531 self.PLOT_POS = plot_pos
1531 1532
1532 1533 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1533 1534 self.isConfig = True
1534 1535 self.figfile = figfile
1535 1536 self.xdata = numpy.array([])
1536 1537 self.ydata = numpy.array([])
1537 1538
1538 1539 update_figfile = True
1539 1540
1540 1541 #open file beacon phase
1541 1542 path = '%s%03d' %(self.PREFIX, self.id)
1542 1543 beacon_file = os.path.join(path,'%s.txt'%self.name)
1543 1544 self.filename_phase = os.path.join(figpath,beacon_file)
1544 1545 #self.save_phase(self.filename_phase)
1545 1546
1546 1547
1547 1548 #store data beacon phase
1548 1549 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1549 1550
1550 1551 self.setWinTitle(title)
1551 1552
1552 1553
1553 1554 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1554 1555
1555 1556 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1556 1557
1557 1558 axes = self.axesList[0]
1558 1559
1559 1560 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1560 1561
1561 1562 if len(self.ydata)==0:
1562 1563 self.ydata = phase_beacon.reshape(-1,1)
1563 1564 else:
1564 1565 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1565 1566
1566 1567
1567 1568 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1568 1569 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1569 1570 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1570 1571 XAxisAsTime=True, grid='both'
1571 1572 )
1572 1573
1573 1574 self.draw()
1574 1575
1575 1576 if dataOut.ltctime >= self.xmax:
1576 1577 self.counter_imagwr = wr_period
1577 1578 self.isConfig = False
1578 1579 update_figfile = True
1579 1580
1580 1581 self.save(figpath=figpath,
1581 1582 figfile=figfile,
1582 1583 save=save,
1583 1584 ftp=ftp,
1584 1585 wr_period=wr_period,
1585 1586 thisDatetime=thisDatetime,
1586 1587 update_figfile=update_figfile)
1587 1588
1588 1589 return dataOut No newline at end of file
@@ -1,500 +1,470
1 1 import os
2 2 import sys
3 3 import datetime
4 4 import numpy
5 import matplotlib
6
7 if 'BACKEND' in os.environ:
8 matplotlib.use(os.environ['BACKEND'])
9 elif 'linux' in sys.platform:
10 matplotlib.use("TkAgg")
11 elif 'darwin' in sys.platform:
12 matplotlib.use('TkAgg')
13 else:
14 from schainpy.utils import log
15 log.warning('Using default Backend="Agg"', 'INFO')
16 matplotlib.use('Agg')
17 # Qt4Agg', 'GTK', 'GTKAgg', 'ps', 'agg', 'cairo', 'MacOSX', 'GTKCairo', 'WXAgg', 'template', 'TkAgg', 'GTK3Cairo', 'GTK3Agg', 'svg', 'WebAgg', 'CocoaAgg', 'emf', 'gdk', 'WX'
18 import matplotlib.pyplot
19
20 from mpl_toolkits.axes_grid1 import make_axes_locatable
21 from matplotlib.ticker import FuncFormatter, LinearLocator
22
23 ###########################################
24 # Actualizacion de las funciones del driver
25 ###########################################
26
27 # create jro colormap
28
29 jet_values = matplotlib.pyplot.get_cmap("jet", 100)(numpy.arange(100))[10:90]
30 blu_values = matplotlib.pyplot.get_cmap(
31 "seismic_r", 20)(numpy.arange(20))[10:15]
32 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
33 "jro", numpy.vstack((blu_values, jet_values)))
34 matplotlib.pyplot.register_cmap(cmap=ncmap)
35
5 from .jroplot_base import matplotlib, make_axes_locatable, FuncFormatter, LinearLocator
36 6
37 7 def createFigure(id, wintitle, width, height, facecolor="w", show=True, dpi=80):
38 8
39 9 matplotlib.pyplot.ioff()
40 10
41 11 fig = matplotlib.pyplot.figure(num=id, facecolor=facecolor, figsize=(
42 12 1.0 * width / dpi, 1.0 * height / dpi))
43 13 fig.canvas.manager.set_window_title(wintitle)
44 14 # fig.canvas.manager.resize(width, height)
45 15 matplotlib.pyplot.ion()
46 16
47 17 if show:
48 18 matplotlib.pyplot.show()
49 19
50 20 return fig
51 21
52 22
53 23 def closeFigure(show=False, fig=None):
54 24
55 25 # matplotlib.pyplot.ioff()
56 26 # matplotlib.pyplot.pause(0)
57 27
58 28 if show:
59 29 matplotlib.pyplot.show()
60 30
61 31 if fig != None:
62 32 matplotlib.pyplot.close(fig)
63 33 # matplotlib.pyplot.pause(0)
64 34 # matplotlib.pyplot.ion()
65 35
66 36 return
67 37
68 38 matplotlib.pyplot.close("all")
69 39 # matplotlib.pyplot.pause(0)
70 40 # matplotlib.pyplot.ion()
71 41
72 42 return
73 43
74 44
75 45 def saveFigure(fig, filename):
76 46
77 47 # matplotlib.pyplot.ioff()
78 48 fig.savefig(filename, dpi=matplotlib.pyplot.gcf().dpi)
79 49 # matplotlib.pyplot.ion()
80 50
81 51
82 52 def clearFigure(fig):
83 53
84 54 fig.clf()
85 55
86 56
87 57 def setWinTitle(fig, title):
88 58
89 59 fig.canvas.manager.set_window_title(title)
90 60
91 61
92 62 def setTitle(fig, title):
93 63
94 64 fig.suptitle(title)
95 65
96 66
97 67 def createAxes(fig, nrow, ncol, xpos, ypos, colspan, rowspan, polar=False):
98 68
99 69 matplotlib.pyplot.ioff()
100 70 matplotlib.pyplot.figure(fig.number)
101 71 axes = matplotlib.pyplot.subplot2grid((nrow, ncol),
102 72 (xpos, ypos),
103 73 colspan=colspan,
104 74 rowspan=rowspan,
105 75 polar=polar)
106 76
107 77 matplotlib.pyplot.ion()
108 78 return axes
109 79
110 80
111 81 def setAxesText(ax, text):
112 82
113 83 ax.annotate(text,
114 84 xy=(.1, .99),
115 85 xycoords='figure fraction',
116 86 horizontalalignment='left',
117 87 verticalalignment='top',
118 88 fontsize=10)
119 89
120 90
121 91 def printLabels(ax, xlabel, ylabel, title):
122 92
123 93 ax.set_xlabel(xlabel, size=11)
124 94 ax.set_ylabel(ylabel, size=11)
125 95 ax.set_title(title, size=8)
126 96
127 97
128 98 def createPline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='',
129 99 ticksize=9, xtick_visible=True, ytick_visible=True,
130 100 nxticks=4, nyticks=10,
131 101 grid=None, color='blue'):
132 102 """
133 103
134 104 Input:
135 105 grid : None, 'both', 'x', 'y'
136 106 """
137 107
138 108 matplotlib.pyplot.ioff()
139 109
140 110 ax.set_xlim([xmin, xmax])
141 111 ax.set_ylim([ymin, ymax])
142 112
143 113 printLabels(ax, xlabel, ylabel, title)
144 114
145 115 ######################################################
146 116 if (xmax - xmin) <= 1:
147 117 xtickspos = numpy.linspace(xmin, xmax, nxticks)
148 118 xtickspos = numpy.array([float("%.1f" % i) for i in xtickspos])
149 119 ax.set_xticks(xtickspos)
150 120 else:
151 121 xtickspos = numpy.arange(nxticks) * \
152 122 int((xmax - xmin) / (nxticks)) + int(xmin)
153 123 # xtickspos = numpy.arange(nxticks)*float(xmax-xmin)/float(nxticks) + int(xmin)
154 124 ax.set_xticks(xtickspos)
155 125
156 126 for tick in ax.get_xticklabels():
157 127 tick.set_visible(xtick_visible)
158 128
159 129 for tick in ax.xaxis.get_major_ticks():
160 130 tick.label.set_fontsize(ticksize)
161 131
162 132 ######################################################
163 133 for tick in ax.get_yticklabels():
164 134 tick.set_visible(ytick_visible)
165 135
166 136 for tick in ax.yaxis.get_major_ticks():
167 137 tick.label.set_fontsize(ticksize)
168 138
169 139 ax.plot(x, y, color=color)
170 140 iplot = ax.lines[-1]
171 141
172 142 ######################################################
173 143 if '0.' in matplotlib.__version__[0:2]:
174 144 print("The matplotlib version has to be updated to 1.1 or newer")
175 145 return iplot
176 146
177 147 if '1.0.' in matplotlib.__version__[0:4]:
178 148 print("The matplotlib version has to be updated to 1.1 or newer")
179 149 return iplot
180 150
181 151 if grid != None:
182 152 ax.grid(b=True, which='major', axis=grid)
183 153
184 154 matplotlib.pyplot.tight_layout()
185 155
186 156 matplotlib.pyplot.ion()
187 157
188 158 return iplot
189 159
190 160
191 161 def set_linedata(ax, x, y, idline):
192 162
193 163 ax.lines[idline].set_data(x, y)
194 164
195 165
196 166 def pline(iplot, x, y, xlabel='', ylabel='', title=''):
197 167
198 168 ax = iplot.axes
199 169
200 170 printLabels(ax, xlabel, ylabel, title)
201 171
202 172 set_linedata(ax, x, y, idline=0)
203 173
204 174
205 175 def addpline(ax, x, y, color, linestyle, lw):
206 176
207 177 ax.plot(x, y, color=color, linestyle=linestyle, lw=lw)
208 178
209 179
210 180 def createPcolor(ax, x, y, z, xmin, xmax, ymin, ymax, zmin, zmax,
211 181 xlabel='', ylabel='', title='', ticksize=9,
212 182 colormap='jet', cblabel='', cbsize="5%",
213 183 XAxisAsTime=False):
214 184
215 185 matplotlib.pyplot.ioff()
216 186
217 187 divider = make_axes_locatable(ax)
218 188 ax_cb = divider.new_horizontal(size=cbsize, pad=0.05)
219 189 fig = ax.get_figure()
220 190 fig.add_axes(ax_cb)
221 191
222 192 ax.set_xlim([xmin, xmax])
223 193 ax.set_ylim([ymin, ymax])
224 194
225 195 printLabels(ax, xlabel, ylabel, title)
226 196
227 197 z = numpy.ma.masked_invalid(z)
228 198 cmap = matplotlib.pyplot.get_cmap(colormap)
229 199 cmap.set_bad('white', 1.)
230 200 imesh = ax.pcolormesh(x, y, z.T, vmin=zmin, vmax=zmax, cmap=cmap)
231 201 cb = matplotlib.pyplot.colorbar(imesh, cax=ax_cb)
232 202 cb.set_label(cblabel)
233 203
234 204 # for tl in ax_cb.get_yticklabels():
235 205 # tl.set_visible(True)
236 206
237 207 for tick in ax.yaxis.get_major_ticks():
238 208 tick.label.set_fontsize(ticksize)
239 209
240 210 for tick in ax.xaxis.get_major_ticks():
241 211 tick.label.set_fontsize(ticksize)
242 212
243 213 for tick in cb.ax.get_yticklabels():
244 214 tick.set_fontsize(ticksize)
245 215
246 216 ax_cb.yaxis.tick_right()
247 217
248 218 if '0.' in matplotlib.__version__[0:2]:
249 219 print("The matplotlib version has to be updated to 1.1 or newer")
250 220 return imesh
251 221
252 222 if '1.0.' in matplotlib.__version__[0:4]:
253 223 print("The matplotlib version has to be updated to 1.1 or newer")
254 224 return imesh
255 225
256 226 matplotlib.pyplot.tight_layout()
257 227
258 228 if XAxisAsTime:
259 229
260 230 def func(x, pos): return ('%s') % (
261 231 datetime.datetime.utcfromtimestamp(x).strftime("%H:%M:%S"))
262 232 ax.xaxis.set_major_formatter(FuncFormatter(func))
263 233 ax.xaxis.set_major_locator(LinearLocator(7))
264 234
265 235 matplotlib.pyplot.ion()
266 236 return imesh
267 237
268 238
269 239 def pcolor(imesh, z, xlabel='', ylabel='', title=''):
270 240
271 241 z = z.T
272 242 ax = imesh.axes
273 243 printLabels(ax, xlabel, ylabel, title)
274 244 imesh.set_array(z.ravel())
275 245
276 246
277 247 def addpcolor(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', colormap='jet'):
278 248
279 249 printLabels(ax, xlabel, ylabel, title)
280 250
281 251 ax.pcolormesh(x, y, z.T, vmin=zmin, vmax=zmax,
282 252 cmap=matplotlib.pyplot.get_cmap(colormap))
283 253
284 254
285 255 def addpcolorbuffer(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', colormap='jet'):
286 256
287 257 printLabels(ax, xlabel, ylabel, title)
288 258
289 259 ax.collections.remove(ax.collections[0])
290 260
291 261 z = numpy.ma.masked_invalid(z)
292 262
293 263 cmap = matplotlib.pyplot.get_cmap(colormap)
294 264 cmap.set_bad('white', 1.)
295 265
296 266 ax.pcolormesh(x, y, z.T, vmin=zmin, vmax=zmax, cmap=cmap)
297 267
298 268
299 269 def createPmultiline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='', legendlabels=None,
300 270 ticksize=9, xtick_visible=True, ytick_visible=True,
301 271 nxticks=4, nyticks=10,
302 272 grid=None):
303 273 """
304 274
305 275 Input:
306 276 grid : None, 'both', 'x', 'y'
307 277 """
308 278
309 279 matplotlib.pyplot.ioff()
310 280
311 281 lines = ax.plot(x.T, y)
312 282 leg = ax.legend(lines, legendlabels, loc='upper right')
313 283 leg.get_frame().set_alpha(0.5)
314 284 ax.set_xlim([xmin, xmax])
315 285 ax.set_ylim([ymin, ymax])
316 286 printLabels(ax, xlabel, ylabel, title)
317 287
318 288 xtickspos = numpy.arange(nxticks) * \
319 289 int((xmax - xmin) / (nxticks)) + int(xmin)
320 290 ax.set_xticks(xtickspos)
321 291
322 292 for tick in ax.get_xticklabels():
323 293 tick.set_visible(xtick_visible)
324 294
325 295 for tick in ax.xaxis.get_major_ticks():
326 296 tick.label.set_fontsize(ticksize)
327 297
328 298 for tick in ax.get_yticklabels():
329 299 tick.set_visible(ytick_visible)
330 300
331 301 for tick in ax.yaxis.get_major_ticks():
332 302 tick.label.set_fontsize(ticksize)
333 303
334 304 iplot = ax.lines[-1]
335 305
336 306 if '0.' in matplotlib.__version__[0:2]:
337 307 print("The matplotlib version has to be updated to 1.1 or newer")
338 308 return iplot
339 309
340 310 if '1.0.' in matplotlib.__version__[0:4]:
341 311 print("The matplotlib version has to be updated to 1.1 or newer")
342 312 return iplot
343 313
344 314 if grid != None:
345 315 ax.grid(b=True, which='major', axis=grid)
346 316
347 317 matplotlib.pyplot.tight_layout()
348 318
349 319 matplotlib.pyplot.ion()
350 320
351 321 return iplot
352 322
353 323
354 324 def pmultiline(iplot, x, y, xlabel='', ylabel='', title=''):
355 325
356 326 ax = iplot.axes
357 327
358 328 printLabels(ax, xlabel, ylabel, title)
359 329
360 330 for i in range(len(ax.lines)):
361 331 line = ax.lines[i]
362 332 line.set_data(x[i, :], y)
363 333
364 334
365 335 def createPmultilineYAxis(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='', legendlabels=None,
366 336 ticksize=9, xtick_visible=True, ytick_visible=True,
367 337 nxticks=4, nyticks=10, marker='.', markersize=10, linestyle="None",
368 338 grid=None, XAxisAsTime=False):
369 339 """
370 340
371 341 Input:
372 342 grid : None, 'both', 'x', 'y'
373 343 """
374 344
375 345 matplotlib.pyplot.ioff()
376 346
377 347 # lines = ax.plot(x, y.T, marker=marker,markersize=markersize,linestyle=linestyle)
378 348 lines = ax.plot(x, y.T)
379 349 # leg = ax.legend(lines, legendlabels, loc=2, bbox_to_anchor=(1.01, 1.00), numpoints=1, handlelength=1.5, \
380 350 # handletextpad=0.5, borderpad=0.5, labelspacing=0.5, borderaxespad=0.)
381 351
382 352 leg = ax.legend(lines, legendlabels,
383 353 loc='upper right', bbox_to_anchor=(1.16, 1), borderaxespad=0)
384 354
385 355 for label in leg.get_texts():
386 356 label.set_fontsize(9)
387 357
388 358 ax.set_xlim([xmin, xmax])
389 359 ax.set_ylim([ymin, ymax])
390 360 printLabels(ax, xlabel, ylabel, title)
391 361
392 362 # xtickspos = numpy.arange(nxticks)*int((xmax-xmin)/(nxticks)) + int(xmin)
393 363 # ax.set_xticks(xtickspos)
394 364
395 365 for tick in ax.get_xticklabels():
396 366 tick.set_visible(xtick_visible)
397 367
398 368 for tick in ax.xaxis.get_major_ticks():
399 369 tick.label.set_fontsize(ticksize)
400 370
401 371 for tick in ax.get_yticklabels():
402 372 tick.set_visible(ytick_visible)
403 373
404 374 for tick in ax.yaxis.get_major_ticks():
405 375 tick.label.set_fontsize(ticksize)
406 376
407 377 iplot = ax.lines[-1]
408 378
409 379 if '0.' in matplotlib.__version__[0:2]:
410 380 print("The matplotlib version has to be updated to 1.1 or newer")
411 381 return iplot
412 382
413 383 if '1.0.' in matplotlib.__version__[0:4]:
414 384 print("The matplotlib version has to be updated to 1.1 or newer")
415 385 return iplot
416 386
417 387 if grid != None:
418 388 ax.grid(b=True, which='major', axis=grid)
419 389
420 390 matplotlib.pyplot.tight_layout()
421 391
422 392 if XAxisAsTime:
423 393
424 394 def func(x, pos): return ('%s') % (
425 395 datetime.datetime.utcfromtimestamp(x).strftime("%H:%M:%S"))
426 396 ax.xaxis.set_major_formatter(FuncFormatter(func))
427 397 ax.xaxis.set_major_locator(LinearLocator(7))
428 398
429 399 matplotlib.pyplot.ion()
430 400
431 401 return iplot
432 402
433 403
434 404 def pmultilineyaxis(iplot, x, y, xlabel='', ylabel='', title=''):
435 405
436 406 ax = iplot.axes
437 407 printLabels(ax, xlabel, ylabel, title)
438 408
439 409 for i in range(len(ax.lines)):
440 410 line = ax.lines[i]
441 411 line.set_data(x, y[i, :])
442 412
443 413
444 414 def createPolar(ax, x, y,
445 415 xlabel='', ylabel='', title='', ticksize=9,
446 416 colormap='jet', cblabel='', cbsize="5%",
447 417 XAxisAsTime=False):
448 418
449 419 matplotlib.pyplot.ioff()
450 420
451 421 ax.plot(x, y, 'bo', markersize=5)
452 422 # ax.set_rmax(90)
453 423 ax.set_ylim(0, 90)
454 424 ax.set_yticks(numpy.arange(0, 90, 20))
455 425 # ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center' ,size='11')
456 426 # ax.text(0, 50, ylabel, rotation='vertical', va ='center', ha = 'left' ,size='11')
457 427 # ax.text(100, 100, 'example', ha='left', va='center', rotation='vertical')
458 428 ax.yaxis.labelpad = 40
459 429 printLabels(ax, xlabel, ylabel, title)
460 430 iplot = ax.lines[-1]
461 431
462 432 if '0.' in matplotlib.__version__[0:2]:
463 433 print("The matplotlib version has to be updated to 1.1 or newer")
464 434 return iplot
465 435
466 436 if '1.0.' in matplotlib.__version__[0:4]:
467 437 print("The matplotlib version has to be updated to 1.1 or newer")
468 438 return iplot
469 439
470 440 # if grid != None:
471 441 # ax.grid(b=True, which='major', axis=grid)
472 442
473 443 matplotlib.pyplot.tight_layout()
474 444
475 445 matplotlib.pyplot.ion()
476 446
477 447 return iplot
478 448
479 449
480 450 def polar(iplot, x, y, xlabel='', ylabel='', title=''):
481 451
482 452 ax = iplot.axes
483 453
484 454 # ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center',size='11')
485 455 printLabels(ax, xlabel, ylabel, title)
486 456
487 457 set_linedata(ax, x, y, idline=0)
488 458
489 459
490 460 def draw(fig):
491 461
492 462 if type(fig) == 'int':
493 463 raise ValueError("Error drawing: Fig parameter should be a matplotlib figure object figure")
494 464
495 465 fig.canvas.draw()
496 466
497 467
498 468 def pause(interval=0.000001):
499 469
500 470 matplotlib.pyplot.pause(interval) No newline at end of file
@@ -1,3858 +1,3858
1 1 import numpy
2 2 import math
3 3 from scipy import optimize, interpolate, signal, stats, ndimage
4 4 import scipy
5 5 import re
6 6 import datetime
7 7 import copy
8 8 import sys
9 9 import importlib
10 10 import itertools
11 11 from multiprocessing import Pool, TimeoutError
12 12 from multiprocessing.pool import ThreadPool
13 13 import time
14 14
15 15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 18 from scipy import asarray as ar,exp
19 19 from scipy.optimize import curve_fit
20 20 from schainpy.utils import log
21 21 import warnings
22 22 from numpy import NaN
23 23 from scipy.optimize.optimize import OptimizeWarning
24 24 warnings.filterwarnings('ignore')
25 25
26 26
27 27 SPEED_OF_LIGHT = 299792458
28 28
29 29
30 30 '''solving pickling issue'''
31 31
32 32 def _pickle_method(method):
33 33 func_name = method.__func__.__name__
34 34 obj = method.__self__
35 35 cls = method.__self__.__class__
36 36 return _unpickle_method, (func_name, obj, cls)
37 37
38 38 def _unpickle_method(func_name, obj, cls):
39 39 for cls in cls.mro():
40 40 try:
41 41 func = cls.__dict__[func_name]
42 42 except KeyError:
43 43 pass
44 44 else:
45 45 break
46 46 return func.__get__(obj, cls)
47 47
48 48 @MPDecorator
49 49 class ParametersProc(ProcessingUnit):
50 50
51 51 METHODS = {}
52 52 nSeconds = None
53 53
54 54 def __init__(self):
55 55 ProcessingUnit.__init__(self)
56 56
57 57 # self.objectDict = {}
58 58 self.buffer = None
59 59 self.firstdatatime = None
60 60 self.profIndex = 0
61 61 self.dataOut = Parameters()
62 62 self.setupReq = False #Agregar a todas las unidades de proc
63 63
64 64 def __updateObjFromInput(self):
65 65
66 66 self.dataOut.inputUnit = self.dataIn.type
67 67
68 68 self.dataOut.timeZone = self.dataIn.timeZone
69 69 self.dataOut.dstFlag = self.dataIn.dstFlag
70 70 self.dataOut.errorCount = self.dataIn.errorCount
71 71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
72 72
73 73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
74 74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
75 75 self.dataOut.channelList = self.dataIn.channelList
76 76 self.dataOut.heightList = self.dataIn.heightList
77 77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
78 78 # self.dataOut.nHeights = self.dataIn.nHeights
79 79 # self.dataOut.nChannels = self.dataIn.nChannels
80 80 self.dataOut.nBaud = self.dataIn.nBaud
81 81 self.dataOut.nCode = self.dataIn.nCode
82 82 self.dataOut.code = self.dataIn.code
83 83 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
84 84 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
85 85 # self.dataOut.utctime = self.firstdatatime
86 86 self.dataOut.utctime = self.dataIn.utctime
87 87 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
88 88 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
89 89 self.dataOut.nCohInt = self.dataIn.nCohInt
90 90 # self.dataOut.nIncohInt = 1
91 91 self.dataOut.ippSeconds = self.dataIn.ippSeconds
92 92 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
93 93 self.dataOut.timeInterval1 = self.dataIn.timeInterval
94 94 self.dataOut.heightList = self.dataIn.getHeiRange()
95 95 self.dataOut.frequency = self.dataIn.frequency
96 96 # self.dataOut.noise = self.dataIn.noise
97 97 self.dataOut.error = self.dataIn.error
98 98
99 99 def run(self):
100 100
101 101
102 102
103 103 #---------------------- Voltage Data ---------------------------
104 104
105 105 if self.dataIn.type == "Voltage":
106 106
107 107 self.__updateObjFromInput()
108 108 self.dataOut.data_pre = self.dataIn.data.copy()
109 109 self.dataOut.flagNoData = False
110 110 self.dataOut.utctimeInit = self.dataIn.utctime
111 111 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
112 112 return
113 113
114 114 #---------------------- Spectra Data ---------------------------
115 115
116 116 if self.dataIn.type == "Spectra":
117 117
118 118 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
119 119 self.dataOut.data_spc = self.dataIn.data_spc
120 120 self.dataOut.data_cspc = self.dataIn.data_cspc
121 121 self.dataOut.nProfiles = self.dataIn.nProfiles
122 122 self.dataOut.nIncohInt = self.dataIn.nIncohInt
123 123 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
124 124 self.dataOut.ippFactor = self.dataIn.ippFactor
125 125 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
126 126 self.dataOut.spc_noise = self.dataIn.getNoise()
127 127 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
128 128 # self.dataOut.normFactor = self.dataIn.normFactor
129 129 self.dataOut.pairsList = self.dataIn.pairsList
130 130 self.dataOut.groupList = self.dataIn.pairsList
131 131 self.dataOut.flagNoData = False
132 132
133 133 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
134 134 self.dataOut.ChanDist = self.dataIn.ChanDist
135 135 else: self.dataOut.ChanDist = None
136 136
137 137 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
138 138 # self.dataOut.VelRange = self.dataIn.VelRange
139 139 #else: self.dataOut.VelRange = None
140 140
141 141 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
142 142 self.dataOut.RadarConst = self.dataIn.RadarConst
143 143
144 144 if hasattr(self.dataIn, 'NPW'): #NPW
145 145 self.dataOut.NPW = self.dataIn.NPW
146 146
147 147 if hasattr(self.dataIn, 'COFA'): #COFA
148 148 self.dataOut.COFA = self.dataIn.COFA
149 149
150 150
151 151
152 152 #---------------------- Correlation Data ---------------------------
153 153
154 154 if self.dataIn.type == "Correlation":
155 155 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
156 156
157 157 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
158 158 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
159 159 self.dataOut.groupList = (acf_pairs, ccf_pairs)
160 160
161 161 self.dataOut.abscissaList = self.dataIn.lagRange
162 162 self.dataOut.noise = self.dataIn.noise
163 163 self.dataOut.data_SNR = self.dataIn.SNR
164 164 self.dataOut.flagNoData = False
165 165 self.dataOut.nAvg = self.dataIn.nAvg
166 166
167 167 #---------------------- Parameters Data ---------------------------
168 168
169 169 if self.dataIn.type == "Parameters":
170 170 self.dataOut.copy(self.dataIn)
171 171 self.dataOut.flagNoData = False
172 172
173 173 return True
174 174
175 175 self.__updateObjFromInput()
176 176 self.dataOut.utctimeInit = self.dataIn.utctime
177 177 self.dataOut.paramInterval = self.dataIn.timeInterval
178 178
179 179 return
180 180
181 181
182 182 def target(tups):
183 183
184 184 obj, args = tups
185 185
186 186 return obj.FitGau(args)
187 187
188 188
189 189 class SpectralFilters(Operation):
190 190
191 191 '''This class allows the Rainfall / Wind Selection for CLAIRE RADAR
192 192
193 193 LimitR : It is the limit in m/s of Rainfall
194 194 LimitW : It is the limit in m/s for Winds
195 195
196 196 Input:
197 197
198 198 self.dataOut.data_pre : SPC and CSPC
199 199 self.dataOut.spc_range : To select wind and rainfall velocities
200 200
201 201 Affected:
202 202
203 203 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
204 204 self.dataOut.spcparam_range : Used in SpcParamPlot
205 205 self.dataOut.SPCparam : Used in PrecipitationProc
206 206
207 207
208 208 '''
209 209
210 210 def __init__(self):
211 211 Operation.__init__(self)
212 212 self.i=0
213 213
214 214 def run(self, dataOut, PositiveLimit=1.5, NegativeLimit=2.5):
215 215
216 216
217 217 #Limite de vientos
218 218 LimitR = PositiveLimit
219 219 LimitN = NegativeLimit
220 220
221 221 self.spc = dataOut.data_pre[0].copy()
222 222 self.cspc = dataOut.data_pre[1].copy()
223 223
224 224 self.Num_Hei = self.spc.shape[2]
225 225 self.Num_Bin = self.spc.shape[1]
226 226 self.Num_Chn = self.spc.shape[0]
227 227
228 228 VelRange = dataOut.spc_range[2]
229 229 TimeRange = dataOut.spc_range[1]
230 230 FrecRange = dataOut.spc_range[0]
231 231
232 232 Vmax= 2*numpy.max(dataOut.spc_range[2])
233 233 Tmax= 2*numpy.max(dataOut.spc_range[1])
234 234 Fmax= 2*numpy.max(dataOut.spc_range[0])
235 235
236 236 Breaker1R=VelRange[numpy.abs(VelRange-(-LimitN)).argmin()]
237 237 Breaker1R=numpy.where(VelRange == Breaker1R)
238 238
239 239 Delta = self.Num_Bin/2 - Breaker1R[0]
240 240
241 241
242 242 '''Reacomodando SPCrange'''
243 243
244 244 VelRange=numpy.roll(VelRange,-(int(self.Num_Bin/2)) ,axis=0)
245 245
246 246 VelRange[-(int(self.Num_Bin/2)):]+= Vmax
247 247
248 248 FrecRange=numpy.roll(FrecRange,-(int(self.Num_Bin/2)),axis=0)
249 249
250 250 FrecRange[-(int(self.Num_Bin/2)):]+= Fmax
251 251
252 252 TimeRange=numpy.roll(TimeRange,-(int(self.Num_Bin/2)),axis=0)
253 253
254 254 TimeRange[-(int(self.Num_Bin/2)):]+= Tmax
255 255
256 256 ''' ------------------ '''
257 257
258 258 Breaker2R=VelRange[numpy.abs(VelRange-(LimitR)).argmin()]
259 259 Breaker2R=numpy.where(VelRange == Breaker2R)
260 260
261 261
262 262 SPCroll = numpy.roll(self.spc,-(int(self.Num_Bin/2)) ,axis=1)
263 263
264 264 SPCcut = SPCroll.copy()
265 265 for i in range(self.Num_Chn):
266 266
267 267 SPCcut[i,0:int(Breaker2R[0]),:] = dataOut.noise[i]
268 268 SPCcut[i,-int(Delta):,:] = dataOut.noise[i]
269 269
270 270 SPCcut[i]=SPCcut[i]- dataOut.noise[i]
271 271 SPCcut[ numpy.where( SPCcut<0 ) ] = 1e-20
272 272
273 273 SPCroll[i]=SPCroll[i]-dataOut.noise[i]
274 274 SPCroll[ numpy.where( SPCroll<0 ) ] = 1e-20
275 275
276 276 SPC_ch1 = SPCroll
277 277
278 278 SPC_ch2 = SPCcut
279 279
280 280 SPCparam = (SPC_ch1, SPC_ch2, self.spc)
281 281 dataOut.SPCparam = numpy.asarray(SPCparam)
282 282
283 283
284 284 dataOut.spcparam_range=numpy.zeros([self.Num_Chn,self.Num_Bin+1])
285 285
286 286 dataOut.spcparam_range[2]=VelRange
287 287 dataOut.spcparam_range[1]=TimeRange
288 288 dataOut.spcparam_range[0]=FrecRange
289 289 return dataOut
290 290
291 291 class GaussianFit(Operation):
292 292
293 293 '''
294 294 Function that fit of one and two generalized gaussians (gg) based
295 295 on the PSD shape across an "power band" identified from a cumsum of
296 296 the measured spectrum - noise.
297 297
298 298 Input:
299 299 self.dataOut.data_pre : SelfSpectra
300 300
301 301 Output:
302 302 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
303 303
304 304 '''
305 305 def __init__(self):
306 306 Operation.__init__(self)
307 307 self.i=0
308 308
309 309
310 310 def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
311 311 """This routine will find a couple of generalized Gaussians to a power spectrum
312 312 input: spc
313 313 output:
314 314 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
315 315 """
316 316
317 317 self.spc = dataOut.data_pre[0].copy()
318 318 self.Num_Hei = self.spc.shape[2]
319 319 self.Num_Bin = self.spc.shape[1]
320 320 self.Num_Chn = self.spc.shape[0]
321 321 Vrange = dataOut.abscissaList
322 322
323 323 GauSPC = numpy.empty([self.Num_Chn,self.Num_Bin,self.Num_Hei])
324 324 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
325 325 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
326 326 SPC_ch1[:] = numpy.NaN
327 327 SPC_ch2[:] = numpy.NaN
328 328
329 329
330 330 start_time = time.time()
331 331
332 332 noise_ = dataOut.spc_noise[0].copy()
333 333
334 334
335 335 pool = Pool(processes=self.Num_Chn)
336 336 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
337 337 objs = [self for __ in range(self.Num_Chn)]
338 338 attrs = list(zip(objs, args))
339 339 gauSPC = pool.map(target, attrs)
340 340 dataOut.SPCparam = numpy.asarray(SPCparam)
341 341
342 342 ''' Parameters:
343 343 1. Amplitude
344 344 2. Shift
345 345 3. Width
346 346 4. Power
347 347 '''
348 348
349 349 def FitGau(self, X):
350 350
351 351 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
352 352
353 353 SPCparam = []
354 354 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
355 355 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
356 356 SPC_ch1[:] = 0#numpy.NaN
357 357 SPC_ch2[:] = 0#numpy.NaN
358 358
359 359
360 360
361 361 for ht in range(self.Num_Hei):
362 362
363 363
364 364 spc = numpy.asarray(self.spc)[ch,:,ht]
365 365
366 366 #############################################
367 367 # normalizing spc and noise
368 368 # This part differs from gg1
369 369 spc_norm_max = max(spc)
370 370 #spc = spc / spc_norm_max
371 371 pnoise = pnoise #/ spc_norm_max
372 372 #############################################
373 373
374 374 fatspectra=1.0
375 375
376 376 wnoise = noise_ #/ spc_norm_max
377 377 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
378 378 #if wnoise>1.1*pnoise: # to be tested later
379 379 # wnoise=pnoise
380 380 noisebl=wnoise*0.9;
381 381 noisebh=wnoise*1.1
382 382 spc=spc-wnoise
383 383
384 384 minx=numpy.argmin(spc)
385 385 #spcs=spc.copy()
386 386 spcs=numpy.roll(spc,-minx)
387 387 cum=numpy.cumsum(spcs)
388 388 tot_noise=wnoise * self.Num_Bin #64;
389 389
390 390 snr = sum(spcs)/tot_noise
391 391 snrdB=10.*numpy.log10(snr)
392 392
393 393 if snrdB < SNRlimit :
394 394 snr = numpy.NaN
395 395 SPC_ch1[:,ht] = 0#numpy.NaN
396 396 SPC_ch1[:,ht] = 0#numpy.NaN
397 397 SPCparam = (SPC_ch1,SPC_ch2)
398 398 continue
399 399
400 400
401 401 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
402 402 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
403 403
404 404 cummax=max(cum);
405 405 epsi=0.08*fatspectra # cumsum to narrow down the energy region
406 406 cumlo=cummax*epsi;
407 407 cumhi=cummax*(1-epsi)
408 408 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
409 409
410 410
411 411 if len(powerindex) < 1:# case for powerindex 0
412 412 continue
413 413 powerlo=powerindex[0]
414 414 powerhi=powerindex[-1]
415 415 powerwidth=powerhi-powerlo
416 416
417 417 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
418 418 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
419 419 midpeak=(firstpeak+secondpeak)/2.
420 420 firstamp=spcs[int(firstpeak)]
421 421 secondamp=spcs[int(secondpeak)]
422 422 midamp=spcs[int(midpeak)]
423 423
424 424 x=numpy.arange( self.Num_Bin )
425 425 y_data=spc+wnoise
426 426
427 427 ''' single Gaussian '''
428 428 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
429 429 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
430 430 power0=2.
431 431 amplitude0=midamp
432 432 state0=[shift0,width0,amplitude0,power0,wnoise]
433 433 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
434 434 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
435 435
436 436 chiSq1=lsq1[1];
437 437
438 438
439 439 if fatspectra<1.0 and powerwidth<4:
440 440 choice=0
441 441 Amplitude0=lsq1[0][2]
442 442 shift0=lsq1[0][0]
443 443 width0=lsq1[0][1]
444 444 p0=lsq1[0][3]
445 445 Amplitude1=0.
446 446 shift1=0.
447 447 width1=0.
448 448 p1=0.
449 449 noise=lsq1[0][4]
450 450 #return (numpy.array([shift0,width0,Amplitude0,p0]),
451 451 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
452 452
453 453 ''' two gaussians '''
454 454 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
455 455 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
456 456 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
457 457 width0=powerwidth/6.;
458 458 width1=width0
459 459 power0=2.;
460 460 power1=power0
461 461 amplitude0=firstamp;
462 462 amplitude1=secondamp
463 463 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
464 464 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
465 465 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
466 466 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
467 467
468 468 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
469 469
470 470
471 471 chiSq2=lsq2[1];
472 472
473 473
474 474
475 475 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
476 476
477 477 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
478 478 if oneG:
479 479 choice=0
480 480 else:
481 481 w1=lsq2[0][1]; w2=lsq2[0][5]
482 482 a1=lsq2[0][2]; a2=lsq2[0][6]
483 483 p1=lsq2[0][3]; p2=lsq2[0][7]
484 484 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
485 485 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
486 486 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
487 487
488 488 if gp1>gp2:
489 489 if a1>0.7*a2:
490 490 choice=1
491 491 else:
492 492 choice=2
493 493 elif gp2>gp1:
494 494 if a2>0.7*a1:
495 495 choice=2
496 496 else:
497 497 choice=1
498 498 else:
499 499 choice=numpy.argmax([a1,a2])+1
500 500 #else:
501 501 #choice=argmin([std2a,std2b])+1
502 502
503 503 else: # with low SNR go to the most energetic peak
504 504 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
505 505
506 506
507 507 shift0=lsq2[0][0];
508 508 vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
509 509 shift1=lsq2[0][4];
510 510 vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
511 511
512 512 max_vel = 1.0
513 513
514 514 #first peak will be 0, second peak will be 1
515 515 if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range
516 516 shift0=lsq2[0][0]
517 517 width0=lsq2[0][1]
518 518 Amplitude0=lsq2[0][2]
519 519 p0=lsq2[0][3]
520 520
521 521 shift1=lsq2[0][4]
522 522 width1=lsq2[0][5]
523 523 Amplitude1=lsq2[0][6]
524 524 p1=lsq2[0][7]
525 525 noise=lsq2[0][8]
526 526 else:
527 527 shift1=lsq2[0][0]
528 528 width1=lsq2[0][1]
529 529 Amplitude1=lsq2[0][2]
530 530 p1=lsq2[0][3]
531 531
532 532 shift0=lsq2[0][4]
533 533 width0=lsq2[0][5]
534 534 Amplitude0=lsq2[0][6]
535 535 p0=lsq2[0][7]
536 536 noise=lsq2[0][8]
537 537
538 538 if Amplitude0<0.05: # in case the peak is noise
539 539 shift0,width0,Amplitude0,p0 = [0,0,0,0]#4*[numpy.NaN]
540 540 if Amplitude1<0.05:
541 541 shift1,width1,Amplitude1,p1 = [0,0,0,0]#4*[numpy.NaN]
542 542
543 543
544 544 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
545 545 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
546 546 SPCparam = (SPC_ch1,SPC_ch2)
547 547
548 548
549 549 return GauSPC
550 550
551 551 def y_model1(self,x,state):
552 552 shift0,width0,amplitude0,power0,noise=state
553 553 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
554 554
555 555 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
556 556
557 557 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
558 558 return model0+model0u+model0d+noise
559 559
560 560 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
561 561 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
562 562 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
563 563
564 564 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
565 565
566 566 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
567 567 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
568 568
569 569 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
570 570
571 571 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
572 572 return model0+model0u+model0d+model1+model1u+model1d+noise
573 573
574 574 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
575 575
576 576 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
577 577
578 578 def misfit2(self,state,y_data,x,num_intg):
579 579 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
580 580
581 581
582 582
583 583 class PrecipitationProc(Operation):
584 584
585 585 '''
586 586 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
587 587
588 588 Input:
589 589 self.dataOut.data_pre : SelfSpectra
590 590
591 591 Output:
592 592
593 593 self.dataOut.data_output : Reflectivity factor, rainfall Rate
594 594
595 595
596 596 Parameters affected:
597 597 '''
598 598
599 599 def __init__(self):
600 600 Operation.__init__(self)
601 601 self.i=0
602 602
603 603
604 604 def gaus(self,xSamples,Amp,Mu,Sigma):
605 605 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
606 606
607 607
608 608
609 609 def Moments(self, ySamples, xSamples):
610 610 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
611 611 yNorm = ySamples / Pot
612 612
613 613 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
614 614 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
615 615 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
616 616
617 617 return numpy.array([Pot, Vr, Desv])
618 618
619 619 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
620 620 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km = 0.93, Altitude=3350):
621 621
622 622
623 623 Velrange = dataOut.spcparam_range[2]
624 624 FrecRange = dataOut.spcparam_range[0]
625 625
626 626 dV= Velrange[1]-Velrange[0]
627 627 dF= FrecRange[1]-FrecRange[0]
628 628
629 629 if radar == "MIRA35C" :
630 630
631 631 self.spc = dataOut.data_pre[0].copy()
632 632 self.Num_Hei = self.spc.shape[2]
633 633 self.Num_Bin = self.spc.shape[1]
634 634 self.Num_Chn = self.spc.shape[0]
635 635 Ze = self.dBZeMODE2(dataOut)
636 636
637 637 else:
638 638
639 639 self.spc = dataOut.SPCparam[1].copy() #dataOut.data_pre[0].copy() #
640 640
641 641 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
642 642
643 643 self.spc[:,:,0:7]= numpy.NaN
644 644
645 645 """##########################################"""
646 646
647 647 self.Num_Hei = self.spc.shape[2]
648 648 self.Num_Bin = self.spc.shape[1]
649 649 self.Num_Chn = self.spc.shape[0]
650 650
651 651 ''' Se obtiene la constante del RADAR '''
652 652
653 653 self.Pt = Pt
654 654 self.Gt = Gt
655 655 self.Gr = Gr
656 656 self.Lambda = Lambda
657 657 self.aL = aL
658 658 self.tauW = tauW
659 659 self.ThetaT = ThetaT
660 660 self.ThetaR = ThetaR
661 661
662 662 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
663 663 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
664 664 RadarConstant = 10e-26 * Numerator / Denominator #
665 665
666 666 ''' ============================= '''
667 667
668 668 self.spc[0] = (self.spc[0]-dataOut.noise[0])
669 669 self.spc[1] = (self.spc[1]-dataOut.noise[1])
670 670 self.spc[2] = (self.spc[2]-dataOut.noise[2])
671 671
672 672 self.spc[ numpy.where(self.spc < 0)] = 0
673 673
674 674 SPCmean = (numpy.mean(self.spc,0) - numpy.mean(dataOut.noise))
675 675 SPCmean[ numpy.where(SPCmean < 0)] = 0
676 676
677 677 ETAn = numpy.zeros([self.Num_Bin,self.Num_Hei])
678 678 ETAv = numpy.zeros([self.Num_Bin,self.Num_Hei])
679 679 ETAd = numpy.zeros([self.Num_Bin,self.Num_Hei])
680 680
681 681 Pr = SPCmean[:,:]
682 682
683 683 VelMeteoro = numpy.mean(SPCmean,axis=0)
684 684
685 685 D_range = numpy.zeros([self.Num_Bin,self.Num_Hei])
686 686 SIGMA = numpy.zeros([self.Num_Bin,self.Num_Hei])
687 687 N_dist = numpy.zeros([self.Num_Bin,self.Num_Hei])
688 688 V_mean = numpy.zeros(self.Num_Hei)
689 689 del_V = numpy.zeros(self.Num_Hei)
690 690 Z = numpy.zeros(self.Num_Hei)
691 691 Ze = numpy.zeros(self.Num_Hei)
692 692 RR = numpy.zeros(self.Num_Hei)
693 693
694 694 Range = dataOut.heightList*1000.
695 695
696 696 for R in range(self.Num_Hei):
697 697
698 698 h = Range[R] + Altitude #Range from ground to radar pulse altitude
699 699 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
700 700
701 701 D_range[:,R] = numpy.log( (9.65 - (Velrange[0:self.Num_Bin] / del_V[R])) / 10.3 ) / -0.6 #Diameter range [m]x10**-3
702 702
703 703 '''NOTA: ETA(n) dn = ETA(f) df
704 704
705 705 dn = 1 Diferencial de muestreo
706 706 df = ETA(n) / ETA(f)
707 707
708 708 '''
709 709
710 710 ETAn[:,R] = RadarConstant * Pr[:,R] * (Range[R] )**2 #Reflectivity (ETA)
711 711
712 712 ETAv[:,R]=ETAn[:,R]/dV
713 713
714 714 ETAd[:,R]=ETAv[:,R]*6.18*exp(-0.6*D_range[:,R])
715 715
716 716 SIGMA[:,R] = Km * (D_range[:,R] * 1e-3 )**6 * numpy.pi**5 / Lambda**4 #Equivalent Section of drops (sigma)
717 717
718 718 N_dist[:,R] = ETAn[:,R] / SIGMA[:,R]
719 719
720 720 DMoments = self.Moments(Pr[:,R], Velrange[0:self.Num_Bin])
721 721
722 722 try:
723 723 popt01,pcov = curve_fit(self.gaus, Velrange[0:self.Num_Bin] , Pr[:,R] , p0=DMoments)
724 724 except:
725 725 popt01=numpy.zeros(3)
726 726 popt01[1]= DMoments[1]
727 727
728 728 if popt01[1]<0 or popt01[1]>20:
729 729 popt01[1]=numpy.NaN
730 730
731 731
732 732 V_mean[R]=popt01[1]
733 733
734 734 Z[R] = numpy.nansum( N_dist[:,R] * (D_range[:,R])**6 )#*10**-18
735 735
736 736 RR[R] = 0.0006*numpy.pi * numpy.nansum( D_range[:,R]**3 * N_dist[:,R] * Velrange[0:self.Num_Bin] ) #Rainfall rate
737 737
738 738 Ze[R] = (numpy.nansum( ETAn[:,R]) * Lambda**4) / ( 10**-18*numpy.pi**5 * Km)
739 739
740 740
741 741
742 742 RR2 = (Z/200)**(1/1.6)
743 743 dBRR = 10*numpy.log10(RR)
744 744 dBRR2 = 10*numpy.log10(RR2)
745 745
746 746 dBZe = 10*numpy.log10(Ze)
747 747 dBZ = 10*numpy.log10(Z)
748 748
749 749 dataOut.data_output = RR[8]
750 750 dataOut.data_param = numpy.ones([3,self.Num_Hei])
751 751 dataOut.channelList = [0,1,2]
752 752
753 753 dataOut.data_param[0]=dBZ
754 754 dataOut.data_param[1]=V_mean
755 755 dataOut.data_param[2]=RR
756 756
757 757 return dataOut
758 758
759 759 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
760 760
761 761 NPW = dataOut.NPW
762 762 COFA = dataOut.COFA
763 763
764 764 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
765 765 RadarConst = dataOut.RadarConst
766 766 #frequency = 34.85*10**9
767 767
768 768 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
769 769 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
770 770
771 771 ETA = numpy.sum(SNR,1)
772 772
773 773 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
774 774
775 775 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
776 776
777 777 for r in range(self.Num_Hei):
778 778
779 779 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
780 780 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
781 781
782 782 return Ze
783 783
784 784 # def GetRadarConstant(self):
785 785 #
786 786 # """
787 787 # Constants:
788 788 #
789 789 # Pt: Transmission Power dB 5kW 5000
790 790 # Gt: Transmission Gain dB 24.7 dB 295.1209
791 791 # Gr: Reception Gain dB 18.5 dB 70.7945
792 792 # Lambda: Wavelenght m 0.6741 m 0.6741
793 793 # aL: Attenuation loses dB 4dB 2.5118
794 794 # tauW: Width of transmission pulse s 4us 4e-6
795 795 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
796 796 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
797 797 #
798 798 # """
799 799 #
800 800 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
801 801 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
802 802 # RadarConstant = Numerator / Denominator
803 803 #
804 804 # return RadarConstant
805 805
806 806
807 807
808 808 class FullSpectralAnalysis(Operation):
809 809
810 810 """
811 811 Function that implements Full Spectral Analisys technique.
812 812
813 813 Input:
814 814 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
815 815 self.dataOut.groupList : Pairlist of channels
816 816 self.dataOut.ChanDist : Physical distance between receivers
817 817
818 818
819 819 Output:
820 820
821 821 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
822 822
823 823
824 824 Parameters affected: Winds, height range, SNR
825 825
826 826 """
827 827 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRlimit=7):
828 828
829 829 self.indice=int(numpy.random.rand()*1000)
830 830
831 831 spc = dataOut.data_pre[0].copy()
832 832 cspc = dataOut.data_pre[1]
833 833
834 834 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
835 835
836 836 SNRspc = spc.copy()
837 837 SNRspc[:,:,0:7]= numpy.NaN
838 838
839 839 """##########################################"""
840 840
841 841
842 842 nChannel = spc.shape[0]
843 843 nProfiles = spc.shape[1]
844 844 nHeights = spc.shape[2]
845 845
846 846 pairsList = dataOut.groupList
847 847 if dataOut.ChanDist is not None :
848 848 ChanDist = dataOut.ChanDist
849 849 else:
850 850 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
851 851
852 852 FrecRange = dataOut.spc_range[0]
853 853
854 854 ySamples=numpy.ones([nChannel,nProfiles])
855 855 phase=numpy.ones([nChannel,nProfiles])
856 856 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
857 857 coherence=numpy.ones([nChannel,nProfiles])
858 858 PhaseSlope=numpy.ones(nChannel)
859 859 PhaseInter=numpy.ones(nChannel)
860 860 data_SNR=numpy.zeros([nProfiles])
861 861
862 862 data = dataOut.data_pre
863 863 noise = dataOut.noise
864 864
865 865 dataOut.data_SNR = (numpy.mean(SNRspc,axis=1)- noise[0]) / noise[0]
866 866
867 867 dataOut.data_SNR[numpy.where( dataOut.data_SNR <0 )] = 1e-20
868 868
869 869
870 870 data_output=numpy.ones([spc.shape[0],spc.shape[2]])*numpy.NaN
871 871
872 872 velocityX=[]
873 873 velocityY=[]
874 874 velocityV=[]
875 875 PhaseLine=[]
876 876
877 877 dbSNR = 10*numpy.log10(dataOut.data_SNR)
878 878 dbSNR = numpy.average(dbSNR,0)
879 879
880 880 for Height in range(nHeights):
881 881
882 882 [Vzon,Vmer,Vver, GaussCenter, PhaseSlope, FitGaussCSPC]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, dataOut.spc_range, dbSNR[Height], SNRlimit)
883 883 PhaseLine = numpy.append(PhaseLine, PhaseSlope)
884 884
885 885 if abs(Vzon)<100. and abs(Vzon)> 0.:
886 886 velocityX=numpy.append(velocityX, Vzon)#Vmag
887 887
888 888 else:
889 889 velocityX=numpy.append(velocityX, numpy.NaN)
890 890
891 891 if abs(Vmer)<100. and abs(Vmer) > 0.:
892 892 velocityY=numpy.append(velocityY, -Vmer)#Vang
893 893
894 894 else:
895 895 velocityY=numpy.append(velocityY, numpy.NaN)
896 896
897 897 if dbSNR[Height] > SNRlimit:
898 898 velocityV=numpy.append(velocityV, -Vver)#FirstMoment[Height])
899 899 else:
900 900 velocityV=numpy.append(velocityV, numpy.NaN)
901 901
902 902
903 903
904 904 '''Nota: Cambiar el signo de numpy.array(velocityX) cuando se intente procesar datos de BLTR'''
905 905 data_output[0] = numpy.array(velocityX) #self.moving_average(numpy.array(velocityX) , N=1)
906 906 data_output[1] = numpy.array(velocityY) #self.moving_average(numpy.array(velocityY) , N=1)
907 907 data_output[2] = velocityV#FirstMoment
908 908
909 909 xFrec=FrecRange[0:spc.shape[1]]
910 910
911 911 dataOut.data_output=data_output
912 912
913 913 return dataOut
914 914
915 915
916 916 def moving_average(self,x, N=2):
917 917 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
918 918
919 919 def gaus(self,xSamples,Amp,Mu,Sigma):
920 920 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
921 921
922 922
923 923
924 924 def Moments(self, ySamples, xSamples):
925 925 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
926 926 yNorm = ySamples / Pot
927 927 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
928 928 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
929 929 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
930 930
931 931 return numpy.array([Pot, Vr, Desv])
932 932
933 933 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit):
934 934
935 935
936 936
937 937 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
938 938 phase=numpy.ones([spc.shape[0],spc.shape[1]])
939 939 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
940 940 coherence=numpy.ones([spc.shape[0],spc.shape[1]])
941 941 PhaseSlope=numpy.zeros(spc.shape[0])
942 942 PhaseInter=numpy.ones(spc.shape[0])
943 943 xFrec=AbbsisaRange[0][0:spc.shape[1]]
944 944 xVel =AbbsisaRange[2][0:spc.shape[1]]
945 945 Vv=numpy.empty(spc.shape[2])*0
946 946 SPCav = numpy.average(spc, axis=0)-numpy.average(noise) #spc[0]-noise[0]#
947 947
948 948 SPCmoments = self.Moments(SPCav[:,Height], xVel )
949 949 CSPCmoments = []
950 950 cspcNoise = numpy.empty(3)
951 951
952 952 '''Getting Eij and Nij'''
953 953
954 954 Xi01=ChanDist[0][0]
955 955 Eta01=ChanDist[0][1]
956 956
957 957 Xi02=ChanDist[1][0]
958 958 Eta02=ChanDist[1][1]
959 959
960 960 Xi12=ChanDist[2][0]
961 961 Eta12=ChanDist[2][1]
962 962
963 963 z = spc.copy()
964 964 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
965 965
966 966 for i in range(spc.shape[0]):
967 967
968 968 '''****** Line of Data SPC ******'''
969 969 zline=z[i,:,Height].copy() - noise[i] # Se resta ruido
970 970
971 971 '''****** SPC is normalized ******'''
972 972 SmoothSPC =self.moving_average(zline.copy(),N=1) # Se suaviza el ruido
973 973 FactNorm = SmoothSPC/numpy.nansum(SmoothSPC) # SPC Normalizado y suavizado
974 974
975 975 xSamples = xFrec # Se toma el rango de frecuncias
976 976 ySamples[i] = FactNorm # Se toman los valores de SPC normalizado
977 977
978 978 for i in range(spc.shape[0]):
979 979
980 980 '''****** Line of Data CSPC ******'''
981 981 cspcLine = ( cspc[i,:,Height].copy())# - noise[i] ) # no! Se resta el ruido
982 982 SmoothCSPC =self.moving_average(cspcLine,N=1) # Se suaviza el ruido
983 983 cspcNorm = SmoothCSPC/numpy.nansum(SmoothCSPC) # CSPC normalizado y suavizado
984 984
985 985 '''****** CSPC is normalized with respect to Briggs and Vincent ******'''
986 986 chan_index0 = pairsList[i][0]
987 987 chan_index1 = pairsList[i][1]
988 988
989 989 CSPCFactor= numpy.abs(numpy.nansum(ySamples[chan_index0]))**2 * numpy.abs(numpy.nansum(ySamples[chan_index1]))**2
990 990 CSPCNorm = cspcNorm / numpy.sqrt(CSPCFactor)
991 991
992 992 CSPCSamples[i] = CSPCNorm
993 993
994 994 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
995 995
996 996 #coherence[i]= self.moving_average(coherence[i],N=1)
997 997
998 998 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
999 999
1000 1000 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPCSamples[0]), xSamples),
1001 1001 self.Moments(numpy.abs(CSPCSamples[1]), xSamples),
1002 1002 self.Moments(numpy.abs(CSPCSamples[2]), xSamples)])
1003 1003
1004 1004
1005 1005 popt=[1e-10,0,1e-10]
1006 1006 popt01, popt02, popt12 = [1e-10,1e-10,1e-10], [1e-10,1e-10,1e-10] ,[1e-10,1e-10,1e-10]
1007 1007 FitGauss01, FitGauss02, FitGauss12 = numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0
1008 1008
1009 1009 CSPCMask01 = numpy.abs(CSPCSamples[0])
1010 1010 CSPCMask02 = numpy.abs(CSPCSamples[1])
1011 1011 CSPCMask12 = numpy.abs(CSPCSamples[2])
1012 1012
1013 1013 mask01 = ~numpy.isnan(CSPCMask01)
1014 1014 mask02 = ~numpy.isnan(CSPCMask02)
1015 1015 mask12 = ~numpy.isnan(CSPCMask12)
1016 1016
1017 1017 #mask = ~numpy.isnan(CSPCMask01)
1018 1018 CSPCMask01 = CSPCMask01[mask01]
1019 1019 CSPCMask02 = CSPCMask02[mask02]
1020 1020 CSPCMask12 = CSPCMask12[mask12]
1021 1021 #CSPCMask01 = numpy.ma.masked_invalid(CSPCMask01)
1022 1022
1023 1023
1024 1024
1025 1025 '''***Fit Gauss CSPC01***'''
1026 1026 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3 :
1027 1027 try:
1028 1028 popt01,pcov = curve_fit(self.gaus,xSamples[mask01],numpy.abs(CSPCMask01),p0=CSPCmoments[0])
1029 1029 popt02,pcov = curve_fit(self.gaus,xSamples[mask02],numpy.abs(CSPCMask02),p0=CSPCmoments[1])
1030 1030 popt12,pcov = curve_fit(self.gaus,xSamples[mask12],numpy.abs(CSPCMask12),p0=CSPCmoments[2])
1031 1031 FitGauss01 = self.gaus(xSamples,*popt01)
1032 1032 FitGauss02 = self.gaus(xSamples,*popt02)
1033 1033 FitGauss12 = self.gaus(xSamples,*popt12)
1034 1034 except:
1035 1035 FitGauss01=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[0]))
1036 1036 FitGauss02=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[1]))
1037 1037 FitGauss12=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[2]))
1038 1038
1039 1039
1040 1040 CSPCopt = numpy.vstack([popt01,popt02,popt12])
1041 1041
1042 1042 '''****** Getting fij width ******'''
1043 1043
1044 1044 yMean = numpy.average(ySamples, axis=0) # ySamples[0]
1045 1045
1046 1046 '''******* Getting fitting Gaussian *******'''
1047 1047 meanGauss = sum(xSamples*yMean) / len(xSamples) # Mu, velocidad radial (frecuencia)
1048 1048 sigma2 = sum(yMean*(xSamples-meanGauss)**2) / len(xSamples) # Varianza, Ancho espectral (frecuencia)
1049 1049
1050 1050 yMoments = self.Moments(yMean, xSamples)
1051 1051
1052 1052 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3: # and abs(meanGauss/sigma2) > 0.00001:
1053 1053 try:
1054 1054 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=yMoments)
1055 1055 FitGauss=self.gaus(xSamples,*popt)
1056 1056
1057 1057 except :#RuntimeError:
1058 1058 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1059 1059
1060 1060
1061 1061 else:
1062 1062 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1063 1063
1064 1064
1065 1065
1066 1066 '''****** Getting Fij ******'''
1067 1067 Fijcspc = CSPCopt[:,2]/2*3
1068 1068
1069 1069
1070 1070 GaussCenter = popt[1] #xFrec[GCpos]
1071 1071 #Punto en Eje X de la Gaussiana donde se encuentra el centro
1072 1072 ClosestCenter = xSamples[numpy.abs(xSamples-GaussCenter).argmin()]
1073 1073 PointGauCenter = numpy.where(xSamples==ClosestCenter)[0][0]
1074 1074
1075 1075 #Punto e^-1 hubicado en la Gaussiana
1076 1076 PeMinus1 = numpy.max(FitGauss)* numpy.exp(-1)
1077 1077 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # El punto mas cercano a "Peminus1" dentro de "FitGauss"
1078 1078 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1079 1079
1080 1080 if xSamples[PointFij] > xSamples[PointGauCenter]:
1081 1081 Fij = xSamples[PointFij] - xSamples[PointGauCenter]
1082 1082
1083 1083 else:
1084 1084 Fij = xSamples[PointGauCenter] - xSamples[PointFij]
1085 1085
1086 1086
1087 1087 '''****** Taking frequency ranges from SPCs ******'''
1088 1088
1089 1089
1090 1090 #GaussCenter = popt[1] #Primer momento 01
1091 1091 GauWidth = popt[2] *3/2 #Ancho de banda de Gau01
1092 1092 Range = numpy.empty(2)
1093 1093 Range[0] = GaussCenter - GauWidth
1094 1094 Range[1] = GaussCenter + GauWidth
1095 1095 #Punto en Eje X de la Gaussiana donde se encuentra ancho de banda (min:max)
1096 1096 ClosRangeMin = xSamples[numpy.abs(xSamples-Range[0]).argmin()]
1097 1097 ClosRangeMax = xSamples[numpy.abs(xSamples-Range[1]).argmin()]
1098 1098
1099 1099 PointRangeMin = numpy.where(xSamples==ClosRangeMin)[0][0]
1100 1100 PointRangeMax = numpy.where(xSamples==ClosRangeMax)[0][0]
1101 1101
1102 1102 Range=numpy.array([ PointRangeMin, PointRangeMax ])
1103 1103
1104 1104 FrecRange = xFrec[ Range[0] : Range[1] ]
1105 1105 VelRange = xVel[ Range[0] : Range[1] ]
1106 1106
1107 1107
1108 1108 '''****** Getting SCPC Slope ******'''
1109 1109
1110 1110 for i in range(spc.shape[0]):
1111 1111
1112 1112 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.3:
1113 1113 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1114 1114
1115 1115 '''***********************VelRange******************'''
1116 1116
1117 1117 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1118 1118
1119 1119 if len(FrecRange) == len(PhaseRange):
1120 1120 try:
1121 1121 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange[mask], PhaseRange[mask])
1122 1122 PhaseSlope[i]=slope
1123 1123 PhaseInter[i]=intercept
1124 1124 except:
1125 1125 PhaseSlope[i]=0
1126 1126 PhaseInter[i]=0
1127 1127 else:
1128 1128 PhaseSlope[i]=0
1129 1129 PhaseInter[i]=0
1130 1130 else:
1131 1131 PhaseSlope[i]=0
1132 1132 PhaseInter[i]=0
1133 1133
1134 1134
1135 1135 '''Getting constant C'''
1136 1136 cC=(Fij*numpy.pi)**2
1137 1137
1138 1138 '''****** Getting constants F and G ******'''
1139 1139 MijEijNij=numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1140 1140 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1141 1141 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1142 1142 MijResults=numpy.array([MijResult0,MijResult1])
1143 1143 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1144 1144
1145 1145 '''****** Getting constants A, B and H ******'''
1146 1146 W01=numpy.nanmax( FitGauss01 ) #numpy.abs(CSPCSamples[0]))
1147 1147 W02=numpy.nanmax( FitGauss02 ) #numpy.abs(CSPCSamples[1]))
1148 1148 W12=numpy.nanmax( FitGauss12 ) #numpy.abs(CSPCSamples[2]))
1149 1149
1150 1150 WijResult0=((cF*Xi01+cG*Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1151 1151 WijResult1=((cF*Xi02+cG*Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1152 1152 WijResult2=((cF*Xi12+cG*Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1153 1153
1154 1154 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1155 1155
1156 1156 WijEijNij=numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1157 1157 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1158 1158
1159 1159 VxVy=numpy.array([[cA,cH],[cH,cB]])
1160 1160 VxVyResults=numpy.array([-cF,-cG])
1161 1161 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1162 1162
1163 1163 Vzon = Vy
1164 1164 Vmer = Vx
1165 1165 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
1166 1166 Vang=numpy.arctan2(Vmer,Vzon)
1167 1167 if numpy.abs( popt[1] ) < 3.5 and len(FrecRange)>4:
1168 1168 Vver=popt[1]
1169 1169 else:
1170 1170 Vver=numpy.NaN
1171 1171 FitGaussCSPC = numpy.array([FitGauss01,FitGauss02,FitGauss12])
1172 1172
1173 1173
1174 1174 return Vzon, Vmer, Vver, GaussCenter, PhaseSlope, FitGaussCSPC
1175 1175
1176 1176 class SpectralMoments(Operation):
1177 1177
1178 1178 '''
1179 1179 Function SpectralMoments()
1180 1180
1181 1181 Calculates moments (power, mean, standard deviation) and SNR of the signal
1182 1182
1183 1183 Type of dataIn: Spectra
1184 1184
1185 1185 Configuration Parameters:
1186 1186
1187 1187 dirCosx : Cosine director in X axis
1188 1188 dirCosy : Cosine director in Y axis
1189 1189
1190 1190 elevation :
1191 1191 azimuth :
1192 1192
1193 1193 Input:
1194 1194 channelList : simple channel list to select e.g. [2,3,7]
1195 1195 self.dataOut.data_pre : Spectral data
1196 1196 self.dataOut.abscissaList : List of frequencies
1197 1197 self.dataOut.noise : Noise level per channel
1198 1198
1199 1199 Affected:
1200 self.dataOut.moments : Parameters per channel
1201 self.dataOut.data_SNR : SNR per channel
1200 self.dataOut.moments : Parameters per channel
1201 self.dataOut.data_SNR : SNR per channel
1202 1202
1203 1203 '''
1204 1204
1205 1205 def run(self, dataOut):
1206 1206
1207 1207 #dataOut.data_pre = dataOut.data_pre[0]
1208 1208 data = dataOut.data_pre[0]
1209 1209 absc = dataOut.abscissaList[:-1]
1210 1210 noise = dataOut.noise
1211 1211 nChannel = data.shape[0]
1212 1212 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1213 1213
1214 1214 for ind in range(nChannel):
1215 1215 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1216 1216
1217 1217 dataOut.moments = data_param[:,1:,:]
1218 1218 dataOut.data_SNR = data_param[:,0]
1219 1219 dataOut.data_DOP = data_param[:,1]
1220 1220 dataOut.data_MEAN = data_param[:,2]
1221 1221 dataOut.data_STD = data_param[:,3]
1222 1222 return dataOut
1223 1223
1224 1224 def __calculateMoments(self, oldspec, oldfreq, n0,
1225 1225 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1226 1226
1227 1227 if (nicoh is None): nicoh = 1
1228 1228 if (graph is None): graph = 0
1229 1229 if (smooth is None): smooth = 0
1230 1230 elif (self.smooth < 3): smooth = 0
1231 1231
1232 1232 if (type1 is None): type1 = 0
1233 1233 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1234 1234 if (snrth is None): snrth = -3
1235 1235 if (dc is None): dc = 0
1236 1236 if (aliasing is None): aliasing = 0
1237 1237 if (oldfd is None): oldfd = 0
1238 1238 if (wwauto is None): wwauto = 0
1239 1239
1240 1240 if (n0 < 1.e-20): n0 = 1.e-20
1241 1241
1242 1242 freq = oldfreq
1243 1243 vec_power = numpy.zeros(oldspec.shape[1])
1244 1244 vec_fd = numpy.zeros(oldspec.shape[1])
1245 1245 vec_w = numpy.zeros(oldspec.shape[1])
1246 1246 vec_snr = numpy.zeros(oldspec.shape[1])
1247 1247
1248 1248 oldspec = numpy.ma.masked_invalid(oldspec)
1249 1249
1250 1250 for ind in range(oldspec.shape[1]):
1251 1251
1252 1252 spec = oldspec[:,ind]
1253 1253 aux = spec*fwindow
1254 1254 max_spec = aux.max()
1255 1255 m = list(aux).index(max_spec)
1256 1256
1257 1257 #Smooth
1258 1258 if (smooth == 0): spec2 = spec
1259 1259 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1260 1260
1261 1261 # Calculo de Momentos
1262 1262 bb = spec2[list(range(m,spec2.size))]
1263 1263 bb = (bb<n0).nonzero()
1264 1264 bb = bb[0]
1265 1265
1266 1266 ss = spec2[list(range(0,m + 1))]
1267 1267 ss = (ss<n0).nonzero()
1268 1268 ss = ss[0]
1269 1269
1270 1270 if (bb.size == 0):
1271 1271 bb0 = spec.size - 1 - m
1272 1272 else:
1273 1273 bb0 = bb[0] - 1
1274 1274 if (bb0 < 0):
1275 1275 bb0 = 0
1276 1276
1277 1277 if (ss.size == 0): ss1 = 1
1278 1278 else: ss1 = max(ss) + 1
1279 1279
1280 1280 if (ss1 > m): ss1 = m
1281 1281
1282 1282 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
1283 1283 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
1284 1284 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
1285 1285 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1286 1286 snr = (spec2.mean()-n0)/n0
1287 1287
1288 1288 if (snr < 1.e-20) :
1289 1289 snr = 1.e-20
1290 1290
1291 1291 vec_power[ind] = power
1292 1292 vec_fd[ind] = fd
1293 1293 vec_w[ind] = w
1294 1294 vec_snr[ind] = snr
1295 1295
1296 1296 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1297 1297 return moments
1298 1298
1299 1299 #------------------ Get SA Parameters --------------------------
1300 1300
1301 1301 def GetSAParameters(self):
1302 1302 #SA en frecuencia
1303 1303 pairslist = self.dataOut.groupList
1304 1304 num_pairs = len(pairslist)
1305 1305
1306 1306 vel = self.dataOut.abscissaList
1307 1307 spectra = self.dataOut.data_pre
1308 1308 cspectra = self.dataIn.data_cspc
1309 1309 delta_v = vel[1] - vel[0]
1310 1310
1311 1311 #Calculating the power spectrum
1312 1312 spc_pow = numpy.sum(spectra, 3)*delta_v
1313 1313 #Normalizing Spectra
1314 1314 norm_spectra = spectra/spc_pow
1315 1315 #Calculating the norm_spectra at peak
1316 1316 max_spectra = numpy.max(norm_spectra, 3)
1317 1317
1318 1318 #Normalizing Cross Spectra
1319 1319 norm_cspectra = numpy.zeros(cspectra.shape)
1320 1320
1321 1321 for i in range(num_chan):
1322 1322 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1323 1323
1324 1324 max_cspectra = numpy.max(norm_cspectra,2)
1325 1325 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1326 1326
1327 1327 for i in range(num_pairs):
1328 1328 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1329 1329 #------------------- Get Lags ----------------------------------
1330 1330
1331 1331 class SALags(Operation):
1332 1332 '''
1333 1333 Function GetMoments()
1334 1334
1335 1335 Input:
1336 1336 self.dataOut.data_pre
1337 1337 self.dataOut.abscissaList
1338 1338 self.dataOut.noise
1339 1339 self.dataOut.normFactor
1340 1340 self.dataOut.data_SNR
1341 1341 self.dataOut.groupList
1342 1342 self.dataOut.nChannels
1343 1343
1344 1344 Affected:
1345 1345 self.dataOut.data_param
1346 1346
1347 1347 '''
1348 1348 def run(self, dataOut):
1349 1349 data_acf = dataOut.data_pre[0]
1350 1350 data_ccf = dataOut.data_pre[1]
1351 1351 normFactor_acf = dataOut.normFactor[0]
1352 1352 normFactor_ccf = dataOut.normFactor[1]
1353 1353 pairs_acf = dataOut.groupList[0]
1354 1354 pairs_ccf = dataOut.groupList[1]
1355 1355
1356 1356 nHeights = dataOut.nHeights
1357 1357 absc = dataOut.abscissaList
1358 1358 noise = dataOut.noise
1359 1359 SNR = dataOut.data_SNR
1360 1360 nChannels = dataOut.nChannels
1361 1361 # pairsList = dataOut.groupList
1362 1362 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1363 1363
1364 1364 for l in range(len(pairs_acf)):
1365 1365 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1366 1366
1367 1367 for l in range(len(pairs_ccf)):
1368 1368 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1369 1369
1370 1370 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1371 1371 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1372 1372 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1373 1373 return
1374 1374
1375 1375 # def __getPairsAutoCorr(self, pairsList, nChannels):
1376 1376 #
1377 1377 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1378 1378 #
1379 1379 # for l in range(len(pairsList)):
1380 1380 # firstChannel = pairsList[l][0]
1381 1381 # secondChannel = pairsList[l][1]
1382 1382 #
1383 1383 # #Obteniendo pares de Autocorrelacion
1384 1384 # if firstChannel == secondChannel:
1385 1385 # pairsAutoCorr[firstChannel] = int(l)
1386 1386 #
1387 1387 # pairsAutoCorr = pairsAutoCorr.astype(int)
1388 1388 #
1389 1389 # pairsCrossCorr = range(len(pairsList))
1390 1390 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1391 1391 #
1392 1392 # return pairsAutoCorr, pairsCrossCorr
1393 1393
1394 1394 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1395 1395
1396 1396 lag0 = data_acf.shape[1]/2
1397 1397 #Funcion de Autocorrelacion
1398 1398 mean_acf = stats.nanmean(data_acf, axis = 0)
1399 1399
1400 1400 #Obtencion Indice de TauCross
1401 1401 ind_ccf = data_ccf.argmax(axis = 1)
1402 1402 #Obtencion Indice de TauAuto
1403 1403 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1404 1404 ccf_lag0 = data_ccf[:,lag0,:]
1405 1405
1406 1406 for i in range(ccf_lag0.shape[0]):
1407 1407 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1408 1408
1409 1409 #Obtencion de TauCross y TauAuto
1410 1410 tau_ccf = lagRange[ind_ccf]
1411 1411 tau_acf = lagRange[ind_acf]
1412 1412
1413 1413 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1414 1414
1415 1415 tau_ccf[Nan1,Nan2] = numpy.nan
1416 1416 tau_acf[Nan1,Nan2] = numpy.nan
1417 1417 tau = numpy.vstack((tau_ccf,tau_acf))
1418 1418
1419 1419 return tau
1420 1420
1421 1421 def __calculateLag1Phase(self, data, lagTRange):
1422 1422 data1 = stats.nanmean(data, axis = 0)
1423 1423 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1424 1424
1425 1425 phase = numpy.angle(data1[lag1,:])
1426 1426
1427 1427 return phase
1428 1428
1429 1429 class SpectralFitting(Operation):
1430 1430 '''
1431 1431 Function GetMoments()
1432 1432
1433 1433 Input:
1434 1434 Output:
1435 1435 Variables modified:
1436 1436 '''
1437 1437
1438 1438 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1439 1439
1440 1440
1441 1441 if path != None:
1442 1442 sys.path.append(path)
1443 1443 self.dataOut.library = importlib.import_module(file)
1444 1444
1445 1445 #To be inserted as a parameter
1446 1446 groupArray = numpy.array(groupList)
1447 1447 # groupArray = numpy.array([[0,1],[2,3]])
1448 1448 self.dataOut.groupList = groupArray
1449 1449
1450 1450 nGroups = groupArray.shape[0]
1451 1451 nChannels = self.dataIn.nChannels
1452 1452 nHeights=self.dataIn.heightList.size
1453 1453
1454 1454 #Parameters Array
1455 1455 self.dataOut.data_param = None
1456 1456
1457 1457 #Set constants
1458 1458 constants = self.dataOut.library.setConstants(self.dataIn)
1459 1459 self.dataOut.constants = constants
1460 1460 M = self.dataIn.normFactor
1461 1461 N = self.dataIn.nFFTPoints
1462 1462 ippSeconds = self.dataIn.ippSeconds
1463 1463 K = self.dataIn.nIncohInt
1464 1464 pairsArray = numpy.array(self.dataIn.pairsList)
1465 1465
1466 1466 #List of possible combinations
1467 1467 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1468 1468 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1469 1469
1470 1470 if getSNR:
1471 1471 listChannels = groupArray.reshape((groupArray.size))
1472 1472 listChannels.sort()
1473 1473 noise = self.dataIn.getNoise()
1474 1474 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1475 1475
1476 1476 for i in range(nGroups):
1477 1477 coord = groupArray[i,:]
1478 1478
1479 1479 #Input data array
1480 1480 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1481 1481 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1482 1482
1483 1483 #Cross Spectra data array for Covariance Matrixes
1484 1484 ind = 0
1485 1485 for pairs in listComb:
1486 1486 pairsSel = numpy.array([coord[x],coord[y]])
1487 1487 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1488 1488 ind += 1
1489 1489 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1490 1490 dataCross = dataCross**2/K
1491 1491
1492 1492 for h in range(nHeights):
1493 1493
1494 1494 #Input
1495 1495 d = data[:,h]
1496 1496
1497 1497 #Covariance Matrix
1498 1498 D = numpy.diag(d**2/K)
1499 1499 ind = 0
1500 1500 for pairs in listComb:
1501 1501 #Coordinates in Covariance Matrix
1502 1502 x = pairs[0]
1503 1503 y = pairs[1]
1504 1504 #Channel Index
1505 1505 S12 = dataCross[ind,:,h]
1506 1506 D12 = numpy.diag(S12)
1507 1507 #Completing Covariance Matrix with Cross Spectras
1508 1508 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1509 1509 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1510 1510 ind += 1
1511 1511 Dinv=numpy.linalg.inv(D)
1512 1512 L=numpy.linalg.cholesky(Dinv)
1513 1513 LT=L.T
1514 1514
1515 1515 dp = numpy.dot(LT,d)
1516 1516
1517 1517 #Initial values
1518 1518 data_spc = self.dataIn.data_spc[coord,:,h]
1519 1519
1520 1520 if (h>0)and(error1[3]<5):
1521 1521 p0 = self.dataOut.data_param[i,:,h-1]
1522 1522 else:
1523 1523 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1524 1524
1525 1525 try:
1526 1526 #Least Squares
1527 1527 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1528 1528 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1529 1529 #Chi square error
1530 1530 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1531 1531 #Error with Jacobian
1532 1532 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1533 1533 except:
1534 1534 minp = p0*numpy.nan
1535 1535 error0 = numpy.nan
1536 1536 error1 = p0*numpy.nan
1537 1537
1538 1538 #Save
1539 1539 if self.dataOut.data_param is None:
1540 1540 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1541 1541 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1542 1542
1543 1543 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1544 1544 self.dataOut.data_param[i,:,h] = minp
1545 1545 return
1546 1546
1547 1547 def __residFunction(self, p, dp, LT, constants):
1548 1548
1549 1549 fm = self.dataOut.library.modelFunction(p, constants)
1550 1550 fmp=numpy.dot(LT,fm)
1551 1551
1552 1552 return dp-fmp
1553 1553
1554 1554 def __getSNR(self, z, noise):
1555 1555
1556 1556 avg = numpy.average(z, axis=1)
1557 1557 SNR = (avg.T-noise)/noise
1558 1558 SNR = SNR.T
1559 1559 return SNR
1560 1560
1561 1561 def __chisq(p,chindex,hindex):
1562 1562 #similar to Resid but calculates CHI**2
1563 1563 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1564 1564 dp=numpy.dot(LT,d)
1565 1565 fmp=numpy.dot(LT,fm)
1566 1566 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1567 1567 return chisq
1568 1568
1569 1569 class WindProfiler(Operation):
1570 1570
1571 1571 __isConfig = False
1572 1572
1573 1573 __initime = None
1574 1574 __lastdatatime = None
1575 1575 __integrationtime = None
1576 1576
1577 1577 __buffer = None
1578 1578
1579 1579 __dataReady = False
1580 1580
1581 1581 __firstdata = None
1582 1582
1583 1583 n = None
1584 1584
1585 1585 def __init__(self):
1586 1586 Operation.__init__(self)
1587 1587
1588 1588 def __calculateCosDir(self, elev, azim):
1589 1589 zen = (90 - elev)*numpy.pi/180
1590 1590 azim = azim*numpy.pi/180
1591 1591 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1592 1592 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1593 1593
1594 1594 signX = numpy.sign(numpy.cos(azim))
1595 1595 signY = numpy.sign(numpy.sin(azim))
1596 1596
1597 1597 cosDirX = numpy.copysign(cosDirX, signX)
1598 1598 cosDirY = numpy.copysign(cosDirY, signY)
1599 1599 return cosDirX, cosDirY
1600 1600
1601 1601 def __calculateAngles(self, theta_x, theta_y, azimuth):
1602 1602
1603 1603 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1604 1604 zenith_arr = numpy.arccos(dir_cosw)
1605 1605 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1606 1606
1607 1607 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1608 1608 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1609 1609
1610 1610 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1611 1611
1612 1612 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1613 1613
1614 1614 #
1615 1615 if horOnly:
1616 1616 A = numpy.c_[dir_cosu,dir_cosv]
1617 1617 else:
1618 1618 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1619 1619 A = numpy.asmatrix(A)
1620 1620 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1621 1621
1622 1622 return A1
1623 1623
1624 1624 def __correctValues(self, heiRang, phi, velRadial, SNR):
1625 1625 listPhi = phi.tolist()
1626 1626 maxid = listPhi.index(max(listPhi))
1627 1627 minid = listPhi.index(min(listPhi))
1628 1628
1629 1629 rango = list(range(len(phi)))
1630 1630 # rango = numpy.delete(rango,maxid)
1631 1631
1632 1632 heiRang1 = heiRang*math.cos(phi[maxid])
1633 1633 heiRangAux = heiRang*math.cos(phi[minid])
1634 1634 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1635 1635 heiRang1 = numpy.delete(heiRang1,indOut)
1636 1636
1637 1637 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1638 1638 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1639 1639
1640 1640 for i in rango:
1641 1641 x = heiRang*math.cos(phi[i])
1642 1642 y1 = velRadial[i,:]
1643 1643 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1644 1644
1645 1645 x1 = heiRang1
1646 1646 y11 = f1(x1)
1647 1647
1648 1648 y2 = SNR[i,:]
1649 1649 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1650 1650 y21 = f2(x1)
1651 1651
1652 1652 velRadial1[i,:] = y11
1653 1653 SNR1[i,:] = y21
1654 1654
1655 1655 return heiRang1, velRadial1, SNR1
1656 1656
1657 1657 def __calculateVelUVW(self, A, velRadial):
1658 1658
1659 1659 #Operacion Matricial
1660 1660 # velUVW = numpy.zeros((velRadial.shape[1],3))
1661 1661 # for ind in range(velRadial.shape[1]):
1662 1662 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1663 1663 # velUVW = velUVW.transpose()
1664 1664 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1665 1665 velUVW[:,:] = numpy.dot(A,velRadial)
1666 1666
1667 1667
1668 1668 return velUVW
1669 1669
1670 1670 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1671 1671
1672 1672 def techniqueDBS(self, kwargs):
1673 1673 """
1674 1674 Function that implements Doppler Beam Swinging (DBS) technique.
1675 1675
1676 1676 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1677 1677 Direction correction (if necessary), Ranges and SNR
1678 1678
1679 1679 Output: Winds estimation (Zonal, Meridional and Vertical)
1680 1680
1681 1681 Parameters affected: Winds, height range, SNR
1682 1682 """
1683 1683 velRadial0 = kwargs['velRadial']
1684 1684 heiRang = kwargs['heightList']
1685 1685 SNR0 = kwargs['SNR']
1686 1686
1687 1687 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1688 1688 theta_x = numpy.array(kwargs['dirCosx'])
1689 1689 theta_y = numpy.array(kwargs['dirCosy'])
1690 1690 else:
1691 1691 elev = numpy.array(kwargs['elevation'])
1692 1692 azim = numpy.array(kwargs['azimuth'])
1693 1693 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1694 1694 azimuth = kwargs['correctAzimuth']
1695 1695 if 'horizontalOnly' in kwargs:
1696 1696 horizontalOnly = kwargs['horizontalOnly']
1697 1697 else: horizontalOnly = False
1698 1698 if 'correctFactor' in kwargs:
1699 1699 correctFactor = kwargs['correctFactor']
1700 1700 else: correctFactor = 1
1701 1701 if 'channelList' in kwargs:
1702 1702 channelList = kwargs['channelList']
1703 1703 if len(channelList) == 2:
1704 1704 horizontalOnly = True
1705 1705 arrayChannel = numpy.array(channelList)
1706 1706 param = param[arrayChannel,:,:]
1707 1707 theta_x = theta_x[arrayChannel]
1708 1708 theta_y = theta_y[arrayChannel]
1709 1709
1710 1710 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1711 1711 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1712 1712 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1713 1713
1714 1714 #Calculo de Componentes de la velocidad con DBS
1715 1715 winds = self.__calculateVelUVW(A,velRadial1)
1716 1716
1717 1717 return winds, heiRang1, SNR1
1718 1718
1719 1719 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1720 1720
1721 1721 nPairs = len(pairs_ccf)
1722 1722 posx = numpy.asarray(posx)
1723 1723 posy = numpy.asarray(posy)
1724 1724
1725 1725 #Rotacion Inversa para alinear con el azimuth
1726 1726 if azimuth!= None:
1727 1727 azimuth = azimuth*math.pi/180
1728 1728 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1729 1729 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1730 1730 else:
1731 1731 posx1 = posx
1732 1732 posy1 = posy
1733 1733
1734 1734 #Calculo de Distancias
1735 1735 distx = numpy.zeros(nPairs)
1736 1736 disty = numpy.zeros(nPairs)
1737 1737 dist = numpy.zeros(nPairs)
1738 1738 ang = numpy.zeros(nPairs)
1739 1739
1740 1740 for i in range(nPairs):
1741 1741 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1742 1742 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1743 1743 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1744 1744 ang[i] = numpy.arctan2(disty[i],distx[i])
1745 1745
1746 1746 return distx, disty, dist, ang
1747 1747 #Calculo de Matrices
1748 1748 # nPairs = len(pairs)
1749 1749 # ang1 = numpy.zeros((nPairs, 2, 1))
1750 1750 # dist1 = numpy.zeros((nPairs, 2, 1))
1751 1751 #
1752 1752 # for j in range(nPairs):
1753 1753 # dist1[j,0,0] = dist[pairs[j][0]]
1754 1754 # dist1[j,1,0] = dist[pairs[j][1]]
1755 1755 # ang1[j,0,0] = ang[pairs[j][0]]
1756 1756 # ang1[j,1,0] = ang[pairs[j][1]]
1757 1757 #
1758 1758 # return distx,disty, dist1,ang1
1759 1759
1760 1760
1761 1761 def __calculateVelVer(self, phase, lagTRange, _lambda):
1762 1762
1763 1763 Ts = lagTRange[1] - lagTRange[0]
1764 1764 velW = -_lambda*phase/(4*math.pi*Ts)
1765 1765
1766 1766 return velW
1767 1767
1768 1768 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1769 1769 nPairs = tau1.shape[0]
1770 1770 nHeights = tau1.shape[1]
1771 1771 vel = numpy.zeros((nPairs,3,nHeights))
1772 1772 dist1 = numpy.reshape(dist, (dist.size,1))
1773 1773
1774 1774 angCos = numpy.cos(ang)
1775 1775 angSin = numpy.sin(ang)
1776 1776
1777 1777 vel0 = dist1*tau1/(2*tau2**2)
1778 1778 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1779 1779 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1780 1780
1781 1781 ind = numpy.where(numpy.isinf(vel))
1782 1782 vel[ind] = numpy.nan
1783 1783
1784 1784 return vel
1785 1785
1786 1786 # def __getPairsAutoCorr(self, pairsList, nChannels):
1787 1787 #
1788 1788 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1789 1789 #
1790 1790 # for l in range(len(pairsList)):
1791 1791 # firstChannel = pairsList[l][0]
1792 1792 # secondChannel = pairsList[l][1]
1793 1793 #
1794 1794 # #Obteniendo pares de Autocorrelacion
1795 1795 # if firstChannel == secondChannel:
1796 1796 # pairsAutoCorr[firstChannel] = int(l)
1797 1797 #
1798 1798 # pairsAutoCorr = pairsAutoCorr.astype(int)
1799 1799 #
1800 1800 # pairsCrossCorr = range(len(pairsList))
1801 1801 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1802 1802 #
1803 1803 # return pairsAutoCorr, pairsCrossCorr
1804 1804
1805 1805 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1806 1806 def techniqueSA(self, kwargs):
1807 1807
1808 1808 """
1809 1809 Function that implements Spaced Antenna (SA) technique.
1810 1810
1811 1811 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1812 1812 Direction correction (if necessary), Ranges and SNR
1813 1813
1814 1814 Output: Winds estimation (Zonal, Meridional and Vertical)
1815 1815
1816 1816 Parameters affected: Winds
1817 1817 """
1818 1818 position_x = kwargs['positionX']
1819 1819 position_y = kwargs['positionY']
1820 1820 azimuth = kwargs['azimuth']
1821 1821
1822 1822 if 'correctFactor' in kwargs:
1823 1823 correctFactor = kwargs['correctFactor']
1824 1824 else:
1825 1825 correctFactor = 1
1826 1826
1827 1827 groupList = kwargs['groupList']
1828 1828 pairs_ccf = groupList[1]
1829 1829 tau = kwargs['tau']
1830 1830 _lambda = kwargs['_lambda']
1831 1831
1832 1832 #Cross Correlation pairs obtained
1833 1833 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1834 1834 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1835 1835 # pairsSelArray = numpy.array(pairsSelected)
1836 1836 # pairs = []
1837 1837 #
1838 1838 # #Wind estimation pairs obtained
1839 1839 # for i in range(pairsSelArray.shape[0]/2):
1840 1840 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1841 1841 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1842 1842 # pairs.append((ind1,ind2))
1843 1843
1844 1844 indtau = tau.shape[0]/2
1845 1845 tau1 = tau[:indtau,:]
1846 1846 tau2 = tau[indtau:-1,:]
1847 1847 # tau1 = tau1[pairs,:]
1848 1848 # tau2 = tau2[pairs,:]
1849 1849 phase1 = tau[-1,:]
1850 1850
1851 1851 #---------------------------------------------------------------------
1852 1852 #Metodo Directo
1853 1853 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1854 1854 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1855 1855 winds = stats.nanmean(winds, axis=0)
1856 1856 #---------------------------------------------------------------------
1857 1857 #Metodo General
1858 1858 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1859 1859 # #Calculo Coeficientes de Funcion de Correlacion
1860 1860 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1861 1861 # #Calculo de Velocidades
1862 1862 # winds = self.calculateVelUV(F,G,A,B,H)
1863 1863
1864 1864 #---------------------------------------------------------------------
1865 1865 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1866 1866 winds = correctFactor*winds
1867 1867 return winds
1868 1868
1869 1869 def __checkTime(self, currentTime, paramInterval, outputInterval):
1870 1870
1871 1871 dataTime = currentTime + paramInterval
1872 1872 deltaTime = dataTime - self.__initime
1873 1873
1874 1874 if deltaTime >= outputInterval or deltaTime < 0:
1875 1875 self.__dataReady = True
1876 1876 return
1877 1877
1878 1878 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1879 1879 '''
1880 1880 Function that implements winds estimation technique with detected meteors.
1881 1881
1882 1882 Input: Detected meteors, Minimum meteor quantity to wind estimation
1883 1883
1884 1884 Output: Winds estimation (Zonal and Meridional)
1885 1885
1886 1886 Parameters affected: Winds
1887 1887 '''
1888 1888 #Settings
1889 1889 nInt = (heightMax - heightMin)/2
1890 1890 nInt = int(nInt)
1891 1891 winds = numpy.zeros((2,nInt))*numpy.nan
1892 1892
1893 1893 #Filter errors
1894 1894 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1895 1895 finalMeteor = arrayMeteor[error,:]
1896 1896
1897 1897 #Meteor Histogram
1898 1898 finalHeights = finalMeteor[:,2]
1899 1899 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1900 1900 nMeteorsPerI = hist[0]
1901 1901 heightPerI = hist[1]
1902 1902
1903 1903 #Sort of meteors
1904 1904 indSort = finalHeights.argsort()
1905 1905 finalMeteor2 = finalMeteor[indSort,:]
1906 1906
1907 1907 # Calculating winds
1908 1908 ind1 = 0
1909 1909 ind2 = 0
1910 1910
1911 1911 for i in range(nInt):
1912 1912 nMet = nMeteorsPerI[i]
1913 1913 ind1 = ind2
1914 1914 ind2 = ind1 + nMet
1915 1915
1916 1916 meteorAux = finalMeteor2[ind1:ind2,:]
1917 1917
1918 1918 if meteorAux.shape[0] >= meteorThresh:
1919 1919 vel = meteorAux[:, 6]
1920 1920 zen = meteorAux[:, 4]*numpy.pi/180
1921 1921 azim = meteorAux[:, 3]*numpy.pi/180
1922 1922
1923 1923 n = numpy.cos(zen)
1924 1924 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1925 1925 # l = m*numpy.tan(azim)
1926 1926 l = numpy.sin(zen)*numpy.sin(azim)
1927 1927 m = numpy.sin(zen)*numpy.cos(azim)
1928 1928
1929 1929 A = numpy.vstack((l, m)).transpose()
1930 1930 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1931 1931 windsAux = numpy.dot(A1, vel)
1932 1932
1933 1933 winds[0,i] = windsAux[0]
1934 1934 winds[1,i] = windsAux[1]
1935 1935
1936 1936 return winds, heightPerI[:-1]
1937 1937
1938 1938 def techniqueNSM_SA(self, **kwargs):
1939 1939 metArray = kwargs['metArray']
1940 1940 heightList = kwargs['heightList']
1941 1941 timeList = kwargs['timeList']
1942 1942
1943 1943 rx_location = kwargs['rx_location']
1944 1944 groupList = kwargs['groupList']
1945 1945 azimuth = kwargs['azimuth']
1946 1946 dfactor = kwargs['dfactor']
1947 1947 k = kwargs['k']
1948 1948
1949 1949 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1950 1950 d = dist*dfactor
1951 1951 #Phase calculation
1952 1952 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1953 1953
1954 1954 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
1955 1955
1956 1956 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1957 1957 azimuth1 = azimuth1*numpy.pi/180
1958 1958
1959 1959 for i in range(heightList.size):
1960 1960 h = heightList[i]
1961 1961 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
1962 1962 metHeight = metArray1[indH,:]
1963 1963 if metHeight.shape[0] >= 2:
1964 1964 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
1965 1965 iazim = metHeight[:,1].astype(int)
1966 1966 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
1967 1967 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
1968 1968 A = numpy.asmatrix(A)
1969 1969 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
1970 1970 velHor = numpy.dot(A1,velAux)
1971 1971
1972 1972 velEst[i,:] = numpy.squeeze(velHor)
1973 1973 return velEst
1974 1974
1975 1975 def __getPhaseSlope(self, metArray, heightList, timeList):
1976 1976 meteorList = []
1977 1977 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
1978 1978 #Putting back together the meteor matrix
1979 1979 utctime = metArray[:,0]
1980 1980 uniqueTime = numpy.unique(utctime)
1981 1981
1982 1982 phaseDerThresh = 0.5
1983 1983 ippSeconds = timeList[1] - timeList[0]
1984 1984 sec = numpy.where(timeList>1)[0][0]
1985 1985 nPairs = metArray.shape[1] - 6
1986 1986 nHeights = len(heightList)
1987 1987
1988 1988 for t in uniqueTime:
1989 1989 metArray1 = metArray[utctime==t,:]
1990 1990 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
1991 1991 tmet = metArray1[:,1].astype(int)
1992 1992 hmet = metArray1[:,2].astype(int)
1993 1993
1994 1994 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
1995 1995 metPhase[:,:] = numpy.nan
1996 1996 metPhase[:,hmet,tmet] = metArray1[:,6:].T
1997 1997
1998 1998 #Delete short trails
1999 1999 metBool = ~numpy.isnan(metPhase[0,:,:])
2000 2000 heightVect = numpy.sum(metBool, axis = 1)
2001 2001 metBool[heightVect<sec,:] = False
2002 2002 metPhase[:,heightVect<sec,:] = numpy.nan
2003 2003
2004 2004 #Derivative
2005 2005 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2006 2006 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2007 2007 metPhase[phDerAux] = numpy.nan
2008 2008
2009 2009 #--------------------------METEOR DETECTION -----------------------------------------
2010 2010 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2011 2011
2012 2012 for p in numpy.arange(nPairs):
2013 2013 phase = metPhase[p,:,:]
2014 2014 phDer = metDer[p,:,:]
2015 2015
2016 2016 for h in indMet:
2017 2017 height = heightList[h]
2018 2018 phase1 = phase[h,:] #82
2019 2019 phDer1 = phDer[h,:]
2020 2020
2021 2021 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2022 2022
2023 2023 indValid = numpy.where(~numpy.isnan(phase1))[0]
2024 2024 initMet = indValid[0]
2025 2025 endMet = 0
2026 2026
2027 2027 for i in range(len(indValid)-1):
2028 2028
2029 2029 #Time difference
2030 2030 inow = indValid[i]
2031 2031 inext = indValid[i+1]
2032 2032 idiff = inext - inow
2033 2033 #Phase difference
2034 2034 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2035 2035
2036 2036 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2037 2037 sizeTrail = inow - initMet + 1
2038 2038 if sizeTrail>3*sec: #Too short meteors
2039 2039 x = numpy.arange(initMet,inow+1)*ippSeconds
2040 2040 y = phase1[initMet:inow+1]
2041 2041 ynnan = ~numpy.isnan(y)
2042 2042 x = x[ynnan]
2043 2043 y = y[ynnan]
2044 2044 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2045 2045 ylin = x*slope + intercept
2046 2046 rsq = r_value**2
2047 2047 if rsq > 0.5:
2048 2048 vel = slope#*height*1000/(k*d)
2049 2049 estAux = numpy.array([utctime,p,height, vel, rsq])
2050 2050 meteorList.append(estAux)
2051 2051 initMet = inext
2052 2052 metArray2 = numpy.array(meteorList)
2053 2053
2054 2054 return metArray2
2055 2055
2056 2056 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2057 2057
2058 2058 azimuth1 = numpy.zeros(len(pairslist))
2059 2059 dist = numpy.zeros(len(pairslist))
2060 2060
2061 2061 for i in range(len(rx_location)):
2062 2062 ch0 = pairslist[i][0]
2063 2063 ch1 = pairslist[i][1]
2064 2064
2065 2065 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2066 2066 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2067 2067 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2068 2068 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2069 2069
2070 2070 azimuth1 -= azimuth0
2071 2071 return azimuth1, dist
2072 2072
2073 2073 def techniqueNSM_DBS(self, **kwargs):
2074 2074 metArray = kwargs['metArray']
2075 2075 heightList = kwargs['heightList']
2076 2076 timeList = kwargs['timeList']
2077 2077 azimuth = kwargs['azimuth']
2078 2078 theta_x = numpy.array(kwargs['theta_x'])
2079 2079 theta_y = numpy.array(kwargs['theta_y'])
2080 2080
2081 2081 utctime = metArray[:,0]
2082 2082 cmet = metArray[:,1].astype(int)
2083 2083 hmet = metArray[:,3].astype(int)
2084 2084 SNRmet = metArray[:,4]
2085 2085 vmet = metArray[:,5]
2086 2086 spcmet = metArray[:,6]
2087 2087
2088 2088 nChan = numpy.max(cmet) + 1
2089 2089 nHeights = len(heightList)
2090 2090
2091 2091 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2092 2092 hmet = heightList[hmet]
2093 2093 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2094 2094
2095 2095 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2096 2096
2097 2097 for i in range(nHeights - 1):
2098 2098 hmin = heightList[i]
2099 2099 hmax = heightList[i + 1]
2100 2100
2101 2101 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2102 2102 indthisH = numpy.where(thisH)
2103 2103
2104 2104 if numpy.size(indthisH) > 3:
2105 2105
2106 2106 vel_aux = vmet[thisH]
2107 2107 chan_aux = cmet[thisH]
2108 2108 cosu_aux = dir_cosu[chan_aux]
2109 2109 cosv_aux = dir_cosv[chan_aux]
2110 2110 cosw_aux = dir_cosw[chan_aux]
2111 2111
2112 2112 nch = numpy.size(numpy.unique(chan_aux))
2113 2113 if nch > 1:
2114 2114 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2115 2115 velEst[i,:] = numpy.dot(A,vel_aux)
2116 2116
2117 2117 return velEst
2118 2118
2119 2119 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2120 2120
2121 2121 param = dataOut.data_param
2122 2122 if dataOut.abscissaList != None:
2123 2123 absc = dataOut.abscissaList[:-1]
2124 2124 # noise = dataOut.noise
2125 2125 heightList = dataOut.heightList
2126 2126 SNR = dataOut.data_SNR
2127 2127
2128 2128 if technique == 'DBS':
2129 2129
2130 2130 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2131 2131 kwargs['heightList'] = heightList
2132 2132 kwargs['SNR'] = SNR
2133 2133
2134 2134 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
2135 2135 dataOut.utctimeInit = dataOut.utctime
2136 2136 dataOut.outputInterval = dataOut.paramInterval
2137 2137
2138 2138 elif technique == 'SA':
2139 2139
2140 2140 #Parameters
2141 2141 # position_x = kwargs['positionX']
2142 2142 # position_y = kwargs['positionY']
2143 2143 # azimuth = kwargs['azimuth']
2144 2144 #
2145 2145 # if kwargs.has_key('crosspairsList'):
2146 2146 # pairs = kwargs['crosspairsList']
2147 2147 # else:
2148 2148 # pairs = None
2149 2149 #
2150 2150 # if kwargs.has_key('correctFactor'):
2151 2151 # correctFactor = kwargs['correctFactor']
2152 2152 # else:
2153 2153 # correctFactor = 1
2154 2154
2155 2155 # tau = dataOut.data_param
2156 2156 # _lambda = dataOut.C/dataOut.frequency
2157 2157 # pairsList = dataOut.groupList
2158 2158 # nChannels = dataOut.nChannels
2159 2159
2160 2160 kwargs['groupList'] = dataOut.groupList
2161 2161 kwargs['tau'] = dataOut.data_param
2162 2162 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2163 2163 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2164 2164 dataOut.data_output = self.techniqueSA(kwargs)
2165 2165 dataOut.utctimeInit = dataOut.utctime
2166 2166 dataOut.outputInterval = dataOut.timeInterval
2167 2167
2168 2168 elif technique == 'Meteors':
2169 2169 dataOut.flagNoData = True
2170 2170 self.__dataReady = False
2171 2171
2172 2172 if 'nHours' in kwargs:
2173 2173 nHours = kwargs['nHours']
2174 2174 else:
2175 2175 nHours = 1
2176 2176
2177 2177 if 'meteorsPerBin' in kwargs:
2178 2178 meteorThresh = kwargs['meteorsPerBin']
2179 2179 else:
2180 2180 meteorThresh = 6
2181 2181
2182 2182 if 'hmin' in kwargs:
2183 2183 hmin = kwargs['hmin']
2184 2184 else: hmin = 70
2185 2185 if 'hmax' in kwargs:
2186 2186 hmax = kwargs['hmax']
2187 2187 else: hmax = 110
2188 2188
2189 2189 dataOut.outputInterval = nHours*3600
2190 2190
2191 2191 if self.__isConfig == False:
2192 2192 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2193 2193 #Get Initial LTC time
2194 2194 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2195 2195 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2196 2196
2197 2197 self.__isConfig = True
2198 2198
2199 2199 if self.__buffer is None:
2200 2200 self.__buffer = dataOut.data_param
2201 2201 self.__firstdata = copy.copy(dataOut)
2202 2202
2203 2203 else:
2204 2204 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2205 2205
2206 2206 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2207 2207
2208 2208 if self.__dataReady:
2209 2209 dataOut.utctimeInit = self.__initime
2210 2210
2211 2211 self.__initime += dataOut.outputInterval #to erase time offset
2212 2212
2213 2213 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2214 2214 dataOut.flagNoData = False
2215 2215 self.__buffer = None
2216 2216
2217 2217 elif technique == 'Meteors1':
2218 2218 dataOut.flagNoData = True
2219 2219 self.__dataReady = False
2220 2220
2221 2221 if 'nMins' in kwargs:
2222 2222 nMins = kwargs['nMins']
2223 2223 else: nMins = 20
2224 2224 if 'rx_location' in kwargs:
2225 2225 rx_location = kwargs['rx_location']
2226 2226 else: rx_location = [(0,1),(1,1),(1,0)]
2227 2227 if 'azimuth' in kwargs:
2228 2228 azimuth = kwargs['azimuth']
2229 2229 else: azimuth = 51.06
2230 2230 if 'dfactor' in kwargs:
2231 2231 dfactor = kwargs['dfactor']
2232 2232 if 'mode' in kwargs:
2233 2233 mode = kwargs['mode']
2234 2234 if 'theta_x' in kwargs:
2235 2235 theta_x = kwargs['theta_x']
2236 2236 if 'theta_y' in kwargs:
2237 2237 theta_y = kwargs['theta_y']
2238 2238 else: mode = 'SA'
2239 2239
2240 2240 #Borrar luego esto
2241 2241 if dataOut.groupList is None:
2242 2242 dataOut.groupList = [(0,1),(0,2),(1,2)]
2243 2243 groupList = dataOut.groupList
2244 2244 C = 3e8
2245 2245 freq = 50e6
2246 2246 lamb = C/freq
2247 2247 k = 2*numpy.pi/lamb
2248 2248
2249 2249 timeList = dataOut.abscissaList
2250 2250 heightList = dataOut.heightList
2251 2251
2252 2252 if self.__isConfig == False:
2253 2253 dataOut.outputInterval = nMins*60
2254 2254 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2255 2255 #Get Initial LTC time
2256 2256 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2257 2257 minuteAux = initime.minute
2258 2258 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2259 2259 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2260 2260
2261 2261 self.__isConfig = True
2262 2262
2263 2263 if self.__buffer is None:
2264 2264 self.__buffer = dataOut.data_param
2265 2265 self.__firstdata = copy.copy(dataOut)
2266 2266
2267 2267 else:
2268 2268 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2269 2269
2270 2270 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2271 2271
2272 2272 if self.__dataReady:
2273 2273 dataOut.utctimeInit = self.__initime
2274 2274 self.__initime += dataOut.outputInterval #to erase time offset
2275 2275
2276 2276 metArray = self.__buffer
2277 2277 if mode == 'SA':
2278 2278 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2279 2279 elif mode == 'DBS':
2280 2280 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2281 2281 dataOut.data_output = dataOut.data_output.T
2282 2282 dataOut.flagNoData = False
2283 2283 self.__buffer = None
2284 2284
2285 2285 return
2286 2286
2287 2287 class EWDriftsEstimation(Operation):
2288 2288
2289 2289 def __init__(self):
2290 2290 Operation.__init__(self)
2291 2291
2292 2292 def __correctValues(self, heiRang, phi, velRadial, SNR):
2293 2293 listPhi = phi.tolist()
2294 2294 maxid = listPhi.index(max(listPhi))
2295 2295 minid = listPhi.index(min(listPhi))
2296 2296
2297 2297 rango = list(range(len(phi)))
2298 2298 # rango = numpy.delete(rango,maxid)
2299 2299
2300 2300 heiRang1 = heiRang*math.cos(phi[maxid])
2301 2301 heiRangAux = heiRang*math.cos(phi[minid])
2302 2302 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2303 2303 heiRang1 = numpy.delete(heiRang1,indOut)
2304 2304
2305 2305 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2306 2306 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2307 2307
2308 2308 for i in rango:
2309 2309 x = heiRang*math.cos(phi[i])
2310 2310 y1 = velRadial[i,:]
2311 2311 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2312 2312
2313 2313 x1 = heiRang1
2314 2314 y11 = f1(x1)
2315 2315
2316 2316 y2 = SNR[i,:]
2317 2317 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2318 2318 y21 = f2(x1)
2319 2319
2320 2320 velRadial1[i,:] = y11
2321 2321 SNR1[i,:] = y21
2322 2322
2323 2323 return heiRang1, velRadial1, SNR1
2324 2324
2325 2325 def run(self, dataOut, zenith, zenithCorrection):
2326 2326 heiRang = dataOut.heightList
2327 2327 velRadial = dataOut.data_param[:,3,:]
2328 2328 SNR = dataOut.data_SNR
2329 2329
2330 2330 zenith = numpy.array(zenith)
2331 2331 zenith -= zenithCorrection
2332 2332 zenith *= numpy.pi/180
2333 2333
2334 2334 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2335 2335
2336 2336 alp = zenith[0]
2337 2337 bet = zenith[1]
2338 2338
2339 2339 w_w = velRadial1[0,:]
2340 2340 w_e = velRadial1[1,:]
2341 2341
2342 2342 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2343 2343 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2344 2344
2345 2345 winds = numpy.vstack((u,w))
2346 2346
2347 2347 dataOut.heightList = heiRang1
2348 2348 dataOut.data_output = winds
2349 2349 dataOut.data_SNR = SNR1
2350 2350
2351 2351 dataOut.utctimeInit = dataOut.utctime
2352 2352 dataOut.outputInterval = dataOut.timeInterval
2353 2353 return
2354 2354
2355 2355 #--------------- Non Specular Meteor ----------------
2356 2356
2357 2357 class NonSpecularMeteorDetection(Operation):
2358 2358
2359 2359 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2360 2360 data_acf = dataOut.data_pre[0]
2361 2361 data_ccf = dataOut.data_pre[1]
2362 2362 pairsList = dataOut.groupList[1]
2363 2363
2364 2364 lamb = dataOut.C/dataOut.frequency
2365 2365 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2366 2366 paramInterval = dataOut.paramInterval
2367 2367
2368 2368 nChannels = data_acf.shape[0]
2369 2369 nLags = data_acf.shape[1]
2370 2370 nProfiles = data_acf.shape[2]
2371 2371 nHeights = dataOut.nHeights
2372 2372 nCohInt = dataOut.nCohInt
2373 2373 sec = numpy.round(nProfiles/dataOut.paramInterval)
2374 2374 heightList = dataOut.heightList
2375 2375 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2376 2376 utctime = dataOut.utctime
2377 2377
2378 2378 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2379 2379
2380 2380 #------------------------ SNR --------------------------------------
2381 2381 power = data_acf[:,0,:,:].real
2382 2382 noise = numpy.zeros(nChannels)
2383 2383 SNR = numpy.zeros(power.shape)
2384 2384 for i in range(nChannels):
2385 2385 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2386 2386 SNR[i] = (power[i]-noise[i])/noise[i]
2387 2387 SNRm = numpy.nanmean(SNR, axis = 0)
2388 2388 SNRdB = 10*numpy.log10(SNR)
2389 2389
2390 2390 if mode == 'SA':
2391 2391 dataOut.groupList = dataOut.groupList[1]
2392 2392 nPairs = data_ccf.shape[0]
2393 2393 #---------------------- Coherence and Phase --------------------------
2394 2394 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2395 2395 # phase1 = numpy.copy(phase)
2396 2396 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2397 2397
2398 2398 for p in range(nPairs):
2399 2399 ch0 = pairsList[p][0]
2400 2400 ch1 = pairsList[p][1]
2401 2401 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2402 2402 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2403 2403 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2404 2404 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2405 2405 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2406 2406 coh = numpy.nanmax(coh1, axis = 0)
2407 2407 # struc = numpy.ones((5,1))
2408 2408 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2409 2409 #---------------------- Radial Velocity ----------------------------
2410 2410 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2411 2411 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2412 2412
2413 2413 if allData:
2414 2414 boolMetFin = ~numpy.isnan(SNRm)
2415 2415 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2416 2416 else:
2417 2417 #------------------------ Meteor mask ---------------------------------
2418 2418 # #SNR mask
2419 2419 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2420 2420 #
2421 2421 # #Erase small objects
2422 2422 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2423 2423 #
2424 2424 # auxEEJ = numpy.sum(boolMet1,axis=0)
2425 2425 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2426 2426 # indEEJ = numpy.where(indOver)[0]
2427 2427 # indNEEJ = numpy.where(~indOver)[0]
2428 2428 #
2429 2429 # boolMetFin = boolMet1
2430 2430 #
2431 2431 # if indEEJ.size > 0:
2432 2432 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2433 2433 #
2434 2434 # boolMet2 = coh > cohThresh
2435 2435 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2436 2436 #
2437 2437 # #Final Meteor mask
2438 2438 # boolMetFin = boolMet1|boolMet2
2439 2439
2440 2440 #Coherence mask
2441 2441 boolMet1 = coh > 0.75
2442 2442 struc = numpy.ones((30,1))
2443 2443 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2444 2444
2445 2445 #Derivative mask
2446 2446 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2447 2447 boolMet2 = derPhase < 0.2
2448 2448 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2449 2449 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2450 2450 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2451 2451 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2452 2452 # #Final mask
2453 2453 # boolMetFin = boolMet2
2454 2454 boolMetFin = boolMet1&boolMet2
2455 2455 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2456 2456 #Creating data_param
2457 2457 coordMet = numpy.where(boolMetFin)
2458 2458
2459 2459 tmet = coordMet[0]
2460 2460 hmet = coordMet[1]
2461 2461
2462 2462 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2463 2463 data_param[:,0] = utctime
2464 2464 data_param[:,1] = tmet
2465 2465 data_param[:,2] = hmet
2466 2466 data_param[:,3] = SNRm[tmet,hmet]
2467 2467 data_param[:,4] = velRad[tmet,hmet]
2468 2468 data_param[:,5] = coh[tmet,hmet]
2469 2469 data_param[:,6:] = phase[:,tmet,hmet].T
2470 2470
2471 2471 elif mode == 'DBS':
2472 2472 dataOut.groupList = numpy.arange(nChannels)
2473 2473
2474 2474 #Radial Velocities
2475 2475 phase = numpy.angle(data_acf[:,1,:,:])
2476 2476 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2477 2477 velRad = phase*lamb/(4*numpy.pi*tSamp)
2478 2478
2479 2479 #Spectral width
2480 2480 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2481 2481 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2482 2482 acf1 = data_acf[:,1,:,:]
2483 2483 acf2 = data_acf[:,2,:,:]
2484 2484
2485 2485 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2486 2486 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2487 2487 if allData:
2488 2488 boolMetFin = ~numpy.isnan(SNRdB)
2489 2489 else:
2490 2490 #SNR
2491 2491 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2492 2492 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2493 2493
2494 2494 #Radial velocity
2495 2495 boolMet2 = numpy.abs(velRad) < 20
2496 2496 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2497 2497
2498 2498 #Spectral Width
2499 2499 boolMet3 = spcWidth < 30
2500 2500 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2501 2501 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2502 2502 boolMetFin = boolMet1&boolMet2&boolMet3
2503 2503
2504 2504 #Creating data_param
2505 2505 coordMet = numpy.where(boolMetFin)
2506 2506
2507 2507 cmet = coordMet[0]
2508 2508 tmet = coordMet[1]
2509 2509 hmet = coordMet[2]
2510 2510
2511 2511 data_param = numpy.zeros((tmet.size, 7))
2512 2512 data_param[:,0] = utctime
2513 2513 data_param[:,1] = cmet
2514 2514 data_param[:,2] = tmet
2515 2515 data_param[:,3] = hmet
2516 2516 data_param[:,4] = SNR[cmet,tmet,hmet].T
2517 2517 data_param[:,5] = velRad[cmet,tmet,hmet].T
2518 2518 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2519 2519
2520 2520 # self.dataOut.data_param = data_int
2521 2521 if len(data_param) == 0:
2522 2522 dataOut.flagNoData = True
2523 2523 else:
2524 2524 dataOut.data_param = data_param
2525 2525
2526 2526 def __erase_small(self, binArray, threshX, threshY):
2527 2527 labarray, numfeat = ndimage.measurements.label(binArray)
2528 2528 binArray1 = numpy.copy(binArray)
2529 2529
2530 2530 for i in range(1,numfeat + 1):
2531 2531 auxBin = (labarray==i)
2532 2532 auxSize = auxBin.sum()
2533 2533
2534 2534 x,y = numpy.where(auxBin)
2535 2535 widthX = x.max() - x.min()
2536 2536 widthY = y.max() - y.min()
2537 2537
2538 2538 #width X: 3 seg -> 12.5*3
2539 2539 #width Y:
2540 2540
2541 2541 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2542 2542 binArray1[auxBin] = False
2543 2543
2544 2544 return binArray1
2545 2545
2546 2546 #--------------- Specular Meteor ----------------
2547 2547
2548 2548 class SMDetection(Operation):
2549 2549 '''
2550 2550 Function DetectMeteors()
2551 2551 Project developed with paper:
2552 2552 HOLDSWORTH ET AL. 2004
2553 2553
2554 2554 Input:
2555 2555 self.dataOut.data_pre
2556 2556
2557 2557 centerReceiverIndex: From the channels, which is the center receiver
2558 2558
2559 2559 hei_ref: Height reference for the Beacon signal extraction
2560 2560 tauindex:
2561 2561 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2562 2562
2563 2563 cohDetection: Whether to user Coherent detection or not
2564 2564 cohDet_timeStep: Coherent Detection calculation time step
2565 2565 cohDet_thresh: Coherent Detection phase threshold to correct phases
2566 2566
2567 2567 noise_timeStep: Noise calculation time step
2568 2568 noise_multiple: Noise multiple to define signal threshold
2569 2569
2570 2570 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2571 2571 multDet_rangeLimit: Multiple Detection Removal range limit in km
2572 2572
2573 2573 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2574 2574 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2575 2575
2576 2576 hmin: Minimum Height of the meteor to use it in the further wind estimations
2577 2577 hmax: Maximum Height of the meteor to use it in the further wind estimations
2578 2578 azimuth: Azimuth angle correction
2579 2579
2580 2580 Affected:
2581 2581 self.dataOut.data_param
2582 2582
2583 2583 Rejection Criteria (Errors):
2584 2584 0: No error; analysis OK
2585 2585 1: SNR < SNR threshold
2586 2586 2: angle of arrival (AOA) ambiguously determined
2587 2587 3: AOA estimate not feasible
2588 2588 4: Large difference in AOAs obtained from different antenna baselines
2589 2589 5: echo at start or end of time series
2590 2590 6: echo less than 5 examples long; too short for analysis
2591 2591 7: echo rise exceeds 0.3s
2592 2592 8: echo decay time less than twice rise time
2593 2593 9: large power level before echo
2594 2594 10: large power level after echo
2595 2595 11: poor fit to amplitude for estimation of decay time
2596 2596 12: poor fit to CCF phase variation for estimation of radial drift velocity
2597 2597 13: height unresolvable echo: not valid height within 70 to 110 km
2598 2598 14: height ambiguous echo: more then one possible height within 70 to 110 km
2599 2599 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2600 2600 16: oscilatory echo, indicating event most likely not an underdense echo
2601 2601
2602 2602 17: phase difference in meteor Reestimation
2603 2603
2604 2604 Data Storage:
2605 2605 Meteors for Wind Estimation (8):
2606 2606 Utc Time | Range Height
2607 2607 Azimuth Zenith errorCosDir
2608 2608 VelRad errorVelRad
2609 2609 Phase0 Phase1 Phase2 Phase3
2610 2610 TypeError
2611 2611
2612 2612 '''
2613 2613
2614 2614 def run(self, dataOut, hei_ref = None, tauindex = 0,
2615 2615 phaseOffsets = None,
2616 2616 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2617 2617 noise_timeStep = 4, noise_multiple = 4,
2618 2618 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2619 2619 phaseThresh = 20, SNRThresh = 5,
2620 2620 hmin = 50, hmax=150, azimuth = 0,
2621 2621 channelPositions = None) :
2622 2622
2623 2623
2624 2624 #Getting Pairslist
2625 2625 if channelPositions is None:
2626 2626 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2627 2627 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2628 2628 meteorOps = SMOperations()
2629 2629 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2630 2630 heiRang = dataOut.getHeiRange()
2631 2631 #Get Beacon signal - No Beacon signal anymore
2632 2632 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2633 2633 #
2634 2634 # if hei_ref != None:
2635 2635 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2636 2636 #
2637 2637
2638 2638
2639 2639 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2640 2640 # see if the user put in pre defined phase shifts
2641 2641 voltsPShift = dataOut.data_pre.copy()
2642 2642
2643 2643 # if predefinedPhaseShifts != None:
2644 2644 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2645 2645 #
2646 2646 # # elif beaconPhaseShifts:
2647 2647 # # #get hardware phase shifts using beacon signal
2648 2648 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2649 2649 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2650 2650 #
2651 2651 # else:
2652 2652 # hardwarePhaseShifts = numpy.zeros(5)
2653 2653 #
2654 2654 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2655 2655 # for i in range(self.dataOut.data_pre.shape[0]):
2656 2656 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2657 2657
2658 2658 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2659 2659
2660 2660 #Remove DC
2661 2661 voltsDC = numpy.mean(voltsPShift,1)
2662 2662 voltsDC = numpy.mean(voltsDC,1)
2663 2663 for i in range(voltsDC.shape[0]):
2664 2664 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2665 2665
2666 2666 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2667 2667 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2668 2668
2669 2669 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2670 2670 #Coherent Detection
2671 2671 if cohDetection:
2672 2672 #use coherent detection to get the net power
2673 2673 cohDet_thresh = cohDet_thresh*numpy.pi/180
2674 2674 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2675 2675
2676 2676 #Non-coherent detection!
2677 2677 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2678 2678 #********** END OF COH/NON-COH POWER CALCULATION**********************
2679 2679
2680 2680 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2681 2681 #Get noise
2682 2682 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2683 2683 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2684 2684 #Get signal threshold
2685 2685 signalThresh = noise_multiple*noise
2686 2686 #Meteor echoes detection
2687 2687 listMeteors = self.__findMeteors(powerNet, signalThresh)
2688 2688 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2689 2689
2690 2690 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2691 2691 #Parameters
2692 2692 heiRange = dataOut.getHeiRange()
2693 2693 rangeInterval = heiRange[1] - heiRange[0]
2694 2694 rangeLimit = multDet_rangeLimit/rangeInterval
2695 2695 timeLimit = multDet_timeLimit/dataOut.timeInterval
2696 2696 #Multiple detection removals
2697 2697 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2698 2698 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2699 2699
2700 2700 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2701 2701 #Parameters
2702 2702 phaseThresh = phaseThresh*numpy.pi/180
2703 2703 thresh = [phaseThresh, noise_multiple, SNRThresh]
2704 2704 #Meteor reestimation (Errors N 1, 6, 12, 17)
2705 2705 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2706 2706 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2707 2707 #Estimation of decay times (Errors N 7, 8, 11)
2708 2708 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2709 2709 #******************* END OF METEOR REESTIMATION *******************
2710 2710
2711 2711 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2712 2712 #Calculating Radial Velocity (Error N 15)
2713 2713 radialStdThresh = 10
2714 2714 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2715 2715
2716 2716 if len(listMeteors4) > 0:
2717 2717 #Setting New Array
2718 2718 date = dataOut.utctime
2719 2719 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2720 2720
2721 2721 #Correcting phase offset
2722 2722 if phaseOffsets != None:
2723 2723 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2724 2724 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2725 2725
2726 2726 #Second Pairslist
2727 2727 pairsList = []
2728 2728 pairx = (0,1)
2729 2729 pairy = (2,3)
2730 2730 pairsList.append(pairx)
2731 2731 pairsList.append(pairy)
2732 2732
2733 2733 jph = numpy.array([0,0,0,0])
2734 2734 h = (hmin,hmax)
2735 2735 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2736 2736
2737 2737 # #Calculate AOA (Error N 3, 4)
2738 2738 # #JONES ET AL. 1998
2739 2739 # error = arrayParameters[:,-1]
2740 2740 # AOAthresh = numpy.pi/8
2741 2741 # phases = -arrayParameters[:,9:13]
2742 2742 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2743 2743 #
2744 2744 # #Calculate Heights (Error N 13 and 14)
2745 2745 # error = arrayParameters[:,-1]
2746 2746 # Ranges = arrayParameters[:,2]
2747 2747 # zenith = arrayParameters[:,5]
2748 2748 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2749 2749 # error = arrayParameters[:,-1]
2750 2750 #********************* END OF PARAMETERS CALCULATION **************************
2751 2751
2752 2752 #***************************+ PASS DATA TO NEXT STEP **********************
2753 2753 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2754 2754 dataOut.data_param = arrayParameters
2755 2755
2756 2756 if arrayParameters is None:
2757 2757 dataOut.flagNoData = True
2758 2758 else:
2759 2759 dataOut.flagNoData = True
2760 2760
2761 2761 return
2762 2762
2763 2763 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2764 2764
2765 2765 minIndex = min(newheis[0])
2766 2766 maxIndex = max(newheis[0])
2767 2767
2768 2768 voltage = voltage0[:,:,minIndex:maxIndex+1]
2769 2769 nLength = voltage.shape[1]/n
2770 2770 nMin = 0
2771 2771 nMax = 0
2772 2772 phaseOffset = numpy.zeros((len(pairslist),n))
2773 2773
2774 2774 for i in range(n):
2775 2775 nMax += nLength
2776 2776 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2777 2777 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2778 2778 phaseOffset[:,i] = phaseCCF.transpose()
2779 2779 nMin = nMax
2780 2780 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2781 2781
2782 2782 #Remove Outliers
2783 2783 factor = 2
2784 2784 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2785 2785 dw = numpy.std(wt,axis = 1)
2786 2786 dw = dw.reshape((dw.size,1))
2787 2787 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2788 2788 phaseOffset[ind] = numpy.nan
2789 2789 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2790 2790
2791 2791 return phaseOffset
2792 2792
2793 2793 def __shiftPhase(self, data, phaseShift):
2794 2794 #this will shift the phase of a complex number
2795 2795 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2796 2796 return dataShifted
2797 2797
2798 2798 def __estimatePhaseDifference(self, array, pairslist):
2799 2799 nChannel = array.shape[0]
2800 2800 nHeights = array.shape[2]
2801 2801 numPairs = len(pairslist)
2802 2802 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2803 2803 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2804 2804
2805 2805 #Correct phases
2806 2806 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2807 2807 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2808 2808
2809 2809 if indDer[0].shape[0] > 0:
2810 2810 for i in range(indDer[0].shape[0]):
2811 2811 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2812 2812 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2813 2813
2814 2814 # for j in range(numSides):
2815 2815 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2816 2816 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2817 2817 #
2818 2818 #Linear
2819 2819 phaseInt = numpy.zeros((numPairs,1))
2820 2820 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2821 2821 for j in range(numPairs):
2822 2822 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2823 2823 phaseInt[j] = fit[1]
2824 2824 #Phase Differences
2825 2825 phaseDiff = phaseInt - phaseCCF[:,2,:]
2826 2826 phaseArrival = phaseInt.reshape(phaseInt.size)
2827 2827
2828 2828 #Dealias
2829 2829 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2830 2830 # indAlias = numpy.where(phaseArrival > numpy.pi)
2831 2831 # phaseArrival[indAlias] -= 2*numpy.pi
2832 2832 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2833 2833 # phaseArrival[indAlias] += 2*numpy.pi
2834 2834
2835 2835 return phaseDiff, phaseArrival
2836 2836
2837 2837 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2838 2838 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2839 2839 #find the phase shifts of each channel over 1 second intervals
2840 2840 #only look at ranges below the beacon signal
2841 2841 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2842 2842 numBlocks = int(volts.shape[1]/numProfPerBlock)
2843 2843 numHeights = volts.shape[2]
2844 2844 nChannel = volts.shape[0]
2845 2845 voltsCohDet = volts.copy()
2846 2846
2847 2847 pairsarray = numpy.array(pairslist)
2848 2848 indSides = pairsarray[:,1]
2849 2849 # indSides = numpy.array(range(nChannel))
2850 2850 # indSides = numpy.delete(indSides, indCenter)
2851 2851 #
2852 2852 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2853 2853 listBlocks = numpy.array_split(volts, numBlocks, 1)
2854 2854
2855 2855 startInd = 0
2856 2856 endInd = 0
2857 2857
2858 2858 for i in range(numBlocks):
2859 2859 startInd = endInd
2860 2860 endInd = endInd + listBlocks[i].shape[1]
2861 2861
2862 2862 arrayBlock = listBlocks[i]
2863 2863 # arrayBlockCenter = listCenter[i]
2864 2864
2865 2865 #Estimate the Phase Difference
2866 2866 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2867 2867 #Phase Difference RMS
2868 2868 arrayPhaseRMS = numpy.abs(phaseDiff)
2869 2869 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2870 2870 indPhase = numpy.where(phaseRMSaux==4)
2871 2871 #Shifting
2872 2872 if indPhase[0].shape[0] > 0:
2873 2873 for j in range(indSides.size):
2874 2874 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2875 2875 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2876 2876
2877 2877 return voltsCohDet
2878 2878
2879 2879 def __calculateCCF(self, volts, pairslist ,laglist):
2880 2880
2881 2881 nHeights = volts.shape[2]
2882 2882 nPoints = volts.shape[1]
2883 2883 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2884 2884
2885 2885 for i in range(len(pairslist)):
2886 2886 volts1 = volts[pairslist[i][0]]
2887 2887 volts2 = volts[pairslist[i][1]]
2888 2888
2889 2889 for t in range(len(laglist)):
2890 2890 idxT = laglist[t]
2891 2891 if idxT >= 0:
2892 2892 vStacked = numpy.vstack((volts2[idxT:,:],
2893 2893 numpy.zeros((idxT, nHeights),dtype='complex')))
2894 2894 else:
2895 2895 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2896 2896 volts2[:(nPoints + idxT),:]))
2897 2897 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2898 2898
2899 2899 vStacked = None
2900 2900 return voltsCCF
2901 2901
2902 2902 def __getNoise(self, power, timeSegment, timeInterval):
2903 2903 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2904 2904 numBlocks = int(power.shape[0]/numProfPerBlock)
2905 2905 numHeights = power.shape[1]
2906 2906
2907 2907 listPower = numpy.array_split(power, numBlocks, 0)
2908 2908 noise = numpy.zeros((power.shape[0], power.shape[1]))
2909 2909 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2910 2910
2911 2911 startInd = 0
2912 2912 endInd = 0
2913 2913
2914 2914 for i in range(numBlocks): #split por canal
2915 2915 startInd = endInd
2916 2916 endInd = endInd + listPower[i].shape[0]
2917 2917
2918 2918 arrayBlock = listPower[i]
2919 2919 noiseAux = numpy.mean(arrayBlock, 0)
2920 2920 # noiseAux = numpy.median(noiseAux)
2921 2921 # noiseAux = numpy.mean(arrayBlock)
2922 2922 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2923 2923
2924 2924 noiseAux1 = numpy.mean(arrayBlock)
2925 2925 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2926 2926
2927 2927 return noise, noise1
2928 2928
2929 2929 def __findMeteors(self, power, thresh):
2930 2930 nProf = power.shape[0]
2931 2931 nHeights = power.shape[1]
2932 2932 listMeteors = []
2933 2933
2934 2934 for i in range(nHeights):
2935 2935 powerAux = power[:,i]
2936 2936 threshAux = thresh[:,i]
2937 2937
2938 2938 indUPthresh = numpy.where(powerAux > threshAux)[0]
2939 2939 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2940 2940
2941 2941 j = 0
2942 2942
2943 2943 while (j < indUPthresh.size - 2):
2944 2944 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2945 2945 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2946 2946 indDNthresh = indDNthresh[indDNAux]
2947 2947
2948 2948 if (indDNthresh.size > 0):
2949 2949 indEnd = indDNthresh[0] - 1
2950 2950 indInit = indUPthresh[j]
2951 2951
2952 2952 meteor = powerAux[indInit:indEnd + 1]
2953 2953 indPeak = meteor.argmax() + indInit
2954 2954 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
2955 2955
2956 2956 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
2957 2957 j = numpy.where(indUPthresh == indEnd)[0] + 1
2958 2958 else: j+=1
2959 2959 else: j+=1
2960 2960
2961 2961 return listMeteors
2962 2962
2963 2963 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
2964 2964
2965 2965 arrayMeteors = numpy.asarray(listMeteors)
2966 2966 listMeteors1 = []
2967 2967
2968 2968 while arrayMeteors.shape[0] > 0:
2969 2969 FLAs = arrayMeteors[:,4]
2970 2970 maxFLA = FLAs.argmax()
2971 2971 listMeteors1.append(arrayMeteors[maxFLA,:])
2972 2972
2973 2973 MeteorInitTime = arrayMeteors[maxFLA,1]
2974 2974 MeteorEndTime = arrayMeteors[maxFLA,3]
2975 2975 MeteorHeight = arrayMeteors[maxFLA,0]
2976 2976
2977 2977 #Check neighborhood
2978 2978 maxHeightIndex = MeteorHeight + rangeLimit
2979 2979 minHeightIndex = MeteorHeight - rangeLimit
2980 2980 minTimeIndex = MeteorInitTime - timeLimit
2981 2981 maxTimeIndex = MeteorEndTime + timeLimit
2982 2982
2983 2983 #Check Heights
2984 2984 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
2985 2985 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
2986 2986 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
2987 2987
2988 2988 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
2989 2989
2990 2990 return listMeteors1
2991 2991
2992 2992 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
2993 2993 numHeights = volts.shape[2]
2994 2994 nChannel = volts.shape[0]
2995 2995
2996 2996 thresholdPhase = thresh[0]
2997 2997 thresholdNoise = thresh[1]
2998 2998 thresholdDB = float(thresh[2])
2999 2999
3000 3000 thresholdDB1 = 10**(thresholdDB/10)
3001 3001 pairsarray = numpy.array(pairslist)
3002 3002 indSides = pairsarray[:,1]
3003 3003
3004 3004 pairslist1 = list(pairslist)
3005 3005 pairslist1.append((0,1))
3006 3006 pairslist1.append((3,4))
3007 3007
3008 3008 listMeteors1 = []
3009 3009 listPowerSeries = []
3010 3010 listVoltageSeries = []
3011 3011 #volts has the war data
3012 3012
3013 3013 if frequency == 30e6:
3014 3014 timeLag = 45*10**-3
3015 3015 else:
3016 3016 timeLag = 15*10**-3
3017 3017 lag = numpy.ceil(timeLag/timeInterval)
3018 3018
3019 3019 for i in range(len(listMeteors)):
3020 3020
3021 3021 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3022 3022 meteorAux = numpy.zeros(16)
3023 3023
3024 3024 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3025 3025 mHeight = listMeteors[i][0]
3026 3026 mStart = listMeteors[i][1]
3027 3027 mPeak = listMeteors[i][2]
3028 3028 mEnd = listMeteors[i][3]
3029 3029
3030 3030 #get the volt data between the start and end times of the meteor
3031 3031 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3032 3032 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3033 3033
3034 3034 #3.6. Phase Difference estimation
3035 3035 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3036 3036
3037 3037 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3038 3038 #meteorVolts0.- all Channels, all Profiles
3039 3039 meteorVolts0 = volts[:,:,mHeight]
3040 3040 meteorThresh = noise[:,mHeight]*thresholdNoise
3041 3041 meteorNoise = noise[:,mHeight]
3042 3042 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3043 3043 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3044 3044
3045 3045 #Times reestimation
3046 3046 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3047 3047 if mStart1.size > 0:
3048 3048 mStart1 = mStart1[-1] + 1
3049 3049
3050 3050 else:
3051 3051 mStart1 = mPeak
3052 3052
3053 3053 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3054 3054 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3055 3055 if mEndDecayTime1.size == 0:
3056 3056 mEndDecayTime1 = powerNet0.size
3057 3057 else:
3058 3058 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3059 3059 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3060 3060
3061 3061 #meteorVolts1.- all Channels, from start to end
3062 3062 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3063 3063 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3064 3064 if meteorVolts2.shape[1] == 0:
3065 3065 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3066 3066 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3067 3067 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3068 3068 ##################### END PARAMETERS REESTIMATION #########################
3069 3069
3070 3070 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3071 3071 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3072 3072 if meteorVolts2.shape[1] > 0:
3073 3073 #Phase Difference re-estimation
3074 3074 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3075 3075 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3076 3076 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3077 3077 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3078 3078 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3079 3079
3080 3080 #Phase Difference RMS
3081 3081 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3082 3082 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3083 3083 #Data from Meteor
3084 3084 mPeak1 = powerNet1.argmax() + mStart1
3085 3085 mPeakPower1 = powerNet1.max()
3086 3086 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3087 3087 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3088 3088 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3089 3089 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3090 3090 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3091 3091 #Vectorize
3092 3092 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3093 3093 meteorAux[7:11] = phaseDiffint[0:4]
3094 3094
3095 3095 #Rejection Criterions
3096 3096 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3097 3097 meteorAux[-1] = 17
3098 3098 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3099 3099 meteorAux[-1] = 1
3100 3100
3101 3101
3102 3102 else:
3103 3103 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3104 3104 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3105 3105 PowerSeries = 0
3106 3106
3107 3107 listMeteors1.append(meteorAux)
3108 3108 listPowerSeries.append(PowerSeries)
3109 3109 listVoltageSeries.append(meteorVolts1)
3110 3110
3111 3111 return listMeteors1, listPowerSeries, listVoltageSeries
3112 3112
3113 3113 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3114 3114
3115 3115 threshError = 10
3116 3116 #Depending if it is 30 or 50 MHz
3117 3117 if frequency == 30e6:
3118 3118 timeLag = 45*10**-3
3119 3119 else:
3120 3120 timeLag = 15*10**-3
3121 3121 lag = numpy.ceil(timeLag/timeInterval)
3122 3122
3123 3123 listMeteors1 = []
3124 3124
3125 3125 for i in range(len(listMeteors)):
3126 3126 meteorPower = listPower[i]
3127 3127 meteorAux = listMeteors[i]
3128 3128
3129 3129 if meteorAux[-1] == 0:
3130 3130
3131 3131 try:
3132 3132 indmax = meteorPower.argmax()
3133 3133 indlag = indmax + lag
3134 3134
3135 3135 y = meteorPower[indlag:]
3136 3136 x = numpy.arange(0, y.size)*timeLag
3137 3137
3138 3138 #first guess
3139 3139 a = y[0]
3140 3140 tau = timeLag
3141 3141 #exponential fit
3142 3142 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3143 3143 y1 = self.__exponential_function(x, *popt)
3144 3144 #error estimation
3145 3145 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3146 3146
3147 3147 decayTime = popt[1]
3148 3148 riseTime = indmax*timeInterval
3149 3149 meteorAux[11:13] = [decayTime, error]
3150 3150
3151 3151 #Table items 7, 8 and 11
3152 3152 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3153 3153 meteorAux[-1] = 7
3154 3154 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3155 3155 meteorAux[-1] = 8
3156 3156 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3157 3157 meteorAux[-1] = 11
3158 3158
3159 3159
3160 3160 except:
3161 3161 meteorAux[-1] = 11
3162 3162
3163 3163
3164 3164 listMeteors1.append(meteorAux)
3165 3165
3166 3166 return listMeteors1
3167 3167
3168 3168 #Exponential Function
3169 3169
3170 3170 def __exponential_function(self, x, a, tau):
3171 3171 y = a*numpy.exp(-x/tau)
3172 3172 return y
3173 3173
3174 3174 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3175 3175
3176 3176 pairslist1 = list(pairslist)
3177 3177 pairslist1.append((0,1))
3178 3178 pairslist1.append((3,4))
3179 3179 numPairs = len(pairslist1)
3180 3180 #Time Lag
3181 3181 timeLag = 45*10**-3
3182 3182 c = 3e8
3183 3183 lag = numpy.ceil(timeLag/timeInterval)
3184 3184 freq = 30e6
3185 3185
3186 3186 listMeteors1 = []
3187 3187
3188 3188 for i in range(len(listMeteors)):
3189 3189 meteorAux = listMeteors[i]
3190 3190 if meteorAux[-1] == 0:
3191 3191 mStart = listMeteors[i][1]
3192 3192 mPeak = listMeteors[i][2]
3193 3193 mLag = mPeak - mStart + lag
3194 3194
3195 3195 #get the volt data between the start and end times of the meteor
3196 3196 meteorVolts = listVolts[i]
3197 3197 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3198 3198
3199 3199 #Get CCF
3200 3200 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3201 3201
3202 3202 #Method 2
3203 3203 slopes = numpy.zeros(numPairs)
3204 3204 time = numpy.array([-2,-1,1,2])*timeInterval
3205 3205 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3206 3206
3207 3207 #Correct phases
3208 3208 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3209 3209 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3210 3210
3211 3211 if indDer[0].shape[0] > 0:
3212 3212 for i in range(indDer[0].shape[0]):
3213 3213 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3214 3214 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3215 3215
3216 3216 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3217 3217 for j in range(numPairs):
3218 3218 fit = stats.linregress(time, angAllCCF[j,:])
3219 3219 slopes[j] = fit[0]
3220 3220
3221 3221 #Remove Outlier
3222 3222 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3223 3223 # slopes = numpy.delete(slopes,indOut)
3224 3224 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3225 3225 # slopes = numpy.delete(slopes,indOut)
3226 3226
3227 3227 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3228 3228 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3229 3229 meteorAux[-2] = radialError
3230 3230 meteorAux[-3] = radialVelocity
3231 3231
3232 3232 #Setting Error
3233 3233 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3234 3234 if numpy.abs(radialVelocity) > 200:
3235 3235 meteorAux[-1] = 15
3236 3236 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3237 3237 elif radialError > radialStdThresh:
3238 3238 meteorAux[-1] = 12
3239 3239
3240 3240 listMeteors1.append(meteorAux)
3241 3241 return listMeteors1
3242 3242
3243 3243 def __setNewArrays(self, listMeteors, date, heiRang):
3244 3244
3245 3245 #New arrays
3246 3246 arrayMeteors = numpy.array(listMeteors)
3247 3247 arrayParameters = numpy.zeros((len(listMeteors), 13))
3248 3248
3249 3249 #Date inclusion
3250 3250 # date = re.findall(r'\((.*?)\)', date)
3251 3251 # date = date[0].split(',')
3252 3252 # date = map(int, date)
3253 3253 #
3254 3254 # if len(date)<6:
3255 3255 # date.append(0)
3256 3256 #
3257 3257 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3258 3258 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3259 3259 arrayDate = numpy.tile(date, (len(listMeteors)))
3260 3260
3261 3261 #Meteor array
3262 3262 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3263 3263 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3264 3264
3265 3265 #Parameters Array
3266 3266 arrayParameters[:,0] = arrayDate #Date
3267 3267 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3268 3268 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3269 3269 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3270 3270 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3271 3271
3272 3272
3273 3273 return arrayParameters
3274 3274
3275 3275 class CorrectSMPhases(Operation):
3276 3276
3277 3277 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3278 3278
3279 3279 arrayParameters = dataOut.data_param
3280 3280 pairsList = []
3281 3281 pairx = (0,1)
3282 3282 pairy = (2,3)
3283 3283 pairsList.append(pairx)
3284 3284 pairsList.append(pairy)
3285 3285 jph = numpy.zeros(4)
3286 3286
3287 3287 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3288 3288 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3289 3289 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3290 3290
3291 3291 meteorOps = SMOperations()
3292 3292 if channelPositions is None:
3293 3293 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3294 3294 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3295 3295
3296 3296 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3297 3297 h = (hmin,hmax)
3298 3298
3299 3299 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3300 3300
3301 3301 dataOut.data_param = arrayParameters
3302 3302 return
3303 3303
3304 3304 class SMPhaseCalibration(Operation):
3305 3305
3306 3306 __buffer = None
3307 3307
3308 3308 __initime = None
3309 3309
3310 3310 __dataReady = False
3311 3311
3312 3312 __isConfig = False
3313 3313
3314 3314 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3315 3315
3316 3316 dataTime = currentTime + paramInterval
3317 3317 deltaTime = dataTime - initTime
3318 3318
3319 3319 if deltaTime >= outputInterval or deltaTime < 0:
3320 3320 return True
3321 3321
3322 3322 return False
3323 3323
3324 3324 def __getGammas(self, pairs, d, phases):
3325 3325 gammas = numpy.zeros(2)
3326 3326
3327 3327 for i in range(len(pairs)):
3328 3328
3329 3329 pairi = pairs[i]
3330 3330
3331 3331 phip3 = phases[:,pairi[0]]
3332 3332 d3 = d[pairi[0]]
3333 3333 phip2 = phases[:,pairi[1]]
3334 3334 d2 = d[pairi[1]]
3335 3335 #Calculating gamma
3336 3336 # jdcos = alp1/(k*d1)
3337 3337 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3338 3338 jgamma = -phip2*d3/d2 - phip3
3339 3339 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3340 3340 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3341 3341 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3342 3342
3343 3343 #Revised distribution
3344 3344 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3345 3345
3346 3346 #Histogram
3347 3347 nBins = 64
3348 3348 rmin = -0.5*numpy.pi
3349 3349 rmax = 0.5*numpy.pi
3350 3350 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3351 3351
3352 3352 meteorsY = phaseHisto[0]
3353 3353 phasesX = phaseHisto[1][:-1]
3354 3354 width = phasesX[1] - phasesX[0]
3355 3355 phasesX += width/2
3356 3356
3357 3357 #Gaussian aproximation
3358 3358 bpeak = meteorsY.argmax()
3359 3359 peak = meteorsY.max()
3360 3360 jmin = bpeak - 5
3361 3361 jmax = bpeak + 5 + 1
3362 3362
3363 3363 if jmin<0:
3364 3364 jmin = 0
3365 3365 jmax = 6
3366 3366 elif jmax > meteorsY.size:
3367 3367 jmin = meteorsY.size - 6
3368 3368 jmax = meteorsY.size
3369 3369
3370 3370 x0 = numpy.array([peak,bpeak,50])
3371 3371 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3372 3372
3373 3373 #Gammas
3374 3374 gammas[i] = coeff[0][1]
3375 3375
3376 3376 return gammas
3377 3377
3378 3378 def __residualFunction(self, coeffs, y, t):
3379 3379
3380 3380 return y - self.__gauss_function(t, coeffs)
3381 3381
3382 3382 def __gauss_function(self, t, coeffs):
3383 3383
3384 3384 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3385 3385
3386 3386 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3387 3387 meteorOps = SMOperations()
3388 3388 nchan = 4
3389 3389 pairx = pairsList[0] #x es 0
3390 3390 pairy = pairsList[1] #y es 1
3391 3391 center_xangle = 0
3392 3392 center_yangle = 0
3393 3393 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3394 3394 ntimes = len(range_angle)
3395 3395
3396 3396 nstepsx = 20
3397 3397 nstepsy = 20
3398 3398
3399 3399 for iz in range(ntimes):
3400 3400 min_xangle = -range_angle[iz]/2 + center_xangle
3401 3401 max_xangle = range_angle[iz]/2 + center_xangle
3402 3402 min_yangle = -range_angle[iz]/2 + center_yangle
3403 3403 max_yangle = range_angle[iz]/2 + center_yangle
3404 3404
3405 3405 inc_x = (max_xangle-min_xangle)/nstepsx
3406 3406 inc_y = (max_yangle-min_yangle)/nstepsy
3407 3407
3408 3408 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3409 3409 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3410 3410 penalty = numpy.zeros((nstepsx,nstepsy))
3411 3411 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3412 3412 jph = numpy.zeros(nchan)
3413 3413
3414 3414 # Iterations looking for the offset
3415 3415 for iy in range(int(nstepsy)):
3416 3416 for ix in range(int(nstepsx)):
3417 3417 d3 = d[pairsList[1][0]]
3418 3418 d2 = d[pairsList[1][1]]
3419 3419 d5 = d[pairsList[0][0]]
3420 3420 d4 = d[pairsList[0][1]]
3421 3421
3422 3422 alp2 = alpha_y[iy] #gamma 1
3423 3423 alp4 = alpha_x[ix] #gamma 0
3424 3424
3425 3425 alp3 = -alp2*d3/d2 - gammas[1]
3426 3426 alp5 = -alp4*d5/d4 - gammas[0]
3427 3427 # jph[pairy[1]] = alpha_y[iy]
3428 3428 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3429 3429
3430 3430 # jph[pairx[1]] = alpha_x[ix]
3431 3431 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3432 3432 jph[pairsList[0][1]] = alp4
3433 3433 jph[pairsList[0][0]] = alp5
3434 3434 jph[pairsList[1][0]] = alp3
3435 3435 jph[pairsList[1][1]] = alp2
3436 3436 jph_array[:,ix,iy] = jph
3437 3437 # d = [2.0,2.5,2.5,2.0]
3438 3438 #falta chequear si va a leer bien los meteoros
3439 3439 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3440 3440 error = meteorsArray1[:,-1]
3441 3441 ind1 = numpy.where(error==0)[0]
3442 3442 penalty[ix,iy] = ind1.size
3443 3443
3444 3444 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3445 3445 phOffset = jph_array[:,i,j]
3446 3446
3447 3447 center_xangle = phOffset[pairx[1]]
3448 3448 center_yangle = phOffset[pairy[1]]
3449 3449
3450 3450 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3451 3451 phOffset = phOffset*180/numpy.pi
3452 3452 return phOffset
3453 3453
3454 3454
3455 3455 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3456 3456
3457 3457 dataOut.flagNoData = True
3458 3458 self.__dataReady = False
3459 3459 dataOut.outputInterval = nHours*3600
3460 3460
3461 3461 if self.__isConfig == False:
3462 3462 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3463 3463 #Get Initial LTC time
3464 3464 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3465 3465 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3466 3466
3467 3467 self.__isConfig = True
3468 3468
3469 3469 if self.__buffer is None:
3470 3470 self.__buffer = dataOut.data_param.copy()
3471 3471
3472 3472 else:
3473 3473 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3474 3474
3475 3475 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3476 3476
3477 3477 if self.__dataReady:
3478 3478 dataOut.utctimeInit = self.__initime
3479 3479 self.__initime += dataOut.outputInterval #to erase time offset
3480 3480
3481 3481 freq = dataOut.frequency
3482 3482 c = dataOut.C #m/s
3483 3483 lamb = c/freq
3484 3484 k = 2*numpy.pi/lamb
3485 3485 azimuth = 0
3486 3486 h = (hmin, hmax)
3487 3487 # pairs = ((0,1),(2,3)) #Estrella
3488 3488 # pairs = ((1,0),(2,3)) #T
3489 3489
3490 3490 if channelPositions is None:
3491 3491 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3492 3492 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3493 3493 meteorOps = SMOperations()
3494 3494 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3495 3495
3496 3496 #Checking correct order of pairs
3497 3497 pairs = []
3498 3498 if distances[1] > distances[0]:
3499 3499 pairs.append((1,0))
3500 3500 else:
3501 3501 pairs.append((0,1))
3502 3502
3503 3503 if distances[3] > distances[2]:
3504 3504 pairs.append((3,2))
3505 3505 else:
3506 3506 pairs.append((2,3))
3507 3507 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3508 3508
3509 3509 meteorsArray = self.__buffer
3510 3510 error = meteorsArray[:,-1]
3511 3511 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3512 3512 ind1 = numpy.where(boolError)[0]
3513 3513 meteorsArray = meteorsArray[ind1,:]
3514 3514 meteorsArray[:,-1] = 0
3515 3515 phases = meteorsArray[:,8:12]
3516 3516
3517 3517 #Calculate Gammas
3518 3518 gammas = self.__getGammas(pairs, distances, phases)
3519 3519 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3520 3520 #Calculate Phases
3521 3521 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3522 3522 phasesOff = phasesOff.reshape((1,phasesOff.size))
3523 3523 dataOut.data_output = -phasesOff
3524 3524 dataOut.flagNoData = False
3525 3525 self.__buffer = None
3526 3526
3527 3527
3528 3528 return
3529 3529
3530 3530 class SMOperations():
3531 3531
3532 3532 def __init__(self):
3533 3533
3534 3534 return
3535 3535
3536 3536 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3537 3537
3538 3538 arrayParameters = arrayParameters0.copy()
3539 3539 hmin = h[0]
3540 3540 hmax = h[1]
3541 3541
3542 3542 #Calculate AOA (Error N 3, 4)
3543 3543 #JONES ET AL. 1998
3544 3544 AOAthresh = numpy.pi/8
3545 3545 error = arrayParameters[:,-1]
3546 3546 phases = -arrayParameters[:,8:12] + jph
3547 3547 # phases = numpy.unwrap(phases)
3548 3548 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3549 3549
3550 3550 #Calculate Heights (Error N 13 and 14)
3551 3551 error = arrayParameters[:,-1]
3552 3552 Ranges = arrayParameters[:,1]
3553 3553 zenith = arrayParameters[:,4]
3554 3554 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3555 3555
3556 3556 #----------------------- Get Final data ------------------------------------
3557 3557 # error = arrayParameters[:,-1]
3558 3558 # ind1 = numpy.where(error==0)[0]
3559 3559 # arrayParameters = arrayParameters[ind1,:]
3560 3560
3561 3561 return arrayParameters
3562 3562
3563 3563 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3564 3564
3565 3565 arrayAOA = numpy.zeros((phases.shape[0],3))
3566 3566 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3567 3567
3568 3568 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3569 3569 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3570 3570 arrayAOA[:,2] = cosDirError
3571 3571
3572 3572 azimuthAngle = arrayAOA[:,0]
3573 3573 zenithAngle = arrayAOA[:,1]
3574 3574
3575 3575 #Setting Error
3576 3576 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3577 3577 error[indError] = 0
3578 3578 #Number 3: AOA not fesible
3579 3579 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3580 3580 error[indInvalid] = 3
3581 3581 #Number 4: Large difference in AOAs obtained from different antenna baselines
3582 3582 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3583 3583 error[indInvalid] = 4
3584 3584 return arrayAOA, error
3585 3585
3586 3586 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3587 3587
3588 3588 #Initializing some variables
3589 3589 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3590 3590 ang_aux = ang_aux.reshape(1,ang_aux.size)
3591 3591
3592 3592 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3593 3593 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3594 3594
3595 3595
3596 3596 for i in range(2):
3597 3597 ph0 = arrayPhase[:,pairsList[i][0]]
3598 3598 ph1 = arrayPhase[:,pairsList[i][1]]
3599 3599 d0 = distances[pairsList[i][0]]
3600 3600 d1 = distances[pairsList[i][1]]
3601 3601
3602 3602 ph0_aux = ph0 + ph1
3603 3603 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3604 3604 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3605 3605 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3606 3606 #First Estimation
3607 3607 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3608 3608
3609 3609 #Most-Accurate Second Estimation
3610 3610 phi1_aux = ph0 - ph1
3611 3611 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3612 3612 #Direction Cosine 1
3613 3613 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3614 3614
3615 3615 #Searching the correct Direction Cosine
3616 3616 cosdir0_aux = cosdir0[:,i]
3617 3617 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3618 3618 #Minimum Distance
3619 3619 cosDiff = (cosdir1 - cosdir0_aux)**2
3620 3620 indcos = cosDiff.argmin(axis = 1)
3621 3621 #Saving Value obtained
3622 3622 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3623 3623
3624 3624 return cosdir0, cosdir
3625 3625
3626 3626 def __calculateAOA(self, cosdir, azimuth):
3627 3627 cosdirX = cosdir[:,0]
3628 3628 cosdirY = cosdir[:,1]
3629 3629
3630 3630 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3631 3631 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3632 3632 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3633 3633
3634 3634 return angles
3635 3635
3636 3636 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3637 3637
3638 3638 Ramb = 375 #Ramb = c/(2*PRF)
3639 3639 Re = 6371 #Earth Radius
3640 3640 heights = numpy.zeros(Ranges.shape)
3641 3641
3642 3642 R_aux = numpy.array([0,1,2])*Ramb
3643 3643 R_aux = R_aux.reshape(1,R_aux.size)
3644 3644
3645 3645 Ranges = Ranges.reshape(Ranges.size,1)
3646 3646
3647 3647 Ri = Ranges + R_aux
3648 3648 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3649 3649
3650 3650 #Check if there is a height between 70 and 110 km
3651 3651 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3652 3652 ind_h = numpy.where(h_bool == 1)[0]
3653 3653
3654 3654 hCorr = hi[ind_h, :]
3655 3655 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3656 3656
3657 3657 hCorr = hi[ind_hCorr][:len(ind_h)]
3658 3658 heights[ind_h] = hCorr
3659 3659
3660 3660 #Setting Error
3661 3661 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3662 3662 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3663 3663 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3664 3664 error[indError] = 0
3665 3665 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3666 3666 error[indInvalid2] = 14
3667 3667 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3668 3668 error[indInvalid1] = 13
3669 3669
3670 3670 return heights, error
3671 3671
3672 3672 def getPhasePairs(self, channelPositions):
3673 3673 chanPos = numpy.array(channelPositions)
3674 3674 listOper = list(itertools.combinations(list(range(5)),2))
3675 3675
3676 3676 distances = numpy.zeros(4)
3677 3677 axisX = []
3678 3678 axisY = []
3679 3679 distX = numpy.zeros(3)
3680 3680 distY = numpy.zeros(3)
3681 3681 ix = 0
3682 3682 iy = 0
3683 3683
3684 3684 pairX = numpy.zeros((2,2))
3685 3685 pairY = numpy.zeros((2,2))
3686 3686
3687 3687 for i in range(len(listOper)):
3688 3688 pairi = listOper[i]
3689 3689
3690 3690 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3691 3691
3692 3692 if posDif[0] == 0:
3693 3693 axisY.append(pairi)
3694 3694 distY[iy] = posDif[1]
3695 3695 iy += 1
3696 3696 elif posDif[1] == 0:
3697 3697 axisX.append(pairi)
3698 3698 distX[ix] = posDif[0]
3699 3699 ix += 1
3700 3700
3701 3701 for i in range(2):
3702 3702 if i==0:
3703 3703 dist0 = distX
3704 3704 axis0 = axisX
3705 3705 else:
3706 3706 dist0 = distY
3707 3707 axis0 = axisY
3708 3708
3709 3709 side = numpy.argsort(dist0)[:-1]
3710 3710 axis0 = numpy.array(axis0)[side,:]
3711 3711 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3712 3712 axis1 = numpy.unique(numpy.reshape(axis0,4))
3713 3713 side = axis1[axis1 != chanC]
3714 3714 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3715 3715 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3716 3716 if diff1<0:
3717 3717 chan2 = side[0]
3718 3718 d2 = numpy.abs(diff1)
3719 3719 chan1 = side[1]
3720 3720 d1 = numpy.abs(diff2)
3721 3721 else:
3722 3722 chan2 = side[1]
3723 3723 d2 = numpy.abs(diff2)
3724 3724 chan1 = side[0]
3725 3725 d1 = numpy.abs(diff1)
3726 3726
3727 3727 if i==0:
3728 3728 chanCX = chanC
3729 3729 chan1X = chan1
3730 3730 chan2X = chan2
3731 3731 distances[0:2] = numpy.array([d1,d2])
3732 3732 else:
3733 3733 chanCY = chanC
3734 3734 chan1Y = chan1
3735 3735 chan2Y = chan2
3736 3736 distances[2:4] = numpy.array([d1,d2])
3737 3737 # axisXsides = numpy.reshape(axisX[ix,:],4)
3738 3738 #
3739 3739 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3740 3740 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3741 3741 #
3742 3742 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3743 3743 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3744 3744 # channel25X = int(pairX[0,ind25X])
3745 3745 # channel20X = int(pairX[1,ind20X])
3746 3746 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3747 3747 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3748 3748 # channel25Y = int(pairY[0,ind25Y])
3749 3749 # channel20Y = int(pairY[1,ind20Y])
3750 3750
3751 3751 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3752 3752 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3753 3753
3754 3754 return pairslist, distances
3755 3755 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3756 3756 #
3757 3757 # arrayAOA = numpy.zeros((phases.shape[0],3))
3758 3758 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3759 3759 #
3760 3760 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3761 3761 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3762 3762 # arrayAOA[:,2] = cosDirError
3763 3763 #
3764 3764 # azimuthAngle = arrayAOA[:,0]
3765 3765 # zenithAngle = arrayAOA[:,1]
3766 3766 #
3767 3767 # #Setting Error
3768 3768 # #Number 3: AOA not fesible
3769 3769 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3770 3770 # error[indInvalid] = 3
3771 3771 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3772 3772 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3773 3773 # error[indInvalid] = 4
3774 3774 # return arrayAOA, error
3775 3775 #
3776 3776 # def __getDirectionCosines(self, arrayPhase, pairsList):
3777 3777 #
3778 3778 # #Initializing some variables
3779 3779 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3780 3780 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3781 3781 #
3782 3782 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3783 3783 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3784 3784 #
3785 3785 #
3786 3786 # for i in range(2):
3787 3787 # #First Estimation
3788 3788 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3789 3789 # #Dealias
3790 3790 # indcsi = numpy.where(phi0_aux > numpy.pi)
3791 3791 # phi0_aux[indcsi] -= 2*numpy.pi
3792 3792 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3793 3793 # phi0_aux[indcsi] += 2*numpy.pi
3794 3794 # #Direction Cosine 0
3795 3795 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3796 3796 #
3797 3797 # #Most-Accurate Second Estimation
3798 3798 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3799 3799 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3800 3800 # #Direction Cosine 1
3801 3801 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3802 3802 #
3803 3803 # #Searching the correct Direction Cosine
3804 3804 # cosdir0_aux = cosdir0[:,i]
3805 3805 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3806 3806 # #Minimum Distance
3807 3807 # cosDiff = (cosdir1 - cosdir0_aux)**2
3808 3808 # indcos = cosDiff.argmin(axis = 1)
3809 3809 # #Saving Value obtained
3810 3810 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3811 3811 #
3812 3812 # return cosdir0, cosdir
3813 3813 #
3814 3814 # def __calculateAOA(self, cosdir, azimuth):
3815 3815 # cosdirX = cosdir[:,0]
3816 3816 # cosdirY = cosdir[:,1]
3817 3817 #
3818 3818 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3819 3819 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3820 3820 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3821 3821 #
3822 3822 # return angles
3823 3823 #
3824 3824 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3825 3825 #
3826 3826 # Ramb = 375 #Ramb = c/(2*PRF)
3827 3827 # Re = 6371 #Earth Radius
3828 3828 # heights = numpy.zeros(Ranges.shape)
3829 3829 #
3830 3830 # R_aux = numpy.array([0,1,2])*Ramb
3831 3831 # R_aux = R_aux.reshape(1,R_aux.size)
3832 3832 #
3833 3833 # Ranges = Ranges.reshape(Ranges.size,1)
3834 3834 #
3835 3835 # Ri = Ranges + R_aux
3836 3836 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3837 3837 #
3838 3838 # #Check if there is a height between 70 and 110 km
3839 3839 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3840 3840 # ind_h = numpy.where(h_bool == 1)[0]
3841 3841 #
3842 3842 # hCorr = hi[ind_h, :]
3843 3843 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3844 3844 #
3845 3845 # hCorr = hi[ind_hCorr]
3846 3846 # heights[ind_h] = hCorr
3847 3847 #
3848 3848 # #Setting Error
3849 3849 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3850 3850 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3851 3851 #
3852 3852 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3853 3853 # error[indInvalid2] = 14
3854 3854 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3855 3855 # error[indInvalid1] = 13
3856 3856 #
3857 3857 # return heights, error
3858 3858 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now