##// END OF EJS Templates
VoltageProcessor: Crea el objeto de salida en el constructor
Miguel Valdez -
r188:c0af656b96e7
parent child
Show More
@@ -1,444 +1,439
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 addOperation(self, object, objId):
40 40
41 41 """
42 42 Agrega el objeto "object" a la lista de objetos "self.objectList" y retorna el
43 43 identificador asociado a este objeto.
44 44
45 45 Input:
46 46
47 47 object : objeto de la clase "Operation"
48 48
49 49 Return:
50 50
51 51 objId : identificador del objeto, necesario para ejecutar la operacion
52 52 """
53 53
54 54 self.objectDict[objId] = object
55 55
56 56 return objId
57 57
58 58 def operation(self, **kwargs):
59 59
60 60 """
61 61 Operacion directa sobre la data (dataout.data). Es necesario actualizar los valores de los
62 62 atributos del objeto dataOut
63 63
64 64 Input:
65 65
66 66 **kwargs : Diccionario de argumentos de la funcion a ejecutar
67 67 """
68 68
69 if self.dataIn.isEmpty():
70 return None
71
72 69 raise ValueError, "ImplementedError"
73 70
74 71 def callMethod(self, name, **kwargs):
75 72
76 73 """
77 74 Ejecuta el metodo con el nombre "name" y con argumentos **kwargs de la propia clase.
78 75
79 76 Input:
80 77 name : nombre del metodo a ejecutar
81 78
82 79 **kwargs : diccionario con los nombres y valores de la funcion a ejecutar.
83 80
84 81 """
85 82
86 if self.dataIn.isEmpty():
87 return None
88
89 83 methodToCall = getattr(self, name)
90 84
91 85 methodToCall(**kwargs)
92 86
93 87 def callObject(self, objId, **kwargs):
94 88
95 89 """
96 90 Ejecuta la operacion asociada al identificador del objeto "objId"
97 91
98 92 Input:
99 93
100 94 objId : identificador del objeto a ejecutar
101 95
102 96 **kwargs : diccionario con los nombres y valores de la funcion a ejecutar.
103 97
104 98 Return:
105 99
106 100 None
107 101 """
108 102
109 if self.dataIn.isEmpty():
110 return None
111
112 103 object = self.objectList[objId]
113 104
114 105 object.run(self.dataOut, **kwargs)
115 106
116 def call(self, operation, **kwargs):
107 def call(self, operationConf, **kwargs):
117 108
118 109 """
119 Ejecuta la operacion "operation" con los argumentos "**kwargs". La operacion puede
110 Ejecuta la operacion "operationConf.name" con los argumentos "**kwargs". La operacion puede
120 111 ser de dos tipos:
121 112
122 113 1. Un metodo propio de esta clase:
123 114
124 115 operation.type = "self"
125 116
126 117 2. El metodo "run" de un objeto del tipo Operation o de un derivado de ella:
127 118 operation.type = "other".
128 119
129 120 Este objeto de tipo Operation debe de haber sido agregado antes con el metodo:
130 121 "addOperation" e identificado con el operation.id
131 122
132 123
133 124 con el id de la operacion.
125
126 Input:
127
128 Operation : Objeto del tipo operacion con los atributos: name, type y id.
129
134 130 """
135 131 if self.dataIn.isEmpty():
136 132 return None
137 133
138 if operation.type == 'self':
139 self.callMethod(operation.name, **kwargs)
134 if operationConf.type == 'self':
135 self.callMethod(operationConf.name, **kwargs)
140 136 return
141 137
142 if operation.type == 'other':
143 self.callObject(operation.id, **kwargs)
138 if operationConf.type == 'other':
139 self.callObject(operationConf.id, **kwargs)
144 140 return
145 141
146 142 class Operation():
147 143
148 144 """
149 145 Clase base para definir las operaciones adicionales que se pueden agregar a la clase ProcessingUnit
150 146 y necesiten acumular informacion previa de los datos a procesar. De preferencia usar un buffer de
151 147 acumulacion dentro de esta clase
152 148
153 149 Ejemplo: Integraciones coherentes, necesita la informacion previa de los n perfiles anteriores (bufffer)
154 150
155 151 """
156 152
157 153 __buffer = None
158 154 __isConfig = False
159 155
160 156 def __init__(self):
161 157
162 158 pass
163 159
164 160 def run(self, dataIn, **kwargs):
165 161
166 162 """
167 163 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los atributos del objeto dataIn.
168 164
169 165 Input:
170 166
171 167 dataIn : objeto del tipo JROData
172 168
173 169 Return:
174 170
175 171 None
176 172
177 173 Affected:
178 174 __buffer : buffer de recepcion de datos.
179 175
180 176 """
181 177
182 178 raise ValueError, "ImplementedError"
183 179
184 180 class VoltageProc(ProcessingUnit):
185 181
186 182
187 183 def __init__(self):
184
188 185 self.objectDict = {}
189 pass
186 self.dataOut = Voltage()
187
190 188
191 189 def setup(self, dataIn=None, dataOut=None):
192 190
193 191 self.dataIn = dataIn
194 192
195 193 if self.dataOut == None:
196 194 dataOut = Voltage()
197 195
198 196 self.dataOut = dataOut
199 197
200 198 return self.dataOut
201 199
202 200 def init(self):
203 201
204 if self.dataIn.isEmpty():
205 return 0
206
207 202 self.dataOut.copy(self.dataIn)
208 203 # No necesita copiar en cada init() los atributos de dataIn
209 204 # la copia deberia hacerse por cada nuevo bloque de datos
210 205
211 206 def selectChannels(self, channelList):
212 207
213 208 if self.dataIn.isEmpty():
214 209 return 0
215 210
216 211 self.selectChannelsByIndex(channelList)
217 212
218 213 def selectChannelsByIndex(self, channelIndexList):
219 214 """
220 215 Selecciona un bloque de datos en base a canales segun el channelIndexList
221 216
222 217 Input:
223 218 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
224 219
225 220 Affected:
226 221 self.dataOut.data
227 222 self.dataOut.channelIndexList
228 223 self.dataOut.nChannels
229 224 self.dataOut.m_ProcessingHeader.totalSpectra
230 225 self.dataOut.systemHeaderObj.numChannels
231 226 self.dataOut.m_ProcessingHeader.blockSize
232 227
233 228 Return:
234 229 None
235 230 """
236 231
237 232 for channel in channelIndexList:
238 233 if channel not in self.dataOut.channelIndexList:
239 234 raise ValueError, "The value %d in channelIndexList is not valid" %channel
240 235
241 236 nChannels = len(channelIndexList)
242 237
243 238 data = self.dataOut.data[channelIndexList,:]
244 239
245 240 self.dataOut.data = data
246 241 self.dataOut.channelIndexList = channelIndexList
247 242 self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
248 243 self.dataOut.nChannels = nChannels
249 244
250 245 return 1
251 246
252 247 class CohInt(Operation):
253 248
254 249 __profIndex = 0
255 250 __withOverapping = False
256 251
257 252 __byTime = False
258 253 __initime = None
259 254 __lastdatatime = None
260 255 __integrationtime = None
261 256
262 257 __buffer = None
263 258
264 259 __dataReady = False
265 260
266 261 nCohInt = None
267 262
268 263
269 264 def __init__(self):
270 265
271 266 self.__isConfig = False
272 267
273 268 def setup(self, nCohInt=None, timeInterval=None, overlapping=False):
274 269 """
275 270 Set the parameters of the integration class.
276 271
277 272 Inputs:
278 273
279 274 nCohInt : Number of coherent integrations
280 275 timeInterval : Time of integration. If the parameter "nCohInt" is selected this one does not work
281 276 overlapping :
282 277
283 278 """
284 279
285 280 self.__initime = None
286 281 self.__lastdatatime = 0
287 282 self.__buffer = None
288 283 self.__dataReady = False
289 284
290 285
291 286 if nCohInt == None and timeInterval == None:
292 287 raise ValueError, "nCohInt or timeInterval should be specified ..."
293 288
294 289 if nCohInt != None:
295 290 self.nCohInt = nCohInt
296 291 self.__byTime = False
297 292 else:
298 293 self.__integrationtime = timeInterval * 60. #if (type(timeInterval)!=integer) -> change this line
299 294 self.nCohInt = 9999
300 295 self.__byTime = True
301 296
302 297 if overlapping:
303 298 self.__withOverapping = True
304 299 self.__buffer = None
305 300 else:
306 301 self.__withOverapping = False
307 302 self.__buffer = 0
308 303
309 304 self.__profIndex = 0
310 305
311 306 def putData(self, data):
312 307
313 308 """
314 309 Add a profile to the __buffer and increase in one the __profileIndex
315 310
316 311 """
317 312
318 313 if not self.__withOverapping:
319 314 self.__buffer += data
320 315 self.__profIndex += 1
321 316 return
322 317
323 318 #Overlapping data
324 319 nChannels, nHeis = data.shape
325 320 data = numpy.reshape(data, (1, nChannels, nHeis))
326 321
327 322 #If the buffer is empty then it takes the data value
328 323 if self.__buffer == None:
329 324 self.__buffer = data
330 325 self.__profIndex += 1
331 326 return
332 327
333 328 #If the buffer length is lower than nCohInt then stakcing the data value
334 329 if self.__profIndex < self.nCohInt:
335 330 self.__buffer = numpy.vstack((self.__buffer, data))
336 331 self.__profIndex += 1
337 332 return
338 333
339 334 #If the buffer length is equal to nCohInt then replacing the last buffer value with the data value
340 335 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
341 336 self.__buffer[self.nCohInt-1] = data
342 337 self.__profIndex = self.nCohInt
343 338 return
344 339
345 340
346 341 def pushData(self):
347 342 """
348 343 Return the sum of the last profiles and the profiles used in the sum.
349 344
350 345 Affected:
351 346
352 347 self.__profileIndex
353 348
354 349 """
355 350
356 351 if not self.__withOverapping:
357 352 data = self.__buffer
358 353 nCohInt = self.__profIndex
359 354
360 355 self.__buffer = 0
361 356 self.__profIndex = 0
362 357
363 358 return data, nCohInt
364 359
365 360 #Integration with Overlapping
366 361 data = numpy.sum(self.__buffer, axis=0)
367 362 nCohInt = self.__profIndex
368 363
369 364 return data, nCohInt
370 365
371 366 def byProfiles(self, data):
372 367
373 368 self.__dataReady = False
374 369 avg_data = None
375 370 nCohInt = None
376 371
377 372 self.putData(data)
378 373
379 374 if self.__profIndex == self.nCohInt:
380 375
381 376 avgdata, nCohInt = self.pushData()
382 377 self.__dataReady = True
383 378
384 379 return avgdata, nCohInt
385 380
386 381 def byTime(self, data, datatime):
387 382
388 383 self.__dataReady = False
389 384 avg_data = None
390 385 nCohInt = None
391 386
392 387 self.putData(data)
393 388
394 389 if (datatime - self.__initime) >= self.__integrationtime:
395 390 avgdata, nCohInt = self.pushData()
396 391 self.nCohInt = nCohInt
397 392 self.__dataReady = True
398 393
399 394 return avgdata, nCohInt
400 395
401 396 def integrate(self, data, datatime=None):
402 397
403 398 if self.__initime == None:
404 399 self.__initime = datatime
405 400
406 401 if self.__byTime:
407 402 avgdata = self.byTime(data, datatime)
408 403 else:
409 404 avgdata = self.byProfiles(data)
410 405
411 406
412 407 self.__lastdatatime = datatime
413 408
414 409 if avgdata == None:
415 410 return None
416 411
417 412 avgdatatime = self.__initime
418 413
419 414 deltatime = datatime -self.__lastdatatime
420 415
421 416 if not self.__withOverapping:
422 417 self.__initime = datatime
423 418 else:
424 419 self.__initime += deltatime
425 420
426 421 return avgdata, avgdatatime
427 422
428 423 def run(self, dataOut, nCohInt=None, timeInterval=None, overlapping=False):
429 424
430 425 if not self.__isConfig:
431 426 self.setup(nCohInt, timeInterval, overlapping)
432 427 self.__isConfig = True
433 428
434 429 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
435 430
436 431 # self.dataOut.timeInterval *= nCohInt
437 432 self.dataOut.flagNoData = True
438 433
439 434 if self.__dataReady:
440 435 dataOut.data = avgdata
441 436 dataOut.timeInterval *= self.nCohInt
442 437 dataOut.nCohInt *= self.nCohInt
443 438 dataOut.utctime = avgdatatime
444 439 dataOut.flagNoData = False No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now