##// END OF EJS Templates
Support for VoltageReader when nTxs is >1 or <1
Miguel Valdez -
r748:0fab1290f1a0
parent child
Show More
@@ -1,594 +1,596
1 1 '''
2 2 Created on Jul 2, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6
7 7 import numpy
8 8
9 9 from jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
10 10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
11 11 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
12 12 from schainpy.model.data.jrodata import Voltage
13 13
14 14 class VoltageReader(JRODataReader, ProcessingUnit):
15 15 """
16 16 Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura
17 17 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones:
18 18 perfiles*alturas*canales) son almacenados en la variable "buffer".
19 19
20 20 perfiles * alturas * canales
21 21
22 22 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
23 23 RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la
24 24 cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de
25 25 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
26 26
27 27 Example:
28 28
29 29 dpath = "/home/myuser/data"
30 30
31 31 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
32 32
33 33 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
34 34
35 35 readerObj = VoltageReader()
36 36
37 37 readerObj.setup(dpath, startTime, endTime)
38 38
39 39 while(True):
40 40
41 41 #to get one profile
42 42 profile = readerObj.getData()
43 43
44 44 #print the profile
45 45 print profile
46 46
47 47 #If you want to see all datablock
48 48 print readerObj.datablock
49 49
50 50 if readerObj.flagNoMoreFiles:
51 51 break
52 52
53 53 """
54 54
55 55 ext = ".r"
56 56
57 57 optchar = "D"
58 58 dataOut = None
59 59
60 60
61 61 def __init__(self):
62 62 """
63 63 Inicializador de la clase VoltageReader para la lectura de datos de voltage.
64 64
65 65 Input:
66 66 dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para
67 67 almacenar un perfil de datos cada vez que se haga un requerimiento
68 68 (getData). El perfil sera obtenido a partir del buffer de datos,
69 69 si el buffer esta vacio se hara un nuevo proceso de lectura de un
70 70 bloque de datos.
71 71 Si este parametro no es pasado se creara uno internamente.
72 72
73 73 Variables afectadas:
74 74 self.dataOut
75 75
76 76 Return:
77 77 None
78 78 """
79 79
80 80 ProcessingUnit.__init__(self)
81 81
82 82 self.isConfig = False
83 83
84 84 self.datablock = None
85 85
86 86 self.utc = 0
87 87
88 88 self.ext = ".r"
89 89
90 90 self.optchar = "D"
91 91
92 92 self.basicHeaderObj = BasicHeader(LOCALTIME)
93 93
94 94 self.systemHeaderObj = SystemHeader()
95 95
96 96 self.radarControllerHeaderObj = RadarControllerHeader()
97 97
98 98 self.processingHeaderObj = ProcessingHeader()
99 99
100 100 self.online = 0
101 101
102 102 self.fp = None
103 103
104 104 self.idFile = None
105 105
106 106 self.dtype = None
107 107
108 108 self.fileSizeByHeader = None
109 109
110 110 self.filenameList = []
111 111
112 112 self.filename = None
113 113
114 114 self.fileSize = None
115 115
116 116 self.firstHeaderSize = 0
117 117
118 118 self.basicHeaderSize = 24
119 119
120 120 self.pathList = []
121 121
122 122 self.filenameList = []
123 123
124 124 self.lastUTTime = 0
125 125
126 126 self.maxTimeStep = 30
127 127
128 128 self.flagNoMoreFiles = 0
129 129
130 130 self.set = 0
131 131
132 132 self.path = None
133 133
134 134 self.profileIndex = 2**32-1
135 135
136 136 self.delay = 3 #seconds
137 137
138 138 self.nTries = 3 #quantity tries
139 139
140 140 self.nFiles = 3 #number of files for searching
141 141
142 142 self.nReadBlocks = 0
143 143
144 144 self.flagIsNewFile = 1
145 145
146 146 self.__isFirstTimeOnline = 1
147 147
148 148 # self.ippSeconds = 0
149 149
150 150 self.flagDiscontinuousBlock = 0
151 151
152 152 self.flagIsNewBlock = 0
153 153
154 154 self.nTotalBlocks = 0
155 155
156 156 self.blocksize = 0
157 157
158 158 self.dataOut = self.createObjByDefault()
159 159
160 160 self.nTxs = 1
161 161
162 162 self.txIndex = 0
163 163
164 164 def createObjByDefault(self):
165 165
166 166 dataObj = Voltage()
167 167
168 168 return dataObj
169 169
170 170 def __hasNotDataInBuffer(self):
171 171
172 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
172 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock*self.nTxs:
173 173 return 1
174 174
175 175 return 0
176 176
177 177
178 178 def getBlockDimension(self):
179 179 """
180 180 Obtiene la cantidad de puntos a leer por cada bloque de datos
181 181
182 182 Affected:
183 183 self.blocksize
184 184
185 185 Return:
186 186 None
187 187 """
188 188 pts2read = self.processingHeaderObj.profilesPerBlock * self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels
189 189 self.blocksize = pts2read
190 190
191 191
192 192 def readBlock(self):
193 193 """
194 194 readBlock lee el bloque de datos desde la posicion actual del puntero del archivo
195 195 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
196 196 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
197 197 es seteado a 0
198 198
199 199 Inputs:
200 200 None
201 201
202 202 Return:
203 203 None
204 204
205 205 Affected:
206 206 self.profileIndex
207 207 self.datablock
208 208 self.flagIsNewFile
209 209 self.flagIsNewBlock
210 210 self.nTotalBlocks
211 211
212 212 Exceptions:
213 213 Si un bloque leido no es un bloque valido
214 214 """
215 215 current_pointer_location = self.fp.tell()
216 216 junk = numpy.fromfile( self.fp, self.dtype, self.blocksize )
217 217
218 218 try:
219 219 junk = junk.reshape( (self.processingHeaderObj.profilesPerBlock, self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels) )
220 220 except:
221 221 #print "The read block (%3d) has not enough data" %self.nReadBlocks
222 222
223 223 if self.waitDataBlock(pointer_location=current_pointer_location):
224 224 junk = numpy.fromfile( self.fp, self.dtype, self.blocksize )
225 225 junk = junk.reshape( (self.processingHeaderObj.profilesPerBlock, self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels) )
226 226 # return 0
227 227
228 228 #Dimensions : nChannels, nProfiles, nSamples
229 229
230 230 junk = numpy.transpose(junk, (2,0,1))
231 231 self.datablock = junk['real'] + junk['imag']*1j
232 232
233 233 self.profileIndex = 0
234 234
235 235 self.flagIsNewFile = 0
236 236 self.flagIsNewBlock = 1
237 237
238 238 self.nTotalBlocks += 1
239 239 self.nReadBlocks += 1
240 240
241 241 return 1
242 242
243 243 def getFirstHeader(self):
244 244
245 245 self.getBasicHeader()
246 246
247 247 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
248 248
249 249 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
250 250
251 251 if self.nTxs > 1:
252 252 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds/self.nTxs
253 253
254 254 #Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj.
255 255
256 256 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt
257 257 #
258 258 # if self.radarControllerHeaderObj.code is not None:
259 259 #
260 260 # self.dataOut.nCode = self.radarControllerHeaderObj.nCode
261 261 #
262 262 # self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud
263 263 #
264 264 # self.dataOut.code = self.radarControllerHeaderObj.code
265 265
266 266 self.dataOut.dtype = self.dtype
267 267
268 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs
268 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
269 269
270 if self.processingHeaderObj.nHeights % self.nTxs != 0:
271 raise ValueError, "nTxs (%d) should be a multiple of nHeights (%d)" %(self.nTxs, self.processingHeaderObj.nHeights)
272
273 xf = self.processingHeaderObj.firstHeight + int(self.processingHeaderObj.nHeights/self.nTxs)*self.processingHeaderObj.deltaHeight
274
275 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.firstHeight, xf, self.processingHeaderObj.deltaHeight)
270 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights) *self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
276 271
277 272 self.dataOut.channelList = range(self.systemHeaderObj.nChannels)
278 273
279 274 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
280 275
281 276 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode #asumo q la data no esta decodificada
282 277
283 278 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip #asumo q la data no esta sin flip
284 279
285 280 self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft
286 281
282 def reshapeData(self):
283
284 if self.nTxs < 0:
285 return
286
287 if self.nTxs == 1:
288 return
289
290 if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1./self.nTxs) != 0:
291 raise ValueError, "1./nTxs (=%f), should be a multiple of nProfiles (=%d)" %(1./self.nTxs, self.processingHeaderObj.profilesPerBlock)
292
293 if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0:
294 raise ValueError, "nTxs (=%d), should be a multiple of nHeights (=%d)" %(self.nTxs, self.processingHeaderObj.nHeights)
295
296 self.datablock = self.datablock.reshape((self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock*self.nTxs, self.processingHeaderObj.nHeights/self.nTxs))
297
298 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs
299 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights/self.nTxs) *self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
300 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds/self.nTxs
301
302 return
303
287 304 def getData(self):
288 305 """
289 306 getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut
290 307 del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos
291 308 en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando
292 309 "readNextBlock"
293 310
294 311 Ademas incrementa el contador del buffer "self.profileIndex" en 1.
295 312
296 313 Return:
297 314
298 315 Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex
299 316 es igual al total de perfiles leidos desde el archivo.
300 317
301 318 Si self.getByBlock == False:
302 319
303 320 self.dataOut.data = buffer[:, thisProfile, :]
304 321
305 322 shape = [nChannels, nHeis]
306 323
307 324 Si self.getByBlock == True:
308 325
309 326 self.dataOut.data = buffer[:, :, :]
310 327
311 328 shape = [nChannels, nProfiles, nHeis]
312 329
313 330 Variables afectadas:
314 331 self.dataOut
315 332 self.profileIndex
316 333
317 334 Affected:
318 335 self.dataOut
319 336 self.profileIndex
320 337 self.flagDiscontinuousBlock
321 338 self.flagIsNewBlock
322 339 """
323 340
324 341 if self.flagNoMoreFiles:
325 342 self.dataOut.flagNoData = True
326 343 print 'Process finished'
327 344 return 0
328 345
329 346 self.flagDiscontinuousBlock = 0
330 347 self.flagIsNewBlock = 0
331 348
332 349 if self.__hasNotDataInBuffer():
333 350
334 351 if not( self.readNextBlock() ):
335 352 return 0
336 353
337 354 self.getFirstHeader()
355
356 self.reshapeData()
338 357
339 358 if self.datablock is None:
340 359 self.dataOut.flagNoData = True
341 360 return 0
342 361
343 362 if not self.getByBlock:
344 363
345 364 """
346 365 Return profile by profile
347 366
348 367 If nTxs > 1 then one profile is divided by nTxs and number of total
349 368 blocks is increased by nTxs (nProfiles *= nTxs)
350 369 """
351 370 self.dataOut.flagDataAsBlock = False
371 self.dataOut.data = self.datablock[:,self.profileIndex,:]
372 self.dataOut.profileIndex = self.profileIndex
352 373
353 if self.nTxs == 1:
354 self.dataOut.data = self.datablock[:,self.profileIndex,:]
355 self.dataOut.profileIndex = self.profileIndex
356
357 self.profileIndex += 1
358
359 else:
360 iniHei_ForThisTx = (self.txIndex)*int(self.processingHeaderObj.nHeights/self.nTxs)
361 endHei_ForThisTx = (self.txIndex+1)*int(self.processingHeaderObj.nHeights/self.nTxs)
362
363 # print iniHei_ForThisTx, endHei_ForThisTx
364
365 self.dataOut.data = self.datablock[:, self.profileIndex, iniHei_ForThisTx:endHei_ForThisTx]
366 self.dataOut.profileIndex = self.profileIndex*self.nTxs + self.txIndex
367
368 self.txIndex += 1
369
370 if self.txIndex == self.nTxs:
371 self.txIndex = 0
372 self.profileIndex += 1
374 self.profileIndex += 1
373 375
374 376 else:
375 377 """
376 378 Return all block
377 379 """
378 380 self.dataOut.flagDataAsBlock = True
379 381 self.dataOut.data = self.datablock
380 self.dataOut.profileIndex = self.processingHeaderObj.profilesPerBlock
382 self.dataOut.profileIndex = self.dataOut.nProfiles - 1
381 383
382 self.profileIndex = self.processingHeaderObj.profilesPerBlock
384 self.profileIndex = self.dataOut.nProfiles
383 385
384 386 self.dataOut.flagNoData = False
385 387
386 388 self.getBasicHeader()
387 389
388 390 self.dataOut.realtime = self.online
389 391
390 392 return self.dataOut.data
391 393
392 394 class VoltageWriter(JRODataWriter, Operation):
393 395 """
394 396 Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura
395 397 de los datos siempre se realiza por bloques.
396 398 """
397 399
398 400 ext = ".r"
399 401
400 402 optchar = "D"
401 403
402 404 shapeBuffer = None
403 405
404 406
405 407 def __init__(self):
406 408 """
407 409 Inicializador de la clase VoltageWriter para la escritura de datos de espectros.
408 410
409 411 Affected:
410 412 self.dataOut
411 413
412 414 Return: None
413 415 """
414 416 Operation.__init__(self)
415 417
416 418 self.nTotalBlocks = 0
417 419
418 420 self.profileIndex = 0
419 421
420 422 self.isConfig = False
421 423
422 424 self.fp = None
423 425
424 426 self.flagIsNewFile = 1
425 427
426 428 self.blockIndex = 0
427 429
428 430 self.flagIsNewBlock = 0
429 431
430 432 self.setFile = None
431 433
432 434 self.dtype = None
433 435
434 436 self.path = None
435 437
436 438 self.filename = None
437 439
438 440 self.basicHeaderObj = BasicHeader(LOCALTIME)
439 441
440 442 self.systemHeaderObj = SystemHeader()
441 443
442 444 self.radarControllerHeaderObj = RadarControllerHeader()
443 445
444 446 self.processingHeaderObj = ProcessingHeader()
445 447
446 448 def hasAllDataInBuffer(self):
447 449 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
448 450 return 1
449 451 return 0
450 452
451 453
452 454 def setBlockDimension(self):
453 455 """
454 456 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
455 457
456 458 Affected:
457 459 self.shape_spc_Buffer
458 460 self.shape_cspc_Buffer
459 461 self.shape_dc_Buffer
460 462
461 463 Return: None
462 464 """
463 465 self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock,
464 466 self.processingHeaderObj.nHeights,
465 467 self.systemHeaderObj.nChannels)
466 468
467 469 self.datablock = numpy.zeros((self.systemHeaderObj.nChannels,
468 470 self.processingHeaderObj.profilesPerBlock,
469 471 self.processingHeaderObj.nHeights),
470 472 dtype=numpy.dtype('complex64'))
471 473
472 474 def writeBlock(self):
473 475 """
474 476 Escribe el buffer en el file designado
475 477
476 478 Affected:
477 479 self.profileIndex
478 480 self.flagIsNewFile
479 481 self.flagIsNewBlock
480 482 self.nTotalBlocks
481 483 self.blockIndex
482 484
483 485 Return: None
484 486 """
485 487 data = numpy.zeros( self.shapeBuffer, self.dtype )
486 488
487 489 junk = numpy.transpose(self.datablock, (1,2,0))
488 490
489 491 data['real'] = junk.real
490 492 data['imag'] = junk.imag
491 493
492 494 data = data.reshape( (-1) )
493 495
494 496 data.tofile( self.fp )
495 497
496 498 self.datablock.fill(0)
497 499
498 500 self.profileIndex = 0
499 501 self.flagIsNewFile = 0
500 502 self.flagIsNewBlock = 1
501 503
502 504 self.blockIndex += 1
503 505 self.nTotalBlocks += 1
504 506
505 507 # print "[Writing] Block = %04d" %self.blockIndex
506 508
507 509 def putData(self):
508 510 """
509 511 Setea un bloque de datos y luego los escribe en un file
510 512
511 513 Affected:
512 514 self.flagIsNewBlock
513 515 self.profileIndex
514 516
515 517 Return:
516 518 0 : Si no hay data o no hay mas files que puedan escribirse
517 519 1 : Si se escribio la data de un bloque en un file
518 520 """
519 521 if self.dataOut.flagNoData:
520 522 return 0
521 523
522 524 self.flagIsNewBlock = 0
523 525
524 526 if self.dataOut.flagDiscontinuousBlock:
525 527 self.datablock.fill(0)
526 528 self.profileIndex = 0
527 529 self.setNextFile()
528 530
529 531 if self.profileIndex == 0:
530 532 self.setBasicHeader()
531 533
532 534 self.datablock[:,self.profileIndex,:] = self.dataOut.data
533 535
534 536 self.profileIndex += 1
535 537
536 538 if self.hasAllDataInBuffer():
537 539 #if self.flagIsNewFile:
538 540 self.writeNextBlock()
539 541 # self.setFirstHeader()
540 542
541 543 return 1
542 544
543 545 def __getBlockSize(self):
544 546 '''
545 547 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage
546 548 '''
547 549
548 550 dtype_width = self.getDtypeWidth()
549 551
550 552 blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels * self.profilesPerBlock * dtype_width * 2)
551 553
552 554 return blocksize
553 555
554 556 def setFirstHeader(self):
555 557
556 558 """
557 559 Obtiene una copia del First Header
558 560
559 561 Affected:
560 562 self.systemHeaderObj
561 563 self.radarControllerHeaderObj
562 564 self.dtype
563 565
564 566 Return:
565 567 None
566 568 """
567 569
568 570 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
569 571 self.systemHeaderObj.nChannels = self.dataOut.nChannels
570 572 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
571 573
572 574 self.processingHeaderObj.dtype = 0 # Voltage
573 575 self.processingHeaderObj.blockSize = self.__getBlockSize()
574 576 self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock
575 577 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
576 578 self.processingHeaderObj.nWindows = 1 #podria ser 1 o self.dataOut.processingHeaderObj.nWindows
577 579 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt
578 580 self.processingHeaderObj.nIncohInt = 1 # Cuando la data de origen es de tipo Voltage
579 581 self.processingHeaderObj.totalSpectra = 0 # Cuando la data de origen es de tipo Voltage
580 582
581 583 if self.dataOut.code is not None:
582 584 self.processingHeaderObj.code = self.dataOut.code
583 585 self.processingHeaderObj.nCode = self.dataOut.nCode
584 586 self.processingHeaderObj.nBaud = self.dataOut.nBaud
585 587
586 588 if self.processingHeaderObj.nWindows != 0:
587 589 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
588 590 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
589 591 self.processingHeaderObj.nHeights = self.dataOut.nHeights
590 592 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
591 593
592 594 self.processingHeaderObj.processFlags = self.getProcessFlags()
593 595
594 596 self.setBasicHeader() No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now