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