I'd like to be able to catch an error while plotting using the matplotlib animation function.
This is necessary for me as I have a program where it can happen that an error occurs in the updatefig function after a couple of loops. I'd like to then continue in the script to save all the data generated up to that point.
Instead of throwing an error, running the code below will just lead to the following output:
Process finished with exit code 1
I tried to put the try except clause at all positions I could think of but was never able to go to the last print().
See this MWE (taken from here):
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
counter = 0
im = plt.imshow(f(x, y), animated=True)
def updatefig(*args):
global x, y, counter
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
counter += 1
# do something that might fail at one point (and will fail in this example)
if counter > 10:
b = 0
print('bla ' + b) # error
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
print('do other stuff now, e.g. save x and y')
There is an error because you are attempting to concatenate a string with an int:
Option 1:
correct the error:
import matplotlib
matplotlib.use('TkAgg')
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
counter = 0
im = plt.imshow(f(x, y), animated=True)
def updatefig(*args):
global x, y, counter
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
counter += 1
# do something that will not fail
if counter > 10:
b = 0
print('bla ' + str(b))
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
print('do other stuff now, e.g. save x and y')
option 2:
catch the Error, save the data, and continue:
import matplotlib
matplotlib.use('TkAgg')
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
counter = 0
im = plt.imshow(f(x, y), animated=True)
def save_if_error():
print('do other stuff now, e.g. save x and y')
def updatefig(*args):
global x, y, counter
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
counter += 1
# do something that might fail at one point and catch the error, save the data and continue
if counter > 10:
b = 0
try:
print('bla ' + b) # error
except TypeError:
print("save the data here")
save_if_error()
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
Related
I run the following code to animate a moving sphere, in which the coordinates are in a text file:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib import cm
from matplotlib import animation
import pandas as pd
df = pd.read_csv('/path/to/text/file', sep=" ", header=None)
fig = plt.figure(facecolor='black')
ax = plt.axes(projection = "3d")
u = np.linspace(0, 2*np.pi, 100)
v = np.linspace(0, np.pi, 100)
r = 4
ax.set_xlim(0, 60)
ax.set_ylim(0, 60)
ax.set_zlim(0, 60)
x0 = r * np.outer(np.cos(u), np.sin(v)) + df[1][0]
y0 = r * np.outer(np.sin(u), np.sin(v)) + df[2][0]
z0 = r * np.outer(np.ones(np.size(u)), np.cos(v)) + df[3][0]
surface_color = "tab:blue"
def init():
ax.plot_trisurf(x0, y0, z0, linewidth=0, antialiased=False)
return fig,
def animate(i):
# remove previous collections
ax.collections.clear()
x = df[1][i]
y = df[2][i]
z = df[3][i]
# add the new sphere
ax.plot_trisurf(x, y, z, linewidth=0, antialiased=False)
return fig,
ani = animation. FuncAnimation(fig, animate, init_func = init, frames = 500, interval = 2)
plt.show()
I get the following error "ValueError: x and y must be equal-length 1D arrays" even though I'm sure the arrays are of equal size. How do I make them equal size and solve this error?
As a sample of whats in the file:
0.196812 19.992262 29.989437 30.040883 0.080273 39.999358 30.009271 30.052325
0.288626 19.998165 29.986778 30.083568 0.305931 39.993330 30.011351 30.126911
0.080401 20.012453 29.982994 30.138681 0.224338 39.986476 30.010048 30.204666
0.380893 20.017042 29.984149 30.196864 0.289713 39.984835 30.009015 30.285159
0.396571 20.009539 29.998625 30.259610 0.350441 39.993791 30.017738 30.361558
0.647959 20.012771 29.995641 30.328414 0.275493 39.992826 30.019380 30.433242
0.741711 20.000002 29.978545 30.397738 0.248958 39.992041 30.010427 30.508367
0.867323 19.991656 29.971294 30.464908 0.313612 39.999097 30.004667 30.591674
The text file is very large, around 20,000 lines.
If the surface you are about to plot has a parametric equation (such as a sphere), use the meshgrid approach (x, y, z must be 2D arrays) and call ax.plot_surface. Instead, you used 1D arrays and later called ax.plot_trisurf: this function is better suited when it's not easy to represent the surface with a meshgrid approach (which is not your case). Do not complicate your life: keep it simply!
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib import cm
from matplotlib import animation
import pandas as pd
df = pd.read_csv('path/to/file', sep=" ", header=None)
fig = plt.figure(facecolor='black')
ax = plt.axes(projection = "3d")
u = np.linspace(0, 2*np.pi, 40)
v = np.linspace(0, np.pi, 20)
u, v = np.meshgrid(u, v)
r = 4
ax.set_xlim(0, 60)
ax.set_ylim(0, 60)
ax.set_zlim(0, 60)
x0 = r * np.outer(np.cos(u), np.sin(v)) + df[1][0]
y0 = r * np.outer(np.sin(u), np.sin(v)) + df[2][0]
z0 = r * np.outer(np.ones(np.size(u)), np.cos(v)) + df[3][0]
surface_color = "tab:blue"
def init():
ax.plot_surface(x0, y0, z0, color=surface_color)
return fig,
def animate(i):
# remove previous collections
ax.collections.clear()
x = df[1][i]
y = df[2][i]
z = df[3][i]
# add the new sphere
ax.plot_surface(x0 + x, y0 + y, z0 + z, color=surface_color)
return fig,
ani = animation. FuncAnimation(fig, animate, init_func = init, frames = 500, interval = 2)
plt.show()
Let me first clarify that I'm not trying to generate random walk lines like in this and many other questions. I'm trying to make a random walk heat map that changes color as points are revisted, like this.
I've been able to create still-lifes like this: but I want to see the process.
I can get the figure to show up, and if I print the array at each step I can see that the walk is working. But the figure itself doesn't animate. My code:
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib import animation as anim
import numpy as np
import sys
import random
length = int(sys.argv[1])
fig = plt.figure()
ax = plt.axes(xlim=(0, length-1), ylim=(0, length-1))
arr = np.zeros((length, length), dtype = int)
cmap = mpl.colors.LinearSegmentedColormap.from_list('my_colormap',
['black','green','white'],
256)
bounds=[0,0,10,10]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
im=plt.imshow(arr, interpolation='nearest',
cmap = cmap,
origin='lower')
x = int(np.random.random_sample() * length)
y = int(np.random.random_sample() * length)
def walk():
global x, y
rand = np.random.random_sample()
if rand < 0.25 :
if x == length - 1:
x = 0
else: x = x + 1
elif rand < 0.5 :
if x == 0:
x = length - 1
else: x = x - 1
elif rand < 0.75 :
if y == length - 1:
y = 0
else: y = y + 1
else:
if y == 0:
y = length - 1
else: y = y - 1
return
def stand(arr):
global x,y
arr[x][y] = arr[x][y] + 1
return arr
def animate(i):
arr=im.get_array()
walk()
#print(a)
arr = stand(arr)
im.set_array(arr)
return [im]
anim = anim.FuncAnimation(fig, animate, frames=200, interval=20, blit=True)
plt.show()
Running Python 3.6, as you can see by the print.
There are so many videos with these animated grids and I can't find any answers! Somebody must know how to do it. Thanks!
I added animated=True and vmin=0, vmax=255, in the imshow() function below. I also changed the stand() line to arr[x][y] = arr[x][y] + 10.
#!/usr/bin/env python3
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib import animation as anim
import numpy as np
import sys
import random
length = int(sys.argv[1])
fig = plt.figure()
ax = plt.axes(xlim=(0, length-1), ylim=(0, length-1))
arr = np.zeros((length, length), dtype = int)
cmap = mpl.colors.LinearSegmentedColormap.from_list('my_colormap',
['black','green','white'],
256)
bounds=[0,0,10,10]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
im=plt.imshow(arr, interpolation='nearest',
cmap = cmap, vmin=0, vmax=255,
origin='lower', animated=True) # small changes here
x = int(np.random.random_sample() * length)
y = int(np.random.random_sample() * length)
def walk():
global x, y
rand = np.random.random_sample()
if rand < 0.25 :
if x == length - 1:
x = 0
else: x = x + 1
elif rand < 0.5 :
if x == 0:
x = length - 1
else: x = x - 1
elif rand < 0.75 :
if y == length - 1:
y = 0
else: y = y + 1
else:
if y == 0:
y = length - 1
else: y = y - 1
return
def stand(arr):
global x,y
arr[x][y] = arr[x][y] + 1000
return arr
def animate(i):
global x,y
arr=im.get_array()
walk()
#print(a)
arr = stand(arr)
im.set_array(arr)
return [im]
anim = anim.FuncAnimation(fig, animate, frames=200, interval=20, blit=True)
plt.show()
And I ran it with length = 50 and I get an animation. See it here. So you may have to play around with your color choices a bit.
Is possible to animate pairs of images in a jupyter notebook?
With two lists of images:
greys = io.imread_collection(path_greys)
grdTru= io.imread_collection(path_grdTru)
The following naïve code fails to generate an animation:
for idx in range(1,900):
plt.subplot(121)
plt.imshow(greys[idx], interpolation='nearest', cmap=plt.cm.gray)
plt.subplot(122)
plt.imshow(grdTru[idx], interpolation='nearest', cmap=plt.cm.,vmin=0,vmax=3)
plt.show()
(It generates a list of subplots)
By the way,the example found in matplotlib doc failed if pasted in a notebook.
In order to make the example work in a jupyter notebook you need to include the
%matplotlib notebook
magic command.
import numpy as np
%matplotlib notebook
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = plt.imshow(f(x, y), animated=True)
def updatefig(*args):
global x, y
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
You can then easily adapt it to your list of images.
From matplotlib version 2.1 on you also have the option to create a JavaScript animation inline.
from IPython.display import HTML
HTML(ani.to_jshtml())
Complete example:
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = plt.imshow(f(x, y), animated=True);
def updatefig(*args):
global x, y
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
from IPython.display import HTML
HTML(ani.to_jshtml())
I am using the below manual method so as to plot the summation of harmonics. The below method is working fine.Please refer the image below.When the same thing implemented in for loop,it is not working as desired.The for loop is meant to take care of n number of harmonic values.Could any help me in this?
import numpy as np
import matplotlib.pyplot as plt
# omega =2*pi
x=np.linspace(0,2*np.pi,2000)
y1=np.sin(1*2*np.pi*x)/1
y2=np.sin(3*2*np.pi*x)/3
y3=np.sin(5*2*np.pi*x)/5
y4=np.sin(7*2*np.pi*x)/7
y5=np.sin(9*2*np.pi*x)/9
Y=y1+y2+y3+y4+y5
plt.plot(x,Y)
plt.grid()
plt.show()
#Implementation in for loop is not working
def Harmonic(i):
y = []
for n in range(0,i):
y=np.sin((2*n+1)*(2*np.pi)*(x))/(2*n+1)
y += y
plt.plot(x,y)
plt.grid()
plt.show()
If the goal was to see the impact of increasing the number of harmonics in "real time", you should use FuncAnimation
fig,ax = plt.subplots()
x=np.linspace(0,2*np.pi,2000)
y=np.zeros((2000,))
l, = ax.plot(x,y)
def initPlot():
ax.set_xlim(0,2*np.pi)
ax.set_ylim(-1,1)
l, = ax.plot(x,y)
return l,
def Harmonic(i):
y=l.get_ydata()
y += np.sin((2*i+1)*(2*np.pi)*(x))/(2*i+1)
l.set_ydata(y)
return l,
anim = animation.FuncAnimation(fig, Harmonic, init_func=initPlot, frames=150, interval=100, blit=True)
Here's a working example for you with a little bit of refactoring:
import numpy as np
import matplotlib.pyplot as plt
def first_solution(N=2000):
w = 2 * np.pi
x = np.linspace(0, w, N)
y1 = np.sin(1 * w * x) / 1
y2 = np.sin(3 * w * x) / 3
y3 = np.sin(5 * w * x) / 5
y4 = np.sin(7 * w * x) / 7
y5 = np.sin(9 * w * x) / 9
y = y1 + y2 + y3 + y4 + y5
plt.plot(x, y)
def second_solution(i, N=2000):
w = 2 * np.pi
x, y = np.linspace(0, w, N), []
harmonics = [np.sin((n * 2 + 1) * w * x) / (n * 2 + 1) for n in range(i)]
plt.plot(x, sum(harmonics))
plt.figure(1)
plt.subplot(211)
first_solution()
plt.grid()
plt.subplot(212)
second_solution(5)
plt.grid()
plt.show()
I've called first_solution to your working method and second_solution to your buggy one. Hope it helps
Do you mean something like that?
import numpy as np
import matplotlib.pyplot as plt
x=np.linspace(0,2*np.pi,2000)
y = [0 for _ in x]
def Harmonic(i):
global y
global x
for n in range(0,i):
y += np.sin((2*n+1)*(2*np.pi)*(x))/(2*n+1)
Harmonic(5)
plt.plot(x,y)
plt.grid()
plt.show()
Or, if you want to have the function the make the plot:
import numpy as np
import matplotlib.pyplot as plt
def Harmonic(i):
x=np.linspace(0,2*np.pi,2000)
y = [0 for _ in x]
for n in range(0,i):
y += np.sin((2*n+1)*(2*np.pi)*(x))/(2*n+1)
plt.plot(x,y)
plt.grid()
plt.show()
Harmonic(5)
Consider the following code directly taken from the Matplotlib documentation:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import time # optional for testing only
import cv2 # optional for testing only
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = plt.imshow(f(x, y), animated=True)
def updatefig(*args):
global x, y
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
This work fine on my system. Now, try to append the following piece of code to the above code:
while True:
#I have tried any of these 3 commands, without success:
pass
#time.sleep(1)
#cv2.waitKey(10)
What happens is that the program freezes. Apparently, the "Animation" class of Matplotlib runs the animation in a separate thread. So I have the 2 following questions:
1) If the process runs in a separate thread, why is it disturbed by the subsequent loop ?
2) How to say to python to wait until the animation has ended ?
For me, copying into ipython works as expected (animation plays first then the infinite loop) but when running the script it freezes.
1) I'm not sure exactly how cpython handles multi-threading, especially when combined with a particular matplotlib backend but it seems to be failing here. One possibility is to be explicit about how you want to use threads, by using
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import multiprocessing as mp
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = plt.imshow(f(x, y), animated=True)
def updatefig(*args):
global x, y
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
return im,
#A function to set thread number 0 to animate and the rest to loop
def worker(num):
if num == 0:
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
else:
while True:
print("in loop")
pass
return
# Create two threads
jobs = []
for i in range(2):
p = mp.Process(target=worker, args=(i,))
jobs.append(p)
p.start()
Which defines two threads and sets one to work on animation, one to loop.
2) To fix this, as suggested by #Mitesh Shah, you can use plt.show(block=True). For me, the script then behaves as expected with animation and then loop. Full code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = plt.imshow(f(x, y), animated=True)
def updatefig(*args):
global x, y
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show(block=True)
while True:
print("in loop")
pass
UPDATE: Alternative is to simply use interactive mode,
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
plt.ion()
plt.show()
def f(x, y):
return np.sin(x) + np.cos(y)
def updatefig(*args):
global x, y
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = plt.imshow(f(x, y))
for i in range(500):
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
plt.draw()
plt.pause(0.0000001)
Thanks to the help of Ed Smith and MiteshNinja, I have finally succeeded in finding a robust method that works not only with the Ipython console, but also with the Python console and the command line. Furthermore, it allows total control on the animation process. Code is self explanatory.
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from multiprocessing import Process
import time # optional for testing only
import matplotlib.animation as animation
# A. First we define some useful tools:
def wait_fig():
# Block the execution of the code until the figure is closed.
# This works even with multiprocessing.
if matplotlib.pyplot.isinteractive():
matplotlib.pyplot.ioff() # this is necessary in mutliprocessing
matplotlib.pyplot.show(block=True)
matplotlib.pyplot.ion() # restitute the interractive state
else:
matplotlib.pyplot.show(block=True)
return
def wait_anim(anim_flag, refresh_rate = 0.1):
#This will be used in synergy with the animation class in the example
#below, whenever the user want the figure to close automatically just
#after the animation has ended.
#Note: this function uses the controversial event_loop of Matplotlib, but
#I see no other way to obtain the desired result.
while anim_flag[0]: #next code extracted from plt.pause(...)
backend = plt.rcParams['backend']
if backend in plt._interactive_bk:
figManager = plt._pylab_helpers.Gcf.get_active()
if figManager is not None:
figManager.canvas.start_event_loop(refresh_rate)
def draw_fig(fig = None):
#Draw the artists of a figure immediately.
#Note: if you are using this function inside a loop, it should be less time
#consuming to set the interactive mode "on" using matplotlib.pyplot.ion()
#before the loop, event if restituting the previous state after the loop.
if matplotlib.pyplot.isinteractive():
if fig is None:
matplotlib.pyplot.draw()
else:
fig.canvas.draw()
else:
matplotlib.pyplot.ion()
if fig is None:
matplotlib.pyplot.draw()
else:
fig.canvas.draw()
matplotlib.pyplot.ioff() # restitute the interactive state
matplotlib.pyplot.show(block=False)
return
def pause_anim(t): #This is taken from plt.pause(...), but without unnecessary
#stuff. Note that the time module should be previously imported.
#Again, this use the controversial event_loop of Matplotlib.
backend = matplotlib.pyplot.rcParams['backend']
if backend in matplotlib.pyplot._interactive_bk:
figManager = matplotlib.pyplot._pylab_helpers.Gcf.get_active()
if figManager is not None:
figManager.canvas.start_event_loop(t)
return
else: time.sleep(t)
#--------------------------
# B. Now come the particular functions that will do the job.
def f(x, y):
return np.sin(x) + np.cos(y)
def plot_graph():
fig = plt.figure()
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = fig.gca().imshow(f(x, y))
draw_fig(fig)
n_frames = 50
#==============================================
#First method - direct animation: This use the start_event_loop, so is
#somewhat controversial according to the Matplotlib doc.
#Uncomment and put the "Second method" below into comments to test.
'''for i in range(n_frames): # n_frames iterations
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
draw_fig(fig)
pause_anim(0.015) # plt.pause(0.015) can also be used, but is slower
wait_fig() # simply suppress this command if you want the figure to close
# automatically just after the animation has ended
'''
#================================================
#Second method: this uses the Matplotlib prefered animation class.
#Put the "first method" above in comments to test it.
def updatefig(i, fig, im, x, y, anim_flag, n_frames):
x = x + i * np.pi / 15.
y = y + i * np.pi / 20.
im.set_array(f(x, y))
if i == n_frames-1:
anim_flag[0] = False
anim_flag = [True]
animation.FuncAnimation(fig, updatefig, repeat = False, frames = n_frames,
interval=50, fargs = (fig, im, x, y, anim_flag, n_frames), blit=False)
#Unfortunately, blit=True seems to causes problems
wait_fig()
#wait_anim(anim_flag) #replace the previous command by this one if you want the
#figure to close automatically just after the animation
#has ended
#================================================
return
#--------------------------
# C. Using multiprocessing to obtain the desired effects. I believe this
# method also works with the "threading" module, but I haven't test that.
def main(): # it is important that ALL the code be typed inside
# this function, otherwise the program will do weird
# things with the Ipython or even the Python console.
# Outside of this condition, type nothing but import
# clauses and function/class definitions.
if __name__ != '__main__': return
p = Process(target=plot_graph)
p.start()
print('hello', flush = True) #just to have something printed here
p.join() # suppress this command if you want the animation be executed in
# parallel with the subsequent code
for i in range(3): # This allows to see if execution takes place after the
#process above, as should be the case because of p.join().
print('world', flush = True)
time.sleep(1)
main()
We can run the animation function in a separate thread. Then start that thread. Once a new thread is created, the execution will continue.
We then use p.join() to wait for our previously created thread to finish execution. As soon as the execution finished (or terminates for some reason) the code will continue further.
Also matplotlib works differently in Interactive Python shells vs. system command line shells, the below code should work for both these scenarios:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from multiprocessing import Process
import time # optional for testing only
#import cv2 # optional for testing only
fig = plt.figure()
def f(x, y):
return np.sin(x) + np.cos(y)
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
im = plt.imshow(f(x, y), animated=True)
def plot_graph(*args):
def updatefig(*args):
global x, y
x += np.pi / 15.
y += np.pi / 20.
im.set_array(f(x, y))
return im,
ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True)
plt.show()
p = Process(target=plot_graph)
p.start()
# Code here computes while the animation is running
for i in range(10):
time.sleep(1)
print('Something')
p.join()
print("Animation is over")
# Code here to be computed after animation is over
I hope this helped! You can find more information here: Is there a way to detach matplotlib plots so that the computation can continue?
Cheers! :)