##// END OF EJS Templates
DataIO.py...
Victor Sarmiento -
r77:3a62c06f85f2
parent child
Show More
@@ -1,1184 +1,1268
1 1 '''
2 2 Created on 23/01/2012
3 3
4 4 @author $Author$
5 5 @version $Id$
6 6 @version $Id$
7 7 '''
8 8
9 9 import os, sys
10 10 import glob
11 11 import time
12 12 import numpy
13 13 import fnmatch
14 14 import time, datetime
15 15
16 16 path = os.path.split(os.getcwd())[0]
17 17 sys.path.append(path)
18 18
19 19 from Model.JROHeader import *
20 20 from Model.JROData import JROData
21 21
22 22 def checkForRealPath(path, year, doy, set, ext):
23 23 """
24 24 Por ser Linux Case Sensitive entonces checkForRealPath encuentra el nombre correcto de un path,
25 25 Prueba por varias combinaciones de nombres entre mayusculas y minusculas para determinar
26 26 el path exacto de un determinado file.
27 27
28 28 Example :
29 29 nombre correcto del file es .../.../D2009307/P2009307367.ext
30 30
31 31 Entonces la funcion prueba con las siguientes combinaciones
32 32 .../.../x2009307/y2009307367.ext
33 33 .../.../x2009307/Y2009307367.ext
34 34 .../.../X2009307/y2009307367.ext
35 35 .../.../X2009307/Y2009307367.ext
36 36 siendo para este caso, la ultima combinacion de letras, identica al file buscado
37 37
38 38 Return:
39 39 Si encuentra la cobinacion adecuada devuelve el path completo y el nombre del file
40 40 caso contrario devuelve None como path y el la ultima combinacion de nombre en mayusculas
41 41 para el filename
42 42 """
43 43 filepath = None
44 44 find_flag = False
45 45 filename = None
46 46
47 47 if ext.lower() == ".r": #voltage
48 48 header1 = "dD"
49 49 header2 = "dD"
50 50 elif ext.lower() == ".pdata": #spectra
51 51 header1 = "dD"
52 52 header2 = "pP"
53 53 else:
54 54 return None, filename
55 55
56 56 for dir in header1: #barrido por las dos combinaciones posibles de "D"
57 57 for fil in header2: #barrido por las dos combinaciones posibles de "D"
58 58 doypath = "%s%04d%03d" % ( dir, year, doy ) #formo el nombre del directorio xYYYYDDD (x=d o x=D)
59 59 filename = "%s%04d%03d%03d%s" % ( fil, year, doy, set, ext ) #formo el nombre del file xYYYYDDDSSS.ext
60 60 filepath = os.path.join( path, doypath, filename ) #formo el path completo
61 61 if os.path.exists( filepath ): #verifico que exista
62 62 find_flag = True
63 63 break
64 64 if find_flag:
65 65 break
66 66
67 67 if not(find_flag):
68 68 return None, filename
69 69
70 70 return filepath, filename
71 71
72 72
73 73 def isNumber(str):
74 74 """
75 75 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
76 76
77 77 Excepciones:
78 78 Si un determinado string no puede ser convertido a numero
79 79 Input:
80 80 str, string al cual se le analiza para determinar si convertible a un numero o no
81 81
82 82 Return:
83 83 True : si el string es uno numerico
84 84 False : no es un string numerico
85 85 """
86 86 try:
87 87 float( str )
88 88 return True
89 89 except:
90 90 return False
91 91
92 92
93 93 def isThisFileinRange(filename, startUTSeconds, endUTSeconds):
94 94 """
95 95 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
96 96
97 97 Inputs:
98 98 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
99 99
100 100 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
101 101 segundos contados desde 01/01/1970.
102 102 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
103 103 segundos contados desde 01/01/1970.
104 104
105 105 Return:
106 106 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
107 107 fecha especificado, de lo contrario retorna False.
108 108
109 109 Excepciones:
110 110 Si el archivo no existe o no puede ser abierto
111 111 Si la cabecera no puede ser leida.
112 112
113 113 """
114 114 m_BasicHeader = BasicHeader()
115 115
116 116 try:
117 117 fp = open(filename,'rb')
118 118 except:
119 119 raise IOError, "The file %s can't be opened" %(filename)
120 120
121 121 sts = m_BasicHeader.read(fp)
122 122 fp.close()
123 123
124 124 if not(sts):
125 125 print "Skipping the file %s because it has not a valid header" %(filename)
126 126 return 0
127 127
128 128 if not ((startUTSeconds <= m_BasicHeader.utc) and (endUTSeconds > m_BasicHeader.utc)):
129 129 return 0
130 130
131 131 return 1
132 132
133 133
134 134 def getlastFileFromPath(path, ext):
135 135 """
136 136 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
137 137 al final de la depuracion devuelve el ultimo file de la lista que quedo.
138 138
139 139 Input:
140 140 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
141 141 ext : extension de los files contenidos en una carpeta
142 142
143 143 Return:
144 144 El ultimo file de una determinada carpeta, no se considera el path.
145 145 """
146 146 validFilelist = []
147 147 fileList = os.listdir(path)
148 148
149 149 # 0 1234 567 89A BCDE
150 150 # H YYYY DDD SSS .ext
151 151
152 152 for file in fileList:
153 153 try:
154 154 year = int(file[1:5])
155 155 doy = int(file[5:8])
156 156
157 157 if (os.path.splitext(file)[-1].upper() != ext.upper()) : continue
158 158 except:
159 159 continue
160 160
161 161 validFilelist.append(file)
162 162
163 163 if validFilelist:
164 164 validFilelist = sorted( validFilelist, key=str.lower )
165 165 return validFilelist[-1]
166 166
167 167 return None
168 168
169 169
170 170 class DataReader():
171 171
172 172 def __init__(self):
173 173 pass
174 174
175 175
176 176 class DataWriter():
177 177
178 178 def __init__(self):
179 179 pass
180 180
181 181
182 182 class JRODataReader(DataReader):
183 183
184 184 """
185 185 Esta clase es usada como la clase padre de las clases DataReader,
186 186 contiene todos lo metodos necesarios para leer datos desde archivos en formato
187 187 jicamarca o pdata (.r o .pdata). La lectura de los datos siempre se realiza por bloques. Los datos
188 188 leidos son array de 3 dimensiones:
189 189
190 190 Para Voltajes - perfiles * alturas * canales
191 191
192 192 Para Spectra - paresCanalesIguales * alturas * perfiles (Self Spectra)
193 193 paresCanalesDiferentes * alturas * perfiles (Cross Spectra)
194 194 canales * alturas (DC Channels)
195 195
196 196 y son almacenados en su buffer respectivo.
197 197
198 198 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
199 199 RadarControllerHeader y DataObj. Los tres primeros se usan para almacenar informacion de la
200 200 cabecera de datos (metadata), y el cuarto (DataObj) para obtener y almacenar los datos desde
201 201 el buffer cada vez que se ejecute el metodo "getData".
202 202 """
203 203
204 204 m_BasicHeader = BasicHeader()
205 205
206 206 m_SystemHeader = SystemHeader()
207 207
208 208 m_RadarControllerHeader = RadarControllerHeader()
209 209
210 210 m_ProcessingHeader = ProcessingHeader()
211 211
212 m_DataObj = None
213
214 heightList = None
215
212 216 online = 0
213 217
214 218 fp = None
215 219
216 220 fileSizeByHeader = None
217 221
218 222 filenameList = []
219 223
220 224 filename = None
221 225
222 226 fileSize = None
223 227
224 228 firstHeaderSize = 0
225 229
226 230 basicHeaderSize = 24
227 231
228 232 dataType = None
229 233
230 234 maxTimeStep = 30
231 235
232 236 flagNoMoreFiles = 0
233 237
234 238 set = 0
235 239
236 240 ext = None
237 241
238 242 path = None
239 243
240 244 delay = 3 #seconds
241 245
242 246 nTries = 3 #quantity tries
243 247
244 248 nFiles = 3 #number of files for searching
245 249
246 250 nBlocks = 0
247 251
248 252 flagIsNewFile = 1
249 253
250 254 ippSeconds = 0
251 255
252 256 flagResetProcessing = 0
253 257
254 258 flagIsNewBlock = 0
255 259
256 260 nReadBlocks = 0
257 261
258 262 blocksize = 0
259 263
260 264 datablockIndex = 9999
261
265
266
262 267 #speed of light
263 268 c = 3E8
264 269
270 def __init__(self, m_DataObj=None):
271 raise ValueError, "This class can't be instanced"
272
273
274
275
276
277 def hasNotDataInBuffer(self):
278 raise ValueError, "Not implemented"
279
280
281 def readBlock(self):
282 raise ValueError, "This method has not been implemented"
283
284 def getData( self ):
285 raise ValueError, "This method has not been implemented"
265 286
266 287 def __rdSystemHeader(self, fp=None):
267 288
268 289 if fp == None:
269 290 fp = self.fp
270 291
271 292 self.m_SystemHeader.read(fp)
272 293
273 294
274 295 def __rdRadarControllerHeader(self, fp=None):
275 296 if fp == None:
276 297 fp = self.fp
277 298
278 299 self.m_RadarControllerHeader.read(fp)
279 300
280 301
281 302 def __rdProcessingHeader(self, fp=None):
282 303 if fp == None:
283 304 fp = self.fp
284 305
285 306 self.m_ProcessingHeader.read(fp)
286 307
287 308
288 309 def __rdBasicHeader(self, fp=None):
289 310
290 311 if fp == None:
291 312 fp = self.fp
292 313
293 314 self.m_BasicHeader.read(fp)
294 315
295
316 def getBlockDimension(self):
317 raise ValueError, "No implemented"
318
296 319 def __readFirstHeader(self):
297 320 """
298 321 Lectura del First Header, es decir el Basic Header y el Long Header
299 322
300 323 Affected:
301 324 self.m_BasicHeader
302 325 self.m_SystemHeader
303 326 self.m_RadarControllerHeader
304 327 self.m_ProcessingHeader
305 328 self.firstHeaderSize
306 self.heights
329 self.heightList
307 330 self.dataType
308 331 self.fileSizeByHeader
309 332 self.ippSeconds
310 333
311 334 Return:
312 335 None
313 336 """
314 337 self.__rdBasicHeader()
315 338 self.__rdSystemHeader()
316 339 self.__rdRadarControllerHeader()
317 340 self.__rdProcessingHeader()
318 341 self.firstHeaderSize = self.m_BasicHeader.size
319 342
320 343 data_type=int(numpy.log2((self.m_ProcessingHeader.processFlags & PROCFLAG.DATATYPE_MASK))-numpy.log2(PROCFLAG.DATATYPE_CHAR))
321 344 if data_type == 0:
322 345 tmp = numpy.dtype([('real','<i1'),('imag','<i1')])
323 346
324 347 elif data_type == 1:
325 348 tmp = numpy.dtype([('real','<i2'),('imag','<i2')])
326 349
327 350 elif data_type == 2:
328 351 tmp = numpy.dtype([('real','<i4'),('imag','<i4')])
329 352
330 353 elif data_type == 3:
331 354 tmp = numpy.dtype([('real','<i8'),('imag','<i8')])
332 355
333 356 elif data_type == 4:
334 357 tmp = numpy.dtype([('real','<f4'),('imag','<f4')])
335 358
336 359 elif data_type == 5:
337 360 tmp = numpy.dtype([('real','<f8'),('imag','<f8')])
338 361
339 362 else:
340 363 raise ValueError, 'Data type was not defined'
341 364
342 365 xi = self.m_ProcessingHeader.firstHeight
343 366 step = self.m_ProcessingHeader.deltaHeight
344 367 xf = xi + self.m_ProcessingHeader.numHeights*step
345 368
346 self.heights = numpy.arange(xi, xf, step)
369 self.heightList = numpy.arange(xi, xf, step)
370 self.channelList = numpy.arange(self.m_SystemHeader.numChannels)
347 371 self.dataType = tmp
348 372 self.fileSizeByHeader = self.m_ProcessingHeader.dataBlocksPerFile * self.m_ProcessingHeader.blockSize + self.firstHeaderSize + self.basicHeaderSize*(self.m_ProcessingHeader.dataBlocksPerFile - 1)
349 373 self.ippSeconds = 2 * 1000 * self.m_RadarControllerHeader.ipp / self.c
350 374
351 375 self.getBlockDimension()
352 376
353 377
354 378 def __setNextFileOnline(self):
355 379 """
356 380 Busca el siguiente file que tenga suficiente data para ser leida, dentro de un folder especifico, si
357 381 no encuentra un file valido espera un tiempo determinado y luego busca en los posibles n files
358 382 siguientes.
359 383
360 384 Affected:
361 385 self.flagIsNewFile
362 386 self.filename
363 387 self.fileSize
364 388 self.fp
365 389 self.set
366 390 self.flagNoMoreFiles
367 391
368 392 Return:
369 393 0 : si luego de una busqueda del siguiente file valido este no pudo ser encontrado
370 394 1 : si el file fue abierto con exito y esta listo a ser leido
371 395
372 396 Excepciones:
373 397 Si un determinado file no puede ser abierto
374 398 """
375 399 nFiles = 0
376 400 fileOk_flag = False
377 401 firstTime_flag = True
378 402
379 403 self.set += 1
380 404
381 405 #busca el 1er file disponible
382 406 file, filename = checkForRealPath( self.path, self.year, self.doy, self.set, self.ext )
383 407 if file:
384 408 if self.__verifyFile(file, False):
385 409 fileOk_flag = True
386 410
387 411 #si no encuentra un file entonces espera y vuelve a buscar
388 412 if not(fileOk_flag):
389 413 for nFiles in range(self.nFiles+1): #busco en los siguientes self.nFiles+1 files posibles
390 414
391 415 if firstTime_flag: #si es la 1era vez entonces hace el for self.nTries veces
392 416 tries = self.nTries
393 417 else:
394 418 tries = 1 #si no es la 1era vez entonces solo lo hace una vez
395 419
396 420 for nTries in range( tries ):
397 421 if firstTime_flag:
398 422 print "\tWaiting %0.2f sec for new \"%s\" file, try %03d ..." % ( self.delay, filename, nTries+1 )
399 423 time.sleep( self.delay )
400 424 else:
401 425 print "\tSearching next \"%s%04d%03d%03d%s\" file ..." % (self.optchar, self.year, self.doy, self.set, self.ext)
402 426
403 427 file, filename = checkForRealPath( self.path, self.year, self.doy, self.set, self.ext )
404 428 if file:
405 429 if self.__verifyFile(file):
406 430 fileOk_flag = True
407 431 break
408 432
409 433 if fileOk_flag:
410 434 break
411 435
412 436 firstTime_flag = False
413 437
414 438 print "\tSkipping the file \"%s\" due to this file doesn't exist yet" % filename
415 439 self.set += 1
416 440
417 441 if nFiles == (self.nFiles-1): #si no encuentro el file buscado cambio de carpeta y busco en la siguiente carpeta
418 442 self.set = 0
419 443 self.doy += 1
420 444
421 445 if fileOk_flag:
422 446 self.fileSize = os.path.getsize( file )
423 447 self.filename = file
424 448 self.flagIsNewFile = 1
425 449 if self.fp != None: self.fp.close()
426 450 self.fp = open(file)
427 451 self.flagNoMoreFiles = 0
428 452 print 'Setting the file: %s' % file
429 453 else:
430 454 self.fileSize = 0
431 455 self.filename = None
432 456 self.flagIsNewFile = 0
433 457 self.fp = None
434 458 self.flagNoMoreFiles = 1
435 459 print 'No more Files'
436 460
437 461 return fileOk_flag
438 462
439 463
440 464 def __setNextFileOffline(self):
441 465 """
442 466 Busca el siguiente file dentro de un folder que tenga suficiente data para ser leida
443 467
444 468 Affected:
445 469 self.flagIsNewFile
446 470 self.fileIndex
447 471 self.filename
448 472 self.fileSize
449 473 self.fp
450 474
451 475 Return:
452 476 0 : si un determinado file no puede ser abierto
453 477 1 : si el file fue abierto con exito
454 478
455 479 Excepciones:
456 480 Si un determinado file no puede ser abierto
457 481 """
458 482 idFile = self.fileIndex
459 483 while(True):
460 484
461 485 idFile += 1
462 486
463 487 if not(idFile < len(self.filenameList)):
464 488 self.flagNoMoreFiles = 1
465 489 print 'No more Files'
466 490 return 0
467 491
468 492 filename = self.filenameList[idFile]
469 493 fileSize = os.path.getsize(filename)
470 494
471 495 try:
472 496 fp = open(filename,'rb')
473 497 except:
474 498 raise IOError, "The file %s can't be opened" %filename
475 499
476 500 currentSize = fileSize - fp.tell()
477 501 neededSize = self.m_ProcessingHeader.blockSize + self.firstHeaderSize
478 502
479 503 if (currentSize < neededSize):
480 504 print "Skipping the file %s due to it hasn't enough data" %filename
481 505 continue
482 506
483 507 break
484 508
485 509 self.flagIsNewFile = 1
486 510 self.fileIndex = idFile
487 511 self.filename = filename
488 512 self.fileSize = fileSize
489 513 self.fp = fp
490 514
491 515 print 'Setting the file: %s'%self.filename
492 516
493 517 return 1
494 518
495 519
496 520 def setNextFile(self):
497 521 """
498 522 Determina el siguiente file a leer y si hay uno disponible lee el First Header
499 523
500 524 Affected:
501 525 self.m_BasicHeader
502 526 self.m_SystemHeader
503 527 self.m_RadarControllerHeader
504 528 self.m_ProcessingHeader
505 529 self.firstHeaderSize
506 530
507 531 Return:
508 532 0 : Si no hay files disponibles
509 533 1 : Si hay mas files disponibles
510 534 """
511 535 if self.fp != None:
512 536 self.fp.close()
513 537
514 538 if self.online:
515 539 newFile = self.__setNextFileOnline()
516 540 else:
517 541 newFile = self.__setNextFileOffline()
518 542
519 543 if self.flagNoMoreFiles:
520 544 sys.exit(0)
521 545
522 546 if not(newFile):
523 547 return 0
524 548
525 549 self.__readFirstHeader()
526 550 self.nBlocks = 0
527 551 return 1
528 552
529 553
530 554 def __setNewBlock(self):
531 555 """
532 556 Lee el Basic Header y posiciona le file pointer en la posicion inicial del bloque a leer
533 557
534 558 Affected:
535 559 self.m_BasicHeader
536 560 self.flagNoContinuousBlock
537 561 self.ns
538 562
539 563 Return:
540 564 0 : Si el file no tiene un Basic Header que pueda ser leido
541 565 1 : Si se pudo leer el Basic Header
542 566 """
543 567 if self.fp == None:
544 568 return 0
545 569
546 570 if self.flagIsNewFile:
547 571 return 1
548 572
549 573 currentSize = self.fileSize - self.fp.tell()
550 574 neededSize = self.m_ProcessingHeader.blockSize + self.basicHeaderSize
551 575
552 576 #If there is enough data setting new data block
553 577 if ( currentSize >= neededSize ):
554 578 self.__rdBasicHeader()
555 579 return 1
556 580
557 581 #si es OnLine y ademas aun no se han leido un bloque completo entonces se espera por uno valido
558 582 elif (self.nBlocks != self.m_ProcessingHeader.dataBlocksPerFile) and self.online:
559 583 for nTries in range( self.nTries ):
560 584
561 585 fpointer = self.fp.tell()
562 586 self.fp.close()
563 587
564 588 print "\tWaiting %0.2f sec for the next block, try %03d ..." % (self.delay, nTries+1)
565 589 time.sleep( self.delay )
566 590
567 591 self.fp = open( self.filename, 'rb' )
568 592 self.fp.seek( fpointer )
569 593
570 594 self.fileSize = os.path.getsize( self.filename )
571 595 currentSize = self.fileSize - self.fp.tell()
572 596 neededSize = self.m_ProcessingHeader.blockSize + self.basicHeaderSize
573 597
574 598 if ( currentSize >= neededSize ):
575 599 self.__rdBasicHeader()
576 600 return 1
577 601
578 602 #Setting new file
579 603 if not( self.setNextFile() ):
580 604 return 0
581 605
582 606 deltaTime = self.m_BasicHeader.utc - self.lastUTTime # check this
583 607
584 608 self.flagResetProcessing = 0
585 609
586 610 if deltaTime > self.maxTimeStep:
587 611 self.flagResetProcessing = 1
588 612 #self.nReadBlocks = 0
589 613
590 614 return 1
591 615
592 616
593 617 def __searchFilesOnLine(self, path, startDateTime=None, endDateTime=None, expLabel = "", ext = None):
594 618 """
595 619 Busca el ultimo archivo de la ultima carpeta (determinada o no por startDateTime) y
596 620 devuelve el archivo encontrado ademas de otros datos.
597 621
598 622 Input:
599 623 path : carpeta donde estan contenidos los files que contiene data
600 624 startDateTime : punto especifico en el tiempo del cual se requiere la data
601 625 ext : extension de los files
602 626
603 627 Return:
604 628 year : el anho
605 629 doy : el numero de dia del anho
606 630 set : el set del archivo
607 631 filename : el ultimo file de una determinada carpeta
608 632 directory : eL directorio donde esta el file encontrado
609 633 """
610 634 dirList = []
611 635 pathList = []
612 636 directory = None
613 637
614 638 for thisPath in os.listdir(path):
615 639 if os.path.isdir(os.path.join(path,thisPath)):
616 640 dirList.append(thisPath)
617 641
618 642 if not(dirList):
619 643 return None, None, None, None, None
620 644
621 645 dirList = sorted( dirList, key=str.lower )
622 646
623 647 if startDateTime:
624 648 thisDateTime = startDateTime
625 649 if endDateTime == None: endDateTime = startDateTime
626 650
627 651 while(thisDateTime <= endDateTime):
628 652 year = thisDateTime.timetuple().tm_year
629 653 doy = thisDateTime.timetuple().tm_yday
630 654
631 655 match = fnmatch.filter(dirList, '?' + '%4.4d%3.3d' % (year,doy))
632 656 if len(match) == 0:
633 657 thisDateTime += datetime.timedelta(1)
634 658 continue
635 659
636 660 pathList.append(os.path.join(path,match[0], expLabel))
637 661 thisDateTime += datetime.timedelta(1)
638 662
639 663 if not(pathList):
640 664 print "\tNo files in range: %s - %s" %(startDateTime.ctime(), endDateTime.ctime())
641 665 return None, None, None, None, None
642 666
643 667 directory = pathList[0]
644 668
645 669 else:
646 670 directory = dirList[-1]
647 671 directory = os.path.join(path,directory)
648 672
649 673 filename = getlastFileFromPath(directory, ext)
650 674
651 675 if not(filename):
652 676 return None, None, None, None, None
653 677
654 678 if not(self.__verifyFile(os.path.join(directory, filename))):
655 679 return None, None, None, None, None
656 680
657 681 year = int( filename[1:5] )
658 682 doy = int( filename[5:8] )
659 683 set = int( filename[8:11] )
660 684
661 685 return directory, filename, year, doy, set
662 686
663 687
664 688 def __searchFilesOffLine(self, path, startDateTime, endDateTime, set=None, expLabel = "", ext = ".r"):
665 689 """
666 690 Realiza una busqueda de los archivos que coincidan con los parametros
667 691 especificados y se encuentren ubicados en el path indicado. Para realizar una busqueda
668 692 correcta la estructura de directorios debe ser la siguiente:
669 693
670 694 ...path/D[yyyy][ddd]/expLabel/D[yyyy][ddd][sss].ext
671 695
672 696 [yyyy]: anio
673 697 [ddd] : dia del anio
674 698 [sss] : set del archivo
675 699
676 700 Inputs:
677 701 path : Directorio de datos donde se realizara la busqueda. Todos los
678 702 ficheros que concidan con el criterio de busqueda seran
679 703 almacenados en una lista y luego retornados.
680 704 startDateTime : Fecha inicial. Rechaza todos los archivos donde
681 705 file end time < startDateTime (obejto datetime.datetime)
682 706
683 707 endDateTime : Fecha final. Rechaza todos los archivos donde
684 708 file start time > endDateTime (obejto datetime.datetime)
685 709
686 710 set : Set del primer archivo a leer. Por defecto None
687 711
688 712 expLabel : Nombre del subdirectorio de datos. Por defecto ""
689 713
690 714 ext : Extension de los archivos a leer. Por defecto .r
691 715
692 716 Return:
693 717
694 718 (pathList, filenameList)
695 719
696 720 pathList : Lista de directorios donde se encontraron archivos dentro
697 721 de los parametros especificados
698 722 filenameList : Lista de archivos (ruta completa) que coincidieron con los
699 723 parametros especificados.
700 724
701 725 Variables afectadas:
702 726
703 727 self.filenameList: Lista de archivos (ruta completa) que la clase utiliza
704 728 como fuente para leer los bloque de datos, si se termina
705 729 de leer todos los bloques de datos de un determinado
706 730 archivo se pasa al siguiente archivo de la lista.
707 731
708 732 Excepciones:
709 733
710 734 """
711 735
712 736 print "Searching files ..."
713 737
714 738 dirList = []
715 739 for thisPath in os.listdir(path):
716 740 if os.path.isdir(os.path.join(path,thisPath)):
717 741 dirList.append(thisPath)
718 742
719 743 if not(dirList):
720 744 return None, None
721 745
722 746 pathList = []
723 747
724 748 thisDateTime = startDateTime
725 749
726 750 while(thisDateTime <= endDateTime):
727 751 year = thisDateTime.timetuple().tm_year
728 752 doy = thisDateTime.timetuple().tm_yday
729 753
730 754 match = fnmatch.filter(dirList, '?' + '%4.4d%3.3d' % (year,doy))
731 755 if len(match) == 0:
732 756 thisDateTime += datetime.timedelta(1)
733 757 continue
734 758
735 759 pathList.append(os.path.join(path,match[0],expLabel))
736 760 thisDateTime += datetime.timedelta(1)
737 761
738 762 startUtSeconds = time.mktime(startDateTime.timetuple())
739 763 endUtSeconds = time.mktime(endDateTime.timetuple())
740 764
741 765 filenameList = []
742 766 for thisPath in pathList:
743 767 fileList = glob.glob1(thisPath, "*%s" %ext)
744 768 fileList.sort()
745 769 for file in fileList:
746 770 filename = os.path.join(thisPath,file)
747 771 if isThisFileinRange(filename, startUtSeconds, endUtSeconds):
748 772 filenameList.append(filename)
749 773
750 774 if not(filenameList):
751 775 return None, None
752 776
753 777 self.filenameList = filenameList
754 778
755 779 return pathList, filenameList
756 780
757 781
758 782 def __verifyFile(self, filename, msgFlag=True):
759 783 """
760 784 Verifica que el filename tenga data valida, para ello leo el FirstHeader del file
761 785
762 786 Return:
763 787 0 : file no valido para ser leido
764 788 1 : file valido para ser leido
765 789 """
766 790 m_BasicHeader = BasicHeader()
767 791 m_SystemHeader = SystemHeader()
768 792 m_RadarControllerHeader = RadarControllerHeader()
769 793 m_ProcessingHeader = ProcessingHeader()
770 794 flagFileOK = False
771 795
772 796 try:
773 797 fp = open( filename,'rb' ) #lectura binaria
774 798 except:
775 799 if msgFlag:
776 800 print "The file %s can't be opened" % (filename)
777 801
778 802 try:
779 803 if not( m_BasicHeader.read(fp) ): raise ValueError
780 804 if not( m_SystemHeader.read(fp) ): raise ValueError
781 805 if not( m_RadarControllerHeader.read(fp) ): raise ValueError
782 806 if not( m_ProcessingHeader.read(fp) ): raise ValueError
783 807 data_type = int(numpy.log2((m_ProcessingHeader.processFlags & PROCFLAG.DATATYPE_MASK))-numpy.log2(PROCFLAG.DATATYPE_CHAR))
784 808 if m_BasicHeader.size > self.basicHeaderSize:
785 809 flagFileOK = True
786 810 except:
787 811 if msgFlag:
788 812 print "\tThe file %s is empty or it hasn't enough data" % filename
789 813
790 814 fp.close()
791 815
792 816 if not(flagFileOK):
793 817 return 0
794 818
795 819 return 1
796 820
797 821
798 822 def setup(self, path, startDateTime=None, endDateTime=None, set=0, expLabel = "", ext = None, online = 0):
799 823 """
800 824 setup configura los parametros de lectura de la clase DataReader.
801 825
802 826 Si el modo de lectura es offline, primero se realiza una busqueda de todos los archivos
803 827 que coincidan con los parametros especificados; esta lista de archivos son almacenados en
804 828 self.filenameList.
805 829
806 830 Input:
807 831 path : Directorios donde se ubican los datos a leer. Dentro de este
808 832 directorio deberia de estar subdirectorios de la forma:
809 833
810 834 path/D[yyyy][ddd]/expLabel/P[yyyy][ddd][sss][ext]
811 835
812 836 startDateTime : Fecha inicial. Rechaza todos los archivos donde
813 837 file end time < startDatetime (obejto datetime.datetime)
814 838
815 839 endDateTime : Fecha final. Si no es None, rechaza todos los archivos donde
816 840 file end time < startDatetime (obejto datetime.datetime)
817 841
818 842 set : Set del primer archivo a leer. Por defecto None
819 843
820 844 expLabel : Nombre del subdirectorio de datos. Por defecto ""
821 845
822 846 ext : Extension de los archivos a leer. Por defecto .r
823 847
824 848 online : Si es == a 0 entonces busca files que cumplan con las condiciones dadas
825 849
826 850 Return:
827 851 0 : Si no encuentra files que cumplan con las condiciones dadas
828 852 1 : Si encuentra files que cumplan con las condiciones dadas
829 853
830 854 Affected:
831 855 self.startUTCSeconds
832 856 self.endUTCSeconds
833 857 self.startYear
834 858 self.endYear
835 859 self.startDoy
836 860 self.endDoy
837 861 self.pathList
838 862 self.filenameList
839 863 self.online
840 864 """
841 865
842 866 if ext == None:
843 867 ext = self.ext
844 868
845 869 if online:
846 870 print "Searching files ..."
847 871 doypath, file, year, doy, set = self.__searchFilesOnLine(path, startDateTime, endDateTime, expLabel, ext)
848 872
849 873 if not(doypath):
850 874 for nTries in range( self.nTries ):
851 875 print '\tWaiting %0.2f sec for valid file in %s: try %02d ...' % (self.delay, path, nTries+1)
852 876 time.sleep( self.delay )
853 877 doypath, file, year, doy, set = self.__searchFilesOnLine(path, startDateTime, endDateTime, expLabel, ext)
854 878 if doypath:
855 879 break
856 880
857 881 if not(doypath):
858 882 print "There 'isn't valied files in %s" % path
859 883 return 0
860 884
861 885 self.year = year
862 886 self.doy = doy
863 887 self.set = set - 1
864 888 self.path = path
865 889
866 890 else: # offline
867 891 pathList, filenameList = self.__searchFilesOffLine(path, startDateTime, endDateTime, set, expLabel, ext)
868 892 if not(pathList):
869 893 print "No files in range: %s - %s" %(startDateTime.ctime(), endDateTime.ctime())
870 894 return 0
871 895
872 896 self.fileIndex = -1
873 897 self.pathList = pathList
874 898 self.filenameList = filenameList
875 899
876 900 self.online = online
877 901 self.ext = ext
878 902
879 903 ext = ext.lower()
880 904
881 905 if not( self.setNextFile() ):
882 906 if (startDateTime != None) and (endDateTime != None):
883 907 print "No files in range: %s - %s" %(startDateTime.ctime(), endDateTime.ctime())
884 908 elif startDateTime != None:
885 909 print "No files in : %s" % startDateTime.ctime()
886 910 else:
887 911 print "No files"
888 912 return 0
889 913
890 914 if startDateTime != None:
891 915 self.startUTCSeconds = time.mktime(startDateTime.timetuple())
892 916 self.startYear = startDateTime.timetuple().tm_year
893 917 self.startDoy = startDateTime.timetuple().tm_yday
894 918
895 919 if endDateTime != None:
896 920 self.endUTCSeconds = time.mktime(endDateTime.timetuple())
897 921 self.endYear = endDateTime.timetuple().tm_year
898 922 self.endDoy = endDateTime.timetuple().tm_yday
899 923 #call fillHeaderValues() - to Data Object
900 924
901 925 self.m_DataObj.m_BasicHeader = self.m_BasicHeader.copy()
902 926 self.m_DataObj.m_ProcessingHeader = self.m_ProcessingHeader.copy()
903 927 self.m_DataObj.m_RadarControllerHeader = self.m_RadarControllerHeader.copy()
904 928 self.m_DataObj.m_SystemHeader = self.m_SystemHeader.copy()
905 929 self.m_DataObj.dataType = self.dataType
906 930
907 931 return 1
908 932
909 933
910 934 def readNextBlock(self):
911 935 """
912 936 Establece un nuevo bloque de datos a leer y los lee, si es que no existiese
913 937 mas bloques disponibles en el archivo actual salta al siguiente.
914 938
915 939 Affected:
916 940 self.lastUTTime
917 941
918 942 Return: None
919 943 """
920 944 if not(self.__setNewBlock()):
921 945 return 0
922 946
923 947 if not(self.readBlock()):
924 948 return 0
925 949
926 950 self.lastUTTime = self.m_BasicHeader.utc
927 951
928 952 return 1
929 953
930 954
931 955 class JRODataWriter(DataWriter):
932 956
933 957 """
934 958 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
935 959 de los datos siempre se realiza por bloques.
936 960 """
937
961
962 m_BasicHeader = BasicHeader()
963
964 m_SystemHeader = SystemHeader()
965
966 m_RadarControllerHeader = RadarControllerHeader()
967
968 m_ProcessingHeader = ProcessingHeader()
969
938 970 fp = None
939 971
940 972 blocksCounter = 0
941 973
942 974 flagIsNewFile = 1
943 975
944 976 nWriteBlocks = 0
945 977
946 978 flagIsNewBlock = 0
947 979
948 980 flagNoMoreFiles = 0
949 981
982 m_DataObj = None
983
984 fp = None
985
986 blocksCounter = 0
987
988 flagIsNewFile = 1
989
990 nWriteBlocks = 0
991
992 flagIsNewBlock = 0
993
994 flagNoMoreFiles = 0
995
996 setFile = None
997
998 dataType = None
999
1000 path = None
1001
1002 noMoreFiles = 0
1003
1004 filename = None
1005
1006 m_BasicHeader = None
1007
1008 m_SystemHeader = None
1009
1010 m_RadarControllerHeader = None
1011
1012 m_ProcessingHeader = None
1013
1014
1015 def __init__(self, m_DataObj=None):
1016 raise ValueError, "Not implemented"
1017
1018
1019 def hasAllDataInBuffer(self):
1020 raise ValueError, "Not implemented"
1021
1022
1023 def setBlockDimension(self):
1024 raise ValueError, "Not implemented"
1025
1026
1027 def writeBlock(self):
1028 raise ValueError, "No implemented"
1029
1030
1031 def putData(self):
1032 raise ValueError, "No implemented"
1033
950 1034
951 1035 def __writeFirstHeader(self):
952 1036 """
953 1037 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
954 1038
955 1039 Affected:
956 1040 __dataType
957 1041
958 1042 Return:
959 1043 None
960 1044 """
961 1045 self.__writeBasicHeader()
962 1046 self.__wrSystemHeader()
963 1047 self.__wrRadarControllerHeader()
964 1048 self.__wrProcessingHeader()
965 1049 self.dataType = self.m_DataObj.dataType
966 1050
967 1051
968 1052 def __writeBasicHeader(self, fp=None):
969 1053 """
970 1054 Escribe solo el Basic header en el file creado
971 1055
972 1056 Return:
973 1057 None
974 1058 """
975 1059 if fp == None:
976 1060 fp = self.fp
977 1061
978 1062 self.m_DataObj.m_BasicHeader.write(fp)
979 1063
980 1064
981 1065 def __wrSystemHeader(self, fp=None):
982 1066 """
983 1067 Escribe solo el System header en el file creado
984 1068
985 1069 Return:
986 1070 None
987 1071 """
988 1072 if fp == None:
989 1073 fp = self.fp
990 1074
991 1075 self.m_DataObj.m_SystemHeader.write(fp)
992 1076
993 1077
994 1078 def __wrRadarControllerHeader(self, fp=None):
995 1079 """
996 1080 Escribe solo el RadarController header en el file creado
997 1081
998 1082 Return:
999 1083 None
1000 1084 """
1001 1085 if fp == None:
1002 1086 fp = self.fp
1003 1087
1004 1088 self.m_DataObj.m_RadarControllerHeader.write(fp)
1005 1089
1006 1090
1007 1091 def __wrProcessingHeader(self, fp=None):
1008 1092 """
1009 1093 Escribe solo el Processing header en el file creado
1010 1094
1011 1095 Return:
1012 1096 None
1013 1097 """
1014 1098 if fp == None:
1015 1099 fp = self.fp
1016 1100
1017 1101 self.m_DataObj.m_ProcessingHeader.write(fp)
1018 1102
1019 1103
1020 1104 def setNextFile(self):
1021 1105 """
1022 1106 Determina el siguiente file que sera escrito
1023 1107
1024 1108 Affected:
1025 1109 self.filename
1026 1110 self.subfolder
1027 1111 self.fp
1028 1112 self.setFile
1029 1113 self.flagIsNewFile
1030 1114
1031 1115 Return:
1032 1116 0 : Si el archivo no puede ser escrito
1033 1117 1 : Si el archivo esta listo para ser escrito
1034 1118 """
1035 1119 ext = self.ext
1036 1120 path = self.path
1037 1121
1038 1122 if self.fp != None:
1039 1123 self.fp.close()
1040 1124
1041 1125 timeTuple = time.localtime( self.m_DataObj.m_BasicHeader.utc )
1042 1126 subfolder = 'D%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
1043 1127
1044 1128 tmp = os.path.join( path, subfolder )
1045 1129 if not( os.path.exists(tmp) ):
1046 1130 os.mkdir(tmp)
1047 1131 self.setFile = -1 #inicializo mi contador de seteo
1048 1132 else:
1049 1133 filesList = os.listdir( tmp )
1050 1134 if len( filesList ) > 0:
1051 1135 filesList = sorted( filesList, key=str.lower )
1052 1136 filen = filesList[-1]
1053 1137 # el filename debera tener el siguiente formato
1054 1138 # 0 1234 567 89A BCDE (hex)
1055 1139 # x YYYY DDD SSS .ext
1056 1140 if isNumber( filen[8:11] ):
1057 1141 self.setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
1058 1142 else:
1059 1143 self.setFile = -1
1060 1144 else:
1061 1145 self.setFile = -1 #inicializo mi contador de seteo
1062 1146
1063 1147 setFile = self.setFile
1064 1148 setFile += 1
1065 1149
1066 1150 file = '%s%4.4d%3.3d%3.3d%s' % (self.optchar,
1067 1151 timeTuple.tm_year,
1068 1152 timeTuple.tm_yday,
1069 1153 setFile,
1070 1154 ext )
1071 1155
1072 1156 filename = os.path.join( path, subfolder, file )
1073 1157
1074 1158 fp = open( filename,'wb' )
1075 1159
1076 1160 self.blocksCounter = 0
1077 1161
1078 1162 #guardando atributos
1079 1163 self.filename = filename
1080 1164 self.subfolder = subfolder
1081 1165 self.fp = fp
1082 1166 self.setFile = setFile
1083 1167 self.flagIsNewFile = 1
1084 1168
1085 1169 print 'Writing the file: %s'%self.filename
1086 1170
1087 1171 self.__writeFirstHeader()
1088 1172
1089 1173 return 1
1090 1174
1091 1175
1092 1176 def __setNewBlock(self):
1093 1177 """
1094 1178 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1095 1179
1096 1180 Return:
1097 1181 0 : si no pudo escribir nada
1098 1182 1 : Si escribio el Basic el First Header
1099 1183 """
1100 1184 if self.fp == None:
1101 1185 self.setNextFile()
1102 1186
1103 1187 if self.flagIsNewFile:
1104 1188 return 1
1105 1189
1106 1190 if self.blocksCounter < self.m_ProcessingHeader.dataBlocksPerFile:
1107 1191 self.__writeBasicHeader()
1108 1192 return 1
1109 1193
1110 1194 if not( self.setNextFile() ):
1111 1195 return 0
1112 1196
1113 1197 return 1
1114 1198
1115 1199
1116 1200 def writeNextBlock(self):
1117 1201 """
1118 1202 Selecciona el bloque siguiente de datos y los escribe en un file
1119 1203
1120 1204 Return:
1121 1205 0 : Si no hizo pudo escribir el bloque de datos
1122 1206 1 : Si no pudo escribir el bloque de datos
1123 1207 """
1124 1208 if not( self.__setNewBlock() ):
1125 1209 return 0
1126 1210
1127 1211 self.writeBlock()
1128 1212
1129 1213 return 1
1130 1214
1131 1215
1132 1216 def getHeader(self):
1133 1217 """
1134 1218 Obtiene una copia del First Header
1135 1219
1136 1220 Affected:
1137 1221 self.m_BasicHeader
1138 1222 self.m_SystemHeader
1139 1223 self.m_RadarControllerHeader
1140 1224 self.m_ProcessingHeader
1141 1225 self.dataType
1142 1226
1143 1227 Return:
1144 1228 None
1145 1229 """
1146 1230 self.m_BasicHeader = self.m_DataObj.m_BasicHeader.copy()
1147 1231 self.m_SystemHeader = self.m_DataObj.m_SystemHeader.copy()
1148 1232 self.m_RadarControllerHeader = self.m_DataObj.m_RadarControllerHeader.copy()
1149 1233 self.m_ProcessingHeader = self.m_DataObj.m_ProcessingHeader.copy()
1150 1234 self.dataType = self.m_DataObj.dataType
1151 1235
1152 1236
1153 1237 def setup(self, path, set=0, ext=None):
1154 1238 """
1155 1239 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1156 1240
1157 1241 Inputs:
1158 1242 path : el path destino en el cual se escribiran los files a crear
1159 1243 format : formato en el cual sera salvado un file
1160 1244 set : el setebo del file
1161 1245
1162 1246 Return:
1163 1247 0 : Si no realizo un buen seteo
1164 1248 1 : Si realizo un buen seteo
1165 1249 """
1166 1250
1167 1251 if ext == None:
1168 1252 ext = self.ext
1169 1253
1170 1254 ext = ext.lower()
1171 1255
1172 1256 self.path = path
1173 1257 self.setFile = set - 1
1174 1258 self.ext = ext
1175 1259 #self.format = format
1176 1260 self.getHeader()
1177 1261
1178 1262 self.setBlockDimension()
1179 1263
1180 1264 if not( self.setNextFile() ):
1181 1265 print "There isn't a next file"
1182 1266 return 0
1183 1267
1184 1268 return 1
General Comments 0
You need to be logged in to leave comments. Login now