I have an animation created with plt.pause as below...
import matplotlib.pyplot as plt
for i in range(10):
plt.scatter(0, i)
plt.pause(0.01)
plt.show()
How can I save this as a video file, e.g. a .mp4 file?
First, I have to redefine the plotting as a function with the plotted point given by a frame i. plt.pause() can be replaced by matplotlib.animate. Finally, I used a package suggested here to get the conversion to .mp4 format. You will need to install MoviePy:
pip install MoviePy
and then I just animate the function with matplotlib.animate into a .gif format before sending it to MoviePy. You'll need to figure out what directory you want this all to happen in. I'm just using the current working directory.
Here is the code:
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import os
import moviepy.editor as mp
frames=20
fig = plt.figure()
ax = plt.gca()
def scatter_ani(i=int):
plt.scatter(0, i)
name = r"\test.gif"
path = str(os.getcwd())
anim = ani.FuncAnimation(fig, scatter_ani, frames = frames, interval=50)
anim.save(path+name)
clip = mp.VideoFileClip(path+name)
clip.write_videofile(path+r"\test.mp4")
The gif is then
To tweak the length of the animation, check out the docs for matplotlib.animate. For example, if you want to clear all of the previous data-points and show only the dot moving up, then you need to clear the axes in the function, and bound the y-axis so you see the motion ie
def scatter_ani(i=int):
ax.clear()
ax.set_ylim(0, frames+1)
plt.scatter(0, i)
to get:
Related
In order to save a wave spectrum image, a typical code is as following,
###########################
import matplotlib.pyplot as plt
import librosa.display
y, sr = librosa.load(filename)
fig = plt.Figure()
canvas = FigureCanvas(fig)
...
librosa.display.specshow(logmelspec, sr=sample_rate, x_axis='time', y_axis='log')
fig.savefig('spec.png')
The question is, 'fig' is created in Figure class, and is also a parameter for FigureCanvas, librosa.display.specshow is a function belong to librosa.display class.
How does fig know the input data for fig.savefig ?
How does the data exchange work between 'fig' and 'librosa'?
When I run this code, it did save the right image as expected(however, if I build a FileDialog based application, load a new wav file and call 'fig.savefig' again, the image will become random).
It seems the following way can fix this issue,
plt.savefig("spec.png")
plt.clf()
plt.close()
I am generating a live plot using matplotlib's funcAnimation function such as in the example below. To be clear I am plotting data that is dynamically updating in real-time and I want to view these updates in the browser rather than in its own local plotting window.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
import mpld3
def animate(i):
plt.clf()
#generate random data
x = np.array([i for i in range(100)])
y = np.random.normal(loc=0,scale=1, size = 100)
plt.scatter(x,y)
def main():
fig = plt.figure()
ani = animation.FuncAnimation(fig, animate, interval=1000)
ani.save('animation.gif', fps=10)
plt.show()
#mpld3.show()
if __name__ == '__main__':
main()
It opens the plot in its own little window.
I was wondering what is the best/quickest way to open this in browser instead? I tried using mpld3 as recommended in some places (see the commented bits of code in my code snippet), but all I get is a static page that does not update. I would like the plot to be redrawn in the browser during each redraw done by the animate fuction as it does when the plot is generated in it's own window instead as in the first image.
Thanks in advance for any help anyone has to offer!
I am working on a project that involves generating a matplotlib animation using pyplot.imshow for the frames. I am doing this in a jupyter notebook. I have managed to get it working, but there is one annoying bug (or feature?) left. After the animation is created, Jupyter shows the last frame of the animation in the output cell. I would like the output to include the animation, captured as html, but not this final frame. Here is a simple example:
import numpy as np
from matplotlib import animation
from IPython.display import HTML
grid = np.zeros((10,10),dtype=int)
fig1 = plt.figure(figsize=(8,8))
ax1 = fig1.add_subplot(1,1,1)
def animate(i):
grid[i,i]=1
ax1.imshow(grid)
return
ani = animation.FuncAnimation(fig1, animate,frames=10);
html = HTML(ani.to_jshtml())
display(html)
I can use the capture magic, but that suppresses everything. This would be OK, but my final goal is to make this public, via binder, and make it as simple as possible for students to use.
I have seen matplotlib animations on the web that don't seem to have this problems, but those used plot, rather than imshow, which might be an issue.
Any suggestions would be greatly appreciated.
Thanks,
David
That's the answer I got from the same thing I was looking for in 'jupyter lab'. Just add plt.close().
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from IPython.display import HTML
grid = np.zeros((10,10),dtype=int)
fig1 = plt.figure(figsize=(8,8))
ax1 = fig1.add_subplot(1,1,1)
def animate(i):
grid[i,i]=1
ax1.imshow(grid)
return
ani = animation.FuncAnimation(fig1, animate,frames=10);
html = HTML(ani.to_jshtml())
display(html)
plt.close() # update
I keep getting this error when trying to save my animations in matplotlib:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
plt.rcParams['animation.ffmpeg_path'] = 'C:\FFmpeg\bin'
fig, ax = plt.subplots()
ax.set_xlim(-0.1 ,2*np.pi + 0.1)
ax.set_ylim(-1.1 ,1.1)
ln, = plt.plot([], [], '-')
x = np.linspace(0,2*np.pi,1000)
def update(frame):
y = frame*np.sin(x)
ln.set_data(x,y)
return ln,
ani = FuncAnimation(fig,
update,
frames=np.linspace(1,-1,1000),
interval=1000/144)
ani.save('lol.gif')
MovieWriter ffmpeg unavailable. Trying to use pillow instead.
This is a repetition of an unanswered question: UserWarning: MovieWriter ffmpeg unavailable
I tried running a sample code from here, but it still says ffmpeg isn't available, even though I installed and activated it according to wikihow. So even setting the path to the binary doesn't seem to work.
I can't set the fps or the dpi, or anything since the save function just defaults. What can I do so that python finally starts using ffmpeg?
I'm trying to create an animated histogram for work, using matplotlib.animation, but animation.FuncAnimation is not functioning properly : when using this code, that i found on the official documentation,
"""
A simple example of an animated plot
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))
def animate(i):
print(i)
line.set_ydata(np.sin(x + i/10.0)) # update the data
return line,
# Init only required for blitting to give a clean slate.
def init():
line.set_ydata(np.ma.array(x, mask=True))
return line,
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200),init_func=init,interval=25, blit=True)
plt.show()
I get as final result the graph created by init() function (an empty graph also), but no animate iterations. Furthermore, I tested other codes, which practically gave me the same result : i get the initialization, or the first frame, but not more. matplotlib and matplotlib.animation are installed, everything seems to be ok, except it doesn't work. Have someone an idea how to fix it ? (Thank you in advance :) !)
I had the same issue working with Jupyter notebook and I solved it by inserting the line
%matplotlib notebook
in the code.
It may be that IPython inside your Spyder is configured to automatically use the inline backend. This would show your plots inside the console as png images. Of course png images cannot be animated.
I would suggest not to use IPython but execute the script in a dedicated Python console. In Spyder, go to Run/Configure.. and set the option to new dedicated Python console.