how to plot multiple animated functions on the same plot with matplotlib? - python

i want to plot two animated functions on the same plot to compare between two functions , lets say for example exp(-x2) and exp(x2)
i know how to animate a function here is the code i used to animate the function
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
%matplotlib qt
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'r', animated=True)
f = np.linspace(-3, 3, 200)
def init():
ax.set_xlim(-3, 3)
ax.set_ylim(-0.25, 2)
ln.set_data(xdata,ydata)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.exp(-frame**2))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=f,enter code here
init_func=init, blit=True, interval = 2.5,repeat=False)
plt.show()
enter code here
and by the same method we can plot the other function but how do we show them on the same plot

As mentioned in the comment, adding another line will work. Here is a working example with exp(-x^2) and exp(x^2), I also changed the limits to see both better:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata0, ydata1 = [], [], []
ln0, = plt.plot([], [], 'r', animated=True)
ln1, = plt.plot([], [], 'b', animated=True)
f = np.linspace(-3, 3, 200)
def init():
ax.set_xlim(-3, 3)
ax.set_ylim(-0.25, 10)
ln0.set_data(xdata,ydata0)
ln1.set_data(xdata,ydata1)
return ln0, ln1
def update(frame):
xdata.append(frame)
ydata0.append(np.exp(-frame**2))
ydata1.append(np.exp(frame**2))
ln0.set_data(xdata, ydata0)
ln1.set_data(xdata, ydata1)
return ln0, ln1,
ani = FuncAnimation(fig, update, frames=f,
init_func=init, blit=True, interval=2.5, repeat=False)
plt.show()
For the gif below I changed the plt.show() line to be ani.save('animated_exp.gif', writer='imagemagick') and changed the interval to be 25.

Related

Matplotlib animate plot - Figure not responding until loop is done

I am trying to animate a plot where my two vectors X,Y are updating through a loop.
I am using FuncAnimation. The problem I am running into is the Figure would show Not Responding or Blank until the loop is completed.
So during the loop, I would get something like:
But if I stopped the loop or at the end, the figure would appear.
I have set my graphics backend to automatic.
Here is the example of the code:
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def animate( intermediate_values):
x = [i for i in range(len(intermediate_values))]
y = intermediate_values
plt.cla()
plt.plot(x,y, label = '...')
plt.legend(loc = 'upper left')
plt.tight_layout()
x = []
y = []
#plt.ion()
for i in range(50):
x.append(i)
y.append(i)
ani = FuncAnimation(plt.gcf(), animate(y), interval = 50)
plt.tight_layout()
#plt.ioff()
plt.show()
The structure of animation in matplotlib is that the animation function is not used in the loop process, but the animation function is the loop process. After setting up the initial graph, the animation function will update the data.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
x = []
y = []
fig = plt.figure()
ax = plt.axes(xlim=(0,50), ylim=(0, 50))
line, = ax.plot([], [], 'b-', lw=3, label='...')
ax.legend(loc='upper left')
def animate(i):
x.append(i)
y.append(i)
line.set_data(x, y)
return line,
ani = FuncAnimation(fig, animate, frames=50, interval=50, repeat=False)
plt.show()

How to use an image instead of a marker in an animated graph using Matplot.lib

I have been trying to use an image that moves in an animation instead of "ro" (red dots) or similar markers. image_1, image_2, image_3 So far I have a graph that has a little red dot moving over the dotted line. I want an image to be the one that moves through the dotted line instead of a red dot.
Here is my code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
img = plt.imread("/Users/salomondabbah/Desktop/mar.jpg")
ax.imshow(img, extent=[0, 2 * np.pi, -1, 1])
xtrack = np.linspace(0, 2 * np.pi, 240)
ytrack = np.sin(xtrack)
ln, = plt.plot([], [], ***'ro'***, zorder=15)
ax.plot(xtrack, np.sin(xtrack), 'k', linewidth=25.0, zorder=5)
ax.plot(xtrack, ytrack, '--y',linewidth=2.0, zorder=10)
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
ln.set_data(frame, np.sin(frame))
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=False)
plt.show()
Thank you in advance for any solutions provided to my issue!
Similar to what you are doing, but using set_extent with imshow instead of set_data with a line:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots(figsize=(5,5))
xdata, ydata = [], []
xtrack = np.linspace(0, 2 * np.pi, 240)
ytrack = np.sin(xtrack)
img = plt.imread("car.png")
im = ax.imshow(img, zorder=10, aspect='auto')
ax.plot(xtrack, np.sin(xtrack), 'k', linewidth=25.0, zorder=5)
ax.plot(xtrack, ytrack, '--y',linewidth=2.0, zorder=10)
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
l = frame - 0.5
r = frame + 0.5
b = np.sin(frame) - 0.2
t = np.sin(frame) + 0.2
im.set_extent([l,r,b,t])
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=False)
ani.save('ani.gif', writer='pillow')
The only finnicky thing is getting the desired size & aspect ratio of the graph and size & aspect ratio of the car. The overall graph can be edited by using figsize when it is created as I have added. But if you don't set the aspect parameter of the imshow to auto, it will override the figure size and shape, in order to make the image have correct dimensions (it seems). So you may have to play around with the 0.5 and 0.2 values in the update to keep your image having approximately correct dimensions.

