Matplotlib animation of a step - python

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()

Related

Why does my graph not plot the points generated by linspace? (animation)

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)

TypeError: 'MovieWriterRegistry' object is not an iterator

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')

Python matplotlib.animation.FuncAnimation never makes a second frame iteration

I am trying to use matplotlib.animation.FuncAnimation to create a custom animation. However, the FuncAnimation function does not seem to make a second iteration of the animate function. I have enclosed a simple example that I found online, which is supposed to work and draw a sine wave. Both on my computer and the Amazon EC2 server the script calls animate and draws the frame for one iteration. A second iteration never seems to happen. What am I getting wrong?
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)
# animation function. This is called sequentially
def animate(i):
print("animate invoked")
print(i)
x = np.linspace(0, 2, 1000)
y = np.sin(2 * np.pi * (x - 0.01 * i))
line.set_data(x, y)
return line,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, frames=np.arange(100), interval=200)
plt.show()
Script output:
animate invoked
0
According to the example here, you need to pass an init_func to FunctionAnimation as well. So you can do:
# First set up the figure, the axis, and the plot element we want to animate
fig, ax = plt.subplots()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)
# init function
def init():
return line,
# animation function. This is called sequentially
def animate(i):
print("animate invoked")
x = np.linspace(0, 2, 1000)
y = np.sin(2 * np.pi * (x - 0.01 * i))
line.set_data(x, y)
return line,
# call the animator. blit=True means only re-draw the parts that have changed.
anim = FuncAnimation(fig, animate, init_func=init, frames=np.arange(100), interval=200)
# for jupyter notebook
HTML(anim.to_html5_video())
Which gives:

Plotting animations to Jupyter Notebook: why does HTML(animator.to_html()) not work when called in an inner scope (i.e in a function)?

The following source shows how to plot animations inline to Jupyter Notebook (with matplotlib of course):
http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-as-interactive-javascript-widgets/
Running the code, it works when I run it directly in a cell (i.e like a script):
from matplotlib import animation, rc
from IPython.display import HTML
fig, ax = plt.subplots()
ax.set_xlim((0, 2))
ax.set_ylim((-2, 2))
line, = ax.plot([], [], lw=2)
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))
line.set_data(x, y)
return (line,)
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20,
blit=True)
#HTML(anim.to_html5_video())
HTML(anim.to_jshtml())
However, when I try to run this within a function, it does not plot an inline figure:
from matplotlib import animation, rc
from IPython.display import HTML
def plot_anim_funct():
fig, ax = plt.subplots()
ax.set_xlim((0, 2))
ax.set_ylim((-2, 2))
line, = ax.plot([], [], lw=2)
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))
line.set_data(x, y)
return (line,)
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20,
blit=True)
#HTML(anim.to_html5_video())
HTML(anim.to_jshtml())
plot_anim_funct()
It doesn't plot anything actually (well there is a static non-animated figure, but that always shows up, I think from running anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=20, blit=True).
Of course, returning the animator object from the function, and then running HTML(anim.to_jshtml()) works as before.
Is there a way to get this working inside a function or do I just need to return the animator every time?
HTML(..) creates a html string from an object. If this is not the last line of the cell it will not be shown. To be on the safe side, you may use IPython.display.display
display(HTML(anim.to_jshtml()))
Complete working code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML, display
def plot_anim_funct():
fig, ax = plt.subplots()
ax.set_xlim((0, 2))
ax.set_ylim((-2, 2))
line, = ax.plot([], [], lw=2)
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))
line.set_data(x, y)
return (line,)
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=100, interval=20,
blit=True)
display(HTML(anim.to_jshtml()))
plot_anim_funct()

How to make an animation in SymPy using Matplotlib (Python)

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()

Categories

Resources