I gave an answer on this thread , talking about fading point on matplotlib. And I got curious about ImportanceOfBeingErnest's answer. So I tried to play around with his code.
First, here is my code.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation
from matplotlib.colors import LinearSegmentedColormap
def get_new_vals():
x = 0
y = 0
while True:
if x >= .9:
x = 0
y = 0
x += .1
y += .1
yield x, y
def update(t, x_vals, y_vals, intensity, scatter, gen):
# Get intermediate points
new_xvals, new_yvals = gen.next()
x_vals.extend([new_xvals])
y_vals.extend([new_yvals])
# Put new values in your plot
scatter.set_offsets(np.c_[x_vals, y_vals])
# Calculate new color values
for index in range(len(intensity)):
if intensity[index] < .1:
intensity[index] = 0
intensity[index] *= .6
intensity.extend(1 for _ in xrange(len([new_xvals])))
intens_dup = np.array(intensity)
"""
intensity = np.concatenate((np.array(intensity) * .6, np.ones(len(new_xvals))))
"""
scatter.set_array(intens_dup)
# Set title
axis.set_title('Time: %0.3f' % t)
def anim_random_points(fig, axis):
x_vals = []
y_vals = []
intensity = []
iterations = 100
colors = [ [0, 0, 1, 0], [0, 0, 1, 0.5], [0, 0.2, 0.4, 1] ]
cmap = LinearSegmentedColormap.from_list("", colors)
scatter = axis.scatter(x_vals, y_vals, c=[], cmap=cmap, vmin=0, vmax=1)
gen_values = get_new_vals()
ani = matplotlib.animation.FuncAnimation(fig, update, frames=iterations,
interval=50, fargs=(x_vals, y_vals, intensity, scatter, gen_values),
repeat=False)
# Position 1 for plt.show()
plt.show()
if __name__ == '__main__':
fig, axis = plt.subplots()
axis.set_xlabel('X Axis', size = 12)
axis.set_ylabel('Y Axis', size = 12)
axis.axis([0,1,0,1])
anim_random_points(fig, axis)
# Position 2 for plt.show()
# plt.show()
I, then, noticed an odd thing. At least for me. Notice the Position 1
and Position 2
(at the end of code). The position 1 is placed just after the animation
function, the other one is placed just after code-wise, since the function ends after position 1 and therefore goes to position 2.
Since FuncAnimation
requires the figure
to run the animation on, I am wondering why the plt.show()
works on Position 1, but not on Position 2.
The matplotlib documentation states about FuncAnimation
It is critical to keep a reference to the instance object. The animation is advanced by a timer (typically from the host GUI framework) which the Animation object holds the only reference to. If you do not hold a reference to the Animation object, it (and hence the timers), will be garbage collected which will stop the animation.
If you put plt.show()
outside of the anim_random_points
function, the variable ani
, which holds the reference to the animation, will be garbage collected and there will be no animation to be shown any more.
The solution for that case would be to return the animation from that function
def anim_random_points(fig, axis):
# ...
ani = matplotlib.animation.FuncAnimation(...)
return ani
if __name__ == '__main__':
# ...
ani = anim_random_points(...)
plt.show()
You should really ask two separate questions.
I can answer the first one. The difference between the two positions is due to the fact that ani
is a local variable to your function anim_random_points()
. It is automatically deleted when the execution reaches the end of the function. Therefore plt.show()
in position 2 has nothing to display.
If you want to use plt.show()
in position 2, you need to return the ani object from your function, and keep a reference to it in the main part of your code.
def anim_random_points(fig, axis):
(...)
ani = matplotlib.animation.FuncAnimation(...)
return ani
if __name__ == '__main__':
(...)
ani = anim_random_points(fig, axis)
# Position 2 for plt.show()
plt.show()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.