Python Forum
Matplotlib Animation with Threading
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Matplotlib Animation with Threading
#1
I have a requirement to do animation with matplotlib and also generate/manipulate the data to be plotted. I was hoping to get this done in the same program using threading - one thread to generate/manipulate the data and write to a text file AND another thread to read this data and do the plotting/animation. I wrote a test script to try this out as below. I have a function incremnt() in which I intend to do the data generation/manipulation. For testing I am just doing a sleep and print statements. I also have a function loop_animate() which calls FuncAnimation with animate() as the animation function. I am using threading to create two threads t1 and t2 and calls incremnt and loop_animate in each of these threads. But when I run it, it just hangs. If I comment the animate and loop_animate functions, uncomment test_func and call this function in thread t2 instead of calling loop_animate, the threading works file and prints the messages from incremnt and test_func as expected. I could probably do this as two separate python scripts but trying to avoid that. Can someone help to sort this out?

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from itertools import count
import time
import random
import threading
 
xcord = []
ycord = [5,3]
index = count()
xcord.append(next(index))
xcord.append(next(index))

fig, ax = plt.subplots(1,1)
xmin, xmax = (0,29)
print(' xmin is {xmin}'.format(xmin=xmin))
print(' xmax is {xmax}'.format(xmax=xmax))

def animate(i,*args):
    global xmin, xmax, xcord, ycord
    
    xcord.append(next(index))
    ycord.append(random.randint(3,8))
    print(xcord)
    print(ycord)
    plt.cla()
    xmin = xmin + 1 if xcord[len(xcord)-1] > 28 else 0
    xmax = xmax + 1 if xcord[len(xcord)-1] > 28 else 29
    args[0].set(xlim=(xmin,xmax), ylim=(0, 10))
    args[0].plot(xcord,ycord)
   
def loop_animate():
    global fig, ax
       
    print('Inside loop_animate')
    ani = FuncAnimation(fig, animate,interval=500)
    plt.tight_layout()
    plt.show()
'''    
def test_func():
    cnt = 0
    while cnt < 5:
        print('Sleeping inside test_func')
        time.sleep(3)
        cnt += 1
        print('Done sleeping inside test_func')
'''
        
def incremnt():
        
    cnt = 0
    while cnt < 5:
        print('Sleeping inside fn incremnt')
        time.sleep(3)
        cnt += 1
        print('Done sleeping inside incremnt')
   

t1 = threading.Thread(target = incremnt)
t2 = threading.Thread(target = loop_animate)


t1.start()
t2.start()
print('Threads started')

t1.join()
t2.join()

print('All done')
Reply
#2
pyplot is not thread safe. Your example works as expected when all pyplot references are removed (as you stated).

Why are you using threads? From what you describe this sounds like a single thread of execution. Get values, update plot, repeat periodically. No need for FuncAnimation.
Reply
#3
As you said , Get values, update plot, repeat periodically is what I was trying to do initially. I tested that with a script like below. In this I am generating the next x,y coordinates and use set_data to plot the graph in a loop. I was expecting to see each point plotted and displayed in each iteration. But what seems to happen is that the plot gets displayed only at the end of script and not after each iteration of the loop. It is after seeing this behaviour that I looked around and discovered FuncAnimation. I tried FuncAnimation in a single thread script and that too did not work. That is when I moved on to two threads.
Is there a way to make the below script display each next point as soon as it is plotted?
import matplotlib.pyplot as plt
from itertools import count
import time
import random
 
xcord = []
ycord = []
index = count()

fig, ax = plt.subplots(1,1)
xmin, xmax = (0,30)

ax.set(xlim=(xmin,xmax), ylim=(0, 10))
ln = ax.plot(xcord,ycord)
plt.tight_layout()
#plt.show()

cnt = 0
while cnt < 10:
    time.sleep(3)
    xcord.append(next(index))
    ycord.append(random.randint(3,8))
    print(' xcord is {xcord}'.format(xcord=xcord))
    print(' ycord is {ycord}'.format(ycord=ycord))
    #plt.cla()
    ax.set(xlim=(xmin,xmax), ylim=(0, 10))
    ln[0].set_data(xcord,ycord)
    plt.show()
    cnt += 1
  
print('All done')
Reply
#4
Show the plot right away and update the plot using figure.canvas.draw()
Reply
#5
(Oct-08-2021, 12:36 PM)deanhystad Wrote: Show the plot right away and update the plot using figure.canvas.draw()

Tried your suggestion.. But couldn't get it to work. What I am seeing is that if I use Qt5 as backend, then the graph gets plotted after the whole script (and the print messages) is done. If I use tkinter a blank fig window comes up and it hangs. If I close the fig window, the script continues and prints the rest of the messages in the loop.
I am pretty new to matplotlib, so can you pls indicate where in the script should I use canvas.draw()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Concurrent futures threading running at same speed as non-threading billykid999 13 1,812 May-03-2023, 08:22 AM
Last Post: billykid999
  Tutorials on sockets, threading and multi-threading? muzikman 2 2,115 Oct-01-2021, 08:32 PM
Last Post: muzikman
  Matplotlib: How do I convert Dates from Excel to use in Matplotlib JaneTan 1 3,219 Mar-11-2021, 10:52 AM
Last Post: buran
  cannot create animation on 2D array using Matplotlib and FuncAnimation Caffeine_Addict 1 2,487 Jan-12-2021, 11:35 AM
Last Post: Caffeine_Addict
  Changing axis graduation matplotlib 3D animation axerousso 0 2,126 Jan-09-2020, 08:25 PM
Last Post: axerousso
  Matplotlib animation problem Potatoez 1 2,333 May-21-2019, 03:58 PM
Last Post: Potatoez
  Animation using matplotlib query JohnDoe 0 2,175 May-09-2019, 08:07 PM
Last Post: JohnDoe
  Matplotlib 3d voxels animation jasiekkm 0 2,748 Apr-07-2019, 07:44 AM
Last Post: jasiekkm
  Python Beacon positioning and animation with Raspberry pi matplotlib joefreedy 1 2,864 Feb-14-2019, 08:47 PM
Last Post: joefreedy

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020