##// END OF EJS Templates
Fix sending data to server in plots
Juan C. Espinoza -
r1299:d2ef58649fbd
parent child
Show More
@@ -1,1386 +1,1387
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 import schainpy.admin
13 13 from schainpy.utils import log
14 14 from .jroheaderIO import SystemHeader, RadarControllerHeader
15 15 from schainpy.model.data import _noise
16 16
17 17
18 18 def getNumpyDtype(dataTypeCode):
19 19
20 20 if dataTypeCode == 0:
21 21 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
22 22 elif dataTypeCode == 1:
23 23 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
24 24 elif dataTypeCode == 2:
25 25 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
26 26 elif dataTypeCode == 3:
27 27 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
28 28 elif dataTypeCode == 4:
29 29 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
30 30 elif dataTypeCode == 5:
31 31 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
32 32 else:
33 33 raise ValueError('dataTypeCode was not defined')
34 34
35 35 return numpyDtype
36 36
37 37
38 38 def getDataTypeCode(numpyDtype):
39 39
40 40 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
41 41 datatype = 0
42 42 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
43 43 datatype = 1
44 44 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
45 45 datatype = 2
46 46 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
47 47 datatype = 3
48 48 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
49 49 datatype = 4
50 50 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
51 51 datatype = 5
52 52 else:
53 53 datatype = None
54 54
55 55 return datatype
56 56
57 57
58 58 def hildebrand_sekhon(data, navg):
59 59 """
60 60 This method is for the objective determination of the noise level in Doppler spectra. This
61 61 implementation technique is based on the fact that the standard deviation of the spectral
62 62 densities is equal to the mean spectral density for white Gaussian noise
63 63
64 64 Inputs:
65 65 Data : heights
66 66 navg : numbers of averages
67 67
68 68 Return:
69 69 mean : noise's level
70 70 """
71 71
72 72 sortdata = numpy.sort(data, axis=None)
73 73 '''
74 74 lenOfData = len(sortdata)
75 75 nums_min = lenOfData*0.2
76 76
77 77 if nums_min <= 5:
78 78
79 79 nums_min = 5
80 80
81 81 sump = 0.
82 82 sumq = 0.
83 83
84 84 j = 0
85 85 cont = 1
86 86
87 87 while((cont == 1)and(j < lenOfData)):
88 88
89 89 sump += sortdata[j]
90 90 sumq += sortdata[j]**2
91 91
92 92 if j > nums_min:
93 93 rtest = float(j)/(j-1) + 1.0/navg
94 94 if ((sumq*j) > (rtest*sump**2)):
95 95 j = j - 1
96 96 sump = sump - sortdata[j]
97 97 sumq = sumq - sortdata[j]**2
98 98 cont = 0
99 99
100 100 j += 1
101 101
102 102 lnoise = sump / j
103 103 '''
104 104 return _noise.hildebrand_sekhon(sortdata, navg)
105 105
106 106
107 107 class Beam:
108 108
109 109 def __init__(self):
110 110 self.codeList = []
111 111 self.azimuthList = []
112 112 self.zenithList = []
113 113
114 114
115 115 class GenericData(object):
116 116
117 117 flagNoData = True
118 118
119 119 def copy(self, inputObj=None):
120 120
121 121 if inputObj == None:
122 122 return copy.deepcopy(self)
123 123
124 124 for key in list(inputObj.__dict__.keys()):
125 125
126 126 attribute = inputObj.__dict__[key]
127 127
128 128 # If this attribute is a tuple or list
129 129 if type(inputObj.__dict__[key]) in (tuple, list):
130 130 self.__dict__[key] = attribute[:]
131 131 continue
132 132
133 133 # If this attribute is another object or instance
134 134 if hasattr(attribute, '__dict__'):
135 135 self.__dict__[key] = attribute.copy()
136 136 continue
137 137
138 138 self.__dict__[key] = inputObj.__dict__[key]
139 139
140 140 def deepcopy(self):
141 141
142 142 return copy.deepcopy(self)
143 143
144 144 def isEmpty(self):
145 145
146 146 return self.flagNoData
147 147
148 148 def isReady(self):
149 149
150 150 return not self.flagNoData
151 151
152 152
153 153 class JROData(GenericData):
154 154
155 155 # m_BasicHeader = BasicHeader()
156 156 # m_ProcessingHeader = ProcessingHeader()
157 157
158 158 systemHeaderObj = SystemHeader()
159 159 radarControllerHeaderObj = RadarControllerHeader()
160 160 # data = None
161 161 type = None
162 162 datatype = None # dtype but in string
163 163 # dtype = None
164 164 # nChannels = None
165 165 # nHeights = None
166 166 nProfiles = None
167 167 heightList = None
168 168 channelList = None
169 169 flagDiscontinuousBlock = False
170 170 useLocalTime = False
171 171 utctime = None
172 172 timeZone = None
173 173 dstFlag = None
174 174 errorCount = None
175 175 blocksize = None
176 176 # nCode = None
177 177 # nBaud = None
178 178 # code = None
179 179 flagDecodeData = False # asumo q la data no esta decodificada
180 180 flagDeflipData = False # asumo q la data no esta sin flip
181 181 flagShiftFFT = False
182 182 # ippSeconds = None
183 183 # timeInterval = None
184 184 nCohInt = None
185 185 # noise = None
186 186 windowOfFilter = 1
187 187 # Speed of ligth
188 188 C = 3e8
189 189 frequency = 49.92e6
190 190 realtime = False
191 191 beacon_heiIndexList = None
192 192 last_block = None
193 193 blocknow = None
194 194 azimuth = None
195 195 zenith = None
196 196 beam = Beam()
197 197 profileIndex = None
198 198 error = None
199 199 data = None
200 200 nmodes = None
201 201
202 202 def __str__(self):
203 203
204 204 return '{} - {}'.format(self.type, self.getDatatime())
205 205
206 206 def getNoise(self):
207 207
208 208 raise NotImplementedError
209 209
210 210 def getNChannels(self):
211 211
212 212 return len(self.channelList)
213 213
214 214 def getChannelIndexList(self):
215 215
216 216 return list(range(self.nChannels))
217 217
218 218 def getNHeights(self):
219 219
220 220 return len(self.heightList)
221 221
222 222 def getHeiRange(self, extrapoints=0):
223 223
224 224 heis = self.heightList
225 225 # deltah = self.heightList[1] - self.heightList[0]
226 226 #
227 227 # heis.append(self.heightList[-1])
228 228
229 229 return heis
230 230
231 231 def getDeltaH(self):
232 232
233 233 delta = self.heightList[1] - self.heightList[0]
234 234
235 235 return delta
236 236
237 237 def getltctime(self):
238 238
239 239 if self.useLocalTime:
240 240 return self.utctime - self.timeZone * 60
241 241
242 242 return self.utctime
243 243
244 244 def getDatatime(self):
245 245
246 246 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
247 247 return datatimeValue
248 248
249 249 def getTimeRange(self):
250 250
251 251 datatime = []
252 252
253 253 datatime.append(self.ltctime)
254 254 datatime.append(self.ltctime + self.timeInterval + 1)
255 255
256 256 datatime = numpy.array(datatime)
257 257
258 258 return datatime
259 259
260 260 def getFmaxTimeResponse(self):
261 261
262 262 period = (10**-6) * self.getDeltaH() / (0.15)
263 263
264 264 PRF = 1. / (period * self.nCohInt)
265 265
266 266 fmax = PRF
267 267
268 268 return fmax
269 269
270 270 def getFmax(self):
271 271 PRF = 1. / (self.ippSeconds * self.nCohInt)
272 272
273 273 fmax = PRF
274 274 return fmax
275 275
276 276 def getVmax(self):
277 277
278 278 _lambda = self.C / self.frequency
279 279
280 280 vmax = self.getFmax() * _lambda / 2
281 281
282 282 return vmax
283 283
284 284 def get_ippSeconds(self):
285 285 '''
286 286 '''
287 287 return self.radarControllerHeaderObj.ippSeconds
288 288
289 289 def set_ippSeconds(self, ippSeconds):
290 290 '''
291 291 '''
292 292
293 293 self.radarControllerHeaderObj.ippSeconds = ippSeconds
294 294
295 295 return
296 296
297 297 def get_dtype(self):
298 298 '''
299 299 '''
300 300 return getNumpyDtype(self.datatype)
301 301
302 302 def set_dtype(self, numpyDtype):
303 303 '''
304 304 '''
305 305
306 306 self.datatype = getDataTypeCode(numpyDtype)
307 307
308 308 def get_code(self):
309 309 '''
310 310 '''
311 311 return self.radarControllerHeaderObj.code
312 312
313 313 def set_code(self, code):
314 314 '''
315 315 '''
316 316 self.radarControllerHeaderObj.code = code
317 317
318 318 return
319 319
320 320 def get_ncode(self):
321 321 '''
322 322 '''
323 323 return self.radarControllerHeaderObj.nCode
324 324
325 325 def set_ncode(self, nCode):
326 326 '''
327 327 '''
328 328 self.radarControllerHeaderObj.nCode = nCode
329 329
330 330 return
331 331
332 332 def get_nbaud(self):
333 333 '''
334 334 '''
335 335 return self.radarControllerHeaderObj.nBaud
336 336
337 337 def set_nbaud(self, nBaud):
338 338 '''
339 339 '''
340 340 self.radarControllerHeaderObj.nBaud = nBaud
341 341
342 342 return
343 343
344 344 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
345 345 channelIndexList = property(
346 346 getChannelIndexList, "I'm the 'channelIndexList' property.")
347 347 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
348 348 #noise = property(getNoise, "I'm the 'nHeights' property.")
349 349 datatime = property(getDatatime, "I'm the 'datatime' property")
350 350 ltctime = property(getltctime, "I'm the 'ltctime' property")
351 351 ippSeconds = property(get_ippSeconds, set_ippSeconds)
352 352 dtype = property(get_dtype, set_dtype)
353 353 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
354 354 code = property(get_code, set_code)
355 355 nCode = property(get_ncode, set_ncode)
356 356 nBaud = property(get_nbaud, set_nbaud)
357 357
358 358
359 359 class Voltage(JROData):
360 360
361 361 # data es un numpy array de 2 dmensiones (canales, alturas)
362 362 data = None
363 363
364 364 def __init__(self):
365 365 '''
366 366 Constructor
367 367 '''
368 368
369 369 self.useLocalTime = True
370 370 self.radarControllerHeaderObj = RadarControllerHeader()
371 371 self.systemHeaderObj = SystemHeader()
372 372 self.type = "Voltage"
373 373 self.data = None
374 374 # self.dtype = None
375 375 # self.nChannels = 0
376 376 # self.nHeights = 0
377 377 self.nProfiles = None
378 378 self.heightList = None
379 379 self.channelList = None
380 380 # self.channelIndexList = None
381 381 self.flagNoData = True
382 382 self.flagDiscontinuousBlock = False
383 383 self.utctime = None
384 384 self.timeZone = None
385 385 self.dstFlag = None
386 386 self.errorCount = None
387 387 self.nCohInt = None
388 388 self.blocksize = None
389 389 self.flagDecodeData = False # asumo q la data no esta decodificada
390 390 self.flagDeflipData = False # asumo q la data no esta sin flip
391 391 self.flagShiftFFT = False
392 392 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
393 393 self.profileIndex = 0
394 394
395 395 def getNoisebyHildebrand(self, channel=None):
396 396 """
397 397 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
398 398
399 399 Return:
400 400 noiselevel
401 401 """
402 402
403 403 if channel != None:
404 404 data = self.data[channel]
405 405 nChannels = 1
406 406 else:
407 407 data = self.data
408 408 nChannels = self.nChannels
409 409
410 410 noise = numpy.zeros(nChannels)
411 411 power = data * numpy.conjugate(data)
412 412
413 413 for thisChannel in range(nChannels):
414 414 if nChannels == 1:
415 415 daux = power[:].real
416 416 else:
417 417 daux = power[thisChannel, :].real
418 418 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
419 419
420 420 return noise
421 421
422 422 def getNoise(self, type=1, channel=None):
423 423
424 424 if type == 1:
425 425 noise = self.getNoisebyHildebrand(channel)
426 426
427 427 return noise
428 428
429 429 def getPower(self, channel=None):
430 430
431 431 if channel != None:
432 432 data = self.data[channel]
433 433 else:
434 434 data = self.data
435 435
436 436 power = data * numpy.conjugate(data)
437 437 powerdB = 10 * numpy.log10(power.real)
438 438 powerdB = numpy.squeeze(powerdB)
439 439
440 440 return powerdB
441 441
442 442 def getTimeInterval(self):
443 443
444 444 timeInterval = self.ippSeconds * self.nCohInt
445 445
446 446 return timeInterval
447 447
448 448 noise = property(getNoise, "I'm the 'nHeights' property.")
449 449 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
450 450
451 451
452 452 class Spectra(JROData):
453 453
454 454 # data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
455 455 data_spc = None
456 456 # data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
457 457 data_cspc = None
458 458 # data dc es un numpy array de 2 dmensiones (canales, alturas)
459 459 data_dc = None
460 460 # data power
461 461 data_pwr = None
462 462 nFFTPoints = None
463 463 # nPairs = None
464 464 pairsList = None
465 465 nIncohInt = None
466 466 wavelength = None # Necesario para cacular el rango de velocidad desde la frecuencia
467 467 nCohInt = None # se requiere para determinar el valor de timeInterval
468 468 ippFactor = None
469 469 profileIndex = 0
470 470 plotting = "spectra"
471 471
472 472 def __init__(self):
473 473 '''
474 474 Constructor
475 475 '''
476 476
477 477 self.useLocalTime = True
478 478 self.radarControllerHeaderObj = RadarControllerHeader()
479 479 self.systemHeaderObj = SystemHeader()
480 480 self.type = "Spectra"
481 481 # self.data = None
482 482 # self.dtype = None
483 483 # self.nChannels = 0
484 484 # self.nHeights = 0
485 485 self.nProfiles = None
486 486 self.heightList = None
487 487 self.channelList = None
488 488 # self.channelIndexList = None
489 489 self.pairsList = None
490 490 self.flagNoData = True
491 491 self.flagDiscontinuousBlock = False
492 492 self.utctime = None
493 493 self.nCohInt = None
494 494 self.nIncohInt = None
495 495 self.blocksize = None
496 496 self.nFFTPoints = None
497 497 self.wavelength = None
498 498 self.flagDecodeData = False # asumo q la data no esta decodificada
499 499 self.flagDeflipData = False # asumo q la data no esta sin flip
500 500 self.flagShiftFFT = False
501 501 self.ippFactor = 1
502 502 #self.noise = None
503 503 self.beacon_heiIndexList = []
504 504 self.noise_estimation = None
505 505
506 506 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
507 507 """
508 508 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
509 509
510 510 Return:
511 511 noiselevel
512 512 """
513 513
514 514 noise = numpy.zeros(self.nChannels)
515 515
516 516 for channel in range(self.nChannels):
517 517 daux = self.data_spc[channel,
518 518 xmin_index:xmax_index, ymin_index:ymax_index]
519 519 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
520 520
521 521 return noise
522 522
523 523 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
524 524
525 525 if self.noise_estimation is not None:
526 526 # this was estimated by getNoise Operation defined in jroproc_spectra.py
527 527 return self.noise_estimation
528 528 else:
529 529 noise = self.getNoisebyHildebrand(
530 530 xmin_index, xmax_index, ymin_index, ymax_index)
531 531 return noise
532 532
533 533 def getFreqRangeTimeResponse(self, extrapoints=0):
534 534
535 535 deltafreq = self.getFmaxTimeResponse() / (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 getAcfRange(self, extrapoints=0):
541 541
542 542 deltafreq = 10. / (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 getFreqRange(self, extrapoints=0):
548 548
549 549 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
550 550 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
551 551
552 552 return freqrange
553 553
554 554 def getVelRange(self, extrapoints=0):
555 555
556 556 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
557 557 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
558 558
559 559 if self.nmodes:
560 560 return velrange/self.nmodes
561 561 else:
562 562 return velrange
563 563
564 564 def getNPairs(self):
565 565
566 566 return len(self.pairsList)
567 567
568 568 def getPairsIndexList(self):
569 569
570 570 return list(range(self.nPairs))
571 571
572 572 def getNormFactor(self):
573 573
574 574 pwcode = 1
575 575
576 576 if self.flagDecodeData:
577 577 pwcode = numpy.sum(self.code[0]**2)
578 578 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
579 579 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
580 580
581 581 return normFactor
582 582
583 583 def getFlagCspc(self):
584 584
585 585 if self.data_cspc is None:
586 586 return True
587 587
588 588 return False
589 589
590 590 def getFlagDc(self):
591 591
592 592 if self.data_dc is None:
593 593 return True
594 594
595 595 return False
596 596
597 597 def getTimeInterval(self):
598 598
599 599 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
600 600 if self.nmodes:
601 601 return self.nmodes*timeInterval
602 602 else:
603 603 return timeInterval
604 604
605 605 def getPower(self):
606 606
607 607 factor = self.normFactor
608 608 z = self.data_spc / factor
609 609 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
610 610 avg = numpy.average(z, axis=1)
611 611
612 612 return 10 * numpy.log10(avg)
613 613
614 614 def getCoherence(self, pairsList=None, phase=False):
615 615
616 616 z = []
617 617 if pairsList is None:
618 618 pairsIndexList = self.pairsIndexList
619 619 else:
620 620 pairsIndexList = []
621 621 for pair in pairsList:
622 622 if pair not in self.pairsList:
623 623 raise ValueError("Pair %s is not in dataOut.pairsList" % (
624 624 pair))
625 625 pairsIndexList.append(self.pairsList.index(pair))
626 626 for i in range(len(pairsIndexList)):
627 627 pair = self.pairsList[pairsIndexList[i]]
628 628 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
629 629 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
630 630 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
631 631 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
632 632 if phase:
633 633 data = numpy.arctan2(avgcoherenceComplex.imag,
634 634 avgcoherenceComplex.real) * 180 / numpy.pi
635 635 else:
636 636 data = numpy.abs(avgcoherenceComplex)
637 637
638 638 z.append(data)
639 639
640 640 return numpy.array(z)
641 641
642 642 def setValue(self, value):
643 643
644 644 print("This property should not be initialized")
645 645
646 646 return
647 647
648 648 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
649 649 pairsIndexList = property(
650 650 getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
651 651 normFactor = property(getNormFactor, setValue,
652 652 "I'm the 'getNormFactor' property.")
653 653 flag_cspc = property(getFlagCspc, setValue)
654 654 flag_dc = property(getFlagDc, setValue)
655 655 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
656 656 timeInterval = property(getTimeInterval, setValue,
657 657 "I'm the 'timeInterval' property")
658 658
659 659
660 660 class SpectraHeis(Spectra):
661 661
662 662 data_spc = None
663 663 data_cspc = None
664 664 data_dc = None
665 665 nFFTPoints = None
666 666 # nPairs = None
667 667 pairsList = None
668 668 nCohInt = None
669 669 nIncohInt = None
670 670
671 671 def __init__(self):
672 672
673 673 self.radarControllerHeaderObj = RadarControllerHeader()
674 674
675 675 self.systemHeaderObj = SystemHeader()
676 676
677 677 self.type = "SpectraHeis"
678 678
679 679 # self.dtype = None
680 680
681 681 # self.nChannels = 0
682 682
683 683 # self.nHeights = 0
684 684
685 685 self.nProfiles = None
686 686
687 687 self.heightList = None
688 688
689 689 self.channelList = None
690 690
691 691 # self.channelIndexList = None
692 692
693 693 self.flagNoData = True
694 694
695 695 self.flagDiscontinuousBlock = False
696 696
697 697 # self.nPairs = 0
698 698
699 699 self.utctime = None
700 700
701 701 self.blocksize = None
702 702
703 703 self.profileIndex = 0
704 704
705 705 self.nCohInt = 1
706 706
707 707 self.nIncohInt = 1
708 708
709 709 def getNormFactor(self):
710 710 pwcode = 1
711 711 if self.flagDecodeData:
712 712 pwcode = numpy.sum(self.code[0]**2)
713 713
714 714 normFactor = self.nIncohInt * self.nCohInt * pwcode
715 715
716 716 return normFactor
717 717
718 718 def getTimeInterval(self):
719 719
720 720 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
721 721
722 722 return timeInterval
723 723
724 724 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
725 725 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
726 726
727 727
728 728 class Fits(JROData):
729 729
730 730 heightList = None
731 731 channelList = None
732 732 flagNoData = True
733 733 flagDiscontinuousBlock = False
734 734 useLocalTime = False
735 735 utctime = None
736 736 timeZone = None
737 737 # ippSeconds = None
738 738 # timeInterval = None
739 739 nCohInt = None
740 740 nIncohInt = None
741 741 noise = None
742 742 windowOfFilter = 1
743 743 # Speed of ligth
744 744 C = 3e8
745 745 frequency = 49.92e6
746 746 realtime = False
747 747
748 748 def __init__(self):
749 749
750 750 self.type = "Fits"
751 751
752 752 self.nProfiles = None
753 753
754 754 self.heightList = None
755 755
756 756 self.channelList = None
757 757
758 758 # self.channelIndexList = None
759 759
760 760 self.flagNoData = True
761 761
762 762 self.utctime = None
763 763
764 764 self.nCohInt = 1
765 765
766 766 self.nIncohInt = 1
767 767
768 768 self.useLocalTime = True
769 769
770 770 self.profileIndex = 0
771 771
772 772 # self.utctime = None
773 773 # self.timeZone = None
774 774 # self.ltctime = None
775 775 # self.timeInterval = None
776 776 # self.header = None
777 777 # self.data_header = None
778 778 # self.data = None
779 779 # self.datatime = None
780 780 # self.flagNoData = False
781 781 # self.expName = ''
782 782 # self.nChannels = None
783 783 # self.nSamples = None
784 784 # self.dataBlocksPerFile = None
785 785 # self.comments = ''
786 786 #
787 787
788 788 def getltctime(self):
789 789
790 790 if self.useLocalTime:
791 791 return self.utctime - self.timeZone * 60
792 792
793 793 return self.utctime
794 794
795 795 def getDatatime(self):
796 796
797 797 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
798 798 return datatime
799 799
800 800 def getTimeRange(self):
801 801
802 802 datatime = []
803 803
804 804 datatime.append(self.ltctime)
805 805 datatime.append(self.ltctime + self.timeInterval)
806 806
807 807 datatime = numpy.array(datatime)
808 808
809 809 return datatime
810 810
811 811 def getHeiRange(self):
812 812
813 813 heis = self.heightList
814 814
815 815 return heis
816 816
817 817 def getNHeights(self):
818 818
819 819 return len(self.heightList)
820 820
821 821 def getNChannels(self):
822 822
823 823 return len(self.channelList)
824 824
825 825 def getChannelIndexList(self):
826 826
827 827 return list(range(self.nChannels))
828 828
829 829 def getNoise(self, type=1):
830 830
831 831 #noise = numpy.zeros(self.nChannels)
832 832
833 833 if type == 1:
834 834 noise = self.getNoisebyHildebrand()
835 835
836 836 if type == 2:
837 837 noise = self.getNoisebySort()
838 838
839 839 if type == 3:
840 840 noise = self.getNoisebyWindow()
841 841
842 842 return noise
843 843
844 844 def getTimeInterval(self):
845 845
846 846 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
847 847
848 848 return timeInterval
849 849
850 850 def get_ippSeconds(self):
851 851 '''
852 852 '''
853 853 return self.ipp_sec
854 854
855 855
856 856 datatime = property(getDatatime, "I'm the 'datatime' property")
857 857 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
858 858 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
859 859 channelIndexList = property(
860 860 getChannelIndexList, "I'm the 'channelIndexList' property.")
861 861 noise = property(getNoise, "I'm the 'nHeights' property.")
862 862
863 863 ltctime = property(getltctime, "I'm the 'ltctime' property")
864 864 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
865 865 ippSeconds = property(get_ippSeconds, '')
866 866
867 867 class Correlation(JROData):
868 868
869 869 noise = None
870 870 SNR = None
871 871 #--------------------------------------------------
872 872 mode = None
873 873 split = False
874 874 data_cf = None
875 875 lags = None
876 876 lagRange = None
877 877 pairsList = None
878 878 normFactor = None
879 879 #--------------------------------------------------
880 880 # calculateVelocity = None
881 881 nLags = None
882 882 nPairs = None
883 883 nAvg = None
884 884
885 885 def __init__(self):
886 886 '''
887 887 Constructor
888 888 '''
889 889 self.radarControllerHeaderObj = RadarControllerHeader()
890 890
891 891 self.systemHeaderObj = SystemHeader()
892 892
893 893 self.type = "Correlation"
894 894
895 895 self.data = None
896 896
897 897 self.dtype = None
898 898
899 899 self.nProfiles = None
900 900
901 901 self.heightList = None
902 902
903 903 self.channelList = None
904 904
905 905 self.flagNoData = True
906 906
907 907 self.flagDiscontinuousBlock = False
908 908
909 909 self.utctime = None
910 910
911 911 self.timeZone = None
912 912
913 913 self.dstFlag = None
914 914
915 915 self.errorCount = None
916 916
917 917 self.blocksize = None
918 918
919 919 self.flagDecodeData = False # asumo q la data no esta decodificada
920 920
921 921 self.flagDeflipData = False # asumo q la data no esta sin flip
922 922
923 923 self.pairsList = None
924 924
925 925 self.nPoints = None
926 926
927 927 def getPairsList(self):
928 928
929 929 return self.pairsList
930 930
931 931 def getNoise(self, mode=2):
932 932
933 933 indR = numpy.where(self.lagR == 0)[0][0]
934 934 indT = numpy.where(self.lagT == 0)[0][0]
935 935
936 936 jspectra0 = self.data_corr[:, :, indR, :]
937 937 jspectra = copy.copy(jspectra0)
938 938
939 939 num_chan = jspectra.shape[0]
940 940 num_hei = jspectra.shape[2]
941 941
942 942 freq_dc = jspectra.shape[1] / 2
943 943 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
944 944
945 945 if ind_vel[0] < 0:
946 946 ind_vel[list(range(0, 1))] = ind_vel[list(
947 947 range(0, 1))] + self.num_prof
948 948
949 949 if mode == 1:
950 950 jspectra[:, freq_dc, :] = (
951 951 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
952 952
953 953 if mode == 2:
954 954
955 955 vel = numpy.array([-2, -1, 1, 2])
956 956 xx = numpy.zeros([4, 4])
957 957
958 958 for fil in range(4):
959 959 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
960 960
961 961 xx_inv = numpy.linalg.inv(xx)
962 962 xx_aux = xx_inv[0, :]
963 963
964 964 for ich in range(num_chan):
965 965 yy = jspectra[ich, ind_vel, :]
966 966 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
967 967
968 968 junkid = jspectra[ich, freq_dc, :] <= 0
969 969 cjunkid = sum(junkid)
970 970
971 971 if cjunkid.any():
972 972 jspectra[ich, freq_dc, junkid.nonzero()] = (
973 973 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
974 974
975 975 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
976 976
977 977 return noise
978 978
979 979 def getTimeInterval(self):
980 980
981 981 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
982 982
983 983 return timeInterval
984 984
985 985 def splitFunctions(self):
986 986
987 987 pairsList = self.pairsList
988 988 ccf_pairs = []
989 989 acf_pairs = []
990 990 ccf_ind = []
991 991 acf_ind = []
992 992 for l in range(len(pairsList)):
993 993 chan0 = pairsList[l][0]
994 994 chan1 = pairsList[l][1]
995 995
996 996 # Obteniendo pares de Autocorrelacion
997 997 if chan0 == chan1:
998 998 acf_pairs.append(chan0)
999 999 acf_ind.append(l)
1000 1000 else:
1001 1001 ccf_pairs.append(pairsList[l])
1002 1002 ccf_ind.append(l)
1003 1003
1004 1004 data_acf = self.data_cf[acf_ind]
1005 1005 data_ccf = self.data_cf[ccf_ind]
1006 1006
1007 1007 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1008 1008
1009 1009 def getNormFactor(self):
1010 1010 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1011 1011 acf_pairs = numpy.array(acf_pairs)
1012 1012 normFactor = numpy.zeros((self.nPairs, self.nHeights))
1013 1013
1014 1014 for p in range(self.nPairs):
1015 1015 pair = self.pairsList[p]
1016 1016
1017 1017 ch0 = pair[0]
1018 1018 ch1 = pair[1]
1019 1019
1020 1020 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
1021 1021 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
1022 1022 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
1023 1023
1024 1024 return normFactor
1025 1025
1026 1026 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1027 1027 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1028 1028
1029 1029
1030 1030 class Parameters(Spectra):
1031 1031
1032 1032 experimentInfo = None # Information about the experiment
1033 1033 # Information from previous data
1034 1034 inputUnit = None # Type of data to be processed
1035 1035 operation = None # Type of operation to parametrize
1036 1036 # normFactor = None #Normalization Factor
1037 1037 groupList = None # List of Pairs, Groups, etc
1038 1038 # Parameters
1039 1039 data_param = None # Parameters obtained
1040 1040 data_pre = None # Data Pre Parametrization
1041 1041 data_SNR = None # Signal to Noise Ratio
1042 1042 # heightRange = None #Heights
1043 1043 abscissaList = None # Abscissa, can be velocities, lags or time
1044 1044 # noise = None #Noise Potency
1045 1045 utctimeInit = None # Initial UTC time
1046 1046 paramInterval = None # Time interval to calculate Parameters in seconds
1047 1047 useLocalTime = True
1048 1048 # Fitting
1049 1049 data_error = None # Error of the estimation
1050 1050 constants = None
1051 1051 library = None
1052 1052 # Output signal
1053 1053 outputInterval = None # Time interval to calculate output signal in seconds
1054 1054 data_output = None # Out signal
1055 1055 nAvg = None
1056 1056 noise_estimation = None
1057 1057 GauSPC = None # Fit gaussian SPC
1058 1058
1059 1059 def __init__(self):
1060 1060 '''
1061 1061 Constructor
1062 1062 '''
1063 1063 self.radarControllerHeaderObj = RadarControllerHeader()
1064 1064
1065 1065 self.systemHeaderObj = SystemHeader()
1066 1066
1067 1067 self.type = "Parameters"
1068 1068
1069 1069 def getTimeRange1(self, interval):
1070 1070
1071 1071 datatime = []
1072 1072
1073 1073 if self.useLocalTime:
1074 1074 time1 = self.utctimeInit - self.timeZone * 60
1075 1075 else:
1076 1076 time1 = self.utctimeInit
1077 1077
1078 1078 datatime.append(time1)
1079 1079 datatime.append(time1 + interval)
1080 1080 datatime = numpy.array(datatime)
1081 1081
1082 1082 return datatime
1083 1083
1084 1084 def getTimeInterval(self):
1085 1085
1086 1086 if hasattr(self, 'timeInterval1'):
1087 1087 return self.timeInterval1
1088 1088 else:
1089 1089 return self.paramInterval
1090 1090
1091 1091 def setValue(self, value):
1092 1092
1093 1093 print("This property should not be initialized")
1094 1094
1095 1095 return
1096 1096
1097 1097 def getNoise(self):
1098 1098
1099 1099 return self.spc_noise
1100 1100
1101 1101 timeInterval = property(getTimeInterval)
1102 1102 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
1103 1103
1104 1104
1105 1105 class PlotterData(object):
1106 1106 '''
1107 1107 Object to hold data to be plotted
1108 1108 '''
1109 1109
1110 MAXNUMX = 100
1111 MAXNUMY = 100
1110 MAXNUMX = 200
1111 MAXNUMY = 200
1112 1112
1113 1113 def __init__(self, code, throttle_value, exp_code, buffering=True, snr=False):
1114 1114
1115 1115 self.key = code
1116 1116 self.throttle = throttle_value
1117 1117 self.exp_code = exp_code
1118 1118 self.buffering = buffering
1119 1119 self.ready = False
1120 1120 self.flagNoData = False
1121 1121 self.localtime = False
1122 1122 self.data = {}
1123 1123 self.meta = {}
1124 1124 self.__times = []
1125 1125 self.__heights = []
1126 1126
1127 1127 if 'snr' in code:
1128 1128 self.plottypes = ['snr']
1129 1129 elif code == 'spc':
1130 1130 self.plottypes = ['spc', 'noise', 'rti']
1131 1131 elif code == 'rti':
1132 1132 self.plottypes = ['noise', 'rti']
1133 1133 else:
1134 1134 self.plottypes = [code]
1135 1135
1136 1136 if 'snr' not in self.plottypes and snr:
1137 1137 self.plottypes.append('snr')
1138 1138
1139 1139 for plot in self.plottypes:
1140 1140 self.data[plot] = {}
1141 1141
1142 1142 def __str__(self):
1143 1143 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1144 1144 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
1145 1145
1146 1146 def __len__(self):
1147 1147 return len(self.__times)
1148 1148
1149 1149 def __getitem__(self, key):
1150 1150
1151 1151 if key not in self.data:
1152 1152 raise KeyError(log.error('Missing key: {}'.format(key)))
1153 1153 if 'spc' in key or not self.buffering:
1154 1154 ret = self.data[key]
1155 1155 elif 'scope' in key:
1156 1156 ret = numpy.array(self.data[key][float(self.tm)])
1157 1157 else:
1158 1158 ret = numpy.array([self.data[key][x] for x in self.times])
1159 1159 if ret.ndim > 1:
1160 1160 ret = numpy.swapaxes(ret, 0, 1)
1161 1161 return ret
1162 1162
1163 1163 def __contains__(self, key):
1164 1164 return key in self.data
1165 1165
1166 1166 def setup(self):
1167 1167 '''
1168 1168 Configure object
1169 1169 '''
1170 1170
1171 1171 self.type = ''
1172 1172 self.ready = False
1173 1173 self.data = {}
1174 1174 self.__times = []
1175 1175 self.__heights = []
1176 1176 self.__all_heights = set()
1177 1177 for plot in self.plottypes:
1178 1178 if 'snr' in plot:
1179 1179 plot = 'snr'
1180 1180 elif 'spc_moments' == plot:
1181 1181 plot = 'moments'
1182 1182 self.data[plot] = {}
1183 1183
1184 1184 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data:
1185 1185 self.data['noise'] = {}
1186 1186 self.data['rti'] = {}
1187 1187 if 'noise' not in self.plottypes:
1188 1188 self.plottypes.append('noise')
1189 1189 if 'rti' not in self.plottypes:
1190 1190 self.plottypes.append('rti')
1191 1191
1192 1192 def shape(self, key):
1193 1193 '''
1194 1194 Get the shape of the one-element data for the given key
1195 1195 '''
1196 1196
1197 1197 if len(self.data[key]):
1198 1198 if 'spc' in key or not self.buffering:
1199 1199 return self.data[key].shape
1200 1200 return self.data[key][self.__times[0]].shape
1201 1201 return (0,)
1202 1202
1203 1203 def update(self, dataOut, tm):
1204 1204 '''
1205 1205 Update data object with new dataOut
1206 1206 '''
1207 1207
1208 1208 if tm in self.__times:
1209 1209 return
1210 1210 self.profileIndex = dataOut.profileIndex
1211 1211 self.tm = tm
1212 1212 self.type = dataOut.type
1213 1213 self.parameters = getattr(dataOut, 'parameters', [])
1214 1214
1215 1215 if hasattr(dataOut, 'meta'):
1216 1216 self.meta.update(dataOut.meta)
1217 1217
1218 1218 if hasattr(dataOut, 'pairsList'):
1219 1219 self.pairs = dataOut.pairsList
1220 1220
1221 1221 self.interval = dataOut.getTimeInterval()
1222 1222 self.localtime = dataOut.useLocalTime
1223 1223 if True in ['spc' in ptype for ptype in self.plottypes]:
1224 1224 self.xrange = (dataOut.getFreqRange(1)/1000.,
1225 1225 dataOut.getAcfRange(1), dataOut.getVelRange(1))
1226 1226 self.factor = dataOut.normFactor
1227 1227 self.__heights.append(dataOut.heightList)
1228 1228 self.__all_heights.update(dataOut.heightList)
1229 1229 self.__times.append(tm)
1230 1230
1231 1231 for plot in self.plottypes:
1232 1232 if plot in ('spc', 'spc_moments', 'spc_cut'):
1233 1233 z = dataOut.data_spc/dataOut.normFactor
1234 1234 buffer = 10*numpy.log10(z)
1235 1235 if plot == 'cspc':
1236 1236 z = dataOut.data_spc/dataOut.normFactor
1237 1237 buffer = (dataOut.data_spc, dataOut.data_cspc)
1238 1238 if plot == 'noise':
1239 1239 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
1240 1240 if plot in ('rti', 'spcprofile'):
1241 1241 buffer = dataOut.getPower()
1242 1242 if plot == 'snr_db':
1243 1243 buffer = dataOut.data_SNR
1244 1244 if plot == 'snr':
1245 1245 buffer = 10*numpy.log10(dataOut.data_SNR)
1246 1246 if plot == 'dop':
1247 1247 buffer = dataOut.data_DOP
1248 1248 if plot == 'pow':
1249 1249 buffer = 10*numpy.log10(dataOut.data_POW)
1250 1250 if plot == 'width':
1251 1251 buffer = dataOut.data_WIDTH
1252 1252 if plot == 'coh':
1253 1253 buffer = dataOut.getCoherence()
1254 1254 if plot == 'phase':
1255 1255 buffer = dataOut.getCoherence(phase=True)
1256 1256 if plot == 'output':
1257 1257 buffer = dataOut.data_output
1258 1258 if plot == 'param':
1259 1259 buffer = dataOut.data_param
1260 1260 if plot == 'scope':
1261 1261 buffer = dataOut.data
1262 1262 self.flagDataAsBlock = dataOut.flagDataAsBlock
1263 1263 self.nProfiles = dataOut.nProfiles
1264 1264
1265 1265 if plot == 'spc':
1266 1266 self.data['spc'] = buffer
1267 1267 elif plot == 'cspc':
1268 1268 self.data['spc'] = buffer[0]
1269 1269 self.data['cspc'] = buffer[1]
1270 1270 elif plot == 'spc_moments':
1271 1271 self.data['spc'] = buffer
1272 1272 self.data['moments'][tm] = dataOut.moments
1273 1273 else:
1274 1274 if self.buffering:
1275 1275 self.data[plot][tm] = buffer
1276 1276 else:
1277 1277 self.data[plot] = buffer
1278 1278
1279 1279 if dataOut.channelList is None:
1280 1280 self.channels = range(buffer.shape[0])
1281 1281 else:
1282 1282 self.channels = dataOut.channelList
1283 1283
1284 1284 if buffer is None:
1285 1285 self.flagNoData = True
1286 1286 raise schainpy.admin.SchainWarning('Attribute data_{} is empty'.format(self.key))
1287 1287
1288 1288 def normalize_heights(self):
1289 1289 '''
1290 1290 Ensure same-dimension of the data for different heighList
1291 1291 '''
1292 1292
1293 1293 H = numpy.array(list(self.__all_heights))
1294 1294 H.sort()
1295 1295 for key in self.data:
1296 1296 shape = self.shape(key)[:-1] + H.shape
1297 1297 for tm, obj in list(self.data[key].items()):
1298 1298 h = self.__heights[self.__times.index(tm)]
1299 1299 if H.size == h.size:
1300 1300 continue
1301 1301 index = numpy.where(numpy.in1d(H, h))[0]
1302 1302 dummy = numpy.zeros(shape) + numpy.nan
1303 1303 if len(shape) == 2:
1304 1304 dummy[:, index] = obj
1305 1305 else:
1306 1306 dummy[index] = obj
1307 1307 self.data[key][tm] = dummy
1308 1308
1309 1309 self.__heights = [H for tm in self.__times]
1310 1310
1311 1311 def jsonify(self, plot_name, plot_type, decimate=False):
1312 1312 '''
1313 1313 Convert data to json
1314 1314 '''
1315 1315
1316 1316 tm = self.times[-1]
1317 1317 dy = int(self.heights.size/self.MAXNUMY) + 1
1318 1318 if self.key in ('spc', 'cspc') or not self.buffering:
1319 1319 dx = int(self.data[self.key].shape[1]/self.MAXNUMX) + 1
1320 1320 data = self.roundFloats(
1321 1321 self.data[self.key][::, ::dx, ::dy].tolist())
1322 1322 else:
1323 data = self.roundFloats(self.data[self.key][tm].tolist())
1324 1323 if self.key is 'noise':
1325 data = [[x] for x in data]
1324 data = [[x] for x in self.roundFloats(self.data[self.key][tm].tolist())]
1325 else:
1326 data = self.roundFloats(self.data[self.key][tm][::, ::dy].tolist())
1326 1327
1327 1328 meta = {}
1328 1329 ret = {
1329 1330 'plot': plot_name,
1330 1331 'code': self.exp_code,
1331 1332 'time': float(tm),
1332 1333 'data': data,
1333 1334 }
1334 1335 meta['type'] = plot_type
1335 1336 meta['interval'] = float(self.interval)
1336 1337 meta['localtime'] = self.localtime
1337 1338 meta['yrange'] = self.roundFloats(self.heights[::dy].tolist())
1338 1339 if 'spc' in self.data or 'cspc' in self.data:
1339 1340 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1340 1341 else:
1341 1342 meta['xrange'] = []
1342 1343
1343 1344 meta.update(self.meta)
1344 1345 ret['metadata'] = meta
1345 1346 return json.dumps(ret)
1346 1347
1347 1348 @property
1348 1349 def times(self):
1349 1350 '''
1350 1351 Return the list of times of the current data
1351 1352 '''
1352 1353
1353 1354 ret = numpy.array(self.__times)
1354 1355 ret.sort()
1355 1356 return ret
1356 1357
1357 1358 @property
1358 1359 def min_time(self):
1359 1360 '''
1360 1361 Return the minimun time value
1361 1362 '''
1362 1363
1363 1364 return self.times[0]
1364 1365
1365 1366 @property
1366 1367 def max_time(self):
1367 1368 '''
1368 1369 Return the maximun time value
1369 1370 '''
1370 1371
1371 1372 return self.times[-1]
1372 1373
1373 1374 @property
1374 1375 def heights(self):
1375 1376 '''
1376 1377 Return the list of heights of the current data
1377 1378 '''
1378 1379
1379 1380 return numpy.array(self.__heights[-1])
1380 1381
1381 1382 @staticmethod
1382 1383 def roundFloats(obj):
1383 1384 if isinstance(obj, list):
1384 1385 return list(map(PlotterData.roundFloats, obj))
1385 1386 elif isinstance(obj, float):
1386 1387 return round(obj, 2)
@@ -1,700 +1,703
1 1
2 2 import os
3 3 import sys
4 4 import zmq
5 5 import time
6 6 import numpy
7 7 import datetime
8 8 from functools import wraps
9 9 from threading import Thread
10 10 import matplotlib
11 11
12 12 if 'BACKEND' in os.environ:
13 13 matplotlib.use(os.environ['BACKEND'])
14 14 elif 'linux' in sys.platform:
15 15 matplotlib.use("TkAgg")
16 16 elif 'darwin' in sys.platform:
17 17 matplotlib.use('WxAgg')
18 18 else:
19 19 from schainpy.utils import log
20 20 log.warning('Using default Backend="Agg"', 'INFO')
21 21 matplotlib.use('Agg')
22 22
23 23 import matplotlib.pyplot as plt
24 24 from matplotlib.patches import Polygon
25 25 from mpl_toolkits.axes_grid1 import make_axes_locatable
26 26 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
27 27
28 28 from schainpy.model.data.jrodata import PlotterData
29 29 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
30 30 from schainpy.utils import log
31 31
32 32 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
33 33 blu_values = matplotlib.pyplot.get_cmap(
34 34 'seismic_r', 20)(numpy.arange(20))[10:15]
35 35 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
36 36 'jro', numpy.vstack((blu_values, jet_values)))
37 37 matplotlib.pyplot.register_cmap(cmap=ncmap)
38 38
39 39 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
40 40 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
41 41
42 42 EARTH_RADIUS = 6.3710e3
43 43
44 44 def ll2xy(lat1, lon1, lat2, lon2):
45 45
46 46 p = 0.017453292519943295
47 47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 52 theta = -theta + numpy.pi/2
53 53 return r*numpy.cos(theta), r*numpy.sin(theta)
54 54
55 55
56 56 def km2deg(km):
57 57 '''
58 58 Convert distance in km to degrees
59 59 '''
60 60
61 61 return numpy.rad2deg(km/EARTH_RADIUS)
62 62
63 63
64 64 def figpause(interval):
65 65 backend = plt.rcParams['backend']
66 66 if backend in matplotlib.rcsetup.interactive_bk:
67 67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 68 if figManager is not None:
69 69 canvas = figManager.canvas
70 70 if canvas.figure.stale:
71 71 canvas.draw()
72 72 try:
73 73 canvas.start_event_loop(interval)
74 74 except:
75 75 pass
76 76 return
77 77
78 78
79 79 def popup(message):
80 80 '''
81 81 '''
82 82
83 83 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 84 text = '\n'.join([s.strip() for s in message.split(':')])
85 85 fig.text(0.01, 0.5, text, ha='left', va='center',
86 86 size='20', weight='heavy', color='w')
87 87 fig.show()
88 88 figpause(1000)
89 89
90 90
91 91 class Throttle(object):
92 92 '''
93 93 Decorator that prevents a function from being called more than once every
94 94 time period.
95 95 To create a function that cannot be called more than once a minute, but
96 96 will sleep until it can be called:
97 97 @Throttle(minutes=1)
98 98 def foo():
99 99 pass
100 100
101 101 for i in range(10):
102 102 foo()
103 103 print "This function has run %s times." % i
104 104 '''
105 105
106 106 def __init__(self, seconds=0, minutes=0, hours=0):
107 107 self.throttle_period = datetime.timedelta(
108 108 seconds=seconds, minutes=minutes, hours=hours
109 109 )
110 110
111 111 self.time_of_last_call = datetime.datetime.min
112 112
113 113 def __call__(self, fn):
114 114 @wraps(fn)
115 115 def wrapper(*args, **kwargs):
116 116 coerce = kwargs.pop('coerce', None)
117 117 if coerce:
118 118 self.time_of_last_call = datetime.datetime.now()
119 119 return fn(*args, **kwargs)
120 120 else:
121 121 now = datetime.datetime.now()
122 122 time_since_last_call = now - self.time_of_last_call
123 123 time_left = self.throttle_period - time_since_last_call
124 124
125 125 if time_left > datetime.timedelta(seconds=0):
126 126 return
127 127
128 128 self.time_of_last_call = datetime.datetime.now()
129 129 return fn(*args, **kwargs)
130 130
131 131 return wrapper
132 132
133 133 def apply_throttle(value):
134 134
135 135 @Throttle(seconds=value)
136 136 def fnThrottled(fn):
137 137 fn()
138 138
139 139 return fnThrottled
140 140
141 141
142 142 @MPDecorator
143 143 class Plot(Operation):
144 144 '''
145 145 Base class for Schain plotting operations
146 146 '''
147 147
148 148 CODE = 'Figure'
149 149 colormap = 'jet'
150 150 bgcolor = 'white'
151 151 buffering = True
152 152 __missing = 1E30
153 153
154 154 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
155 155 'showprofile']
156 156
157 157 def __init__(self):
158 158
159 159 Operation.__init__(self)
160 160 self.isConfig = False
161 161 self.isPlotConfig = False
162 162 self.save_counter = 1
163 self.sender_counter = 1
163 self.sender_time = 0
164 164 self.data = None
165 165 self.firsttime = True
166 166 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
167 167
168 168 def __fmtTime(self, x, pos):
169 169 '''
170 170 '''
171 171
172 172 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
173 173
174 174 def __setup(self, **kwargs):
175 175 '''
176 176 Initialize variables
177 177 '''
178 178
179 179 self.figures = []
180 180 self.axes = []
181 181 self.cb_axes = []
182 182 self.localtime = kwargs.pop('localtime', True)
183 183 self.show = kwargs.get('show', True)
184 184 self.save = kwargs.get('save', False)
185 185 self.save_period = kwargs.get('save_period', 1)
186 186 self.ftp = kwargs.get('ftp', False)
187 187 self.colormap = kwargs.get('colormap', self.colormap)
188 188 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
189 189 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
190 190 self.colormaps = kwargs.get('colormaps', None)
191 191 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
192 192 self.showprofile = kwargs.get('showprofile', False)
193 193 self.title = kwargs.get('wintitle', self.CODE.upper())
194 194 self.cb_label = kwargs.get('cb_label', None)
195 195 self.cb_labels = kwargs.get('cb_labels', None)
196 196 self.labels = kwargs.get('labels', None)
197 197 self.xaxis = kwargs.get('xaxis', 'frequency')
198 198 self.zmin = kwargs.get('zmin', None)
199 199 self.zmax = kwargs.get('zmax', None)
200 200 self.zlimits = kwargs.get('zlimits', None)
201 201 self.xmin = kwargs.get('xmin', None)
202 202 self.xmax = kwargs.get('xmax', None)
203 203 self.xrange = kwargs.get('xrange', 24)
204 204 self.xscale = kwargs.get('xscale', None)
205 205 self.ymin = kwargs.get('ymin', None)
206 206 self.ymax = kwargs.get('ymax', None)
207 207 self.yscale = kwargs.get('yscale', None)
208 208 self.xlabel = kwargs.get('xlabel', None)
209 209 self.attr_time = kwargs.get('attr_time', 'utctime')
210 210 self.decimation = kwargs.get('decimation', None)
211 211 self.showSNR = kwargs.get('showSNR', False)
212 212 self.oneFigure = kwargs.get('oneFigure', True)
213 213 self.width = kwargs.get('width', None)
214 214 self.height = kwargs.get('height', None)
215 215 self.colorbar = kwargs.get('colorbar', True)
216 216 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
217 217 self.channels = kwargs.get('channels', None)
218 218 self.titles = kwargs.get('titles', [])
219 219 self.polar = False
220 220 self.type = kwargs.get('type', 'iq')
221 221 self.grid = kwargs.get('grid', False)
222 222 self.pause = kwargs.get('pause', False)
223 223 self.save_code = kwargs.get('save_code', None)
224 224 self.realtime = kwargs.get('realtime', True)
225 225 self.throttle = kwargs.get('throttle', 0)
226 226 self.exp_code = kwargs.get('exp_code', None)
227 227 self.plot_server = kwargs.get('plot_server', False)
228 self.sender_period = kwargs.get('sender_period', 1)
228 self.sender_period = kwargs.get('sender_period', 60)
229 229 self.height_index = kwargs.get('height_index', None)
230 230 self.__throttle_plot = apply_throttle(self.throttle)
231 231 self.data = PlotterData(
232 232 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
233 233
234 234 if self.plot_server:
235 235 if not self.plot_server.startswith('tcp://'):
236 236 self.plot_server = 'tcp://{}'.format(self.plot_server)
237 237 log.success(
238 238 'Sending to server: {}'.format(self.plot_server),
239 239 self.name
240 240 )
241 241 if 'plot_name' in kwargs:
242 242 self.plot_name = kwargs['plot_name']
243 243
244 244 def __setup_plot(self):
245 245 '''
246 246 Common setup for all figures, here figures and axes are created
247 247 '''
248 248
249 249 self.setup()
250 250
251 251 self.time_label = 'LT' if self.localtime else 'UTC'
252 252
253 253 if self.width is None:
254 254 self.width = 8
255 255
256 256 self.figures = []
257 257 self.axes = []
258 258 self.cb_axes = []
259 259 self.pf_axes = []
260 260 self.cmaps = []
261 261
262 262 size = '15%' if self.ncols == 1 else '30%'
263 263 pad = '4%' if self.ncols == 1 else '8%'
264 264
265 265 if self.oneFigure:
266 266 if self.height is None:
267 267 self.height = 1.4 * self.nrows + 1
268 268 fig = plt.figure(figsize=(self.width, self.height),
269 269 edgecolor='k',
270 270 facecolor='w')
271 271 self.figures.append(fig)
272 272 for n in range(self.nplots):
273 273 ax = fig.add_subplot(self.nrows, self.ncols,
274 274 n + 1, polar=self.polar)
275 275 ax.tick_params(labelsize=8)
276 276 ax.firsttime = True
277 277 ax.index = 0
278 278 ax.press = None
279 279 self.axes.append(ax)
280 280 if self.showprofile:
281 281 cax = self.__add_axes(ax, size=size, pad=pad)
282 282 cax.tick_params(labelsize=8)
283 283 self.pf_axes.append(cax)
284 284 else:
285 285 if self.height is None:
286 286 self.height = 3
287 287 for n in range(self.nplots):
288 288 fig = plt.figure(figsize=(self.width, self.height),
289 289 edgecolor='k',
290 290 facecolor='w')
291 291 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
292 292 ax.tick_params(labelsize=8)
293 293 ax.firsttime = True
294 294 ax.index = 0
295 295 ax.press = None
296 296 self.figures.append(fig)
297 297 self.axes.append(ax)
298 298 if self.showprofile:
299 299 cax = self.__add_axes(ax, size=size, pad=pad)
300 300 cax.tick_params(labelsize=8)
301 301 self.pf_axes.append(cax)
302 302
303 303 for n in range(self.nrows):
304 304 if self.colormaps is not None:
305 305 cmap = plt.get_cmap(self.colormaps[n])
306 306 else:
307 307 cmap = plt.get_cmap(self.colormap)
308 308 cmap.set_bad(self.bgcolor, 1.)
309 309 self.cmaps.append(cmap)
310 310
311 311 def __add_axes(self, ax, size='30%', pad='8%'):
312 312 '''
313 313 Add new axes to the given figure
314 314 '''
315 315 divider = make_axes_locatable(ax)
316 316 nax = divider.new_horizontal(size=size, pad=pad)
317 317 ax.figure.add_axes(nax)
318 318 return nax
319 319
320 320 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
321 321 '''
322 322 Create a masked array for missing data
323 323 '''
324 324 if x_buffer.shape[0] < 2:
325 325 return x_buffer, y_buffer, z_buffer
326 326
327 327 deltas = x_buffer[1:] - x_buffer[0:-1]
328 328 x_median = numpy.median(deltas)
329 329
330 330 index = numpy.where(deltas > 5 * x_median)
331 331
332 332 if len(index[0]) != 0:
333 333 z_buffer[::, index[0], ::] = self.__missing
334 334 z_buffer = numpy.ma.masked_inside(z_buffer,
335 335 0.99 * self.__missing,
336 336 1.01 * self.__missing)
337 337
338 338 return x_buffer, y_buffer, z_buffer
339 339
340 340 def decimate(self):
341 341
342 342 # dx = int(len(self.x)/self.__MAXNUMX) + 1
343 343 dy = int(len(self.y) / self.decimation) + 1
344 344
345 345 # x = self.x[::dx]
346 346 x = self.x
347 347 y = self.y[::dy]
348 348 z = self.z[::, ::, ::dy]
349 349
350 350 return x, y, z
351 351
352 352 def format(self):
353 353 '''
354 354 Set min and max values, labels, ticks and titles
355 355 '''
356 356
357 357 if self.xmin is None:
358 358 xmin = self.data.min_time
359 359 else:
360 360 if self.xaxis is 'time':
361 361 dt = self.getDateTime(self.data.min_time)
362 362 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
363 363 datetime.datetime(1970, 1, 1)).total_seconds()
364 364 if self.data.localtime:
365 365 xmin += time.timezone
366 366 else:
367 367 xmin = self.xmin
368 368
369 369 if self.xmax is None:
370 370 xmax = xmin + self.xrange * 60 * 60
371 371 else:
372 372 if self.xaxis is 'time':
373 373 dt = self.getDateTime(self.data.max_time)
374 374 xmax = self.xmax - 1
375 375 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
376 376 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
377 377 if self.data.localtime:
378 378 xmax += time.timezone
379 379 else:
380 380 xmax = self.xmax
381 381
382 382 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
383 383 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
384 384
385 385 for n, ax in enumerate(self.axes):
386 386 if ax.firsttime:
387 387
388 388 dig = int(numpy.log10(ymax))
389 389 if dig == 0:
390 390 digD = len(str(ymax)) - 2
391 391 ydec = ymax*(10**digD)
392 392
393 393 dig = int(numpy.log10(ydec))
394 394 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
395 395 ystep = ystep/5
396 396 ystep = ystep/(10**digD)
397 397
398 398 else:
399 399 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
400 400 ystep = ystep/5
401 401
402 402 if self.xaxis is not 'time':
403 403
404 404 dig = int(numpy.log10(xmax))
405 405
406 406 if dig <= 0:
407 407 digD = len(str(xmax)) - 2
408 408 xdec = xmax*(10**digD)
409 409
410 410 dig = int(numpy.log10(xdec))
411 411 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
412 412 xstep = xstep*0.5
413 413 xstep = xstep/(10**digD)
414 414
415 415 else:
416 416 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
417 417 xstep = xstep/5
418 418
419 419 ax.set_facecolor(self.bgcolor)
420 420 ax.yaxis.set_major_locator(MultipleLocator(ystep))
421 421 if self.xscale:
422 422 ax.xaxis.set_major_formatter(FuncFormatter(
423 423 lambda x, pos: '{0:g}'.format(x*self.xscale)))
424 424 if self.xscale:
425 425 ax.yaxis.set_major_formatter(FuncFormatter(
426 426 lambda x, pos: '{0:g}'.format(x*self.yscale)))
427 427 if self.xaxis is 'time':
428 428 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
429 429 ax.xaxis.set_major_locator(LinearLocator(9))
430 430 else:
431 431 ax.xaxis.set_major_locator(MultipleLocator(xstep))
432 432 if self.xlabel is not None:
433 433 ax.set_xlabel(self.xlabel)
434 434 ax.set_ylabel(self.ylabel)
435 435 ax.firsttime = False
436 436 if self.showprofile:
437 437 self.pf_axes[n].set_ylim(ymin, ymax)
438 438 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
439 439 self.pf_axes[n].set_xlabel('dB')
440 440 self.pf_axes[n].grid(b=True, axis='x')
441 441 [tick.set_visible(False)
442 442 for tick in self.pf_axes[n].get_yticklabels()]
443 443 if self.colorbar:
444 444 ax.cbar = plt.colorbar(
445 445 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
446 446 ax.cbar.ax.tick_params(labelsize=8)
447 447 ax.cbar.ax.press = None
448 448 if self.cb_label:
449 449 ax.cbar.set_label(self.cb_label, size=8)
450 450 elif self.cb_labels:
451 451 ax.cbar.set_label(self.cb_labels[n], size=8)
452 452 else:
453 453 ax.cbar = None
454 454 if self.grid:
455 455 ax.grid(True)
456 456
457 457 if not self.polar:
458 458 ax.set_xlim(xmin, xmax)
459 459 ax.set_ylim(ymin, ymax)
460 460 ax.set_title('{} {} {}'.format(
461 461 self.titles[n],
462 462 self.getDateTime(self.data.max_time).strftime(
463 463 '%Y-%m-%d %H:%M:%S'),
464 464 self.time_label),
465 465 size=8)
466 466 else:
467 467 ax.set_title('{}'.format(self.titles[n]), size=8)
468 468 ax.set_ylim(0, 90)
469 469 ax.set_yticks(numpy.arange(0, 90, 20))
470 470 ax.yaxis.labelpad = 40
471 471
472 472 if self.firsttime:
473 473 for n, fig in enumerate(self.figures):
474 474 fig.subplots_adjust(**self.plots_adjust)
475 475 self.firsttime = False
476 476
477 477 def clear_figures(self):
478 478 '''
479 479 Reset axes for redraw plots
480 480 '''
481 481
482 482 for ax in self.axes+self.pf_axes+self.cb_axes:
483 483 ax.clear()
484 484 ax.firsttime = True
485 485 if ax.cbar:
486 486 ax.cbar.remove()
487 487
488 488 def __plot(self):
489 489 '''
490 490 Main function to plot, format and save figures
491 491 '''
492 492
493 493 self.plot()
494 494 self.format()
495 495
496 496 for n, fig in enumerate(self.figures):
497 497 if self.nrows == 0 or self.nplots == 0:
498 498 log.warning('No data', self.name)
499 499 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
500 500 fig.canvas.manager.set_window_title(self.CODE)
501 501 continue
502 502
503 503 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
504 504 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
505 505 fig.canvas.draw()
506 506 if self.show:
507 507 fig.show()
508 508 figpause(0.01)
509 509
510 510 if self.save:
511 511 self.save_figure(n)
512 512
513 513 if self.plot_server:
514 514 self.send_to_server()
515 515
516 516 def save_figure(self, n):
517 517 '''
518 518 '''
519 519
520 520 if self.save_counter < self.save_period:
521 521 self.save_counter += 1
522 522 return
523 523
524 524 self.save_counter = 1
525 525
526 526 fig = self.figures[n]
527 527
528 528 if self.save_code:
529 529 if isinstance(self.save_code, str):
530 530 labels = [self.save_code for x in self.figures]
531 531 else:
532 532 labels = self.save_code
533 533 else:
534 534 labels = [self.CODE for x in self.figures]
535 535
536 536 figname = os.path.join(
537 537 self.save,
538 538 labels[n],
539 539 '{}_{}.png'.format(
540 540 labels[n],
541 541 self.getDateTime(self.data.max_time).strftime(
542 542 '%Y%m%d_%H%M%S'
543 543 ),
544 544 )
545 545 )
546 546 log.log('Saving figure: {}'.format(figname), self.name)
547 547 if not os.path.isdir(os.path.dirname(figname)):
548 548 os.makedirs(os.path.dirname(figname))
549 549 fig.savefig(figname)
550 550
551 551 if self.throttle == 0:
552 552 figname = os.path.join(
553 553 self.save,
554 554 '{}_{}.png'.format(
555 555 labels[n],
556 556 self.getDateTime(self.data.min_time).strftime(
557 557 '%Y%m%d'
558 558 ),
559 559 )
560 560 )
561 561 fig.savefig(figname)
562 562
563 563 def send_to_server(self):
564 564 '''
565 565 '''
566 566
567 if self.sender_counter < self.sender_period:
568 self.sender_counter += 1
567 if self.data.tm - self.sender_time < self.sender_period:
569 568 return
570 569
571 self.sender_counter = 1
572 self.data.meta['titles'] = self.titles
570 self.sender_time = self.data.tm
571
572 attrs = ['titles', 'zmin', 'zmax']
573 for attr in attrs:
574 self.data.meta[attr] = getattr(self, attr)
575
573 576 retries = 2
574 577 while True:
575 578 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
576 579 socks = dict(self.poll.poll(5000))
577 580 if socks.get(self.socket) == zmq.POLLIN:
578 581 reply = self.socket.recv_string()
579 582 if reply == 'ok':
580 583 log.log("Response from server ok", self.name)
581 584 break
582 585 else:
583 586 log.warning(
584 587 "Malformed reply from server: {}".format(reply), self.name)
585 588
586 589 else:
587 590 log.warning(
588 591 "No response from server, retrying...", self.name)
589 592 self.socket.setsockopt(zmq.LINGER, 0)
590 593 self.socket.close()
591 594 self.poll.unregister(self.socket)
592 595 retries -= 1
593 596 if retries == 0:
594 597 log.error(
595 598 "Server seems to be offline, abandoning", self.name)
596 599 self.socket = self.context.socket(zmq.REQ)
597 600 self.socket.connect(self.plot_server)
598 601 self.poll.register(self.socket, zmq.POLLIN)
599 602 time.sleep(1)
600 603 break
601 604 self.socket = self.context.socket(zmq.REQ)
602 605 self.socket.connect(self.plot_server)
603 606 self.poll.register(self.socket, zmq.POLLIN)
604 607 time.sleep(0.5)
605 608
606 609 def setup(self):
607 610 '''
608 611 This method should be implemented in the child class, the following
609 612 attributes should be set:
610 613
611 614 self.nrows: number of rows
612 615 self.ncols: number of cols
613 616 self.nplots: number of plots (channels or pairs)
614 617 self.ylabel: label for Y axes
615 618 self.titles: list of axes title
616 619
617 620 '''
618 621 raise NotImplementedError
619 622
620 623 def plot(self):
621 624 '''
622 625 Must be defined in the child class
623 626 '''
624 627 raise NotImplementedError
625 628
626 629 def run(self, dataOut, **kwargs):
627 630 '''
628 631 Main plotting routine
629 632 '''
630 633
631 634 if self.isConfig is False:
632 635 self.__setup(**kwargs)
633 636
634 637 t = getattr(dataOut, self.attr_time)
635 638
636 639 if dataOut.useLocalTime:
637 640 self.getDateTime = datetime.datetime.fromtimestamp
638 641 if not self.localtime:
639 642 t += time.timezone
640 643 else:
641 644 self.getDateTime = datetime.datetime.utcfromtimestamp
642 645 if self.localtime:
643 646 t -= time.timezone
644 647
645 648 if 'buffer' in self.plot_type:
646 649 if self.xmin is None:
647 650 self.tmin = t
648 651 self.xmin = self.getDateTime(t).hour
649 652 else:
650 653 self.tmin = (
651 654 self.getDateTime(t).replace(
652 655 hour=int(self.xmin),
653 656 minute=0,
654 657 second=0) - self.getDateTime(0)).total_seconds()
655 658
656 659 self.data.setup()
657 660 self.isConfig = True
658 661 if self.plot_server:
659 662 self.context = zmq.Context()
660 663 self.socket = self.context.socket(zmq.REQ)
661 664 self.socket.connect(self.plot_server)
662 665 self.poll = zmq.Poller()
663 666 self.poll.register(self.socket, zmq.POLLIN)
664 667
665 668 tm = getattr(dataOut, self.attr_time)
666 669
667 670 if not dataOut.useLocalTime and self.localtime:
668 671 tm -= time.timezone
669 672 if dataOut.useLocalTime and not self.localtime:
670 673 tm += time.timezone
671 674
672 675 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
673 676 self.save_counter = self.save_period
674 677 self.__plot()
675 678 self.xmin += self.xrange
676 679 if self.xmin >= 24:
677 680 self.xmin -= 24
678 681 self.tmin += self.xrange*60*60
679 682 self.data.setup()
680 683 self.clear_figures()
681 684
682 685 self.data.update(dataOut, tm)
683 686
684 687 if self.isPlotConfig is False:
685 688 self.__setup_plot()
686 689 self.isPlotConfig = True
687 690
688 691 if self.throttle == 0:
689 692 self.__plot()
690 693 else:
691 694 self.__throttle_plot(self.__plot)#, coerce=coerce)
692 695
693 696 def close(self):
694 697
695 698 if self.data and not self.data.flagNoData:
696 699 self.save_counter = self.save_period
697 700 self.__plot()
698 701 if self.data and not self.data.flagNoData and self.pause:
699 702 figpause(10)
700 703
General Comments 0
You need to be logged in to leave comments. Login now