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