Can we use matplotlib.animation in kivy? If Yes,How?

Question:

Well this How to use matplotlib animation within kivy question is similar but the answer is just not at all valuable
Also as pointed by @ImportanceOfBeingErnest I edited the question to Can we actually do it?If Yes then proceed below.

So it was easy to add animation in tkinter according to the following tutorial Sentdex tutorial on how to add matplotlib animation in tkinter

I tried to do the same in kivy but cannot figure out where to write the line ani=animation.Funcanimation(blabla) See the last line in the following code

class Graph(FigureCanvasKivyAgg):
    def __init__(self,*args,**kwargs):
        FigureCanvasKivyAgg.__init__(self,f)
        pullData = open("TimeLatitude.txt", "r").read()
        dataList = pullData.split('n')
        xList = []
        yList = []
        pullData2 = open("TimeLongitude.txt", "r").read()
        dataList2 = pullData2.split('n')
        xList2 = []
        yList2 = []
        for eachLine in dataList:
            if len(eachLine) > 1:
                x, y = eachLine.split(',')
                xList.append(int(x))
                yList.append(int(y))
        for eachLine in dataList2:
            if len(eachLine) > 1:
                x, y = eachLine.split(',')
                xList2.append(int(x))
                yList2.append(int(y))
        a.clear()
        a.plot(xList, yList, "#00A3E0", label="Latitude")
        a.plot(xList2, yList2, "#183A54", label="Longitude")
        a.legend(bbox_to_anchor=(0, 1.02, 1, .102), loc=3,
                 ncol=2, borderaxespad=0)
        title = "Oxymora Mars Rover Geographic PointsnLast Longitude : " + str(
            yList2[len(yList2) - 1]) + "nLast Latitude : " + str(yList[len(yList) - 1])
        a.set_title(title)
        ani = animation.FuncAnimation(f, animate, interval=1000)
Asked By: 5cube

||

Answers:

I think kivy is less used nowadays.Nobody answered So i somehow i figured out a alternative to what i wanted to achieve.
I added a Refresh button which runs the whole fuction again which includes fetching of the values from a file and draws the graph again.Thus whenever the values are updated in the file we get a plot for that.

Here’s the python 3 code.

class Graph(FigureCanvasKivyAgg):
    def __init__(self,*args,**kwargs):
        FigureCanvasKivyAgg.__init__(self,f)
        pullData = open("TimeLatitude.txt", "r").read()
        dataList = pullData.split('n')
        xList = []
        yList = []
        pullData2 = open("TimeLongitude.txt", "r").read()
        dataList2 = pullData2.split('n')
        xList2 = []
        yList2 = []
        for eachLine in dataList:
            if len(eachLine) > 1:
                x, y = eachLine.split(',')
                xList.append(int(x))
                yList.append(int(y))
        for eachLine in dataList2:
            if len(eachLine) > 1:
                x, y = eachLine.split(',')
                xList2.append(int(x))
                yList2.append(int(y))
        a.plot(xList, yList, "#00A3E0", label="Latitude")
        a.plot(xList2, yList2, "#183A54", label="Longitude")
        a.legend(bbox_to_anchor=(0, 1.02, 1, .102), loc=3,
             ncol=2, borderaxespad=0)
        title = "Oxymora Mars Rover CoordinatesnLast Longitude : " + str(
            yList2[len(yList2) - 1]) + "nLast Latitude : " + str(yList[len(yList) - 1])
        a.set_title(title)
    def animate(self):
        pullData = open("TimeLatitude.txt", "r").read()
        dataList = pullData.split('n')
        xList = []
        yList = []
        pullData2 = open("TimeLongitude.txt", "r").read()
        dataList2 = pullData2.split('n')
        xList2 = []
        yList2 = []
        for eachLine in dataList:
            if len(eachLine) > 1:
                x, y = eachLine.split(',')
                xList.append(int(x))
                yList.append(int(y))
        for eachLine in dataList2:
            if len(eachLine) > 1:
                x, y = eachLine.split(',')
                xList2.append(int(x))
                yList2.append(int(y))
        a.clear()
        a.plot(xList, yList, "#00A3E0", label="Latitude")
        a.plot(xList2, yList2, "#183A54", label="Longitude")
        a.legend(bbox_to_anchor=(0, 1.02, 1, .102), loc=3,
                 ncol=2, borderaxespad=0)
        title = "Oxymora Mars Rover CoordinatesnLast Longitude : " + str(
            yList2[len(yList2) - 1]) + "nLast Latitude : " + str(yList[len(yList) - 1])
        a.set_title(title)
        self.draw()

and here’s the corresponding kivy code.

<MainScreen>:
    name: "main"
    FloatLayout:
        Graph
            id:gr
        Button:
            on_release: gr.animate()
            text: "Refresh"
            font_size: 15
            size_hint:0.068,0.05
            pos_hint: {"x":0,"top":0.8}
            color: 1,0,1,1

So finally after running my complete code kivy application looks like this-
Kivy application image

Answered By: 5cube

Okay…. so I know it’s a year late, but I solved my real-time graphing problem. It seems to me that Matplotlib’s FuncAnimation() method does not work with FigureCanvasKivyAgg.

Instead you have to use Kivy’s Clock.schedule_interval() method, and then within the method it calls, have a line that redraws the canvas. Like this:
self.fig.canvas.draw()

It’s not fast enough for proper real-time audio treatments. But for most typical graphing uses, it’s usable.

Here’s an example:

import queue
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
import numpy as np
from kivy.clock import Clock

class PlotInputStream():

    def __init__(self, queue):
        self.q = queue
        self.length = int((2048*2) * 44100 / (1000 * 10))
        self.plotdata = np.zeros((self.length, 1))
        self.fig, self.ax = plt.subplots()
        self.lineColour = 'blue'
        self.lines = self.ax.plot(self.plotdata, color=self.lineColour)
        # self.ani = FuncAnimation(self.fig, self.update_plot, interval=10, blit=False)
        Clock.schedule_interval(self.update_plot, 1 / 60.)

    def update_plot(self, frame):
        while True:
            try:
                data = self.q.get_nowait()
            except queue.Empty:
                break
            shift = len(data)
            self.plotdata = np.roll(self.plotdata, -shift, axis=0)
            self.plotdata[-shift:, :] = data
        for column, line in enumerate(self.lines):
            line.set_ydata(self.plotdata[:, column])
        self.fig.canvas.draw()
        return self.lines

I’m plotting audio-data, but you should be able to take the same principles and plot anything. Important to note that the above is a class that gets instantiated in my Kivy app’s build method. I then feed the instance into a Screen instance using:

self.figurecanvas = FigureCanvasKivyAgg(self.figure)
self.boxlayout_01.add_widget(self.figurecanvas)

That should be enough for you to get a Pyplot graph updating inside your Kivy app rather than having to rely on Matplotlib’s default figure window.

Answered By: DrewTNBD

the answer is Yes,
In kivy FigureCanvasKivyAgg is used to display images and for display an image of current figure in case of matplotlib you can display by simply return gcf() or return fig

for animation you can achieved by:

fig.canvas.draw() this line should be added it will draw figure on canvas before return.
fig.canvas.draw()
return fig

or
fig.canvas.draw()
return gcf()

hope this help

Answered By: zaheer
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.