Motivation
This note is related to the dynamic visualization note . Sometimes we want to export a movie or animation from matlab or python. Here summarize some common code clips.
Matlab
GIF
Others: MOV AVI MP4 etc
Note GIF is less compressed so it’s often huge comparing to other formats.
So for outputing lots of movies please use AVI. VideoWriter
if option.save
v = VideoWriter(fullfile(savedir,compose("%s_%s_Exp%d_%s_cc_%s.avi",Animal,ExpType,Expi,layername,Meanstr)));
v.FrameRate = 2;open(v);
fprintf("Writing video to %s\n",fullfile(savedir,compose("%s_%s_Exp%d_%s_cc_%s.avi",Animal,ExpType,Expi,layername,Meanstr)))
end
CMIN = prctile(plot_tsr, [ 2], 'all');
CMAX = prctile(plot_tsr, [98], 'all');
figure(18);set(18,'Position',[0 435 552 543])
IMS = imagesc(plot_tsr(:,:,1));axis image
caxis([CMIN,CMAX]);colorbar;
for fi = 1:size(plot_tsr,3)
wdw = wdw_vect(fi,:); % [1, 20] + 10 * (fi - 1);
IMS.CData = plot_tsr(:,:,fi);
IMS.Parent.Title.String = sprintf("%s %s Exp %d Pref chan %d\n %s CorreCoef in of VGG16 %s feature\n with [%d,%d] ms firing rate", ...
Animal, ExpType, Expi, EStats(Expi).units.pref_chan, Meanstr, layername, wdw(1), wdw(2));
pause(0.2)
Fs = getframe(18);
if option.save, writeVideo(v,Fs); end
drawnow;
end
if option.save, close(v); end
Python
https://www.learnopencv.com/read-write-and-display-a-video-using-opencv-cpp-python/
Getframe like matlab
This is a small useful trick just like matlab. It can save figures as frames and
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.animation import FFMpegWriter
metadata = dict(title='Movie Test', artist='Matplotlib',
comment='Movie support!')
writer = FFMpegWriter(fps=15, metadata=metadata)
fig = plt.figure()
l, = plt.plot([], [], 'k-o')
plt.xlim(-5, 5)
plt.ylim(-5, 5)
x0, y0 = 0, 0
with writer.saving(fig, "writer_test.mp4", 100):
for i in range(100):
x0 += 0.1 * np.random.randn()
y0 += 0.1 * np.random.randn()
l.set_data(x0, y0)
writer.grab_frame()
https://www.sfn.org/meetings/neuroscience-2020/abstracts/call-for-abstracts
Matplotlib.animation
This is useful when you want to animate a Figure or axes. It has 2 major classes, artist animation and function animation
For artist animation, you construct a list of list. In each sublist, it contains a group of Artist
objects to show together. So note that the title and the figure can be different artists.
img = [] # some array of images
frames = [] # for storing the generated images
fig = plt.figure()
for i in xrange(6):
im = plt.imshow(img[i], cmap=cm.Greys_r,animated=True)
frames.append([im])
anim = animation.ArtistAnimation(fig, frames, interval=200, blit=True, repeat_delay=1000)
anim.save('movie.mp4')
plt.show()
This method has a known issue that axes title will not change through out animation! You need to use text
instead.
fig, ax = plt.subplots()
ims=[]
for iternum in range(4):
title = plt.text(0.5,1.01,iternum, ha="center",va="bottom",color=np.random.rand(3),
transform=ax.transAxes, fontsize="large")
text = ax.text(iternum,iternum,iternum)
scatter = ax.scatter(np.random.randint(0,10,5), np.random.randint(0,20,5),marker='+')
ims.append([text,scatter,title,])
ani = animation.ArtistAnimation(fig, ims, interval=500, blit=False, repeat_delay=2000)
https://stackoverflow.com/questions/47421486/matplotlib-artist-animation-title-or-text-not-changing
In contrast, function animation is very easy to update title. In its essence, you write an update function to change the figure using the iteration number. And then send the function to animation.FuncAnimation
.
VMIN, VMAX = np.percentile(ThrL1_data,[2,98])
fig, ax = plt.subplots()
ccmap = ax.imshow(ThrL1_data[:, :, 10],vmin=VMIN,vmax=VMAX)
Title = ax.set_title("Rate [1, 20]ms")
plt.colorbar(ccmap)
def update(fi):
wdw = wdw_vect[fi,:]
ccmap.set_data(ThrL1_data[:, :, fi])
Title.set_text("Rate [%d, %d]ms"%(wdw[0], wdw[1]))
plt.pause(0.2)
clear_output(wait=True)
display(fig)
anims = animation.FuncAnimation(fig, update, frames=cc_tsr.shape[-1], interval=200, blit=False,
repeat_delay=2000)
anims.save('Beto_Manif_Exp11_conv4-3_2.mp4')
plt.show()
cv2.VideoWriter
This is useful when you want to animate a sequence of images
Matplotlib Export
(This seems irrelevant here. Grab frame is much easier. )
fig = Figure()
# attach a non-interactive Agg canvas to the figure
# (as a side-effect of the ``__init__``)
canvas = FigureCanvas(fig)
ax = fig.subplots()
ax.plot([1, 2, 3])
ax.set_title('a simple figure')
# Force a draw so we can grab the pixel buffer
canvas.draw()
# grab the pixel buffer and dump it into a numpy array
IMG = np.array(canvas.renderer.buffer_rgba())