from __future__ import print_function
from matplotlib.pyplot import *
from numpy import *

# Define the functions
def f(x): return sin(x)
def g(x): return 1./(1.+x*x)
def h(x): return x**(-12) - x**(-6)

# A function to simplify plotting
def plot_interp(f, min, max, interp, ns=[5,10,15], nodes=linspace):
    """Create a plot of the function f between min and max plus plots 
    of the interpolating functions interp with ns different interpolation 
    points. 
    nodes should be a function that generates n supporting points in the 
    interval [min, max]. 
    """
    xp = linspace(min, max, 1000)
    plot(xp, f(xp), label="$f(x)$")

    for n in ns:
        x = nodes(min, max, n)
        ip = interp(x, f(x))
        plot(xp, ip(xp), label="$P_{{{0}}}(x)$".format(n))
    legend(loc="best")

# Spline Interpolation

from scipy.interpolate import interp1d
def cubic_spline(x, y): return interp1d(x,y,'cubic',bounds_error=False)
def quadratic_spline(x, y): return interp1d(x,y,'quadratic',bounds_error=False)

figure(figsize=(15,5))
subplot(121)
plot_interp(f, 0.0, 2*pi, cubic_spline)
title("Cubic Sine")
subplot(122)
plot_interp(f, 0.0, 2*pi, quadratic_spline)
title("Quadratic Sine")

figure(figsize=(15,5))
subplot(121)
plot_interp(g, -5., 5., cubic_spline)
title("Cubic Runge")
subplot(122)
plot_interp(g, -5., 5., quadratic_spline)
title("Quadratic Runge")

figure(figsize=(15,5))
subplot(121)
plot_interp(h, 1., 5., cubic_spline)
title("Cubic LJ")
subplot(122)
plot_interp(h, 1., 5., quadratic_spline)
title("Quadratic LJ")

show()
