Luis Miguel Peci Sanchez
2012-12-17 17:34:52 UTC
I show a plot with chaco and traits. In the y-axis I show the data from a file and in the x-axis I show the index. I use a timer to update the data and I increment the index but I would like to show the date and time instead of the index. I don't know how to do it. I show a piece of code to illustrate:
import random import wx import time from numpy import arange, array, hstack, random # Enthought importsfrom chaco.api importPlot,ArrayPlotData,ArrayDataSource,BarPlot,DataRange1D, \ LinearMapper,VPlotContainer,PlotAxis, \ FilledLinePlot, add_default_grids,PlotLabel#from chaco.api import Plot, ArrayPlotDatafrom enable.component_editor importComponentEditorfrom numpy import linspace from traits.api importArray,Bool,Callable,Enum,Float,HasTraits, \ Instance,Int,Traitfrom traitsui.api importGroup,HGroup,Item,View, spring,Handlerfrom pyface.timer.api importTimer# Chaco importsfrom chaco.chaco_plot_editor importChacoPlotItemfrom chaco.scales.api importCalendarScaleSystemfrom chaco.scales_tick_generator importScalesTickGeneratorimport os import matplotlib import matplotlib.pyplot as plt from datetime import*#abrimos el fichero de configuracion _fconf = open('graficas.cfg','r')#obtenemos el directorio de los ficheros_udp _directorio_in = _fconf.read(40)#cerramos el fichero de ArithmeticError _fconf.close()classViewer(HasTraits):""" Esta clase solo contiene los dos arrays que serán actualizados por el controlador. La visualización / edicion para esta clase es una grafica de chaco. """ index =Array data =Array# This "view" attribute defines how an instance of this class will# be displayed when .edit_traits() is called on it. (See MyApp.OnInit()# below.) view =View(ChacoPlotItem("index","data", resizable=True, x_label="Fecha", y_label="Temperatura ($^\circ$C)C", color="blue", bgcolor="white", border_visible=True, border_width=1, padding_bg_color="lightgray", width=800, height=300, marker_size=2, show_label=False), resizable =True, buttons =["OK"], width=800, height=500, title="CECAFLUX")# Funcion encargada de la lectura de los datos del fichero de datosdef get_datos(obj): datos_hoy = matplotlib.mlab.csv2rec(obj, delimiter=',') ultimo_reg = datos_hoy[-1] fecha = ultimo_reg['fecha'] t1 = ultimo_reg['t1'] t2 = ultimo_reg['t2'] t3 = ultimo_reg['t3'] t4 = ultimo_reg['t4'] t5 = ultimo_reg['t5'] f1 = ultimo_reg['f1'] f2 = ultimo_reg['f2'] p = ultimo_reg['peltier']return(fecha, t1, t2, t3, t4, t5, f1, f2, p)classController(HasTraits):# A reference to the plot viewer object viewer =Instance(Viewer)# El numero maximo de puntos a acumular en la grafica en este caso 288, 24 horas si muestreamos a 5 minutos. max_num_points =Int(288)# The number of data points we have received; we need to keep track of# this in order to generate the correct x axis data series. num_ticks =Int(0)def timer_tick(self,*args):""" Callback function that should get called based on a wx timer tick. This will generate a new random datapoint and set it on the .data array of our viewer object. """global _fconf global _directorio_in #obtenemos la fecha del sistema ahora = datetime.utcnow() anio = datetime.today().year mes = datetime.today().month diferencia = timedelta(days=1) ayer = ahora - diferencia directorio_fecha ="%d/%d/"%(anio, mes)#print _directorio_in directorio_aux = _directorio_in + directorio_fecha #obtenemos todos los ficheros del directorio ficheros = os.listdir(directorio_aux)#ordenamos la lista de ficheros ficheros.sort()#obtenemos la longitud longitud = len(ficheros)#obtenemos el fichero ultimo que es el que esta abierto fichero_ultimo = ficheros[longitud-1]#abrimos el fichero y obtenemos el ultimo dato si ha sido modificado ahora_noUTC = datetime.now() dt=ahora_noUTC-timedelta(minutes=1) path=os.path.join(directorio_aux,fichero_ultimo) st=os.stat(path) mtime=datetime.fromtimestamp(st.st_mtime)print"mtime "+str(mtime)print"dt "+str(dt)if mtime>dt:print"Fichero modificado"# generamos los nuevos datos e incrementamos el contados de marcas del eje x fecha, t1, t2, t3, t4, t5, f1, f2, peltier = get_datos(path)# identar new_val = t1 self.num_ticks +=1# grab the existing data, truncate it, and append the new point.# This isn't the most efficient thing in the world but it works.# almacena el dato actual en cur_data cur_data = self.viewer.data cur_data_x = self.viewer.index # movemos el valor actual una posicion y apilamos el nuevo valor new_data = hstack((cur_data[-self.max_num_points+1:],[new_val]))# here I would like to show date and time instead of the index number new_index = arange(self.num_ticks - len(new_data)+1, self.num_ticks+0.01) self.viewer.index = new_index self.viewer.data = new_data return# wxApp used when this file is run from the command line.classMyApp(wx.PySimpleApp):defOnInit(self,*args,**kw): viewer =Viewer() controller =Controller(viewer = viewer)# Pop up the windows for the two objects#viewer.configure_traits() viewer.edit_traits()#controller.edit_traits()# Set up the timer and start it up self.setup_timer(controller)returnTruedef setup_timer(self, controller):# Create a new WX timer timerId = wx.NewId() self.timer = wx.Timer(self, timerId)# Register a callback with the timer event self.Bind(wx.EVT_TIMER, controller.timer_tick, id=timerId)# Start up the timer! We have to tell it how many milliseconds# to wait between timer events. For now we will hardcode it# to be 100 ms, so we get 10 points per second.# ejecutamos cada 1 minuto self.timer.Start(60000.0, wx.TIMER_CONTINUOUS)return# This is called when this example is to be run in a standalone mode.if __name__ =="__main__": app =MyApp() app.MainLoop()# EOF
import random import wx import time from numpy import arange, array, hstack, random # Enthought importsfrom chaco.api importPlot,ArrayPlotData,ArrayDataSource,BarPlot,DataRange1D, \ LinearMapper,VPlotContainer,PlotAxis, \ FilledLinePlot, add_default_grids,PlotLabel#from chaco.api import Plot, ArrayPlotDatafrom enable.component_editor importComponentEditorfrom numpy import linspace from traits.api importArray,Bool,Callable,Enum,Float,HasTraits, \ Instance,Int,Traitfrom traitsui.api importGroup,HGroup,Item,View, spring,Handlerfrom pyface.timer.api importTimer# Chaco importsfrom chaco.chaco_plot_editor importChacoPlotItemfrom chaco.scales.api importCalendarScaleSystemfrom chaco.scales_tick_generator importScalesTickGeneratorimport os import matplotlib import matplotlib.pyplot as plt from datetime import*#abrimos el fichero de configuracion _fconf = open('graficas.cfg','r')#obtenemos el directorio de los ficheros_udp _directorio_in = _fconf.read(40)#cerramos el fichero de ArithmeticError _fconf.close()classViewer(HasTraits):""" Esta clase solo contiene los dos arrays que serán actualizados por el controlador. La visualización / edicion para esta clase es una grafica de chaco. """ index =Array data =Array# This "view" attribute defines how an instance of this class will# be displayed when .edit_traits() is called on it. (See MyApp.OnInit()# below.) view =View(ChacoPlotItem("index","data", resizable=True, x_label="Fecha", y_label="Temperatura ($^\circ$C)C", color="blue", bgcolor="white", border_visible=True, border_width=1, padding_bg_color="lightgray", width=800, height=300, marker_size=2, show_label=False), resizable =True, buttons =["OK"], width=800, height=500, title="CECAFLUX")# Funcion encargada de la lectura de los datos del fichero de datosdef get_datos(obj): datos_hoy = matplotlib.mlab.csv2rec(obj, delimiter=',') ultimo_reg = datos_hoy[-1] fecha = ultimo_reg['fecha'] t1 = ultimo_reg['t1'] t2 = ultimo_reg['t2'] t3 = ultimo_reg['t3'] t4 = ultimo_reg['t4'] t5 = ultimo_reg['t5'] f1 = ultimo_reg['f1'] f2 = ultimo_reg['f2'] p = ultimo_reg['peltier']return(fecha, t1, t2, t3, t4, t5, f1, f2, p)classController(HasTraits):# A reference to the plot viewer object viewer =Instance(Viewer)# El numero maximo de puntos a acumular en la grafica en este caso 288, 24 horas si muestreamos a 5 minutos. max_num_points =Int(288)# The number of data points we have received; we need to keep track of# this in order to generate the correct x axis data series. num_ticks =Int(0)def timer_tick(self,*args):""" Callback function that should get called based on a wx timer tick. This will generate a new random datapoint and set it on the .data array of our viewer object. """global _fconf global _directorio_in #obtenemos la fecha del sistema ahora = datetime.utcnow() anio = datetime.today().year mes = datetime.today().month diferencia = timedelta(days=1) ayer = ahora - diferencia directorio_fecha ="%d/%d/"%(anio, mes)#print _directorio_in directorio_aux = _directorio_in + directorio_fecha #obtenemos todos los ficheros del directorio ficheros = os.listdir(directorio_aux)#ordenamos la lista de ficheros ficheros.sort()#obtenemos la longitud longitud = len(ficheros)#obtenemos el fichero ultimo que es el que esta abierto fichero_ultimo = ficheros[longitud-1]#abrimos el fichero y obtenemos el ultimo dato si ha sido modificado ahora_noUTC = datetime.now() dt=ahora_noUTC-timedelta(minutes=1) path=os.path.join(directorio_aux,fichero_ultimo) st=os.stat(path) mtime=datetime.fromtimestamp(st.st_mtime)print"mtime "+str(mtime)print"dt "+str(dt)if mtime>dt:print"Fichero modificado"# generamos los nuevos datos e incrementamos el contados de marcas del eje x fecha, t1, t2, t3, t4, t5, f1, f2, peltier = get_datos(path)# identar new_val = t1 self.num_ticks +=1# grab the existing data, truncate it, and append the new point.# This isn't the most efficient thing in the world but it works.# almacena el dato actual en cur_data cur_data = self.viewer.data cur_data_x = self.viewer.index # movemos el valor actual una posicion y apilamos el nuevo valor new_data = hstack((cur_data[-self.max_num_points+1:],[new_val]))# here I would like to show date and time instead of the index number new_index = arange(self.num_ticks - len(new_data)+1, self.num_ticks+0.01) self.viewer.index = new_index self.viewer.data = new_data return# wxApp used when this file is run from the command line.classMyApp(wx.PySimpleApp):defOnInit(self,*args,**kw): viewer =Viewer() controller =Controller(viewer = viewer)# Pop up the windows for the two objects#viewer.configure_traits() viewer.edit_traits()#controller.edit_traits()# Set up the timer and start it up self.setup_timer(controller)returnTruedef setup_timer(self, controller):# Create a new WX timer timerId = wx.NewId() self.timer = wx.Timer(self, timerId)# Register a callback with the timer event self.Bind(wx.EVT_TIMER, controller.timer_tick, id=timerId)# Start up the timer! We have to tell it how many milliseconds# to wait between timer events. For now we will hardcode it# to be 100 ms, so we get 10 points per second.# ejecutamos cada 1 minuto self.timer.Start(60000.0, wx.TIMER_CONTINUOUS)return# This is called when this example is to be run in a standalone mode.if __name__ =="__main__": app =MyApp() app.MainLoop()# EOF