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