Search
Spline Fit
""" From "COMPUTATIONAL PHYSICS", 3rd Ed, Enlarged Python eTextBook  
    by RH Landau, MJ Paez, and CC Bordeianu
    Copyright Wiley-VCH Verlag GmbH & Co. KGaA, Berlin;  Copyright R Landau,
    Oregon State Unv, MJ Paez, Univ Antioquia, C Bordeianu, Univ Bucharest, 2015.
    Support by National Science Foundation"""

# SplineInteract.py  Spline fit

import matplotlib.pyplot as plt
import numpy as np
x = np.array([0.0, 0.12, 0.25, 0.37, 0.5, 0.62, 0.75, 0.87, 0.99])  # input
y = np.array([10.6, 16.0, 45.0, 83.5, 52.8, 19.9, 10.8, 8.25, 4.7])
n = 9
# Initialize
y2 = np.zeros_like(y)
u = np.zeros_like(y)

Nfit = 100  # Original algorithm did Nfit + 1 points instead

Xfit = np.zeros((Nfit), float)
Yfit = np.zeros((Nfit), float)

yp1 = (
    (y[1] - y[0]) / (x[1] - x[0])
    - (y[2] - y[1]) / (x[2] - x[1])
    + (y[2] - y[0]) / (x[2] - x[0])
)

ypn = (
    (y[-1] - y[-2]) / (x[-1] - x[-2])
    - (y[-2] - y[-3]) / (x[-2] - x[-3])
    + (y[-1] - y[-3]) / (x[-1] - x[-3])
)

if yp1 > 0.99e30:
    y2[0] = 0.0
    u[0] = 0.0

else:
    y2[0] = -0.5
    u[0] = 3 / (x[1] - x[0]) * ((y[1] - y[0]) / (x[1] - x[0]) - yp1)

for i in range(1, n - 1):  # Decomp loop
    sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1])
    p = sig * y2[i - 1] + 2.0
    y2[i] = (sig - 1.0) / p
    u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1])

    u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p

if ypn > 0.99e30:  # Test for natural
    qn = un = 0.0
else:
    qn = 0.5
    un = 3 / (x[-1] - x[-2]) * (ypn - (y[-1] - y[-2]) / (x[-1] - x[-2]))

y2[-1] = (un - qn * u[-2]) / (qn * y2[-2] + 1)

for k in range(n - 2, 1, -1):
    y2[k] = y2[k] * y2[k + 1] + u[k]

for i in range(Nfit):  # Begin fit
    xout = x[0] + (x[-1] - x[0]) * i / (Nfit - 1)
    klo = 0  # Bisection algor
    khi = n - 1
    while khi - klo > 1:
        k = khi + klo >> 1
        if x[k] > xout:
            khi = k
        else:
            klo = k

    h = x[khi] - x[klo]

    if x[k] > xout:
        khi = k
    else:
        klo = k

    h = x[khi] - x[klo]
    a = (x[khi] - xout) / h
    b = (xout - x[klo]) / h
    yout = (
        a * y[klo]
        + b * y[khi]
        + ((a * a * a - a) * y2[klo] + (b * b * b - b) * y2[khi]) * h * h / 6
    )

    Xfit[i] = xout
    Yfit[i] = yout
from scipy.interpolate import CubicSpline
plt.figure(figsize=(12, 7))
plt.plot(x, y, "o")
plt.plot(Xfit, CubicSpline(x, y)(Xfit), "-")
plt.plot(Xfit, Yfit, ".")
plt.show()