##// END OF EJS Templates
Merge branch 'schain_mp' of http://jro-dev.igp.gob.pe/rhodecode/schain into schain_mp
José Chávez -
r940:3b577291ba9a merge
parent child
Show More
@@ -1,1225 +1,1228
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 5 '''
6 6
7 7 import copy
8 8 import numpy
9 9 import datetime
10 10
11 11 from jroheaderIO import SystemHeader, RadarControllerHeader
12 12 from schainpy import cSchain
13 13
14 14
15 15 def getNumpyDtype(dataTypeCode):
16 16
17 17 if dataTypeCode == 0:
18 18 numpyDtype = numpy.dtype([('real','<i1'),('imag','<i1')])
19 19 elif dataTypeCode == 1:
20 20 numpyDtype = numpy.dtype([('real','<i2'),('imag','<i2')])
21 21 elif dataTypeCode == 2:
22 22 numpyDtype = numpy.dtype([('real','<i4'),('imag','<i4')])
23 23 elif dataTypeCode == 3:
24 24 numpyDtype = numpy.dtype([('real','<i8'),('imag','<i8')])
25 25 elif dataTypeCode == 4:
26 26 numpyDtype = numpy.dtype([('real','<f4'),('imag','<f4')])
27 27 elif dataTypeCode == 5:
28 28 numpyDtype = numpy.dtype([('real','<f8'),('imag','<f8')])
29 29 else:
30 30 raise ValueError, 'dataTypeCode was not defined'
31 31
32 32 return numpyDtype
33 33
34 34 def getDataTypeCode(numpyDtype):
35 35
36 36 if numpyDtype == numpy.dtype([('real','<i1'),('imag','<i1')]):
37 37 datatype = 0
38 38 elif numpyDtype == numpy.dtype([('real','<i2'),('imag','<i2')]):
39 39 datatype = 1
40 40 elif numpyDtype == numpy.dtype([('real','<i4'),('imag','<i4')]):
41 41 datatype = 2
42 42 elif numpyDtype == numpy.dtype([('real','<i8'),('imag','<i8')]):
43 43 datatype = 3
44 44 elif numpyDtype == numpy.dtype([('real','<f4'),('imag','<f4')]):
45 45 datatype = 4
46 46 elif numpyDtype == numpy.dtype([('real','<f8'),('imag','<f8')]):
47 47 datatype = 5
48 48 else:
49 49 datatype = None
50 50
51 51 return datatype
52 52
53 53 def hildebrand_sekhon(data, navg):
54 54 """
55 55 This method is for the objective determination of the noise level in Doppler spectra. This
56 56 implementation technique is based on the fact that the standard deviation of the spectral
57 57 densities is equal to the mean spectral density for white Gaussian noise
58 58
59 59 Inputs:
60 60 Data : heights
61 61 navg : numbers of averages
62 62
63 63 Return:
64 64 -1 : any error
65 65 anoise : noise's level
66 66 """
67 67
68 68 sortdata = numpy.sort(data, axis=None)
69 69 # lenOfData = len(sortdata)
70 70 # nums_min = lenOfData*0.2
71 71 #
72 72 # if nums_min <= 5:
73 73 # nums_min = 5
74 74 #
75 75 # sump = 0.
76 76 #
77 77 # sumq = 0.
78 78 #
79 79 # j = 0
80 80 #
81 81 # cont = 1
82 82 #
83 83 # while((cont==1)and(j<lenOfData)):
84 84 #
85 85 # sump += sortdata[j]
86 86 #
87 87 # sumq += sortdata[j]**2
88 88 #
89 89 # if j > nums_min:
90 90 # rtest = float(j)/(j-1) + 1.0/navg
91 91 # if ((sumq*j) > (rtest*sump**2)):
92 92 # j = j - 1
93 93 # sump = sump - sortdata[j]
94 94 # sumq = sumq - sortdata[j]**2
95 95 # cont = 0
96 96 #
97 97 # j += 1
98 98 #
99 99 # lnoise = sump /j
100 100 #
101 101 # return lnoise
102 102
103 103 return cSchain.hildebrand_sekhon(sortdata, navg)
104 104
105 105
106 106 class Beam:
107 107
108 108 def __init__(self):
109 109 self.codeList = []
110 110 self.azimuthList = []
111 111 self.zenithList = []
112 112
113 113 class GenericData(object):
114 114
115 115 flagNoData = True
116 116
117 117 def __init__(self):
118 118
119 119 raise NotImplementedError
120 120
121 121 def copy(self, inputObj=None):
122 122
123 123 if inputObj == None:
124 124 return copy.deepcopy(self)
125 125
126 126 for key in inputObj.__dict__.keys():
127 127
128 128 attribute = inputObj.__dict__[key]
129 129
130 130 #If this attribute is a tuple or list
131 131 if type(inputObj.__dict__[key]) in (tuple, list):
132 132 self.__dict__[key] = attribute[:]
133 133 continue
134 134
135 135 #If this attribute is another object or instance
136 136 if hasattr(attribute, '__dict__'):
137 137 self.__dict__[key] = attribute.copy()
138 138 continue
139 139
140 140 self.__dict__[key] = inputObj.__dict__[key]
141 141
142 142 def deepcopy(self):
143 143
144 144 return copy.deepcopy(self)
145 145
146 146 def isEmpty(self):
147 147
148 148 return self.flagNoData
149 149
150 150 class JROData(GenericData):
151 151
152 152 # m_BasicHeader = BasicHeader()
153 153 # m_ProcessingHeader = ProcessingHeader()
154 154
155 155 systemHeaderObj = SystemHeader()
156 156
157 157 radarControllerHeaderObj = RadarControllerHeader()
158 158
159 159 # data = None
160 160
161 161 type = None
162 162
163 163 datatype = None #dtype but in string
164 164
165 165 # dtype = None
166 166
167 167 # nChannels = None
168 168
169 169 # nHeights = None
170 170
171 171 nProfiles = None
172 172
173 173 heightList = None
174 174
175 175 channelList = None
176 176
177 177 flagDiscontinuousBlock = False
178 178
179 179 useLocalTime = False
180 180
181 181 utctime = None
182 182
183 183 timeZone = None
184 184
185 185 dstFlag = None
186 186
187 187 errorCount = None
188 188
189 189 blocksize = None
190 190
191 191 # nCode = None
192 192 #
193 193 # nBaud = None
194 194 #
195 195 # code = None
196 196
197 197 flagDecodeData = False #asumo q la data no esta decodificada
198 198
199 199 flagDeflipData = False #asumo q la data no esta sin flip
200 200
201 201 flagShiftFFT = False
202 202
203 203 # ippSeconds = None
204 204
205 205 # timeInterval = None
206 206
207 207 nCohInt = None
208 208
209 209 # noise = None
210 210
211 211 windowOfFilter = 1
212 212
213 213 #Speed of ligth
214 214 C = 3e8
215 215
216 216 frequency = 49.92e6
217 217
218 218 realtime = False
219 219
220 220 beacon_heiIndexList = None
221 221
222 222 last_block = None
223 223
224 224 blocknow = None
225 225
226 226 azimuth = None
227 227
228 228 zenith = None
229 229
230 230 beam = Beam()
231 231
232 232 profileIndex = None
233 233
234 234 def __init__(self):
235 235
236 236 raise NotImplementedError
237 237
238 238 def getNoise(self):
239 239
240 240 raise NotImplementedError
241 241
242 242 def getNChannels(self):
243 243
244 244 return len(self.channelList)
245 245
246 246 def getChannelIndexList(self):
247 247
248 248 return range(self.nChannels)
249 249
250 250 def getNHeights(self):
251 251
252 252 return len(self.heightList)
253 253
254 254 def getHeiRange(self, extrapoints=0):
255 255
256 256 heis = self.heightList
257 257 # deltah = self.heightList[1] - self.heightList[0]
258 258 #
259 259 # heis.append(self.heightList[-1])
260 260
261 261 return heis
262 262
263 263 def getDeltaH(self):
264 264
265 265 delta = self.heightList[1] - self.heightList[0]
266 266
267 267 return delta
268 268
269 269 def getltctime(self):
270 270
271 271 if self.useLocalTime:
272 272 return self.utctime - self.timeZone*60
273 273
274 274 return self.utctime
275 275
276 276 def getDatatime(self):
277 277
278 278 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
279 279 return datatimeValue
280 280
281 281 def getTimeRange(self):
282 282
283 283 datatime = []
284 284
285 285 datatime.append(self.ltctime)
286 286 datatime.append(self.ltctime + self.timeInterval+1)
287 287
288 288 datatime = numpy.array(datatime)
289 289
290 290 return datatime
291 291
292 292 def getFmaxTimeResponse(self):
293 293
294 294 period = (10**-6)*self.getDeltaH()/(0.15)
295 295
296 296 PRF = 1./(period * self.nCohInt)
297 297
298 298 fmax = PRF
299 299
300 300 return fmax
301 301
302 302 def getFmax(self):
303 303
304 304 PRF = 1./(self.ippSeconds * self.nCohInt)
305 305
306 306 fmax = PRF
307 307
308 308 return fmax
309 309
310 310 def getVmax(self):
311 311
312 312 _lambda = self.C/self.frequency
313 313
314 314 vmax = self.getFmax() * _lambda/2
315 315
316 316 return vmax
317 317
318 318 def get_ippSeconds(self):
319 319 '''
320 320 '''
321 321 return self.radarControllerHeaderObj.ippSeconds
322 322
323 323 def set_ippSeconds(self, ippSeconds):
324 324 '''
325 325 '''
326 326
327 327 self.radarControllerHeaderObj.ippSeconds = ippSeconds
328 328
329 329 return
330 330
331 331 def get_dtype(self):
332 332 '''
333 333 '''
334 334 return getNumpyDtype(self.datatype)
335 335
336 336 def set_dtype(self, numpyDtype):
337 337 '''
338 338 '''
339 339
340 340 self.datatype = getDataTypeCode(numpyDtype)
341 341
342 342 def get_code(self):
343 343 '''
344 344 '''
345 345 return self.radarControllerHeaderObj.code
346 346
347 347 def set_code(self, code):
348 348 '''
349 349 '''
350 350 self.radarControllerHeaderObj.code = code
351 351
352 352 return
353 353
354 354 def get_ncode(self):
355 355 '''
356 356 '''
357 357 return self.radarControllerHeaderObj.nCode
358 358
359 359 def set_ncode(self, nCode):
360 360 '''
361 361 '''
362 362 self.radarControllerHeaderObj.nCode = nCode
363 363
364 364 return
365 365
366 366 def get_nbaud(self):
367 367 '''
368 368 '''
369 369 return self.radarControllerHeaderObj.nBaud
370 370
371 371 def set_nbaud(self, nBaud):
372 372 '''
373 373 '''
374 374 self.radarControllerHeaderObj.nBaud = nBaud
375 375
376 376 return
377 377
378 378 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
379 379 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
380 380 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
381 381 #noise = property(getNoise, "I'm the 'nHeights' property.")
382 382 datatime = property(getDatatime, "I'm the 'datatime' property")
383 383 ltctime = property(getltctime, "I'm the 'ltctime' property")
384 384 ippSeconds = property(get_ippSeconds, set_ippSeconds)
385 385 dtype = property(get_dtype, set_dtype)
386 386 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
387 387 code = property(get_code, set_code)
388 388 nCode = property(get_ncode, set_ncode)
389 389 nBaud = property(get_nbaud, set_nbaud)
390 390
391 391 class Voltage(JROData):
392 392
393 393 #data es un numpy array de 2 dmensiones (canales, alturas)
394 394 data = None
395 395
396 396 def __init__(self):
397 397 '''
398 398 Constructor
399 399 '''
400 400
401 401 self.useLocalTime = True
402 402
403 403 self.radarControllerHeaderObj = RadarControllerHeader()
404 404
405 405 self.systemHeaderObj = SystemHeader()
406 406
407 407 self.type = "Voltage"
408 408
409 409 self.data = None
410 410
411 411 # self.dtype = None
412 412
413 413 # self.nChannels = 0
414 414
415 415 # self.nHeights = 0
416 416
417 417 self.nProfiles = None
418 418
419 419 self.heightList = None
420 420
421 421 self.channelList = None
422 422
423 423 # self.channelIndexList = None
424 424
425 425 self.flagNoData = True
426 426
427 427 self.flagDiscontinuousBlock = False
428 428
429 429 self.utctime = None
430 430
431 431 self.timeZone = None
432 432
433 433 self.dstFlag = None
434 434
435 435 self.errorCount = None
436 436
437 437 self.nCohInt = None
438 438
439 439 self.blocksize = None
440 440
441 441 self.flagDecodeData = False #asumo q la data no esta decodificada
442 442
443 443 self.flagDeflipData = False #asumo q la data no esta sin flip
444 444
445 445 self.flagShiftFFT = False
446 446
447 447 self.flagDataAsBlock = False #Asumo que la data es leida perfil a perfil
448 448
449 449 self.profileIndex = 0
450 450
451 451 def getNoisebyHildebrand(self, channel = None):
452 452 """
453 453 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
454 454
455 455 Return:
456 456 noiselevel
457 457 """
458 458
459 459 if channel != None:
460 460 data = self.data[channel]
461 461 nChannels = 1
462 462 else:
463 463 data = self.data
464 464 nChannels = self.nChannels
465 465
466 466 noise = numpy.zeros(nChannels)
467 467 power = data * numpy.conjugate(data)
468 468
469 469 for thisChannel in range(nChannels):
470 470 if nChannels == 1:
471 471 daux = power[:].real
472 472 else:
473 473 daux = power[thisChannel,:].real
474 474 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
475 475
476 476 return noise
477 477
478 478 def getNoise(self, type = 1, channel = None):
479 479
480 480 if type == 1:
481 481 noise = self.getNoisebyHildebrand(channel)
482 482
483 483 return noise
484 484
485 485 def getPower(self, channel = None):
486 486
487 487 if channel != None:
488 488 data = self.data[channel]
489 489 else:
490 490 data = self.data
491 491
492 492 power = data * numpy.conjugate(data)
493 493 powerdB = 10*numpy.log10(power.real)
494 494 powerdB = numpy.squeeze(powerdB)
495 495
496 496 return powerdB
497 497
498 498 def getTimeInterval(self):
499 499
500 500 timeInterval = self.ippSeconds * self.nCohInt
501 501
502 502 return timeInterval
503 503
504 504 noise = property(getNoise, "I'm the 'nHeights' property.")
505 505 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
506 506
507 507 class Spectra(JROData):
508 508
509 509 #data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
510 510 data_spc = None
511 511
512 512 #data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
513 513 data_cspc = None
514 514
515 515 #data dc es un numpy array de 2 dmensiones (canales, alturas)
516 516 data_dc = None
517 517
518 518 #data power
519 519 data_pwr = None
520 520
521 521 nFFTPoints = None
522 522
523 523 # nPairs = None
524 524
525 525 pairsList = None
526 526
527 527 nIncohInt = None
528 528
529 529 wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia
530 530
531 531 nCohInt = None #se requiere para determinar el valor de timeInterval
532 532
533 533 ippFactor = None
534 534
535 535 profileIndex = 0
536 536
537 537 plotting = "spectra"
538 538
539 539 def __init__(self):
540 540 '''
541 541 Constructor
542 542 '''
543 543
544 544 self.useLocalTime = True
545 545
546 546 self.radarControllerHeaderObj = RadarControllerHeader()
547 547
548 548 self.systemHeaderObj = SystemHeader()
549 549
550 550 self.type = "Spectra"
551 551
552 552 # self.data = None
553 553
554 554 # self.dtype = None
555 555
556 556 # self.nChannels = 0
557 557
558 558 # self.nHeights = 0
559 559
560 560 self.nProfiles = None
561 561
562 562 self.heightList = None
563 563
564 564 self.channelList = None
565 565
566 566 # self.channelIndexList = None
567 567
568 568 self.pairsList = None
569 569
570 570 self.flagNoData = True
571 571
572 572 self.flagDiscontinuousBlock = False
573 573
574 574 self.utctime = None
575 575
576 576 self.nCohInt = None
577 577
578 578 self.nIncohInt = None
579 579
580 580 self.blocksize = None
581 581
582 582 self.nFFTPoints = None
583 583
584 584 self.wavelength = None
585 585
586 586 self.flagDecodeData = False #asumo q la data no esta decodificada
587 587
588 588 self.flagDeflipData = False #asumo q la data no esta sin flip
589 589
590 590 self.flagShiftFFT = False
591 591
592 592 self.ippFactor = 1
593 593
594 594 #self.noise = None
595 595
596 596 self.beacon_heiIndexList = []
597 597
598 598 self.noise_estimation = None
599 599
600 600
601 601 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
602 602 """
603 603 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
604 604
605 605 Return:
606 606 noiselevel
607 607 """
608 608
609 609 noise = numpy.zeros(self.nChannels)
610 610
611 611 for channel in range(self.nChannels):
612 612 daux = self.data_spc[channel,xmin_index:xmax_index,ymin_index:ymax_index]
613 613 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
614 614
615 615 return noise
616 616
617 617 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
618 618
619 619 if self.noise_estimation is not None:
620 620 return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py
621 621 else:
622 622 noise = self.getNoisebyHildebrand(xmin_index, xmax_index, ymin_index, ymax_index)
623 623 return noise
624 624
625 625 def getFreqRangeTimeResponse(self, extrapoints=0):
626 626
627 627 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints*self.ippFactor)
628 628 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
629 629
630 630 return freqrange
631 631
632 632 def getAcfRange(self, extrapoints=0):
633 633
634 634 deltafreq = 10./(self.getFmax() / (self.nFFTPoints*self.ippFactor))
635 635 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
636 636
637 637 return freqrange
638 638
639 639 def getFreqRange(self, extrapoints=0):
640 640
641 641 deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor)
642 642 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
643 643
644 644 return freqrange
645 645
646 646 def getVelRange(self, extrapoints=0):
647 647
648 648 deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor)
649 649 velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) #- deltav/2
650 650
651 651 return velrange
652 652
653 653 def getNPairs(self):
654 654
655 655 return len(self.pairsList)
656 656
657 657 def getPairsIndexList(self):
658 658
659 659 return range(self.nPairs)
660 660
661 661 def getNormFactor(self):
662 662
663 663 pwcode = 1
664 664
665 665 if self.flagDecodeData:
666 666 pwcode = numpy.sum(self.code[0]**2)
667 667 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
668 668 normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
669 669
670 670 return normFactor
671 671
672 672 def getFlagCspc(self):
673 673
674 674 if self.data_cspc is None:
675 675 return True
676 676
677 677 return False
678 678
679 679 def getFlagDc(self):
680 680
681 681 if self.data_dc is None:
682 682 return True
683 683
684 684 return False
685 685
686 686 def getTimeInterval(self):
687 687
688 688 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles
689 689
690 690 return timeInterval
691 691
692 692 def getPower(self):
693 693
694 694 factor = self.normFactor
695 695 z = self.data_spc/factor
696 696 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
697 697 avg = numpy.average(z, axis=1)
698 698
699 699 return 10*numpy.log10(avg)
700 700
701 701 def getCoherence(self, pairsList=None, phase=False):
702 702
703 703 z = []
704 704 if pairsList is None:
705 705 pairsIndexList = self.pairsIndexList
706 706 else:
707 707 pairsIndexList = []
708 708 for pair in pairsList:
709 709 if pair not in self.pairsList:
710 710 raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair)
711 711 pairsIndexList.append(self.pairsList.index(pair))
712 712 for i in range(len(pairsIndexList)):
713 713 pair = self.pairsList[pairsIndexList[i]]
714 714 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
715 715 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
716 716 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
717 717 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
718 718 if phase:
719 719 data = numpy.arctan2(avgcoherenceComplex.imag,
720 720 avgcoherenceComplex.real)*180/numpy.pi
721 721 else:
722 722 data = numpy.abs(avgcoherenceComplex)
723 723
724 724 z.append(data)
725 725
726 726 return numpy.array(z)
727 727
728 728 def setValue(self, value):
729 729
730 730 print "This property should not be initialized"
731 731
732 732 return
733 733
734 734 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
735 735 pairsIndexList = property(getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
736 736 normFactor = property(getNormFactor, setValue, "I'm the 'getNormFactor' property.")
737 737 flag_cspc = property(getFlagCspc, setValue)
738 738 flag_dc = property(getFlagDc, setValue)
739 739 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
740 740 timeInterval = property(getTimeInterval, setValue, "I'm the 'timeInterval' property")
741 741
742 742 class SpectraHeis(Spectra):
743 743
744 744 data_spc = None
745 745
746 746 data_cspc = None
747 747
748 748 data_dc = None
749 749
750 750 nFFTPoints = None
751 751
752 752 # nPairs = None
753 753
754 754 pairsList = None
755 755
756 756 nCohInt = None
757 757
758 758 nIncohInt = None
759 759
760 760 def __init__(self):
761 761
762 762 self.radarControllerHeaderObj = RadarControllerHeader()
763 763
764 764 self.systemHeaderObj = SystemHeader()
765 765
766 766 self.type = "SpectraHeis"
767 767
768 768 # self.dtype = None
769 769
770 770 # self.nChannels = 0
771 771
772 772 # self.nHeights = 0
773 773
774 774 self.nProfiles = None
775 775
776 776 self.heightList = None
777 777
778 778 self.channelList = None
779 779
780 780 # self.channelIndexList = None
781 781
782 782 self.flagNoData = True
783 783
784 784 self.flagDiscontinuousBlock = False
785 785
786 786 # self.nPairs = 0
787 787
788 788 self.utctime = None
789 789
790 790 self.blocksize = None
791 791
792 792 self.profileIndex = 0
793 793
794 794 self.nCohInt = 1
795 795
796 796 self.nIncohInt = 1
797 797
798 798 def getNormFactor(self):
799 799 pwcode = 1
800 800 if self.flagDecodeData:
801 801 pwcode = numpy.sum(self.code[0]**2)
802 802
803 803 normFactor = self.nIncohInt*self.nCohInt*pwcode
804 804
805 805 return normFactor
806 806
807 807 def getTimeInterval(self):
808 808
809 809 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
810 810
811 811 return timeInterval
812 812
813 813 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
814 814 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
815 815
816 816 class Fits(JROData):
817 817
818 818 heightList = None
819 819
820 820 channelList = None
821 821
822 822 flagNoData = True
823 823
824 824 flagDiscontinuousBlock = False
825 825
826 826 useLocalTime = False
827 827
828 828 utctime = None
829 829
830 830 timeZone = None
831 831
832 832 # ippSeconds = None
833 833
834 834 # timeInterval = None
835 835
836 836 nCohInt = None
837 837
838 838 nIncohInt = None
839 839
840 840 noise = None
841 841
842 842 windowOfFilter = 1
843 843
844 844 #Speed of ligth
845 845 C = 3e8
846 846
847 847 frequency = 49.92e6
848 848
849 849 realtime = False
850 850
851 851
852 852 def __init__(self):
853 853
854 854 self.type = "Fits"
855 855
856 856 self.nProfiles = None
857 857
858 858 self.heightList = None
859 859
860 860 self.channelList = None
861 861
862 862 # self.channelIndexList = None
863 863
864 864 self.flagNoData = True
865 865
866 866 self.utctime = None
867 867
868 868 self.nCohInt = 1
869 869
870 870 self.nIncohInt = 1
871 871
872 872 self.useLocalTime = True
873 873
874 874 self.profileIndex = 0
875 875
876 876 # self.utctime = None
877 877 # self.timeZone = None
878 878 # self.ltctime = None
879 879 # self.timeInterval = None
880 880 # self.header = None
881 881 # self.data_header = None
882 882 # self.data = None
883 883 # self.datatime = None
884 884 # self.flagNoData = False
885 885 # self.expName = ''
886 886 # self.nChannels = None
887 887 # self.nSamples = None
888 888 # self.dataBlocksPerFile = None
889 889 # self.comments = ''
890 890 #
891 891
892 892
893 893 def getltctime(self):
894 894
895 895 if self.useLocalTime:
896 896 return self.utctime - self.timeZone*60
897 897
898 898 return self.utctime
899 899
900 900 def getDatatime(self):
901 901
902 902 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
903 903 return datatime
904 904
905 905 def getTimeRange(self):
906 906
907 907 datatime = []
908 908
909 909 datatime.append(self.ltctime)
910 910 datatime.append(self.ltctime + self.timeInterval)
911 911
912 912 datatime = numpy.array(datatime)
913 913
914 914 return datatime
915 915
916 916 def getHeiRange(self):
917 917
918 918 heis = self.heightList
919 919
920 920 return heis
921 921
922 922 def getNHeights(self):
923 923
924 924 return len(self.heightList)
925 925
926 926 def getNChannels(self):
927 927
928 928 return len(self.channelList)
929 929
930 930 def getChannelIndexList(self):
931 931
932 932 return range(self.nChannels)
933 933
934 934 def getNoise(self, type = 1):
935 935
936 936 #noise = numpy.zeros(self.nChannels)
937 937
938 938 if type == 1:
939 939 noise = self.getNoisebyHildebrand()
940 940
941 941 if type == 2:
942 942 noise = self.getNoisebySort()
943 943
944 944 if type == 3:
945 945 noise = self.getNoisebyWindow()
946 946
947 947 return noise
948 948
949 949 def getTimeInterval(self):
950 950
951 951 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
952 952
953 953 return timeInterval
954 954
955 955 datatime = property(getDatatime, "I'm the 'datatime' property")
956 956 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
957 957 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
958 958 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
959 959 noise = property(getNoise, "I'm the 'nHeights' property.")
960 960
961 961 ltctime = property(getltctime, "I'm the 'ltctime' property")
962 962 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
963 963
964 964
965 965 class Correlation(JROData):
966 966
967 967 noise = None
968 968
969 969 SNR = None
970 970
971 971 #--------------------------------------------------
972 972
973 973 mode = None
974 974
975 975 split = False
976 976
977 977 data_cf = None
978 978
979 979 lags = None
980 980
981 981 lagRange = None
982 982
983 983 pairsList = None
984 984
985 985 normFactor = None
986 986
987 987 #--------------------------------------------------
988 988
989 989 # calculateVelocity = None
990 990
991 991 nLags = None
992 992
993 993 nPairs = None
994 994
995 995 nAvg = None
996 996
997 997
998 998 def __init__(self):
999 999 '''
1000 1000 Constructor
1001 1001 '''
1002 1002 self.radarControllerHeaderObj = RadarControllerHeader()
1003 1003
1004 1004 self.systemHeaderObj = SystemHeader()
1005 1005
1006 1006 self.type = "Correlation"
1007 1007
1008 1008 self.data = None
1009 1009
1010 1010 self.dtype = None
1011 1011
1012 1012 self.nProfiles = None
1013 1013
1014 1014 self.heightList = None
1015 1015
1016 1016 self.channelList = None
1017 1017
1018 1018 self.flagNoData = True
1019 1019
1020 1020 self.flagDiscontinuousBlock = False
1021 1021
1022 1022 self.utctime = None
1023 1023
1024 1024 self.timeZone = None
1025 1025
1026 1026 self.dstFlag = None
1027 1027
1028 1028 self.errorCount = None
1029 1029
1030 1030 self.blocksize = None
1031 1031
1032 1032 self.flagDecodeData = False #asumo q la data no esta decodificada
1033 1033
1034 1034 self.flagDeflipData = False #asumo q la data no esta sin flip
1035 1035
1036 1036 self.pairsList = None
1037 1037
1038 1038 self.nPoints = None
1039 1039
1040 1040 def getPairsList(self):
1041 1041
1042 1042 return self.pairsList
1043 1043
1044 1044 def getNoise(self, mode = 2):
1045 1045
1046 1046 indR = numpy.where(self.lagR == 0)[0][0]
1047 1047 indT = numpy.where(self.lagT == 0)[0][0]
1048 1048
1049 1049 jspectra0 = self.data_corr[:,:,indR,:]
1050 1050 jspectra = copy.copy(jspectra0)
1051 1051
1052 1052 num_chan = jspectra.shape[0]
1053 1053 num_hei = jspectra.shape[2]
1054 1054
1055 1055 freq_dc = jspectra.shape[1]/2
1056 1056 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
1057 1057
1058 1058 if ind_vel[0]<0:
1059 1059 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
1060 1060
1061 1061 if mode == 1:
1062 1062 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
1063 1063
1064 1064 if mode == 2:
1065 1065
1066 1066 vel = numpy.array([-2,-1,1,2])
1067 1067 xx = numpy.zeros([4,4])
1068 1068
1069 1069 for fil in range(4):
1070 1070 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
1071 1071
1072 1072 xx_inv = numpy.linalg.inv(xx)
1073 1073 xx_aux = xx_inv[0,:]
1074 1074
1075 1075 for ich in range(num_chan):
1076 1076 yy = jspectra[ich,ind_vel,:]
1077 1077 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
1078 1078
1079 1079 junkid = jspectra[ich,freq_dc,:]<=0
1080 1080 cjunkid = sum(junkid)
1081 1081
1082 1082 if cjunkid.any():
1083 1083 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
1084 1084
1085 1085 noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:]
1086 1086
1087 1087 return noise
1088 1088
1089 1089 def getTimeInterval(self):
1090 1090
1091 1091 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1092 1092
1093 1093 return timeInterval
1094 1094
1095 1095 def splitFunctions(self):
1096 1096
1097 1097 pairsList = self.pairsList
1098 1098 ccf_pairs = []
1099 1099 acf_pairs = []
1100 1100 ccf_ind = []
1101 1101 acf_ind = []
1102 1102 for l in range(len(pairsList)):
1103 1103 chan0 = pairsList[l][0]
1104 1104 chan1 = pairsList[l][1]
1105 1105
1106 1106 #Obteniendo pares de Autocorrelacion
1107 1107 if chan0 == chan1:
1108 1108 acf_pairs.append(chan0)
1109 1109 acf_ind.append(l)
1110 1110 else:
1111 1111 ccf_pairs.append(pairsList[l])
1112 1112 ccf_ind.append(l)
1113 1113
1114 1114 data_acf = self.data_cf[acf_ind]
1115 1115 data_ccf = self.data_cf[ccf_ind]
1116 1116
1117 1117 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1118 1118
1119 1119 def getNormFactor(self):
1120 1120 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1121 1121 acf_pairs = numpy.array(acf_pairs)
1122 1122 normFactor = numpy.zeros((self.nPairs,self.nHeights))
1123 1123
1124 1124 for p in range(self.nPairs):
1125 1125 pair = self.pairsList[p]
1126 1126
1127 1127 ch0 = pair[0]
1128 1128 ch1 = pair[1]
1129 1129
1130 1130 ch0_max = numpy.max(data_acf[acf_pairs==ch0,:,:], axis=1)
1131 1131 ch1_max = numpy.max(data_acf[acf_pairs==ch1,:,:], axis=1)
1132 1132 normFactor[p,:] = numpy.sqrt(ch0_max*ch1_max)
1133 1133
1134 1134 return normFactor
1135 1135
1136 1136 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1137 1137 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1138 1138
1139 1139 class Parameters(Spectra):
1140 1140
1141 1141 experimentInfo = None #Information about the experiment
1142 1142
1143 1143 #Information from previous data
1144 1144
1145 1145 inputUnit = None #Type of data to be processed
1146 1146
1147 1147 operation = None #Type of operation to parametrize
1148 1148
1149 1149 #normFactor = None #Normalization Factor
1150 1150
1151 1151 groupList = None #List of Pairs, Groups, etc
1152 1152
1153 1153 #Parameters
1154 1154
1155 1155 data_param = None #Parameters obtained
1156 1156
1157 1157 data_pre = None #Data Pre Parametrization
1158 1158
1159 1159 data_SNR = None #Signal to Noise Ratio
1160 1160
1161 1161 # heightRange = None #Heights
1162 1162
1163 1163 abscissaList = None #Abscissa, can be velocities, lags or time
1164 1164
1165 1165 # noise = None #Noise Potency
1166 1166
1167 1167 utctimeInit = None #Initial UTC time
1168 1168
1169 1169 paramInterval = None #Time interval to calculate Parameters in seconds
1170 1170
1171 1171 useLocalTime = True
1172 1172
1173 1173 #Fitting
1174 1174
1175 1175 data_error = None #Error of the estimation
1176 1176
1177 1177 constants = None
1178 1178
1179 1179 library = None
1180 1180
1181 1181 #Output signal
1182 1182
1183 1183 outputInterval = None #Time interval to calculate output signal in seconds
1184 1184
1185 1185 data_output = None #Out signal
1186 1186
1187 1187 nAvg = None
1188 1188
1189 1189 noise_estimation = None
1190 1190
1191 1191
1192 1192 def __init__(self):
1193 1193 '''
1194 1194 Constructor
1195 1195 '''
1196 1196 self.radarControllerHeaderObj = RadarControllerHeader()
1197 1197
1198 1198 self.systemHeaderObj = SystemHeader()
1199 1199
1200 1200 self.type = "Parameters"
1201 1201
1202 1202 def getTimeRange1(self, interval):
1203 1203
1204 1204 datatime = []
1205 1205
1206 1206 if self.useLocalTime:
1207 1207 time1 = self.utctimeInit - self.timeZone*60
1208 1208 else:
1209 1209 time1 = self.utctimeInit
1210 1210
1211 1211 datatime.append(time1)
1212 1212 datatime.append(time1 + interval)
1213 1213 datatime = numpy.array(datatime)
1214 1214
1215 1215 return datatime
1216 1216
1217 1217 def getTimeInterval(self):
1218 1218
1219 if hasattr(self, 'timeInterval1'):
1219 1220 return self.timeInterval1
1221 else:
1222 return self.paramInterval
1220 1223
1221 1224 def getNoise(self):
1222 1225
1223 1226 return self.spc_noise
1224 1227
1225 1228 timeInterval = property(getTimeInterval)
@@ -1,709 +1,775
1 1
2 2 import os
3 3 import zmq
4 4 import time
5 5 import numpy
6 6 import datetime
7 7 import numpy as np
8 8 import matplotlib
9 9 matplotlib.use('TkAgg')
10 10 import matplotlib.pyplot as plt
11 11 from mpl_toolkits.axes_grid1 import make_axes_locatable
12 12 from matplotlib.ticker import FuncFormatter, LinearLocator
13 13 from multiprocessing import Process
14 14
15 15 from schainpy.model.proc.jroproc_base import Operation
16 16
17 17 plt.ion()
18 18
19 19 func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M'))
20 20
21 21 d1970 = datetime.datetime(1970,1,1)
22 22
23 23 class PlotData(Operation, Process):
24 24
25 25 CODE = 'Figure'
26 26 colormap = 'jro'
27 27 CONFLATE = False
28 28 __MAXNUMX = 80
29 29 __missing = 1E30
30 30
31 31 def __init__(self, **kwargs):
32 32
33 33 Operation.__init__(self, plot=True, **kwargs)
34 34 Process.__init__(self)
35 35 self.kwargs['code'] = self.CODE
36 36 self.mp = False
37 37 self.dataOut = None
38 38 self.isConfig = False
39 39 self.figure = None
40 40 self.axes = []
41 41 self.localtime = kwargs.pop('localtime', True)
42 42 self.show = kwargs.get('show', True)
43 43 self.save = kwargs.get('save', False)
44 44 self.colormap = kwargs.get('colormap', self.colormap)
45 45 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
46 46 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
47 47 self.showprofile = kwargs.get('showprofile', True)
48 48 self.title = kwargs.get('wintitle', '')
49 49 self.xaxis = kwargs.get('xaxis', 'frequency')
50 50 self.zmin = kwargs.get('zmin', None)
51 51 self.zmax = kwargs.get('zmax', None)
52 52 self.xmin = kwargs.get('xmin', None)
53 53 self.xmax = kwargs.get('xmax', None)
54 54 self.xrange = kwargs.get('xrange', 24)
55 55 self.ymin = kwargs.get('ymin', None)
56 56 self.ymax = kwargs.get('ymax', None)
57 57 self.__MAXNUMY = kwargs.get('decimation', 80)
58 58 self.throttle_value = 5
59 59 self.times = []
60 60 #self.interactive = self.kwargs['parent']
61 61
62 62
63 63 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
64 64
65 65 if x_buffer.shape[0] < 2:
66 66 return x_buffer, y_buffer, z_buffer
67 67
68 68 deltas = x_buffer[1:] - x_buffer[0:-1]
69 69 x_median = np.median(deltas)
70 70
71 71 index = np.where(deltas > 5*x_median)
72 72
73 73 if len(index[0]) != 0:
74 74 z_buffer[::, index[0], ::] = self.__missing
75 75 z_buffer = np.ma.masked_inside(z_buffer,
76 76 0.99*self.__missing,
77 77 1.01*self.__missing)
78 78
79 79 return x_buffer, y_buffer, z_buffer
80 80
81 81 def decimate(self):
82 82
83 83 # dx = int(len(self.x)/self.__MAXNUMX) + 1
84 84 dy = int(len(self.y)/self.__MAXNUMY) + 1
85 85
86 86 # x = self.x[::dx]
87 87 x = self.x
88 88 y = self.y[::dy]
89 89 z = self.z[::, ::, ::dy]
90 90
91 91 return x, y, z
92 92
93 93 def __plot(self):
94 94
95 95 print 'plotting...{}'.format(self.CODE)
96 96
97 97 if self.show:
98 print 'showing'
99 98 self.figure.show()
100 99
101 100 self.plot()
102 101 plt.tight_layout()
103 self.figure.canvas.manager.set_window_title('{} {} - Date:{}'.format(self.title, self.CODE.upper(),
104 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')))
102 self.figure.canvas.manager.set_window_title('{} {} - {}'.format(self.title, self.CODE.upper(),
103 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
105 104
106 105 if self.save:
107 106 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
108 107 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
109 108 print 'Saving figure: {}'.format(figname)
110 109 self.figure.savefig(figname)
111 110
112 111 self.figure.canvas.draw()
113 112
114 113 def plot(self):
115 114
116 115 print 'plotting...{}'.format(self.CODE.upper())
117 116 return
118 117
119 118 def run(self):
120 119
121 120 print '[Starting] {}'.format(self.name)
121
122 122 context = zmq.Context()
123 123 receiver = context.socket(zmq.SUB)
124 124 receiver.setsockopt(zmq.SUBSCRIBE, '')
125 125 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
126
127 if 'server' in self.kwargs['parent']:
128 receiver.connect('ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
129 else:
126 130 receiver.connect("ipc:///tmp/zmq.plots")
131
127 132 seconds_passed = 0
133
128 134 while True:
129 135 try:
130 136 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)#flags=zmq.NOBLOCK
131 137 self.started = self.data['STARTED']
132 138 self.dataOut = self.data['dataOut']
133 139
134 140 if (len(self.times) < len(self.data['times']) and not self.started and self.data['ENDED']):
135 141 continue
136 142
137 143 self.times = self.data['times']
138 144 self.times.sort()
139 145 self.throttle_value = self.data['throttle']
140 146 self.min_time = self.times[0]
141 147 self.max_time = self.times[-1]
142 148
143 149 if self.isConfig is False:
144 150 print 'setting up'
145 151 self.setup()
146 152 self.isConfig = True
147 153 self.__plot()
148 154
149 155 if self.data['ENDED'] is True:
150 156 print '********GRAPHIC ENDED********'
151 157 self.ended = True
152 158 self.isConfig = False
153 159 self.__plot()
154 160 elif seconds_passed >= self.data['throttle']:
155 161 print 'passed', seconds_passed
156 162 self.__plot()
157 163 seconds_passed = 0
158 164
159 165 except zmq.Again as e:
160 166 print 'Waiting for data...'
161 167 plt.pause(2)
162 168 seconds_passed += 2
163 169
164 170 def close(self):
165 171 if self.dataOut:
166 172 self.__plot()
167 173
168 174
169 175 class PlotSpectraData(PlotData):
170 176
171 177 CODE = 'spc'
172 178 colormap = 'jro'
173 179 CONFLATE = False
174 180
175 181 def setup(self):
176 182
177 183 ncolspan = 1
178 184 colspan = 1
179 185 self.ncols = int(numpy.sqrt(self.dataOut.nChannels)+0.9)
180 186 self.nrows = int(self.dataOut.nChannels*1./self.ncols + 0.9)
181 187 self.width = 3.6*self.ncols
182 188 self.height = 3.2*self.nrows
183 189 if self.showprofile:
184 190 ncolspan = 3
185 191 colspan = 2
186 192 self.width += 1.2*self.ncols
187 193
188 194 self.ylabel = 'Range [Km]'
189 195 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
190 196
191 197 if self.figure is None:
192 198 self.figure = plt.figure(figsize=(self.width, self.height),
193 199 edgecolor='k',
194 200 facecolor='w')
195 201 else:
196 202 self.figure.clf()
197 203
198 204 n = 0
199 205 for y in range(self.nrows):
200 206 for x in range(self.ncols):
201 207 if n >= self.dataOut.nChannels:
202 208 break
203 209 ax = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan), 1, colspan)
204 210 if self.showprofile:
205 211 ax.ax_profile = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan+colspan), 1, 1)
206 212
207 213 ax.firsttime = True
208 214 self.axes.append(ax)
209 215 n += 1
210 216
211 217 def plot(self):
212 218
213 219 if self.xaxis == "frequency":
214 220 x = self.dataOut.getFreqRange(1)/1000.
215 221 xlabel = "Frequency (kHz)"
216 222 elif self.xaxis == "time":
217 223 x = self.dataOut.getAcfRange(1)
218 224 xlabel = "Time (ms)"
219 225 else:
220 226 x = self.dataOut.getVelRange(1)
221 227 xlabel = "Velocity (m/s)"
222 228
223 229 y = self.dataOut.getHeiRange()
224 230 z = self.data[self.CODE]
225 231
226 232 for n, ax in enumerate(self.axes):
227 233
228 234 if ax.firsttime:
229 235 self.xmax = self.xmax if self.xmax else np.nanmax(x)
230 236 self.xmin = self.xmin if self.xmin else -self.xmax
231 237 self.ymin = self.ymin if self.ymin else np.nanmin(y)
232 238 self.ymax = self.ymax if self.ymax else np.nanmax(y)
233 239 self.zmin = self.zmin if self.zmin else np.nanmin(z)
234 240 self.zmax = self.zmax if self.zmax else np.nanmax(z)
235 241 ax.plot = ax.pcolormesh(x, y, z[n].T,
236 242 vmin=self.zmin,
237 243 vmax=self.zmax,
238 244 cmap=plt.get_cmap(self.colormap)
239 245 )
240 246 divider = make_axes_locatable(ax)
241 247 cax = divider.new_horizontal(size='3%', pad=0.05)
242 248 self.figure.add_axes(cax)
243 249 plt.colorbar(ax.plot, cax)
244 250
245 251 ax.set_xlim(self.xmin, self.xmax)
246 252 ax.set_ylim(self.ymin, self.ymax)
247 253
248 254 ax.set_ylabel(self.ylabel)
249 255 ax.set_xlabel(xlabel)
250 256
251 257 ax.firsttime = False
252 258
253 259 if self.showprofile:
254 260 ax.plot_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
255 261 ax.ax_profile.set_xlim(self.zmin, self.zmax)
256 262 ax.ax_profile.set_ylim(self.ymin, self.ymax)
257 263 ax.ax_profile.set_xlabel('dB')
258 264 ax.ax_profile.grid(b=True, axis='x')
259 265 ax.plot_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
260 266 color="k", linestyle="dashed", lw=2)[0]
261 267 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
262 268 else:
263 269 ax.plot.set_array(z[n].T.ravel())
264 270 if self.showprofile:
265 271 ax.plot_profile.set_data(self.data['rti'][self.max_time][n], y)
266 272 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
267 273
268 274 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
269 275 size=8)
270 276 self.saveTime = self.max_time
271 277
272 278
273 279 class PlotCrossSpectraData(PlotData):
274 280
275 281 CODE = 'cspc'
276 282 zmin_coh = None
277 283 zmax_coh = None
278 284 zmin_phase = None
279 285 zmax_phase = None
280 286 CONFLATE = False
281 287
282 288 def setup(self):
283 289
284 290 ncolspan = 1
285 291 colspan = 1
286 292 self.ncols = 2
287 293 self.nrows = self.dataOut.nPairs
288 294 self.width = 3.6*self.ncols
289 295 self.height = 3.2*self.nrows
290 296
291 297 self.ylabel = 'Range [Km]'
292 298 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
293 299
294 300 if self.figure is None:
295 301 self.figure = plt.figure(figsize=(self.width, self.height),
296 302 edgecolor='k',
297 303 facecolor='w')
298 304 else:
299 305 self.figure.clf()
300 306
301 307 for y in range(self.nrows):
302 308 for x in range(self.ncols):
303 309 ax = plt.subplot2grid((self.nrows, self.ncols), (y, x), 1, 1)
304 310 ax.firsttime = True
305 311 self.axes.append(ax)
306 312
307 313 def plot(self):
308 314
309 315 if self.xaxis == "frequency":
310 316 x = self.dataOut.getFreqRange(1)/1000.
311 317 xlabel = "Frequency (kHz)"
312 318 elif self.xaxis == "time":
313 319 x = self.dataOut.getAcfRange(1)
314 320 xlabel = "Time (ms)"
315 321 else:
316 322 x = self.dataOut.getVelRange(1)
317 323 xlabel = "Velocity (m/s)"
318 324
319 325 y = self.dataOut.getHeiRange()
320 326 z_coh = self.data['cspc_coh']
321 327 z_phase = self.data['cspc_phase']
322 328
323 329 for n in range(self.nrows):
324 330 ax = self.axes[2*n]
325 331 ax1 = self.axes[2*n+1]
326 332 if ax.firsttime:
327 333 self.xmax = self.xmax if self.xmax else np.nanmax(x)
328 334 self.xmin = self.xmin if self.xmin else -self.xmax
329 335 self.ymin = self.ymin if self.ymin else np.nanmin(y)
330 336 self.ymax = self.ymax if self.ymax else np.nanmax(y)
331 337 self.zmin_coh = self.zmin_coh if self.zmin_coh else 0.0
332 338 self.zmax_coh = self.zmax_coh if self.zmax_coh else 1.0
333 339 self.zmin_phase = self.zmin_phase if self.zmin_phase else -180
334 340 self.zmax_phase = self.zmax_phase if self.zmax_phase else 180
335 341
336 342 ax.plot = ax.pcolormesh(x, y, z_coh[n].T,
337 343 vmin=self.zmin_coh,
338 344 vmax=self.zmax_coh,
339 345 cmap=plt.get_cmap(self.colormap_coh)
340 346 )
341 347 divider = make_axes_locatable(ax)
342 348 cax = divider.new_horizontal(size='3%', pad=0.05)
343 349 self.figure.add_axes(cax)
344 350 plt.colorbar(ax.plot, cax)
345 351
346 352 ax.set_xlim(self.xmin, self.xmax)
347 353 ax.set_ylim(self.ymin, self.ymax)
348 354
349 355 ax.set_ylabel(self.ylabel)
350 356 ax.set_xlabel(xlabel)
351 357 ax.firsttime = False
352 358
353 359 ax1.plot = ax1.pcolormesh(x, y, z_phase[n].T,
354 360 vmin=self.zmin_phase,
355 361 vmax=self.zmax_phase,
356 362 cmap=plt.get_cmap(self.colormap_phase)
357 363 )
358 364 divider = make_axes_locatable(ax1)
359 365 cax = divider.new_horizontal(size='3%', pad=0.05)
360 366 self.figure.add_axes(cax)
361 367 plt.colorbar(ax1.plot, cax)
362 368
363 369 ax1.set_xlim(self.xmin, self.xmax)
364 370 ax1.set_ylim(self.ymin, self.ymax)
365 371
366 372 ax1.set_ylabel(self.ylabel)
367 373 ax1.set_xlabel(xlabel)
368 374 ax1.firsttime = False
369 375 else:
370 376 ax.plot.set_array(z_coh[n].T.ravel())
371 377 ax1.plot.set_array(z_phase[n].T.ravel())
372 378
373 379 ax.set_title('Coherence Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
374 380 ax1.set_title('Phase Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
375 381 self.saveTime = self.max_time
376 382
377 383
378 384 class PlotSpectraMeanData(PlotSpectraData):
379 385
380 386 CODE = 'spc_mean'
381 387 colormap = 'jet'
382 388
383 389 def plot(self):
384 390
385 391 if self.xaxis == "frequency":
386 392 x = self.dataOut.getFreqRange(1)/1000.
387 393 xlabel = "Frequency (kHz)"
388 394 elif self.xaxis == "time":
389 395 x = self.dataOut.getAcfRange(1)
390 396 xlabel = "Time (ms)"
391 397 else:
392 398 x = self.dataOut.getVelRange(1)
393 399 xlabel = "Velocity (m/s)"
394 400
395 401 y = self.dataOut.getHeiRange()
396 402 z = self.data['spc']
397 403 mean = self.data['mean'][self.max_time]
398 404
399 405 for n, ax in enumerate(self.axes):
400 406
401 407 if ax.firsttime:
402 408 self.xmax = self.xmax if self.xmax else np.nanmax(x)
403 409 self.xmin = self.xmin if self.xmin else -self.xmax
404 410 self.ymin = self.ymin if self.ymin else np.nanmin(y)
405 411 self.ymax = self.ymax if self.ymax else np.nanmax(y)
406 412 self.zmin = self.zmin if self.zmin else np.nanmin(z)
407 413 self.zmax = self.zmax if self.zmax else np.nanmax(z)
408 414 ax.plt = ax.pcolormesh(x, y, z[n].T,
409 415 vmin=self.zmin,
410 416 vmax=self.zmax,
411 417 cmap=plt.get_cmap(self.colormap)
412 418 )
413 419 ax.plt_dop = ax.plot(mean[n], y,
414 420 color='k')[0]
415 421
416 422 divider = make_axes_locatable(ax)
417 423 cax = divider.new_horizontal(size='3%', pad=0.05)
418 424 self.figure.add_axes(cax)
419 425 plt.colorbar(ax.plt, cax)
420 426
421 427 ax.set_xlim(self.xmin, self.xmax)
422 428 ax.set_ylim(self.ymin, self.ymax)
423 429
424 430 ax.set_ylabel(self.ylabel)
425 431 ax.set_xlabel(xlabel)
426 432
427 433 ax.firsttime = False
428 434
429 435 if self.showprofile:
430 436 ax.plt_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
431 437 ax.ax_profile.set_xlim(self.zmin, self.zmax)
432 438 ax.ax_profile.set_ylim(self.ymin, self.ymax)
433 439 ax.ax_profile.set_xlabel('dB')
434 440 ax.ax_profile.grid(b=True, axis='x')
435 441 ax.plt_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
436 442 color="k", linestyle="dashed", lw=2)[0]
437 443 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
438 444 else:
439 445 ax.plt.set_array(z[n].T.ravel())
440 446 ax.plt_dop.set_data(mean[n], y)
441 447 if self.showprofile:
442 448 ax.plt_profile.set_data(self.data['rti'][self.max_time][n], y)
443 449 ax.plt_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
444 450
445 451 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
446 452 size=8)
447 453 self.saveTime = self.max_time
448 454
449 455
450 456 class PlotRTIData(PlotData):
451 457
452 458 CODE = 'rti'
453 459 colormap = 'jro'
454 460
455 461 def setup(self):
456 462 self.ncols = 1
457 463 self.nrows = self.dataOut.nChannels
458 464 self.width = 10
459 465 self.height = 2.2*self.nrows if self.nrows<6 else 12
460 466 if self.nrows==1:
461 467 self.height += 1
462 468 self.ylabel = 'Range [Km]'
463 469 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
464 470
465 471 if self.figure is None:
466 472 self.figure = plt.figure(figsize=(self.width, self.height),
467 473 edgecolor='k',
468 474 facecolor='w')
469 475 else:
470 476 self.figure.clf()
471 477 self.axes = []
472 478
473 479 for n in range(self.nrows):
474 480 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
475 481 ax.firsttime = True
476 482 self.axes.append(ax)
477 483
478 484 def plot(self):
479 485
480 486 self.x = np.array(self.times)
481 487 self.y = self.dataOut.getHeiRange()
482 488 self.z = []
483 489
484 490 for ch in range(self.nrows):
485 491 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
486 492
487 493 self.z = np.array(self.z)
488 494 for n, ax in enumerate(self.axes):
489 495 x, y, z = self.fill_gaps(*self.decimate())
490 496 xmin = self.min_time
491 497 xmax = xmin+self.xrange*60*60
492 498 self.zmin = self.zmin if self.zmin else np.min(self.z)
493 499 self.zmax = self.zmax if self.zmax else np.max(self.z)
494 500 if ax.firsttime:
495 501 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
496 502 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
497 503 plot = ax.pcolormesh(x, y, z[n].T,
498 504 vmin=self.zmin,
499 505 vmax=self.zmax,
500 506 cmap=plt.get_cmap(self.colormap)
501 507 )
502 508 divider = make_axes_locatable(ax)
503 509 cax = divider.new_horizontal(size='2%', pad=0.05)
504 510 self.figure.add_axes(cax)
505 511 plt.colorbar(plot, cax)
506 512 ax.set_ylim(self.ymin, self.ymax)
507 513
508 514 ax.xaxis.set_major_formatter(FuncFormatter(func))
509 515 ax.xaxis.set_major_locator(LinearLocator(6))
510 516
511 517 ax.set_ylabel(self.ylabel)
512 518
513 519 # if self.xmin is None:
514 520 # xmin = self.min_time
515 521 # else:
516 522 # xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
517 523 # datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
518 524
519 525 ax.set_xlim(xmin, xmax)
520 526 ax.firsttime = False
521 527 else:
522 528 ax.collections.remove(ax.collections[0])
523 529 ax.set_xlim(xmin, xmax)
524 530 plot = ax.pcolormesh(x, y, z[n].T,
525 531 vmin=self.zmin,
526 532 vmax=self.zmax,
527 533 cmap=plt.get_cmap(self.colormap)
528 534 )
529 535 ax.set_title('{} {}'.format(self.titles[n],
530 536 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
531 537 size=8)
532 538
533 539 self.saveTime = self.min_time
534 540
535 541
536 542 class PlotCOHData(PlotRTIData):
537 543
538 544 CODE = 'coh'
539 545
540 546 def setup(self):
541 547
542 548 self.ncols = 1
543 549 self.nrows = self.dataOut.nPairs
544 550 self.width = 10
545 551 self.height = 2.2*self.nrows if self.nrows<6 else 12
546 552 if self.nrows==1:
547 553 self.height += 1
548 554 self.ylabel = 'Range [Km]'
549 555 self.titles = ['{} Ch{} * Ch{}'.format(self.CODE.upper(), x[0], x[1]) for x in self.dataOut.pairsList]
550 556
551 557 if self.figure is None:
552 558 self.figure = plt.figure(figsize=(self.width, self.height),
553 559 edgecolor='k',
554 560 facecolor='w')
555 561 else:
556 562 self.figure.clf()
557 563 self.axes = []
558 564
559 565 for n in range(self.nrows):
560 566 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
561 567 ax.firsttime = True
562 568 self.axes.append(ax)
563 569
564 570
565 571 class PlotNoiseData(PlotData):
566 572 CODE = 'noise'
567 573
568 574 def setup(self):
569 575
570 576 self.ncols = 1
571 577 self.nrows = 1
572 578 self.width = 10
573 579 self.height = 3.2
574 580 self.ylabel = 'Intensity [dB]'
575 581 self.titles = ['Noise']
576 582
577 583 if self.figure is None:
578 584 self.figure = plt.figure(figsize=(self.width, self.height),
579 585 edgecolor='k',
580 586 facecolor='w')
581 587 else:
582 588 self.figure.clf()
583 589 self.axes = []
584 590
585 591 self.ax = self.figure.add_subplot(self.nrows, self.ncols, 1)
586 592 self.ax.firsttime = True
587 593
588 594 def plot(self):
589 595
590 596 x = self.times
591 597 xmin = self.min_time
592 598 xmax = xmin+self.xrange*60*60
593 599 if self.ax.firsttime:
594 600 for ch in self.dataOut.channelList:
595 601 y = [self.data[self.CODE][t][ch] for t in self.times]
596 602 self.ax.plot(x, y, lw=1, label='Ch{}'.format(ch))
597 603 self.ax.firsttime = False
598 604 self.ax.xaxis.set_major_formatter(FuncFormatter(func))
599 605 self.ax.xaxis.set_major_locator(LinearLocator(6))
600 606 self.ax.set_ylabel(self.ylabel)
601 607 plt.legend()
602 608 else:
603 609 for ch in self.dataOut.channelList:
604 610 y = [self.data[self.CODE][t][ch] for t in self.times]
605 611 self.ax.lines[ch].set_data(x, y)
606 612
607 613 self.ax.set_xlim(xmin, xmax)
608 614 self.ax.set_ylim(min(y)-5, max(y)+5)
609 615 self.saveTime = self.min_time
610 616
611 617
612 618 class PlotWindProfilerData(PlotRTIData):
619
613 620 CODE = 'wind'
614 621 colormap = 'seismic'
615 622
616 623 def setup(self):
617 624 self.ncols = 1
618 625 self.nrows = self.dataOut.data_output.shape[0]
619 626 self.width = 10
620 627 self.height = 2.2*self.nrows
621 628 self.ylabel = 'Height [Km]'
622 self.titles = ['Zonal' ,'Meridional', 'Vertical']
629 self.titles = ['Zonal Wind' ,'Meridional Wind', 'Vertical Wind']
623 630 self.clabels = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
624 631 self.windFactor = [1, 1, 100]
625 632
626 633 if self.figure is None:
627 634 self.figure = plt.figure(figsize=(self.width, self.height),
628 635 edgecolor='k',
629 636 facecolor='w')
630 637 else:
631 638 self.figure.clf()
632 639 self.axes = []
633 640
634 641 for n in range(self.nrows):
635 642 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
636 643 ax.firsttime = True
637 644 self.axes.append(ax)
638 645
639 646 def plot(self):
640 647
641 648 self.x = np.array(self.times)
642 649 self.y = self.dataOut.heightList
643 650 self.z = []
644 651
645 652 for ch in range(self.nrows):
646 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
653 self.z.append([self.data['output'][t][ch] for t in self.times])
647 654
648 655 self.z = np.array(self.z)
649 656 self.z = numpy.ma.masked_invalid(self.z)
650 657
651 658 cmap=plt.get_cmap(self.colormap)
652 cmap.set_bad('white', 1.)
659 cmap.set_bad('black', 1.)
653 660
654 661 for n, ax in enumerate(self.axes):
655 662 x, y, z = self.fill_gaps(*self.decimate())
656 663 xmin = self.min_time
657 664 xmax = xmin+self.xrange*60*60
658 665 if ax.firsttime:
659 666 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
660 667 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
661 668 self.zmax = self.zmax if self.zmax else numpy.nanmax(abs(self.z[:-1, :]))
662 669 self.zmin = self.zmin if self.zmin else -self.zmax
663 670
664 671 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
665 672 vmin=self.zmin,
666 673 vmax=self.zmax,
667 674 cmap=cmap
668 675 )
669 676 divider = make_axes_locatable(ax)
670 677 cax = divider.new_horizontal(size='2%', pad=0.05)
671 cax.set_ylabel(self.clabels[n])
672 678 self.figure.add_axes(cax)
673 plt.colorbar(plot, cax)
679 cb = plt.colorbar(plot, cax)
680 cb.set_label(self.clabels[n])
674 681 ax.set_ylim(self.ymin, self.ymax)
675 682
676 683 ax.xaxis.set_major_formatter(FuncFormatter(func))
677 684 ax.xaxis.set_major_locator(LinearLocator(6))
678 685
679 686 ax.set_ylabel(self.ylabel)
680 687
681 688 ax.set_xlim(xmin, xmax)
682 689 ax.firsttime = False
683 690 else:
684 691 ax.collections.remove(ax.collections[0])
685 692 ax.set_xlim(xmin, xmax)
686 693 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
687 694 vmin=self.zmin,
688 695 vmax=self.zmax,
689 696 cmap=plt.get_cmap(self.colormap)
690 697 )
691 698 ax.set_title('{} {}'.format(self.titles[n],
692 699 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
693 700 size=8)
694 701
695 702 self.saveTime = self.min_time
696 703
697 704
698 705 class PlotSNRData(PlotRTIData):
699 706 CODE = 'snr'
700 707 colormap = 'jet'
701 708
702 709 class PlotDOPData(PlotRTIData):
703 710 CODE = 'dop'
704 711 colormap = 'jet'
705 712
706 713
707 714 class PlotPHASEData(PlotCOHData):
708 715 CODE = 'phase'
709 716 colormap = 'seismic'
717
718
719 class PlotSkyMapData(PlotData):
720
721 CODE = 'met'
722
723 def setup(self):
724
725 self.ncols = 1
726 self.nrows = 1
727 self.width = 7.2
728 self.height = 7.2
729
730 self.xlabel = 'Zonal Zenith Angle (deg)'
731 self.ylabel = 'Meridional Zenith Angle (deg)'
732
733 if self.figure is None:
734 self.figure = plt.figure(figsize=(self.width, self.height),
735 edgecolor='k',
736 facecolor='w')
737 else:
738 self.figure.clf()
739
740 self.ax = plt.subplot2grid((self.nrows, self.ncols), (0, 0), 1, 1, polar=True)
741 self.ax.firsttime = True
742
743
744 def plot(self):
745
746 arrayParameters = np.concatenate([self.data['param'][t] for t in self.times])
747 error = arrayParameters[:,-1]
748 indValid = numpy.where(error == 0)[0]
749 finalMeteor = arrayParameters[indValid,:]
750 finalAzimuth = finalMeteor[:,3]
751 finalZenith = finalMeteor[:,4]
752
753 x = finalAzimuth*numpy.pi/180
754 y = finalZenith
755
756 if self.ax.firsttime:
757 self.ax.plot = self.ax.plot(x, y, 'bo', markersize=5)[0]
758 self.ax.set_ylim(0,90)
759 self.ax.set_yticks(numpy.arange(0,90,20))
760 self.ax.set_xlabel(self.xlabel)
761 self.ax.set_ylabel(self.ylabel)
762 self.ax.yaxis.labelpad = 40
763 self.ax.firsttime = False
764 else:
765 self.ax.plot.set_data(x, y)
766
767
768 dt1 = datetime.datetime.fromtimestamp(self.min_time).strftime('%y/%m/%d %H:%M:%S')
769 dt2 = datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')
770 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
771 dt2,
772 len(x))
773 self.ax.set_title(title, size=8)
774
775 self.saveTime = self.max_time
@@ -1,346 +1,349
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: jroproc_base.py 1 2012-11-12 18:56:07Z murco $
5 5 '''
6 6 import inspect
7 7 from fuzzywuzzy import process
8 8
9 9 def checkKwargs(method, kwargs):
10 10 currentKwargs = kwargs
11 11 choices = inspect.getargspec(method).args
12 12 try:
13 13 choices.remove('self')
14 14 except Exception as e:
15 15 pass
16 16
17 17 try:
18 18 choices.remove('dataOut')
19 19 except Exception as e:
20 20 pass
21 21
22 22 for kwarg in kwargs:
23 23 fuzz = process.extractOne(kwarg, choices)
24 24 if fuzz is None:
25 25 continue
26 26 if fuzz[1] < 100:
27 27 raise Exception('\x1b[0;32;40mDid you mean {} instead of {} in {}? \x1b[0m'.
28 28 format(fuzz[0], kwarg, method.__self__.__class__.__name__))
29 29
30 30 class ProcessingUnit(object):
31 31
32 32 """
33 33 Esta es la clase base para el procesamiento de datos.
34 34
35 35 Contiene el metodo "call" para llamar operaciones. Las operaciones pueden ser:
36 36 - Metodos internos (callMethod)
37 37 - Objetos del tipo Operation (callObject). Antes de ser llamados, estos objetos
38 38 tienen que ser agreagados con el metodo "add".
39 39
40 40 """
41 41 # objeto de datos de entrada (Voltage, Spectra o Correlation)
42 42 dataIn = None
43 43 dataInList = []
44 44
45 45 # objeto de datos de entrada (Voltage, Spectra o Correlation)
46 46 dataOut = None
47 47
48 48 operations2RunDict = None
49 49
50 50 isConfig = False
51 51
52 52
53 53 def __init__(self, *args, **kwargs):
54 54
55 55 self.dataIn = None
56 56 self.dataInList = []
57 57
58 58 self.dataOut = None
59 59
60 60 self.operations2RunDict = {}
61 61 self.operationKwargs = {}
62 62
63 63 self.isConfig = False
64 64
65 65 self.args = args
66 66 self.kwargs = kwargs
67 67 checkKwargs(self.run, kwargs)
68 68
69 69 def getAllowedArgs(self):
70 70 return inspect.getargspec(self.run).args
71 71
72 72 def addOperationKwargs(self, objId, **kwargs):
73 73 '''
74 74 '''
75 75
76 76 self.operationKwargs[objId] = kwargs
77 77
78 78
79 79 def addOperation(self, opObj, objId):
80 80
81 81 """
82 82 Agrega un objeto del tipo "Operation" (opObj) a la lista de objetos "self.objectList" y retorna el
83 83 identificador asociado a este objeto.
84 84
85 85 Input:
86 86
87 87 object : objeto de la clase "Operation"
88 88
89 89 Return:
90 90
91 91 objId : identificador del objeto, necesario para ejecutar la operacion
92 92 """
93 93
94 94 self.operations2RunDict[objId] = opObj
95 95
96 96 return objId
97 97
98 98 def getOperationObj(self, objId):
99 99
100 100 if objId not in self.operations2RunDict.keys():
101 101 return None
102 102
103 103 return self.operations2RunDict[objId]
104 104
105 105 def operation(self, **kwargs):
106 106
107 107 """
108 108 Operacion directa sobre la data (dataOut.data). Es necesario actualizar los valores de los
109 109 atributos del objeto dataOut
110 110
111 111 Input:
112 112
113 113 **kwargs : Diccionario de argumentos de la funcion a ejecutar
114 114 """
115 115
116 116 raise NotImplementedError
117 117
118 118 def callMethod(self, name, opId):
119 119
120 120 """
121 121 Ejecuta el metodo con el nombre "name" y con argumentos **kwargs de la propia clase.
122 122
123 123 Input:
124 124 name : nombre del metodo a ejecutar
125 125
126 126 **kwargs : diccionario con los nombres y valores de la funcion a ejecutar.
127 127
128 128 """
129 129
130 130 #Checking the inputs
131 131 if name == 'run':
132 132
133 133 if not self.checkInputs():
134 134 self.dataOut.flagNoData = True
135 135 return False
136 136 else:
137 137 #Si no es un metodo RUN la entrada es la misma dataOut (interna)
138 138 if self.dataOut is not None and self.dataOut.isEmpty():
139 139 return False
140 140
141 141 #Getting the pointer to method
142 142 methodToCall = getattr(self, name)
143 143
144 144 #Executing the self method
145 145
146 146 if hasattr(self, 'mp'):
147 147 if name=='run':
148 148 if self.mp is False:
149 149 self.mp = True
150 150 self.start()
151 151 else:
152 self.operationKwargs[opId]['parent'] = self.kwargs
152 153 methodToCall(**self.operationKwargs[opId])
153 154 else:
154 155 if name=='run':
155 156 methodToCall(**self.kwargs)
156 157 else:
157 158 methodToCall(**self.operationKwargs[opId])
158 159
159 160 if self.dataOut is None:
160 161 return False
161 162
162 163 if self.dataOut.isEmpty():
163 164 return False
164 165
165 166 return True
166 167
167 168 def callObject(self, objId):
168 169
169 170 """
170 171 Ejecuta la operacion asociada al identificador del objeto "objId"
171 172
172 173 Input:
173 174
174 175 objId : identificador del objeto a ejecutar
175 176
176 177 **kwargs : diccionario con los nombres y valores de la funcion a ejecutar.
177 178
178 179 Return:
179 180
180 181 None
181 182 """
182 183
183 184 if self.dataOut is not None and self.dataOut.isEmpty():
184 185 return False
185 186
186 187 externalProcObj = self.operations2RunDict[objId]
187 188
188 189 if hasattr(externalProcObj, 'mp'):
189 190 if externalProcObj.mp is False:
191 externalProcObj.kwargs['parent'] = self.kwargs
190 192 self.operationKwargs[objId] = externalProcObj.kwargs
191 193 externalProcObj.mp = True
192 194 externalProcObj.start()
193 195 else:
194 196 externalProcObj.run(self.dataOut, **externalProcObj.kwargs)
195 197 self.operationKwargs[objId] = externalProcObj.kwargs
196 198
199
197 200 return True
198 201
199 202 def call(self, opType, opName=None, opId=None):
200 203
201 204 """
202 205 Return True si ejecuta la operacion interna nombrada "opName" o la operacion externa
203 206 identificada con el id "opId"; con los argumentos "**kwargs".
204 207
205 208 False si la operacion no se ha ejecutado.
206 209
207 210 Input:
208 211
209 212 opType : Puede ser "self" o "external"
210 213
211 214 Depende del tipo de operacion para llamar a:callMethod or callObject:
212 215
213 216 1. If opType = "self": Llama a un metodo propio de esta clase:
214 217
215 218 name_method = getattr(self, name)
216 219 name_method(**kwargs)
217 220
218 221
219 222 2. If opType = "other" o"external": Llama al metodo "run()" de una instancia de la
220 223 clase "Operation" o de un derivado de ella:
221 224
222 225 instanceName = self.operationList[opId]
223 226 instanceName.run(**kwargs)
224 227
225 228 opName : Si la operacion es interna (opType = 'self'), entonces el "opName" sera
226 229 usada para llamar a un metodo interno de la clase Processing
227 230
228 231 opId : Si la operacion es externa (opType = 'other' o 'external), entonces el
229 232 "opId" sera usada para llamar al metodo "run" de la clase Operation
230 233 registrada anteriormente con ese Id
231 234
232 235 Exception:
233 236 Este objeto de tipo Operation debe de haber sido agregado antes con el metodo:
234 237 "addOperation" e identificado con el valor "opId" = el id de la operacion.
235 238 De lo contrario retornara un error del tipo ValueError
236 239
237 240 """
238 241
239 242 if opType == 'self':
240 243
241 244 if not opName:
242 245 raise ValueError, "opName parameter should be defined"
243 246
244 247 sts = self.callMethod(opName, opId)
245 248
246 249 elif opType == 'other' or opType == 'external' or opType == 'plotter':
247 250
248 251 if not opId:
249 252 raise ValueError, "opId parameter should be defined"
250 253
251 254 if opId not in self.operations2RunDict.keys():
252 255 raise ValueError, "Any operation with id=%s has been added" %str(opId)
253 256
254 257 sts = self.callObject(opId)
255 258
256 259 else:
257 260 raise ValueError, "opType should be 'self', 'external' or 'plotter'; and not '%s'" %opType
258 261
259 262 return sts
260 263
261 264 def setInput(self, dataIn):
262 265
263 266 self.dataIn = dataIn
264 267 self.dataInList.append(dataIn)
265 268
266 269 def getOutputObj(self):
267 270
268 271 return self.dataOut
269 272
270 273 def checkInputs(self):
271 274
272 275 for thisDataIn in self.dataInList:
273 276
274 277 if thisDataIn.isEmpty():
275 278 return False
276 279
277 280 return True
278 281
279 282 def setup(self):
280 283
281 284 raise NotImplementedError
282 285
283 286 def run(self):
284 287
285 288 raise NotImplementedError
286 289
287 290 def close(self):
288 291 #Close every thread, queue or any other object here is it is neccesary.
289 292 return
290 293
291 294 class Operation(object):
292 295
293 296 """
294 297 Clase base para definir las operaciones adicionales que se pueden agregar a la clase ProcessingUnit
295 298 y necesiten acumular informacion previa de los datos a procesar. De preferencia usar un buffer de
296 299 acumulacion dentro de esta clase
297 300
298 301 Ejemplo: Integraciones coherentes, necesita la informacion previa de los n perfiles anteriores (bufffer)
299 302
300 303 """
301 304
302 305 __buffer = None
303 306 isConfig = False
304 307
305 308 def __init__(self, **kwargs):
306 309
307 310 self.__buffer = None
308 311 self.isConfig = False
309 312 self.kwargs = kwargs
310 313 checkKwargs(self.run, kwargs)
311 314
312 315 def getAllowedArgs(self):
313 316 return inspect.getargspec(self.run).args
314 317
315 318 def setup(self):
316 319
317 320 self.isConfig = True
318 321
319 322 raise NotImplementedError
320 323
321 324 def run(self, dataIn, **kwargs):
322 325
323 326 """
324 327 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
325 328 atributos del objeto dataIn.
326 329
327 330 Input:
328 331
329 332 dataIn : objeto del tipo JROData
330 333
331 334 Return:
332 335
333 336 None
334 337
335 338 Affected:
336 339 __buffer : buffer de recepcion de datos.
337 340
338 341 """
339 342 if not self.isConfig:
340 343 self.setup(**kwargs)
341 344
342 345 raise NotImplementedError
343 346
344 347 def close(self):
345 348
346 349 pass
@@ -1,456 +1,464
1 1 '''
2 2 @author: Juan C. Espinoza
3 3 '''
4 4
5 5 import time
6 6 import json
7 7 import numpy
8 8 import paho.mqtt.client as mqtt
9 9 import zmq
10 10 from profilehooks import profile
11 11 import datetime
12 12 from zmq.utils.monitor import recv_monitor_message
13 13 from functools import wraps
14 14 from threading import Thread
15 15 from multiprocessing import Process
16 16
17 17 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
18 18
19 19 MAXNUMX = 100
20 20 MAXNUMY = 100
21 21
22 22 class PrettyFloat(float):
23 23 def __repr__(self):
24 24 return '%.2f' % self
25 25
26 26 def roundFloats(obj):
27 27 if isinstance(obj, list):
28 28 return map(roundFloats, obj)
29 29 elif isinstance(obj, float):
30 30 return round(obj, 2)
31 31
32 32 def decimate(z, MAXNUMY):
33 33 # dx = int(len(self.x)/self.__MAXNUMX) + 1
34 34
35 35 dy = int(len(z[0])/MAXNUMY) + 1
36 36
37 37 return z[::, ::dy]
38 38
39 39 class throttle(object):
40 40 """Decorator that prevents a function from being called more than once every
41 41 time period.
42 42 To create a function that cannot be called more than once a minute, but
43 43 will sleep until it can be called:
44 44 @throttle(minutes=1)
45 45 def foo():
46 46 pass
47 47
48 48 for i in range(10):
49 49 foo()
50 50 print "This function has run %s times." % i
51 51 """
52 52
53 53 def __init__(self, seconds=0, minutes=0, hours=0):
54 54 self.throttle_period = datetime.timedelta(
55 55 seconds=seconds, minutes=minutes, hours=hours
56 56 )
57 57
58 58 self.time_of_last_call = datetime.datetime.min
59 59
60 60 def __call__(self, fn):
61 61 @wraps(fn)
62 62 def wrapper(*args, **kwargs):
63 63 now = datetime.datetime.now()
64 64 time_since_last_call = now - self.time_of_last_call
65 65 time_left = self.throttle_period - time_since_last_call
66 66
67 67 if time_left > datetime.timedelta(seconds=0):
68 68 return
69 69
70 70 self.time_of_last_call = datetime.datetime.now()
71 71 return fn(*args, **kwargs)
72 72
73 73 return wrapper
74 74
75 75
76 76 class PublishData(Operation):
77 77 """Clase publish."""
78 78
79 79 def __init__(self, **kwargs):
80 80 """Inicio."""
81 81 Operation.__init__(self, **kwargs)
82 82 self.isConfig = False
83 83 self.client = None
84 84 self.zeromq = None
85 85 self.mqtt = None
86 86
87 87 def on_disconnect(self, client, userdata, rc):
88 88 if rc != 0:
89 89 print("Unexpected disconnection.")
90 90 self.connect()
91 91
92 92 def connect(self):
93 93 print 'trying to connect'
94 94 try:
95 95 self.client.connect(
96 96 host=self.host,
97 97 port=self.port,
98 98 keepalive=60*10,
99 99 bind_address='')
100 100 self.client.loop_start()
101 101 # self.client.publish(
102 102 # self.topic + 'SETUP',
103 103 # json.dumps(setup),
104 104 # retain=True
105 105 # )
106 106 except:
107 107 print "MQTT Conection error."
108 108 self.client = False
109 109
110 110 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
111 111 self.counter = 0
112 112 self.topic = kwargs.get('topic', 'schain')
113 113 self.delay = kwargs.get('delay', 0)
114 114 self.plottype = kwargs.get('plottype', 'spectra')
115 115 self.host = kwargs.get('host', "10.10.10.82")
116 116 self.port = kwargs.get('port', 3000)
117 117 self.clientId = clientId
118 118 self.cnt = 0
119 119 self.zeromq = zeromq
120 120 self.mqtt = kwargs.get('plottype', 0)
121 121 self.client = None
122 122 self.verbose = verbose
123 123 self.dataOut.firstdata = True
124 124 setup = []
125 125 if mqtt is 1:
126 126 self.client = mqtt.Client(
127 127 client_id=self.clientId + self.topic + 'SCHAIN',
128 128 clean_session=True)
129 129 self.client.on_disconnect = self.on_disconnect
130 130 self.connect()
131 131 for plot in self.plottype:
132 132 setup.append({
133 133 'plot': plot,
134 134 'topic': self.topic + plot,
135 135 'title': getattr(self, plot + '_' + 'title', False),
136 136 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
137 137 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
138 138 'xrange': getattr(self, plot + '_' + 'xrange', False),
139 139 'yrange': getattr(self, plot + '_' + 'yrange', False),
140 140 'zrange': getattr(self, plot + '_' + 'zrange', False),
141 141 })
142 142 if zeromq is 1:
143 143 context = zmq.Context()
144 144 self.zmq_socket = context.socket(zmq.PUSH)
145 145 server = kwargs.get('server', 'zmq.pipe')
146 146
147 147 if 'tcp://' in server:
148 148 address = server
149 149 else:
150 150 address = 'ipc:///tmp/%s' % server
151 151
152 152 self.zmq_socket.connect(address)
153 153 time.sleep(1)
154 154
155 155
156 156 def publish_data(self):
157 157 self.dataOut.finished = False
158 158 if self.mqtt is 1:
159 159 yData = self.dataOut.heightList[:2].tolist()
160 160 if self.plottype == 'spectra':
161 161 data = getattr(self.dataOut, 'data_spc')
162 162 z = data/self.dataOut.normFactor
163 163 zdB = 10*numpy.log10(z)
164 164 xlen, ylen = zdB[0].shape
165 165 dx = int(xlen/MAXNUMX) + 1
166 166 dy = int(ylen/MAXNUMY) + 1
167 167 Z = [0 for i in self.dataOut.channelList]
168 168 for i in self.dataOut.channelList:
169 169 Z[i] = zdB[i][::dx, ::dy].tolist()
170 170 payload = {
171 171 'timestamp': self.dataOut.utctime,
172 172 'data': roundFloats(Z),
173 173 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
174 174 'interval': self.dataOut.getTimeInterval(),
175 175 'type': self.plottype,
176 176 'yData': yData
177 177 }
178 178 # print payload
179 179
180 180 elif self.plottype in ('rti', 'power'):
181 181 data = getattr(self.dataOut, 'data_spc')
182 182 z = data/self.dataOut.normFactor
183 183 avg = numpy.average(z, axis=1)
184 184 avgdB = 10*numpy.log10(avg)
185 185 xlen, ylen = z[0].shape
186 186 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
187 187 AVG = [0 for i in self.dataOut.channelList]
188 188 for i in self.dataOut.channelList:
189 189 AVG[i] = avgdB[i][::dy].tolist()
190 190 payload = {
191 191 'timestamp': self.dataOut.utctime,
192 192 'data': roundFloats(AVG),
193 193 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
194 194 'interval': self.dataOut.getTimeInterval(),
195 195 'type': self.plottype,
196 196 'yData': yData
197 197 }
198 198 elif self.plottype == 'noise':
199 199 noise = self.dataOut.getNoise()/self.dataOut.normFactor
200 200 noisedB = 10*numpy.log10(noise)
201 201 payload = {
202 202 'timestamp': self.dataOut.utctime,
203 203 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
204 204 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
205 205 'interval': self.dataOut.getTimeInterval(),
206 206 'type': self.plottype,
207 207 'yData': yData
208 208 }
209 209 elif self.plottype == 'snr':
210 210 data = getattr(self.dataOut, 'data_SNR')
211 211 avgdB = 10*numpy.log10(data)
212 212
213 213 ylen = data[0].size
214 214 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
215 215 AVG = [0 for i in self.dataOut.channelList]
216 216 for i in self.dataOut.channelList:
217 217 AVG[i] = avgdB[i][::dy].tolist()
218 218 payload = {
219 219 'timestamp': self.dataOut.utctime,
220 220 'data': roundFloats(AVG),
221 221 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
222 222 'type': self.plottype,
223 223 'yData': yData
224 224 }
225 225 else:
226 226 print "Tipo de grafico invalido"
227 227 payload = {
228 228 'data': 'None',
229 229 'timestamp': 'None',
230 230 'type': None
231 231 }
232 232 # print 'Publishing data to {}'.format(self.host)
233 233 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
234 234
235 235 if self.zeromq is 1:
236 236 if self.verbose:
237 237 print '[Sending] {} - {}'.format(self.dataOut.type, self.dataOut.datatime)
238 238 self.zmq_socket.send_pyobj(self.dataOut)
239 239 self.dataOut.firstdata = False
240 240
241 241
242 242 def run(self, dataOut, **kwargs):
243 243 self.dataOut = dataOut
244 244 if not self.isConfig:
245 245 self.setup(**kwargs)
246 246 self.isConfig = True
247 247
248 248 self.publish_data()
249 249 time.sleep(self.delay)
250 250
251 251 def close(self):
252 252 if self.zeromq is 1:
253 253 self.dataOut.finished = True
254 254 self.zmq_socket.send_pyobj(self.dataOut)
255 255 self.zmq_socket.close()
256 256 if self.client:
257 257 self.client.loop_stop()
258 258 self.client.disconnect()
259 259
260 260 class ReceiverData(ProcessingUnit, Process):
261 261
262 262 throttle_value = 5
263 263
264 264 def __init__(self, **kwargs):
265 265
266 266 ProcessingUnit.__init__(self, **kwargs)
267 267 Process.__init__(self)
268 268 self.mp = False
269 269 self.isConfig = False
270 270 self.isWebConfig = False
271 271 self.plottypes =[]
272 272 self.connections = 0
273 273 server = kwargs.get('server', 'zmq.pipe')
274 274 plot_server = kwargs.get('plot_server', 'zmq.web')
275 275 if 'tcp://' in server:
276 276 address = server
277 277 else:
278 278 address = 'ipc:///tmp/%s' % server
279 279
280 280 if 'tcp://' in plot_server:
281 281 plot_address = plot_server
282 282 else:
283 283 plot_address = 'ipc:///tmp/%s' % plot_server
284 284
285 285 self.address = address
286 286 self.plot_address = plot_address
287 287 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
288 288 self.realtime = kwargs.get('realtime', False)
289 289 self.throttle_value = kwargs.get('throttle', 5)
290 290 self.sendData = self.initThrottle(self.throttle_value)
291 291 self.setup()
292 292
293 293 def setup(self):
294 294
295 295 self.data = {}
296 296 self.data['times'] = []
297 297 for plottype in self.plottypes:
298 298 self.data[plottype] = {}
299 299 self.data['noise'] = {}
300 300 self.data['throttle'] = self.throttle_value
301 301 self.data['ENDED'] = False
302 302 self.isConfig = True
303 303 self.data_web = {}
304 304
305 305 def event_monitor(self, monitor):
306 306
307 307 events = {}
308 308
309 309 for name in dir(zmq):
310 310 if name.startswith('EVENT_'):
311 311 value = getattr(zmq, name)
312 312 events[value] = name
313 313
314 314 while monitor.poll():
315 315 evt = recv_monitor_message(monitor)
316 316 if evt['event'] == 32:
317 317 self.connections += 1
318 318 if evt['event'] == 512:
319 319 pass
320 320 if self.connections == 0 and self.started is True:
321 321 self.ended = True
322 322
323 323 evt.update({'description': events[evt['event']]})
324 324
325 325 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
326 326 break
327 327 monitor.close()
328 328 print("event monitor thread done!")
329 329
330 330 def initThrottle(self, throttle_value):
331 331
332 332 @throttle(seconds=throttle_value)
333 333 def sendDataThrottled(fn_sender, data):
334 334 fn_sender(data)
335 335
336 336 return sendDataThrottled
337 337
338 338
339 339 def send(self, data):
340 340 # print '[sending] data=%s size=%s' % (data.keys(), len(data['times']))
341 341 self.sender.send_pyobj(data)
342 342
343 343
344 344 def update(self):
345 345 t = self.dataOut.utctime
346 346
347 347 if t in self.data['times']:
348 348 return
349 349
350 350 self.data['times'].append(t)
351 351 self.data['dataOut'] = self.dataOut
352 352
353 353 for plottype in self.plottypes:
354 354 if plottype == 'spc':
355 355 z = self.dataOut.data_spc/self.dataOut.normFactor
356 356 self.data[plottype] = 10*numpy.log10(z)
357 357 self.data['noise'][t] = 10*numpy.log10(self.dataOut.getNoise()/self.dataOut.normFactor)
358 358 if plottype == 'cspc':
359 359 jcoherence = self.dataOut.data_cspc/numpy.sqrt(self.dataOut.data_spc*self.dataOut.data_spc)
360 360 self.data['cspc_coh'] = numpy.abs(jcoherence)
361 361 self.data['cspc_phase'] = numpy.arctan2(jcoherence.imag, jcoherence.real)*180/numpy.pi
362 362 if plottype == 'rti':
363 363 self.data[plottype][t] = self.dataOut.getPower()
364 364 if plottype == 'snr':
365 365 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_SNR)
366 366 if plottype == 'dop':
367 367 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_DOP)
368 368 if plottype == 'mean':
369 369 self.data[plottype][t] = self.dataOut.data_MEAN
370 370 if plottype == 'std':
371 371 self.data[plottype][t] = self.dataOut.data_STD
372 372 if plottype == 'coh':
373 373 self.data[plottype][t] = self.dataOut.getCoherence()
374 374 if plottype == 'phase':
375 375 self.data[plottype][t] = self.dataOut.getCoherence(phase=True)
376 if plottype == 'wind':
376 if plottype == 'output':
377 377 self.data[plottype][t] = self.dataOut.data_output
378 if plottype == 'param':
379 self.data[plottype][t] = self.dataOut.data_param
378 380 if self.realtime:
379 381 self.data_web['timestamp'] = t
380 382 if plottype == 'spc':
381 383 self.data_web[plottype] = roundFloats(decimate(self.data[plottype]).tolist())
382 384 elif plottype == 'cspc':
383 385 self.data_web['cspc_coh'] = roundFloats(decimate(self.data['cspc_coh']).tolist())
384 386 self.data_web['cspc_phase'] = roundFloats(decimate(self.data['cspc_phase']).tolist())
385 387 elif plottype == 'noise':
386 388 self.data_web['noise'] = roundFloats(self.data['noise'][t].tolist())
387 389 else:
388 390 self.data_web[plottype] = roundFloats(decimate(self.data[plottype][t]).tolist())
389 391 self.data_web['interval'] = self.dataOut.getTimeInterval()
390 392 self.data_web['type'] = plottype
391 393
392 394 def run(self):
393 395
394 396 print '[Starting] {} from {}'.format(self.name, self.address)
395 397
396 398 self.context = zmq.Context()
397 399 self.receiver = self.context.socket(zmq.PULL)
398 400 self.receiver.bind(self.address)
399 401 monitor = self.receiver.get_monitor_socket()
400 402 self.sender = self.context.socket(zmq.PUB)
401 403 if self.realtime:
402 404 self.sender_web = self.context.socket(zmq.PUB)
403 405 self.sender_web.connect(self.plot_address)
404 406 time.sleep(1)
407
408 if 'server' in self.kwargs:
409 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
410 else:
405 411 self.sender.bind("ipc:///tmp/zmq.plots")
412
406 413 time.sleep(3)
414
407 415 t = Thread(target=self.event_monitor, args=(monitor,))
408 416 t.start()
409 417
410 418 while True:
411 419 self.dataOut = self.receiver.recv_pyobj()
412 420 # print '[Receiving] {} - {}'.format(self.dataOut.type,
413 421 # self.dataOut.datatime.ctime())
414 422
415 423 self.update()
416 424
417 425 if self.dataOut.firstdata is True:
418 426 self.data['STARTED'] = True
419 427
420 428 if self.dataOut.finished is True:
421 429 self.send(self.data)
422 430 self.connections -= 1
423 431 if self.connections == 0 and self.started:
424 432 self.ended = True
425 433 self.data['ENDED'] = True
426 434 self.send(self.data)
427 435 self.setup()
428 436 self.started = False
429 437 else:
430 438 if self.realtime:
431 439 self.send(self.data)
432 440 self.sender_web.send_string(json.dumps(self.data_web))
433 441 else:
434 442 self.sendData(self.send, self.data)
435 443 self.started = True
436 444
437 445 self.data['STARTED'] = False
438 446 return
439 447
440 448 def sendToWeb(self):
441 449
442 450 if not self.isWebConfig:
443 451 context = zmq.Context()
444 452 sender_web_config = context.socket(zmq.PUB)
445 453 if 'tcp://' in self.plot_address:
446 454 dum, address, port = self.plot_address.split(':')
447 455 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
448 456 else:
449 457 conf_address = self.plot_address + '.config'
450 458 sender_web_config.bind(conf_address)
451 459 time.sleep(1)
452 460 for kwargs in self.operationKwargs.values():
453 461 if 'plot' in kwargs:
454 462 print '[Sending] Config data to web for {}'.format(kwargs['code'].upper())
455 463 sender_web_config.send_string(json.dumps(kwargs))
456 464 self.isWebConfig = True
General Comments 0
You need to be logged in to leave comments. Login now