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