I have this code. I want to add a subplot to draw the cosine function. (I do not want to create a class). The second plot should be dynamically updated as well
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def data_gen():
t = data_gen.t
cnt = 0
while cnt < 1000:
cnt+=1
t += 0.05
yield t, np.sin(2*np.pi*t) * np.exp(-t/10.)
data_gen.t = 0
fig, ax = plt.subplots()
line, = ax.plot([], [], lw=2)
ax.set_ylim(-1.1, 1.1)
ax.set_xlim(0, 5)
ax.grid()
xdata, ydata = [], []
def run(data):
# update the data
t,y = data
xdata.append(t)
ydata.append(y)
xmin, xmax = ax.get_xlim()
if t >= xmax:
ax.set_xlim(xmin, 2*xmax)
ax.figure.canvas.draw()
line.set_data(xdata, ydata)
return line,
ani = animation.FuncAnimation(fig, run, data_gen, blit=True, interval=10,
repeat=False)
plt.show()
Basically you can use a very similar structure as the one you have in your example. You only need to create an additional axes (subplot) and a second line object:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def data_gen():
t = data_gen.t
cnt = 0
while cnt < 1000:
cnt+=1
t += 0.05
y1 = np.sin(2*np.pi*t) * np.exp(-t/10.)
y2 = np.cos(2*np.pi*t) * np.exp(-t/10.)
# adapted the data generator to yield both sin and cos
yield t, y1, y2
data_gen.t = 0
# create a figure with two subplots
fig, (ax1, ax2) = plt.subplots(2,1)
# intialize two line objects (one in each axes)
line1, = ax1.plot([], [], lw=2)
line2, = ax2.plot([], [], lw=2, color='r')
line = [line1, line2]
# the same axes initalizations as before (just now we do it for both of them)
for ax in [ax1, ax2]:
ax.set_ylim(-1.1, 1.1)
ax.set_xlim(0, 5)
ax.grid()
# initialize the data arrays
xdata, y1data, y2data = [], [], []
def run(data):
# update the data
t, y1, y2 = data
xdata.append(t)
y1data.append(y1)
y2data.append(y2)
# axis limits checking. Same as before, just for both axes
for ax in [ax1, ax2]:
xmin, xmax = ax.get_xlim()
if t >= xmax:
ax.set_xlim(xmin, 2*xmax)
ax.figure.canvas.draw()
# update the data of both line objects
line[0].set_data(xdata, y1data)
line[1].set_data(xdata, y2data)
return line
ani = animation.FuncAnimation(fig, run, data_gen, blit=True, interval=10,
repeat=False)
plt.show()
Related
I am trying to dynamically update the bar chart value labels in an animated matplotlib chart. The toy code I am using is here:
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
fig = plt.figure()
x = [1,2,3,4,5]
y = [5,7,2,5,3]
ax1 = plt.subplot(2, 1, 1)
ax2 = plt.subplot(2, 1, 2)
data = np.column_stack([np.linspace(0, yi, 50) for yi in y])
rects = ax1.bar(x, data[0], color='c')
line, = ax2.plot(x, data[0], color='r')
ax1.set_ylim(0, max(y))
ax1.bar_label(rects, padding=1)
ax2.set_ylim(0, max(y))
def animate(i):
for rect, yi in zip(rects, data[i]):
rect.set_height(yi)
ax1.bar_label(rects, padding=1)
line.set_data(x, data[i])
anim = animation.FuncAnimation(fig, animate, frames=len(data), interval=40)
plt.show()
The value labels are being printed at each time step, but they remain on the plot.
How can I update the value labels with each step in the animation without having the old labels remain on the chart?
You can recreate rects in each frame in clearing ax1:
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
fig = plt.figure()
x = [1,2,3,4,5]
y = [5,7,2,5,3]
ax1 = plt.subplot(2, 1, 1)
ax2 = plt.subplot(2, 1, 2)
data = np.column_stack([np.linspace(0, yi, 50) for yi in y])
ax1.set_ylim(0, max(y))
ax2.set_ylim(0, max(y))
line, = ax2.plot(x, [0] * len(x), color='r')
def animate(i):
ax1.cla()
ax1.set_ylim(0, max(y))
rects = ax1.bar(x, data[i], color='c')
ax1.bar_label(rects, padding=1)
line.set_data(x, data[i])
anim = animation.FuncAnimation(fig, animate, frames=len(data), interval=40)
plt.show()
I am trying to create an animation of growing concentric circles in python. As the program runs, more circles should generate from the centre and grow outwards
Right now I have this, which just creates one expanding circle.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
fig = plt.figure()
ax = plt.axes(xlim=(0, 128), ylim=(0, 128))
line, = ax.plot([], [], lw=2)
def init():
line.set_data([], [])
return line,
def animate(i):
theta = np.linspace(0, 2 * np.pi, 100)
r = np.sqrt(i)
x = r * np.cos(theta) + 64
y = r * np.sin(theta) + 64
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=1000, interval=10, blit=True)
plt.gca().set_aspect('equal', adjustable='box')
plt.show()
How do I modify my code so that new growing circles generate from the middle to create growing concentric circles.
You can keep a list of lines, and add a new one every few frames with a smaller radius
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
fig = plt.figure()
ax = plt.axes(xlim=(0, 128), ylim=(0, 128))
# Keep a list of lines instead of a single one
lines = ax.plot([], [], lw=2)
def init():
for line in lines:
line.set_data([], [])
return lines
def animate(i):
# Add a new line every 100 frames
if i // 100 >= len(lines):
new_line, = ax.plot([], [], lw=2)
lines.append(new_line)
for line_num, line in enumerate(lines):
theta = np.linspace(0, 2 * np.pi, 100)
# Reduce the radius of the new lines
r = np.sqrt(i - 100 * line_num)
x = r * np.cos(theta) + 64
y = r * np.sin(theta) + 64
line.set_data(x, y)
return lines
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=1000, interval=10, blit=True)
plt.gca().set_aspect('equal', adjustable='box')
plt.show()
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.
I am trying to create a 3D line animation, on top of a 3D surface plot in matplotlib.
I am able to plot the 3D surface, but there is no animation. And there is no error in the code. I am setting the X,Y and Z values of the 3D line upto the current frame.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib import animation
def f(x,y):
return x+y
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X = np.arange(0, 10, 1)
Y = np.arange(0, 10, 1)
Z = X+Y
X1, Y1 = np.meshgrid(X, Y)
Z1 = f(X1, Y1)
ax.plot_surface(X1, Y1, Z1, color='b', alpha=0.5)
plt.show()
line, = ax.plot([], [], [], lw=2)
def init():
line.set_data([], [])
line.set_3d_properties([])
return line
def animate(i, line, X, Y, Z):
line.set_data(X[:i], Y[:i])
line.set_3d_properties(Z[:i])
return line
anim = animation.FuncAnimation(fig, animate, init_func=init, fargs=(line, X, Y, Z),
frames=10, interval=200,
repeat_delay=5, blit=True)
plt.show()
You don't get any error, because you call plt.show() before any animation is even defined. Remove the first plt.show().
You will then get errors as expected. The problem is that you need to return a list of artists from the animating functions when using blit=True. This is easily achieved by adding a comma,
return line,
Complete code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib import animation
def f(x,y):
return x+y
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X = np.arange(0, 10, 1)
Y = np.arange(0, 10, 1)
Z = X+Y
X1, Y1 = np.meshgrid(X, Y)
Z1 = f(X1, Y1)
ax.plot_surface(X1, Y1, Z1, color='red', alpha=0.5)
line, = ax.plot([], [], [], lw=2)
def init():
line.set_data([], [])
line.set_3d_properties([])
return line,
def animate(i, line, X, Y, Z):
line.set_data(X[:i], Y[:i])
line.set_3d_properties(Z[:i])
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init, fargs=(line, X, Y, Z),
frames=10, interval=200,
repeat_delay=5, blit=True)
plt.show()
I am trying to make this animated so that the dot and the green line move due to the for loop. This code displays 3 different graphs one below the other. The middle graph has no animation section.
x =lag_range
count = 0
plt.ion()
fig, ax = plt.subplots()
for b in x:
plt.subplot(311)
plt.plot(x,pear_corr, color='b', linewidth=1.5, label ='Pearson')
plt.plot(x,spear_corr, color ='r', linewidth=1.5, label='Spearman')
plt.plot(x[count],pear_corr[count],'yo')
plt.legend()
axes = plt.gca()
plt.ylabel('Correlation coefficients')
plt.xlabel('Lag times /days')
axes.set_xlim([min(lag_list),last])
axes.set_ylim(-1,1)
plt.subplot(312)
plt.plot(x,pear_p_values, color='b', linewidth=1.5)
plt.plot(x,spear_p_values, color ='r', linewidth=1.5)
axes = plt.gca()
plt.ylabel('P values')
plt.xlabel('Lag times /days')
axes.set_xlim([min(lag_list),last])
plt.subplot(313)
ax1 = plt.subplot(313)
x_for_p = range(len(x_prices))
ax1.plot(x_for_p, x_prices, color ='grey', linewidth=1.5)
ax1.set_ylabel('Share price', color ='grey')
ax1.tick_params('y', colors='grey')
ax1.set_xlabel('Days')
axes = plt.gca()
axes.set_xlim([min(lag_list),(2*last)])
ax2 = ax1.twinx()
x_for_den = range(b,(b+len(x_prices)))
ax2.plot(x_for_den, y_planes, color='g', linewidth=1.5)
ax2.set_ylabel('Plane density', color='g')
ax2.tick_params('y', colors='g')
count += 1
plt.pause(2)
plt.draw()
cross_corr2_vis(prices, density_p3)
If you could share a working code or just definitions of variables pear_corr, spear_corr, etc., the following code might have not resulted in this simple animation:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
N_points = 1000
x = np.linspace(0,2.*np.pi,N_points)
y = np.sin(x)
fig, ax = plt.subplots()
ax.set_xlim([0,2.*np.pi])
ax.set_ylim([-1,1])
line, = ax.plot( [],[], lw=2, color='g')
sctr = ax.scatter([],[], s=100, color='r')
def animate(i):
line.set_ydata(y[:i+1]) # update
line.set_xdata(x[:i+1])
sctr.set_offsets((x[i],y[i]))
return line,sctr
ani = animation.FuncAnimation(fig, animate, N_points, interval=5, blit=True)
plt.show()