How to show only 'x' amount of values on a graph in python

I am new to python and am carrying out some little projects along side watching tutorials to enable me to learn.
I have recently been working with some APIs to collect data - I save this data in a CSV file and then open the CSV file to show the data as a graph.
I want the graph to show the data LIVE, but in doing so I only want 10 values on the screen at once, so when the 11th value is plotted, the 1st is no longer visible unless the scrolling function is used to look back at it..
I have managed to pull together the code that plots the live data from the CSV file, as well as some code that creates the graph in the desired format - but as I am quite new to python I am unsure of how I'd make them work together.. Any advice would be greatly appreciated.
Below is the code that I have created to read and plot from a CSV file:
import random
from itertools import count
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
index = count()
def animate(i):
data = pd.read_csv('x.csv')
x = data['Time']
y = data['R1Temp']
y1 = data['R2Temp']
y2 = data['R3Temp']
plt.cla()
plt.plot(x, y, marker = 'o', label='Room 1 Temp')
plt.plot(x, y1, marker = 'o', label='Room 2 Temp')
plt.plot(x, y2, marker = 'o', label='Room 3 Temp')
plt.xlabel("Time")
plt.ylabel("Temperature °C")
plt.title("Live temperature of Rooms")
plt.legend(loc='upper left')
plt.tight_layout()
ani = FuncAnimation(plt.gcf(), animate, interval=1000)
plt.tight_layout()
plt.show()
Below is the code that shows the way in which I'd like the graph to format the data plots:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def update(frame):
global x, y
start = x[max(frame-PAN//2, 0)]
start = x[max(frame-PAN+1, 0)]
end = start + PAN
ax.set_xlim(start, end)
start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, TICK))
ax.figure.canvas.draw()
line1.set_data(x[0:frame+1], y[0:frame+1])
return (line1,)
# main
NUM = 100
TICK = 1
PAN = 10
x = np.arange(start=1, stop=NUM + 1, step=1)
for i in range(NUM):
y = np.random.rand(NUM) * 100
fig, ax = plt.subplots()
ax.set_xlim(0, PAN)
start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, TICK))
ax.set_ylim(0, 100)
line1, = ax.plot([], [], color="r")
ani = animation.FuncAnimation(fig, update, frames=len(x), interval=1000, repeat=False)
plt.show()
I have tried many ways to merge them together, but I just cant seem to find the correct way to go about it.
Thanks in advance!!
Showing the last N time points is quite easy. Just use DataFrame.tail() to get the last N rows of your dataframe.
Note that when doing an animation, the recommended way is to create your axes and artists outside the animation code, and only update your artists' data inside the animate code.
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
l1, = ax.plot([], [], marker='o', label='Room 1 Temp')
l2, = ax.plot([], [], marker='o', label='Room 2 Temp')
l3, = ax.plot([], [], marker='o', label='Room 3 Temp')
plt.xlabel("Time")
plt.ylabel("Temperature °C")
plt.title("Live temperature of Rooms")
plt.legend(loc='upper left')
plt.tight_layout()
def animate(i, N):
data = pd.read_csv('x.csv').tail(N)
l1.set_data(data['Time'], data['R1Temp'])
l2.set_data(data['Time'], data['R2Temp'])
l3.set_data(data['Time'], data['R3Temp'])
ax.relim()
ax.autoscale_view()
return l1, l2, l3
ani = FuncAnimation(fig, animate, interval=1000, frames=None, fargs=(10,))
plt.show()

How to animate a complex function with matplotlib?

