Matplotlib redraw plots
Date: March 5th 2016
Last updated: March 5th 2016
This is my cheap and easy approach to redrawing plots using matplotlib in kivy. This example completely removes the widget and redraws everything. I imagine it is a horribly inefficient method, but it works. As this was my first success at redrawing plots, I'm taking it as a win. I'll look for alternative methods in the future. There are some additional comments inside main.py (e.g. what I tried and what failed).
main.py
"""
Trialled many methods for clearing existing widget.
None have worked so far.... until... I decided to cheat!
In this example I have simply provided a redraw of everything
which will be the most inefficient method of acheiving the
desired result.
It seems fast enough on my desktop, but it will most likely be
slower on a phone or tablet.
"""
import matplotlib
matplotlib.use('module://kivy.garden.matplotlib.backend_kivy')
import matplotlib.pyplot as plt
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvas
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
import matplotlib.mlab as mlab
from random import gauss
import numpy as np
class DrawPlot(BoxLayout):
def __init__(self, **kwargs):
super(DrawPlot, self).__init__(**kwargs)
def get_data(self):
x = [gauss(100, 15) for i in range(100)]
return x
def draw_plot_frame(self):
self.fig, self.ax = plt.subplots()
self.ax.set_xlim([0, 200])
canvas = FigureCanvas(figure=self.fig)
self.add_widget(canvas, 1)
def plot(self):
x = self.get_data()
#self.ax.remove() # Doesnt work: first click rm widget, second click exits program
#self.fig.remove() # Doesnt work: cannot remove artist
#self.fig.close() #Doesnt work: figure object has no attr 'close'
#self.fig.clf() #Doesnt work: clears the entire figure widget
n, bins, patches = self.ax.hist(x, 50, normed=1, facecolor='white', alpha=0.3)
pdf = mlab.normpdf(bins, 100, 15)
self.ax.plot(bins, pdf, 'r-', linewidth=2)
#self.fig.clear() #Doesnt work: clears the figure widget
#self.draw_plot_frame() #Doesnt work: adds a NEW blank graph window
canvas = self.fig.canvas
canvas.draw()
# Tried to replace the previous line with the following line
#self.fig.canvas.draw() #Doesnt work: adds hist bins to existing figure
def cheatmethod(self):
canvas = self.fig.canvas
self.remove_widget(canvas)
self.draw_plot_frame()
self.plot()
class SampleApp(App):
def build(self):
return DrawPlot()
if __name__ == '__main__':
SampleApp().run()
sample.kv
#:kivy 1.9.1
<DrawPlot>:
orientation: 'vertical'
BoxLayout:
orientation: 'vertical'
size_hint: 1, None
height: main_title.height
Label:
id: main_title
text: "Plotting using Matplotlib in Kivy"
font_size: '35sp'
size_hint: 1, None
height: self.height
Label:
size_hint_x: 0.8
source: root.draw_plot_frame()
BoxLayout:
orientation: 'horizontal'
size_hint: 1, None
height: playbutton.height
Button:
id: playbutton
text: 'play'
size_hint: 1, None
height: self.height
on_press: root.cheatmethod() #<==== redraw everything on every click!!
Button:
text: 'reset'
size_hint: 1, None
Button:
text: 'quit'
size_hint: 1, None
Output
The first screen has an empty plot.
The next screen is after the first click on the 'play' button.
On the next click, the graph widget is redrawn.
And one more time.