##// END OF EJS Templates
Tested window 20
Christianpl -
r1782:c73c874ee2f8
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,1093 +1,1094
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Definition of diferent Data objects for different types of data
6 6
7 7 Here you will find the diferent data objects for the different types
8 8 of data, this data objects must be used as dataIn or dataOut objects in
9 9 processing units and operations. Currently the supported data objects are:
10 10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
11 11 """
12 12
13 13 import copy
14 14 import numpy
15 15 import datetime
16 16 import json
17 17
18 18 import schainpy.admin
19 19 from schainpy.utils import log
20 20 from .jroheaderIO import SystemHeader, RadarControllerHeader
21 21 from schainpy.model.data import _noise
22 22
23 23
24 24 def getNumpyDtype(dataTypeCode):
25 25
26 26 if dataTypeCode == 0:
27 27 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
28 28 elif dataTypeCode == 1:
29 29 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
30 30 elif dataTypeCode == 2:
31 31 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
32 32 elif dataTypeCode == 3:
33 33 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
34 34 elif dataTypeCode == 4:
35 35 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
36 36 elif dataTypeCode == 5:
37 37 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
38 38 else:
39 39 raise ValueError('dataTypeCode was not defined')
40 40
41 41 return numpyDtype
42 42
43 43
44 44 def getDataTypeCode(numpyDtype):
45 45
46 46 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
47 47 datatype = 0
48 48 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
49 49 datatype = 1
50 50 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
51 51 datatype = 2
52 52 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
53 53 datatype = 3
54 54 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
55 55 datatype = 4
56 56 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
57 57 datatype = 5
58 58 else:
59 59 datatype = None
60 60
61 61 return datatype
62 62
63 63
64 64 def hildebrand_sekhon(data, navg):
65 65 """
66 66 This method is for the objective determination of the noise level in Doppler spectra. This
67 67 implementation technique is based on the fact that the standard deviation of the spectral
68 68 densities is equal to the mean spectral density for white Gaussian noise
69 69
70 70 Inputs:
71 71 Data : heights
72 72 navg : numbers of averages
73 73
74 74 Return:
75 75 mean : noise's level
76 76 """
77 77
78 78 sortdata = numpy.sort(data, axis=None)
79 79 #print(numpy.shape(data))
80 80 #exit()
81 '''
81
82 82 lenOfData = len(sortdata)
83 83 nums_min = lenOfData*0.2
84 84
85 85 if nums_min <= 5:
86 86
87 87 nums_min = 5
88 88
89 89 sump = 0.
90 90 sumq = 0.
91 91
92 92 j = 0
93 93 cont = 1
94 94
95 95 while((cont == 1)and(j < lenOfData)):
96 96
97 97 sump += sortdata[j]
98 98 sumq += sortdata[j]**2
99 99
100 100 if j > nums_min:
101 101 rtest = float(j)/(j-1) + 1.0/navg
102 102 if ((sumq*j) > (rtest*sump**2)):
103 103 j = j - 1
104 104 sump = sump - sortdata[j]
105 105 sumq = sumq - sortdata[j]**2
106 106 cont = 0
107 107
108 108 j += 1
109 109
110 110 lnoise = sump / j
111
111
112 112 return lnoise
113 '''
114 return _noise.hildebrand_sekhon(sortdata, navg)
113
114 #return _noise.hildebrand_sekhon(sortdata, navg)
115 115
116 116
117 117 class Beam:
118 118
119 119 def __init__(self):
120 120 self.codeList = []
121 121 self.azimuthList = []
122 122 self.zenithList = []
123 123
124 124
125 125 class GenericData(object):
126 126
127 127 flagNoData = True
128 128 blockReader = False
129 129
130 130 def copy(self, inputObj=None):
131 131
132 132 if inputObj == None:
133 133 return copy.deepcopy(self)
134 134
135 135 for key in list(inputObj.__dict__.keys()):
136 136
137 137 attribute = inputObj.__dict__[key]
138 138
139 139 # If this attribute is a tuple or list
140 140 if type(inputObj.__dict__[key]) in (tuple, list):
141 141 self.__dict__[key] = attribute[:]
142 142 continue
143 143
144 144 # If this attribute is another object or instance
145 145 if hasattr(attribute, '__dict__'):
146 146 self.__dict__[key] = attribute.copy()
147 147 continue
148 148
149 149 self.__dict__[key] = inputObj.__dict__[key]
150 150
151 151 def deepcopy(self):
152 152
153 153 return copy.deepcopy(self)
154 154
155 155 def isEmpty(self):
156 156
157 157 return self.flagNoData
158 158
159 159 def isReady(self):
160 160
161 161 return not self.flagNoData
162 162
163 163
164 164 class JROData(GenericData):
165 165
166 166 systemHeaderObj = SystemHeader()
167 167 radarControllerHeaderObj = RadarControllerHeader()
168 168 type = None
169 169 datatype = None # dtype but in string
170 170 nProfiles = None
171 171 heightList = None
172 172 channelList = None
173 173 flagDiscontinuousBlock = False
174 174 useLocalTime = False
175 175 utctime = None
176 176 timeZone = None
177 177 dstFlag = None
178 178 errorCount = None
179 179 blocksize = None
180 180 flagDecodeData = False # asumo q la data no esta decodificada
181 181 flagDeflipData = False # asumo q la data no esta sin flip
182 182 flagShiftFFT = False
183 183 nCohInt = None
184 184 windowOfFilter = 1
185 185 C = 3e8
186 186 frequency = 49.92e6
187 187 realtime = False
188 188 beacon_heiIndexList = None
189 189 last_block = None
190 190 blocknow = None
191 191 azimuth = None
192 192 zenith = None
193 193 beam = Beam()
194 194 profileIndex = None
195 195 error = None
196 196 data = None
197 197 nmodes = None
198 198 metadata_list = ['heightList', 'timeZone', 'type']
199 199
200 200 def __str__(self):
201 201
202 202 try:
203 203 dt = self.datatime
204 204 except:
205 205 dt = 'None'
206 206 return '{} - {}'.format(self.type, dt)
207 207
208 208 def getNoise(self):
209 209
210 210 raise NotImplementedError
211 211
212 212 @property
213 213 def nChannels(self):
214 214
215 215 return len(self.channelList)
216 216
217 217 @property
218 218 def channelIndexList(self):
219 219
220 220 return list(range(self.nChannels))
221 221
222 222 @property
223 223 def nHeights(self):
224 224
225 225 return len(self.heightList)
226 226
227 227 def getDeltaH(self):
228 228
229 229 return self.heightList[1] - self.heightList[0]
230 230
231 231 @property
232 232 def ltctime(self):
233 233
234 234 if self.useLocalTime:
235 235 return self.utctime - self.timeZone * 60
236 236
237 237 return self.utctime
238 238
239 239 @property
240 240 def datatime(self):
241 241
242 242 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
243 243 return datatimeValue
244 244
245 245 def getTimeRange(self):
246 246
247 247 datatime = []
248 248
249 249 datatime.append(self.ltctime)
250 250 datatime.append(self.ltctime + self.timeInterval + 1)
251 251
252 252 datatime = numpy.array(datatime)
253 253
254 254 return datatime
255 255
256 256 def getFmaxTimeResponse(self):
257 257
258 258 period = (10**-6) * self.getDeltaH() / (0.15)
259 259
260 260 PRF = 1. / (period * self.nCohInt)
261 261
262 262 fmax = PRF
263 263
264 264 return fmax
265 265
266 266 def getFmax(self):
267 267 PRF = 1. / (self.ippSeconds * self.nCohInt)
268 268 #print("ippsec",self.ippSeconds)
269 269 fmax = PRF
270 270 return fmax
271 271
272 272 def getVmax(self):
273 273
274 274 _lambda = self.C / self.frequency
275 275
276 276 vmax = self.getFmax() * _lambda / 2
277 277
278 278 return vmax
279 279
280 280 @property
281 281 def ippSeconds(self):
282 282 '''
283 283 '''
284 284 return self.radarControllerHeaderObj.ippSeconds
285 285
286 286 @ippSeconds.setter
287 287 def ippSeconds(self, ippSeconds):
288 288 '''
289 289 '''
290 290 self.radarControllerHeaderObj.ippSeconds = ippSeconds
291 291
292 292 @property
293 293 def code(self):
294 294 '''
295 295 '''
296 296 return self.radarControllerHeaderObj.code
297 297
298 298 @code.setter
299 299 def code(self, code):
300 300 '''
301 301 '''
302 302 self.radarControllerHeaderObj.code = code
303 303
304 304 @property
305 305 def nCode(self):
306 306 '''
307 307 '''
308 308 return self.radarControllerHeaderObj.nCode
309 309
310 310 @nCode.setter
311 311 def nCode(self, ncode):
312 312 '''
313 313 '''
314 314 self.radarControllerHeaderObj.nCode = ncode
315 315
316 316 @property
317 317 def nBaud(self):
318 318 '''
319 319 '''
320 320 return self.radarControllerHeaderObj.nBaud
321 321
322 322 @nBaud.setter
323 323 def nBaud(self, nbaud):
324 324 '''
325 325 '''
326 326 self.radarControllerHeaderObj.nBaud = nbaud
327 327
328 328 @property
329 329 def ipp(self):
330 330 '''
331 331 '''
332 332 return self.radarControllerHeaderObj.ipp
333 333
334 334 @ipp.setter
335 335 def ipp(self, ipp):
336 336 '''
337 337 '''
338 338 self.radarControllerHeaderObj.ipp = ipp
339 339
340 340 @property
341 341 def metadata(self):
342 342 '''
343 343 '''
344 344
345 345 return {attr: getattr(self, attr) for attr in self.metadata_list}
346 346
347 347
348 348 class Voltage(JROData):
349 349
350 350 dataPP_POW = None
351 351 dataPP_DOP = None
352 352 dataPP_WIDTH = None
353 353 dataPP_SNR = None
354 354
355 355 def __init__(self):
356 356 '''
357 357 Constructor
358 358 '''
359 359
360 360 self.useLocalTime = True
361 361 self.radarControllerHeaderObj = RadarControllerHeader()
362 362 self.systemHeaderObj = SystemHeader()
363 363 self.type = "Voltage"
364 364 self.data = None
365 365 self.nProfiles = None
366 366 self.heightList = None
367 367 self.channelList = None
368 368 self.flagNoData = True
369 369 self.flagDiscontinuousBlock = False
370 370 self.utctime = None
371 371 self.timeZone = 0
372 372 self.dstFlag = None
373 373 self.errorCount = None
374 374 self.nCohInt = None
375 375 self.blocksize = None
376 376 self.flagCohInt = False
377 377 self.flagDecodeData = False # asumo q la data no esta decodificada
378 378 self.flagDeflipData = False # asumo q la data no esta sin flip
379 379 self.flagShiftFFT = False
380 380 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
381 381 self.profileIndex = 0
382 382 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
383 383 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
384 384
385 385 def getNoisebyHildebrand(self, channel=None, Profmin_index=None, Profmax_index=None):
386 386 """
387 387 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
388 388
389 389 Return:
390 390 noiselevel
391 391 """
392 392
393 393 if channel != None:
394 394 data = self.data[channel]
395 395 nChannels = 1
396 396 else:
397 397 data = self.data
398 398 nChannels = self.nChannels
399 399
400 400 noise = numpy.zeros(nChannels)
401 401 power = data * numpy.conjugate(data)
402 402
403 403 for thisChannel in range(nChannels):
404 404 if nChannels == 1:
405 405 daux = power[:].real
406 406 else:
407 407 #print(power.shape)
408 408 daux = power[thisChannel, Profmin_index:Profmax_index, :].real
409 409 #print(daux.shape)
410 410 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
411 411
412 412 return noise
413 413
414 414 def getNoise(self, type=1, channel=None, Profmin_index=None, Profmax_index=None):
415 415
416 416 if type == 1:
417 417 noise = self.getNoisebyHildebrand(channel, Profmin_index, Profmax_index)
418 418
419 419 return noise
420 420
421 421 def getPower(self, channel=None):
422 422
423 423 if channel != None:
424 424 data = self.data[channel]
425 425 else:
426 426 data = self.data
427 427
428 428 power = data * numpy.conjugate(data)
429 429 powerdB = 10 * numpy.log10(power.real)
430 430 powerdB = numpy.squeeze(powerdB)
431 431
432 432 return powerdB
433 433
434 434 @property
435 435 def timeInterval(self):
436 436
437 437 return self.ippSeconds * self.nCohInt
438 438
439 439 noise = property(getNoise, "I'm the 'nHeights' property.")
440 440
441 441
442 442 class Spectra(JROData):
443 443
444 444 def __init__(self):
445 445 '''
446 446 Constructor
447 447 '''
448 448
449 449 self.data_dc = None
450 450 self.data_spc = None
451 451 self.data_cspc = None
452 452 self.useLocalTime = True
453 453 self.radarControllerHeaderObj = RadarControllerHeader()
454 454 self.systemHeaderObj = SystemHeader()
455 455 self.type = "Spectra"
456 456 self.timeZone = 0
457 457 self.nProfiles = None
458 458 self.heightList = None
459 459 self.channelList = None
460 460 self.pairsList = None
461 461 self.flagNoData = True
462 462 self.flagDiscontinuousBlock = False
463 463 self.utctime = None
464 464 self.nCohInt = None
465 465 self.nIncohInt = None
466 466 self.blocksize = None
467 467 self.nFFTPoints = None
468 468 self.wavelength = None
469 469 self.flagDecodeData = False # asumo q la data no esta decodificada
470 470 self.flagDeflipData = False # asumo q la data no esta sin flip
471 471 self.flagShiftFFT = False
472 472 self.ippFactor = 1
473 473 self.beacon_heiIndexList = []
474 474 self.noise_estimation = None
475 475 self.spc_noise = None
476 476 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
477 477 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp', 'nIncohInt', 'nFFTPoints', 'nProfiles', 'flagDecodeData']
478 478
479 479 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
480 480 """
481 481 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
482 482
483 483 Return:
484 484 noiselevel
485 485 """
486 486
487 487 noise = numpy.zeros(self.nChannels)
488 488
489 489 for channel in range(self.nChannels):
490 490 #print(self.data_spc[0])
491 491 #exit(1)
492 492 daux = self.data_spc[channel,
493 493 xmin_index:xmax_index, ymin_index:ymax_index]
494 #print("daux",daux)
494 495 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
495 496
496 497 return noise
497 498
498 499 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
499 500
500 501 if self.spc_noise is not None:
501 502 # this was estimated by getNoise Operation defined in jroproc_parameters.py
502 503 return self.spc_noise
503 504 elif self.noise_estimation is not None:
504 505 # this was estimated by getNoise Operation defined in jroproc_spectra.py
505 506 return self.noise_estimation
506 507 else:
507 508
508 509 noise = self.getNoisebyHildebrand(
509 510 xmin_index, xmax_index, ymin_index, ymax_index)
510 511 return noise
511 512
512 513 def getFreqRangeTimeResponse(self, extrapoints=0):
513 514
514 515 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
515 516 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
516 517
517 518 return freqrange
518 519
519 520 def getAcfRange(self, extrapoints=0):
520 521
521 522 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
522 523 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
523 524
524 525 return freqrange
525 526
526 527 def getFreqRange(self, extrapoints=0):
527 528
528 529 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
529 530 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
530 531
531 532 return freqrange
532 533
533 534 def getVelRange(self, extrapoints=0):
534 535
535 536 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
536 537 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
537 538
538 539 if self.nmodes:
539 540 return velrange/self.nmodes
540 541 else:
541 542 return velrange
542 543
543 544 @property
544 545 def nPairs(self):
545 546
546 547 return len(self.pairsList)
547 548
548 549 @property
549 550 def pairsIndexList(self):
550 551
551 552 return list(range(self.nPairs))
552 553
553 554 @property
554 555 def normFactor(self):
555 556
556 557 pwcode = 1
557 558
558 559 if self.flagDecodeData:
559 560 pwcode = numpy.sum(self.code[0]**2)
560 561 #pwcode = 64
561 562 #print("pwcode: ", pwcode)
562 563 #exit(1)
563 564 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
564 565 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
565 566
566 567 return normFactor
567 568
568 569 @property
569 570 def flag_cspc(self):
570 571
571 572 if self.data_cspc is None:
572 573 return True
573 574
574 575 return False
575 576
576 577 @property
577 578 def flag_dc(self):
578 579
579 580 if self.data_dc is None:
580 581 return True
581 582
582 583 return False
583 584
584 585 @property
585 586 def timeInterval(self):
586 587
587 588 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
588 589 if self.nmodes:
589 590 return self.nmodes*timeInterval
590 591 else:
591 592 return timeInterval
592 593
593 594 def getPower(self):
594 595
595 596 factor = self.normFactor
596 597 z = self.data_spc / factor
597 598 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
598 599 avg = numpy.average(z, axis=1)
599 600
600 601 return 10 * numpy.log10(avg)
601 602
602 603 def getCoherence(self, pairsList=None, phase=False):
603 604
604 605 z = []
605 606 if pairsList is None:
606 607 pairsIndexList = self.pairsIndexList
607 608 else:
608 609 pairsIndexList = []
609 610 for pair in pairsList:
610 611 if pair not in self.pairsList:
611 612 raise ValueError("Pair %s is not in dataOut.pairsList" % (
612 613 pair))
613 614 pairsIndexList.append(self.pairsList.index(pair))
614 615 for i in range(len(pairsIndexList)):
615 616 pair = self.pairsList[pairsIndexList[i]]
616 617 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
617 618 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
618 619 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
619 620 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
620 621 if phase:
621 622 data = numpy.arctan2(avgcoherenceComplex.imag,
622 623 avgcoherenceComplex.real) * 180 / numpy.pi
623 624 else:
624 625 data = numpy.abs(avgcoherenceComplex)
625 626
626 627 z.append(data)
627 628
628 629 return numpy.array(z)
629 630
630 631 def setValue(self, value):
631 632
632 633 print("This property should not be initialized")
633 634
634 635 return
635 636
636 637 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
637 638
638 639
639 640 class SpectraHeis(Spectra):
640 641
641 642 def __init__(self):
642 643
643 644 self.radarControllerHeaderObj = RadarControllerHeader()
644 645 self.systemHeaderObj = SystemHeader()
645 646 self.type = "SpectraHeis"
646 647 self.nProfiles = None
647 648 self.heightList = None
648 649 self.channelList = None
649 650 self.flagNoData = True
650 651 self.flagDiscontinuousBlock = False
651 652 self.utctime = None
652 653 self.blocksize = None
653 654 self.profileIndex = 0
654 655 self.nCohInt = 1
655 656 self.nIncohInt = 1
656 657
657 658 @property
658 659 def normFactor(self):
659 660 pwcode = 1
660 661 if self.flagDecodeData:
661 662 pwcode = numpy.sum(self.code[0]**2)
662 663
663 664 normFactor = self.nIncohInt * self.nCohInt * pwcode
664 665
665 666 return normFactor
666 667
667 668 @property
668 669 def timeInterval(self):
669 670
670 671 return self.ippSeconds * self.nCohInt * self.nIncohInt
671 672
672 673
673 674 class Fits(JROData):
674 675
675 676 def __init__(self):
676 677
677 678 self.type = "Fits"
678 679 self.nProfiles = None
679 680 self.heightList = None
680 681 self.channelList = None
681 682 self.flagNoData = True
682 683 self.utctime = None
683 684 self.nCohInt = 1
684 685 self.nIncohInt = 1
685 686 self.useLocalTime = True
686 687 self.profileIndex = 0
687 688 self.timeZone = 0
688 689
689 690 def getTimeRange(self):
690 691
691 692 datatime = []
692 693
693 694 datatime.append(self.ltctime)
694 695 datatime.append(self.ltctime + self.timeInterval)
695 696
696 697 datatime = numpy.array(datatime)
697 698
698 699 return datatime
699 700
700 701 def getChannelIndexList(self):
701 702
702 703 return list(range(self.nChannels))
703 704
704 705 def getNoise(self, type=1):
705 706
706 707
707 708 if type == 1:
708 709 noise = self.getNoisebyHildebrand()
709 710
710 711 if type == 2:
711 712 noise = self.getNoisebySort()
712 713
713 714 if type == 3:
714 715 noise = self.getNoisebyWindow()
715 716
716 717 return noise
717 718
718 719 @property
719 720 def timeInterval(self):
720 721
721 722 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
722 723
723 724 return timeInterval
724 725
725 726 @property
726 727 def ippSeconds(self):
727 728 '''
728 729 '''
729 730 return self.ipp_sec
730 731
731 732 noise = property(getNoise, "I'm the 'nHeights' property.")
732 733
733 734
734 735 class Correlation(JROData):
735 736
736 737 def __init__(self):
737 738 '''
738 739 Constructor
739 740 '''
740 741 self.radarControllerHeaderObj = RadarControllerHeader()
741 742 self.systemHeaderObj = SystemHeader()
742 743 self.type = "Correlation"
743 744 self.data = None
744 745 self.dtype = None
745 746 self.nProfiles = None
746 747 self.heightList = None
747 748 self.channelList = None
748 749 self.flagNoData = True
749 750 self.flagDiscontinuousBlock = False
750 751 self.utctime = None
751 752 self.timeZone = 0
752 753 self.dstFlag = None
753 754 self.errorCount = None
754 755 self.blocksize = None
755 756 self.flagDecodeData = False # asumo q la data no esta decodificada
756 757 self.flagDeflipData = False # asumo q la data no esta sin flip
757 758 self.pairsList = None
758 759 self.nPoints = None
759 760
760 761 def getPairsList(self):
761 762
762 763 return self.pairsList
763 764
764 765 def getNoise(self, mode=2):
765 766
766 767 indR = numpy.where(self.lagR == 0)[0][0]
767 768 indT = numpy.where(self.lagT == 0)[0][0]
768 769
769 770 jspectra0 = self.data_corr[:, :, indR, :]
770 771 jspectra = copy.copy(jspectra0)
771 772
772 773 num_chan = jspectra.shape[0]
773 774 num_hei = jspectra.shape[2]
774 775
775 776 freq_dc = jspectra.shape[1] / 2
776 777 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
777 778
778 779 if ind_vel[0] < 0:
779 780 ind_vel[list(range(0, 1))] = ind_vel[list(
780 781 range(0, 1))] + self.num_prof
781 782
782 783 if mode == 1:
783 784 jspectra[:, freq_dc, :] = (
784 785 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
785 786
786 787 if mode == 2:
787 788
788 789 vel = numpy.array([-2, -1, 1, 2])
789 790 xx = numpy.zeros([4, 4])
790 791
791 792 for fil in range(4):
792 793 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
793 794
794 795 xx_inv = numpy.linalg.inv(xx)
795 796 xx_aux = xx_inv[0, :]
796 797
797 798 for ich in range(num_chan):
798 799 yy = jspectra[ich, ind_vel, :]
799 800 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
800 801
801 802 junkid = jspectra[ich, freq_dc, :] <= 0
802 803 cjunkid = sum(junkid)
803 804
804 805 if cjunkid.any():
805 806 jspectra[ich, freq_dc, junkid.nonzero()] = (
806 807 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
807 808
808 809 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
809 810
810 811 return noise
811 812
812 813 @property
813 814 def timeInterval(self):
814 815
815 816 return self.ippSeconds * self.nCohInt * self.nProfiles
816 817
817 818 def splitFunctions(self):
818 819
819 820 pairsList = self.pairsList
820 821 ccf_pairs = []
821 822 acf_pairs = []
822 823 ccf_ind = []
823 824 acf_ind = []
824 825 for l in range(len(pairsList)):
825 826 chan0 = pairsList[l][0]
826 827 chan1 = pairsList[l][1]
827 828
828 829 # Obteniendo pares de Autocorrelacion
829 830 if chan0 == chan1:
830 831 acf_pairs.append(chan0)
831 832 acf_ind.append(l)
832 833 else:
833 834 ccf_pairs.append(pairsList[l])
834 835 ccf_ind.append(l)
835 836
836 837 data_acf = self.data_cf[acf_ind]
837 838 data_ccf = self.data_cf[ccf_ind]
838 839
839 840 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
840 841
841 842 @property
842 843 def normFactor(self):
843 844 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
844 845 acf_pairs = numpy.array(acf_pairs)
845 846 normFactor = numpy.zeros((self.nPairs, self.nHeights))
846 847
847 848 for p in range(self.nPairs):
848 849 pair = self.pairsList[p]
849 850
850 851 ch0 = pair[0]
851 852 ch1 = pair[1]
852 853
853 854 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
854 855 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
855 856 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
856 857
857 858 return normFactor
858 859
859 860
860 861 class Parameters(Spectra):
861 862
862 863 groupList = None # List of Pairs, Groups, etc
863 864 data_param = None # Parameters obtained
864 865 data_pre = None # Data Pre Parametrization
865 866 data_SNR = None # Signal to Noise Ratio
866 867 abscissaList = None # Abscissa, can be velocities, lags or time
867 868 utctimeInit = None # Initial UTC time
868 869 paramInterval = None # Time interval to calculate Parameters in seconds
869 870 useLocalTime = True
870 871 # Fitting
871 872 data_error = None # Error of the estimation
872 873 constants = None
873 874 library = None
874 875 # Output signal
875 876 outputInterval = None # Time interval to calculate output signal in seconds
876 877 data_output = None # Out signal
877 878 nAvg = None
878 879 noise_estimation = None
879 880 GauSPC = None # Fit gaussian SPC
880 881 spc_noise = None
881 882
882 883 def __init__(self):
883 884 '''
884 885 Constructor
885 886 '''
886 887 self.radarControllerHeaderObj = RadarControllerHeader()
887 888 self.systemHeaderObj = SystemHeader()
888 889 self.type = "Parameters"
889 890 self.timeZone = 0
890 891 self.ippFactor = 1
891 892
892 893 def getTimeRange1(self, interval):
893 894
894 895 datatime = []
895 896
896 897 if self.useLocalTime:
897 898 time1 = self.utctimeInit - self.timeZone * 60
898 899 else:
899 900 time1 = self.utctimeInit
900 901
901 902 datatime.append(time1)
902 903 datatime.append(time1 + interval)
903 904 datatime = numpy.array(datatime)
904 905
905 906 return datatime
906 907
907 908 @property
908 909 def timeInterval(self):
909 910
910 911 if hasattr(self, 'timeInterval1'):
911 912 return self.timeInterval1
912 913 else:
913 914 return self.paramInterval
914 915
915 916
916 917 def setValue(self, value):
917 918
918 919 print("This property should not be initialized")
919 920
920 921 return
921 922
922 923 def getNoise(self):
923 924
924 925 return self.spc_noise
925 926
926 927 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
927 928
928 929
929 930 class PlotterData(object):
930 931 '''
931 932 Object to hold data to be plotted
932 933 '''
933 934
934 935 MAXNUMX = 200
935 936 MAXNUMY = 200
936 937
937 938 def __init__(self, code, exp_code, localtime=True):
938 939
939 940 self.key = code
940 941 self.exp_code = exp_code
941 942 self.ready = False
942 943 self.flagNoData = False
943 944 self.localtime = localtime
944 945 self.data = {}
945 946 self.meta = {}
946 947 self.__heights = []
947 948
948 949 def __str__(self):
949 950 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
950 951 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
951 952
952 953 def __len__(self):
953 954 return len(self.data)
954 955
955 956 def __getitem__(self, key):
956 957 if isinstance(key, int):
957 958 return self.data[self.times[key]]
958 959 elif isinstance(key, str):
959 960 ret = numpy.array([self.data[x][key] for x in self.times])
960 961 if ret.ndim > 1:
961 962 ret = numpy.swapaxes(ret, 0, 1)
962 963 return ret
963 964
964 965 def __contains__(self, key):
965 966 return key in self.data[self.min_time]
966 967
967 968 def setup(self):
968 969 '''
969 970 Configure object
970 971 '''
971 972 self.type = ''
972 973 self.ready = False
973 974 del self.data
974 975 self.data = {}
975 976 self.__heights = []
976 977 self.__all_heights = set()
977 978
978 979 def shape(self, key):
979 980 '''
980 981 Get the shape of the one-element data for the given key
981 982 '''
982 983
983 984 if len(self.data[self.min_time][key]):
984 985 return self.data[self.min_time][key].shape
985 986 return (0,)
986 987
987 988 def update(self, data, tm, meta={}):
988 989 '''
989 990 Update data object with new dataOut
990 991 '''
991 992
992 993 self.data[tm] = data
993 994
994 995 for key, value in meta.items():
995 996 setattr(self, key, value)
996 997
997 998 def normalize_heights(self):
998 999 '''
999 1000 Ensure same-dimension of the data for different heighList
1000 1001 '''
1001 1002
1002 1003 H = numpy.array(list(self.__all_heights))
1003 1004 H.sort()
1004 1005 for key in self.data:
1005 1006 shape = self.shape(key)[:-1] + H.shape
1006 1007 for tm, obj in list(self.data[key].items()):
1007 1008 h = self.__heights[self.times.tolist().index(tm)]
1008 1009 if H.size == h.size:
1009 1010 continue
1010 1011 index = numpy.where(numpy.in1d(H, h))[0]
1011 1012 dummy = numpy.zeros(shape) + numpy.nan
1012 1013 if len(shape) == 2:
1013 1014 dummy[:, index] = obj
1014 1015 else:
1015 1016 dummy[index] = obj
1016 1017 self.data[key][tm] = dummy
1017 1018
1018 1019 self.__heights = [H for tm in self.times]
1019 1020
1020 1021 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1021 1022 '''
1022 1023 Convert data to json
1023 1024 '''
1024 1025
1025 1026 meta = {}
1026 1027 meta['xrange'] = []
1027 1028 dy = int(len(self.yrange)/self.MAXNUMY) + 1
1028 1029 tmp = self.data[tm][self.key]
1029 1030 shape = tmp.shape
1030 1031 if len(shape) == 2:
1031 1032 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1032 1033 elif len(shape) == 3:
1033 1034 dx = int(self.data[tm][self.key].shape[1]/self.MAXNUMX) + 1
1034 1035 data = self.roundFloats(
1035 1036 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1036 1037 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1037 1038 else:
1038 1039 data = self.roundFloats(self.data[tm][self.key].tolist())
1039 1040
1040 1041 ret = {
1041 1042 'plot': plot_name,
1042 1043 'code': self.exp_code,
1043 1044 'time': float(tm),
1044 1045 'data': data,
1045 1046 }
1046 1047 meta['type'] = plot_type
1047 1048 meta['interval'] = float(self.interval)
1048 1049 meta['localtime'] = self.localtime
1049 1050 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1050 1051 meta.update(self.meta)
1051 1052 ret['metadata'] = meta
1052 1053 return json.dumps(ret)
1053 1054
1054 1055 @property
1055 1056 def times(self):
1056 1057 '''
1057 1058 Return the list of times of the current data
1058 1059 '''
1059 1060
1060 1061 ret = [t for t in self.data]
1061 1062 ret.sort()
1062 1063 return numpy.array(ret)
1063 1064
1064 1065 @property
1065 1066 def min_time(self):
1066 1067 '''
1067 1068 Return the minimun time value
1068 1069 '''
1069 1070
1070 1071 return self.times[0]
1071 1072
1072 1073 @property
1073 1074 def max_time(self):
1074 1075 '''
1075 1076 Return the maximun time value
1076 1077 '''
1077 1078
1078 1079 return self.times[-1]
1079 1080
1080 1081 # @property
1081 1082 # def heights(self):
1082 1083 # '''
1083 1084 # Return the list of heights of the current data
1084 1085 # '''
1085 1086
1086 1087 # return numpy.array(self.__heights[-1])
1087 1088
1088 1089 @staticmethod
1089 1090 def roundFloats(obj):
1090 1091 if isinstance(obj, list):
1091 1092 return list(map(PlotterData.roundFloats, obj))
1092 1093 elif isinstance(obj, float):
1093 1094 return round(obj, 2)
@@ -1,1350 +1,1349
1 1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Classes to plot Spectra data
6 6
7 7 """
8 8
9 9 import os
10 10 import numpy
11 11 #import collections.abc
12 12
13 13 from schainpy.model.graphics.jroplot_base import Plot, plt, log
14 14
15 15 class SpectraPlot(Plot):
16 16 '''
17 17 Plot for Spectra data
18 18 '''
19 19
20 20 CODE = 'spc'
21 21 colormap = 'jet'
22 22 plot_type = 'pcolor'
23 23 buffering = False
24 24
25 25 def setup(self):
26 26
27 27 self.nplots = len(self.data.channels)
28 28 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
29 29 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
30 30 self.height = 2.6 * self.nrows
31 31 self.cb_label = 'dB'
32 32 if self.showprofile:
33 33 self.width = 4 * self.ncols
34 34 else:
35 35 self.width = 3.5 * self.ncols
36 36 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
37 37 self.ylabel = 'Range [km]'
38 38
39 39 def update(self, dataOut):
40 40
41 41 data = {}
42 42 meta = {}
43 43
44 44 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
45 45 #print("dataOut.normFactor: ", dataOut.normFactor)
46 46 #print("spc: ", dataOut.data_spc[0,0,0])
47 47 #spc = 10*numpy.log10(dataOut.data_spc)
48 48 #print("Spc: ",spc[0])
49 49 #exit(1)
50 50 data['spc'] = spc
51 51 data['rti'] = dataOut.getPower()
52 52 #print(data['rti'][0])
53 53 #exit(1)
54 54 #print("NormFactor: ",dataOut.normFactor)
55 55 #data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
56 56 if hasattr(dataOut, 'LagPlot'): #Double Pulse
57 max_hei_id = dataOut.nHeights - 2*dataOut.LagPlot
58 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=46,ymax_index=max_hei_id)/dataOut.normFactor)
59 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=40,ymax_index=max_hei_id)/dataOut.normFactor)
60 data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=53,ymax_index=max_hei_id)/dataOut.normFactor)
61 data['noise'][0] = 10*numpy.log10(dataOut.getNoise(ymin_index=53)[0]/dataOut.normFactor)
57 ymin_index = numpy.abs(dataOut.heightList - 800).argmin()
58 max_hei_id = dataOut.nHeights - dataOut.TxLagRate*dataOut.LagPlot
59 data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=ymin_index,ymax_index=max_hei_id)/dataOut.normFactor)
60 data['noise'][0] = 10*numpy.log10(dataOut.getNoise(ymin_index=ymin_index)[0]/dataOut.normFactor)
62 61 #data['noise'][1] = 22.035507
63 62 else:
64 63 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
65 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=26,ymax_index=44)/dataOut.normFactor)
64
66 65 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
67 66
68 67 if self.CODE == 'spc_moments':
69 68 data['moments'] = dataOut.moments
70 69 if self.CODE == 'gaussian_fit':
71 70 data['gaussfit'] = dataOut.DGauFitParams
72 71
73 72 return data, meta
74 73
75 74 def plot(self):
76 75
77 76 if self.xaxis == "frequency":
78 77 x = self.data.xrange[0]
79 78 self.xlabel = "Frequency (kHz)"
80 79 elif self.xaxis == "time":
81 80 x = self.data.xrange[1]
82 81 self.xlabel = "Time (ms)"
83 82 else:
84 83 x = self.data.xrange[2]
85 84 self.xlabel = "Velocity (m/s)"
86 85
87 86 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
88 87 x = self.data.xrange[2]
89 88 self.xlabel = "Velocity (m/s)"
90 89
91 90 self.titles = []
92 91
93 92 y = self.data.yrange
94 93 self.y = y
95 94
96 95 data = self.data[-1]
97 96 z = data['spc']
98 97
99 98 self.CODE2 = 'spc_oblique'
100 99
101 100 for n, ax in enumerate(self.axes):
102 101 noise = data['noise'][n]
103 102 if self.CODE == 'spc_moments':
104 103 mean = data['moments'][n, 1]
105 104 if self.CODE == 'gaussian_fit':
106 105 gau0 = data['gaussfit'][n][2,:,0]
107 106 gau1 = data['gaussfit'][n][2,:,1]
108 107 if ax.firsttime:
109 108 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
110 109 self.xmin = self.xmin if self.xmin else numpy.nanmin(x)#-self.xmax
111 110 #self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
112 111 #self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
113 112 if self.zlimits is not None:
114 113 self.zmin, self.zmax = self.zlimits[n]
115 114
116 115 ax.plt = ax.pcolormesh(x, y, z[n].T,
117 116 vmin=self.zmin,
118 117 vmax=self.zmax,
119 118 cmap=plt.get_cmap(self.colormap),
120 119 )
121 120
122 121 if self.showprofile:
123 122 ax.plt_profile = self.pf_axes[n].plot(
124 123 data['rti'][n], y)[0]
125 124 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
126 125 color="k", linestyle="dashed", lw=1)[0]
127 126 if self.CODE == 'spc_moments':
128 127 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
129 128 if self.CODE == 'gaussian_fit':
130 129 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
131 130 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
132 131 else:
133 132 if self.zlimits is not None:
134 133 self.zmin, self.zmax = self.zlimits[n]
135 134 ax.plt.set_array(z[n].T.ravel())
136 135 if self.showprofile:
137 136 ax.plt_profile.set_data(data['rti'][n], y)
138 137 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
139 138 if self.CODE == 'spc_moments':
140 139 ax.plt_mean.set_data(mean, y)
141 140 if self.CODE == 'gaussian_fit':
142 141 ax.plt_gau0.set_data(gau0, y)
143 142 ax.plt_gau1.set_data(gau1, y)
144 143 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
145 144
146 145 class SpectraObliquePlot(Plot):
147 146 '''
148 147 Plot for Spectra data
149 148 '''
150 149
151 150 CODE = 'spc_oblique'
152 151 colormap = 'jet'
153 152 plot_type = 'pcolor'
154 153
155 154 def setup(self):
156 155 self.xaxis = "oblique"
157 156 self.nplots = len(self.data.channels)
158 157 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
159 158 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
160 159 self.height = 2.6 * self.nrows
161 160 self.cb_label = 'dB'
162 161 if self.showprofile:
163 162 self.width = 4 * self.ncols
164 163 else:
165 164 self.width = 3.5 * self.ncols
166 165 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
167 166 self.ylabel = 'Range [km]'
168 167
169 168 def update(self, dataOut):
170 169
171 170 data = {}
172 171 meta = {}
173 172
174 173 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
175 174 data['spc'] = spc
176 175 data['rti'] = dataOut.getPower()
177 176 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
178 177 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
179 178 '''
180 179 data['shift1'] = dataOut.Oblique_params[0,-2,:]
181 180 data['shift2'] = dataOut.Oblique_params[0,-1,:]
182 181 data['shift1_error'] = dataOut.Oblique_param_errors[0,-2,:]
183 182 data['shift2_error'] = dataOut.Oblique_param_errors[0,-1,:]
184 183 '''
185 184 '''
186 185 data['shift1'] = dataOut.Oblique_params[0,1,:]
187 186 data['shift2'] = dataOut.Oblique_params[0,4,:]
188 187 data['shift1_error'] = dataOut.Oblique_param_errors[0,1,:]
189 188 data['shift2_error'] = dataOut.Oblique_param_errors[0,4,:]
190 189 '''
191 190 data['shift1'] = dataOut.Dop_EEJ_T1[0]
192 191 data['shift2'] = dataOut.Dop_EEJ_T2[0]
193 192 data['max_val_2'] = dataOut.Oblique_params[0,-1,:]
194 193 data['shift1_error'] = dataOut.Err_Dop_EEJ_T1[0]
195 194 data['shift2_error'] = dataOut.Err_Dop_EEJ_T2[0]
196 195
197 196 return data, meta
198 197
199 198 def plot(self):
200 199
201 200 if self.xaxis == "frequency":
202 201 x = self.data.xrange[0]
203 202 self.xlabel = "Frequency (kHz)"
204 203 elif self.xaxis == "time":
205 204 x = self.data.xrange[1]
206 205 self.xlabel = "Time (ms)"
207 206 else:
208 207 x = self.data.xrange[2]
209 208 self.xlabel = "Velocity (m/s)"
210 209
211 210 self.titles = []
212 211
213 212 y = self.data.yrange
214 213 self.y = y
215 214
216 215 data = self.data[-1]
217 216 z = data['spc']
218 217
219 218 for n, ax in enumerate(self.axes):
220 219 noise = self.data['noise'][n][-1]
221 220 shift1 = data['shift1']
222 221 #print(shift1)
223 222 shift2 = data['shift2']
224 223 max_val_2 = data['max_val_2']
225 224 err1 = data['shift1_error']
226 225 err2 = data['shift2_error']
227 226 if ax.firsttime:
228 227
229 228 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
230 229 self.xmin = self.xmin if self.xmin else -self.xmax
231 230 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
232 231 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
233 232 ax.plt = ax.pcolormesh(x, y, z[n].T,
234 233 vmin=self.zmin,
235 234 vmax=self.zmax,
236 235 cmap=plt.get_cmap(self.colormap)
237 236 )
238 237
239 238 if self.showprofile:
240 239 ax.plt_profile = self.pf_axes[n].plot(
241 240 self.data['rti'][n][-1], y)[0]
242 241 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
243 242 color="k", linestyle="dashed", lw=1)[0]
244 243
245 244 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
246 245 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
247 246 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
248 247
249 248 #print("plotter1: ", self.ploterr1,shift1)
250 249
251 250 else:
252 251 #print("else plotter1: ", self.ploterr1,shift1)
253 252 self.ploterr1.remove()
254 253 self.ploterr2.remove()
255 254 self.ploterr3.remove()
256 255 ax.plt.set_array(z[n].T.ravel())
257 256 if self.showprofile:
258 257 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
259 258 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
260 259 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
261 260 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
262 261 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
263 262
264 263 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
265 264
266 265
267 266 class CrossSpectraPlot(Plot):
268 267
269 268 CODE = 'cspc'
270 269 colormap = 'jet'
271 270 plot_type = 'pcolor'
272 271 zmin_coh = None
273 272 zmax_coh = None
274 273 zmin_phase = None
275 274 zmax_phase = None
276 275
277 276 def setup(self):
278 277
279 278 self.ncols = 4
280 279 self.nplots = len(self.data.pairs) * 2
281 280 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
282 281 self.width = 3.1 * self.ncols
283 282 self.height = 5 * self.nrows
284 283 self.ylabel = 'Range [km]'
285 284 self.showprofile = False
286 285 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
287 286
288 287 def update(self, dataOut):
289 288
290 289 data = {}
291 290 meta = {}
292 291
293 292 spc = dataOut.data_spc
294 293 cspc = dataOut.data_cspc
295 294 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
296 295 meta['pairs'] = dataOut.pairsList
297 296
298 297 tmp = []
299 298
300 299 for n, pair in enumerate(meta['pairs']):
301 300 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
302 301 coh = numpy.abs(out)
303 302 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
304 303 tmp.append(coh)
305 304 tmp.append(phase)
306 305
307 306 data['cspc'] = numpy.array(tmp)
308 307
309 308 return data, meta
310 309
311 310 def plot(self):
312 311
313 312 if self.xaxis == "frequency":
314 313 x = self.data.xrange[0]
315 314 self.xlabel = "Frequency (kHz)"
316 315 elif self.xaxis == "time":
317 316 x = self.data.xrange[1]
318 317 self.xlabel = "Time (ms)"
319 318 else:
320 319 x = self.data.xrange[2]
321 320 self.xlabel = "Velocity (m/s)"
322 321
323 322 self.titles = []
324 323
325 324 y = self.data.yrange
326 325 self.y = y
327 326
328 327 data = self.data[-1]
329 328 cspc = data['cspc']
330 329
331 330 for n in range(len(self.data.pairs)):
332 331 pair = self.data.pairs[n]
333 332 coh = cspc[n*2]
334 333 phase = cspc[n*2+1]
335 334 ax = self.axes[2 * n]
336 335 if ax.firsttime:
337 336 ax.plt = ax.pcolormesh(x, y, coh.T,
338 337 vmin=0,
339 338 vmax=1,
340 339 cmap=plt.get_cmap(self.colormap_coh)
341 340 )
342 341 else:
343 342 ax.plt.set_array(coh.T.ravel())
344 343 self.titles.append(
345 344 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
346 345
347 346 ax = self.axes[2 * n + 1]
348 347 if ax.firsttime:
349 348 ax.plt = ax.pcolormesh(x, y, phase.T,
350 349 vmin=-180,
351 350 vmax=180,
352 351 cmap=plt.get_cmap(self.colormap_phase)
353 352 )
354 353 else:
355 354 ax.plt.set_array(phase.T.ravel())
356 355 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
357 356
358 357
359 358 class CrossSpectra4Plot(Plot):
360 359
361 360 CODE = 'cspc'
362 361 colormap = 'jet'
363 362 plot_type = 'pcolor'
364 363 zmin_coh = None
365 364 zmax_coh = None
366 365 zmin_phase = None
367 366 zmax_phase = None
368 367
369 368 def setup(self):
370 369
371 370 self.ncols = 4
372 371 self.nrows = len(self.data.pairs)
373 372 self.nplots = self.nrows * 4
374 373 self.width = 3.1 * self.ncols
375 374 self.height = 5 * self.nrows
376 375 self.ylabel = 'Range [km]'
377 376 self.showprofile = False
378 377 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
379 378
380 379 def plot(self):
381 380
382 381 if self.xaxis == "frequency":
383 382 x = self.data.xrange[0]
384 383 self.xlabel = "Frequency (kHz)"
385 384 elif self.xaxis == "time":
386 385 x = self.data.xrange[1]
387 386 self.xlabel = "Time (ms)"
388 387 else:
389 388 x = self.data.xrange[2]
390 389 self.xlabel = "Velocity (m/s)"
391 390
392 391 self.titles = []
393 392
394 393
395 394 y = self.data.heights
396 395 self.y = y
397 396 nspc = self.data['spc']
398 397 #print(numpy.shape(self.data['spc']))
399 398 spc = self.data['cspc'][0]
400 399 #print(numpy.shape(nspc))
401 400 #exit()
402 401 #nspc[1,:,:] = numpy.flip(nspc[1,:,:],axis=0)
403 402 #print(numpy.shape(spc))
404 403 #exit()
405 404 cspc = self.data['cspc'][1]
406 405
407 406 #xflip=numpy.flip(x)
408 407 #print(numpy.shape(cspc))
409 408 #exit()
410 409
411 410 for n in range(self.nrows):
412 411 noise = self.data['noise'][:,-1]
413 412 pair = self.data.pairs[n]
414 413 #print(pair)
415 414 #exit()
416 415 ax = self.axes[4 * n]
417 416 if ax.firsttime:
418 417 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
419 418 self.xmin = self.xmin if self.xmin else -self.xmax
420 419 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
421 420 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
422 421 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
423 422 vmin=self.zmin,
424 423 vmax=self.zmax,
425 424 cmap=plt.get_cmap(self.colormap)
426 425 )
427 426 else:
428 427 #print(numpy.shape(nspc[pair[0]].T))
429 428 #exit()
430 429 ax.plt.set_array(nspc[pair[0]].T.ravel())
431 430 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
432 431
433 432 ax = self.axes[4 * n + 1]
434 433
435 434 if ax.firsttime:
436 435 ax.plt = ax.pcolormesh(x , y, numpy.flip(nspc[pair[1]],axis=0).T,
437 436 vmin=self.zmin,
438 437 vmax=self.zmax,
439 438 cmap=plt.get_cmap(self.colormap)
440 439 )
441 440 else:
442 441
443 442 ax.plt.set_array(numpy.flip(nspc[pair[1]],axis=0).T.ravel())
444 443 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
445 444
446 445 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
447 446 coh = numpy.abs(out)
448 447 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
449 448
450 449 ax = self.axes[4 * n + 2]
451 450 if ax.firsttime:
452 451 ax.plt = ax.pcolormesh(x, y, numpy.flip(coh,axis=0).T,
453 452 vmin=0,
454 453 vmax=1,
455 454 cmap=plt.get_cmap(self.colormap_coh)
456 455 )
457 456 else:
458 457 ax.plt.set_array(numpy.flip(coh,axis=0).T.ravel())
459 458 self.titles.append(
460 459 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
461 460
462 461 ax = self.axes[4 * n + 3]
463 462 if ax.firsttime:
464 463 ax.plt = ax.pcolormesh(x, y, numpy.flip(phase,axis=0).T,
465 464 vmin=-180,
466 465 vmax=180,
467 466 cmap=plt.get_cmap(self.colormap_phase)
468 467 )
469 468 else:
470 469 ax.plt.set_array(numpy.flip(phase,axis=0).T.ravel())
471 470 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
472 471
473 472
474 473 class CrossSpectra2Plot(Plot):
475 474
476 475 CODE = 'cspc'
477 476 colormap = 'jet'
478 477 plot_type = 'pcolor'
479 478 zmin_coh = None
480 479 zmax_coh = None
481 480 zmin_phase = None
482 481 zmax_phase = None
483 482
484 483 def setup(self):
485 484
486 485 self.ncols = 1
487 486 self.nrows = len(self.data.pairs)
488 487 self.nplots = self.nrows * 1
489 488 self.width = 3.1 * self.ncols
490 489 self.height = 5 * self.nrows
491 490 self.ylabel = 'Range [km]'
492 491 self.showprofile = False
493 492 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
494 493
495 494 def plot(self):
496 495
497 496 if self.xaxis == "frequency":
498 497 x = self.data.xrange[0]
499 498 self.xlabel = "Frequency (kHz)"
500 499 elif self.xaxis == "time":
501 500 x = self.data.xrange[1]
502 501 self.xlabel = "Time (ms)"
503 502 else:
504 503 x = self.data.xrange[2]
505 504 self.xlabel = "Velocity (m/s)"
506 505
507 506 self.titles = []
508 507
509 508
510 509 y = self.data.heights
511 510 self.y = y
512 511 #nspc = self.data['spc']
513 512 #print(numpy.shape(self.data['spc']))
514 513 #spc = self.data['cspc'][0]
515 514 #print(numpy.shape(spc))
516 515 #exit()
517 516 cspc = self.data['cspc'][1]
518 517 #print(numpy.shape(cspc))
519 518 #exit()
520 519
521 520 for n in range(self.nrows):
522 521 noise = self.data['noise'][:,-1]
523 522 pair = self.data.pairs[n]
524 523 #print(pair) #exit()
525 524
526 525
527 526
528 527 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
529 528
530 529 #print(out[:,53])
531 530 #exit()
532 531 cross = numpy.abs(out)
533 532 z = cross/self.data.nFactor
534 533 #print("here")
535 534 #print(dataOut.data_spc[0,0,0])
536 535 #exit()
537 536
538 537 cross = 10*numpy.log10(z)
539 538 #print(numpy.shape(cross))
540 539 #print(cross[0,:])
541 540 #print(self.data.nFactor)
542 541 #exit()
543 542 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
544 543
545 544 ax = self.axes[1 * n]
546 545 if ax.firsttime:
547 546 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
548 547 self.xmin = self.xmin if self.xmin else -self.xmax
549 548 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
550 549 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
551 550 ax.plt = ax.pcolormesh(x, y, cross.T,
552 551 vmin=self.zmin,
553 552 vmax=self.zmax,
554 553 cmap=plt.get_cmap(self.colormap)
555 554 )
556 555 else:
557 556 ax.plt.set_array(cross.T.ravel())
558 557 self.titles.append(
559 558 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
560 559
561 560
562 561 class CrossSpectra3Plot(Plot):
563 562
564 563 CODE = 'cspc'
565 564 colormap = 'jet'
566 565 plot_type = 'pcolor'
567 566 zmin_coh = None
568 567 zmax_coh = None
569 568 zmin_phase = None
570 569 zmax_phase = None
571 570
572 571 def setup(self):
573 572
574 573 self.ncols = 3
575 574 self.nrows = len(self.data.pairs)
576 575 self.nplots = self.nrows * 3
577 576 self.width = 3.1 * self.ncols
578 577 self.height = 5 * self.nrows
579 578 self.ylabel = 'Range [km]'
580 579 self.showprofile = False
581 580 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
582 581
583 582 def plot(self):
584 583
585 584 if self.xaxis == "frequency":
586 585 x = self.data.xrange[0]
587 586 self.xlabel = "Frequency (kHz)"
588 587 elif self.xaxis == "time":
589 588 x = self.data.xrange[1]
590 589 self.xlabel = "Time (ms)"
591 590 else:
592 591 x = self.data.xrange[2]
593 592 self.xlabel = "Velocity (m/s)"
594 593
595 594 self.titles = []
596 595
597 596
598 597 y = self.data.heights
599 598 self.y = y
600 599 #nspc = self.data['spc']
601 600 #print(numpy.shape(self.data['spc']))
602 601 #spc = self.data['cspc'][0]
603 602 #print(numpy.shape(spc))
604 603 #exit()
605 604 cspc = self.data['cspc'][1]
606 605 #print(numpy.shape(cspc))
607 606 #exit()
608 607
609 608 for n in range(self.nrows):
610 609 noise = self.data['noise'][:,-1]
611 610 pair = self.data.pairs[n]
612 611 #print(pair) #exit()
613 612
614 613
615 614
616 615 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
617 616
618 617 #print(out[:,53])
619 618 #exit()
620 619 cross = numpy.abs(out)
621 620 z = cross/self.data.nFactor
622 621 cross = 10*numpy.log10(z)
623 622
624 623 out_r= out.real/self.data.nFactor
625 624 #out_r = 10*numpy.log10(out_r)
626 625
627 626 out_i= out.imag/self.data.nFactor
628 627 #out_i = 10*numpy.log10(out_i)
629 628 #print(numpy.shape(cross))
630 629 #print(cross[0,:])
631 630 #print(self.data.nFactor)
632 631 #exit()
633 632 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
634 633
635 634 ax = self.axes[3 * n]
636 635 if ax.firsttime:
637 636 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
638 637 self.xmin = self.xmin if self.xmin else -self.xmax
639 638 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
640 639 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
641 640 ax.plt = ax.pcolormesh(x, y, cross.T,
642 641 vmin=self.zmin,
643 642 vmax=self.zmax,
644 643 cmap=plt.get_cmap(self.colormap)
645 644 )
646 645 else:
647 646 ax.plt.set_array(cross.T.ravel())
648 647 self.titles.append(
649 648 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
650 649
651 650 ax = self.axes[3 * n + 1]
652 651 if ax.firsttime:
653 652 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
654 653 self.xmin = self.xmin if self.xmin else -self.xmax
655 654 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
656 655 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
657 656 ax.plt = ax.pcolormesh(x, y, out_r.T,
658 657 vmin=-1.e6,
659 658 vmax=0,
660 659 cmap=plt.get_cmap(self.colormap)
661 660 )
662 661 else:
663 662 ax.plt.set_array(out_r.T.ravel())
664 663 self.titles.append(
665 664 'Cross Spectra Real Ch{} * Ch{}'.format(pair[0], pair[1]))
666 665
667 666 ax = self.axes[3 * n + 2]
668 667
669 668
670 669 if ax.firsttime:
671 670 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
672 671 self.xmin = self.xmin if self.xmin else -self.xmax
673 672 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
674 673 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
675 674 ax.plt = ax.pcolormesh(x, y, out_i.T,
676 675 vmin=-1.e6,
677 676 vmax=1.e6,
678 677 cmap=plt.get_cmap(self.colormap)
679 678 )
680 679 else:
681 680 ax.plt.set_array(out_i.T.ravel())
682 681 self.titles.append(
683 682 'Cross Spectra Imag Ch{} * Ch{}'.format(pair[0], pair[1]))
684 683
685 684 class RTIPlot(Plot):
686 685 '''
687 686 Plot for RTI data
688 687 '''
689 688
690 689 CODE = 'rti'
691 690 colormap = 'jet'
692 691 plot_type = 'pcolorbuffer'
693 692
694 693 def setup(self):
695 694 self.xaxis = 'time'
696 695 self.ncols = 1
697 696 self.nrows = len(self.data.channels)
698 697 self.nplots = len(self.data.channels)
699 698 self.ylabel = 'Range [km]'
700 699 self.xlabel = 'Time'
701 700 self.cb_label = 'dB'
702 701 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
703 702 self.titles = ['{} Channel {}'.format(
704 703 self.CODE.upper(), x) for x in range(self.nrows)]
705 704
706 705 def update(self, dataOut):
707 706
708 707 data = {}
709 708 meta = {}
710 709 data['rti'] = dataOut.getPower()
711 710 #print(numpy.shape(data['rti']))
712 711
713 712 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
714 713
715 714 return data, meta
716 715
717 716 def plot(self):
718 717
719 718 self.x = self.data.times
720 719 self.y = self.data.yrange
721 720 self.z = self.data[self.CODE]
722 721 #print("Inside RTI: ", self.z)
723 722 self.z = numpy.ma.masked_invalid(self.z)
724 723
725 724 if self.decimation is None:
726 725 x, y, z = self.fill_gaps(self.x, self.y, self.z)
727 726 else:
728 727 x, y, z = self.fill_gaps(*self.decimate())
729 728 #print("self.z: ", self.z)
730 729 #exit(1)
731 730 '''
732 731 if not isinstance(self.zmin, collections.abc.Sequence):
733 732 if not self.zmin:
734 733 self.zmin = [numpy.min(self.z)]*len(self.axes)
735 734 else:
736 735 self.zmin = [self.zmin]*len(self.axes)
737 736
738 737 if not isinstance(self.zmax, collections.abc.Sequence):
739 738 if not self.zmax:
740 739 self.zmax = [numpy.max(self.z)]*len(self.axes)
741 740 else:
742 741 self.zmax = [self.zmax]*len(self.axes)
743 742 '''
744 743 for n, ax in enumerate(self.axes):
745 744
746 745 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
747 746 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
748 747
749 748 if ax.firsttime:
750 749 if self.zlimits is not None:
751 750 self.zmin, self.zmax = self.zlimits[n]
752 751 ax.plt = ax.pcolormesh(x, y, z[n].T,
753 752 vmin=self.zmin,
754 753 vmax=self.zmax,
755 754 cmap=plt.get_cmap(self.colormap)
756 755 )
757 756 if self.showprofile:
758 757 ax.plot_profile = self.pf_axes[n].plot(
759 758 self.data['rti'][n][-1], self.y)[0]
760 759 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
761 760 color="k", linestyle="dashed", lw=1)[0]
762 761 else:
763 762 if self.zlimits is not None:
764 763 self.zmin, self.zmax = self.zlimits[n]
765 764 ax.plt.remove()
766 765 ax.plt = ax.pcolormesh(x, y, z[n].T,
767 766 vmin=self.zmin,
768 767 vmax=self.zmax,
769 768 cmap=plt.get_cmap(self.colormap)
770 769 )
771 770 if self.showprofile:
772 771 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
773 772 ax.plot_noise.set_data(numpy.repeat(
774 773 self.data['noise'][n][-1], len(self.y)), self.y)
775 774
776 775
777 776 class SpectrogramPlot(Plot):
778 777 '''
779 778 Plot for Spectrogram data
780 779 '''
781 780
782 781 CODE = 'Spectrogram_Profile'
783 782 colormap = 'binary'
784 783 plot_type = 'pcolorbuffer'
785 784
786 785 def setup(self):
787 786 self.xaxis = 'time'
788 787 self.ncols = 1
789 788 self.nrows = len(self.data.channels)
790 789 self.nplots = len(self.data.channels)
791 790 self.xlabel = 'Time'
792 791 #self.cb_label = 'dB'
793 792 self.plots_adjust.update({'hspace':1.2, 'left': 0.1, 'bottom': 0.12, 'right':0.95})
794 793 self.titles = []
795 794
796 795 #self.titles = ['{} Channel {} \n H = {} km ({} - {})'.format(
797 796 #self.CODE.upper(), x, self.data.heightList[self.data.hei], self.data.heightList[self.data.hei],self.data.heightList[self.data.hei]+(self.data.DH*self.data.nProfiles)) for x in range(self.nrows)]
798 797
799 798 self.titles = ['{} Channel {}'.format(
800 799 self.CODE.upper(), x) for x in range(self.nrows)]
801 800
802 801
803 802 def update(self, dataOut):
804 803 data = {}
805 804 meta = {}
806 805
807 806 maxHei = 1620#+12000
808 807 maxHei = 1180
809 808 maxHei = 500
810 809 indb = numpy.where(dataOut.heightList <= maxHei)
811 810 hei = indb[0][-1]
812 811 #print(dataOut.heightList)
813 812
814 813 factor = dataOut.nIncohInt
815 814 z = dataOut.data_spc[:,:,hei] / factor
816 815 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
817 816 #buffer = 10 * numpy.log10(z)
818 817
819 818 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
820 819
821 820
822 821 #self.hei = hei
823 822 #self.heightList = dataOut.heightList
824 823 #self.DH = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
825 824 #self.nProfiles = dataOut.nProfiles
826 825
827 826 data['Spectrogram_Profile'] = 10 * numpy.log10(z)
828 827
829 828 data['hei'] = hei
830 829 data['DH'] = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
831 830 data['nProfiles'] = dataOut.nProfiles
832 831 #meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
833 832 '''
834 833 import matplotlib.pyplot as plt
835 834 plt.plot(10 * numpy.log10(z[0,:]))
836 835 plt.show()
837 836
838 837 from time import sleep
839 838 sleep(10)
840 839 '''
841 840 return data, meta
842 841
843 842 def plot(self):
844 843
845 844 self.x = self.data.times
846 845 self.z = self.data[self.CODE]
847 846 self.y = self.data.xrange[0]
848 847
849 848 hei = self.data['hei'][-1]
850 849 DH = self.data['DH'][-1]
851 850 nProfiles = self.data['nProfiles'][-1]
852 851
853 852 self.ylabel = "Frequency (kHz)"
854 853
855 854 self.z = numpy.ma.masked_invalid(self.z)
856 855
857 856 if self.decimation is None:
858 857 x, y, z = self.fill_gaps(self.x, self.y, self.z)
859 858 else:
860 859 x, y, z = self.fill_gaps(*self.decimate())
861 860
862 861 for n, ax in enumerate(self.axes):
863 862 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
864 863 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
865 864 data = self.data[-1]
866 865 if ax.firsttime:
867 866 ax.plt = ax.pcolormesh(x, y, z[n].T,
868 867 vmin=self.zmin,
869 868 vmax=self.zmax,
870 869 cmap=plt.get_cmap(self.colormap)
871 870 )
872 871 else:
873 872 ax.plt.remove()
874 873 ax.plt = ax.pcolormesh(x, y, z[n].T,
875 874 vmin=self.zmin,
876 875 vmax=self.zmax,
877 876 cmap=plt.get_cmap(self.colormap)
878 877 )
879 878
880 879 #self.titles.append('Spectrogram')
881 880
882 881 #self.titles.append('{} Channel {} \n H = {} km ({} - {})'.format(
883 882 #self.CODE.upper(), x, y[hei], y[hei],y[hei]+(DH*nProfiles)))
884 883
885 884
886 885
887 886
888 887 class CoherencePlot(RTIPlot):
889 888 '''
890 889 Plot for Coherence data
891 890 '''
892 891
893 892 CODE = 'coh'
894 893
895 894 def setup(self):
896 895 self.xaxis = 'time'
897 896 self.ncols = 1
898 897 self.nrows = len(self.data.pairs)
899 898 self.nplots = len(self.data.pairs)
900 899 self.ylabel = 'Range [km]'
901 900 self.xlabel = 'Time'
902 901 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
903 902 if self.CODE == 'coh':
904 903 self.cb_label = ''
905 904 self.titles = [
906 905 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
907 906 else:
908 907 self.cb_label = 'Degrees'
909 908 self.titles = [
910 909 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
911 910
912 911 def update(self, dataOut):
913 912
914 913 data = {}
915 914 meta = {}
916 915 data['coh'] = dataOut.getCoherence()
917 916 meta['pairs'] = dataOut.pairsList
918 917
919 918 return data, meta
920 919
921 920 class PhasePlot(CoherencePlot):
922 921 '''
923 922 Plot for Phase map data
924 923 '''
925 924
926 925 CODE = 'phase'
927 926 colormap = 'seismic'
928 927
929 928 def update(self, dataOut):
930 929
931 930 data = {}
932 931 meta = {}
933 932 data['phase'] = dataOut.getCoherence(phase=True)
934 933 meta['pairs'] = dataOut.pairsList
935 934
936 935 return data, meta
937 936
938 937 class NoisePlot(Plot):
939 938 '''
940 939 Plot for noise
941 940 '''
942 941
943 942 CODE = 'noise'
944 943 plot_type = 'scatterbuffer'
945 944
946 945 def setup(self):
947 946 self.xaxis = 'time'
948 947 self.ncols = 1
949 948 self.nrows = 1
950 949 self.nplots = 1
951 950 self.ylabel = 'Intensity [dB]'
952 951 self.xlabel = 'Time'
953 952 self.titles = ['Noise']
954 953 self.colorbar = False
955 954 self.plots_adjust.update({'right': 0.85 })
956 955
957 956 def update(self, dataOut):
958 957
959 958 data = {}
960 959 meta = {}
961 960 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
962 961 meta['yrange'] = numpy.array([])
963 962
964 963 return data, meta
965 964
966 965 def plot(self):
967 966
968 967 x = self.data.times
969 968 xmin = self.data.min_time
970 969 xmax = xmin + self.xrange * 60 * 60
971 970 Y = self.data['noise']
972 971
973 972 if self.axes[0].firsttime:
974 973 self.ymin = numpy.nanmin(Y) - 5
975 974 self.ymax = numpy.nanmax(Y) + 5
976 975 for ch in self.data.channels:
977 976 y = Y[ch]
978 977 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
979 978 plt.legend(bbox_to_anchor=(1.18, 1.0))
980 979 else:
981 980 for ch in self.data.channels:
982 981 y = Y[ch]
983 982 self.axes[0].lines[ch].set_data(x, y)
984 983
985 984 self.ymin = numpy.nanmin(Y) - 5
986 985 self.ymax = numpy.nanmax(Y) + 10
987 986
988 987
989 988 class PowerProfilePlot(Plot):
990 989
991 990 CODE = 'pow_profile'
992 991 plot_type = 'scatter'
993 992
994 993 def setup(self):
995 994
996 995 self.ncols = 1
997 996 self.nrows = 1
998 997 self.nplots = 1
999 998 self.height = 4
1000 999 self.width = 3
1001 1000 self.ylabel = 'Range [km]'
1002 1001 self.xlabel = 'Intensity [dB]'
1003 1002 self.titles = ['Power Profile']
1004 1003 self.colorbar = False
1005 1004
1006 1005 def update(self, dataOut):
1007 1006
1008 1007 data = {}
1009 1008 meta = {}
1010 1009 data[self.CODE] = dataOut.getPower()
1011 1010
1012 1011 return data, meta
1013 1012
1014 1013 def plot(self):
1015 1014
1016 1015 y = self.data.yrange
1017 1016 self.y = y
1018 1017
1019 1018 x = self.data[-1][self.CODE]
1020 1019
1021 1020 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
1022 1021 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
1023 1022
1024 1023 if self.axes[0].firsttime:
1025 1024 for ch in self.data.channels:
1026 1025 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
1027 1026 plt.legend()
1028 1027 else:
1029 1028 for ch in self.data.channels:
1030 1029 self.axes[0].lines[ch].set_data(x[ch], y)
1031 1030
1032 1031
1033 1032 class SpectraCutPlot(Plot):
1034 1033
1035 1034 CODE = 'spc_cut'
1036 1035 plot_type = 'scatter'
1037 1036 buffering = False
1038 1037
1039 1038 def setup(self):
1040 1039
1041 1040 self.nplots = len(self.data.channels)
1042 1041 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
1043 1042 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
1044 1043 self.width = 3.4 * self.ncols + 1.5
1045 1044 self.height = 3 * self.nrows
1046 1045 self.ylabel = 'Power [dB]'
1047 1046 self.colorbar = False
1048 1047 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
1049 1048
1050 1049 def update(self, dataOut):
1051 1050
1052 1051 data = {}
1053 1052 meta = {}
1054 1053 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
1055 1054 data['spc'] = spc
1056 1055 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
1057 1056 if self.CODE == 'cut_gaussian_fit':
1058 1057 data['gauss_fit0'] = 10*numpy.log10(dataOut.GaussFit0/dataOut.normFactor)
1059 1058 data['gauss_fit1'] = 10*numpy.log10(dataOut.GaussFit1/dataOut.normFactor)
1060 1059 return data, meta
1061 1060
1062 1061 def plot(self):
1063 1062 if self.xaxis == "frequency":
1064 1063 x = self.data.xrange[0][1:]
1065 1064 self.xlabel = "Frequency (kHz)"
1066 1065 elif self.xaxis == "time":
1067 1066 x = self.data.xrange[1]
1068 1067 self.xlabel = "Time (ms)"
1069 1068 else:
1070 1069 x = self.data.xrange[2][:-1]
1071 1070 self.xlabel = "Velocity (m/s)"
1072 1071
1073 1072 if self.CODE == 'cut_gaussian_fit':
1074 1073 x = self.data.xrange[2][:-1]
1075 1074 self.xlabel = "Velocity (m/s)"
1076 1075
1077 1076 self.titles = []
1078 1077
1079 1078 y = self.data.yrange
1080 1079 data = self.data[-1]
1081 1080 z = data['spc']
1082 1081
1083 1082 if self.height_index:
1084 1083 index = numpy.array(self.height_index)
1085 1084 else:
1086 1085 index = numpy.arange(0, len(y), int((len(y))/9))
1087 1086
1088 1087 for n, ax in enumerate(self.axes):
1089 1088 if self.CODE == 'cut_gaussian_fit':
1090 1089 gau0 = data['gauss_fit0']
1091 1090 gau1 = data['gauss_fit1']
1092 1091 if ax.firsttime:
1093 1092 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
1094 1093 self.xmin = self.xmin if self.xmin else -self.xmax
1095 1094 self.ymin = self.ymin if self.ymin else numpy.nanmin(z[:,:,index])
1096 1095 self.ymax = self.ymax if self.ymax else numpy.nanmax(z[:,:,index])
1097 1096 #print(self.ymax)
1098 1097 #print(z[n, :, index])
1099 1098 ax.plt = ax.plot(x, z[n, :, index].T, lw=0.25)
1100 1099 if self.CODE == 'cut_gaussian_fit':
1101 1100 ax.plt_gau0 = ax.plot(x, gau0[n, :, index].T, lw=1, linestyle='-.')
1102 1101 for i, line in enumerate(ax.plt_gau0):
1103 1102 line.set_color(ax.plt[i].get_color())
1104 1103 ax.plt_gau1 = ax.plot(x, gau1[n, :, index].T, lw=1, linestyle='--')
1105 1104 for i, line in enumerate(ax.plt_gau1):
1106 1105 line.set_color(ax.plt[i].get_color())
1107 1106 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
1108 1107 self.figures[0].legend(ax.plt, labels, loc='center right')
1109 1108 else:
1110 1109 for i, line in enumerate(ax.plt):
1111 1110 line.set_data(x, z[n, :, index[i]].T)
1112 1111 for i, line in enumerate(ax.plt_gau0):
1113 1112 line.set_data(x, gau0[n, :, index[i]].T)
1114 1113 line.set_color(ax.plt[i].get_color())
1115 1114 for i, line in enumerate(ax.plt_gau1):
1116 1115 line.set_data(x, gau1[n, :, index[i]].T)
1117 1116 line.set_color(ax.plt[i].get_color())
1118 1117 self.titles.append('CH {}'.format(n))
1119 1118
1120 1119
1121 1120 class BeaconPhase(Plot):
1122 1121
1123 1122 __isConfig = None
1124 1123 __nsubplots = None
1125 1124
1126 1125 PREFIX = 'beacon_phase'
1127 1126
1128 1127 def __init__(self):
1129 1128 Plot.__init__(self)
1130 1129 self.timerange = 24*60*60
1131 1130 self.isConfig = False
1132 1131 self.__nsubplots = 1
1133 1132 self.counter_imagwr = 0
1134 1133 self.WIDTH = 800
1135 1134 self.HEIGHT = 400
1136 1135 self.WIDTHPROF = 120
1137 1136 self.HEIGHTPROF = 0
1138 1137 self.xdata = None
1139 1138 self.ydata = None
1140 1139
1141 1140 self.PLOT_CODE = BEACON_CODE
1142 1141
1143 1142 self.FTP_WEI = None
1144 1143 self.EXP_CODE = None
1145 1144 self.SUB_EXP_CODE = None
1146 1145 self.PLOT_POS = None
1147 1146
1148 1147 self.filename_phase = None
1149 1148
1150 1149 self.figfile = None
1151 1150
1152 1151 self.xmin = None
1153 1152 self.xmax = None
1154 1153
1155 1154 def getSubplots(self):
1156 1155
1157 1156 ncol = 1
1158 1157 nrow = 1
1159 1158
1160 1159 return nrow, ncol
1161 1160
1162 1161 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1163 1162
1164 1163 self.__showprofile = showprofile
1165 1164 self.nplots = nplots
1166 1165
1167 1166 ncolspan = 7
1168 1167 colspan = 6
1169 1168 self.__nsubplots = 2
1170 1169
1171 1170 self.createFigure(id = id,
1172 1171 wintitle = wintitle,
1173 1172 widthplot = self.WIDTH+self.WIDTHPROF,
1174 1173 heightplot = self.HEIGHT+self.HEIGHTPROF,
1175 1174 show=show)
1176 1175
1177 1176 nrow, ncol = self.getSubplots()
1178 1177
1179 1178 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1180 1179
1181 1180 def save_phase(self, filename_phase):
1182 1181 f = open(filename_phase,'w+')
1183 1182 f.write('\n\n')
1184 1183 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1185 1184 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1186 1185 f.close()
1187 1186
1188 1187 def save_data(self, filename_phase, data, data_datetime):
1189 1188 f=open(filename_phase,'a')
1190 1189 timetuple_data = data_datetime.timetuple()
1191 1190 day = str(timetuple_data.tm_mday)
1192 1191 month = str(timetuple_data.tm_mon)
1193 1192 year = str(timetuple_data.tm_year)
1194 1193 hour = str(timetuple_data.tm_hour)
1195 1194 minute = str(timetuple_data.tm_min)
1196 1195 second = str(timetuple_data.tm_sec)
1197 1196 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1198 1197 f.close()
1199 1198
1200 1199 def plot(self):
1201 1200 log.warning('TODO: Not yet implemented...')
1202 1201
1203 1202 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1204 1203 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1205 1204 timerange=None,
1206 1205 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1207 1206 server=None, folder=None, username=None, password=None,
1208 1207 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1209 1208
1210 1209 if dataOut.flagNoData:
1211 1210 return dataOut
1212 1211
1213 1212 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1214 1213 return
1215 1214
1216 1215 if pairsList == None:
1217 1216 pairsIndexList = dataOut.pairsIndexList[:10]
1218 1217 else:
1219 1218 pairsIndexList = []
1220 1219 for pair in pairsList:
1221 1220 if pair not in dataOut.pairsList:
1222 1221 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1223 1222 pairsIndexList.append(dataOut.pairsList.index(pair))
1224 1223
1225 1224 if pairsIndexList == []:
1226 1225 return
1227 1226
1228 1227 # if len(pairsIndexList) > 4:
1229 1228 # pairsIndexList = pairsIndexList[0:4]
1230 1229
1231 1230 hmin_index = None
1232 1231 hmax_index = None
1233 1232
1234 1233 if hmin != None and hmax != None:
1235 1234 indexes = numpy.arange(dataOut.nHeights)
1236 1235 hmin_list = indexes[dataOut.heightList >= hmin]
1237 1236 hmax_list = indexes[dataOut.heightList <= hmax]
1238 1237
1239 1238 if hmin_list.any():
1240 1239 hmin_index = hmin_list[0]
1241 1240
1242 1241 if hmax_list.any():
1243 1242 hmax_index = hmax_list[-1]+1
1244 1243
1245 1244 x = dataOut.getTimeRange()
1246 1245
1247 1246 thisDatetime = dataOut.datatime
1248 1247
1249 1248 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1250 1249 xlabel = "Local Time"
1251 1250 ylabel = "Phase (degrees)"
1252 1251
1253 1252 update_figfile = False
1254 1253
1255 1254 nplots = len(pairsIndexList)
1256 1255 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1257 1256 phase_beacon = numpy.zeros(len(pairsIndexList))
1258 1257 for i in range(nplots):
1259 1258 pair = dataOut.pairsList[pairsIndexList[i]]
1260 1259 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1261 1260 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1262 1261 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1263 1262 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1264 1263 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1265 1264
1266 1265 if dataOut.beacon_heiIndexList:
1267 1266 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1268 1267 else:
1269 1268 phase_beacon[i] = numpy.average(phase)
1270 1269
1271 1270 if not self.isConfig:
1272 1271
1273 1272 nplots = len(pairsIndexList)
1274 1273
1275 1274 self.setup(id=id,
1276 1275 nplots=nplots,
1277 1276 wintitle=wintitle,
1278 1277 showprofile=showprofile,
1279 1278 show=show)
1280 1279
1281 1280 if timerange != None:
1282 1281 self.timerange = timerange
1283 1282
1284 1283 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1285 1284
1286 1285 if ymin == None: ymin = 0
1287 1286 if ymax == None: ymax = 360
1288 1287
1289 1288 self.FTP_WEI = ftp_wei
1290 1289 self.EXP_CODE = exp_code
1291 1290 self.SUB_EXP_CODE = sub_exp_code
1292 1291 self.PLOT_POS = plot_pos
1293 1292
1294 1293 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1295 1294 self.isConfig = True
1296 1295 self.figfile = figfile
1297 1296 self.xdata = numpy.array([])
1298 1297 self.ydata = numpy.array([])
1299 1298
1300 1299 update_figfile = True
1301 1300
1302 1301 #open file beacon phase
1303 1302 path = '%s%03d' %(self.PREFIX, self.id)
1304 1303 beacon_file = os.path.join(path,'%s.txt'%self.name)
1305 1304 self.filename_phase = os.path.join(figpath,beacon_file)
1306 1305 #self.save_phase(self.filename_phase)
1307 1306
1308 1307
1309 1308 #store data beacon phase
1310 1309 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1311 1310
1312 1311 self.setWinTitle(title)
1313 1312
1314 1313
1315 1314 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1316 1315
1317 1316 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1318 1317
1319 1318 axes = self.axesList[0]
1320 1319
1321 1320 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1322 1321
1323 1322 if len(self.ydata)==0:
1324 1323 self.ydata = phase_beacon.reshape(-1,1)
1325 1324 else:
1326 1325 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1327 1326
1328 1327
1329 1328 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1330 1329 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1331 1330 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1332 1331 XAxisAsTime=True, grid='both'
1333 1332 )
1334 1333
1335 1334 self.draw()
1336 1335
1337 1336 if dataOut.ltctime >= self.xmax:
1338 1337 self.counter_imagwr = wr_period
1339 1338 self.isConfig = False
1340 1339 update_figfile = True
1341 1340
1342 1341 self.save(figpath=figpath,
1343 1342 figfile=figfile,
1344 1343 save=save,
1345 1344 ftp=ftp,
1346 1345 wr_period=wr_period,
1347 1346 thisDatetime=thisDatetime,
1348 1347 update_figfile=update_figfile)
1349 1348
1350 1349 return dataOut
@@ -1,1428 +1,1428
1 1
2 2 import os
3 3 import time
4 4 import math
5 5 import datetime
6 6 import numpy
7 7
8 8 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator #YONG
9 9
10 10 from .jroplot_spectra import RTIPlot, NoisePlot
11 11
12 12 from schainpy.utils import log
13 13 from .plotting_codes import *
14 14
15 15 from schainpy.model.graphics.jroplot_base import Plot, plt
16 16
17 17 import matplotlib.pyplot as plt
18 18 import matplotlib.colors as colors
19 19 from matplotlib.ticker import MultipleLocator, LogLocator, NullFormatter
20 20
21 21 class RTIDPPlot(RTIPlot):
22 22 '''
23 23 Written by R. Flores
24 24 '''
25 25 '''Plot for RTI Double Pulse Experiment Using Cross Products Analysis
26 26 '''
27 27
28 28 CODE = 'RTIDP'
29 29 colormap = 'jet'
30 30 plot_name = 'RTI'
31 31 plot_type = 'pcolorbuffer'
32 32
33 33 def setup(self):
34 34 self.xaxis = 'time'
35 35 self.ncols = 1
36 36 self.nrows = 3
37 37 self.nplots = self.nrows
38 38
39 39 self.ylabel = 'Range [km]'
40 40 self.xlabel = 'Time (LT)'
41 41
42 42 self.cb_label = 'Intensity (dB)'
43 43
44 44 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
45 45
46 46 self.titles = ['{} Channel {}'.format(
47 47 self.plot_name.upper(), '0x1'),'{} Channel {}'.format(
48 48 self.plot_name.upper(), '0'),'{} Channel {}'.format(
49 49 self.plot_name.upper(), '1')]
50 50
51 51 def update(self, dataOut):
52 52
53 53 data = {}
54 54 meta = {}
55 55 data['rti'] = dataOut.data_for_RTI_DP
56 56 data['NDP'] = dataOut.NDP
57 57
58 58 return data, meta
59 59
60 60 def plot(self):
61 61
62 62 NDP = self.data['NDP'][-1]
63 63 self.x = self.data.times
64 64 self.y = self.data.yrange[0:NDP]
65 65 self.z = self.data['rti']
66 66 self.z = numpy.ma.masked_invalid(self.z)
67 67
68 68 if self.decimation is None:
69 69 x, y, z = self.fill_gaps(self.x, self.y, self.z)
70 70 else:
71 71 x, y, z = self.fill_gaps(*self.decimate())
72 72
73 73 for n, ax in enumerate(self.axes):
74 74
75 75 self.zmax = self.zmax if self.zmax is not None else numpy.max(
76 76 self.z[1][0,12:40])
77 77 self.zmin = self.zmin if self.zmin is not None else numpy.min(
78 78 self.z[1][0,12:40])
79 79
80 80 if ax.firsttime:
81 81
82 82 if self.zlimits is not None:
83 83 self.zmin, self.zmax = self.zlimits[n]
84 84
85 85 ax.plt = ax.pcolormesh(x, y, z[n].T,
86 86 vmin=self.zmin,
87 87 vmax=self.zmax,
88 88 cmap=plt.get_cmap(self.colormap)
89 89 )
90 90 else:
91 91 #if self.zlimits is not None:
92 92 #self.zmin, self.zmax = self.zlimits[n]
93 93 ax.plt.remove()
94 94 ax.plt = ax.pcolormesh(x, y, z[n].T,
95 95 vmin=self.zmin,
96 96 vmax=self.zmax,
97 97 cmap=plt.get_cmap(self.colormap)
98 98 )
99 99
100 100
101 101 class RTILPPlot(RTIPlot):
102 102 '''
103 103 Written by R. Flores
104 104 '''
105 105 '''
106 106 Plot for RTI Long Pulse Using Cross Products Analysis
107 107 '''
108 108
109 109 CODE = 'RTILP'
110 110 colormap = 'jet'
111 111 plot_name = 'RTI LP'
112 112 plot_type = 'pcolorbuffer'
113 113
114 114 def setup(self):
115 115 self.xaxis = 'time'
116 116 self.ncols = 1
117 117 self.nrows = 2
118 118 self.nplots = self.nrows
119 119
120 120 self.ylabel = 'Range [km]'
121 121 self.xlabel = 'Time (LT)'
122 122
123 123 self.cb_label = 'Intensity (dB)'
124 124
125 125 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
126 126
127 127
128 128 self.titles = ['{} Channel {}'.format(
129 129 self.plot_name.upper(), '0'),'{} Channel {}'.format(
130 130 self.plot_name.upper(), '1'),'{} Channel {}'.format(
131 131 self.plot_name.upper(), '2'),'{} Channel {}'.format(
132 132 self.plot_name.upper(), '3')]
133 133
134 134
135 135 def update(self, dataOut):
136 136
137 137 data = {}
138 138 meta = {}
139 139 data['rti'] = dataOut.data_for_RTI_LP
140 140 data['NRANGE'] = dataOut.NRANGE
141 141
142 142 return data, meta
143 143
144 144 def plot(self):
145 145
146 146 NRANGE = self.data['NRANGE'][-1]
147 147 self.x = self.data.times
148 148 self.y = self.data.yrange[0:NRANGE]
149 149
150 150 self.z = self.data['rti']
151 151
152 152 self.z = numpy.ma.masked_invalid(self.z)
153 153
154 154 if self.decimation is None:
155 155 x, y, z = self.fill_gaps(self.x, self.y, self.z)
156 156 else:
157 157 x, y, z = self.fill_gaps(*self.decimate())
158 158
159 159 for n, ax in enumerate(self.axes):
160 160
161 161 self.zmax = self.zmax if self.zmax is not None else numpy.max(
162 162 self.z[1][0,12:40])
163 163 self.zmin = self.zmin if self.zmin is not None else numpy.min(
164 164 self.z[1][0,12:40])
165 165
166 166 if ax.firsttime:
167 167
168 168 if self.zlimits is not None:
169 169 self.zmin, self.zmax = self.zlimits[n]
170 170
171 171
172 172 ax.plt = ax.pcolormesh(x, y, z[n].T,
173 173 vmin=self.zmin,
174 174 vmax=self.zmax,
175 175 cmap=plt.get_cmap(self.colormap)
176 176 )
177 177
178 178 else:
179 179 if self.zlimits is not None:
180 180 self.zmin, self.zmax = self.zlimits[n]
181 181 ax.plt.remove()
182 182 ax.plt = ax.pcolormesh(x, y, z[n].T,
183 183 vmin=self.zmin,
184 184 vmax=self.zmax,
185 185 cmap=plt.get_cmap(self.colormap)
186 186 )
187 187
188 188
189 189 class DenRTIPlot(RTIPlot):
190 190 '''
191 191 Written by R. Flores
192 192 '''
193 193 '''
194 194 RTI Plot for Electron Densities
195 195 '''
196 196
197 197 CODE = 'denrti'
198 198 colormap = 'jet'
199 199
200 200 def setup(self):
201 201 self.xaxis = 'time'
202 202 self.ncols = 1
203 203 self.nrows = self.data.shape(self.CODE)[0]
204 204 self.nplots = self.nrows
205 205
206 206 self.ylabel = 'Range [km]'
207 207 self.xlabel = 'Time (LT)'
208 208
209 209 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
210 210
211 211 if self.CODE == 'denrti':
212 212 self.cb_label = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
213 213
214 214 self.titles = ['Electron Density RTI']
215 215
216 216 def update(self, dataOut):
217 217
218 218 data = {}
219 219 meta = {}
220 220
221 221 data['denrti'] = dataOut.DensityFinal*1.e-6 #To Plot in cm^-3
222 222
223 223 return data, meta
224 224
225 225 def plot(self):
226 226
227 227 self.x = self.data.times
228 228 self.y = self.data.yrange
229 229
230 230 self.z = self.data[self.CODE]
231 231
232 232 self.z = numpy.ma.masked_invalid(self.z)
233 233
234 234 if self.decimation is None:
235 235 x, y, z = self.fill_gaps(self.x, self.y, self.z)
236 236 else:
237 237 x, y, z = self.fill_gaps(*self.decimate())
238 238
239 239 for n, ax in enumerate(self.axes):
240 240
241 241 self.zmax = self.zmax if self.zmax is not None else numpy.max(
242 242 self.z[n])
243 243 self.zmin = self.zmin if self.zmin is not None else numpy.min(
244 244 self.z[n])
245 245
246 246 if ax.firsttime:
247 247
248 248 if self.zlimits is not None:
249 249 self.zmin, self.zmax = self.zlimits[n]
250 250 if numpy.log10(self.zmin)<0:
251 251 self.zmin=1
252 252 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
253 253 #vmin=self.zmin,
254 254 #vmax=self.zmax,
255 255 cmap=self.cmaps[n],
256 256 norm=colors.LogNorm(vmin=self.zmin,vmax=self.zmax)
257 257 )
258 258
259 259 else:
260 260 if self.zlimits is not None:
261 261 self.zmin, self.zmax = self.zlimits[n]
262 262 ax.plt.remove()
263 263 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
264 264 #vmin=self.zmin,
265 265 #vmax=self.zmax,
266 266 cmap=self.cmaps[n],
267 267 norm=colors.LogNorm(vmin=self.zmin,vmax=self.zmax)
268 268 )
269 269
270 270
271 271 class ETempRTIPlot(RTIPlot):
272 272 '''
273 273 Written by R. Flores
274 274 '''
275 275 '''
276 276 Plot for Electron Temperature
277 277 '''
278 278
279 279 CODE = 'ETemp'
280 280 colormap = 'jet'
281 281
282 282 def setup(self):
283 283 self.xaxis = 'time'
284 284 self.ncols = 1
285 285 self.nrows = self.data.shape(self.CODE)[0]
286 286 self.nplots = self.nrows
287 287
288 288 self.ylabel = 'Range [km]'
289 289 self.xlabel = 'Time (LT)'
290 290 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
291 291 if self.CODE == 'ETemp':
292 292 self.cb_label = 'Electron Temperature (K)'
293 293 self.titles = ['Electron Temperature RTI']
294 294 if self.CODE == 'ITemp':
295 295 self.cb_label = 'Ion Temperature (K)'
296 296 self.titles = ['Ion Temperature RTI']
297 297 if self.CODE == 'HeFracLP':
298 298 self.cb_label ='He+ Fraction'
299 299 self.titles = ['He+ Fraction RTI']
300 300 self.zmax=0.16
301 301 if self.CODE == 'HFracLP':
302 302 self.cb_label ='H+ Fraction'
303 303 self.titles = ['H+ Fraction RTI']
304 304
305 305 def update(self, dataOut):
306 306
307 307 data = {}
308 308 meta = {}
309 309
310 310 data['ETemp'] = dataOut.ElecTempFinal
311 311
312 312 return data, meta
313 313
314 314 def plot(self):
315 315
316 316 self.x = self.data.times
317 317 self.y = self.data.yrange
318 318 self.z = self.data[self.CODE]
319 319
320 320 self.z = numpy.ma.masked_invalid(self.z)
321 321
322 322 if self.decimation is None:
323 323 x, y, z = self.fill_gaps(self.x, self.y, self.z)
324 324 else:
325 325 x, y, z = self.fill_gaps(*self.decimate())
326 326
327 327 for n, ax in enumerate(self.axes):
328 328
329 329 self.zmax = self.zmax if self.zmax is not None else numpy.max(
330 330 self.z[n])
331 331 self.zmin = self.zmin if self.zmin is not None else numpy.min(
332 332 self.z[n])
333 333
334 334 if ax.firsttime:
335 335
336 336 if self.zlimits is not None:
337 337 self.zmin, self.zmax = self.zlimits[n]
338 338
339 339 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
340 340 vmin=self.zmin,
341 341 vmax=self.zmax,
342 342 cmap=self.cmaps[n]
343 343 )
344 344 #plt.tight_layout()
345 345
346 346 else:
347 347 if self.zlimits is not None:
348 348 self.zmin, self.zmax = self.zlimits[n]
349 349 ax.plt.remove()
350 350 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
351 351 vmin=self.zmin,
352 352 vmax=self.zmax,
353 353 cmap=self.cmaps[n]
354 354 )
355 355
356 356
357 357 class ITempRTIPlot(ETempRTIPlot):
358 358 '''
359 359 Written by R. Flores
360 360 '''
361 361 '''
362 362 Plot for Ion Temperature
363 363 '''
364 364
365 365 CODE = 'ITemp'
366 366 colormap = 'jet'
367 367 plot_name = 'Ion Temperature'
368 368
369 369 def update(self, dataOut):
370 370
371 371 data = {}
372 372 meta = {}
373 373
374 374 data['ITemp'] = dataOut.IonTempFinal
375 375
376 376 return data, meta
377 377
378 378
379 379 class HFracRTIPlot(ETempRTIPlot):
380 380 '''
381 381 Written by R. Flores
382 382 '''
383 383 '''
384 384 Plot for H+ LP
385 385 '''
386 386
387 387 CODE = 'HFracLP'
388 388 colormap = 'jet'
389 389 plot_name = 'H+ Frac'
390 390
391 391 def update(self, dataOut):
392 392
393 393 data = {}
394 394 meta = {}
395 395 data['HFracLP'] = dataOut.PhyFinal
396 396
397 397 return data, meta
398 398
399 399
400 400 class HeFracRTIPlot(ETempRTIPlot):
401 401 '''
402 402 Written by R. Flores
403 403 '''
404 404 '''
405 405 Plot for He+ LP
406 406 '''
407 407
408 408 CODE = 'HeFracLP'
409 409 colormap = 'jet'
410 410 plot_name = 'He+ Frac'
411 411
412 412 def update(self, dataOut):
413 413
414 414 data = {}
415 415 meta = {}
416 416 data['HeFracLP'] = dataOut.PheFinal
417 417
418 418 return data, meta
419 419
420 420
421 421 class TempsDPPlot(Plot):
422 422 '''
423 423 Written by R. Flores
424 424 '''
425 425 '''
426 426 Plot for Electron - Ion Temperatures
427 427 '''
428 428
429 429 CODE = 'tempsDP'
430 430 #plot_name = 'Temperatures'
431 431 plot_type = 'scatterbuffer'
432 432
433 433 def setup(self):
434 434
435 435 self.ncols = 1
436 436 self.nrows = 1
437 437 self.nplots = 1
438 438 self.ylabel = 'Range [km]'
439 439 self.xlabel = 'Temperature (K)'
440 440 self.titles = ['Electron/Ion Temperatures']
441 441 self.width = 3.5
442 442 self.height = 5.5
443 443 self.colorbar = False
444 444 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
445 445
446 446 def update(self, dataOut):
447 447 data = {}
448 448 meta = {}
449 449
450 450 data['Te'] = dataOut.te2
451 451 data['Ti'] = dataOut.ti2
452 452 data['Te_error'] = dataOut.ete2
453 453 data['Ti_error'] = dataOut.eti2
454 454
455 455 meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
456 456
457 457 return data, meta
458 458
459 459 def plot(self):
460 460
461 461 y = self.data.yrange
462 462
463 463 self.xmin = -100
464 464 self.xmax = 5000
465 465
466 466 ax = self.axes[0]
467 467
468 468 data = self.data[-1]
469 469
470 470 Te = data['Te']
471 471 Ti = data['Ti']
472 472 errTe = data['Te_error']
473 473 errTi = data['Ti_error']
474 474
475 475 if ax.firsttime:
476 476 ax.errorbar(Te, y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
477 477 ax.errorbar(Ti, y, fmt='k^', xerr=errTi,elinewidth=1.0,color='k',linewidth=2.0, label='Ti')
478 478 plt.legend(loc='lower right')
479 479 self.ystep_given = 50
480 480 ax.yaxis.set_minor_locator(MultipleLocator(15))
481 481 ax.grid(which='minor')
482 482
483 483 else:
484 484 self.clear_figures()
485 485 ax.errorbar(Te, y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
486 486 ax.errorbar(Ti, y, fmt='k^', xerr=errTi,elinewidth=1.0,color='k',linewidth=2.0, label='Ti')
487 487 plt.legend(loc='lower right')
488 488 ax.yaxis.set_minor_locator(MultipleLocator(15))
489 489
490 490
491 491 class TempsHPPlot(Plot):
492 492 '''
493 493 Written by R. Flores
494 494 '''
495 495 '''
496 496 Plot for Temperatures Hybrid Experiment
497 497 '''
498 498
499 499 CODE = 'temps_LP'
500 500 #plot_name = 'Temperatures'
501 501 plot_type = 'scatterbuffer'
502 502
503 503
504 504 def setup(self):
505 505
506 506 self.ncols = 1
507 507 self.nrows = 1
508 508 self.nplots = 1
509 509 self.ylabel = 'Range [km]'
510 510 self.xlabel = 'Temperature (K)'
511 511 self.titles = ['Electron/Ion Temperatures']
512 512 self.width = 3.5
513 513 self.height = 6.5
514 514 self.colorbar = False
515 515 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
516 516
517 517 def update(self, dataOut):
518 518 data = {}
519 519 meta = {}
520 520
521 521
522 522 data['Te'] = numpy.concatenate((dataOut.te2[:dataOut.cut],dataOut.te[dataOut.cut:]))
523 523 data['Ti'] = numpy.concatenate((dataOut.ti2[:dataOut.cut],dataOut.ti[dataOut.cut:]))
524 524 data['Te_error'] = numpy.concatenate((dataOut.ete2[:dataOut.cut],dataOut.ete[dataOut.cut:]))
525 525 data['Ti_error'] = numpy.concatenate((dataOut.eti2[:dataOut.cut],dataOut.eti[dataOut.cut:]))
526 526
527 527 meta['yrange'] = dataOut.heightList[0:dataOut.NACF]
528 528
529 529 return data, meta
530 530
531 531 def plot(self):
532 532
533 533
534 534 self.y = self.data.yrange
535 535 self.xmin = -100
536 536 self.xmax = 4500
537 537 ax = self.axes[0]
538 538
539 539 data = self.data[-1]
540 540
541 541 Te = data['Te']
542 542 Ti = data['Ti']
543 543 errTe = data['Te_error']
544 544 errTi = data['Ti_error']
545 545
546 546 if ax.firsttime:
547 547
548 548 ax.errorbar(Te, self.y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
549 549 ax.errorbar(Ti, self.y, fmt='k^', xerr=errTi,elinewidth=1.0,color='',linewidth=2.0, label='Ti')
550 550 plt.legend(loc='lower right')
551 551 self.ystep_given = 200
552 552 ax.yaxis.set_minor_locator(MultipleLocator(15))
553 553 ax.grid(which='minor')
554 554
555 555 else:
556 556 self.clear_figures()
557 557 ax.errorbar(Te, self.y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
558 558 ax.errorbar(Ti, self.y, fmt='k^', xerr=errTi,elinewidth=1.0,color='k',linewidth=2.0, label='Ti')
559 559 plt.legend(loc='lower right')
560 560 ax.yaxis.set_minor_locator(MultipleLocator(15))
561 561 ax.grid(which='minor')
562 562
563 563
564 564 class FracsHPPlot(Plot):
565 565 '''
566 566 Written by R. Flores
567 567 '''
568 568 '''
569 569 Plot for Composition LP
570 570 '''
571 571
572 572 CODE = 'fracs_LP'
573 573 plot_type = 'scatterbuffer'
574 574
575 575
576 576 def setup(self):
577 577
578 578 self.ncols = 1
579 579 self.nrows = 1
580 580 self.nplots = 1
581 581 self.ylabel = 'Range [km]'
582 582 self.xlabel = 'Frac'
583 583 self.titles = ['Composition']
584 584 self.width = 3.5
585 585 self.height = 6.5
586 586 self.colorbar = False
587 587 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
588 588
589 589 def update(self, dataOut):
590 590 data = {}
591 591 meta = {}
592 592
593 593 #aux_nan=numpy.zeros(dataOut.cut,'float32')
594 594 #aux_nan[:]=numpy.nan
595 595 #data['ph'] = numpy.concatenate((aux_nan,dataOut.ph[dataOut.cut:]))
596 596 #data['eph'] = numpy.concatenate((aux_nan,dataOut.eph[dataOut.cut:]))
597 597
598 598 data['ph'] = dataOut.ph[dataOut.cut:]
599 599 data['eph'] = dataOut.eph[dataOut.cut:]
600 600 data['phe'] = dataOut.phe[dataOut.cut:]
601 601 data['ephe'] = dataOut.ephe[dataOut.cut:]
602 602
603 603 data['cut'] = dataOut.cut
604 604
605 605 meta['yrange'] = dataOut.heightList[0:dataOut.NACF]
606 606
607 607
608 608 return data, meta
609 609
610 610 def plot(self):
611 611
612 612 data = self.data[-1]
613 613
614 614 ph = data['ph']
615 615 eph = data['eph']
616 616 phe = data['phe']
617 617 ephe = data['ephe']
618 618 cut = data['cut']
619 619 self.y = self.data.yrange
620 620
621 621 self.xmin = 0
622 622 self.xmax = 1
623 623 ax = self.axes[0]
624 624
625 625 if ax.firsttime:
626 626
627 627 ax.errorbar(ph, self.y[cut:], xerr=eph, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='H+')
628 628 ax.errorbar(phe, self.y[cut:], fmt='k^', xerr=ephe,elinewidth=1.0,color='k',linewidth=2.0, label='He+')
629 629 plt.legend(loc='lower right')
630 630 self.xstep_given = 0.2
631 631 self.ystep_given = 200
632 632 ax.yaxis.set_minor_locator(MultipleLocator(15))
633 633 ax.grid(which='minor')
634 634
635 635 else:
636 636 self.clear_figures()
637 637 ax.errorbar(ph, self.y[cut:], xerr=eph, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='H+')
638 638 ax.errorbar(phe, self.y[cut:], fmt='k^', xerr=ephe,elinewidth=1.0,color='k',linewidth=2.0, label='He+')
639 639 plt.legend(loc='lower right')
640 640 ax.yaxis.set_minor_locator(MultipleLocator(15))
641 641 ax.grid(which='minor')
642 642
643 643 class EDensityPlot(Plot):
644 644 '''
645 645 Written by R. Flores
646 646 '''
647 647 '''
648 648 Plot for electron density
649 649 '''
650 650
651 651 CODE = 'den'
652 652 #plot_name = 'Electron Density'
653 653 plot_type = 'scatterbuffer'
654 654
655 655 def setup(self):
656 656
657 657 self.ncols = 1
658 658 self.nrows = 1
659 659 self.nplots = 1
660 660 self.ylabel = 'Range [km]'
661 661 self.xlabel = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
662 662 self.titles = ['Electron Density']
663 663 self.width = 3.5
664 664 self.height = 5.5
665 665 self.colorbar = False
666 666 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
667 667
668 668 def update(self, dataOut):
669 669 data = {}
670 670 meta = {}
671 671
672 672 data['den_power'] = dataOut.ph2[:dataOut.NSHTS]
673 673 data['den_Faraday'] = dataOut.dphi[:dataOut.NSHTS]
674 674 data['den_error'] = dataOut.sdp2[:dataOut.NSHTS]
675 675 #data['err_Faraday'] = dataOut.sdn1[:dataOut.NSHTS]
676 676 #print(numpy.shape(data['den_power']))
677 677 #print(numpy.shape(data['den_Faraday']))
678 678 #print(numpy.shape(data['den_error']))
679 679
680 680 data['NSHTS'] = dataOut.NSHTS
681 681
682 682 meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
683 683
684 684 return data, meta
685 685
686 686 def plot(self):
687 687
688 688 y = self.data.yrange
689 689
690 690 #self.xmin = 1e3
691 691 #self.xmax = 1e7
692 692
693 693 ax = self.axes[0]
694 694
695 695 data = self.data[-1]
696 696
697 697 DenPow = data['den_power']
698 698 DenFar = data['den_Faraday']
699 699 errDenPow = data['den_error']
700 700 #errFaraday = data['err_Faraday']
701 701
702 702 NSHTS = data['NSHTS']
703 703
704 704 if self.CODE == 'denLP':
705 705 DenPowLP = data['den_LP']
706 706 errDenPowLP = data['den_LP_error']
707 707 cut = data['cut']
708 708
709 709 if ax.firsttime:
710 710 self.autoxticks=False
711 711 #ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
712 712 ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday',markersize=2,linestyle='-')
713 713 #ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
714 714 ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
715 715
716 716 if self.CODE=='denLP':
717 717 ax.errorbar(DenPowLP[cut:], y[cut:], xerr=errDenPowLP[cut:], fmt='r^-',elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
718 718
719 719 plt.legend(loc='upper left',fontsize=8.5)
720 720 #plt.legend(loc='lower left',fontsize=8.5)
721 721 ax.set_xscale("log")#, nonposx='clip')
722 722 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
723 723 self.ystep_given=100
724 724 if self.CODE=='denLP':
725 725 self.ystep_given=200
726 726 ax.set_yticks(grid_y_ticks,minor=True)
727 727 locmaj = LogLocator(base=10,numticks=12)
728 728 ax.xaxis.set_major_locator(locmaj)
729 729 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
730 730 ax.xaxis.set_minor_locator(locmin)
731 731 ax.xaxis.set_minor_formatter(NullFormatter())
732 732 ax.grid(which='minor')
733 733
734 734 else:
735 735 dataBefore = self.data[-2]
736 736 DenPowBefore = dataBefore['den_power']
737 737 self.clear_figures()
738 738 #ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
739 739 ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday',markersize=2,linestyle='-')
740 740 #ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
741 741 ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
742 742 ax.errorbar(DenPowBefore, y[:NSHTS], elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
743 743
744 744 if self.CODE=='denLP':
745 745 ax.errorbar(DenPowLP[cut:], y[cut:], fmt='r^-', xerr=errDenPowLP[cut:],elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
746 746
747 747 ax.set_xscale("log")#, nonposx='clip')
748 748 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
749 749 ax.set_yticks(grid_y_ticks,minor=True)
750 750 locmaj = LogLocator(base=10,numticks=12)
751 751 ax.xaxis.set_major_locator(locmaj)
752 752 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
753 753 ax.xaxis.set_minor_locator(locmin)
754 754 ax.xaxis.set_minor_formatter(NullFormatter())
755 755 ax.grid(which='minor')
756 756 plt.legend(loc='upper left',fontsize=8.5)
757 757 #plt.legend(loc='lower left',fontsize=8.5)
758 758
759 759 class RelativeDenPlot(Plot):
760 760 '''
761 761 Written by R. Flores
762 762 '''
763 763 '''
764 764 Plot for electron density
765 765 '''
766 766
767 767 CODE = 'den'
768 768 #plot_name = 'Electron Density'
769 769 plot_type = 'scatterbuffer'
770 770
771 771 def setup(self):
772 772
773 773 self.ncols = 1
774 774 self.nrows = 1
775 775 self.nplots = 1
776 776 self.ylabel = 'Range [km]'
777 777 self.xlabel = r'$\mathrm{N_e}$ Relative Electron Density ($\mathrm{1/cm^3}$)'
778 778 self.titles = ['Electron Density']
779 779 self.width = 3.5
780 780 self.height = 5.5
781 781 self.colorbar = False
782 782 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
783 783
784 784 def update(self, dataOut):
785 785 data = {}
786 786 meta = {}
787 787
788 788 data['den_power'] = dataOut.ph2
789 789 data['den_error'] = dataOut.sdp2
790 790
791 791 meta['yrange'] = dataOut.heightList
792 792
793 793 return data, meta
794 794
795 795 def plot(self):
796 796
797 797 y = self.data.yrange
798 798
799 799 ax = self.axes[0]
800 800
801 801 data = self.data[-1]
802 802
803 803 DenPow = data['den_power']
804 804 errDenPow = data['den_error']
805 805
806 806 if ax.firsttime:
807 807 self.autoxticks=False
808 808 ax.errorbar(DenPow, y, fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
809 809
810 810 plt.legend(loc='upper left',fontsize=8.5)
811 811 #plt.legend(loc='lower left',fontsize=8.5)
812 812 ax.set_xscale("log")#, nonposx='clip')
813 813 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
814 814 self.ystep_given=100
815 815 ax.set_yticks(grid_y_ticks,minor=True)
816 816 locmaj = LogLocator(base=10,numticks=12)
817 817 ax.xaxis.set_major_locator(locmaj)
818 818 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
819 819 ax.xaxis.set_minor_locator(locmin)
820 820 ax.xaxis.set_minor_formatter(NullFormatter())
821 821 ax.grid(which='minor')
822 822
823 823 else:
824 824 dataBefore = self.data[-2]
825 825 DenPowBefore = dataBefore['den_power']
826 826 self.clear_figures()
827 827 ax.errorbar(DenPow, y, fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
828 828 ax.errorbar(DenPowBefore, y, elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
829 829
830 830 ax.set_xscale("log")#, nonposx='clip')
831 831 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
832 832 ax.set_yticks(grid_y_ticks,minor=True)
833 833 locmaj = LogLocator(base=10,numticks=12)
834 834 ax.xaxis.set_major_locator(locmaj)
835 835 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
836 836 ax.xaxis.set_minor_locator(locmin)
837 837 ax.xaxis.set_minor_formatter(NullFormatter())
838 838 ax.grid(which='minor')
839 839 plt.legend(loc='upper left',fontsize=8.5)
840 840 #plt.legend(loc='lower left',fontsize=8.5)
841 841
842 842 class FaradayAnglePlot(Plot):
843 843 '''
844 844 Written by R. Flores
845 845 '''
846 846 '''
847 847 Plot for electron density
848 848 '''
849 849
850 850 CODE = 'angle'
851 851 plot_name = 'Faraday Angle'
852 852 plot_type = 'scatterbuffer'
853 853
854 854 def setup(self):
855 855
856 856 self.ncols = 1
857 857 self.nrows = 1
858 858 self.nplots = 1
859 859 self.ylabel = 'Range [km]'
860 860 self.xlabel = 'Faraday Angle (º)'
861 861 self.titles = ['Electron Density']
862 862 self.width = 3.5
863 863 self.height = 5.5
864 864 self.colorbar = False
865 865 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
866 866
867 867 def update(self, dataOut):
868 868 data = {}
869 869 meta = {}
870 870
871 871 data['angle'] = numpy.degrees(dataOut.phi)
872 872 #'''
873 873 #print(dataOut.phi_uwrp)
874 874 #print(data['angle'])
875 875 #exit(1)
876 876 #'''
877 877 data['dphi'] = dataOut.dphi_uc*10
878 878 #print(dataOut.dphi)
879 879
880 880 #data['NSHTS'] = dataOut.NSHTS
881 881
882 882 #meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
883 883
884 884 return data, meta
885 885
886 886 def plot(self):
887 887
888 888 data = self.data[-1]
889 889 self.x = data[self.CODE]
890 890 dphi = data['dphi']
891 891 self.y = self.data.yrange
892 892 self.xmin = -360#-180
893 893 self.xmax = 360#180
894 894 ax = self.axes[0]
895 895
896 896 if ax.firsttime:
897 897 self.autoxticks=False
898 898 #if self.CODE=='den':
899 899 ax.plot(self.x, self.y,marker='o',color='g',linewidth=1.0,markersize=2)
900 900 ax.plot(dphi, self.y,marker='o',color='blue',linewidth=1.0,markersize=2)
901 901
902 902 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
903 903 self.ystep_given=100
904 904 if self.CODE=='denLP':
905 905 self.ystep_given=200
906 906 ax.set_yticks(grid_y_ticks,minor=True)
907 907 ax.grid(which='minor')
908 908 #plt.tight_layout()
909 909 else:
910 910
911 911 self.clear_figures()
912 912 #if self.CODE=='den':
913 913 #print(numpy.shape(self.x))
914 914 ax.plot(self.x, self.y, marker='o',color='g',linewidth=1.0, markersize=2)
915 915 ax.plot(dphi, self.y,marker='o',color='blue',linewidth=1.0,markersize=2)
916 916
917 917 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
918 918 ax.set_yticks(grid_y_ticks,minor=True)
919 919 ax.grid(which='minor')
920 920
921 921 class EDensityHPPlot(EDensityPlot):
922 922 '''
923 923 Written by R. Flores
924 924 '''
925 925 '''
926 926 Plot for Electron Density Hybrid Experiment
927 927 '''
928 928
929 929 CODE = 'denLP'
930 930 plot_name = 'Electron Density'
931 931 plot_type = 'scatterbuffer'
932 932
933 933 def update(self, dataOut):
934 934 data = {}
935 935 meta = {}
936 936
937 937 data['den_power'] = dataOut.ph2[:dataOut.NSHTS]
938 938 data['den_Faraday']=dataOut.dphi[:dataOut.NSHTS]
939 939 data['den_error']=dataOut.sdp2[:dataOut.NSHTS]
940 940 data['den_LP']=dataOut.ne[:dataOut.NACF]
941 941 data['den_LP_error']=dataOut.ene[:dataOut.NACF]*dataOut.ne[:dataOut.NACF]*0.434
942 942 #self.ene=10**dataOut.ene[:dataOut.NACF]
943 943 data['NSHTS']=dataOut.NSHTS
944 944 data['cut']=dataOut.cut
945 945
946 946 return data, meta
947 947
948 948
949 949 class ACFsPlot(Plot):
950 950 '''
951 951 Written by R. Flores
952 952 '''
953 953 '''
954 954 Plot for ACFs Double Pulse Experiment
955 955 '''
956 956
957 957 CODE = 'acfs'
958 958 #plot_name = 'ACF'
959 959 plot_type = 'scatterbuffer'
960 960
961 961
962 962 def setup(self):
963 963 self.ncols = 1
964 964 self.nrows = 1
965 965 self.nplots = 1
966 966 self.ylabel = 'Range [km]'
967 967 self.xlabel = 'Lag (ms)'
968 968 self.titles = ['ACFs']
969 969 self.width = 3.5
970 970 self.height = 5.5
971 971 self.colorbar = False
972 972 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
973 973
974 974 def update(self, dataOut):
975 975 data = {}
976 976 meta = {}
977 977
978 978 data['ACFs'] = dataOut.acfs_to_plot
979 979 data['ACFs_error'] = dataOut.acfs_error_to_plot
980 980 data['lags'] = dataOut.lags_to_plot
981 981 data['Lag_contaminated_1'] = dataOut.x_igcej_to_plot
982 982 data['Lag_contaminated_2'] = dataOut.x_ibad_to_plot
983 983 data['Height_contaminated_1'] = dataOut.y_igcej_to_plot
984 984 data['Height_contaminated_2'] = dataOut.y_ibad_to_plot
985 985
986 986 meta['yrange'] = numpy.array([])
987 987 #meta['NSHTS'] = dataOut.NSHTS
988 988 #meta['DPL'] = dataOut.DPL
989 989 data['NSHTS'] = dataOut.NSHTS #This is metadata
990 990 data['DPL'] = dataOut.DPL #This is metadata
991 991
992 992 return data, meta
993 993
994 994 def plot(self):
995 995
996 996 data = self.data[-1]
997 997 #NSHTS = self.meta['NSHTS']
998 998 #DPL = self.meta['DPL']
999 999 NSHTS = data['NSHTS'] #This is metadata
1000 1000 DPL = data['DPL'] #This is metadata
1001 1001
1002 1002 lags = data['lags']
1003 1003 ACFs = data['ACFs']
1004 1004 errACFs = data['ACFs_error']
1005 1005 BadLag1 = data['Lag_contaminated_1']
1006 1006 BadLag2 = data['Lag_contaminated_2']
1007 1007 BadHei1 = data['Height_contaminated_1']
1008 1008 BadHei2 = data['Height_contaminated_2']
1009 1009
1010 1010 self.xmin = 0.0
1011 self.xmax = 2.0
1011 #self.xmax = 2.0
1012 1012 self.y = ACFs
1013 1013
1014 1014 ax = self.axes[0]
1015 1015
1016 1016 if ax.firsttime:
1017 1017
1018 1018 for i in range(NSHTS):
1019 1019 x_aux = numpy.isfinite(lags[i,:])
1020 1020 y_aux = numpy.isfinite(ACFs[i,:])
1021 1021 yerr_aux = numpy.isfinite(errACFs[i,:])
1022 1022 x_igcej_aux = numpy.isfinite(BadLag1[i,:])
1023 1023 y_igcej_aux = numpy.isfinite(BadHei1[i,:])
1024 1024 x_ibad_aux = numpy.isfinite(BadLag2[i,:])
1025 1025 y_ibad_aux = numpy.isfinite(BadHei2[i,:])
1026 1026 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1027 1027 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',marker='o',linewidth=1.0,markersize=2)
1028 1028 ax.plot(BadLag1[i,x_igcej_aux],BadHei1[i,y_igcej_aux],'x',color='red',markersize=2)
1029 1029 ax.plot(BadLag2[i,x_ibad_aux],BadHei2[i,y_ibad_aux],'X',color='red',markersize=2)
1030 1030
1031 1031 self.xstep_given = (self.xmax-self.xmin)/(DPL-1)
1032 1032 self.ystep_given = 50
1033 1033 ax.yaxis.set_minor_locator(MultipleLocator(15))
1034 1034 ax.grid(which='minor')
1035 1035
1036 1036 else:
1037 1037 self.clear_figures()
1038 1038 for i in range(NSHTS):
1039 1039 x_aux = numpy.isfinite(lags[i,:])
1040 1040 y_aux = numpy.isfinite(ACFs[i,:])
1041 1041 yerr_aux = numpy.isfinite(errACFs[i,:])
1042 1042 x_igcej_aux = numpy.isfinite(BadLag1[i,:])
1043 1043 y_igcej_aux = numpy.isfinite(BadHei1[i,:])
1044 1044 x_ibad_aux = numpy.isfinite(BadLag2[i,:])
1045 1045 y_ibad_aux = numpy.isfinite(BadHei2[i,:])
1046 1046 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1047 1047 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],linewidth=1.0,markersize=2,color='b',marker='o')
1048 1048 ax.plot(BadLag1[i,x_igcej_aux],BadHei1[i,y_igcej_aux],'x',color='red',markersize=2)
1049 1049 ax.plot(BadLag2[i,x_ibad_aux],BadHei2[i,y_ibad_aux],'X',color='red',markersize=2)
1050 1050 ax.yaxis.set_minor_locator(MultipleLocator(15))
1051 1051
1052 1052 class ACFsLPPlot(Plot):
1053 1053 '''
1054 1054 Written by R. Flores
1055 1055 '''
1056 1056 '''
1057 1057 Plot for ACFs Double Pulse Experiment
1058 1058 '''
1059 1059
1060 1060 CODE = 'acfs_LP'
1061 1061 #plot_name = 'ACF'
1062 1062 plot_type = 'scatterbuffer'
1063 1063
1064 1064
1065 1065 def setup(self):
1066 1066 self.ncols = 1
1067 1067 self.nrows = 1
1068 1068 self.nplots = 1
1069 1069 self.ylabel = 'Range [km]'
1070 1070 self.xlabel = 'Lag (ms)'
1071 1071 self.titles = ['ACFs']
1072 1072 self.width = 3.5
1073 1073 self.height = 5.5
1074 1074 self.colorbar = False
1075 1075 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1076 1076
1077 1077 def update(self, dataOut):
1078 1078 data = {}
1079 1079 meta = {}
1080 1080
1081 1081 aux=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1082 1082 errors=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1083 1083 lags_LP_to_plot=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1084 1084
1085 1085 for i in range(dataOut.NACF):
1086 1086 for j in range(dataOut.IBITS):
1087 1087 if numpy.abs(dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0])<1.0:
1088 1088 aux[i,j]=dataOut.output_LP_integrated.real[j,i,0]/dataOut.output_LP_integrated.real[0,i,0]
1089 1089 aux[i,j]=max(min(aux[i,j],1.0),-1.0)*dataOut.DH+dataOut.heightList[i]
1090 1090 lags_LP_to_plot[i,j]=dataOut.lags_LP[j]
1091 1091 errors[i,j]=dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0]*dataOut.DH
1092 1092 else:
1093 1093 aux[i,j]=numpy.nan
1094 1094 lags_LP_to_plot[i,j]=numpy.nan
1095 1095 errors[i,j]=numpy.nan
1096 1096
1097 1097 data['ACFs'] = aux
1098 1098 data['ACFs_error'] = errors
1099 1099 data['lags'] = lags_LP_to_plot
1100 1100
1101 1101 meta['yrange'] = numpy.array([])
1102 1102 #meta['NACF'] = dataOut.NACF
1103 1103 #meta['NLAG'] = dataOut.NLAG
1104 1104 data['NACF'] = dataOut.NACF #This is metadata
1105 1105 data['NLAG'] = dataOut.NLAG #This is metadata
1106 1106
1107 1107 return data, meta
1108 1108
1109 1109 def plot(self):
1110 1110
1111 1111 data = self.data[-1]
1112 1112 #NACF = self.meta['NACF']
1113 1113 #NLAG = self.meta['NLAG']
1114 1114 NACF = data['NACF'] #This is metadata
1115 1115 NLAG = data['NLAG'] #This is metadata
1116 1116
1117 1117 lags = data['lags']
1118 1118 ACFs = data['ACFs']
1119 1119 errACFs = data['ACFs_error']
1120 1120
1121 1121 self.xmin = 0.0
1122 1122 self.xmax = 1.5
1123 1123
1124 1124 self.y = ACFs
1125 1125
1126 1126 ax = self.axes[0]
1127 1127
1128 1128 if ax.firsttime:
1129 1129
1130 1130 for i in range(NACF):
1131 1131 x_aux = numpy.isfinite(lags[i,:])
1132 1132 y_aux = numpy.isfinite(ACFs[i,:])
1133 1133 yerr_aux = numpy.isfinite(errACFs[i,:])
1134 1134
1135 1135 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1136 1136 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
1137 1137
1138 1138 #self.xstep_given = (self.xmax-self.xmin)/(self.data.NLAG-1)
1139 1139 self.xstep_given=0.3
1140 1140 self.ystep_given = 200
1141 1141 ax.yaxis.set_minor_locator(MultipleLocator(15))
1142 1142 ax.grid(which='minor')
1143 1143
1144 1144 else:
1145 1145 self.clear_figures()
1146 1146
1147 1147 for i in range(NACF):
1148 1148 x_aux = numpy.isfinite(lags[i,:])
1149 1149 y_aux = numpy.isfinite(ACFs[i,:])
1150 1150 yerr_aux = numpy.isfinite(errACFs[i,:])
1151 1151
1152 1152 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1153 1153 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
1154 1154
1155 1155 ax.yaxis.set_minor_locator(MultipleLocator(15))
1156 1156
1157 1157
1158 1158 class CrossProductsPlot(Plot):
1159 1159 '''
1160 1160 Written by R. Flores
1161 1161 '''
1162 1162 '''
1163 1163 Plot for cross products
1164 1164 '''
1165 1165
1166 1166 CODE = 'crossprod'
1167 1167 plot_name = 'Cross Products'
1168 1168 plot_type = 'scatterbuffer'
1169 1169
1170 1170 def setup(self):
1171 1171
1172 1172 self.ncols = 3
1173 1173 self.nrows = 1
1174 1174 self.nplots = 3
1175 1175 self.ylabel = 'Range [km]'
1176 1176 self.titles = []
1177 1177 self.width = 3.5*self.nplots
1178 1178 self.height = 5.5
1179 1179 self.colorbar = False
1180 1180 self.plots_adjust.update({'wspace':.3, 'left': 0.12, 'right': 0.92, 'bottom': 0.1})
1181 1181
1182 1182
1183 1183 def update(self, dataOut):
1184 1184
1185 1185 data = {}
1186 1186 meta = {}
1187 1187
1188 1188 data['crossprod'] = dataOut.crossprods
1189 1189 data['NDP'] = dataOut.NDP
1190 1190
1191 1191 return data, meta
1192 1192
1193 1193 def plot(self):
1194 1194
1195 1195 NDP = self.data['NDP'][-1]
1196 1196 x = self.data['crossprod'][:,-1,:,:,:,:]
1197 1197 y = self.data.yrange[0:NDP]
1198 1198
1199 1199 for n, ax in enumerate(self.axes):
1200 1200
1201 1201 self.xmin=numpy.min(numpy.concatenate((x[n][0,20:30,0,0],x[n][1,20:30,0,0],x[n][2,20:30,0,0],x[n][3,20:30,0,0])))
1202 1202 self.xmax=numpy.max(numpy.concatenate((x[n][0,20:30,0,0],x[n][1,20:30,0,0],x[n][2,20:30,0,0],x[n][3,20:30,0,0])))
1203 1203
1204 1204 if ax.firsttime:
1205 1205
1206 1206 self.autoxticks=False
1207 1207 if n==0:
1208 1208 label1='kax'
1209 1209 label2='kay'
1210 1210 label3='kbx'
1211 1211 label4='kby'
1212 1212 self.xlimits=[(self.xmin,self.xmax)]
1213 1213 elif n==1:
1214 1214 label1='kax2'
1215 1215 label2='kay2'
1216 1216 label3='kbx2'
1217 1217 label4='kby2'
1218 1218 self.xlimits.append((self.xmin,self.xmax))
1219 1219 elif n==2:
1220 1220 label1='kaxay'
1221 1221 label2='kbxby'
1222 1222 label3='kaxbx'
1223 1223 label4='kaxby'
1224 1224 self.xlimits.append((self.xmin,self.xmax))
1225 1225
1226 1226 ax.plotline1 = ax.plot(x[n][0,:,0,0], y, color='r',linewidth=2.0, label=label1)
1227 1227 ax.plotline2 = ax.plot(x[n][1,:,0,0], y, color='k',linewidth=2.0, label=label2)
1228 1228 ax.plotline3 = ax.plot(x[n][2,:,0,0], y, color='b',linewidth=2.0, label=label3)
1229 1229 ax.plotline4 = ax.plot(x[n][3,:,0,0], y, color='m',linewidth=2.0, label=label4)
1230 1230 ax.legend(loc='upper right')
1231 1231 ax.set_xlim(self.xmin, self.xmax)
1232 1232 self.titles.append('{}'.format(self.plot_name.upper()))
1233 1233
1234 1234 else:
1235 1235
1236 1236 if n==0:
1237 1237 self.xlimits=[(self.xmin,self.xmax)]
1238 1238 else:
1239 1239 self.xlimits.append((self.xmin,self.xmax))
1240 1240
1241 1241 ax.set_xlim(self.xmin, self.xmax)
1242 1242
1243 1243 ax.plotline1[0].set_data(x[n][0,:,0,0],y)
1244 1244 ax.plotline2[0].set_data(x[n][1,:,0,0],y)
1245 1245 ax.plotline3[0].set_data(x[n][2,:,0,0],y)
1246 1246 ax.plotline4[0].set_data(x[n][3,:,0,0],y)
1247 1247 self.titles.append('{}'.format(self.plot_name.upper()))
1248 1248
1249 1249
1250 1250 class CrossProductsLPPlot(Plot):
1251 1251 '''
1252 1252 Written by R. Flores
1253 1253 '''
1254 1254 '''
1255 1255 Plot for cross products LP
1256 1256 '''
1257 1257
1258 1258 CODE = 'crossprodslp'
1259 1259 plot_name = 'Cross Products LP'
1260 1260 plot_type = 'scatterbuffer'
1261 1261
1262 1262
1263 1263 def setup(self):
1264 1264
1265 1265 self.ncols = 2
1266 1266 self.nrows = 1
1267 1267 self.nplots = 2
1268 1268 self.ylabel = 'Range [km]'
1269 1269 self.xlabel = 'dB'
1270 1270 self.width = 3.5*self.nplots
1271 1271 self.height = 5.5
1272 1272 self.colorbar = False
1273 1273 self.titles = []
1274 1274 self.plots_adjust.update({'wspace': .8 ,'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1275 1275
1276 1276 def update(self, dataOut):
1277 1277 data = {}
1278 1278 meta = {}
1279 1279
1280 1280 data['crossprodslp'] = 10*numpy.log10(numpy.abs(dataOut.output_LP))
1281 1281
1282 1282 data['NRANGE'] = dataOut.NRANGE #This is metadata
1283 1283 data['NLAG'] = dataOut.NLAG #This is metadata
1284 1284
1285 1285 return data, meta
1286 1286
1287 1287 def plot(self):
1288 1288
1289 1289 NRANGE = self.data['NRANGE'][-1]
1290 1290 NLAG = self.data['NLAG'][-1]
1291 1291
1292 1292 x = self.data[self.CODE][:,-1,:,:]
1293 1293 self.y = self.data.yrange[0:NRANGE]
1294 1294
1295 1295 label_array=numpy.array(['lag '+ str(x) for x in range(NLAG)])
1296 1296 color_array=['r','k','g','b','c','m','y','orange','steelblue','purple','peru','darksalmon','grey','limegreen','olive','midnightblue']
1297 1297
1298 1298
1299 1299 for n, ax in enumerate(self.axes):
1300 1300
1301 1301 self.xmin=28#30
1302 1302 self.xmax=70#70
1303 1303 #self.xmin=numpy.min(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1304 1304 #self.xmax=numpy.max(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1305 1305
1306 1306 if ax.firsttime:
1307 1307
1308 1308 self.autoxticks=False
1309 1309 if n == 0:
1310 1310 self.plotline_array=numpy.zeros((2,NLAG),dtype=object)
1311 1311
1312 1312 for i in range(NLAG):
1313 1313 self.plotline_array[n,i], = ax.plot(x[i,:,n], self.y, color=color_array[i],linewidth=1.0, label=label_array[i])
1314 1314
1315 1315 ax.legend(loc='upper right')
1316 1316 ax.set_xlim(self.xmin, self.xmax)
1317 1317 if n==0:
1318 1318 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1319 1319 if n==1:
1320 1320 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1321 1321 else:
1322 1322 for i in range(NLAG):
1323 1323 self.plotline_array[n,i].set_data(x[i,:,n],self.y)
1324 1324
1325 1325 if n==0:
1326 1326 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1327 1327 if n==1:
1328 1328 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1329 1329
1330 1330
1331 1331 class NoiseDPPlot(NoisePlot):
1332 1332 '''
1333 1333 Written by R. Flores
1334 1334 '''
1335 1335 '''
1336 1336 Plot for noise Double Pulse
1337 1337 '''
1338 1338
1339 1339 CODE = 'noise'
1340 1340 #plot_name = 'Noise'
1341 1341 #plot_type = 'scatterbuffer'
1342 1342
1343 1343 def update(self, dataOut):
1344 1344
1345 1345 data = {}
1346 1346 meta = {}
1347 1347 data['noise'] = 10*numpy.log10(dataOut.noise_final)
1348 1348
1349 1349 return data, meta
1350 1350
1351 1351
1352 1352 class XmitWaveformPlot(Plot):
1353 1353 '''
1354 1354 Written by R. Flores
1355 1355 '''
1356 1356 '''
1357 1357 Plot for xmit waveform
1358 1358 '''
1359 1359
1360 1360 CODE = 'xmit'
1361 1361 plot_name = 'Xmit Waveform'
1362 1362 plot_type = 'scatterbuffer'
1363 1363
1364 1364
1365 1365 def setup(self):
1366 1366
1367 1367 self.ncols = 1
1368 1368 self.nrows = 1
1369 1369 self.nplots = 1
1370 1370 self.ylabel = ''
1371 1371 self.xlabel = 'Number of Lag'
1372 1372 self.width = 5.5
1373 1373 self.height = 3.5
1374 1374 self.colorbar = False
1375 1375 self.plots_adjust.update({'right': 0.85 })
1376 1376 self.titles = [self.plot_name]
1377 1377 #self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1378 1378
1379 1379 #if not self.titles:
1380 1380 #self.titles = self.data.parameters \
1381 1381 #if self.data.parameters else ['{}'.format(self.plot_name.upper())]
1382 1382
1383 1383 def update(self, dataOut):
1384 1384
1385 1385 data = {}
1386 1386 meta = {}
1387 1387
1388 1388 y_1=numpy.arctan2(dataOut.output_LP[:,0,2].imag,dataOut.output_LP[:,0,2].real)* 180 / (numpy.pi*10)
1389 1389 y_2=numpy.abs(dataOut.output_LP[:,0,2])
1390 1390 norm=numpy.max(y_2)
1391 1391 norm=max(norm,0.1)
1392 1392 y_2=y_2/norm
1393 1393
1394 1394 meta['yrange'] = numpy.array([])
1395 1395
1396 1396 data['xmit'] = numpy.vstack((y_1,y_2))
1397 1397 data['NLAG'] = dataOut.NLAG
1398 1398
1399 1399 return data, meta
1400 1400
1401 1401 def plot(self):
1402 1402
1403 1403 data = self.data[-1]
1404 1404 NLAG = data['NLAG']
1405 1405 x = numpy.arange(0,NLAG,1,'float32')
1406 1406 y = data['xmit']
1407 1407
1408 1408 self.xmin = 0
1409 1409 self.xmax = NLAG-1
1410 1410 self.ymin = -1.0
1411 1411 self.ymax = 1.0
1412 1412 ax = self.axes[0]
1413 1413
1414 1414 if ax.firsttime:
1415 1415 ax.plotline0=ax.plot(x,y[0,:],color='blue')
1416 1416 ax.plotline1=ax.plot(x,y[1,:],color='red')
1417 1417 secax=ax.secondary_xaxis(location=0.5)
1418 1418 secax.xaxis.tick_bottom()
1419 1419 secax.tick_params( labelleft=False, labeltop=False,
1420 1420 labelright=False, labelbottom=False)
1421 1421
1422 1422 self.xstep_given = 3
1423 1423 self.ystep_given = .25
1424 1424 secax.set_xticks(numpy.linspace(self.xmin, self.xmax, 6)) #only works on matplotlib.version>3.2
1425 1425
1426 1426 else:
1427 1427 ax.plotline0[0].set_data(x,y[0,:])
1428 1428 ax.plotline1[0].set_data(x,y[1,:])
@@ -1,191 +1,241
1 1 {"conditions": [
2 2
3 3 {"year": 2024, "doy": 47, "initial_time": [5,32], "final_time": [6,42], "aux_index": [ null, 11]},
4 4
5 5 {"year": 2024, "doy": 247, "initial_time": [2,0], "final_time": [5,0], "aux_index": [ null, 11]},
6 6 {"year": 2024, "doy": 247, "initial_time": [1,40], "final_time": [2,0], "aux_index": [ null, 26]},
7 7 {"year": 2024, "doy": 247, "initial_time": [0,45], "final_time": [0,45], "aux_index": [ null, 28]},
8 8 {"year": 2024, "doy": 246, "initial_time": [23,15], "final_time": [23,59], "aux_index": [ null, 21]},
9 9 {"year": 2024, "doy": 246, "initial_time": [13,55], "final_time": [23,59], "aux_index": [ null, 11]},
10 10 {"year": 2024, "doy": 247, "initial_time": [0,0], "final_time": [2,25], "aux_index": [ null, 22]},
11 11 {"year": 2024, "doy": 247, "initial_time": [3,0], "final_time": [3,0], "aux_index": [ 34, null]},
12 12
13 13 {"year": 2024, "doy": 247, "initial_time": [5,0], "final_time": [23,59], "aux_index": [ null, 11]},
14 14 {"year": 2024, "doy": 247, "initial_time": [5,0], "final_time": [11,25], "aux_index": [ 11, 13]},
15 15 {"year": 2024, "doy": 247, "initial_time": [5,30], "final_time": [9,50], "aux_index": [ 13, 13]},
16 16 {"year": 2024, "doy": 247, "initial_time": [23,15], "final_time": [23,59], "aux_index": [ null, 15]},
17 17 {"year": 2024, "doy": 248, "initial_time": [0,0], "final_time": [4,59], "aux_index": [ null, 13]},
18 18 {"year": 2024, "doy": 248, "initial_time": [0,0], "final_time": [1,50], "aux_index": [ null, 21]},
19 19 {"year": 2024, "doy": 248, "initial_time": [0,0], "final_time": [2,50], "aux_index": [ null, 17]},
20 20 {"year": 2024, "doy": 247, "initial_time": [8,5], "final_time": [8,10], "aux_index": [ null, null]},
21 21 {"year": 2024, "doy": 248, "initial_time": [2,50], "final_time": [2,50], "aux_index": [ 30, null]},
22 22 {"year": 2024, "doy": 248, "initial_time": [3,55], "final_time": [4,0], "aux_index": [ 26, null]},
23 23 {"year": 2024, "doy": 247, "initial_time": [5,0], "final_time": [5,0], "aux_index": [ 18, 24]},
24 24 {"year": 2024, "doy": 247, "initial_time": [5,5], "final_time": [5,5], "aux_index": [ 21, 26]},
25 25 {"year": 2024, "doy": 247, "initial_time": [5,15], "final_time": [5,15], "aux_index": [ 19, 21]},
26 26 {"year": 2024, "doy": 247, "initial_time": [5,20], "final_time": [5,20], "aux_index": [ 21, 23]},
27 27 {"year": 2024, "doy": 247, "initial_time": [5,25], "final_time": [5,25], "aux_index": [ 21, 26]},
28 28 {"year": 2024, "doy": 247, "initial_time": [5,30], "final_time": [5,30], "aux_index": [ 20, 27]},
29 29 {"year": 2024, "doy": 247, "initial_time": [5,35], "final_time": [5,35], "aux_index": [ 22, 27]},
30 30 {"year": 2024, "doy": 247, "initial_time": [8,5], "final_time": [8,10], "aux_index": [ null, null]},
31 31 {"year": 2024, "doy": 247, "initial_time": [15,30], "final_time": [15,30], "aux_index": [ null, null]},
32 32
33 33
34 34 {"year": 2024, "doy": 248, "initial_time": [5,20], "final_time": [5,35], "aux_index": [ 20, null]},
35 35 {"year": 2024, "doy": 248, "initial_time": [5,40], "final_time": [5,55], "aux_index": [ 23, null]},
36 36 {"year": 2024, "doy": 248, "initial_time": [5,0], "final_time": [23,59], "aux_index": [ null, 11]},
37 37 {"year": 2024, "doy": 249, "initial_time": [0,0], "final_time": [4,59], "aux_index": [ null, 12]},
38 38 {"year": 2024, "doy": 248, "initial_time": [5,0], "final_time": [9,0], "aux_index": [ null, 13]},
39 39 {"year": 2024, "doy": 249, "initial_time": [2,0], "final_time": [2,20], "aux_index": [ null, 17]},
40 40 {"year": 2024, "doy": 249, "initial_time": [2,55], "final_time": [2,55], "aux_index": [ 27, null]},
41 41 {"year": 2024, "doy": 249, "initial_time": [3,0], "final_time": [3,5], "aux_index": [ 25, null]},
42 42 {"year": 2024, "doy": 249, "initial_time": [4,5], "final_time": [4,5], "aux_index": [ 23, null]},
43 43 {"year": 2024, "doy": 249, "initial_time": [4,10], "final_time": [4,10], "aux_index": [ 26, null]},
44 44 {"year": 2024, "doy": 249, "initial_time": [4,15], "final_time": [4,15], "aux_index": [ 30, null]},
45 45 {"year": 2024, "doy": 249, "initial_time": [0,30], "final_time": [0,40], "aux_index": [ null, null]},
46 46
47 47 {"year": 2024, "doy": 249, "initial_time": [5,20], "final_time": [5,20], "aux_index": [ 22, null]},
48 48 {"year": 2024, "doy": 249, "initial_time": [5,25], "final_time": [5,25], "aux_index": [ 23, null]},
49 49 {"year": 2024, "doy": 249, "initial_time": [5,30], "final_time": [5,30], "aux_index": [ 18, 37]},
50 50 {"year": 2024, "doy": 249, "initial_time": [5,35], "final_time": [5,40], "aux_index": [ 18, 34]},
51 51 {"year": 2024, "doy": 249, "initial_time": [5,45], "final_time": [5,45], "aux_index": [ 20, 30]},
52 52 {"year": 2024, "doy": 249, "initial_time": [6,5], "final_time": [6,5], "aux_index": [ 24, null]},
53 53 {"year": 2024, "doy": 249, "initial_time": [10,5], "final_time": [10,5], "aux_index": [ null, null]},
54 54 {"year": 2024, "doy": 249, "initial_time": [6,10], "final_time": [6,10], "aux_index": [ 29, null]},
55 55 {"year": 2024, "doy": 249, "initial_time": [6,45], "final_time": [6,45], "aux_index": [ 21, null]},
56 56 {"year": 2024, "doy": 249, "initial_time": [5,0], "final_time": [20,0], "aux_index": [ null, 11]},
57 57 {"year": 2024, "doy": 249, "initial_time": [23,10], "final_time": [23,59], "aux_index": [ null, 11]},
58 58 {"year": 2024, "doy": 250, "initial_time": [0,0], "final_time": [4,59], "aux_index": [ null, 13]},
59 59 {"year": 2024, "doy": 249, "initial_time": [5,0], "final_time": [8,50], "aux_index": [ null, 12]},
60 60 {"year": 2024, "doy": 250, "initial_time": [0,0], "final_time": [3,35], "aux_index": [ null, 23]},
61 61 {"year": 2024, "doy": 250, "initial_time": [0,0], "final_time": [0,55], "aux_index": [ null, null]},
62 62 {"year": 2024, "doy": 249, "initial_time": [7,15], "final_time": [7,15], "aux_index": [ null, 14]},
63 63 {"year": 2024, "doy": 250, "initial_time": [3,15], "final_time": [3,35], "aux_index": [ 46, null]},
64 64 {"year": 2024, "doy": 250, "initial_time": [3,25], "final_time": [3,25], "aux_index": [ null, 30]},
65 65 {"year": 2024, "doy": 250, "initial_time": [3,30], "final_time": [3,30], "aux_index": [ null, 32]},
66 66 {"year": 2024, "doy": 250, "initial_time": [3,35], "final_time": [3,35], "aux_index": [ null, 34]},
67 67 {"year": 2024, "doy": 250, "initial_time": [3,40], "final_time": [3,40], "aux_index": [ 21, 38]},
68 68 {"year": 2024, "doy": 250, "initial_time": [3,45], "final_time": [3,45], "aux_index": [ 22, 37]},
69 69 {"year": 2024, "doy": 250, "initial_time": [1,35], "final_time": [1,35], "aux_index": [ 36, null]},
70 70 {"year": 2024, "doy": 250, "initial_time": [1,40], "final_time": [1,40], "aux_index": [ 32, null]},
71 71 {"year": 2024, "doy": 250, "initial_time": [1,45], "final_time": [1,45], "aux_index": [ 31, null]},
72 72 {"year": 2024, "doy": 250, "initial_time": [2,30], "final_time": [2,30], "aux_index": [ 30, null]},
73 73 {"year": 2024, "doy": 250, "initial_time": [2,35], "final_time": [2,35], "aux_index": [ 33, null]},
74 74 {"year": 2024, "doy": 250, "initial_time": [2,40], "final_time": [2,40], "aux_index": [ 27, null]},
75 75
76 76 {"year": 2024, "doy": 251, "initial_time": [3,0], "final_time": [3,45], "aux_index": [ null, null]},
77 77 {"year": 2024, "doy": 251, "initial_time": [0,30], "final_time": [0,45], "aux_index": [ null, null]},
78 78
79 79 {"year": 2024, "doy": 250, "initial_time": [5,0], "final_time": [5,0], "aux_index": [ 20, 41]},
80 80 {"year": 2024, "doy": 250, "initial_time": [5,5], "final_time": [5,10], "aux_index": [ 24, 37]},
81 81 {"year": 2024, "doy": 250, "initial_time": [5,20], "final_time": [5,25], "aux_index": [ 23, 39]},
82 82 {"year": 2024, "doy": 250, "initial_time": [5,30], "final_time": [5,30], "aux_index": [ 19, null]},
83 83 {"year": 2024, "doy": 250, "initial_time": [6,5], "final_time": [6,5], "aux_index": [ 24, null]},
84 84 {"year": 2024, "doy": 250, "initial_time": [6,10], "final_time": [6,10], "aux_index": [ 20, 41]},
85 85 {"year": 2024, "doy": 250, "initial_time": [6,15], "final_time": [6,15], "aux_index": [ 20, 39]},
86 86 {"year": 2024, "doy": 250, "initial_time": [6,20], "final_time": [6,20], "aux_index": [ 20, 37]},
87 87 {"year": 2024, "doy": 250, "initial_time": [6,25], "final_time": [6,25], "aux_index": [ 21, 29]},
88 88 {"year": 2024, "doy": 250, "initial_time": [6,30], "final_time": [6,30], "aux_index": [ 22, 29]},
89 89 {"year": 2024, "doy": 250, "initial_time": [6,45], "final_time": [6,45], "aux_index": [ 20, null]},
90 90 {"year": 2024, "doy": 250, "initial_time": [6,50], "final_time": [6,50], "aux_index": [ 19, 38]},
91 91 {"year": 2024, "doy": 250, "initial_time": [6,55], "final_time": [6,55], "aux_index": [ 23, 42]},
92 92 {"year": 2024, "doy": 250, "initial_time": [7,0], "final_time": [7,0], "aux_index": [ 20, null]},
93 93 {"year": 2024, "doy": 250, "initial_time": [7,5], "final_time": [7,5], "aux_index": [ 23, 40]},
94 94 {"year": 2024, "doy": 250, "initial_time": [7,10], "final_time": [7,10], "aux_index": [ 23, 42]},
95 95 {"year": 2024, "doy": 250, "initial_time": [7,15], "final_time": [7,15], "aux_index": [ 25, 37]},
96 96 {"year": 2024, "doy": 250, "initial_time": [7,30], "final_time": [7,30], "aux_index": [ 25, 40]},
97 97 {"year": 2024, "doy": 250, "initial_time": [7,35], "final_time": [7,35], "aux_index": [ 25, 39]},
98 98 {"year": 2024, "doy": 250, "initial_time": [7,40], "final_time": [7,40], "aux_index": [ 23, 41]},
99 99 {"year": 2024, "doy": 250, "initial_time": [7,45], "final_time": [7,45], "aux_index": [ 27, 38]},
100 100 {"year": 2024, "doy": 250, "initial_time": [23,10], "final_time": [23,59], "aux_index": [ null, 12]},
101 101 {"year": 2024, "doy": 251, "initial_time": [0,0], "final_time": [4,59], "aux_index": [ null, 13]},
102 102 {"year": 2024, "doy": 250, "initial_time": [5,0], "final_time": [8,10], "aux_index": [ null, 12]},
103 103 {"year": 2024, "doy": 250, "initial_time": [9,10], "final_time": [10,50], "aux_index": [ null, 12]},
104 104 {"year": 2024, "doy": 251, "initial_time": [0,0], "final_time": [3,30], "aux_index": [ null, 27]},
105 105 {"year": 2024, "doy": 250, "initial_time": [19,30], "final_time": [19,30], "aux_index": [ 19, 26]},
106 106 {"year": 2024, "doy": 250, "initial_time": [10,50], "final_time": [13,20], "aux_index": [ null, 12]},
107 107
108 108
109 109 {"year": 2024, "doy": 251, "initial_time": [5,0], "final_time": [5,0], "aux_index": [ 23, 40]},
110 110 {"year": 2024, "doy": 251, "initial_time": [5,5], "final_time": [5,10], "aux_index": [ 25, 40]},
111 111 {"year": 2024, "doy": 251, "initial_time": [17,30], "final_time": [20,30], "aux_index": [ 56, null]},
112 112 {"year": 2024, "doy": 251, "initial_time": [5,0], "final_time": [8,10], "aux_index": [ null, 12]},
113 113 {"year": 2024, "doy": 251, "initial_time": [5,0], "final_time": [20,0], "aux_index": [ null, 11]},
114 114 {"year": 2024, "doy": 251, "initial_time": [19,50], "final_time": [19,50], "aux_index": [ null, null]},
115 115 {"year": 2024, "doy": 252, "initial_time": [0,30], "final_time": [0,55], "aux_index": [ null, null]},
116 116 {"year": 2024, "doy": 252, "initial_time": [0,55], "final_time": [1,0], "aux_index": [ null, 40]},
117 117 {"year": 2024, "doy": 252, "initial_time": [1,0], "final_time": [1,15], "aux_index": [ null, 34]},
118 118 {"year": 2024, "doy": 252, "initial_time": [0,30], "final_time": [0,55], "aux_index": [ null, null]},
119 119 {"year": 2024, "doy": 252, "initial_time": [1,35], "final_time": [1,55], "aux_index": [ null, null]},
120 120 {"year": 2024, "doy": 251, "initial_time": [23,10], "final_time": [23,59], "aux_index": [ null, 20]},
121 121 {"year": 2024, "doy": 252, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 12]},
122 122 {"year": 2024, "doy": 252, "initial_time": [0,0], "final_time": [1,50], "aux_index": [ null, 31]},
123 123 {"year": 2024, "doy": 252, "initial_time": [3,20], "final_time": [3,25], "aux_index": [ 22, null]},
124 124 {"year": 2024, "doy": 252, "initial_time": [3,30], "final_time": [3,35], "aux_index": [ 23, null]},
125 125 {"year": 2024, "doy": 252, "initial_time": [3,50], "final_time": [3,50], "aux_index": [ 22, null]},
126 126 {"year": 2024, "doy": 252, "initial_time": [3,55], "final_time": [4,5], "aux_index": [ 21, null]},
127 127 {"year": 2024, "doy": 252, "initial_time": [4,10], "final_time": [4,10], "aux_index": [ 21, 36]},
128 128
129 129 {"year": 2024, "doy": 252, "initial_time": [5,0], "final_time": [20,0], "aux_index": [ null, 12]},
130 130 {"year": 2024, "doy": 252, "initial_time": [13,0], "final_time": [13,0], "aux_index": [ null, null]},
131 131 {"year": 2024, "doy": 252, "initial_time": [5,15], "final_time": [5,20], "aux_index": [ 23, null]},
132 132 {"year": 2024, "doy": 252, "initial_time": [5,25], "final_time": [5,25], "aux_index": [ 27, 36]},
133 133 {"year": 2024, "doy": 252, "initial_time": [5,30], "final_time": [5,30], "aux_index": [ 27, null]},
134 134 {"year": 2024, "doy": 252, "initial_time": [5,35], "final_time": [5,35], "aux_index": [ 31, null]},
135 135 {"year": 2024, "doy": 252, "initial_time": [5,20], "final_time": [5,40], "aux_index": [ 33, null]},
136 136 {"year": 2024, "doy": 252, "initial_time": [7,5], "final_time": [7,5], "aux_index": [ 21, null]},
137 137 {"year": 2024, "doy": 252, "initial_time": [7,10], "final_time": [7,10], "aux_index": [ 23, null]},
138 138
139 139
140 140
141 141 {"year": 2025, "doy": 21, "initial_time": [19,45], "final_time": [19,50], "aux_index": [ null, null]},
142 142 {"year": 2025, "doy": 22, "initial_time": [0,50], "final_time": [3,30], "aux_index": [ null, 30]},
143 143 {"year": 2025, "doy": 22, "initial_time": [1,50], "final_time": [1,50], "aux_index": [ null, null]},
144 144 {"year": 2025, "doy": 22, "initial_time": [2,15], "final_time": [2,25], "aux_index": [ null, 38]},
145 145 {"year": 2025, "doy": 22, "initial_time": [2,25], "final_time": [2,35], "aux_index": [ null, null]},
146 146 {"year": 2025, "doy": 22, "initial_time": [2,40], "final_time": [2,50], "aux_index": [ null, 40]},
147 147 {"year": 2025, "doy": 22, "initial_time": [2,40], "final_time": [2,40], "aux_index": [ 44, null]},
148 148 {"year": 2025, "doy": 22, "initial_time": [2,45], "final_time": [2,45], "aux_index": [ 50, null]},
149 149 {"year": 2025, "doy": 22, "initial_time": [3,0], "final_time": [3,15], "aux_index": [ null, 33]},
150 150 {"year": 2025, "doy": 22, "initial_time": [3,30], "final_time": [4,15], "aux_index": [ null, 28]},
151 151 {"year": 2025, "doy": 22, "initial_time": [4,15], "final_time": [4,25], "aux_index": [ null, 24]},
152 152 {"year": 2025, "doy": 22, "initial_time": [3,50], "final_time": [4,15], "aux_index": [ null, 15]},
153 153 {"year": 2025, "doy": 22, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 13]},
154 154
155 155 {"year": 2025, "doy": 22, "initial_time": [5,0], "final_time": [23,55], "aux_index": [ null, 13]},
156 156 {"year": 2025, "doy": 22, "initial_time": [14,20], "final_time": [14,20], "aux_index": [ null, null]},
157 157 {"year": 2025, "doy": 23, "initial_time": [0,10], "final_time": [0,10], "aux_index": [ null, null]},
158 158 {"year": 2025, "doy": 23, "initial_time": [0,55], "final_time": [3,30], "aux_index": [ null, 26]},
159 159 {"year": 2025, "doy": 23, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 13]},
160 160 {"year": 2025, "doy": 23, "initial_time": [2,25], "final_time": [2,25], "aux_index": [ null, 34]},
161 161 {"year": 2025, "doy": 23, "initial_time": [2,10], "final_time": [2,10], "aux_index": [ 44, 48]},
162 162 {"year": 2025, "doy": 23, "initial_time": [0,50], "final_time": [0,50], "aux_index": [ 53, 53]},
163 163
164 164 {"year": 2025, "doy": 23, "initial_time": [5,0], "final_time": [23,55], "aux_index": [ null, 13]},
165 165 {"year": 2025, "doy": 23, "initial_time": [5,0], "final_time": [8,0], "aux_index": [ null, 14]},
166 166 {"year": 2025, "doy": 23, "initial_time": [12,5], "final_time": [12,5], "aux_index": [ null, null]},
167 167 {"year": 2025, "doy": 24, "initial_time": [1,40], "final_time": [3,15], "aux_index": [ null, null]},
168 168 {"year": 2025, "doy": 24, "initial_time": [3,25], "final_time": [3,30], "aux_index": [ 44, null]},
169 169 {"year": 2025, "doy": 24, "initial_time": [3,20], "final_time": [3,40], "aux_index": [ null, 31]},
170 170 {"year": 2025, "doy": 24, "initial_time": [3,40], "final_time": [4,55], "aux_index": [ null, 29]},
171 171 {"year": 2025, "doy": 24, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 13]},
172 172
173 173 {"year": 2025, "doy": 24, "initial_time": [5,0], "final_time": [23,55], "aux_index": [ null, 13]},
174 {"year": 2025, "doy": 25, "initial_time": [0,0], "final_time": [4,55], "aux_index": [ null, 27]},
174 {"year": 2025, "doy": 24, "initial_time": [5,0], "final_time": [5,5], "aux_index": [ null, 34]},
175 {"year": 2025, "doy": 24, "initial_time": [5,10], "final_time": [5,10], "aux_index": [ 24, 35]},
176 {"year": 2025, "doy": 24, "initial_time": [5,15], "final_time": [5,15], "aux_index": [ 25, 33]},
177 {"year": 2025, "doy": 24, "initial_time": [5,20], "final_time": [5,20], "aux_index": [ 26, 33]},
178 {"year": 2025, "doy": 24, "initial_time": [5,25], "final_time": [5,25], "aux_index": [ 27, 32]},
179 {"year": 2025, "doy": 24, "initial_time": [5,30], "final_time": [5,30], "aux_index": [ 23, 24]},
180 {"year": 2025, "doy": 24, "initial_time": [5,35], "final_time": [5,35], "aux_index": [ 22, 27]},
181 {"year": 2025, "doy": 24, "initial_time": [5,40], "final_time": [5,55], "aux_index": [ 22, 31]},
182 {"year": 2025, "doy": 24, "initial_time": [6,0], "final_time": [6,0], "aux_index": [ 22, 33]},
183 {"year": 2025, "doy": 24, "initial_time": [6,30], "final_time": [6,30], "aux_index": [ 22, 25]},
184 {"year": 2025, "doy": 24, "initial_time": [6,35], "final_time": [6,35], "aux_index": [ 22, 32]},
185 {"year": 2025, "doy": 24, "initial_time": [6,35], "final_time": [6,40], "aux_index": [ 22, 32]},
186 {"year": 2025, "doy": 24, "initial_time": [6,45], "final_time": [6,45], "aux_index": [ 23, 32]},
187 {"year": 2025, "doy": 24, "initial_time": [6,50], "final_time": [6,50], "aux_index": [ 24, 34]},
188 {"year": 2025, "doy": 24, "initial_time": [6,55], "final_time": [6,55], "aux_index": [ 25, 32]},
189 {"year": 2025, "doy": 25, "initial_time": [0,50], "final_time": [4,55], "aux_index": [ null, 27]},
175 190 {"year": 2025, "doy": 25, "initial_time": [2,50], "final_time": [4,55], "aux_index": [ null, 30]},
191 {"year": 2025, "doy": 25, "initial_time": [3,5], "final_time": [3,45], "aux_index": [ null, 33]},
176 192 {"year": 2025, "doy": 25, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 13]},
177 193
178 194 {"year": 2025, "doy": 25, "initial_time": [5,0], "final_time": [23,55], "aux_index": [ null, 13]},
179 195 {"year": 2025, "doy": 26, "initial_time": [2,50], "final_time": [4,5], "aux_index": [ null, null]},
180 196 {"year": 2025, "doy": 26, "initial_time": [2,50], "final_time": [4,5], "aux_index": [ null, null]},
181 197 {"year": 2025, "doy": 26, "initial_time": [0,40], "final_time": [4,20], "aux_index": [ null, 24]},
182 198 {"year": 2025, "doy": 26, "initial_time": [4,30], "final_time": [4,30], "aux_index": [ null, 20]},
183 199 {"year": 2025, "doy": 26, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 13]},
184 200
185 201 {"year": 2025, "doy": 26, "initial_time": [5,0], "final_time": [23,55], "aux_index": [ null, 13]},
202 {"year": 2025, "doy": 26, "initial_time": [5,20], "final_time": [5,20], "aux_index": [ null, 28]},
203 {"year": 2025, "doy": 26, "initial_time": [5,25], "final_time": [5,25], "aux_index": [ 25, 34]},
186 204 {"year": 2025, "doy": 26, "initial_time": [0,55], "final_time": [0,55], "aux_index": [ null, null]},
187 205 {"year": 2025, "doy": 26, "initial_time": [0,55], "final_time": [4,55], "aux_index": [ null, 24]},
188 {"year": 2025, "doy": 27, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 13]}
206 {"year": 2025, "doy": 27, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 13]},
207
208 {"year": 2025, "doy": 41, "initial_time": [23,0], "final_time": [23,0], "aux_index": [ null, null]},
209 {"year": 2025, "doy": 42, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 14]},
210 {"year": 2025, "doy": 42, "initial_time": [4,24], "final_time": [4,24], "aux_index": [ 35, 38]},
211 {"year": 2025, "doy": 42, "initial_time": [1,30], "final_time": [5,0], "aux_index": [ null, 26]},
212 {"year": 2025, "doy": 42, "initial_time": [2,12], "final_time": [4,0], "aux_index": [ null, null]},
213 {"year": 2025, "doy": 42, "initial_time": [1,24], "final_time": [1,24], "aux_index": [ 39, 40]},
214 {"year": 2025, "doy": 42, "initial_time": [1,18], "final_time": [1,18], "aux_index": [ 48, 50]},
215
216 {"year": 2025, "doy": 42, "initial_time": [5,0], "final_time": [12,0], "aux_index": [ null, 7]},
217 {"year": 2025, "doy": 42, "initial_time": [5,0], "final_time": [7,30], "aux_index": [ null, 13]},
218 {"year": 2025, "doy": 42, "initial_time": [5,0], "final_time": [11,0], "aux_index": [ null, 10]},
219 {"year": 2025, "doy": 42, "initial_time": [5,0], "final_time": [5,0], "aux_index": [ 20, 22]},
220
221 {"year": 2025, "doy": 43, "initial_time": [0,0], "final_time": [5,0], "aux_index": [ null, 19]},
222 {"year": 2025, "doy": 43, "initial_time": [2,25], "final_time": [2,38], "aux_index": [ null, 24]},
223 {"year": 2025, "doy": 43, "initial_time": [2,2], "final_time": [2,2], "aux_index": [ null, null]},
224
225 {"year": 2025, "doy": 43, "initial_time": [5,0], "final_time": [10,50], "aux_index": [ null, 12]},
226 {"year": 2025, "doy": 43, "initial_time": [5,0], "final_time": [23,0], "aux_index": [ null, 8]},
227 {"year": 2025, "doy": 44, "initial_time": [0,50], "final_time": [0,50], "aux_index": [ 47, null]},
228 {"year": 2025, "doy": 44, "initial_time": [1,0], "final_time": [1,15], "aux_index": [ 39, null]},
229 {"year": 2025, "doy": 44, "initial_time": [3,14], "final_time": [3,40], "aux_index": [ null, 30]},
230 {"year": 2025, "doy": 44, "initial_time": [3,26], "final_time": [3,26], "aux_index": [ null, 32]},
231 {"year": 2025, "doy": 44, "initial_time": [0,14], "final_time": [3,40], "aux_index": [ null, 22]},
232 {"year": 2025, "doy": 44, "initial_time": [0,40], "final_time": [3,40], "aux_index": [ null, 25]},
233 {"year": 2025, "doy": 44, "initial_time": [4,0], "final_time": [5,0], "aux_index": [ null, null]},
234
235 {"year": 2025, "doy": 44, "initial_time": [5,50], "final_time": [5,50], "aux_index": [ null, null]},
236 {"year": 2025, "doy": 44, "initial_time": [7,50], "final_time": [8,38], "aux_index": [ null, null]},
237 {"year": 2025, "doy": 44, "initial_time": [5,0], "final_time": [9,14], "aux_index": [ null, 14]}
238
189 239
190 240 ]}
191 241
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now