I want to make an animation with the function ((phi^n)-((-1/phi)^n))/(5^0.5) (Binet's formula) as n ∈ ℝ,
so that the graph starts as a straight line on the real axes then shifts into the actual graph.
I have tried to add
from matplotlib.animation import FuncAnimation
.
.
.
def g(val):
main_graph.set_ydata(imag(f(x))*val)
return main_graph,
animation = FuncAnimation(main_graph, func=g, frames=arange(0, 10, 0.1), interval=10)
plt.show
However, it did not work and I have no clue why I followed various tutorials and all of them had the same result (An error)
I also tried
import matplotlib.animation as animation
.
.
.
def init():
main_graph.set_ydata([np.nan] * len(real(f(x))))
return main_graph,
def g(val):
main_graph.set_ydata(imag(f(x))*val)
return main_graph,
ani = animation.FuncAnimation(main_graph, g, init_func=init, interval=2, blit=True, save_count=50)
The error, in both cases, is AttributeError: 'Line2D' object has no attribute 'canvas'. Here is the full code
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from numpy import arange, real, imag
phi = (1+(5**0.5))/2
x = arange(0,5,0.01)
def f(x):
return ((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position(('data', 0.0))
ax.spines['bottom'].set_position(('data', 0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
#labels for x and y axes
plt.xlabel('real')
plt.ylabel('imag')
plt.grid(alpha=.4,linestyle=':')
main_graph, = plt.plot(real(f(x)),imag(f(x)), label='((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)')
plt.legend()
def g(val):
main_graph.set_ydata(imag(f(x))*val)
return main_graph,
animation = FuncAnimation(main_graph, func=g, frames=arange(0, 10, 0.1), interval=10)
plt.show()
To see the final graph use this code
import matplotlib.pyplot as plt
from numpy import arange, real, imag
phi = (1+(5**0.5))/2
x = arange(0,5,0.01)
def f(x):
return ((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position(('data', 0.0))
ax.spines['bottom'].set_position(('data', 0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
#labels for x and y axes
plt.xlabel('real')
plt.ylabel('imag')
plt.grid(alpha=.4,linestyle=':')
main_graph, = plt.plot(real(f(x)),imag(f(x)), label='((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)')
plt.legend()
plt.show()
I have adapted the example from matplotlib's animation documentation. Here's how the code has been modified to allow for the modification of axis elements (in this case, the legend) by setting blit=False
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from numpy import arange, real, imag
phi = (1+(5**0.5))/2
x = arange(0,5,0.01)
def f(x):
return ((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)
fig = plt.figure()
main_graph, = plt.plot(real(f(x)),imag(f(x)), label='((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)')
#labels for x and y axes
plt.xlabel('real')
plt.ylabel('imag')
plt.grid(alpha=.4,linestyle=':')
#plt.legend(loc=4)
def init():
global legs
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position(('data', 0.0))
ax.spines['bottom'].set_position(('data', 0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_ylim(-4,4)
legs=ax.legend(loc=4, prop={'size': 12})
return main_graph,
def g(val):
main_graph.set_ydata(imag(f(x))*val)
label = '((phi**(x+0j))-((-1/phi)**(x+0j)))/(5**0.5)x{}'.format(val)
legs.texts[0].set_text(label)
return main_graph,
#Note that blit has been set to False, because axes elements are being modified
animation = FuncAnimation(fig, func=g,frames=arange(0, 10, 0.1), init_func=init,interval=10,blit=False)
animation.save('animation.gif', writer='imagemagick', fps=30)
plt.show()
Here's how the animation is:

How do I get a fill_between shape in Funcanimation?

I would like to make a moving plot where the area under the curve gets colored while the curve is getting plotted.
I have googled a bit and found that I should somehow create a patch. However, I do not understand any of the examples they give, so let me ask it here with my specific example:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import pylab as p
data = np.loadtext('datafile.dat', delimiter=',')
A = data[:,1]
B = data[:,2]
fig = plt.figure(figsize=(25,5), dpi=80)
ax = plt.axes(xlim=(0, 3.428), ylim=(-1,1))
line, = ax.plot([], [], lw=5)
def init():
line.set_data([], [])
return line,
def animate(i):
x = A[0:(i-1)*400]
y = B[0:(i-1)*400]
line.set_data(x,y)
# Here is the problem. I would now like to add the following line
# p.fill_between(x, 0, y, facecolor = 'C0', alpha = 0.2)
return line,
anim = animation.FuncAnimation(fig,animate, init_func=init, frames = 857, interval=20, blit=True)
I hope someone can give me a solution for my problem or at least point me in the correct direction.
So my question would be: how can I add the commented part without any errors?
Assuming you want blit = True, you will need to return the patch produced by fill_between as well.
p = plt.fill_between(x, y, 0)
return line, p,
Complete working example:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
X = np.linspace(0,3.428, num=250)
Y = np.sin(X*3)
fig = plt.figure(figsize=(13,5), dpi=80)
ax = plt.axes(xlim=(0, 3.428), ylim=(-1,1))
line, = ax.plot([], [], lw=5)
def init():
line.set_data([], [])
return line,
def animate(i):
x = X[0:(i-1)]
y = Y[0:(i-1)]
line.set_data(x,y)
p = plt.fill_between(x, y, 0, facecolor = 'C0', alpha = 0.2)
return line, p,
anim = animation.FuncAnimation(fig,animate, init_func=init,
frames = 250, interval=20, blit=True)
plt.show()

Categories