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