diff --git a/schainpy/IO/DataIO.py b/schainpy/IO/DataIO.py index 3e3d522..7ed5767 100644 --- a/schainpy/IO/DataIO.py +++ b/schainpy/IO/DataIO.py @@ -4,16 +4,1511 @@ Created on 23/01/2012 @author $Author$ @version $Id$ ''' +import os, sys +import glob +import time +import numpy +path = os.path.split(os.getcwd())[0] +sys.path.append(path) -class DataReader: - +from Model.JROHeader import * + +def checkForRealPath( path, year, doy, set, ext ): + """ + Por ser Linux Case Sensitive entonces checkForRealPath encuentra el nombre correcto de un path, + Prueba por varias combinaciones de nombres entre mayusculas y minusculas para determinar + el path exacto de un determinado file. + + Example : + nombre correcto del file es ../RAWDATA/D2009307/P2009307367 + + Entonces la funcion prueba con las siguientes combinaciones + ../RAWDATA/d2009307/p2009307367 + ../RAWDATA/d2009307/P2009307367 + ../RAWDATA/D2009307/p2009307367 + ../RAWDATA/D2009307/P2009307367 + siendo para este caso, la ultima combinacion de letras, identica al file buscado + + Return: + Si encuentra la cobinacion adecuada devuelve el path completo y el nombre del file + caso contrario devuelve None como path y el la ultima combinacion de nombre en mayusculas + para el filename + """ + filepath = None + find_flag = False + filename = None + + for dir in "dD": #barrido por las dos combinaciones posibles de "D" + for fil in "dD": #barrido por las dos combinaciones posibles de "D" + doypath = "%s%04d%03d" % ( dir, year, doy ) #formo el nombre del directorio xYYYYDDD (x=d o x=D) + filename = "%s%04d%03d%03d%s" % ( fil, year, doy, set, ext ) #formo el nombre del file xYYYYDDDSSS.ext (p=d o p=D) + filepath = os.path.join( path, doypath, filename ) #formo el path completo + if os.path.exists( filepath ): #verifico que exista + find_flag = True + break + if find_flag: + break + + if not(find_flag): + return None, filename + + return filepath, filename + + +def isNumber( str ): + """ + Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero. + + Excepciones: + Si un determinado string no puede ser convertido a numero + Input: + str, string al cual se le analiza para determinar si convertible a un numero o no + + Return: + True : si el string es uno numerico + False : no es un string numerico + """ + try: + float( str ) + return True + except: + return False + + +def isThisFileinRange(filename, startUTSeconds, endUTSeconds): + """ + Esta funcion determina si un archivo de datos en formato Jicamarca(.r) se encuentra + o no dentro del rango de fecha especificado. + + Inputs: + filename : nombre completo del archivo de datos en formato Jicamarca (.r) + + startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en + segundos contados desde 01/01/1970. + endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en + segundos contados desde 01/01/1970. + + Return: + Boolean : Retorna True si el archivo de datos contiene datos en el rango de + fecha especificado, de lo contrario retorna False. + + Excepciones: + Si el archivo no existe o no puede ser abierto + Si la cabecera no puede ser leida. + + """ + m_BasicHeader = BasicHeader() + + try: + fp = open(filename,'rb') + except: + raise IOError, "The file %s can't be opened" %(filename) + + if not(m_BasicHeader.read(fp)): + raise IOError, "The file %s has not a valid header" %(filename) + + fp.close() + + if not ((startUTSeconds <= m_BasicHeader.utc) and (endUTSeconds >= m_BasicHeader.utc)): + return 0 + + return 1 + + +def getlastFileFromPath( pathList, ext ): + """ + Depura el pathList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext" + al final de la depuracion devuelve el ultimo file de la lista que quedo. + + Input: + pathList : lista conteniendo todos los filename completos que componen una determinada carpeta + ext : extension de los files contenidos en una carpeta + + Return: + El ultimo file de una determinada carpeta + """ + + filesList = [] + filename = None + + # 0 1234 567 89A BCDE + # D YYYY DDD SSS .ext + + for filename in pathList: + year = filename[1:5] + doy = filename[5:8] + leng = len( ext ) + + if ( filename[-leng:].upper() != ext.upper() ) : continue + if not( isNumber( year ) ) : continue + if not( isNumber( doy ) ) : continue + + filesList.append(filename) + + if len( filesList ) > 0: + filesList = sorted( filesList, key=str.lower ) + filename = filesList[-1] + + return filename + + +class DataReader(): + def __init__(self): - __buffer = 0 - __buffer_count = 0 + pass + +class DataWriter(): + + def __init__(self): + pass + +class JRODataReader(): + + """ + Esta clase es usada como la clase padre de las clases VoltageReader and SpectraReader, + contiene todos lo metodos necesarios para leer datos desde archivos en formato + Jicamarca (.r o .pdata). La lectura de los datos siempre se realiza por bloques. Los datos + leidos son array de 3 dimensiones: + perfiles*alturas*canales + + y son almacenados en la variable "datablock". + + Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader, + RadarControllerHeader y DataObj. Los tres primeros se usan para almacenar informacion de la + cabecera de datos (metadata), y el cuarto (DataObj) para obtener y almacenar los datos desde + el "datablock" cada vez que se ejecute el metodo "getData". + + + """ + + m_BasicHeader = BasicHeader() + + m_SystemHeader = SystemHeader() + + m_RadarControllerHeader = RadarControllerHeader() + + m_ProcessingHeader = ProcessingHeader() + + m_DataObj = None + + online = 0 + + __startDateTime = None + + __endDateTime = None + + __fp = None + + __fileSizeByHeader = None + + __pathList = [] + + __filenameList = [] + + __fileIndex = None + + filename = None + + fileSize = None + + firstHeaderSize = 0 + + basicHeaderSize = 24 + + __dataType = None + + __blocksize = 0 + + datablock = None + + __datablockIndex = None + + __pts2read = 0 + + #Parametros para el procesamiento en linea + __year = 0 + + __doy = 0 + + __set = 0 -class DataWriter: + __ext = None + + __path = None + + __delay = 60 #seconds + + __nTries = 3 #quantity tries + + __nFiles = 3 #number of files for searching + + #speed of light + __c = 3E8 + + def __init__(self): + + """ + Inicializador + """ + + raise ValueError, "This class has not been implemented" + + def __rdSystemHeader(self,fp=None): + + if fp == None: + fp = self.__fp + + self.m_SystemHeader.read(fp) + + def __rdRadarControllerHeader(self,fp=None): + if fp == None: + fp = self.__fp + + self.m_RadarControllerHeader.read(fp) + + def __rdProcessingHeader(self,fp=None): + if fp == None: + fp = self.__fp + + self.m_ProcessingHeader.read(fp) + + def __rdBasicHeader(self, fp=None): + + if fp == None: + fp = self.__fp + + self.m_BasicHeader.read(fp) + + def __readFirstHeader(self): + + self.__rdBasicHeader() + self.__rdSystemHeader() + self.__rdRadarControllerHeader() + self.__rdProcessingHeader() + self.firstHeaderSize = self.m_BasicHeader.size + + data_type=int(numpy.log2((self.m_ProcessingHeader.processFlags & PROCFLAG.DATATYPE_MASK))-numpy.log2(PROCFLAG.DATATYPE_CHAR)) + if data_type == 0: + tmp = numpy.dtype([('real',' (self.__nFiles + 1): + break + + self.__set += 1 + + if countFiles > self.__nFiles: #si no encuentro el file buscado cambio de carpeta y busco en la siguiente carpeta + self.__set = 0 + self.__doy += 1 + bChangeDir = True + + file = None + filename = None + + countTries = 0 + + #espero hasta encontrar el 1er file disponible + while( True ): + + countTries += 1 + if( countTries >= self.__nTries ): #checkeo que no haya ido mas alla de la cantidad de intentos + break + + file, filename = checkForRealPath( self.__path, self.__year, self.__doy, self.__set, self.__ext ) + if file != None: + break + + if notFirstTime_flag: #este flag me sirve solo para esperar por el 1er file, en lo siguientes no espera solo checkea si existe o no + countTries = self.__nTries + print "\tsearching next \"%s\" file ..." % filename + break + + print "\twaiting new \"%s\" file ..." % filename + time.sleep( self.__delay ) + + if countTries >= self.__nTries: #se realizaron n intentos y no hubo un file nuevo + notFirstTime_flag = True + continue #vuelvo al inico del while principal + + countTries = 0 + + #una vez que se obtuvo el 1er file valido se procede a checkear su contenido, y se espera una cierta cantidad + #de tiempo por una cierta cantidad de veces hasta que el contenido del file sea un contenido valido + while( True ): + countTries += 1 + if countTries > self.__nTries: + break + + try: + fp = open(file) + except: + print "The file \"%s\" can't be opened" % file + break + + fileSize = os.path.getsize( file ) + currentSize = fileSize - fp.tell() + neededSize = self.m_ProcessingHeader.blockSize + self.firstHeaderSize + + if currentSize > neededSize: + fileStatus = 1 + break + + fp.close() + + if bChangeDir: #si al buscar un file cambie de directorio ya no espero y salgo del bucle while + print "\tsearching next \"%s\" file ..." % filename + break + + print "\twaiting for block of \"%s\" file ..." % filename + time.sleep( self.__delay ) + + if fileStatus == 1: + break + + print "Skipping the file \"%s\" due to this files is empty" % filename + countFiles = 0 + + + if fileStatus == 1: + self.fileSize = fileSize + self.filename = file + self.__flagNewFile = 1 + self.__fp = fp + self.flagNoMoreFiles = 0 + print 'Setting the file: %s' % file + else: + self.fileSize = 0 + self.filename = None + self.__fp = None + self.flagNoMoreFiles = 1 + print 'No more Files' + + return fileStatus + + + def __setNextFileOffline(self): + + idFile = self.__fileIndex + while(True): + + idFile += 1 + + if not(idFile < len(self.__filenameList)): + self.flagNoMoreFiles = 1 + return 0 + + filename = self.__filenameList[idFile] + fileSize = os.path.getsize(filename) + + try: + fp = open(filename,'rb') + except: + raise IOError, "The file %s can't be opened" %filename + + currentSize = fileSize - fp.tell() + neededSize = self.m_ProcessingHeader.blockSize + self.firstHeaderSize + + if (currentSize < neededSize): + print "Skipping the file %s due to it hasn't enough data" %filename + continue + + break + + self.__flagNewFile = 1 + self.__fileIndex = idFile + self.filename = filename + self.fileSize = fileSize + self.__fp = fp + + print 'Setting the file: %s'%self.filename + + return 1 + + def __setNextFile( self ): + """ + Determina el siguiente file a leer y si hay uno disponible lee el First Header + + Affected: + self.m_BasicHeader + self.m_SystemHeader + self.m_RadarControllerHeader + self.m_ProcessingHeader + self.firstHeaderSize + + Return: + 0 : Si no hay files disponibles + 1 : Si hay mas files disponibles + """ + if self.__fp != None: + self.__fp.close() + + if self.online: + newFile = self.__setNextFileOnline() + else: + newFile = self.__setNextFileOffline() + + if not(newFile): + return 0 + + self.__readFirstHeader() + + return 1 + + + def __setNewBlock( self ): + """ + Lee el Basic Header y posiciona le file pointer en la posicion inicial del bloque a leer + + Affected: + self.m_BasicHeader + self.flagNoContinuousBlock + self.ns + + Return: + 0 : Si el file no tiene un Basic Header que pueda ser leido + 1 : Si se pudo leer el Basic Header + """ + if self.__fp == None: + return 0 + + if self.__flagNewFile: + return 1 + + currentSize = self.fileSize - self.__fp.tell() + neededSize = self.m_ProcessingHeader.blockSize + self.basicHeaderSize + + #If there is enough data setting new data block + if ( currentSize >= neededSize ): + self.__rdBasicHeader() + return 1 + elif self.online: + nTries = 0 + while( nTries < self.__nTries ): + nTries += 1 + print "Waiting for the next block, try %03d ..." % nTries + time.sleep( self.__delay ) + + fileSize = os.path.getsize(self.filename) + currentSize = fileSize - self.__fp.tell() + neededSize = self.m_ProcessingHeader.blockSize + self.basicHeaderSize + + if ( currentSize >= neededSize ): + self.__rdBasicHeader() + return 1 + + #Setting new file + if not( self.__setNextFile() ): + return 0 + + deltaTime = self.m_BasicHeader.utc - self.__lastUTTime # check this + + self.flagNoContinuousBlock = 0 + + if deltaTime > self.__maxTimeStep: + self.flagNoContinuousBlock = 1 + self.nReadBlocks = 0 + + return 1 + + def __readBlock(self): + """ + __readBlock lee el bloque de datos desde la posicion actual del puntero del archivo + (self.__fp) y actualiza todos los parametros relacionados al bloque de datos + (metadata + data). La data leida es almacenada en el buffer y el contador del buffer + es seteado a 0 + + + Inputs: + None + + Return: + None + + Variables afectadas: + + self.__datablockIndex + + self.datablock + + self.__flagNewFile + + self.__flagNewBlock + + self.nReadBlocks + + """ + + #pts2read = self.m_ProcessingHeader.profilesPerBlock*self.m_ProcessingHeader.numHeights*self.m_SystemHeader.numChannels + + fpointer = self.__fp.tell() + + junk = numpy.fromfile( self.__fp, self.__dataType, self.__pts2read ) + + if self.online: + if junk.size != self.__blocksize: + nTries = 0 + while( nTries < self.__nTries ): + nTries += 1 + print "Waiting for the next block, try %03d ..." % nTries + time.sleep( self.__delay ) + self.__fp.seek( fpointer ) + fpointer = self.__fp.tell() + junk = numpy.fromfile( self.__fp, self.__dataType, self.__pts2read ) + if junk.size == self.__blocksize: + nTries = 0 + break + if nTries > 0: + return + + junk = junk.reshape( (self.m_ProcessingHeader.profilesPerBlock, self.m_ProcessingHeader.numHeights, self.m_SystemHeader.numChannels) ) + + data = junk['real'] + junk['imag']*1j + + self.__datablockIndex = 0 + + self.datablock = data + + self.__flagNewFile = 0 + + self.__flagNewBlock = 1 + + self.nReadBlocks += 1 + + def __hasNotDataInBuffer(self): + if self.__datablockIndex >= self.m_ProcessingHeader.profilesPerBlock: + return 1 + + return 0 + + + def __searchFilesOnLine( self, path, startDateTime=None, ext = ".r" ): + """ + Busca el ultimo archivo de la ultima carpeta (determinada o no por startDateTime) y + devuelve el archivo encontrado ademas de otros datos. + + Input: + path : carpeta donde estan contenidos los files que contiene data + startDateTime : punto especifico en el tiempo del cual se requiere la data + ext : extension de los files + + Return: + year : el anho + doy : el numero de dia del anho + set : el set del archivo + filename : el ultimo file de una determinada carpeta + directory : eL directorio donde esta el file encontrado + """ + + print "Searching files ..." + + dirList = [] + directory = None + + if startDateTime == None: + for thisPath in os.listdir(path): + if os.path.isdir( os.path.join(path,thisPath) ): + dirList.append( thisPath ) + + dirList = sorted( dirList, key=str.lower ) #para que quede ordenado al margen de si el nombre esta en mayusculas o minusculas, utilizo la funcion sorted + if len(dirList) > 0 : + directory = dirList[-1] + else: + year = startDateTime.timetuple().tm_year + doy = startDateTime.timetuple().tm_yday + + doyPath = "D%04d%03d" % (year,doy) #caso del nombre en mayusculas + if os.path.isdir( os.path.join(path,doyPath) ): + directory = doyPath + + doyPath = doyPath.lower() #caso del nombre en minusculas + if os.path.isdir( os.path.join(path,doyPath) ): + directory = doyPath + + if directory == None: + return 0, 0, 0, None, None + + filename = getlastFileFromPath( os.listdir( os.path.join(path,directory) ), ext ) + + if filename == None: + return 0, 0, 0, None, None + + year = int( directory[-7:-3] ) + doy = int( directory[-3:] ) + ln = len( ext ) + set = int( filename[-ln-3:-ln] ) + + return year, doy, set, filename, directory + + + def __searchFilesOffLine(self, path, startDateTime, endDateTime, set=None, expLabel = "", ext = ".r"): + """ + Realiza una busqueda de los archivos que coincidan con los parametros + especificados y se encuentren ubicados en el path indicado. Para realizar una busqueda + correcta la estructura de directorios debe ser la siguiente: + + ...path/D[yyyy][ddd]/expLabel/D[yyyy][ddd][sss].ext + + [yyyy]: anio + [ddd] : dia del anio + [sss] : set del archivo + + Inputs: + path : Directorio de datos donde se realizara la busqueda. Todos los + ficheros que concidan con el criterio de busqueda seran + almacenados en una lista y luego retornados. + startDateTime : Fecha inicial. Rechaza todos los archivos donde + file end time < startDateTime (obejto datetime.datetime) + + endDateTime : Fecha final. Rechaza todos los archivos donde + file start time > endDateTime (obejto datetime.datetime) + + set : Set del primer archivo a leer. Por defecto None + + expLabel : Nombre del subdirectorio de datos. Por defecto "" + + ext : Extension de los archivos a leer. Por defecto .r + + Return: + + (pathList, filenameList) + + pathList : Lista de directorios donde se encontraron archivos dentro + de los parametros especificados + filenameList : Lista de archivos (ruta completa) que coincidieron con los + parametros especificados. + + Variables afectadas: + + self.__filenameList: Lista de archivos (ruta completa) que la clase utiliza + como fuente para leer los bloque de datos, si se termina + de leer todos los bloques de datos de un determinado + archivo se pasa al siguiente archivo de la lista. + + Excepciones: + + """ + + print "Searching files ..." + + dirList = [] + for thisPath in os.listdir(path): + if os.path.isdir(os.path.join(path,thisPath)): + dirList.append(thisPath) + + pathList = [] + + thisDateTime = startDateTime + + while(thisDateTime <= endDateTime): + year = thisDateTime.timetuple().tm_year + doy = thisDateTime.timetuple().tm_yday + + match = fnmatch.filter(dirList, '?' + '%4.4d%3.3d' % (year,doy)) + if len(match) == 0: + thisDateTime += datetime.timedelta(1) + continue + + pathList.append(os.path.join(path,match[0],expLabel)) + thisDateTime += datetime.timedelta(1) + + startUtSeconds = time.mktime(startDateTime.timetuple()) + endUtSeconds = time.mktime(endDateTime.timetuple()) + + filenameList = [] + for thisPath in pathList: + fileList = glob.glob1(thisPath, "*%s" %ext) + fileList.sort() + for file in fileList: + filename = os.path.join(thisPath,file) + if isThisFileinRange(filename, startUtSeconds, endUtSeconds): + filenameList.append(filename) + + self.__filenameList = filenameList + + return pathList, filenameList + + + def __initFilesOnline( self, path, dirfilename, filename ): + """ + Verifica que el primer file tenga una data valida, para ello leo el 1er bloque + del file, si no es un file valido espera una cierta cantidad de tiempo a que + lo sea, si transcurrido el tiempo no logra validar el file entonces el metodo + devuelve 0 caso contrario devuelve 1 + + Affected: + m_BasicHeader + + Return: + 0 : file no valido para ser leido + 1 : file valido para ser leido + """ + m_BasicHeader = BasicHeader() + + file = os.path.join( path, dirfilename, filename ) + + nTries = 0 + while(True): + + nTries += 1 + if nTries > self.__nTries: + break + + try: + fp = open( file,'rb' ) #lectura binaria + except: + raise IOError, "The file %s can't be opened" %(file) + + try: + m_BasicHeader.read(fp) + except: + print "The file %s is empty" % filename + + fp.close() + + if m_BasicHeader.size > 24: + break + + print 'waiting for new block: try %02d' % ( nTries ) + time.sleep( self.__delay) + + if m_BasicHeader.size <= 24: + return 0 + + return 1 + + + def setup(self, path, startDateTime, endDateTime=None, set=None, expLabel = "", ext = ".r", online = 0): + """ + setup configura los parametros de lectura de la clase VoltageReader. + + Si el modo de lectura es offline, primero se realiza una busqueda de todos los archivos + que coincidan con los parametros especificados; esta lista de archivos son almacenados en + self.__filenameList. + + Input: + path : Directorios donde se ubican los datos a leer. Dentro de este + directorio deberia de estar subdirectorios de la forma: + + path/D[yyyy][ddd]/expLabel/P[yyyy][ddd][sss][ext] + + startDateTime : Fecha inicial. Rechaza todos los archivos donde + file end time < startDatetime (obejto datetime.datetime) + + endDateTime : Fecha final. Si no es None, rechaza todos los archivos donde + file end time < startDatetime (obejto datetime.datetime) + + set : Set del primer archivo a leer. Por defecto None + + expLabel : Nombre del subdirectorio de datos. Por defecto "" + + ext : Extension de los archivos a leer. Por defecto .r + + online : Si es == a 0 entonces busca files que cumplan con las condiciones dadas + + Return: + 0 : Si no encuentra files que cumplan con las condiciones dadas + 1 : Si encuentra files que cumplan con las condiciones dadas + + Affected: + self.startUTCSeconds + self.endUTCSeconds + self.startYear + self.endYear + self.startDoy + self.endDoy + self.__pathList + self.__filenameList + self.online + """ + if online: + nTries = 0 + while( nTries < self.__nTries ): + nTries += 1 + subfolder = "D%04d%03d" % ( startDateTime.timetuple().tm_year, startDateTime.timetuple().tm_yday ) + year, doy, set, filename, dirfilename = self.__searchFilesOnLine( path, startDateTime, ext ) + if filename == None: + file = os.path.join( path, subfolder ) + print "Searching first file in \"%s\", try %03d ..." % ( file, nTries ) + time.sleep( self.__delay ) + else: + break + + if filename == None: + print "No files On Line" + return 0 + + if self.__initFilesOnline( path, dirfilename, filename ) == 0: + print "The file %s hasn't enough data" + return 0 + + self.__year = year + self.__doy = doy + self.__set = set - 1 + self.__path = path + + else: + pathList, filenameList = self.__searchFilesOffLine( path, startDateTime, endDateTime, set, expLabel, ext ) + self.__fileIndex = -1 + self.__pathList = pathList + self.__filenameList = filenameList + + self.online = online + self.__ext = ext + + if not( self.__setNextFile() ): + if (startDateTime != None) and (endDateTime != None): + print "No files in range: %s - %s" %(startDateTime.ctime(), endDateTime.ctime()) + elif startDateTime != None: + print "No files in : %s" % startDateTime.ctime() + else: + print "No files" + return 0 + + if startDateTime != None: + self.startUTCSeconds = time.mktime(startDateTime.timetuple()) + self.startYear = startDateTime.timetuple().tm_year + self.startDoy = startDateTime.timetuple().tm_yday + + if endDateTime != None: + self.endUTCSeconds = time.mktime(endDateTime.timetuple()) + self.endYear = endDateTime.timetuple().tm_year + self.endDoy = endDateTime.timetuple().tm_yday + #call fillHeaderValues() - to Data Object + + self.m_Voltage.m_BasicHeader = self.m_BasicHeader.copy() + self.m_Voltage.m_ProcessingHeader = self.m_ProcessingHeader.copy() + self.m_Voltage.m_RadarControllerHeader = self.m_RadarControllerHeader.copy() + self.m_Voltage.m_SystemHeader = self.m_SystemHeader.copy() + self.m_Voltage.dataType = self.__dataType + + return 1 + + + def readNextBlock( self ): + """ + Establece un nuevo bloque de datos a leer y los lee, si es que no existiese + mas bloques disponibles en el archivo actual salta al siguiente. + + Affected: + self.__lastUTTime + + Return: None + """ + if not(self.__setNewBlock()): + return 0 + + self.__readBlock() + + self.__lastUTTime = self.m_BasicHeader.utc + + return 1 + + + def getData( self ): + """ + getData obtiene una unidad de datos del buffer de lectura y la copia a la clase "Voltage" + con todos los parametros asociados a este (metadata). cuando no hay datos en el buffer de + lectura es necesario hacer una nueva lectura de los bloques de datos usando "readNextBlock" + + Ademas incrementa el contador del buffer en 1. + + Return: + data : retorna un perfil de voltages (alturas * canales) copiados desde el + buffer. Si no hay mas archivos a leer retorna None. + + Variables afectadas: + self.m_Voltage + self.__datablockIndex + + Affected: + self.m_Voltage + self.__datablockIndex + self.flagNoContinuousBlock + self.__flagNewBlock + """ + self.flagNoContinuousBlock = 0 + self.__flagNewBlock = 0 + + if self.__hasNotDataInBuffer(): + + self.readNextBlock() + + self.m_Voltage.m_BasicHeader = self.m_BasicHeader.copy() + self.m_Voltage.m_ProcessingHeader = self.m_ProcessingHeader.copy() + self.m_Voltage.m_RadarControllerHeader = self.m_RadarControllerHeader.copy() + self.m_Voltage.m_SystemHeader = self.m_SystemHeader.copy() + self.m_Voltage.heights = self.__heights + self.m_Voltage.dataType = self.__dataType + + if self.flagNoMoreFiles == 1: + print 'Process finished' + return None + + #data es un numpy array de 3 dmensiones (perfiles, alturas y canales) + + time = self.m_BasicHeader.utc + self.__datablockIndex * self.__ippSeconds + self.m_Voltage.m_BasicHeader.utc = time + + self.m_Voltage.flagNoData = False + self.m_Voltage.flagNoContinuousBlock = self.flagNoContinuousBlock + + self.m_Voltage.data = self.datablock[self.__datablockIndex,:,:] + self.m_Voltage.profileIndex = self.__datablockIndex + + self.__datablockIndex += 1 + + #call setData - to Data Object + + return self.m_Voltage.data + + +#class VoltageWriter(DataWriter): +# """ +# Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura +# de los datos siempre se realiza por bloques. +# """ +# __configHeaderFile = 'wrSetHeadet.txt' +# +# def __init__( self, m_Voltage = None ): +# """ +# Inicializador de la clase VoltageWriter para la escritura de datos de espectros. +# +# Affected: +# self.m_Voltage +# self.m_BasicHeader +# self.m_SystemHeader +# self.m_RadarControllerHeader +# self.m_ProcessingHeader +# +# Return: None +# """ +# if m_Voltage == None: +# m_Voltage = Voltage() +# +# self.m_Voltage = m_Voltage +# +# self.__path = None +# +# self.__fp = None +# +# self.__format = None +# +# self.__blocksCounter = 0 +# +# self.__setFile = None +# +# self.__flagNewFile = 1 +# +# self.datablock = None +# +# self.__datablockIndex = 0 +# +# self.__dataType = None +# +# self.__ext = None +# +# self.__shapeBuffer = None +# +# self.nWriteBlocks = 0 +# +# self.__flagNewBlock = 0 +# +# self.flagNoMoreFiles = 0 +# +# self.filename = None +# +# self.m_BasicHeader= BasicHeader() +# +# self.m_SystemHeader = SystemHeader() +# +# self.m_RadarControllerHeader = RadarControllerHeader() +# +# self.m_ProcessingHeader = ProcessingHeader() +# +# +# def __writeFirstHeader( self ): +# """ +# Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader) +# +# Affected: +# __dataType +# +# Return: +# None +# """ +# self.__writeBasicHeader() +# self.__wrSystemHeader() +# self.__wrRadarControllerHeader() +# self.__wrProcessingHeader() +# self.__dataType = self.m_Voltage.dataType +# +# +# def __writeBasicHeader( self, fp=None ): +# """ +# Escribe solo el Basic header en el file creado +# +# Return: +# None +# """ +# if fp == None: +# fp = self.__fp +# +# self.m_BasicHeader.write(fp) +# +# +# def __wrSystemHeader( self, fp=None ): +# """ +# Escribe solo el System header en el file creado +# +# Return: +# None +# """ +# if fp == None: +# fp = self.__fp +# +# self.m_SystemHeader.write(fp) +# +# +# def __wrRadarControllerHeader( self, fp=None ): +# """ +# Escribe solo el RadarController header en el file creado +# +# Return: +# None +# """ +# if fp == None: +# fp = self.__fp +# +# self.m_RadarControllerHeader.write(fp) +# +# +# def __wrProcessingHeader( self, fp=None ): +# """ +# Escribe solo el Processing header en el file creado +# +# Return: +# None +# """ +# if fp == None: +# fp = self.__fp +# +# self.m_ProcessingHeader.write(fp) +# +# def __setNextFile( self ): +# """ +# Determina el siguiente file que sera escrito +# +# Affected: +# self.filename +# self.__subfolder +# self.__fp +# self.__setFile +# self.__flagNewFile +# +# Return: +# 0 : Si el archivo no puede ser escrito +# 1 : Si el archivo esta listo para ser escrito +# """ +# #setFile = self.__setFile +# ext = self.__ext +# path = self.__path +# +# #setFile += 1 +# +# if self.__fp != None: +# self.__fp.close() +# +# """ +# timeTuple = time.localtime(self.m_Voltage.m_BasicHeader.utc) # utc from m_Voltage +# file = 'D%4.4d%3.3d%3.3d%s' % (timeTuple.tm_year,timeTuple.tm_yday,setFile,ext) +# subfolder = 'D%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday) +# tmp = os.path.join(path,subfolder) +# if not(os.path.exists(tmp)): +# os.mkdir(tmp) +# """ +# ################################## +# if self.m_BasicHeader.size <= 24: return 0 #no existe la suficiente data para ser escrita +# +# timeTuple = time.localtime( self.m_Voltage.m_BasicHeader.utc ) # utc from m_Voltage +# subfolder = 'D%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday) +# +# tmp = os.path.join( path, subfolder ) +# if not( os.path.exists(tmp) ): +# os.mkdir(tmp) +# self.__setFile = -1 #inicializo mi contador de seteo +# else: +# filesList = os.listdir( tmp ) +# if len( filesList ) > 0: +# filesList = sorted( filesList, key=str.lower ) +# filen = filesList[-1] +# # el filename debera tener el siguiente formato +# # 0 1234 567 89A BCDE (hex) +# # D YYYY DDD SSS .ext +# if isNumber( filen[8:11] ): +# self.__setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file +# else: +# self.__setFile = -1 +# else: +# self.__setFile = -1 #inicializo mi contador de seteo +# +# setFile = self.__setFile +# setFile += 1 +# file = 'D%4.4d%3.3d%3.3d%s' % ( timeTuple.tm_year, timeTuple.tm_yday, setFile, ext ) +# ################################## +# +# filename = os.path.join( path, subfolder, file ) +# +# fp = open( filename,'wb' ) +# +# self.__blocksCounter = 0 +# +# #guardando atributos +# self.filename = filename +# self.__subfolder = subfolder +# self.__fp = fp +# self.__setFile = setFile +# self.__flagNewFile = 1 +# +# print 'Writing the file: %s'%self.filename +# +# self.__writeFirstHeader() +# +# return 1 +# +# +# def __setNewBlock( self ): +# """ +# Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header +# +# Return: +# 0 : si no pudo escribir nada +# 1 : Si escribio el Basic el First Header +# """ +# if self.__fp == None: +# self.__setNextFile() +# +# if self.__flagNewFile: +# return 1 +# +# if self.__blocksCounter < self.m_ProcessingHeader.dataBlocksPerFile: +# self.__writeBasicHeader() +# return 1 +# +# if not( self.__setNextFile() ): +# return 0 +# +# return 1 +# +# def __writeBlock( self ): +# """ +# Escribe el buffer en el file designado +# +# Affected: +# self.__datablockIndex +# self.__flagNewFile +# self.__flagNewBlock +# self.nWriteBlocks +# self.__blocksCounter +# +# Return: None +# """ +# data = numpy.zeros( self.__shapeBuffer, self.__dataType ) +# +# data['real'] = self.datablock.real +# data['imag'] = self.datablock.imag +# +# data = data.reshape( (-1) ) +# +# data.tofile( self.__fp ) +# +# self.datablock.fill(0) +# +# self.__datablockIndex = 0 +# +# self.__flagNewFile = 0 +# +# self.__flagNewBlock = 1 +# +# self.nWriteBlocks += 1 +# +# self.__blocksCounter += 1 +# +# +# def writeNextBlock( self ): +# """ +# Selecciona el bloque siguiente de datos y los escribe en un file +# +# Return: +# 0 : Si no hizo pudo escribir el bloque de datos +# 1 : Si no pudo escribir el bloque de datos +# """ +# if not(self.__setNewBlock()): +# return 0 +# +# self.__writeBlock() +# +# return 1 +# +# +# def __hasAllDataInBuffer( self ): +# if self.__datablockIndex >= self.m_ProcessingHeader.profilesPerBlock: +# return 1 +# +# return 0 +# +# +# def putData( self ): +# """ +# Setea un bloque de datos y luego los escribe en un file +# +# Affected: +# self.__flagNewBlock +# self.__datablockIndex +# +# Return: +# 0 : Si no hay data o no hay mas files que puedan escribirse +# 1 : Si se escribio la data de un bloque en un file +# """ +# self.__flagNewBlock = 0 +# +# if self.m_Voltage.flagNoData: +# return 0 +# +# if self.m_Voltage.flagNoContinuousBlock: +# +# self.datablock.fill(0) +# +# self.__datablockIndex = 0 +# self.__setNextFile() +# +# self.datablock[self.__datablockIndex,:,:] = self.m_Voltage.data +# +# self.__datablockIndex += 1 +# +# if self.__hasAllDataInBuffer(): +# +# self.__getHeader() +# self.writeNextBlock() +# +# if self.flagNoMoreFiles: +# #print 'Process finished' +# return 0 +# +# return 1 +# +# +# def __getHeader( self ): +# """ +# Obtiene una copia del First Header +# +# Affected: +# self.m_BasicHeader +# self.m_SystemHeader +# self.m_RadarControllerHeader +# self.m_ProcessingHeader +# self.__dataType +# +# Return: +# None +# """ +# self.m_BasicHeader = self.m_Voltage.m_BasicHeader.copy() +# self.m_SystemHeader = self.m_Voltage.m_SystemHeader.copy() +# self.m_RadarControllerHeader = self.m_Voltage.m_RadarControllerHeader.copy() +# self.m_ProcessingHeader = self.m_Voltage.m_ProcessingHeader.copy() +# self.__dataType = self.m_Voltage.dataType +# +# +# def __setHeaderByFile( self ): +# +# format = self.__format +# header = ['Basic','System','RadarController','Processing'] +# +# fmtFromFile = None +# headerFromFile = None +# +# +# fileTable = self.__configHeaderFile +# +# if os.access(fileTable, os.R_OK): +# import re, string +# +# f = open(fileTable,'r') +# lines = f.read() +# f.close() +# +# #Delete comments into expConfig +# while 1: +# +# startComment = string.find(lines.lower(),'#') +# if startComment == -1: +# break +# endComment = string.find(lines.lower(),'\n',startComment) +# lines = string.replace(lines,lines[startComment:endComment+1],'', 1) +# +# while expFromFile == None: +# +# currFmt = string.find(lines.lower(),'format="%s"' %(expName)) +# nextFmt = string.find(lines.lower(),'format',currFmt+10) +# +# if currFmt == -1: +# break +# if nextFmt == -1: +# nextFmt = len(lines)-1 +# +# fmtTable = lines[currFmt:nextFmt] +# lines = lines[nextFmt:] +# +# fmtRead = self.__getValueFromArg(fmtTable,'format') +# if fmtRead != format: +# continue +# fmtFromFile = fmtRead +# +# lines2 = fmtTable +# +# while headerFromFile == None: +# +# currHeader = string.find(lines2.lower(),'header="%s"' %(header)) +# nextHeader = string.find(lines2.lower(),'header',currHeader+10) +# +# if currHeader == -1: +# break +# if nextHeader == -1: +# nextHeader = len(lines2)-1 +# +# headerTable = lines2[currHeader:nextHeader] +# lines2 = lines2[nextHeader:] +# +# headerRead = self.__getValueFromArg(headerTable,'site') +# if not(headerRead in header): +# continue +# headerFromFile = headerRead +# +# if headerRead == 'Basic': +# self.m_BasicHeader.size = self.__getValueFromArg(headerTable,'size',lower=False) +# self.m_BasicHeader.version = self.__getValueFromArg(headerTable,'version',lower=False) +# self.m_BasicHeader.dataBlock = self.__getValueFromArg(headerTable,'dataBlock',lower=False) +# self.m_BasicHeader.utc = self.__getValueFromArg(headerTable,'utc',lower=False) +# self.m_BasicHeader.miliSecond = self.__getValueFromArg(headerTable,'miliSecond',lower=False) +# self.m_BasicHeader.timeZone = self.__getValueFromArg(headerTable,'timeZone',lower=False) +# self.m_BasicHeader.dstFlag = self.__getValueFromArg(headerTable,'dstFlag',lower=False) +# self.m_BasicHeader.errorCount = self.__getValueFromArg(headerTable,'errorCount',lower=False) +# +# else: +# print "file access denied:%s"%fileTable +# sys.exit(0) +# +# +# def setup( self, path, set=0, format='rawdata' ): +# """ +# Setea el tipo de formato en la cual sera guardada la data y escribe el First Header +# +# Inputs: +# path : el path destino en el cual se escribiran los files a crear +# format : formato en el cual sera salvado un file +# set : el setebo del file +# +# Return: +# 0 : Si no realizo un buen seteo +# 1 : Si realizo un buen seteo +# """ +# if format == 'hdf5': +# ext = '.hdf5' +# format = 'hdf5' +# print 'call hdf5 library' +# return 0 +# +# if format == 'rawdata': +# ext = '.r' +# format = 'Jicamarca' +# +# #call to config_headers +# #self.__setHeaderByFile() +# +# self.__path = path +# self.__setFile = set - 1 +# self.__ext = ext +# self.__format = format +# +# self.__getHeader() +# self.__shapeBuffer = (self.m_ProcessingHeader.profilesPerBlock, +# self.m_ProcessingHeader.numHeights, +# self.m_SystemHeader.numChannels ) +# +# self.datablock = numpy.zeros(self.__shapeBuffer, numpy.dtype('complex')) +# +## if not(self.__setNextFile()): +## return 0 +# return 1 + +class JRODataWriter(): def __init__(self): - __buffer = 0 - __buffer_count = 0 \ No newline at end of file + pass \ No newline at end of file diff --git a/schainpy/IO/HeaderIO.py b/schainpy/IO/HeaderIO.py deleted file mode 100644 index 1edaae2..0000000 --- a/schainpy/IO/HeaderIO.py +++ /dev/null @@ -1,410 +0,0 @@ -''' -Created on 23/01/2012 - -@author $Author$ -@version $Id$ -''' - -import numpy - -class BasicHeader: - - def __init__(self): - self.size = 0 - self.version = 0 - self.dataBlock = 0 - self.utc = 0 - self.miliSecond = 0 - self.timeZone = 0 - self.dstFlag = 0 - self.errorCount = 0 - self.struct = numpy.dtype([ - ('nSize','