working dynamic graph using matplotlib

This commit is contained in:
Kienan Stewart 2014-12-10 22:38:40 -05:00
parent 290fb94a9d
commit bf5a6c6920
2 changed files with 107 additions and 7 deletions

View File

@ -1,6 +1,8 @@
<MyLabel@Label>: <MyLabel@Label>:
text: 'Current Temperature: n/a' text: 'Current Temperature: n/a'
# on_lastTemperature: self.update_current_temperature_label()
<PlotWidget@Image>:
allow_stretch: True
<MainWindow>: <MainWindow>:
label_wid: "Temperature Monitor" label_wid: "Temperature Monitor"
@ -17,5 +19,5 @@
text: 'No File Chosen' text: 'No File Chosen'
Label: Label:
text: 'Data Source' text: 'Data Source'
Label: PlotWidget:
text: 'Graph placeholder' id: 'mainplot'

106
main.py
View File

@ -1,13 +1,23 @@
import kivy import kivy
from kivy.app import App from kivy.app import App
from kivy.clock import Clock from kivy.clock import Clock
import kivy.core.image
from kivy.core.image.img_pygame import ImageLoaderPygame
import kivy.graphics.texture
from kivy.logger import Logger from kivy.logger import Logger
from kivy.properties import ObjectProperty, StringProperty from kivy.properties import ListProperty, NumericProperty, ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.label import Label from kivy.uix.label import Label
import kivy.lang import kivy.lang
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.image
import matplotlib.pyplot
import Queue import Queue
import StringIO
import temp_log import temp_log
import threading import threading
@ -36,7 +46,8 @@ class MainApp(App):
class MainWindow(FloatLayout): class MainWindow(FloatLayout):
"""Main Window class""" """Main Window class"""
dataSource = StringProperty('/dev/ttyACM0') dataSource = StringProperty('/dev/ttyACM0')
lastTemperature = StringProperty('n/a') lastTemperature = NumericProperty(-1000.)
lastTime = NumericProperty(-1.)
def update_last_temperature(self, dt): def update_last_temperature(self, dt):
global dataThreadDataQueue global dataThreadDataQueue
@ -44,20 +55,48 @@ class MainWindow(FloatLayout):
try: try:
data = dataThreadDataQueue.get_nowait() data = dataThreadDataQueue.get_nowait()
if data is not None: if data is not None:
self.lastTemperature = str(data['data']['temperature']) Logger.debug('Data: ' + str(data))
if 'data' in data and 'temperature' in data['data']:
self.lastTemperature = float(data['data']['temperature'])
if 'time' in data:
self.lastTime = float(data['time'])
except Queue.Empty: except Queue.Empty:
pass pass
def on_lastTemperature(self, instance, value): def on_lastTemperature(self, instance, value):
Logger.debug('lastTemperature has changed to: ' + str(value)) Logger.debug('lastTemperature has changed to: ' + str(value))
children = self.children[:] children = self.children[:]
while children: while children:
child = children.pop() child = children.pop()
children.extend(child.children)
if child is self:
continue
try: try:
child.on_lastTemperature(instance, value) child.on_lastTemperature(instance, value)
except Exception, e: #Logger.debug('Called on_lastTemperature for child: ' + str(child))
except AttributeError:
pass pass
except Exception, e:
Logger.exception(str(e))
def on_lastTime(self, instance, value):
Logger.debug('lastTime has changed to: ' + str(value))
children = self.children[:]
while children:
child = children.pop()
children.extend(child.children) children.extend(child.children)
if child is self:
continue
#Logger.debug(str(child))
try:
child.on_lastTime(instance, value)
#Logger.debug('Called on_lastTime for child: ' + str(child))
except AttributeError, e:
pass
except Exception, e:
Logger.exception(str(e))
class MyLabel(Label): class MyLabel(Label):
@ -66,6 +105,65 @@ class MyLabel(Label):
self.text = 'Current temperature: ' + str(value) self.text = 'Current temperature: ' + str(value)
class PlotWidget(Image):
def __init__(self, **kwargs):
super(Image, self).__init__(**kwargs)
self.data = numpy.array([], dtype=float);
self.lastTime = 0
self.lastTemperature = 0
self.figure = matplotlib.pyplot.figure()
self.plot_axes = self.figure.add_subplot(1, 1, 1)
self.plot_axes.hold(False)
self.plot_axes.set_ylabel('Temperature (deg C)')
self.plot_axes.set_xlabel('Time')
self.plot_axes.set_title('Recorded Temperature')
def update(self):
if not self.data.any():
return
#Logger.debug('self.data: ' + str(self.data))
#Logger.debug('self.data shape: ' + str(self.data.shape))
data = numpy.copy(self.data)
data = data.transpose()
#Logger.debug('transpoed data: ' + str(data))
#Logger.debug('transposed data shape: ' + str(data.shape))
t, temperature = numpy.split(data, 2, axis = 0)
#Logger.debug('time: ' + str(t[0]))
#Logger.debug('temperature: ' + str(temperature[0]))
self.plot_axes.plot(t[0], temperature[0])
image_data = StringIO.StringIO()
self.figure.savefig(image_data, format = 'png')
image_data.seek(0)
self.texture = ImageLoaderPygame(image_data, nocache = True).texture
def on_lastTemperature(self, instance, value):
self.lastTemperature = value
self.update_data()
def on_lastTime(self, instance, value):
self.lastTime = value
self.update_data()
def update_data(self):
if self.lastTime == 0 or self.lastTemperature == 0:
return
newpoint = numpy.array([(self.lastTime, self.lastTemperature)], dtype=float, ndmin = 2)
if not self.data.any():
self.data = newpoint
return
#Logger.debug('self.data: ' + str(self.data))
#Logger.debug('newpoint: ' + str(newpoint))
self.data = numpy.vstack((self.data, newpoint))
self.update()
#self.data = numpy.concatenate((self.data, newpoint), axis = 0)
#self.data = numpy.copy(self.data) # This will cause ObjectProperty to fire a change event
if __name__ == '__main__': if __name__ == '__main__':
dataThread = threading.Thread(None, temp_log.threaded_reader, None, ['/dev/ttyACM0', dataThreadDataQueue, dataThreadCommandQueue]) dataThread = threading.Thread(None, temp_log.threaded_reader, None, ['/dev/ttyACM0', dataThreadDataQueue, dataThreadCommandQueue])
MainApp().run() MainApp().run()