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