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()
Related
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
x, y = [], []
line, = plt.plot([], [], 'bo')
circle = plt.Circle((0,0), 1, color = 'g', fill = False,)
def update(frame):
x.append(np.cos(frame))
y.append(np.sin(frame))
line.set_data(x, y)
return circle, line,
ani = FuncAnimation(fig, update, frames= np.linspace(0, 2*np.pi, 128), interval = 0.1)
plt.show()
what I want to animate
I tried to animate uniform circular motion through the code above, but what I can see was only dot moving, not the circle under the dot. How can I plot circle while animating dot?
You can add the circle to the artist with ax.add_artist(circle).
Also, I rewrite the update function so that it only tracks the current dot.
Reference: https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.add_artist.html
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots(figsize=(5, 5))
radius = 2
ax.set_xlim(-radius * 1.05, radius * 1.05)
ax.set_ylim(-radius * 1.05, radius * 1.05)
line, = plt.plot([], [], 'bo')
circle = plt.Circle((0, 0), radius, color='k', fill=False)
red_dot = plt.plot(0, 0, 'ro')
ax.set_aspect('equal')
ax.add_artist(circle)
ax.set_axis_off()
def update(i):
theta = np.deg2rad(i)
x = [0, radius * np.cos(theta)]
y = [0, radius * np.sin(theta)]
line.set_data(x, y)
ani = FuncAnimation(fig, update, frames=360, interval=30)
ani.save('fig_1.gif', writer='pillow', fps=45)
plt.show()
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)
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')
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.
I creating a Matplotlib animation of a step function. I am using the following code...
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.step([], [])
def init():
line.set_data([], [])
return line,
def animate(i):
x = np.linspace(0, 2, 10)
y = np.sin(2 * np.pi * (x - 0.01 * i))
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20, blit=True)
plt.show()
It vaguely resembles what I desire (something like the gif below) but instead of the values being constant and scrolling with time each step is dynamic and shifts up and down. How would go about changing my code to achieve this shift?
step explicitly plots steps between the input data points. It can never plot a partial "step".
You're wanting an animation with "partial steps" in between.
Instead of using ax.step, use ax.plot, but make a stepped series by plotting y = y - y % step_size.
In other words, something like:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 1000) # Using a series of 1000 points...
y = np.sin(x)
# Make *y* increment in steps of 0.3
y -= y % 0.3
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()
Notice the partial "steps" at the beginning and end
Incorporating this into your animation example, we'd get something similar to:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
def init():
line.set_data([], [])
return line,
def animate(i):
x = np.linspace(0, 2, 1000)
y = np.sin(2 * np.pi * (x - 0.01 * i))
y -= y % 0.3
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20, blit=True)
plt.show()