Discussion:
Dynamic update x-axis with date and time ticks in Chaco
Luis Miguel Peci Sanchez
2012-12-17 17:34:52 UTC
Permalink
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
Luis Miguel Peci Sanchez
2012-12-17 17:39:56 UTC
Permalink
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 imports
from chaco.api import Plot, ArrayPlotData, ArrayDataSource, BarPlot, DataRange1D, \
LinearMapper, VPlotContainer, PlotAxis, \
FilledLinePlot, add_default_grids, PlotLabel
#from chaco.api import Plot, ArrayPlotData
from enable.component_editor import ComponentEditor
from numpy import linspace
from traits.api import Array, Bool, Callable, Enum, Float, HasTraits, \
Instance, Int, Trait
from traitsui.api import Group, HGroup, Item, View, spring, Handler
from pyface.timer.api import Timer

# Chaco imports
from chaco.chaco_plot_editor import ChacoPlotItem
from chaco.scales.api import CalendarScaleSystem
from chaco.scales_tick_generator import ScalesTickGenerator

import 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()


class Viewer(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 datos
def 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)




class Controller(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]))
new_index = arange(self.num_ticks - len(new_data) + 1, self.num_ticks+0.01)
#new_index = hstack((cur_data_x[-self.max_num_points+1:], ['A']))

self.viewer.index = new_index
self.viewer.data = new_data

return


# wxApp used when this file is run from the command line.

class MyApp(wx.PySimpleApp):

def OnInit(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)
return True


def 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







UCA

Luis Miguel Peci Sánchez
Laboratorio Astronomía, Geodesia y Cartografía
Dpt. Matemáticas - Universidad de Cádiz

Universidad de Cádiz
Campus Rio San Pedro
11510 Puerto Real - Cádiz.
Tel 956015309 / 956016287 Fax 956016288
luismiguel.peci-***@public.gmane.org [ mailto:luismiguel.peci-***@public.gmane.org ]
Loading...