#! /usr/bin/env python # -*- coding: utf-8 -*- """ Solution for the problem 2 of the last CS101 lab assignment sheet. Plotting the exponential function and its 5 first Taylor approximation (on the same graph). Plot an animation, adding more and more higher order Taylor approximations. @date: Wed April 22 10:31:45 2015. @author: Lilian Besson for CS101 course at Mahindra Ecole Centrale 2015. @licence: GNU Public License version 3. """ import numpy as np import matplotlib.pyplot as plt from math import factorial # The function and point we are interested about def f(x): return np.exp(x) #x0 = 0.0 def taylor_exp(x, x0=0, n=1): """ Return $T_n(exp, x_0)(x)$, the Taylor expansion of order n for the function exponential, at the point x_0, for x.""" y = (x - x0)**0 # np.ones(n) for k in xrange(1, n+1): y += f(x0) * (x - x0)**k / factorial(k) return y # %% Animation example from matplotlib import animation def makeanimation(xmin=-6, xmax=3, x0=0, frames=10): """ Make an animation for exp(x) and its first Taylor approximations, from xmin to xmax.""" assert frames > 0 assert xmin < x0 < xmax # New figure fig, ax = plt.subplots() print fig print ax # Samples for the X axis X = np.linspace(xmin, xmax, 500) Yf = f(X) # Plot exp(x) line1, = ax.plot(X, Yf, color="black", linewidth=5, label=r"$\exp(x)$") Y = taylor_exp(X, x0, 0) line2, = ax.plot(X, Y, label=(r"$T_{0}(\exp, x_0)(x)$"), color='blue', linewidth=2) line3, = ax.plot(X, Y, label=(r"$T_{0}(\exp, x_0)(x)$"), color='blue') # Initialization function: plot the background of each frame def init(): print "init() called." # Move spines axobj = plt.gca() axobj.spines['right'].set_color('none') axobj.spines['top'].set_color('none') axobj.xaxis.set_ticks_position('bottom') axobj.spines['bottom'].set_position(('data', 0)) axobj.yaxis.set_ticks_position('left') axobj.spines['left'].set_position(('data', 0)) # Title, xlabel and ylabel ax.set_title("The exponential function and its first {} Taylor approximations.".format(frames)) ax.set_xlabel(r"Values for $x$") ax.set_xlim(1.05*xmin, 1.05*xmax) ymax = abs(Yf.max()) ax.set_ylabel(r"Values for $y$") ax.set_ylim(-0.3*ymax, 1.05*ymax) # Add a legend (using the label of each plot), and show to graph ax.legend(loc="upper left") plt.show() print fig, ax print "init() ended." return line3, # End of init function # Animation function. This is called sequentially def animate(i): print "animate({}) called.".format(i) # Plot the successive Taylor expansion (can go up to 5 or more!) Y = taylor_exp(X, x0, i) # line3, = ax.plot(X, Y, label=(r"$T_{" + str(i) + r"}(\exp, x_0)(x)$")) line3.set_label((r"$T_{" + str(i) + r"}(\exp, x_0)(x)$")) line3.set_color('green') line3.set_alpha(0.4) line3.set_linewidth(4) line3.set_data(X, Y) error = np.sum( (Y - Yf)**2 ) print "From {} to {}, with a Taylor expansion of order {}, the approximative 2-norm error is about {:g}.".format(xmin, xmax, i, error) new_title = r"The $\exp(x)$ function and $T_{" + str(i) + r"}(\exp, x_0)(x)$.\n" + ("From {} to {}, with a Taylor expansion of order {}, the approximative 2-norm error is about {:g}.".format(xmin, xmax, i, error)) print "New title should be:", new_title ax.set_title(new_title) ax.legend(loc="upper left") plt.show() print "animate({}) ended.".format(i) return line3, # End of animate() # Call the animator. print "Launching the animation, with {} frames.".format(frames) print init print animate anim = animation.FuncAnimation( fig, animate, init_func=init, frames=range(1, frames+1), # FIXME: choose the best value interval=500, # FIXME: choose the best value repeat=False, blit=True # True to only draw what have changed ) print anim, init, animate # %% Conclude by saving the animation # FIXME not working on Windows! # anim.save('Animation__Successive_polynomial_interpolation_for_ln1+x2+cosx.mp4', # fps=1, # writer='ffmpeg' # ) return ax, fig, anim, init, animate # End of the function makeanimation # %% Main example if __name__ == '__main__': ax, fig, anim, init, animate = makeanimation(frames=25) # End of the script