When I remove linspace and plot points by typing them into a list by hand they are plotted just fine. However switch to linspace, and the points on the graph come up blank. What am I missing here? Printing the linspace lists show they are generating the values, but they don't seem to make the graph
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
%matplotlib qt
fig = plt.figure(figsize=(6,4))
axes = fig.add_subplot(1,1,1)
plt.title("Image That's Moving")
P=np.linspace(1,50,100)
T=np.linspace(1,50,100)
Position =[P]
Time = [T]
p2=[P]
t2=[T]
x,y=[],[]
x2,y2=[],[]
def animate(i):
x.append(Time[i])
y.append((Position[i]))
x2.append(t2[i])
y2.append((p2[i]))
plt.xlim(0,100)
plt.ylim(0,100)
plt.plot(x,y, color="blue")
plt.plot(x2,y2, color="red")
anim = FuncAnimation(fig, animate, interval=300)
It seems like you are facing a problem because of Position = [P] and Time = [T].
Because numpy.linspace already returns an array, you don't need additional [].
Here is a working example that is referenced from matplotlib tutorial.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def init():
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
return ln,
def update(i):
xdata.append(T[i])
ydata.append(P[i])
ln.set_data(xdata, ydata)
return ln,
P = np.linspace(1, 50, 99)
T = np.linspace(1, 50, 99)
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')
ani = FuncAnimation(fig, update, frames=np.arange(len(T)),
init_func=init, blit=True)
plt.show()
It is not as easy as your written code and, also, not related to np.linspace, AIK. Combining Choi answer (or matplotlib example) with another related SO post we can do this job using some code like:
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
def init():
ax1.set_xlim(0, 100)
ax1.set_ylim(0, 100)
ax2.set_xlim(0, 100)
ax2.set_ylim(0, 100)
return ln, ln2
def update(i, Position, Time, P2, T2, ln, ln2):
x.append(Time[i])
y.append(Position[i])
x2.append(T2[i] + 10)
y2.append(P2[i] + 10)
ln.set_data(x, y)
ln2.set_data(x2, y2)
return ln, ln2
Position = P2 = np.linspace(1, 50, 100)
Time = T2 = np.linspace(1, 50, 100)
fig = plt.figure(figsize=(6, 4))
plt.title("Image That's Moving")
plt.xticks([])
plt.yticks([])
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
x, y, x2, y2 = [], [], [], []
ln, = ax1.plot([], [], 'bo')
ln2, = ax2.plot([], [], 'ro')
ani = FuncAnimation(fig, update, frames=Time.shape[0], fargs=(Position, Time, P2, T2, ln, ln2), init_func=init, blit=True)
ani.save('test.gif', writer='imagemagick', fps=30)
Related
Working example:
import numpy as np
import matplotlib as mpl
mpl.use("TKAgg")
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def animate(i, line, xs, ys):
ys.append(i)
ys = ys[-10:]
line.set_data(xs, ys)
return line,
fig = plt.figure()
ax = plt.axes(xlim=(0, 10), ylim=(0, 200))
line, = ax.plot([], [], lw=2)
xs = [val for val in range(10)]
ys = [0 for _ in range(10)]
anim = animation.FuncAnimation(fig, animate, fargs=(line, xs, ys), interval=10, blit=True)
Not working:
def animate(i, line, npx, npy):
npy = np.roll(npy, -1)
npy[-1] = i
line.set_data(npx, npy)
return line,
fig = plt.figure()
ax = plt.axes(xlim=(0, 10), ylim=(0, 200))
line, = ax.plot([], [], lw=2)
npx = np.linspace(0, 9, 10)
npy = np.zeros(10)
anim = animation.FuncAnimation(fig, animate, fargs=(line, npx, npy), interval=10, blit=True)
I tested this:
for i in range(10):
npy = np.roll(npy, -1)
npy[-1] = i
and it shows an array with the values as expected.
It's like npy is passed by value because at each iteration it resets to an array of zeroes as only the last value is non-zero. I don't understand why it works using a list and not a numpy array.
Edit: managed to make it "work" using this approach:
def animate(i, line, x):
y = line.get_ydata(orig=True)
y = np.roll(y, -1)
y[-1] = np.cos(np.pi*i*.1)
line.set_data(x, y)
return line,
fig = plt.figure()
ax = plt.axes(xlim=(0, 100), ylim=(-2, 2))
xs = [val for val in range(100)]
ys = np.zeros(100)
line, = ax.plot(xs, ys, lw=2)
anim = animation.FuncAnimation(fig, animate, fargs=(line, xs, ys), interval=10, blit=True)
I am trying to generate an animation of this plot with FuncAnimation. Those lines change over time, and that's what I would like to capture with FuncAnimation.
Currently, I can generate an animation, but one single line per subplot.
My code for animation roughly looks like this:
y1 = np.random.rand(1000, 5, 80)
y2 = np.random.rand(1000, 5, 80)
fig, axes = plt.subplots(1 ,2)
lines = []
x = np.linspace(0, 1, 1000)
for index, ax in enumerate(axes.flatten()):
if index == 0:
l, = ax.plot(y1[:,0,0], x)
if index == 1:
l, = ax.plot(y2[:,0,0], x)
lines.append(l)
def run(it):
for index, line in enumerate(lines):
if index == 0:
line.set_data(x, y1[:, 0, it]
if index == 1:
line.set_data(x, y2[:, 0, it]
return lines
ani = animation.FuncAnimation(fig, run, frames =80)
plt.show()
But, again, that code only generates only line per subplot. I'd like to have multiple lines per subplot (in the example code, that would be 5 lines). Does anyone know how do that? I don't have to use my code template, it could be something entirely different.
I've adapted the matplotlib animation example:
You can see which lines I've added/changed in the comments.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, (ax, ax2) = plt.subplots(2) #create two axes
xdata, ydata = [], []
ln, = ax.plot([], [], 'ro')
ln2, = ax2.plot([], [], 'go') # added
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
ax2.set_xlim(0, 2*np.pi) # added
ax2.set_ylim(-1, 1) # added
return ln,ln2 # added ln2
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
ln2.set_data(xdata, ydata) # added
return ln, ln2 #added ln2
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)
plt.show()
I was trying to create an animation of a sin wave using the FuncAnimation function from matplotlib, but it keeps throwing an error. I am a little new to it, but I read that there is a bug in the latest version? Anyone that can help me is welcome.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
plt.style.use('seaborn-pastel')
fig = plt.figure()
ax = plt.axes(xlim=(0, 4), ylim=(-2, 2))
line, = ax.plot([], [], lw=3)
def init():
line.set_data([], [])
return line,
def animate(i):
x = np.linspace(0, 4, 1000)
y = np.sin(2 * np.pi * (x - 0.01 * i))
line.set_data(x, y)
return line,
anim = FuncAnimation(fig, animate, init_func=init,
frames=200, interval=20, blit=True)
anim.save('sine_wave.gif', writer='imagemagick')
EDIT
I will try to be more precise (above details have been removed because they are unnecessary):
I want to make an animation where a (red) ball departs from (0,0) and draws the function sin(x). The function has to be drawn in blue, and the leading point has to be red (just as seen on the above pic)
I have found a method to draw (animate) a function:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'bo')
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)
plt.show()
My issue now is how to make the leading point red
I've been told that I should create an empty list of the line elements and use the "append()" method to add new line elements, but I still don't get how to do so.
Reference https://www.physicsforums.com/threads/how-to-make-an-animation-in-sympy-using-python.969906/
Thank you for your help.
Definitely, there are better ways:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
points = 50
x = np.linspace(0, 2 * np.pi, points)
y = np.sin(x)
fig, ax = plt.subplots()
ax.set_xlim(-0.3, 2 * np.pi + 0.3)
ax.set_ylim(-1.2, 1.2)
def animate(i):
if i == 0:
# fig.clear()
ax.plot(x[i], y[i], 'ro')
else:
# fig.clear()
ax.plot(x[i-1], y[i-1], 'bo')
ax.plot(x[i], y[i], 'ro')
anim = FuncAnimation(fig, animate, frames=points, repeat=False, interval=150)
plt.show()
I am trying to implement a live graph, however, my x and y axis are not showing up. Ive tried placing it in multiple areas of the code, however, none of those methods were successful.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
style.use('fivethirtyeight')
fig = plt.figure()
plt.xlabel('Time (s)')
plt.ylabel('Temperature (F)')
plt.title("Your drink's current temperature")
plt.xlabel('xlabel', fontsize=10)
plt.ylabel('ylabel', fontsize=10)
ax1 = fig.add_subplot(1,1,1)
def animate(i):
plt.xlabel('xlabel', fontsize=10)
plt.ylabel('ylabel', fontsize=10)
graph_data = open('plot.txt', 'r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line) > 1:
x, y = line.split(',')
xs.append(x)
ys.append(y)
ax1.clear()
ax1.plot(xs,ys)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
Here is the data file that I am reading from (plot.txt):
0,27.00
1,68.85
2,69.30
3,69.30
4,69.30
5,69.75
6,70.20
7,69.75
8,69.75
9,69.30
10,69.75
11,69.75
12,69.75
13,69.75
14,70.20
15,69.75
16,69.75
17,69.75
18,69.75
19,68.85
20,69.75
21,69.75
22,69.75
23,69.30
The problem is that you are calling clear in your animation function. You want to just update an existing artist (and let the animation code take care of re-drawing it as needed)
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as manimation
fig, ax = plt.subplots()
ax.set_xlabel('Time (s)')
ax.set_ylabel('Temperature (F)')
ax.set_title("Your drink's current temperature")
xs = np.linspace(0, 2*np.pi, 512)
ys = np.sin(xs)
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
ln, = ax.plot([], [], lw=3)
def init(*args, **kwargs):
ln.set_data([], [])
return ln,
def animate(i):
ln.set_data(xs[:i], ys[:i])
return ln,
ani = manimation.FuncAnimation(fig, animate,
frames=512, blit=True,
init_func=init)
plt.show()
if you need to read in from another data source (ex, your file) just read it and then set the data on your line.