import numpy as np import matplotlib.pyplot as plt plt.rc('font', size=16) N = 101 xs = np.linspace(0,90,N) ys = (100-((xs+10)%20-10)**2) * np.exp(-xs/30) xs = xs * np.exp(-xs/200) fig, ax = plt.subplots(figsize=(4, 6)) ax.axis('equal') ax.plot(xs,ys)
animation
module from Matplotlib:
from matplotlib import animation plt.rc('animation', html='jshtml') ball = ax.plot([],[],'ro')[0] def update(i): ball.set_data(xs[i],ys[i]) return [ball] anim = animation.FuncAnimation(fig, update, frames=N, interval=10, blit=True) anim
anim
evaluation creates an animation widget that opens in the Jupyter Notebook like this (You cannot click on the buttons of the widget in this book - only in the Jupyter Notebook):
animation
module is imported
and some display setting is changed which enables the Jupyter Notebook to render the animation in a browser:
from matplotlib import animation plt.rc('animation', html='jshtml')
matplotlib.lines.Line2D
object is created when
calling ax.plot
. The object is to become a red filled
circle because of the 'ro'
argument, but
to begin with it has no - or -coordinates (because of the
two empty list, []
, arguments,
and will hence not show
up yet. Note the [0]
that picks the first element of
the list returned by ax.plot
:
ball = ax.plot([],[],'ro')[0]
ball
is now a Python object variable that allows us access the (not yet drawn) red filled circle. To do so, we
write a function, update
, that takes an index i
as an argument and changes the and
coordinates of the red filled circle to the 'th value in the two lists, xs
and ys
:
def update(i): ball.set_data(xs[i],ys[i]) return [ball]
update
returns ball
as the only
element in a list
of drawing objects, i.e. it returns [ball]
and not just
ball
.
anim = animation.FuncAnimation(fig, # figure canvas as returned by plt.subplots() update, # update and return a list of drawing objects frames=N, # i in range(N), i passed to update interval=10, # delay between frames in ms blit=True) anim
FuncAnimation
method calls our update
function frames=N
times
with the arguments from to , whereby the red filled circle gets all the calculated coordinates one by one. When
the call of update
returns with the list [ball]
, FuncAnimation
is advised
that the drawing object ball
has changed and should be redrawn in the figure.
print('Available writers:', animation.writers.list())
Available writers: ['pillow', 'html']
'pillow'
is present, one may proceed with these two commands:
writer = animation.writers['pillow'](fps=50) # frames per second anim.save('bouncing_ball.gif', writer=writer)
'pillow'
is absent, you'll need to install it on your system.
P0
,
P1
,
P2
,
and
P3
, the coordinates for a given angle
may be calculated with
the xy_of_theta
function as defined here:
%matplotlib inline import numpy as np import matplotlib.pyplot as plt np.set_printoptions(precision=3) plt.rc('font', size=16) def xy_of_theta(theta): vec1 = np.array([np.cos(theta),np.sin(theta)]) vec2 = np.array([-np.sin(theta),np.cos(theta)]) P0 = [0,0] P1 = vec1 P2 = vec1 + vec2 P3 = vec2 x_of_theta = [P0[0],P1[0],P2[0],P3[0],P0[0]] y_of_theta = [P0[1],P1[1],P2[1],P3[1],P0[1]] return x_of_theta,y_of_theta
P0
appear both at the beginning and at the
end of the returned coordinate lists. This means that the square can
be plotted with Matplotlibs
pyplot.plot
function as done here:
fig, ax = plt.subplots() ax.axis('equal') ax.grid() ax.set_xlim(-3,3) ax.set_ylim(-2,2) ax.set_yticks(range(-1,2)) xs, ys = xy_of_theta(np.pi/6) square = ax.plot(xs,ys)[0]
plot
, the first element
of the returned list is captured in square
which
reveals that it is a Line2D object:
square
<matplotlib.lines.Line2D at 0x7fbc989f7850>
get_data
method:
square.get_data()
(array([ 0. , 0.866, 0.366, -0.5 , 0. ]), array([0. , 0.5 , 1.366, 0.866, 0. ]))
set_data
method:
xs, ys = xy_of_theta(np.pi/3) # new angle square.set_data((xs,ys)) fig
set_data
method can be used to make an animation,
where the square is being rotated:
from matplotlib import animation plt.rc('animation', html='jshtml') N = 50 def update(i): theta = i * 2*np.pi/N xs, ys = xy_of_theta(theta) square.set_data((xs,ys)) return [square] anim = animation.FuncAnimation(fig, update, frames=N, interval=10, blit=True) anim
i
, is used to
calculate a new angle that the first side of the square forms with the -axis.
Choose which booklet to go to: