VoltageIO.py
387 lines
| 11.7 KiB
| text/x-python
|
PythonLexer
|
r9 | ''' | |
Created on 23/01/2012 | |||
|
r16 | @author $Author$ | |
@version $Id$ | |||
|
r9 | ''' | |
import os, sys | |||
import numpy | |||
import glob | |||
import fnmatch | |||
|
r20 | import time, datetime | |
|
r9 | ||
|
r18 | path = os.path.split(os.getcwd())[0] | |
sys.path.append(path) | |||
|
r49 | from Model.JROHeader import * | |
|
r11 | from Model.Voltage import Voltage | |
|
r9 | ||
|
r49 | from IO.DataIO import JRODataReader | |
from IO.DataIO import JRODataWriter | |||
|
r37 | ||
|
r59 | ||
|
r49 | class VoltageReader(JRODataReader): | |
|
r20 | """ | |
Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura | |||
de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones: | |||
perfiles*alturas*canales) son almacenados en la variable "buffer". | |||
|
r59 | Voltajes - perfiles * alturas * canales | |
|
r20 | Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader, | |
RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la | |||
cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de | |||
datos desde el "buffer" cada vez que se ejecute el metodo "getData". | |||
Example: | |||
dpath = "/home/myuser/data" | |||
startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0) | |||
endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0) | |||
readerObj = VoltageReader() | |||
readerObj.setup(dpath, startTime, endTime) | |||
while(True): | |||
|
r25 | #to get one profile | |
profile = readerObj.getData() | |||
|
r20 | ||
|
r25 | #print the profile | |
print profile | |||
#If you want to see all datablock | |||
print readerObj.datablock | |||
|
r20 | ||
|
r59 | if readerObj.flagNoMoreFiles: | |
|
r20 | break | |
""" | |||
|
r59 | m_DataObj = None | |
idProfile = 0 | |||
datablock = None | |||
ext = ".r" | |||
pts2read = 0 | |||
utc = 0 | |||
|
r46 | ||
|
r9 | ||
|
r59 | def __init__(self, m_Voltage=None): | |
|
r20 | """ | |
Inicializador de la clase VoltageReader para la lectura de datos de voltage. | |||
Input: | |||
m_Voltage : Objeto de la clase Voltage. Este objeto sera utilizado para | |||
almacenar un perfil de datos cada vez que se haga un requerimiento | |||
(getData). El perfil sera obtenido a partir del buffer de datos, | |||
si el buffer esta vacio se hara un nuevo proceso de lectura de un | |||
bloque de datos. | |||
Si este parametro no es pasado se creara uno internamente. | |||
Variables afectadas: | |||
|
r53 | self.m_DataObj | |
|
r9 | ||
|
r20 | Return: | |
|
r59 | None | |
|
r20 | """ | |
|
r11 | if m_Voltage == None: | |
m_Voltage = Voltage() | |||
|
r20 | ||
if not(isinstance(m_Voltage, Voltage)): | |||
raise ValueError, "in VoltageReader, m_Voltage must be an Voltage class object" | |||
|
r53 | self.m_DataObj = m_Voltage | |
|
r12 | ||
|
r37 | ||
|
r59 | def __hasNotDataInBuffer(self): | |
|
r53 | if self.datablockIndex >= self.m_ProcessingHeader.profilesPerBlock: | |
|
r9 | return 1 | |
|
r53 | return 0 | |
|
r37 | ||
|
r59 | ||
|
r53 | def getBlockDimension(self): | |
|
r59 | """ | |
Obtiene la cantidad de puntos a leer por cada bloque de datos | |||
|
r9 | ||
|
r59 | Affected: | |
self.pts2read | |||
self.blocksize | |||
Return: | |||
None | |||
""" | |||
|
r53 | self.pts2read = self.m_ProcessingHeader.profilesPerBlock * self.m_ProcessingHeader.numHeights * self.m_SystemHeader.numChannels | |
self.blocksize = self.pts2read | |||
|
r59 | ||
|
r9 | ||
|
r53 | def readBlock(self): | |
|
r20 | """ | |
|
r53 | 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 | |||
|
r20 | (metadata + data). La data leida es almacenada en el buffer y el contador del buffer | |
es seteado a 0 | |||
Inputs: | |||
None | |||
Return: | |||
None | |||
|
r46 | Affected: | |
|
r53 | self.datablockIndex | |
|
r25 | self.datablock | |
|
r53 | self.flagIsNewFile | |
|
r20 | self.idProfile | |
self.flagIsNewBlock | |||
self.nReadBlocks | |||
|
r46 | Exceptions: | |
Si un bloque leido no es un bloque valido | |||
|
r9 | """ | |
|
r46 | blockOk_flag = False | |
|
r53 | fpointer = self.fp.tell() | |
|
r20 | ||
|
r53 | junk = numpy.fromfile( self.fp, self.dataType, self.pts2read ) | |
|
r37 | ||
if self.online: | |||
|
r53 | if junk.size != self.blocksize: | |
for nTries in range( self.nTries ): | |||
|
r59 | print "\tWaiting %0.2f sec for the next block, try %03d ..." % (self.delay, nTries+1) | |
|
r53 | 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: | |||
|
r46 | blockOk_flag = True | |
|
r37 | break | |
|
r46 | ||
if not( blockOk_flag ): | |||
return 0 | |||
|
r37 | ||
|
r46 | try: | |
junk = junk.reshape( (self.m_ProcessingHeader.profilesPerBlock, self.m_ProcessingHeader.numHeights, self.m_SystemHeader.numChannels) ) | |||
except: | |||
print "Data file %s is invalid" % self.filename | |||
return 0 | |||
|
r9 | ||
|
r46 | #data = junk['real'] + junk['imag']*1j | |
self.datablock = junk['real'] + junk['imag']*1j | |||
|
r20 | ||
|
r53 | self.datablockIndex = 0 | |
self.flagIsNewFile = 0 | |||
|
r20 | self.idProfile = 0 | |
|
r13 | self.flagIsNewBlock = 1 | |
|
r46 | ||
|
r13 | self.nReadBlocks += 1 | |
|
r46 | self.nBlocks += 1 | |
return 1 | |||
|
r59 | ||
|
r46 | ||
def getData(self): | |||
|
r20 | """ | |
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 | |||
|
r12 | lectura es necesario hacer una nueva lectura de los bloques de datos usando "readNextBlock" | |
|
r20 | ||
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: | |||
|
r53 | self.m_DataObj | |
self.datablockIndex | |||
|
r20 | self.idProfile | |
|
r37 | Affected: | |
|
r53 | self.m_DataObj | |
self.datablockIndex | |||
|
r37 | self.flagResetProcessing | |
self.flagIsNewBlock | |||
self.idProfile | |||
|
r9 | """ | |
|
r59 | if self.flagNoMoreFiles: return 0 | |
|
r46 | ||
|
r9 | self.flagResetProcessing = 0 | |
|
r13 | self.flagIsNewBlock = 0 | |
|
r9 | ||
|
r59 | if self.__hasNotDataInBuffer(): | |
|
r37 | ||
|
r46 | if not( self.readNextBlock() ): | |
|
r53 | self.setNextFile() | |
|
r46 | return 0 | |
|
r23 | ||
|
r53 | self.m_DataObj.m_BasicHeader = self.m_BasicHeader.copy() | |
self.m_DataObj.m_ProcessingHeader = self.m_ProcessingHeader.copy() | |||
self.m_DataObj.m_RadarControllerHeader = self.m_RadarControllerHeader.copy() | |||
self.m_DataObj.m_SystemHeader = self.m_SystemHeader.copy() | |||
self.m_DataObj.heights = self.heights | |||
self.m_DataObj.dataType = self.dataType | |||
|
r23 | ||
|
r59 | if self.flagNoMoreFiles == 1: | |
|
r11 | print 'Process finished' | |
|
r46 | return 0 | |
|
r9 | ||
|
r18 | #data es un numpy array de 3 dmensiones (perfiles, alturas y canales) | |
|
r15 | ||
|
r46 | if self.datablock == None: | |
|
r53 | self.m_DataObj.flagNoData = True | |
|
r46 | return 0 | |
|
r53 | time = self.m_BasicHeader.utc + self.datablockIndex * self.ippSeconds | |
self.utc = time | |||
#self.m_DataObj.m_BasicHeader.utc = time | |||
|
r37 | ||
|
r53 | self.m_DataObj.flagNoData = False | |
self.m_DataObj.flagResetProcessing = self.flagResetProcessing | |||
|
r23 | ||
|
r53 | self.m_DataObj.data = self.datablock[self.datablockIndex,:,:] | |
self.m_DataObj.idProfile = self.idProfile | |||
|
r23 | ||
|
r53 | self.datablockIndex += 1 | |
|
r20 | self.idProfile += 1 | |
|
r9 | ||
#call setData - to Data Object | |||
|
r53 | return 1 #self.m_DataObj.data | |
|
r9 | ||
|
r59 | ||
|
r49 | class VoltageWriter( JRODataWriter ): | |
|
r37 | """ | |
Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura | |||
de los datos siempre se realiza por bloques. | |||
""" | |||
|
r22 | __configHeaderFile = 'wrSetHeadet.txt' | |
|
r9 | ||
|
r59 | m_DataObj = None | |
datablock = None | |||
datablockIndex = 0 | |||
ext = ".r" | |||
optchar = "D" | |||
shapeBuffer = None | |||
def __init__(self, m_Voltage=None): | |||
|
r37 | """ | |
Inicializador de la clase VoltageWriter para la escritura de datos de espectros. | |||
Affected: | |||
|
r53 | self.m_DataObj | |
|
r37 | ||
Return: None | |||
""" | |||
|
r19 | if m_Voltage == None: | |
m_Voltage = Voltage() | |||
|
r9 | ||
|
r59 | if not( isinstance(m_Voltage, Voltage) ): | |
raise ValueError, "in VoltageReader, m_Spectra must be an Spectra class object" | |||
|
r53 | self.m_DataObj = m_Voltage | |
|
r59 | ||
|
r37 | ||
|
r53 | def hasAllDataInBuffer(self): | |
if self.datablockIndex >= self.m_ProcessingHeader.profilesPerBlock: | |||
return 1 | |||
return 0 | |||
|
r37 | ||
|
r59 | ||
|
r53 | def setBlockDimension(self): | |
|
r59 | """ | |
Obtiene las formas dimensionales del los subbloques de datos que componen un bloque | |||
Affected: | |||
self.shape_spc_Buffer | |||
self.shape_cspc_Buffer | |||
self.shape_dc_Buffer | |||
Return: None | |||
""" | |||
self.shapeBuffer = (self.m_ProcessingHeader.profilesPerBlock, | |||
self.m_ProcessingHeader.numHeights, | |||
self.m_SystemHeader.numChannels ) | |||
|
r22 | ||
|
r53 | self.datablock = numpy.zeros(self.shapeBuffer, numpy.dtype('complex')) | |
|
r59 | ||
|
r19 | ||
|
r53 | def writeBlock(self): | |
|
r37 | """ | |
Escribe el buffer en el file designado | |||
Affected: | |||
|
r53 | self.datablockIndex | |
self.flagIsNewFile | |||
|
r37 | self.flagIsNewBlock | |
self.nWriteBlocks | |||
|
r53 | self.blocksCounter | |
|
r37 | ||
Return: None | |||
""" | |||
|
r53 | data = numpy.zeros( self.shapeBuffer, self.dataType ) | |
|
r23 | ||
|
r25 | data['real'] = self.datablock.real | |
data['imag'] = self.datablock.imag | |||
|
r23 | ||
|
r37 | data = data.reshape( (-1) ) | |
|
r23 | ||
|
r53 | data.tofile( self.fp ) | |
|
r23 | ||
|
r25 | self.datablock.fill(0) | |
|
r53 | self.datablockIndex = 0 | |
self.flagIsNewFile = 0 | |||
|
r19 | self.flagIsNewBlock = 1 | |
self.nWriteBlocks += 1 | |||
|
r53 | self.blocksCounter += 1 | |
|
r19 | ||
|
r59 | ||
|
r46 | def putData(self): | |
|
r37 | """ | |
Setea un bloque de datos y luego los escribe en un file | |||
Affected: | |||
self.flagIsNewBlock | |||
|
r53 | self.datablockIndex | |
|
r37 | ||
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 | |||
""" | |||
|
r19 | self.flagIsNewBlock = 0 | |
|
r53 | if self.m_DataObj.flagNoData: | |
|
r23 | return 0 | |
|
r19 | ||
|
r53 | if self.m_DataObj.flagResetProcessing: | |
|
r23 | ||
|
r25 | self.datablock.fill(0) | |
|
r53 | self.datablockIndex = 0 | |
self.setNextFile() | |||
|
r22 | ||
|
r53 | self.datablock[self.datablockIndex,:,:] = self.m_DataObj.data | |
|
r19 | ||
|
r53 | self.datablockIndex += 1 | |
|
r19 | ||
|
r53 | if self.hasAllDataInBuffer(): | |
|
r59 | #if self.flagIsNewFile: | |
|
r53 | self.getHeader() | |
|
r19 | self.writeNextBlock() | |
|
r59 | if self.flagNoMoreFiles: | |
|
r23 | #print 'Process finished' | |
return 0 | |||
|
r19 | ||
return 1 | |||
|
r22 |