##// END OF EJS Templates
Adicion del metodo filterByHeights en la clase VoltageProc....
Daniel Valdez -
r223:413a7765ec9f
parent child
Show More
@@ -1,975 +1,1145
1 1 '''
2 2
3 3 $Author: dsuarez $
4 4 $Id: Processor.py 1 2012-11-12 18:56:07Z dsuarez $
5 5 '''
6 6 import os
7 7 import numpy
8 8 import datetime
9 9 import time
10 10
11 11 from jrodata import *
12 12 from jrodataIO import *
13 13 from jroplot import *
14 14
15 15 class ProcessingUnit:
16 16
17 17 """
18 18 Esta es la clase base para el procesamiento de datos.
19 19
20 20 Contiene el metodo "call" para llamar operaciones. Las operaciones pueden ser:
21 21 - Metodos internos (callMethod)
22 22 - Objetos del tipo Operation (callObject). Antes de ser llamados, estos objetos
23 23 tienen que ser agreagados con el metodo "add".
24 24
25 25 """
26 26 # objeto de datos de entrada (Voltage, Spectra o Correlation)
27 27 dataIn = None
28 28
29 29 # objeto de datos de entrada (Voltage, Spectra o Correlation)
30 30 dataOut = None
31 31
32 32
33 33 objectDict = None
34 34
35 35 def __init__(self):
36 36
37 37 self.objectDict = {}
38 38
39 39 def init(self):
40 40
41 41 raise ValueError, "Not implemented"
42 42
43 43 def addOperation(self, object, objId):
44 44
45 45 """
46 46 Agrega el objeto "object" a la lista de objetos "self.objectList" y retorna el
47 47 identificador asociado a este objeto.
48 48
49 49 Input:
50 50
51 51 object : objeto de la clase "Operation"
52 52
53 53 Return:
54 54
55 55 objId : identificador del objeto, necesario para ejecutar la operacion
56 56 """
57 57
58 58 self.objectDict[objId] = object
59 59
60 60 return objId
61 61
62 62 def operation(self, **kwargs):
63 63
64 64 """
65 65 Operacion directa sobre la data (dataout.data). Es necesario actualizar los valores de los
66 66 atributos del objeto dataOut
67 67
68 68 Input:
69 69
70 70 **kwargs : Diccionario de argumentos de la funcion a ejecutar
71 71 """
72 72
73 73 raise ValueError, "ImplementedError"
74 74
75 75 def callMethod(self, name, **kwargs):
76 76
77 77 """
78 78 Ejecuta el metodo con el nombre "name" y con argumentos **kwargs de la propia clase.
79 79
80 80 Input:
81 81 name : nombre del metodo a ejecutar
82 82
83 83 **kwargs : diccionario con los nombres y valores de la funcion a ejecutar.
84 84
85 85 """
86 86 if name != 'run':
87 87
88 88 if name == 'init' and self.dataIn.isEmpty():
89 89 self.dataOut.flagNoData = True
90 90 return False
91 91
92 92 if name != 'init' and self.dataOut.isEmpty():
93 93 return False
94 94
95 95 methodToCall = getattr(self, name)
96 96
97 97 methodToCall(**kwargs)
98 98
99 99 if name != 'run':
100 100 return True
101 101
102 102 if self.dataOut.isEmpty():
103 103 return False
104 104
105 105 return True
106 106
107 107 def callObject(self, objId, **kwargs):
108 108
109 109 """
110 110 Ejecuta la operacion asociada al identificador del objeto "objId"
111 111
112 112 Input:
113 113
114 114 objId : identificador del objeto a ejecutar
115 115
116 116 **kwargs : diccionario con los nombres y valores de la funcion a ejecutar.
117 117
118 118 Return:
119 119
120 120 None
121 121 """
122 122
123 123 if self.dataOut.isEmpty():
124 124 return False
125 125
126 126 object = self.objectDict[objId]
127 127
128 128 object.run(self.dataOut, **kwargs)
129 129
130 130 return True
131 131
132 132 def call(self, operationConf, **kwargs):
133 133
134 134 """
135 135 Return True si ejecuta la operacion "operationConf.name" con los
136 136 argumentos "**kwargs". False si la operacion no se ha ejecutado.
137 137 La operacion puede ser de dos tipos:
138 138
139 139 1. Un metodo propio de esta clase:
140 140
141 141 operation.type = "self"
142 142
143 143 2. El metodo "run" de un objeto del tipo Operation o de un derivado de ella:
144 144 operation.type = "other".
145 145
146 146 Este objeto de tipo Operation debe de haber sido agregado antes con el metodo:
147 147 "addOperation" e identificado con el operation.id
148 148
149 149
150 150 con el id de la operacion.
151 151
152 152 Input:
153 153
154 154 Operation : Objeto del tipo operacion con los atributos: name, type y id.
155 155
156 156 """
157 157
158 158 if operationConf.type == 'self':
159 159 sts = self.callMethod(operationConf.name, **kwargs)
160 160
161 161 if operationConf.type == 'other':
162 162 sts = self.callObject(operationConf.id, **kwargs)
163 163
164 164 return sts
165 165
166 166 def setInput(self, dataIn):
167 167
168 168 self.dataIn = dataIn
169 169
170 170 def getOutput(self):
171 171
172 172 return self.dataOut
173 173
174 174 class Operation():
175 175
176 176 """
177 177 Clase base para definir las operaciones adicionales que se pueden agregar a la clase ProcessingUnit
178 178 y necesiten acumular informacion previa de los datos a procesar. De preferencia usar un buffer de
179 179 acumulacion dentro de esta clase
180 180
181 181 Ejemplo: Integraciones coherentes, necesita la informacion previa de los n perfiles anteriores (bufffer)
182 182
183 183 """
184 184
185 185 __buffer = None
186 186 __isConfig = False
187 187
188 188 def __init__(self):
189 189
190 190 pass
191 191
192 192 def run(self, dataIn, **kwargs):
193 193
194 194 """
195 195 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los atributos del objeto dataIn.
196 196
197 197 Input:
198 198
199 199 dataIn : objeto del tipo JROData
200 200
201 201 Return:
202 202
203 203 None
204 204
205 205 Affected:
206 206 __buffer : buffer de recepcion de datos.
207 207
208 208 """
209 209
210 210 raise ValueError, "ImplementedError"
211 211
212 212 class VoltageProc(ProcessingUnit):
213 213
214 214
215 215 def __init__(self):
216 216
217 217 self.objectDict = {}
218 218 self.dataOut = Voltage()
219 219
220 220 def init(self):
221 221
222 222 self.dataOut.copy(self.dataIn)
223 223 # No necesita copiar en cada init() los atributos de dataIn
224 224 # la copia deberia hacerse por cada nuevo bloque de datos
225 225
226 226 def selectChannels(self, channelList):
227 227
228 228 channelIndexList = []
229 229
230 230 for channel in channelList:
231 231 index = self.dataOut.channelList.index(channel)
232 232 channelIndexList.append(index)
233 233
234 234 self.selectChannelsByIndex(channelIndexList)
235 235
236 236 def selectChannelsByIndex(self, channelIndexList):
237 237 """
238 238 Selecciona un bloque de datos en base a canales segun el channelIndexList
239 239
240 240 Input:
241 241 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
242 242
243 243 Affected:
244 244 self.dataOut.data
245 245 self.dataOut.channelIndexList
246 246 self.dataOut.nChannels
247 247 self.dataOut.m_ProcessingHeader.totalSpectra
248 248 self.dataOut.systemHeaderObj.numChannels
249 249 self.dataOut.m_ProcessingHeader.blockSize
250 250
251 251 Return:
252 252 None
253 253 """
254 254
255 255 for channelIndex in channelIndexList:
256 256 if channelIndex not in self.dataOut.channelIndexList:
257 257 print channelIndexList
258 258 raise ValueError, "The value %d in channelIndexList is not valid" %channelIndex
259 259
260 260 nChannels = len(channelIndexList)
261 261
262 262 data = self.dataOut.data[channelIndexList,:]
263 263
264 264 self.dataOut.data = data
265 265 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
266 266 # self.dataOut.nChannels = nChannels
267 267
268 268 return 1
269 269
270 270 def selectHeights(self, minHei, maxHei):
271 271 """
272 272 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
273 273 minHei <= height <= maxHei
274 274
275 275 Input:
276 276 minHei : valor minimo de altura a considerar
277 277 maxHei : valor maximo de altura a considerar
278 278
279 279 Affected:
280 280 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
281 281
282 282 Return:
283 283 1 si el metodo se ejecuto con exito caso contrario devuelve 0
284 284 """
285 285 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
286 286 raise ValueError, "some value in (%d,%d) is not valid" % (minHei, maxHei)
287 287
288 288 if (maxHei > self.dataOut.heightList[-1]):
289 289 maxHei = self.dataOut.heightList[-1]
290 290 # raise ValueError, "some value in (%d,%d) is not valid" % (minHei, maxHei)
291 291
292 292 minIndex = 0
293 293 maxIndex = 0
294 294 data = self.dataOut.heightList
295 295
296 296 for i,val in enumerate(data):
297 297 if val < minHei:
298 298 continue
299 299 else:
300 300 minIndex = i;
301 301 break
302 302
303 303 for i,val in enumerate(data):
304 304 if val <= maxHei:
305 305 maxIndex = i;
306 306 else:
307 307 break
308 308
309 309 self.selectHeightsByIndex(minIndex, maxIndex)
310 310
311 311 return 1
312 312
313 313
314 314 def selectHeightsByIndex(self, minIndex, maxIndex):
315 315 """
316 316 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
317 317 minIndex <= index <= maxIndex
318 318
319 319 Input:
320 320 minIndex : valor de indice minimo de altura a considerar
321 321 maxIndex : valor de indice maximo de altura a considerar
322 322
323 323 Affected:
324 324 self.dataOut.data
325 325 self.dataOut.heightList
326 326
327 327 Return:
328 328 1 si el metodo se ejecuto con exito caso contrario devuelve 0
329 329 """
330 330
331 331 if (minIndex < 0) or (minIndex > maxIndex):
332 332 raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex)
333 333
334 334 if (maxIndex >= self.dataOut.nHeights):
335 335 maxIndex = self.dataOut.nHeights-1
336 336 # raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex)
337 337
338 338 nHeights = maxIndex - minIndex + 1
339 339
340 340 #voltage
341 341 data = self.dataOut.data[:,minIndex:maxIndex+1]
342 342
343 343 firstHeight = self.dataOut.heightList[minIndex]
344 344
345 345 self.dataOut.data = data
346 346 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex+1]
347 347
348 348 return 1
349 349
350
351 def filterByHeights(self, window):
352 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
353
354 if window == None:
355 window = self.dataOut.radarControllerHeaderObj.txA / deltaHeight
356
357 newdelta = deltaHeight * window
358 r = self.dataOut.data.shape[1] % window
359 buffer = self.dataOut.data[:,0:self.dataOut.data.shape[1]-r]
360 buffer = buffer.reshape(self.dataOut.data.shape[0],self.dataOut.data.shape[1]/window,window)
361 buffer = numpy.sum(buffer,2)
362 self.dataOut.data = buffer
363 self.dataOut.heightList = numpy.arange(self.dataOut.heightList[0],newdelta*self.dataOut.nHeights/window,newdelta)
364
350 365
351 366 class CohInt(Operation):
352 367
353 368 __profIndex = 0
354 369 __withOverapping = False
355 370
356 371 __byTime = False
357 372 __initime = None
358 373 __lastdatatime = None
359 374 __integrationtime = None
360 375
361 376 __buffer = None
362 377
363 378 __dataReady = False
364 379
365 380 n = None
366 381
367 382
368 383 def __init__(self):
369 384
370 385 self.__isConfig = False
371 386
372 387 def setup(self, n=None, timeInterval=None, overlapping=False):
373 388 """
374 389 Set the parameters of the integration class.
375 390
376 391 Inputs:
377 392
378 393 n : Number of coherent integrations
379 394 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
380 395 overlapping :
381 396
382 397 """
383 398
384 399 self.__initime = None
385 400 self.__lastdatatime = 0
386 401 self.__buffer = None
387 402 self.__dataReady = False
388 403
389 404
390 405 if n == None and timeInterval == None:
391 406 raise ValueError, "n or timeInterval should be specified ..."
392 407
393 408 if n != None:
394 409 self.n = n
395 410 self.__byTime = False
396 411 else:
397 412 self.__integrationtime = timeInterval * 60. #if (type(timeInterval)!=integer) -> change this line
398 413 self.n = 9999
399 414 self.__byTime = True
400 415
401 416 if overlapping:
402 417 self.__withOverapping = True
403 418 self.__buffer = None
404 419 else:
405 420 self.__withOverapping = False
406 421 self.__buffer = 0
407 422
408 423 self.__profIndex = 0
409 424
410 425 def putData(self, data):
411 426
412 427 """
413 428 Add a profile to the __buffer and increase in one the __profileIndex
414 429
415 430 """
416 431
417 432 if not self.__withOverapping:
418 433 self.__buffer += data.copy()
419 434 self.__profIndex += 1
420 435 return
421 436
422 437 #Overlapping data
423 438 nChannels, nHeis = data.shape
424 439 data = numpy.reshape(data, (1, nChannels, nHeis))
425 440
426 441 #If the buffer is empty then it takes the data value
427 442 if self.__buffer == None:
428 443 self.__buffer = data
429 444 self.__profIndex += 1
430 445 return
431 446
432 447 #If the buffer length is lower than n then stakcing the data value
433 448 if self.__profIndex < self.n:
434 449 self.__buffer = numpy.vstack((self.__buffer, data))
435 450 self.__profIndex += 1
436 451 return
437 452
438 453 #If the buffer length is equal to n then replacing the last buffer value with the data value
439 454 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
440 455 self.__buffer[self.n-1] = data
441 456 self.__profIndex = self.n
442 457 return
443 458
444 459
445 460 def pushData(self):
446 461 """
447 462 Return the sum of the last profiles and the profiles used in the sum.
448 463
449 464 Affected:
450 465
451 466 self.__profileIndex
452 467
453 468 """
454 469
455 470 if not self.__withOverapping:
456 471 data = self.__buffer
457 472 n = self.__profIndex
458 473
459 474 self.__buffer = 0
460 475 self.__profIndex = 0
461 476
462 477 return data, n
463 478
464 479 #Integration with Overlapping
465 480 data = numpy.sum(self.__buffer, axis=0)
466 481 n = self.__profIndex
467 482
468 483 return data, n
469 484
470 485 def byProfiles(self, data):
471 486
472 487 self.__dataReady = False
473 488 avgdata = None
474 489 n = None
475 490
476 491 self.putData(data)
477 492
478 493 if self.__profIndex == self.n:
479 494
480 495 avgdata, n = self.pushData()
481 496 self.__dataReady = True
482 497
483 498 return avgdata
484 499
485 500 def byTime(self, data, datatime):
486 501
487 502 self.__dataReady = False
488 503 avgdata = None
489 504 n = None
490 505
491 506 self.putData(data)
492 507
493 508 if (datatime - self.__initime) >= self.__integrationtime:
494 509 avgdata, n = self.pushData()
495 510 self.n = n
496 511 self.__dataReady = True
497 512
498 513 return avgdata
499 514
500 515 def integrate(self, data, datatime=None):
501 516
502 517 if self.__initime == None:
503 518 self.__initime = datatime
504 519
505 520 if self.__byTime:
506 521 avgdata = self.byTime(data, datatime)
507 522 else:
508 523 avgdata = self.byProfiles(data)
509 524
510 525
511 526 self.__lastdatatime = datatime
512 527
513 528 if avgdata == None:
514 529 return None, None
515 530
516 531 avgdatatime = self.__initime
517 532
518 533 deltatime = datatime -self.__lastdatatime
519 534
520 535 if not self.__withOverapping:
521 536 self.__initime = datatime
522 537 else:
523 538 self.__initime += deltatime
524 539
525 540 return avgdata, avgdatatime
526 541
527 542 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
528 543
529 544 if not self.__isConfig:
530 545 self.setup(n, timeInterval, overlapping)
531 546 self.__isConfig = True
532 547
533 548 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
534 549
535 550 # dataOut.timeInterval *= n
536 551 dataOut.flagNoData = True
537 552
538 553 if self.__dataReady:
539 554 dataOut.data = avgdata
540 555 dataOut.nCohInt *= self.n
541 556 dataOut.utctime = avgdatatime
542 557 dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
543 558 dataOut.flagNoData = False
544 559
545 560
546 561 class SpectraProc(ProcessingUnit):
547 562
548 563 def __init__(self):
549 564
550 565 self.objectDict = {}
551 566 self.buffer = None
552 567 self.firstdatatime = None
553 568 self.profIndex = 0
554 569 self.dataOut = Spectra()
555 570
556 571 def __updateObjFromInput(self):
557 572
558 573 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
559 574 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
560 575 self.dataOut.channelList = self.dataIn.channelList
561 576 self.dataOut.heightList = self.dataIn.heightList
562 577 self.dataOut.dtype = self.dataIn.dtype
563 578 # self.dataOut.nHeights = self.dataIn.nHeights
564 579 # self.dataOut.nChannels = self.dataIn.nChannels
565 580 self.dataOut.nBaud = self.dataIn.nBaud
566 581 self.dataOut.nCode = self.dataIn.nCode
567 582 self.dataOut.code = self.dataIn.code
568 583 self.dataOut.nProfiles = self.dataOut.nFFTPoints
569 584 # self.dataOut.channelIndexList = self.dataIn.channelIndexList
570 585 self.dataOut.flagTimeBlock = self.dataIn.flagTimeBlock
571 586 self.dataOut.utctime = self.firstdatatime
572 587 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
573 588 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
574 589 self.dataOut.flagShiftFFT = self.dataIn.flagShiftFFT
575 590 self.dataOut.nCohInt = self.dataIn.nCohInt
576 591 self.dataOut.nIncohInt = 1
577 592 self.dataOut.ippSeconds = self.dataIn.ippSeconds
578 593
579 594 self.dataOut.timeInterval = self.dataIn.timeInterval*self.dataOut.nFFTPoints*self.dataOut.nIncohInt
580 595
581 596 def __getFft(self):
582 597 """
583 598 Convierte valores de Voltaje a Spectra
584 599
585 600 Affected:
586 601 self.dataOut.data_spc
587 602 self.dataOut.data_cspc
588 603 self.dataOut.data_dc
589 604 self.dataOut.heightList
590 605 self.profIndex
591 606 self.buffer
592 607 self.dataOut.flagNoData
593 608 """
594 609 fft_volt = numpy.fft.fft(self.buffer,axis=1)
595 610 dc = fft_volt[:,0,:]
596 611
597 612 #calculo de self-spectra
598 613 fft_volt = numpy.fft.fftshift(fft_volt,axes=(1,))
599 614 spc = fft_volt * numpy.conjugate(fft_volt)
600 615 spc = spc.real
601 616
602 617 blocksize = 0
603 618 blocksize += dc.size
604 619 blocksize += spc.size
605 620
606 621 cspc = None
607 622 pairIndex = 0
608 623 if self.dataOut.pairsList != None:
609 624 #calculo de cross-spectra
610 625 cspc = numpy.zeros((self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
611 626 for pair in self.dataOut.pairsList:
612 627 cspc[pairIndex,:,:] = numpy.abs(fft_volt[pair[0],:,:] * numpy.conjugate(fft_volt[pair[1],:,:]))
613 628 pairIndex += 1
614 629 blocksize += cspc.size
615 630
616 631 self.dataOut.data_spc = spc
617 632 self.dataOut.data_cspc = cspc
618 633 self.dataOut.data_dc = dc
619 634 self.dataOut.blockSize = blocksize
620 635
621 636 def init(self, nFFTPoints=None, pairsList=None):
622 637
623 638 if self.dataIn.type == "Spectra":
624 639 self.dataOut.copy(self.dataIn)
625 640 return
626 641
627 642 if self.dataIn.type == "Voltage":
628 643
629 644 if nFFTPoints == None:
630 645 raise ValueError, "This SpectraProc.init() need nFFTPoints input variable"
631 646
632 647 if pairsList == None:
633 648 nPairs = 0
634 649 else:
635 650 nPairs = len(pairsList)
636 651
637 652 self.dataOut.nFFTPoints = nFFTPoints
638 653 self.dataOut.pairsList = pairsList
639 654 self.dataOut.nPairs = nPairs
640 655
641 656 if self.buffer == None:
642 657 self.buffer = numpy.zeros((self.dataIn.nChannels,
643 658 self.dataOut.nFFTPoints,
644 659 self.dataIn.nHeights),
645 660 dtype='complex')
646 661
647 662
648 663 self.buffer[:,self.profIndex,:] = self.dataIn.data
649 664 self.profIndex += 1
650 665
651 666 if self.firstdatatime == None:
652 667 self.firstdatatime = self.dataIn.utctime
653 668
654 669 if self.profIndex == self.dataOut.nFFTPoints:
655 670 self.__updateObjFromInput()
656 671 self.__getFft()
657 672
658 673 self.dataOut.flagNoData = False
659 674
660 675 self.buffer = None
661 676 self.firstdatatime = None
662 677 self.profIndex = 0
663 678
664 679 return
665 680
666 681 raise ValuError, "The type object %s is not valid"%(self.dataIn.type)
667 682
668 683 def selectChannels(self, channelList):
669 684
670 685 channelIndexList = []
671 686
672 687 for channel in channelList:
673 688 index = self.dataOut.channelList.index(channel)
674 689 channelIndexList.append(index)
675 690
676 691 self.selectChannelsByIndex(channelIndexList)
677 692
678 693 def selectChannelsByIndex(self, channelIndexList):
679 694 """
680 695 Selecciona un bloque de datos en base a canales segun el channelIndexList
681 696
682 697 Input:
683 698 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
684 699
685 700 Affected:
686 701 self.dataOut.data_spc
687 702 self.dataOut.channelIndexList
688 703 self.dataOut.nChannels
689 704
690 705 Return:
691 706 None
692 707 """
693 708
694 709 for channelIndex in channelIndexList:
695 710 if channelIndex not in self.dataOut.channelIndexList:
696 711 print channelIndexList
697 712 raise ValueError, "The value %d in channelIndexList is not valid" %channelIndex
698 713
699 714 nChannels = len(channelIndexList)
700 715
701 716 data_spc = self.dataOut.data_spc[channelIndexList,:]
702 717
703 718 self.dataOut.data_spc = data_spc
704 719 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
705 720 # self.dataOut.nChannels = nChannels
706 721
707 722 return 1
708 723
709 724
710 725 class IncohInt(Operation):
711 726
712 727
713 728 __profIndex = 0
714 729 __withOverapping = False
715 730
716 731 __byTime = False
717 732 __initime = None
718 733 __lastdatatime = None
719 734 __integrationtime = None
720 735
721 736 __buffer_spc = None
722 737 __buffer_cspc = None
723 738 __buffer_dc = None
724 739
725 740 __dataReady = False
726 741
727 742 n = None
728 743
729 744
730 745 def __init__(self):
731 746
732 747 self.__isConfig = False
733 748
734 749 def setup(self, n=None, timeInterval=None, overlapping=False):
735 750 """
736 751 Set the parameters of the integration class.
737 752
738 753 Inputs:
739 754
740 755 n : Number of coherent integrations
741 756 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
742 757 overlapping :
743 758
744 759 """
745 760
746 761 self.__initime = None
747 762 self.__lastdatatime = 0
748 763 self.__buffer_spc = None
749 764 self.__buffer_cspc = None
750 765 self.__buffer_dc = None
751 766 self.__dataReady = False
752 767
753 768
754 769 if n == None and timeInterval == None:
755 770 raise ValueError, "n or timeInterval should be specified ..."
756 771
757 772 if n != None:
758 773 self.n = n
759 774 self.__byTime = False
760 775 else:
761 776 self.__integrationtime = timeInterval * 60. #if (type(timeInterval)!=integer) -> change this line
762 777 self.n = 9999
763 778 self.__byTime = True
764 779
765 780 if overlapping:
766 781 self.__withOverapping = True
767 782 else:
768 783 self.__withOverapping = False
769 784 self.__buffer_spc = 0
770 785 self.__buffer_cspc = 0
771 786 self.__buffer_dc = 0
772 787
773 788 self.__profIndex = 0
774 789
775 790 def putData(self, data_spc, data_cspc, data_dc):
776 791
777 792 """
778 793 Add a profile to the __buffer_spc and increase in one the __profileIndex
779 794
780 795 """
781 796
782 797 if not self.__withOverapping:
783 798 self.__buffer_spc += data_spc
784 799
785 800 if data_cspc == None:
786 801 self.__buffer_cspc = None
787 802 else:
788 803 self.__buffer_cspc += data_cspc
789 804
790 805 if data_dc == None:
791 806 self.__buffer_dc = None
792 807 else:
793 808 self.__buffer_dc += data_dc
794 809
795 810 self.__profIndex += 1
796 811 return
797 812
798 813 #Overlapping data
799 814 nChannels, nFFTPoints, nHeis = data_spc.shape
800 815 data_spc = numpy.reshape(data_spc, (1, nChannels, nFFTPoints, nHeis))
801 816 if data_cspc != None:
802 817 data_cspc = numpy.reshape(data_cspc, (1, -1, nFFTPoints, nHeis))
803 818 if data_dc != None:
804 819 data_dc = numpy.reshape(data_dc, (1, -1, nHeis))
805 820
806 821 #If the buffer is empty then it takes the data value
807 822 if self.__buffer_spc == None:
808 823 self.__buffer_spc = data_spc
809 824
810 825 if data_cspc == None:
811 826 self.__buffer_cspc = None
812 827 else:
813 828 self.__buffer_cspc += data_cspc
814 829
815 830 if data_dc == None:
816 831 self.__buffer_dc = None
817 832 else:
818 833 self.__buffer_dc += data_dc
819 834
820 835 self.__profIndex += 1
821 836 return
822 837
823 838 #If the buffer length is lower than n then stakcing the data value
824 839 if self.__profIndex < self.n:
825 840 self.__buffer_spc = numpy.vstack((self.__buffer_spc, data_spc))
826 841
827 842 if data_cspc != None:
828 843 self.__buffer_cspc = numpy.vstack((self.__buffer_cspc, data_cspc))
829 844
830 845 if data_dc != None:
831 846 self.__buffer_dc = numpy.vstack((self.__buffer_dc, data_dc))
832 847
833 848 self.__profIndex += 1
834 849 return
835 850
836 851 #If the buffer length is equal to n then replacing the last buffer value with the data value
837 852 self.__buffer_spc = numpy.roll(self.__buffer_spc, -1, axis=0)
838 853 self.__buffer_spc[self.n-1] = data_spc
839 854
840 855 if data_cspc != None:
841 856 self.__buffer_cspc = numpy.roll(self.__buffer_cspc, -1, axis=0)
842 857 self.__buffer_cspc[self.n-1] = data_cspc
843 858
844 859 if data_dc != None:
845 860 self.__buffer_dc = numpy.roll(self.__buffer_dc, -1, axis=0)
846 861 self.__buffer_dc[self.n-1] = data_dc
847 862
848 863 self.__profIndex = self.n
849 864 return
850 865
851 866
852 867 def pushData(self):
853 868 """
854 869 Return the sum of the last profiles and the profiles used in the sum.
855 870
856 871 Affected:
857 872
858 873 self.__profileIndex
859 874
860 875 """
861 876 data_spc = None
862 877 data_cspc = None
863 878 data_dc = None
864 879
865 880 if not self.__withOverapping:
866 881 data_spc = self.__buffer_spc
867 882 data_cspc = self.__buffer_cspc
868 883 data_dc = self.__buffer_dc
869 884
870 885 n = self.__profIndex
871 886
872 887 self.__buffer_spc = 0
873 888 self.__buffer_cspc = 0
874 889 self.__buffer_dc = 0
875 890 self.__profIndex = 0
876 891
877 892 return data_spc, data_cspc, data_dc, n
878 893
879 894 #Integration with Overlapping
880 895 data_spc = numpy.sum(self.__buffer_spc, axis=0)
881 896
882 897 if self.__buffer_cspc != None:
883 898 data_cspc = numpy.sum(self.__buffer_cspc, axis=0)
884 899
885 900 if self.__buffer_dc != None:
886 901 data_dc = numpy.sum(self.__buffer_dc, axis=0)
887 902
888 903 n = self.__profIndex
889 904
890 905 return data_spc, data_cspc, data_dc, n
891 906
892 907 def byProfiles(self, *args):
893 908
894 909 self.__dataReady = False
895 910 avgdata_spc = None
896 911 avgdata_cspc = None
897 912 avgdata_dc = None
898 913 n = None
899 914
900 915 self.putData(*args)
901 916
902 917 if self.__profIndex == self.n:
903 918
904 919 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
905 920 self.__dataReady = True
906 921
907 922 return avgdata_spc, avgdata_cspc, avgdata_dc
908 923
909 924 def byTime(self, datatime, *args):
910 925
911 926 self.__dataReady = False
912 927 avgdata_spc = None
913 928 avgdata_cspc = None
914 929 avgdata_dc = None
915 930 n = None
916 931
917 932 self.putData(*args)
918 933
919 934 if (datatime - self.__initime) >= self.__integrationtime:
920 935 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
921 936 self.n = n
922 937 self.__dataReady = True
923 938
924 939 return avgdata_spc, avgdata_cspc, avgdata_dc
925 940
926 941 def integrate(self, datatime, *args):
927 942
928 943 if self.__initime == None:
929 944 self.__initime = datatime
930 945
931 946 if self.__byTime:
932 947 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(datatime, *args)
933 948 else:
934 949 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
935 950
936 951 self.__lastdatatime = datatime
937 952
938 953 if avgdata_spc == None:
939 954 return None, None, None, None
940 955
941 956 avgdatatime = self.__initime
942 957
943 958 deltatime = datatime -self.__lastdatatime
944 959
945 960 if not self.__withOverapping:
946 961 self.__initime = datatime
947 962 else:
948 963 self.__initime += deltatime
949 964
950 965 return avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc
951 966
952 967 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
953 968
954 969 if not self.__isConfig:
955 970 self.setup(n, timeInterval, overlapping)
956 971 self.__isConfig = True
957 972
958 973 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
959 974 dataOut.data_spc,
960 975 dataOut.data_cspc,
961 976 dataOut.data_dc)
962 977
963 978 # dataOut.timeInterval *= n
964 979 dataOut.flagNoData = True
965 980
966 981 if self.__dataReady:
967 982 dataOut.data_spc = avgdata_spc
968 983 dataOut.data_cspc = avgdata_cspc
969 984 dataOut.data_dc = avgdata_dc
970 985
971 986 dataOut.nIncohInt *= self.n
972 987 dataOut.utctime = avgdatatime
973 988 dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt * dataOut.nIncohInt * dataOut.nFFTPoints
974 989 dataOut.flagNoData = False
975 No newline at end of file
990
991
992 class ProfileSelector(Operation):
993
994 profileIndex = None
995 # Tamanho total de los perfiles
996 nProfiles = None
997
998 def __init__(self):
999
1000 self.profileIndex = 0
1001
1002 def incIndex(self):
1003 self.profileIndex += 1
1004
1005 if self.profileIndex >= self.nProfiles:
1006 self.profileIndex = 0
1007
1008 def isProfileInRange(self, minIndex, maxIndex):
1009
1010 if self.profileIndex < minIndex:
1011 return False
1012
1013 if self.profileIndex > maxIndex:
1014 return False
1015
1016 return True
1017
1018 def isProfileInList(self, profileList):
1019
1020 if self.profileIndex not in profileList:
1021 return False
1022
1023 return True
1024
1025 def run(self, dataOut, profileList=None, profileRangeList=None):
1026
1027 self.nProfiles = dataOut.nProfiles
1028
1029 if profileList != None:
1030 if not(self.isProfileInList(profileList)):
1031 dataOut.flagNoData = True
1032 else:
1033 dataOut.flagNoData = False
1034 self.incIndex()
1035 return 1
1036
1037
1038 elif profileRangeList != None:
1039 minIndex = profileRangeList[0]
1040 maxIndex = profileRangeList[1]
1041 if not(self.isProfileInRange(minIndex, maxIndex)):
1042 dataOut.flagNoData = True
1043 else:
1044 dataOut.flagNoData = False
1045 self.incIndex()
1046 return 1
1047 else:
1048 raise ValueError, "ProfileSelector needs profileList or profileRangeList"
1049
1050 return 0
1051
1052 class Decoder:
1053
1054 data = None
1055 profCounter = None
1056 code = None
1057 ncode = None
1058 nbaud = None
1059 codeIndex = None
1060 flag = False
1061
1062 def __init__(self):
1063
1064 self.data = None
1065 self.ndata = None
1066 self.profCounter = 1
1067 self.codeIndex = 0
1068 self.flag = False
1069 self.code = None
1070 self.ncode = None
1071 self.nbaud = None
1072 self.__isConfig = False
1073
1074 def convolutionInFreq(self, data, ndata):
1075
1076 newcode = numpy.zeros(ndata)
1077 newcode[0:self.nbaud] = self.code[self.codeIndex]
1078
1079 self.codeIndex += 1
1080
1081 fft_data = numpy.fft.fft(data, axis=1)
1082 fft_code = numpy.conj(numpy.fft.fft(newcode))
1083 fft_code = fft_code.reshape(1,len(fft_code))
1084
1085 conv = fft_data.copy()
1086 conv.fill(0)
1087
1088 conv = fft_data*fft_code
1089
1090 data = numpy.fft.ifft(conv,axis=1)
1091 self.data = data[:,:-self.nbaud+1]
1092 self.flag = True
1093
1094 if self.profCounter == self.ncode:
1095 self.profCounter = 0
1096 self.codeIndex = 0
1097
1098 self.profCounter += 1
1099
1100 def convolutionInTime(self, data, ndata):
1101
1102 nchannel = data.shape[1]
1103 newcode = self.code[self.codeIndex]
1104 self.codeIndex += 1
1105 conv = data.copy()
1106 for i in range(nchannel):
1107 conv[i,:] = numpy.correlate(data[i,:], newcode)
1108
1109 self.data = conv
1110 self.flag = True
1111
1112 if self.profCounter == self.ncode:
1113 self.profCounter = 0
1114 self.codeIndex = 0
1115
1116 self.profCounter += 1
1117
1118 def run(self, dataOut, code=None, mode = 0):
1119
1120 if not(self.__isConfig):
1121 if code == None:
1122 code = dataOut.radarControllerHeaderObj.code
1123 # code = dataOut.code
1124
1125 ncode, nbaud = code.shape
1126 self.code = code
1127 self.ncode = ncode
1128 self.nbaud = nbaud
1129 self.__isConfig = True
1130
1131 ndata = dataOut.data.shape[1]
1132
1133 if mode == 0:
1134 self.convolutionInFreq(dataOut.data, ndata)
1135
1136 if mode == 1:
1137 self.convolutionInTime(dataOut.data, ndata)
1138
1139 self.ndata = ndata - self.nbaud + 1
1140
1141 dataOut.data = self.data
1142
1143 dataOut.heightList = dataOut.heightList[:self.ndata]
1144
1145 dataOut.flagNoData = False No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now