##// END OF EJS Templates
profile concat parameter
avaldez -
r1247:9ada11315bac
parent child
Show More
@@ -1,1251 +1,1261
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 5 '''
6 6
7 7 import copy
8 8 import numpy
9 9 import datetime
10 10
11 11 from jroheaderIO import SystemHeader, RadarControllerHeader
12 12 from schainpy import cSchain
13 13
14 14
15 15 def getNumpyDtype(dataTypeCode):
16 16
17 17 if dataTypeCode == 0:
18 18 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
19 19 elif dataTypeCode == 1:
20 20 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
21 21 elif dataTypeCode == 2:
22 22 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
23 23 elif dataTypeCode == 3:
24 24 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
25 25 elif dataTypeCode == 4:
26 26 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
27 27 elif dataTypeCode == 5:
28 28 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
29 29 else:
30 30 raise ValueError, 'dataTypeCode was not defined'
31 31
32 32 return numpyDtype
33 33
34 34
35 35 def getDataTypeCode(numpyDtype):
36 36
37 37 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
38 38 datatype = 0
39 39 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
40 40 datatype = 1
41 41 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
42 42 datatype = 2
43 43 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
44 44 datatype = 3
45 45 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
46 46 datatype = 4
47 47 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
48 48 datatype = 5
49 49 else:
50 50 datatype = None
51 51
52 52 return datatype
53 53
54 54
55 55 def hildebrand_sekhon(data, navg):
56 56 """
57 57 This method is for the objective determination of the noise level in Doppler spectra. This
58 58 implementation technique is based on the fact that the standard deviation of the spectral
59 59 densities is equal to the mean spectral density for white Gaussian noise
60 60
61 61 Inputs:
62 62 Data : heights
63 63 navg : numbers of averages
64 64
65 65 Return:
66 66 -1 : any error
67 67 anoise : noise's level
68 68 """
69 69
70 70 sortdata = numpy.sort(data, axis=None)
71 71 # lenOfData = len(sortdata)
72 72 # nums_min = lenOfData*0.2
73 73 #
74 74 # if nums_min <= 5:
75 75 # nums_min = 5
76 76 #
77 77 # sump = 0.
78 78 #
79 79 # sumq = 0.
80 80 #
81 81 # j = 0
82 82 #
83 83 # cont = 1
84 84 #
85 85 # while((cont==1)and(j<lenOfData)):
86 86 #
87 87 # sump += sortdata[j]
88 88 #
89 89 # sumq += sortdata[j]**2
90 90 #
91 91 # if j > nums_min:
92 92 # rtest = float(j)/(j-1) + 1.0/navg
93 93 # if ((sumq*j) > (rtest*sump**2)):
94 94 # j = j - 1
95 95 # sump = sump - sortdata[j]
96 96 # sumq = sumq - sortdata[j]**2
97 97 # cont = 0
98 98 #
99 99 # j += 1
100 100 #
101 101 # lnoise = sump /j
102 102 #
103 103 # return lnoise
104 104
105 105 return cSchain.hildebrand_sekhon(sortdata, navg)
106 106
107 107
108 108 class Beam:
109 109
110 110 def __init__(self):
111 111 self.codeList = []
112 112 self.azimuthList = []
113 113 self.zenithList = []
114 114
115 115
116 116 class GenericData(object):
117 117
118 118 flagNoData = True
119 119
120 120 def copy(self, inputObj=None):
121 121
122 122 if inputObj == None:
123 123 return copy.deepcopy(self)
124 124
125 125 for key in inputObj.__dict__.keys():
126 126
127 127 attribute = inputObj.__dict__[key]
128 128
129 129 # If this attribute is a tuple or list
130 130 if type(inputObj.__dict__[key]) in (tuple, list):
131 131 self.__dict__[key] = attribute[:]
132 132 continue
133 133
134 134 # If this attribute is another object or instance
135 135 if hasattr(attribute, '__dict__'):
136 136 self.__dict__[key] = attribute.copy()
137 137 continue
138 138
139 139 self.__dict__[key] = inputObj.__dict__[key]
140 140
141 141 def deepcopy(self):
142 142
143 143 return copy.deepcopy(self)
144 144
145 145 def isEmpty(self):
146 146
147 147 return self.flagNoData
148 148
149 149
150 150 class JROData(GenericData):
151 151
152 152 # m_BasicHeader = BasicHeader()
153 153 # m_ProcessingHeader = ProcessingHeader()
154 154
155 155 systemHeaderObj = SystemHeader()
156 156
157 157 radarControllerHeaderObj = RadarControllerHeader()
158 158
159 159 # data = None
160 160
161 161 type = None
162 162
163 163 datatype = None # dtype but in string
164 164
165 165 # dtype = None
166 166
167 167 # nChannels = None
168 168
169 169 # nHeights = None
170 170
171 171 nProfiles = None
172 172
173 173 heightList = None
174 174
175 175 channelList = None
176 176
177 177 flagDiscontinuousBlock = False
178 178
179 179 useLocalTime = False
180 180
181 181 utctime = None
182 182
183 183 timeZone = None
184 184
185 185 dstFlag = None
186 186
187 187 errorCount = None
188 188
189 189 blocksize = None
190 190
191 191 # nCode = None
192 192 #
193 193 # nBaud = None
194 194 #
195 195 # code = None
196 196
197 197 flagDecodeData = False # asumo q la data no esta decodificada
198 198
199 199 flagDeflipData = False # asumo q la data no esta sin flip
200 200
201 201 flagShiftFFT = False
202 202
203 203 # ippSeconds = None
204 204
205 205 # timeInterval = None
206 206
207 207 nCohInt = None
208 208
209 209 # noise = None
210 210
211 211 windowOfFilter = 1
212 212
213 213 # Speed of ligth
214 214 C = 3e8
215 215
216 216 frequency = 49.92e6
217 217
218 218 realtime = False
219 219
220 220 beacon_heiIndexList = None
221 221
222 222 last_block = None
223 223
224 224 blocknow = None
225 225
226 226 azimuth = None
227 227
228 228 zenith = None
229 229
230 230 beam = Beam()
231 231
232 232 profileIndex = None
233 233
234 234 def getNoise(self):
235 235
236 236 raise NotImplementedError
237 237
238 238 def getNChannels(self):
239 239
240 240 return len(self.channelList)
241 241
242 242 def getChannelIndexList(self):
243 243
244 244 return range(self.nChannels)
245 245
246 246 def getNHeights(self):
247 247
248 248 return len(self.heightList)
249 249
250 250 def getHeiRange(self, extrapoints=0):
251 251
252 252 heis = self.heightList
253 253 # deltah = self.heightList[1] - self.heightList[0]
254 254 #
255 255 # heis.append(self.heightList[-1])
256 256
257 257 return heis
258 258
259 259 def getDeltaH(self):
260 260
261 261 delta = self.heightList[1] - self.heightList[0]
262 262
263 263 return delta
264 264
265 265 def getltctime(self):
266 266
267 267 if self.useLocalTime:
268 268 return self.utctime - self.timeZone * 60
269 269
270 270 return self.utctime
271 271
272 272 def getDatatime(self):
273 273
274 274 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
275 275 return datatimeValue
276 276
277 277 def getTimeRange(self):
278 278
279 279 datatime = []
280 280
281 281 datatime.append(self.ltctime)
282 282 datatime.append(self.ltctime + self.timeInterval + 1)
283 283
284 284 datatime = numpy.array(datatime)
285 285
286 286 return datatime
287 287
288 288 def getFmaxTimeResponse(self):
289 289
290 290 period = (10**-6) * self.getDeltaH() / (0.15)
291 291
292 292 PRF = 1. / (period * self.nCohInt)
293 293
294 294 fmax = PRF
295 295
296 296 return fmax
297 297
298 298 def getFmax(self):
299 299 PRF = 1. / (self.ippSeconds * self.nCohInt)
300 #print "ippSeconds",self.ippSeconds
301 #print "nCohInt",self.nIncohInt
302 #print PRF
303 #import time
304 #time.sleep(30)
300 305 fmax = PRF
301 306 return fmax
302 307
303 308 def getVmax(self):
304 309
305 310 _lambda = self.C / self.frequency
306 311
307 312 vmax = self.getFmax() * _lambda / 2
308 313
309 314 return vmax
310 315
311 316 def get_ippSeconds(self):
312 317 '''
313 318 '''
314 319 return self.radarControllerHeaderObj.ippSeconds
315 320
316 321 def set_ippSeconds(self, ippSeconds):
317 322 '''
318 323 '''
319 324
320 325 self.radarControllerHeaderObj.ippSeconds = ippSeconds
321 326
322 327 return
323 328
324 329 def get_dtype(self):
325 330 '''
326 331 '''
327 332 return getNumpyDtype(self.datatype)
328 333
329 334 def set_dtype(self, numpyDtype):
330 335 '''
331 336 '''
332 337
333 338 self.datatype = getDataTypeCode(numpyDtype)
334 339
335 340 def get_code(self):
336 341 '''
337 342 '''
338 343 return self.radarControllerHeaderObj.code
339 344
340 345 def set_code(self, code):
341 346 '''
342 347 '''
343 348 self.radarControllerHeaderObj.code = code
344 349
345 350 return
346 351
347 352 def get_ncode(self):
348 353 '''
349 354 '''
350 355 return self.radarControllerHeaderObj.nCode
351 356
352 357 def set_ncode(self, nCode):
353 358 '''
354 359 '''
355 360 self.radarControllerHeaderObj.nCode = nCode
356 361
357 362 return
358 363
359 364 def get_nbaud(self):
360 365 '''
361 366 '''
362 367 return self.radarControllerHeaderObj.nBaud
363 368
364 369 def set_nbaud(self, nBaud):
365 370 '''
366 371 '''
367 372 self.radarControllerHeaderObj.nBaud = nBaud
368 373
369 374 return
370 375
371 376 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
372 377 channelIndexList = property(
373 378 getChannelIndexList, "I'm the 'channelIndexList' property.")
374 379 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
375 380 #noise = property(getNoise, "I'm the 'nHeights' property.")
376 381 datatime = property(getDatatime, "I'm the 'datatime' property")
377 382 ltctime = property(getltctime, "I'm the 'ltctime' property")
378 383 ippSeconds = property(get_ippSeconds, set_ippSeconds)
379 384 dtype = property(get_dtype, set_dtype)
380 385 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
381 386 code = property(get_code, set_code)
382 387 nCode = property(get_ncode, set_ncode)
383 388 nBaud = property(get_nbaud, set_nbaud)
384 389
385 390
386 391 class Voltage(JROData):
387 392
388 393 # data es un numpy array de 2 dmensiones (canales, alturas)
389 394 data = None
390 395
391 396 def __init__(self):
392 397 '''
393 398 Constructor
394 399 '''
395 400
396 401 self.useLocalTime = True
397 402
398 403 self.radarControllerHeaderObj = RadarControllerHeader()
399 404
400 405 self.systemHeaderObj = SystemHeader()
401 406
402 407 self.type = "Voltage"
403 408
404 409 self.data = None
405 410
406 411 # self.dtype = None
407 412
408 413 # self.nChannels = 0
409 414
410 415 # self.nHeights = 0
411 416
412 417 self.nProfiles = None
413 418
414 419 self.heightList = None
415 420
416 421 self.channelList = None
417 422
418 423 # self.channelIndexList = None
419 424
420 425 self.flagNoData = True
421 426
422 427 self.flagDiscontinuousBlock = False
423 428
424 429 self.utctime = None
425 430
426 431 self.timeZone = None
427 432
428 433 self.dstFlag = None
429 434
430 435 self.errorCount = None
431 436
432 437 self.nCohInt = None
433 438
434 439 self.blocksize = None
435 440
436 441 self.flagDecodeData = False # asumo q la data no esta decodificada
437 442
438 443 self.flagDeflipData = False # asumo q la data no esta sin flip
439 444
440 445 self.flagShiftFFT = False
441 446
442 447 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
443 448
444 449 self.profileIndex = 0
445 450
446 451 def getNoisebyHildebrand(self, channel=None):
447 452 """
448 453 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
449 454
450 455 Return:
451 456 noiselevel
452 457 """
453 458
454 459 if channel != None:
455 460 data = self.data[channel]
456 461 nChannels = 1
457 462 else:
458 463 data = self.data
459 464 nChannels = self.nChannels
460 465
461 466 noise = numpy.zeros(nChannels)
462 467 power = data * numpy.conjugate(data)
463 468
464 469 for thisChannel in range(nChannels):
465 470 if nChannels == 1:
466 471 daux = power[:].real
467 472 else:
468 473 daux = power[thisChannel, :].real
469 474 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
470 475
471 476 return noise
472 477
473 478 def getNoise(self, type=1, channel=None):
474 479
475 480 if type == 1:
476 481 noise = self.getNoisebyHildebrand(channel)
477 482
478 483 return noise
479 484
480 485 def getPower(self, channel=None):
481 486
482 487 if channel != None:
483 488 data = self.data[channel]
484 489 else:
485 490 data = self.data
486 491
487 492 power = data * numpy.conjugate(data)
488 493 powerdB = 10 * numpy.log10(power.real)
489 494 powerdB = numpy.squeeze(powerdB)
490 495
491 496 return powerdB
492 497
493 498 def getTimeInterval(self):
494 499
495 500 timeInterval = self.ippSeconds * self.nCohInt
496 501
497 502 return timeInterval
498 503
499 504 noise = property(getNoise, "I'm the 'nHeights' property.")
500 505 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
501 506
502 507
503 508 class Spectra(JROData):
504 509
505 510 # data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
506 511 data_spc = None
507 512
508 513 # data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
509 514 data_cspc = None
510 515
511 516 # data dc es un numpy array de 2 dmensiones (canales, alturas)
512 517 data_dc = None
513 518
514 519 # data power
515 520 data_pwr = None
516 521
517 522 nFFTPoints = None
518 523
519 524 # nPairs = None
520 525
521 526 pairsList = None
522 527
523 528 nIncohInt = None
524 529
525 530 wavelength = None # Necesario para cacular el rango de velocidad desde la frecuencia
526 531
527 532 nCohInt = None # se requiere para determinar el valor de timeInterval
528 533
529 534 ippFactor = None
530 535
531 536 profileIndex = 0
532 537
533 538 plotting = "spectra"
534 539
535 540 def __init__(self):
536 541 '''
537 542 Constructor
538 543 '''
539 544
540 545 self.useLocalTime = True
541 546
542 547 self.radarControllerHeaderObj = RadarControllerHeader()
543 548
544 549 self.systemHeaderObj = SystemHeader()
545 550
546 551 self.type = "Spectra"
547 552
548 553 # self.data = None
549 554
550 555 # self.dtype = None
551 556
552 557 # self.nChannels = 0
553 558
554 559 # self.nHeights = 0
555 560
556 561 self.nProfiles = None
557 562
558 563 self.heightList = None
559 564
560 565 self.channelList = None
561 566
562 567 # self.channelIndexList = None
563 568
564 569 self.pairsList = None
565 570
566 571 self.flagNoData = True
567 572
568 573 self.flagDiscontinuousBlock = False
569 574
570 575 self.utctime = None
571 576
572 577 self.nCohInt = None
573 578
574 579 self.nIncohInt = None
575 580
576 581 self.blocksize = None
577 582
578 583 self.nFFTPoints = None
579 584
580 585 self.wavelength = None
581 586
582 587 self.flagDecodeData = False # asumo q la data no esta decodificada
583 588
584 589 self.flagDeflipData = False # asumo q la data no esta sin flip
585 590
586 591 self.flagShiftFFT = False
587 592
588 593 self.ippFactor = 1
589 594
590 595 #self.noise = None
591 596
592 597 self.beacon_heiIndexList = []
593 598
594 599 self.noise_estimation = None
595 600
596 601 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
597 602 """
598 603 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
599 604
600 605 Return:
601 606 noiselevel
602 607 """
603 608
604 609 noise = numpy.zeros(self.nChannels)
605 610
606 611 for channel in range(self.nChannels):
607 612 daux = self.data_spc[channel,
608 613 xmin_index:xmax_index, ymin_index:ymax_index]
609 614
610 615 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
611 616
612 617 return noise
613 618
614 619 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
615 620
616 621 if self.noise_estimation is not None:
617 622 # this was estimated by getNoise Operation defined in jroproc_spectra.py
618 623 return self.noise_estimation
619 624 else:
620 625 noise = self.getNoisebyHildebrand(
621 626 xmin_index, xmax_index, ymin_index, ymax_index)
622 627 return noise
623 628
624 629 def getFreqRangeTimeResponse(self, extrapoints=0):
625 630
626 631 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
627 632 freqrange = deltafreq * \
628 633 (numpy.arange(self.nFFTPoints + extrapoints) -
629 634 self.nFFTPoints / 2.) - deltafreq / 2
630 635
631 636 return freqrange
632 637
633 638 def getAcfRange(self, extrapoints=0):
639 #print "NFFTPoints",self.nFFTPoints
640 #print "IPPFactor", self.ippFactor
634 641 deltafreq = 10. / ( self.getFmax() / (self.nFFTPoints * self.ippFactor) )
642 #print "deltafreq",deltafreq
643 #import time
644 #time.sleep(30)
635 645 freqrange = deltafreq * \
636 646 (numpy.arange(self.nFFTPoints + extrapoints) -
637 647 self.nFFTPoints / 2.) - deltafreq / 2
638 648
639 649 return freqrange
640 650
641 651 def getFreqRange(self, extrapoints=0):
642 652
643 653 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
644 654 #print "deltafreq", deltafreq
645 655 freqrange = deltafreq * \
646 656 (numpy.arange(self.nFFTPoints + extrapoints) -
647 657 self.nFFTPoints / 2.) - deltafreq / 2
648 658 #print "freqrange",freqrange
649 659 return freqrange
650 660
651 661 def getVelRange(self, extrapoints=0):
652 662
653 663 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
654 664 velrange = deltav * (numpy.arange(self.nFFTPoints +
655 665 extrapoints) - self.nFFTPoints / 2.) # - deltav/2
656 666
657 667 return velrange
658 668
659 669 def getNPairs(self):
660 670
661 671 return len(self.pairsList)
662 672
663 673 def getPairsIndexList(self):
664 674
665 675 return range(self.nPairs)
666 676
667 677 def getNormFactor(self):
668 678
669 679 pwcode = 1
670 680
671 681 if self.flagDecodeData:
672 682 pwcode = numpy.sum(self.code[0]**2)
673 683 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
674 684 normFactor = self.nProfiles * self.nIncohInt * \
675 685 self.nCohInt * pwcode * self.windowOfFilter
676 686
677 687 return normFactor
678 688
679 689 def getFlagCspc(self):
680 690
681 691 if self.data_cspc is None:
682 692 return True
683 693
684 694 return False
685 695
686 696 def getFlagDc(self):
687 697
688 698 if self.data_dc is None:
689 699 return True
690 700
691 701 return False
692 702
693 703 def getTimeInterval(self):
694 704
695 705 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
696 706
697 707 return timeInterval
698 708
699 709 def getPower(self):
700 710
701 711 factor = self.normFactor
702 712 z = self.data_spc / factor
703 713 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
704 714 avg = numpy.average(z, axis=1)
705 715
706 716 return 10 * numpy.log10(avg)
707 717
708 718 def getCoherence(self, pairsList=None, phase=False):
709 719
710 720 z = []
711 721 if pairsList is None:
712 722 pairsIndexList = self.pairsIndexList
713 723 else:
714 724 pairsIndexList = []
715 725 for pair in pairsList:
716 726 if pair not in self.pairsList:
717 727 raise ValueError, "Pair %s is not in dataOut.pairsList" % (
718 728 pair)
719 729 pairsIndexList.append(self.pairsList.index(pair))
720 730 for i in range(len(pairsIndexList)):
721 731 pair = self.pairsList[pairsIndexList[i]]
722 732 ccf = numpy.average(
723 733 self.data_cspc[pairsIndexList[i], :, :], axis=0)
724 734 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
725 735 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
726 736 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
727 737 if phase:
728 738 data = numpy.arctan2(avgcoherenceComplex.imag,
729 739 avgcoherenceComplex.real) * 180 / numpy.pi
730 740 else:
731 741 data = numpy.abs(avgcoherenceComplex)
732 742
733 743 z.append(data)
734 744
735 745 return numpy.array(z)
736 746
737 747 def setValue(self, value):
738 748
739 749 print "This property should not be initialized"
740 750
741 751 return
742 752
743 753 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
744 754 pairsIndexList = property(
745 755 getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
746 756 normFactor = property(getNormFactor, setValue,
747 757 "I'm the 'getNormFactor' property.")
748 758 flag_cspc = property(getFlagCspc, setValue)
749 759 flag_dc = property(getFlagDc, setValue)
750 760 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
751 761 timeInterval = property(getTimeInterval, setValue,
752 762 "I'm the 'timeInterval' property")
753 763
754 764
755 765 class SpectraHeis(Spectra):
756 766
757 767 data_spc = None
758 768
759 769 data_cspc = None
760 770
761 771 data_dc = None
762 772
763 773 nFFTPoints = None
764 774
765 775 # nPairs = None
766 776
767 777 pairsList = None
768 778
769 779 nCohInt = None
770 780
771 781 nIncohInt = None
772 782
773 783 def __init__(self):
774 784
775 785 self.radarControllerHeaderObj = RadarControllerHeader()
776 786
777 787 self.systemHeaderObj = SystemHeader()
778 788
779 789 self.type = "SpectraHeis"
780 790
781 791 # self.dtype = None
782 792
783 793 # self.nChannels = 0
784 794
785 795 # self.nHeights = 0
786 796
787 797 self.nProfiles = None
788 798
789 799 self.heightList = None
790 800
791 801 self.channelList = None
792 802
793 803 # self.channelIndexList = None
794 804
795 805 self.flagNoData = True
796 806
797 807 self.flagDiscontinuousBlock = False
798 808
799 809 # self.nPairs = 0
800 810
801 811 self.utctime = None
802 812
803 813 self.blocksize = None
804 814
805 815 self.profileIndex = 0
806 816
807 817 self.nCohInt = 1
808 818
809 819 self.nIncohInt = 1
810 820
811 821 def getNormFactor(self):
812 822 pwcode = 1
813 823 if self.flagDecodeData:
814 824 pwcode = numpy.sum(self.code[0]**2)
815 825
816 826 normFactor = self.nIncohInt * self.nCohInt * pwcode
817 827
818 828 return normFactor
819 829
820 830 def getTimeInterval(self):
821 831
822 832 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
823 833
824 834 return timeInterval
825 835
826 836 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
827 837 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
828 838
829 839
830 840 class Fits(JROData):
831 841
832 842 heightList = None
833 843
834 844 channelList = None
835 845
836 846 flagNoData = True
837 847
838 848 flagDiscontinuousBlock = False
839 849
840 850 useLocalTime = False
841 851
842 852 utctime = None
843 853
844 854 timeZone = None
845 855
846 856 # ippSeconds = None
847 857
848 858 # timeInterval = None
849 859
850 860 nCohInt = None
851 861
852 862 nIncohInt = None
853 863
854 864 noise = None
855 865
856 866 windowOfFilter = 1
857 867
858 868 # Speed of ligth
859 869 C = 3e8
860 870
861 871 frequency = 49.92e6
862 872
863 873 realtime = False
864 874
865 875 def __init__(self):
866 876
867 877 self.type = "Fits"
868 878
869 879 self.nProfiles = None
870 880
871 881 self.heightList = None
872 882
873 883 self.channelList = None
874 884
875 885 # self.channelIndexList = None
876 886
877 887 self.flagNoData = True
878 888
879 889 self.utctime = None
880 890
881 891 self.nCohInt = 1
882 892
883 893 self.nIncohInt = 1
884 894
885 895 self.useLocalTime = True
886 896
887 897 self.profileIndex = 0
888 898
889 899 # self.utctime = None
890 900 # self.timeZone = None
891 901 # self.ltctime = None
892 902 # self.timeInterval = None
893 903 # self.header = None
894 904 # self.data_header = None
895 905 # self.data = None
896 906 # self.datatime = None
897 907 # self.flagNoData = False
898 908 # self.expName = ''
899 909 # self.nChannels = None
900 910 # self.nSamples = None
901 911 # self.dataBlocksPerFile = None
902 912 # self.comments = ''
903 913 #
904 914
905 915 def getltctime(self):
906 916
907 917 if self.useLocalTime:
908 918 return self.utctime - self.timeZone * 60
909 919
910 920 return self.utctime
911 921
912 922 def getDatatime(self):
913 923
914 924 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
915 925 return datatime
916 926
917 927 def getTimeRange(self):
918 928
919 929 datatime = []
920 930
921 931 datatime.append(self.ltctime)
922 932 datatime.append(self.ltctime + self.timeInterval)
923 933
924 934 datatime = numpy.array(datatime)
925 935
926 936 return datatime
927 937
928 938 def getHeiRange(self):
929 939
930 940 heis = self.heightList
931 941
932 942 return heis
933 943
934 944 def getNHeights(self):
935 945
936 946 return len(self.heightList)
937 947
938 948 def getNChannels(self):
939 949
940 950 return len(self.channelList)
941 951
942 952 def getChannelIndexList(self):
943 953
944 954 return range(self.nChannels)
945 955
946 956 def getNoise(self, type=1):
947 957
948 958 #noise = numpy.zeros(self.nChannels)
949 959
950 960 if type == 1:
951 961 noise = self.getNoisebyHildebrand()
952 962
953 963 if type == 2:
954 964 noise = self.getNoisebySort()
955 965
956 966 if type == 3:
957 967 noise = self.getNoisebyWindow()
958 968
959 969 return noise
960 970
961 971 def getTimeInterval(self):
962 972
963 973 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
964 974
965 975 return timeInterval
966 976
967 977 datatime = property(getDatatime, "I'm the 'datatime' property")
968 978 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
969 979 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
970 980 channelIndexList = property(
971 981 getChannelIndexList, "I'm the 'channelIndexList' property.")
972 982 noise = property(getNoise, "I'm the 'nHeights' property.")
973 983
974 984 ltctime = property(getltctime, "I'm the 'ltctime' property")
975 985 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
976 986
977 987
978 988 class Correlation(JROData):
979 989
980 990 noise = None
981 991
982 992 SNR = None
983 993
984 994 #--------------------------------------------------
985 995
986 996 mode = None
987 997
988 998 split = False
989 999
990 1000 data_cf = None
991 1001
992 1002 lags = None
993 1003
994 1004 lagRange = None
995 1005
996 1006 pairsList = None
997 1007
998 1008 normFactor = None
999 1009
1000 1010 #--------------------------------------------------
1001 1011
1002 1012 # calculateVelocity = None
1003 1013
1004 1014 nLags = None
1005 1015
1006 1016 nPairs = None
1007 1017
1008 1018 nAvg = None
1009 1019
1010 1020 def __init__(self):
1011 1021 '''
1012 1022 Constructor
1013 1023 '''
1014 1024 self.radarControllerHeaderObj = RadarControllerHeader()
1015 1025
1016 1026 self.systemHeaderObj = SystemHeader()
1017 1027
1018 1028 self.type = "Correlation"
1019 1029
1020 1030 self.data = None
1021 1031
1022 1032 self.dtype = None
1023 1033
1024 1034 self.nProfiles = None
1025 1035
1026 1036 self.heightList = None
1027 1037
1028 1038 self.channelList = None
1029 1039
1030 1040 self.flagNoData = True
1031 1041
1032 1042 self.flagDiscontinuousBlock = False
1033 1043
1034 1044 self.utctime = None
1035 1045
1036 1046 self.timeZone = None
1037 1047
1038 1048 self.dstFlag = None
1039 1049
1040 1050 self.errorCount = None
1041 1051
1042 1052 self.blocksize = None
1043 1053
1044 1054 self.flagDecodeData = False # asumo q la data no esta decodificada
1045 1055
1046 1056 self.flagDeflipData = False # asumo q la data no esta sin flip
1047 1057
1048 1058 self.pairsList = None
1049 1059
1050 1060 self.nPoints = None
1051 1061
1052 1062 def getPairsList(self):
1053 1063
1054 1064 return self.pairsList
1055 1065
1056 1066 def getNoise(self, mode=2):
1057 1067
1058 1068 indR = numpy.where(self.lagR == 0)[0][0]
1059 1069 indT = numpy.where(self.lagT == 0)[0][0]
1060 1070
1061 1071 jspectra0 = self.data_corr[:, :, indR, :]
1062 1072 jspectra = copy.copy(jspectra0)
1063 1073
1064 1074 num_chan = jspectra.shape[0]
1065 1075 num_hei = jspectra.shape[2]
1066 1076
1067 1077 freq_dc = jspectra.shape[1] / 2
1068 1078 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
1069 1079
1070 1080 if ind_vel[0] < 0:
1071 1081 ind_vel[range(0, 1)] = ind_vel[range(0, 1)] + self.num_prof
1072 1082
1073 1083 if mode == 1:
1074 1084 jspectra[:, freq_dc, :] = (
1075 1085 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
1076 1086
1077 1087 if mode == 2:
1078 1088
1079 1089 vel = numpy.array([-2, -1, 1, 2])
1080 1090 xx = numpy.zeros([4, 4])
1081 1091
1082 1092 for fil in range(4):
1083 1093 xx[fil, :] = vel[fil]**numpy.asarray(range(4))
1084 1094
1085 1095 xx_inv = numpy.linalg.inv(xx)
1086 1096 xx_aux = xx_inv[0, :]
1087 1097
1088 1098 for ich in range(num_chan):
1089 1099 yy = jspectra[ich, ind_vel, :]
1090 1100 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
1091 1101
1092 1102 junkid = jspectra[ich, freq_dc, :] <= 0
1093 1103 cjunkid = sum(junkid)
1094 1104
1095 1105 if cjunkid.any():
1096 1106 jspectra[ich, freq_dc, junkid.nonzero()] = (
1097 1107 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
1098 1108
1099 1109 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
1100 1110
1101 1111 return noise
1102 1112
1103 1113 def getTimeInterval(self):
1104 1114
1105 1115 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1106 1116
1107 1117 return timeInterval
1108 1118
1109 1119 def splitFunctions(self):
1110 1120
1111 1121 pairsList = self.pairsList
1112 1122 ccf_pairs = []
1113 1123 acf_pairs = []
1114 1124 ccf_ind = []
1115 1125 acf_ind = []
1116 1126 for l in range(len(pairsList)):
1117 1127 chan0 = pairsList[l][0]
1118 1128 chan1 = pairsList[l][1]
1119 1129
1120 1130 # Obteniendo pares de Autocorrelacion
1121 1131 if chan0 == chan1:
1122 1132 acf_pairs.append(chan0)
1123 1133 acf_ind.append(l)
1124 1134 else:
1125 1135 ccf_pairs.append(pairsList[l])
1126 1136 ccf_ind.append(l)
1127 1137
1128 1138 data_acf = self.data_cf[acf_ind]
1129 1139 data_ccf = self.data_cf[ccf_ind]
1130 1140
1131 1141 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1132 1142
1133 1143 def getNormFactor(self):
1134 1144 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1135 1145 acf_pairs = numpy.array(acf_pairs)
1136 1146 normFactor = numpy.zeros((self.nPairs, self.nHeights))
1137 1147
1138 1148 for p in range(self.nPairs):
1139 1149 pair = self.pairsList[p]
1140 1150
1141 1151 ch0 = pair[0]
1142 1152 ch1 = pair[1]
1143 1153
1144 1154 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
1145 1155 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
1146 1156 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
1147 1157
1148 1158 return normFactor
1149 1159
1150 1160 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1151 1161 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1152 1162
1153 1163
1154 1164 class Parameters(Spectra):
1155 1165
1156 1166 experimentInfo = None # Information about the experiment
1157 1167
1158 1168 # Information from previous data
1159 1169
1160 1170 inputUnit = None # Type of data to be processed
1161 1171
1162 1172 operation = None # Type of operation to parametrize
1163 1173
1164 1174 # normFactor = None #Normalization Factor
1165 1175
1166 1176 groupList = None # List of Pairs, Groups, etc
1167 1177
1168 1178 # Parameters
1169 1179
1170 1180 data_param = None # Parameters obtained
1171 1181
1172 1182 data_pre = None # Data Pre Parametrization
1173 1183
1174 1184 data_SNR = None # Signal to Noise Ratio
1175 1185
1176 1186 # heightRange = None #Heights
1177 1187
1178 1188 abscissaList = None # Abscissa, can be velocities, lags or time
1179 1189
1180 1190 # noise = None #Noise Potency
1181 1191
1182 1192 utctimeInit = None # Initial UTC time
1183 1193
1184 1194 paramInterval = None # Time interval to calculate Parameters in seconds
1185 1195
1186 1196 useLocalTime = True
1187 1197
1188 1198 # Fitting
1189 1199
1190 1200 data_error = None # Error of the estimation
1191 1201
1192 1202 constants = None
1193 1203
1194 1204 library = None
1195 1205
1196 1206 # Output signal
1197 1207
1198 1208 outputInterval = None # Time interval to calculate output signal in seconds
1199 1209
1200 1210 data_output = None # Out signal
1201 1211
1202 1212 nAvg = None
1203 1213
1204 1214 noise_estimation = None
1205 1215
1206 1216 GauSPC = None # Fit gaussian SPC
1207 1217
1208 1218 def __init__(self):
1209 1219 '''
1210 1220 Constructor
1211 1221 '''
1212 1222 self.radarControllerHeaderObj = RadarControllerHeader()
1213 1223
1214 1224 self.systemHeaderObj = SystemHeader()
1215 1225
1216 1226 self.type = "Parameters"
1217 1227
1218 1228 def getTimeRange1(self, interval):
1219 1229
1220 1230 datatime = []
1221 1231
1222 1232 if self.useLocalTime:
1223 1233 time1 = self.utctimeInit - self.timeZone * 60
1224 1234 else:
1225 1235 time1 = self.utctimeInit
1226 1236
1227 1237 datatime.append(time1)
1228 1238 datatime.append(time1 + interval)
1229 1239 datatime = numpy.array(datatime)
1230 1240
1231 1241 return datatime
1232 1242
1233 1243 def getTimeInterval(self):
1234 1244
1235 1245 if hasattr(self, 'timeInterval1'):
1236 1246 return self.timeInterval1
1237 1247 else:
1238 1248 return self.paramInterval
1239 1249
1240 1250 def setValue(self, value):
1241 1251
1242 1252 print "This property should not be initialized"
1243 1253
1244 1254 return
1245 1255
1246 1256 def getNoise(self):
1247 1257
1248 1258 return self.spc_noise
1249 1259
1250 1260 timeInterval = property(getTimeInterval)
1251 1261 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
@@ -1,1520 +1,1530
1 1 import sys
2 2 import numpy
3 3 from scipy import interpolate
4 4 from schainpy import cSchain
5 5 from jroproc_base import ProcessingUnit, Operation
6 6 from schainpy.model.data.jrodata import Voltage
7 7 from time import time
8 8
9 9 import math
10 10
11 11 def rep_seq(x, rep=10):
12 12 L = len(x) * rep
13 13 res = numpy.zeros(L, dtype=x.dtype)
14 14 idx = numpy.arange(len(x)) * rep
15 15 for i in numpy.arange(rep):
16 16 res[idx + i] = x
17 17 return(res)
18 18
19 19
20 20 def create_pseudo_random_code(clen=10000, seed=0):
21 21 """
22 22 seed is a way of reproducing the random code without
23 23 having to store all actual codes. the seed can then
24 24 act as a sort of station_id.
25 25
26 26 """
27 27 numpy.random.seed(seed)
28 28 phases = numpy.array(
29 29 numpy.exp(1.0j * 2.0 * math.pi * numpy.random.random(clen)),
30 30 dtype=numpy.complex64,
31 31 )
32 32 return(phases)
33 33
34 34
35 35 def periodic_convolution_matrix(envelope, rmin=0, rmax=100):
36 36 """
37 37 we imply that the number of measurements is equal to the number of elements
38 38 in code
39 39
40 40 """
41 41 L = len(envelope)
42 42 ridx = numpy.arange(rmin, rmax)
43 43 A = numpy.zeros([L, rmax-rmin], dtype=numpy.complex64)
44 44 for i in numpy.arange(L):
45 45 A[i, :] = envelope[(i-ridx) % L]
46 46 result = {}
47 47 result['A'] = A
48 48 result['ridx'] = ridx
49 49 return(result)
50 50
51 51
52 52 B_cache = 0
53 53 r_cache = 0
54 54 B_cached = False
55 55 def create_estimation_matrix(code, rmin=0, rmax=1000, cache=True):
56 56 global B_cache
57 57 global r_cache
58 58 global B_cached
59 59
60 60 if not cache or not B_cached:
61 61 r_cache = periodic_convolution_matrix(
62 62 envelope=code, rmin=rmin, rmax=rmax,
63 63 )
64 64 A = r_cache['A']
65 65 Ah = numpy.transpose(numpy.conjugate(A))
66 66 B_cache = numpy.dot(numpy.linalg.inv(numpy.dot(Ah, A)), Ah)
67 67 r_cache['B'] = B_cache
68 68 B_cached = True
69 69 return(r_cache)
70 70 else:
71 71 return(r_cache)
72 72
73 73 class VoltageProc(ProcessingUnit):
74 74
75 75
76 76 def __init__(self, **kwargs):
77 77
78 78 ProcessingUnit.__init__(self, **kwargs)
79 79
80 80 # self.objectDict = {}
81 81 self.dataOut = Voltage()
82 82 self.flip = 1
83 83
84 84 def run(self):
85 85 if self.dataIn.type == 'AMISR':
86 86 self.__updateObjFromAmisrInput()
87 87
88 88 if self.dataIn.type == 'Voltage':
89 89 self.dataOut.copy(self.dataIn)
90 90
91 91 # self.dataOut.copy(self.dataIn)
92 92
93 93 def __updateObjFromAmisrInput(self):
94 94
95 95 self.dataOut.timeZone = self.dataIn.timeZone
96 96 self.dataOut.dstFlag = self.dataIn.dstFlag
97 97 self.dataOut.errorCount = self.dataIn.errorCount
98 98 self.dataOut.useLocalTime = self.dataIn.useLocalTime
99 99
100 100 self.dataOut.flagNoData = self.dataIn.flagNoData
101 101 self.dataOut.data = self.dataIn.data
102 102 self.dataOut.utctime = self.dataIn.utctime
103 103 self.dataOut.channelList = self.dataIn.channelList
104 104 # self.dataOut.timeInterval = self.dataIn.timeInterval
105 105 self.dataOut.heightList = self.dataIn.heightList
106 106 self.dataOut.nProfiles = self.dataIn.nProfiles
107 107
108 108 self.dataOut.nCohInt = self.dataIn.nCohInt
109 109 self.dataOut.ippSeconds = self.dataIn.ippSeconds
110 110 self.dataOut.frequency = self.dataIn.frequency
111 111
112 112 self.dataOut.azimuth = self.dataIn.azimuth
113 113 self.dataOut.zenith = self.dataIn.zenith
114 114
115 115 self.dataOut.beam.codeList = self.dataIn.beam.codeList
116 116 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
117 117 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
118 118 #
119 119 # pass#
120 120 #
121 121 # def init(self):
122 122 #
123 123 #
124 124 # if self.dataIn.type == 'AMISR':
125 125 # self.__updateObjFromAmisrInput()
126 126 #
127 127 # if self.dataIn.type == 'Voltage':
128 128 # self.dataOut.copy(self.dataIn)
129 129 # # No necesita copiar en cada init() los atributos de dataIn
130 130 # # la copia deberia hacerse por cada nuevo bloque de datos
131 131
132 132 def selectChannels(self, channelList):
133 133
134 134 channelIndexList = []
135 135
136 136 for channel in channelList:
137 137 if channel not in self.dataOut.channelList:
138 138 raise ValueError, "Channel %d is not in %s" %(channel, str(self.dataOut.channelList))
139 139
140 140 index = self.dataOut.channelList.index(channel)
141 141 channelIndexList.append(index)
142 142
143 143 self.selectChannelsByIndex(channelIndexList)
144 144
145 145 def selectChannelsByIndex(self, channelIndexList):
146 146 """
147 147 Selecciona un bloque de datos en base a canales segun el channelIndexList
148 148
149 149 Input:
150 150 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
151 151
152 152 Affected:
153 153 self.dataOut.data
154 154 self.dataOut.channelIndexList
155 155 self.dataOut.nChannels
156 156 self.dataOut.m_ProcessingHeader.totalSpectra
157 157 self.dataOut.systemHeaderObj.numChannels
158 158 self.dataOut.m_ProcessingHeader.blockSize
159 159
160 160 Return:
161 161 None
162 162 """
163 163
164 164 for channelIndex in channelIndexList:
165 165 if channelIndex not in self.dataOut.channelIndexList:
166 166 print channelIndexList
167 167 raise ValueError, "The value %d in channelIndexList is not valid" %channelIndex
168 168
169 169 if self.dataOut.flagDataAsBlock:
170 170 """
171 171 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
172 172 """
173 173 data = self.dataOut.data[channelIndexList,:,:]
174 174 else:
175 175 data = self.dataOut.data[channelIndexList,:]
176 176
177 177 self.dataOut.data = data
178 178 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
179 179 # self.dataOut.nChannels = nChannels
180 180
181 181 return 1
182 182
183 183 def selectHeights(self, minHei=None, maxHei=None):
184 184 """
185 185 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
186 186 minHei <= height <= maxHei
187 187
188 188 Input:
189 189 minHei : valor minimo de altura a considerar
190 190 maxHei : valor maximo de altura a considerar
191 191
192 192 Affected:
193 193 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
194 194
195 195 Return:
196 196 1 si el metodo se ejecuto con exito caso contrario devuelve 0
197 197 """
198 198
199 199 if minHei == None:
200 200 minHei = self.dataOut.heightList[0]
201 201
202 202 if maxHei == None:
203 203 maxHei = self.dataOut.heightList[-1]
204 204
205 205 if (minHei < self.dataOut.heightList[0]):
206 206 minHei = self.dataOut.heightList[0]
207 207
208 208 if (maxHei > self.dataOut.heightList[-1]):
209 209 maxHei = self.dataOut.heightList[-1]
210 210
211 211 minIndex = 0
212 212 maxIndex = 0
213 213 heights = self.dataOut.heightList
214 214
215 215 inda = numpy.where(heights >= minHei)
216 216 indb = numpy.where(heights <= maxHei)
217 217
218 218 try:
219 219 minIndex = inda[0][0]
220 220 except:
221 221 minIndex = 0
222 222
223 223 try:
224 224 maxIndex = indb[0][-1]
225 225 except:
226 226 maxIndex = len(heights)
227 227
228 228 self.selectHeightsByIndex(minIndex, maxIndex)
229 229
230 230 return 1
231 231
232 232
233 233 def selectHeightsByIndex(self, minIndex, maxIndex):
234 234 """
235 235 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
236 236 minIndex <= index <= maxIndex
237 237
238 238 Input:
239 239 minIndex : valor de indice minimo de altura a considerar
240 240 maxIndex : valor de indice maximo de altura a considerar
241 241
242 242 Affected:
243 243 self.dataOut.data
244 244 self.dataOut.heightList
245 245
246 246 Return:
247 247 1 si el metodo se ejecuto con exito caso contrario devuelve 0
248 248 """
249 249
250 250 if (minIndex < 0) or (minIndex > maxIndex):
251 251 raise ValueError, "Height index range (%d,%d) is not valid" % (minIndex, maxIndex)
252 252
253 253 if (maxIndex >= self.dataOut.nHeights):
254 254 maxIndex = self.dataOut.nHeights
255 255
256 256 #voltage
257 257 if self.dataOut.flagDataAsBlock:
258 258 """
259 259 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
260 260 """
261 261 data = self.dataOut.data[:,:, minIndex:maxIndex]
262 262 else:
263 263 data = self.dataOut.data[:, minIndex:maxIndex]
264 264
265 265 # firstHeight = self.dataOut.heightList[minIndex]
266 266
267 267 self.dataOut.data = data
268 268 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
269 269
270 270 if self.dataOut.nHeights <= 1:
271 271 raise ValueError, "selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights)
272 272
273 273 return 1
274 274
275 275
276 276 def filterByHeights(self, window):
277 277
278 278 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
279 279
280 280 if window == None:
281 281 window = (self.dataOut.radarControllerHeaderObj.txA/self.dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
282 282
283 283 newdelta = deltaHeight * window
284 284 r = self.dataOut.nHeights % window
285 285 newheights = (self.dataOut.nHeights-r)/window
286 286
287 287 if newheights <= 1:
288 288 raise ValueError, "filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(self.dataOut.nHeights, window)
289 289
290 290 if self.dataOut.flagDataAsBlock:
291 291 """
292 292 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
293 293 """
294 294 buffer = self.dataOut.data[:, :, 0:self.dataOut.nHeights-r]
295 295 buffer = buffer.reshape(self.dataOut.nChannels,self.dataOut.nProfiles,self.dataOut.nHeights/window,window)
296 296 buffer = numpy.sum(buffer,3)
297 297
298 298 else:
299 299 buffer = self.dataOut.data[:,0:self.dataOut.nHeights-r]
300 300 buffer = buffer.reshape(self.dataOut.nChannels,self.dataOut.nHeights/window,window)
301 301 buffer = numpy.sum(buffer,2)
302 302
303 303 self.dataOut.data = buffer
304 304 self.dataOut.heightList = self.dataOut.heightList[0] + numpy.arange( newheights )*newdelta
305 305 self.dataOut.windowOfFilter = window
306 306
307 307 def setH0(self, h0, deltaHeight = None):
308 308
309 309 if not deltaHeight:
310 310 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
311 311
312 312 nHeights = self.dataOut.nHeights
313 313
314 314 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
315 315
316 316 self.dataOut.heightList = newHeiRange
317 317
318 318 def deFlip(self, channelList = []):
319 319
320 320 data = self.dataOut.data.copy()
321 321
322 322 if self.dataOut.flagDataAsBlock:
323 323 flip = self.flip
324 324 profileList = range(self.dataOut.nProfiles)
325 325
326 326 if not channelList:
327 327 for thisProfile in profileList:
328 328 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
329 329 flip *= -1.0
330 330 else:
331 331 for thisChannel in channelList:
332 332 if thisChannel not in self.dataOut.channelList:
333 333 continue
334 334
335 335 for thisProfile in profileList:
336 336 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
337 337 flip *= -1.0
338 338
339 339 self.flip = flip
340 340
341 341 else:
342 342 if not channelList:
343 343 data[:,:] = data[:,:]*self.flip
344 344 else:
345 345 for thisChannel in channelList:
346 346 if thisChannel not in self.dataOut.channelList:
347 347 continue
348 348
349 349 data[thisChannel,:] = data[thisChannel,:]*self.flip
350 350
351 351 self.flip *= -1.
352 352
353 353 self.dataOut.data = data
354 354
355 355 def setRadarFrequency(self, frequency=None):
356 356
357 357 if frequency != None:
358 358 self.dataOut.frequency = frequency
359 359
360 360 return 1
361 361
362 362 def interpolateHeights(self, topLim, botLim):
363 363 #69 al 72 para julia
364 364 #82-84 para meteoros
365 365 if len(numpy.shape(self.dataOut.data))==2:
366 366 sampInterp = (self.dataOut.data[:,botLim-1] + self.dataOut.data[:,topLim+1])/2
367 367 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
368 368 #self.dataOut.data[:,botLim:limSup+1] = sampInterp
369 369 self.dataOut.data[:,botLim:topLim+1] = sampInterp
370 370 else:
371 371 nHeights = self.dataOut.data.shape[2]
372 372 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
373 373 y = self.dataOut.data[:,:,range(botLim)+range(topLim+1,nHeights)]
374 374 f = interpolate.interp1d(x, y, axis = 2)
375 375 xnew = numpy.arange(botLim,topLim+1)
376 376 ynew = f(xnew)
377 377
378 378 self.dataOut.data[:,:,botLim:topLim+1] = ynew
379 379
380 380 # import collections
381 381
382 382 class CohInt(Operation):
383 383
384 384 isConfig = False
385 385 __profIndex = 0
386 386 __byTime = False
387 387 __initime = None
388 388 __lastdatatime = None
389 389 __integrationtime = None
390 390 __buffer = None
391 391 __bufferStride = []
392 392 __dataReady = False
393 393 __profIndexStride = 0
394 394 __dataToPutStride = False
395 395 n = None
396 396
397 397 def __init__(self, **kwargs):
398 398
399 399 Operation.__init__(self, **kwargs)
400 400
401 401 # self.isConfig = False
402 402
403 403 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
404 404 """
405 405 Set the parameters of the integration class.
406 406
407 407 Inputs:
408 408
409 409 n : Number of coherent integrations
410 410 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
411 411 overlapping :
412 412 """
413 413
414 414 self.__initime = None
415 415 self.__lastdatatime = 0
416 416 self.__buffer = None
417 417 self.__dataReady = False
418 418 self.byblock = byblock
419 419 self.stride = stride
420 420
421 421 if n == None and timeInterval == None:
422 422 raise ValueError, "n or timeInterval should be specified ..."
423 423
424 424 if n != None:
425 425 self.n = n
426 426 self.__byTime = False
427 427 else:
428 428 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
429 429 self.n = 9999
430 430 self.__byTime = True
431 431
432 432 if overlapping:
433 433 self.__withOverlapping = True
434 434 self.__buffer = None
435 435 else:
436 436 self.__withOverlapping = False
437 437 self.__buffer = 0
438 438
439 439 self.__profIndex = 0
440 440
441 441 def putData(self, data):
442 442
443 443 """
444 444 Add a profile to the __buffer and increase in one the __profileIndex
445 445
446 446 """
447 447
448 448 if not self.__withOverlapping:
449 449 self.__buffer += data.copy()
450 450 self.__profIndex += 1
451 451 return
452 452
453 453 #Overlapping data
454 454 nChannels, nHeis = data.shape
455 455 data = numpy.reshape(data, (1, nChannels, nHeis))
456 456
457 457 #If the buffer is empty then it takes the data value
458 458 if self.__buffer is None:
459 459 self.__buffer = data
460 460 self.__profIndex += 1
461 461 return
462 462
463 463 #If the buffer length is lower than n then stakcing the data value
464 464 if self.__profIndex < self.n:
465 465 self.__buffer = numpy.vstack((self.__buffer, data))
466 466 self.__profIndex += 1
467 467 return
468 468
469 469 #If the buffer length is equal to n then replacing the last buffer value with the data value
470 470 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
471 471 self.__buffer[self.n-1] = data
472 472 self.__profIndex = self.n
473 473 return
474 474
475 475
476 476 def pushData(self):
477 477 """
478 478 Return the sum of the last profiles and the profiles used in the sum.
479 479
480 480 Affected:
481 481
482 482 self.__profileIndex
483 483
484 484 """
485 485
486 486 if not self.__withOverlapping:
487 487 data = self.__buffer
488 488 n = self.__profIndex
489 489
490 490 self.__buffer = 0
491 491 self.__profIndex = 0
492 492
493 493 return data, n
494 494
495 495 #Integration with Overlapping
496 496 data = numpy.sum(self.__buffer, axis=0)
497 497 # print data
498 498 # raise
499 499 n = self.__profIndex
500 500
501 501 return data, n
502 502
503 503 def byProfiles(self, data):
504 504
505 505 self.__dataReady = False
506 506 avgdata = None
507 507 # n = None
508 508 # print data
509 509 # raise
510 510 self.putData(data)
511 511
512 512 if self.__profIndex == self.n:
513 513 avgdata, n = self.pushData()
514 514 self.__dataReady = True
515 515
516 516 return avgdata
517 517
518 518 def byTime(self, data, datatime):
519 519
520 520 self.__dataReady = False
521 521 avgdata = None
522 522 n = None
523 523
524 524 self.putData(data)
525 525
526 526 if (datatime - self.__initime) >= self.__integrationtime:
527 527 avgdata, n = self.pushData()
528 528 self.n = n
529 529 self.__dataReady = True
530 530
531 531 return avgdata
532 532
533 533 def integrateByStride(self, data, datatime):
534 534 # print data
535 535 if self.__profIndex == 0:
536 536 self.__buffer = [[data.copy(), datatime]]
537 537 else:
538 538 self.__buffer.append([data.copy(),datatime])
539 539 self.__profIndex += 1
540 540 self.__dataReady = False
541 541
542 542 if self.__profIndex == self.n * self.stride :
543 543 self.__dataToPutStride = True
544 544 self.__profIndexStride = 0
545 545 self.__profIndex = 0
546 546 self.__bufferStride = []
547 547 for i in range(self.stride):
548 548 current = self.__buffer[i::self.stride]
549 549 data = numpy.sum([t[0] for t in current], axis=0)
550 550 avgdatatime = numpy.average([t[1] for t in current])
551 551 # print data
552 552 self.__bufferStride.append((data, avgdatatime))
553 553
554 554 if self.__dataToPutStride:
555 555 self.__dataReady = True
556 556 self.__profIndexStride += 1
557 557 if self.__profIndexStride == self.stride:
558 558 self.__dataToPutStride = False
559 559 # print self.__bufferStride[self.__profIndexStride - 1]
560 560 # raise
561 561 return self.__bufferStride[self.__profIndexStride - 1]
562 562
563 563
564 564 return None, None
565 565
566 566 def integrate(self, data, datatime=None):
567 567
568 568 if self.__initime == None:
569 569 self.__initime = datatime
570 570
571 571 if self.__byTime:
572 572 avgdata = self.byTime(data, datatime)
573 573 else:
574 574 avgdata = self.byProfiles(data)
575 575
576 576
577 577 self.__lastdatatime = datatime
578 578
579 579 if avgdata is None:
580 580 return None, None
581 581
582 582 avgdatatime = self.__initime
583 583
584 584 deltatime = datatime - self.__lastdatatime
585 585
586 586 if not self.__withOverlapping:
587 587 self.__initime = datatime
588 588 else:
589 589 self.__initime += deltatime
590 590
591 591 return avgdata, avgdatatime
592 592
593 593 def integrateByBlock(self, dataOut):
594 594
595 595 times = int(dataOut.data.shape[1]/self.n)
596 596 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
597 597
598 598 id_min = 0
599 599 id_max = self.n
600 600
601 601 for i in range(times):
602 602 junk = dataOut.data[:,id_min:id_max,:]
603 603 avgdata[:,i,:] = junk.sum(axis=1)
604 604 id_min += self.n
605 605 id_max += self.n
606 606
607 607 timeInterval = dataOut.ippSeconds*self.n
608 608 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
609 609 self.__dataReady = True
610 610 return avgdata, avgdatatime
611 611
612 612 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
613 613 if not self.isConfig:
614 614 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
615 615 self.isConfig = True
616 616
617 617 if dataOut.flagDataAsBlock:
618 618 """
619 619 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
620 620 """
621 621 avgdata, avgdatatime = self.integrateByBlock(dataOut)
622 622 dataOut.nProfiles /= self.n
623 623 else:
624 624 if stride is None:
625 625 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
626 626 else:
627 627 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
628 628
629 629
630 630 # dataOut.timeInterval *= n
631 631 dataOut.flagNoData = True
632 632
633 633 if self.__dataReady:
634 634 dataOut.data = avgdata
635 635 dataOut.nCohInt *= self.n
636 636 dataOut.utctime = avgdatatime
637 637 # print avgdata, avgdatatime
638 638 # raise
639 639 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
640 640 dataOut.flagNoData = False
641 641
642 642 class Decoder(Operation):
643 643
644 644 isConfig = False
645 645 __profIndex = 0
646 646
647 647 code = None
648 648
649 649 nCode = None
650 650 nBaud = None
651 651
652 652 def __init__(self, **kwargs):
653 653
654 654 Operation.__init__(self, **kwargs)
655 655
656 656 self.times = None
657 657 self.osamp = None
658 658 # self.__setValues = False
659 659 self.isConfig = False
660 660
661 661 def setup(self, code, osamp, dataOut):
662 662
663 663 self.__profIndex = 0
664 664
665 665 self.code = code
666 666
667 667 self.nCode = len(code)
668 668 self.nBaud = len(code[0])
669 669
670 670 if (osamp != None) and (osamp >1):
671 671 self.osamp = osamp
672 672 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
673 673 self.nBaud = self.nBaud*self.osamp
674 674
675 675 self.__nChannels = dataOut.nChannels
676 676 self.__nProfiles = dataOut.nProfiles
677 677 self.__nHeis = dataOut.nHeights
678 678
679 679 if self.__nHeis < self.nBaud:
680 680 raise ValueError, 'Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud)
681 681
682 682 #Frequency
683 683 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
684 684
685 685 __codeBuffer[:,0:self.nBaud] = self.code
686 686
687 687 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
688 688
689 689 if dataOut.flagDataAsBlock:
690 690
691 691 self.ndatadec = self.__nHeis #- self.nBaud + 1
692 692
693 693 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
694 694
695 695 else:
696 696
697 697 #Time
698 698 self.ndatadec = self.__nHeis #- self.nBaud + 1
699 699
700 700 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
701 701
702 702 def __convolutionInFreq(self, data):
703 703
704 704 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
705 705
706 706 fft_data = numpy.fft.fft(data, axis=1)
707 707
708 708 conv = fft_data*fft_code
709 709
710 710 data = numpy.fft.ifft(conv,axis=1)
711 711
712 712 return data
713 713
714 714 def __convolutionInFreqOpt(self, data):
715 715
716 716 raise NotImplementedError
717 717
718 718 def __convolutionInTime(self, data):
719 719
720 720 code = self.code[self.__profIndex]
721 721 for i in range(self.__nChannels):
722 722 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
723 723
724 724 return self.datadecTime
725 725
726 726 def __convolutionByBlockInTime(self, data):
727 727
728 728 repetitions = self.__nProfiles / self.nCode
729 729
730 730 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
731 731 junk = junk.flatten()
732 732 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
733 733 profilesList = xrange(self.__nProfiles)
734 734
735 735 for i in range(self.__nChannels):
736 736 for j in profilesList:
737 737 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
738 738 return self.datadecTime
739 739
740 740 def __convolutionByBlockInFreq(self, data):
741 741
742 742 raise NotImplementedError, "Decoder by frequency fro Blocks not implemented"
743 743
744 744
745 745 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
746 746
747 747 fft_data = numpy.fft.fft(data, axis=2)
748 748
749 749 conv = fft_data*fft_code
750 750
751 751 data = numpy.fft.ifft(conv,axis=2)
752 752
753 753 return data
754 754
755 755
756 756 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
757 757
758 758 if dataOut.flagDecodeData:
759 759 print "This data is already decoded, recoding again ..."
760 760
761 761 if not self.isConfig:
762 762
763 763 if code is None:
764 764 if dataOut.code is None:
765 765 raise ValueError, "Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type
766 766
767 767 code = dataOut.code
768 768 else:
769 769 code = numpy.array(code).reshape(nCode,nBaud)
770 770 self.setup(code, osamp, dataOut)
771 771
772 772 self.isConfig = True
773 773
774 774 if mode == 3:
775 775 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
776 776
777 777 if times != None:
778 778 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
779 779
780 780 if self.code is None:
781 781 print "Fail decoding: Code is not defined."
782 782 return
783 783
784 784 self.__nProfiles = dataOut.nProfiles
785 785 datadec = None
786 786
787 787 if mode == 3:
788 788 mode = 0
789 789
790 790 if dataOut.flagDataAsBlock:
791 791 """
792 792 Decoding when data have been read as block,
793 793 """
794 794
795 795 if mode == 0:
796 796 datadec = self.__convolutionByBlockInTime(dataOut.data)
797 797 if mode == 1:
798 798 datadec = self.__convolutionByBlockInFreq(dataOut.data)
799 799 else:
800 800 """
801 801 Decoding when data have been read profile by profile
802 802 """
803 803 if mode == 0:
804 804 datadec = self.__convolutionInTime(dataOut.data)
805 805
806 806 if mode == 1:
807 807 datadec = self.__convolutionInFreq(dataOut.data)
808 808
809 809 if mode == 2:
810 810 datadec = self.__convolutionInFreqOpt(dataOut.data)
811 811
812 812 if datadec is None:
813 813 raise ValueError, "Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode
814 814
815 815 dataOut.code = self.code
816 816 dataOut.nCode = self.nCode
817 817 dataOut.nBaud = self.nBaud
818 818
819 819 dataOut.data = datadec
820 820
821 821 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
822 822
823 823 dataOut.flagDecodeData = True #asumo q la data esta decodificada
824 824
825 825 if self.__profIndex == self.nCode-1:
826 826 self.__profIndex = 0
827 827 return 1
828 828
829 829 self.__profIndex += 1
830 830
831 831 return 1
832 832 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
833 833
834 834
835 835 class ProfileConcat(Operation):
836 836
837 837 isConfig = False
838 838 buffer = None
839 concat_m =None
839 840
840 841 def __init__(self, **kwargs):
841 842
842 843 Operation.__init__(self, **kwargs)
843 844 self.profileIndex = 0
844 845
845 846 def reset(self):
846 847 self.buffer = numpy.zeros_like(self.buffer)
847 848 self.start_index = 0
848 849 self.times = 1
849 850
850 851 def setup(self, data, m, n=1):
851 852 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
852 853 self.nHeights = data.shape[1]#.nHeights
853 854 self.start_index = 0
854 855 self.times = 1
855 856
856 857 def concat(self, data):
857 858
858 859 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
859 860 self.start_index = self.start_index + self.nHeights
860 861
861 862 def run(self, dataOut, m):
862 863
864 self.concat_m= m
863 865 dataOut.flagNoData = True
864 866
865 867 if not self.isConfig:
866 868 self.setup(dataOut.data, m, 1)
867 869 self.isConfig = True
868 870
869 871 if dataOut.flagDataAsBlock:
870 872 raise ValueError, "ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False"
871 873
872 874 else:
873 875 self.concat(dataOut.data)
874 876 self.times += 1
875 877 if self.times > m:
876 878 dataOut.data = self.buffer
877 879 self.reset()
878 880 dataOut.flagNoData = False
879 881 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
880 882 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
881 883 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
882 884 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
883 885 dataOut.ippSeconds *= m
886 dataOut.concat_m = int(m)
884 887
885 888 class ProfileSelector(Operation):
886 889
887 890 profileIndex = None
888 891 # Tamanho total de los perfiles
889 892 nProfiles = None
890 893
891 894 def __init__(self, **kwargs):
892 895
893 896 Operation.__init__(self, **kwargs)
894 897 self.profileIndex = 0
895 898
896 899 def incProfileIndex(self):
897 900
898 901 self.profileIndex += 1
899 902
900 903 if self.profileIndex >= self.nProfiles:
901 904 self.profileIndex = 0
902 905
903 906 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
904 907
905 908 if profileIndex < minIndex:
906 909 return False
907 910
908 911 if profileIndex > maxIndex:
909 912 return False
910 913
911 914 return True
912 915
913 916 def isThisProfileInList(self, profileIndex, profileList):
914 917
915 918 if profileIndex not in profileList:
916 919 return False
917 920
918 921 return True
919 922
920 923 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
921 924
922 925 """
923 926 ProfileSelector:
924 927
925 928 Inputs:
926 929 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
927 930
928 931 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
929 932
930 933 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
931 934
932 935 """
933 936
934 937 if rangeList is not None:
935 938 if type(rangeList[0]) not in (tuple, list):
936 939 rangeList = [rangeList]
937 940
938 941 dataOut.flagNoData = True
939 942
940 943 if dataOut.flagDataAsBlock:
941 944 """
942 945 data dimension = [nChannels, nProfiles, nHeis]
943 946 """
944 947 if profileList != None:
945 948 dataOut.data = dataOut.data[:,profileList,:]
946 949
947 950 if profileRangeList != None:
948 951 minIndex = profileRangeList[0]
949 952 maxIndex = profileRangeList[1]
950 953 profileList = range(minIndex, maxIndex+1)
951 954
952 955 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
953 956
954 957 if rangeList != None:
955 958
956 959 profileList = []
957 960
958 961 for thisRange in rangeList:
959 962 minIndex = thisRange[0]
960 963 maxIndex = thisRange[1]
961 964
962 965 profileList.extend(range(minIndex, maxIndex+1))
963 966
964 967 dataOut.data = dataOut.data[:,profileList,:]
965 968
966 969 dataOut.nProfiles = len(profileList)
967 970 dataOut.profileIndex = dataOut.nProfiles - 1
968 971 dataOut.flagNoData = False
969 972
970 973 return True
971 974
972 975 """
973 976 data dimension = [nChannels, nHeis]
974 977 """
975 978
976 979 if profileList != None:
977 980
978 981 if self.isThisProfileInList(dataOut.profileIndex, profileList):
979 982
980 983 self.nProfiles = len(profileList)
981 984 dataOut.nProfiles = self.nProfiles
982 985 dataOut.profileIndex = self.profileIndex
983 986 dataOut.flagNoData = False
984 987
985 988 self.incProfileIndex()
986 989 return True
987 990
988 991 if profileRangeList != None:
989 992
990 993 minIndex = profileRangeList[0]
991 994 maxIndex = profileRangeList[1]
992 995
993 996 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
994 997
995 998 self.nProfiles = maxIndex - minIndex + 1
996 999 dataOut.nProfiles = self.nProfiles
997 1000 dataOut.profileIndex = self.profileIndex
998 1001 dataOut.flagNoData = False
999 1002
1000 1003 self.incProfileIndex()
1001 1004 return True
1002 1005
1003 1006 if rangeList != None:
1004 1007
1005 1008 nProfiles = 0
1006 1009
1007 1010 for thisRange in rangeList:
1008 1011 minIndex = thisRange[0]
1009 1012 maxIndex = thisRange[1]
1010 1013
1011 1014 nProfiles += maxIndex - minIndex + 1
1012 1015
1013 1016 for thisRange in rangeList:
1014 1017
1015 1018 minIndex = thisRange[0]
1016 1019 maxIndex = thisRange[1]
1017 1020
1018 1021 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1019 1022
1020 1023 self.nProfiles = nProfiles
1021 1024 dataOut.nProfiles = self.nProfiles
1022 1025 dataOut.profileIndex = self.profileIndex
1023 1026 dataOut.flagNoData = False
1024 1027
1025 1028 self.incProfileIndex()
1026 1029
1027 1030 break
1028 1031
1029 1032 return True
1030 1033
1031 1034
1032 1035 if beam != None: #beam is only for AMISR data
1033 1036 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
1034 1037 dataOut.flagNoData = False
1035 1038 dataOut.profileIndex = self.profileIndex
1036 1039
1037 1040 self.incProfileIndex()
1038 1041
1039 1042 return True
1040 1043
1041 1044 raise ValueError, "ProfileSelector needs profileList, profileRangeList or rangeList parameter"
1042 1045
1043 1046 return False
1044 1047
1045 1048 class Reshaper(Operation):
1046 1049
1047 1050 def __init__(self, **kwargs):
1048 1051
1049 1052 Operation.__init__(self, **kwargs)
1050 1053
1051 1054 self.__buffer = None
1052 1055 self.__nitems = 0
1053 1056
1054 1057 def __appendProfile(self, dataOut, nTxs):
1055 1058
1056 1059 if self.__buffer is None:
1057 1060 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
1058 1061 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
1059 1062
1060 1063 ini = dataOut.nHeights * self.__nitems
1061 1064 end = ini + dataOut.nHeights
1062 1065
1063 1066 self.__buffer[:, ini:end] = dataOut.data
1064 1067
1065 1068 self.__nitems += 1
1066 1069
1067 1070 return int(self.__nitems*nTxs)
1068 1071
1069 1072 def __getBuffer(self):
1070 1073
1071 1074 if self.__nitems == int(1./self.__nTxs):
1072 1075
1073 1076 self.__nitems = 0
1074 1077
1075 1078 return self.__buffer.copy()
1076 1079
1077 1080 return None
1078 1081
1079 1082 def __checkInputs(self, dataOut, shape, nTxs):
1080 1083
1081 1084 if shape is None and nTxs is None:
1082 1085 raise ValueError, "Reshaper: shape of factor should be defined"
1083 1086
1084 1087 if nTxs:
1085 1088 if nTxs < 0:
1086 1089 raise ValueError, "nTxs should be greater than 0"
1087 1090
1088 1091 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1089 1092 raise ValueError, "nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs))
1090 1093
1091 1094 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1092 1095
1093 1096 return shape, nTxs
1094 1097
1095 1098 if len(shape) != 2 and len(shape) != 3:
1096 1099 raise ValueError, "shape dimension should be equal to 2 or 3. shape = (nProfiles, nHeis) or (nChannels, nProfiles, nHeis). Actually shape = (%d, %d, %d)" %(dataOut.nChannels, dataOut.nProfiles, dataOut.nHeights)
1097 1100
1098 1101 if len(shape) == 2:
1099 1102 shape_tuple = [dataOut.nChannels]
1100 1103 shape_tuple.extend(shape)
1101 1104 else:
1102 1105 shape_tuple = list(shape)
1103 1106
1104 1107 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1105 1108
1106 1109 return shape_tuple, nTxs
1107 1110
1108 1111 def run(self, dataOut, shape=None, nTxs=None):
1109 1112
1110 1113 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1111 1114
1112 1115 dataOut.flagNoData = True
1113 1116 profileIndex = None
1114 1117
1115 1118 if dataOut.flagDataAsBlock:
1116 1119
1117 1120 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1118 1121 dataOut.flagNoData = False
1119 1122
1120 1123 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1121 1124
1122 1125 else:
1123 1126
1124 1127 if self.__nTxs < 1:
1125 1128
1126 1129 self.__appendProfile(dataOut, self.__nTxs)
1127 1130 new_data = self.__getBuffer()
1128 1131
1129 1132 if new_data is not None:
1130 1133 dataOut.data = new_data
1131 1134 dataOut.flagNoData = False
1132 1135
1133 1136 profileIndex = dataOut.profileIndex*nTxs
1134 1137
1135 1138 else:
1136 1139 raise ValueError, "nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)"
1137 1140
1138 1141 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1139 1142
1140 1143 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1141 1144
1142 1145 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1143 1146
1144 1147 dataOut.profileIndex = profileIndex
1145 1148
1146 1149 dataOut.ippSeconds /= self.__nTxs
1147 1150
1148 1151 class SplitProfiles(Operation):
1149 1152
1150 1153 def __init__(self, **kwargs):
1151 1154
1152 1155 Operation.__init__(self, **kwargs)
1153 1156
1154 1157 def run(self, dataOut, n):
1155 1158
1156 1159 dataOut.flagNoData = True
1157 1160 profileIndex = None
1158 1161
1159 1162 if dataOut.flagDataAsBlock:
1160 1163
1161 1164 #nchannels, nprofiles, nsamples
1162 1165 shape = dataOut.data.shape
1163 1166
1164 1167 if shape[2] % n != 0:
1165 1168 raise ValueError, "Could not split the data, n=%d has to be multiple of %d" %(n, shape[2])
1166 1169
1167 1170 new_shape = shape[0], shape[1]*n, shape[2]/n
1168 1171
1169 1172 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1170 1173 dataOut.flagNoData = False
1171 1174
1172 1175 profileIndex = int(dataOut.nProfiles/n) - 1
1173 1176
1174 1177 else:
1175 1178
1176 1179 raise ValueError, "Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)"
1177 1180
1178 1181 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1179 1182
1180 1183 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1181 1184
1182 1185 dataOut.nProfiles = int(dataOut.nProfiles*n)
1183 1186
1184 1187 dataOut.profileIndex = profileIndex
1185 1188
1186 1189 dataOut.ippSeconds /= n
1187 1190
1188 1191 class CombineProfiles(Operation):
1189 1192
1190 1193 def __init__(self, **kwargs):
1191 1194
1192 1195 Operation.__init__(self, **kwargs)
1193 1196
1194 1197 self.__remData = None
1195 1198 self.__profileIndex = 0
1196 1199
1197 1200 def run(self, dataOut, n):
1198 1201
1199 1202 dataOut.flagNoData = True
1200 1203 profileIndex = None
1201 1204
1202 1205 if dataOut.flagDataAsBlock:
1203 1206
1204 1207 #nchannels, nprofiles, nsamples
1205 1208 shape = dataOut.data.shape
1206 1209 new_shape = shape[0], shape[1]/n, shape[2]*n
1207 1210
1208 1211 if shape[1] % n != 0:
1209 1212 raise ValueError, "Could not split the data, n=%d has to be multiple of %d" %(n, shape[1])
1210 1213
1211 1214 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1212 1215 dataOut.flagNoData = False
1213 1216
1214 1217 profileIndex = int(dataOut.nProfiles*n) - 1
1215 1218
1216 1219 else:
1217 1220
1218 1221 #nchannels, nsamples
1219 1222 if self.__remData is None:
1220 1223 newData = dataOut.data
1221 1224 else:
1222 1225 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1223 1226
1224 1227 self.__profileIndex += 1
1225 1228
1226 1229 if self.__profileIndex < n:
1227 1230 self.__remData = newData
1228 1231 #continue
1229 1232 return
1230 1233
1231 1234 self.__profileIndex = 0
1232 1235 self.__remData = None
1233 1236
1234 1237 dataOut.data = newData
1235 1238 dataOut.flagNoData = False
1236 1239
1237 1240 profileIndex = dataOut.profileIndex/n
1238 1241
1239 1242
1240 1243 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1241 1244
1242 1245 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1243 1246
1244 1247 dataOut.nProfiles = int(dataOut.nProfiles/n)
1245 1248
1246 1249 dataOut.profileIndex = profileIndex
1247 1250
1248 1251 dataOut.ippSeconds *= n
1249 1252
1250 1253
1251 1254 class SSheightProfiles(Operation):
1252 1255
1253 1256 step = None
1254 1257 nsamples = None
1255 1258 bufferShape = None
1256 1259 profileShape = None
1257 1260 sshProfiles = None
1258 1261 profileIndex = None
1259 1262
1260 1263 def __init__(self, **kwargs):
1261 1264
1262 1265 Operation.__init__(self, **kwargs)
1263 1266 self.isConfig = False
1264 1267
1265 1268 def setup(self,dataOut ,step = None , nsamples = None):
1266 1269
1267 1270 if step == None and nsamples == None:
1268 1271 raise ValueError, "step or nheights should be specified ..."
1269 1272
1270 1273 self.step = step
1271 1274 self.nsamples = nsamples
1272 1275 self.__nChannels = dataOut.nChannels
1273 1276 self.__nProfiles = dataOut.nProfiles
1274 1277 self.__nHeis = dataOut.nHeights
1275 1278 shape = dataOut.data.shape #nchannels, nprofiles, nsamples
1276 1279
1277 1280
1278 1281 residue = (shape[1] - self.nsamples) % self.step
1279 1282 if residue != 0:
1280 1283 print "The residue is %d, step=%d should be multiple of %d to avoid loss of %d samples"%(residue,step,shape[1] - self.nsamples,residue)
1281 1284
1282 1285 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1283 1286 numberProfile = self.nsamples
1284 1287 numberSamples = (shape[1] - self.nsamples)/self.step
1285 1288
1286 1289 print "New number of profile: %d, number of height: %d, Resolution %d Km"%(numberProfile,numberSamples,deltaHeight*self.step)
1287 1290
1288 1291 self.bufferShape = shape[0], numberSamples, numberProfile # nchannels, nsamples , nprofiles
1289 1292 self.profileShape = shape[0], numberProfile, numberSamples # nchannels, nprofiles, nsamples
1290 1293
1291 1294 self.buffer = numpy.zeros(self.bufferShape , dtype=numpy.complex)
1292 1295 self.sshProfiles = numpy.zeros(self.profileShape, dtype=numpy.complex)
1293 1296
1294 1297 def run(self, dataOut, step, nsamples):
1295 1298
1296 1299 dataOut.flagNoData = True
1297 1300 dataOut.flagDataAsBlock = False
1298 1301 profileIndex = None
1299 1302
1303
1300 1304 if not self.isConfig:
1301 1305 self.setup(dataOut, step=step , nsamples=nsamples)
1302 1306 self.isConfig = True
1303 1307
1304 1308 for i in range(self.buffer.shape[1]):
1305 1309 self.buffer[:,i] = numpy.flip(dataOut.data[:,i*self.step:i*self.step + self.nsamples])
1306 1310 #self.buffer[:,j,self.__nHeis-j*self.step - self.nheights:self.__nHeis-j*self.step] = numpy.flip(dataOut.data[:,j*self.step:j*self.step + self.nheights])
1307 1311
1308 1312 for j in range(self.buffer.shape[0]):
1309 1313 self.sshProfiles[j] = numpy.transpose(self.buffer[j])
1310 1314
1311 1315 profileIndex = self.nsamples
1312 1316 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1313 1317 ippSeconds = (deltaHeight*1.0e-6)/(0.15)
1318 try:
1319 if dataOut.concat_m is not None:
1320 ippSeconds= ippSeconds/float(dataOut.concat_m)
1321 #print "Profile concat %d"%dataOut.concat_m
1322 except:
1323 pass
1314 1324
1315 1325 dataOut.data = self.sshProfiles
1316 1326 dataOut.flagNoData = False
1317 1327 dataOut.heightList = numpy.arange(self.buffer.shape[1]) *self.step*deltaHeight + dataOut.heightList[0]
1318 1328 dataOut.nProfiles = int(dataOut.nProfiles*self.nsamples)
1319 1329 dataOut.profileIndex = profileIndex
1320 1330 dataOut.flagDataAsBlock = True
1321 1331 dataOut.ippSeconds = ippSeconds
1322 1332 dataOut.step = self.step
1323 1333
1324 1334
1325 1335 import time
1326 1336 #################################################
1327 1337
1328 1338 class decoPseudorandom(Operation):
1329 1339
1330 1340 nProfiles= 0
1331 1341 buffer= None
1332 1342 isConfig = False
1333 1343
1334 1344 def setup(self, clen= 10000,seed= 0,Nranges= 1000,oversample=1):
1335 1345 #code = create_pseudo_random_code(clen=clen, seed=seed)
1336 1346 code= rep_seq(create_pseudo_random_code(clen=clen, seed=seed),rep=oversample)
1337 1347 #print ("code_rx", code.shape)
1338 1348 #N = int(an_len/clen) # 100
1339 1349 B_cache = 0
1340 1350 r_cache = 0
1341 1351 B_cached = False
1342 1352 r = create_estimation_matrix(code=code, cache=True, rmax=Nranges)
1343 1353 #print ("code shape", code.shape)
1344 1354 #print ("seed",seed)
1345 1355 #print ("Code", code[0:10])
1346 1356 self.B = r['B']
1347 1357
1348 1358
1349 1359 def run (self,dataOut,length_code= 10000,seed= 0,Nranges= 1000,oversample=1):
1350 1360 #print((dataOut.data.shape))
1351 1361 if not self.isConfig:
1352 1362 self.setup(clen= length_code,seed= seed,Nranges= Nranges,oversample=oversample)
1353 1363 self.isConfig = True
1354 1364
1355 1365 dataOut.flagNoData = True
1356 1366 data =dataOut.data
1357 1367 #print "length_CODE",length_code
1358 1368 data_shape = (data.shape[1])
1359 1369 #print "data_shape",data_shape
1360 1370 n = (length_code /data_shape)
1361 1371 #print "we need this number of sample",n
1362 1372
1363 1373 if n>0 and self.buffer is None:
1364 1374 self.buffer = numpy.zeros([1, length_code], dtype=numpy.complex64)
1365 1375 self.buffer[0][0:data_shape] = data[0]
1366 1376 #print "FIRST CREATION",self.buffer.shape
1367 1377
1368 1378 else:
1369 1379 self.buffer[0][self.nProfiles*data_shape:(self.nProfiles+1)*data_shape]=data[0]
1370 1380
1371 1381 #print "buffer_shape",(self.buffer.shape)
1372 1382 self.nProfiles += 1
1373 1383 #print "count",self.nProfiles
1374 1384
1375 1385 if self.nProfiles== n:
1376 1386 temporal = numpy.dot(self.B, numpy.transpose(self.buffer))
1377 1387 #print temporal.shape
1378 1388 #import time
1379 1389 #time.sleep(40)
1380 1390 dataOut.data=numpy.transpose(temporal)
1381 1391
1382 1392 dataOut.flagNoData = False
1383 1393 self.buffer= None
1384 1394 self.nProfiles = 0
1385 1395
1386 1396 # import collections
1387 1397 # from scipy.stats import mode
1388 1398 #
1389 1399 # class Synchronize(Operation):
1390 1400 #
1391 1401 # isConfig = False
1392 1402 # __profIndex = 0
1393 1403 #
1394 1404 # def __init__(self, **kwargs):
1395 1405 #
1396 1406 # Operation.__init__(self, **kwargs)
1397 1407 # # self.isConfig = False
1398 1408 # self.__powBuffer = None
1399 1409 # self.__startIndex = 0
1400 1410 # self.__pulseFound = False
1401 1411 #
1402 1412 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1403 1413 #
1404 1414 # #Read data
1405 1415 #
1406 1416 # powerdB = dataOut.getPower(channel = channel)
1407 1417 # noisedB = dataOut.getNoise(channel = channel)[0]
1408 1418 #
1409 1419 # self.__powBuffer.extend(powerdB.flatten())
1410 1420 #
1411 1421 # dataArray = numpy.array(self.__powBuffer)
1412 1422 #
1413 1423 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1414 1424 #
1415 1425 # maxValue = numpy.nanmax(filteredPower)
1416 1426 #
1417 1427 # if maxValue < noisedB + 10:
1418 1428 # #No se encuentra ningun pulso de transmision
1419 1429 # return None
1420 1430 #
1421 1431 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1422 1432 #
1423 1433 # if len(maxValuesIndex) < 2:
1424 1434 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1425 1435 # return None
1426 1436 #
1427 1437 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1428 1438 #
1429 1439 # #Seleccionar solo valores con un espaciamiento de nSamples
1430 1440 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1431 1441 #
1432 1442 # if len(pulseIndex) < 2:
1433 1443 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1434 1444 # return None
1435 1445 #
1436 1446 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1437 1447 #
1438 1448 # #remover senales que se distancien menos de 10 unidades o muestras
1439 1449 # #(No deberian existir IPP menor a 10 unidades)
1440 1450 #
1441 1451 # realIndex = numpy.where(spacing > 10 )[0]
1442 1452 #
1443 1453 # if len(realIndex) < 2:
1444 1454 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1445 1455 # return None
1446 1456 #
1447 1457 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1448 1458 # realPulseIndex = pulseIndex[realIndex]
1449 1459 #
1450 1460 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1451 1461 #
1452 1462 # print "IPP = %d samples" %period
1453 1463 #
1454 1464 # self.__newNSamples = dataOut.nHeights #int(period)
1455 1465 # self.__startIndex = int(realPulseIndex[0])
1456 1466 #
1457 1467 # return 1
1458 1468 #
1459 1469 #
1460 1470 # def setup(self, nSamples, nChannels, buffer_size = 4):
1461 1471 #
1462 1472 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1463 1473 # maxlen = buffer_size*nSamples)
1464 1474 #
1465 1475 # bufferList = []
1466 1476 #
1467 1477 # for i in range(nChannels):
1468 1478 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1469 1479 # maxlen = buffer_size*nSamples)
1470 1480 #
1471 1481 # bufferList.append(bufferByChannel)
1472 1482 #
1473 1483 # self.__nSamples = nSamples
1474 1484 # self.__nChannels = nChannels
1475 1485 # self.__bufferList = bufferList
1476 1486 #
1477 1487 # def run(self, dataOut, channel = 0):
1478 1488 #
1479 1489 # if not self.isConfig:
1480 1490 # nSamples = dataOut.nHeights
1481 1491 # nChannels = dataOut.nChannels
1482 1492 # self.setup(nSamples, nChannels)
1483 1493 # self.isConfig = True
1484 1494 #
1485 1495 # #Append new data to internal buffer
1486 1496 # for thisChannel in range(self.__nChannels):
1487 1497 # bufferByChannel = self.__bufferList[thisChannel]
1488 1498 # bufferByChannel.extend(dataOut.data[thisChannel])
1489 1499 #
1490 1500 # if self.__pulseFound:
1491 1501 # self.__startIndex -= self.__nSamples
1492 1502 #
1493 1503 # #Finding Tx Pulse
1494 1504 # if not self.__pulseFound:
1495 1505 # indexFound = self.__findTxPulse(dataOut, channel)
1496 1506 #
1497 1507 # if indexFound == None:
1498 1508 # dataOut.flagNoData = True
1499 1509 # return
1500 1510 #
1501 1511 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1502 1512 # self.__pulseFound = True
1503 1513 # self.__startIndex = indexFound
1504 1514 #
1505 1515 # #If pulse was found ...
1506 1516 # for thisChannel in range(self.__nChannels):
1507 1517 # bufferByChannel = self.__bufferList[thisChannel]
1508 1518 # #print self.__startIndex
1509 1519 # x = numpy.array(bufferByChannel)
1510 1520 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1511 1521 #
1512 1522 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1513 1523 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1514 1524 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1515 1525 #
1516 1526 # dataOut.data = self.__arrayBuffer
1517 1527 #
1518 1528 # self.__startIndex += self.__newNSamples
1519 1529 #
1520 1530 # return
General Comments 0
You need to be logged in to leave comments. Login now