working dynamic graph using matplotlib
This commit is contained in:
parent
290fb94a9d
commit
bf5a6c6920
8
main.kv
8
main.kv
|
@ -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
106
main.py
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue