
# lagrangeSine.py
# Andrew Davison, ad@coe.psu.ac.th, June 2026
'''
Use a Lagrange polynomial based on NUM_TERM coordinates
as an approximation for sin(x). Plot it and the original
function, and also a graph of the absolute error between
the two plots.
'''

import math
import matplotlib.pyplot as plt
import faUtils

NUM_TERMS = 4
MAX_PTS = 200

xs = [k*math.pi/3 for k in range(NUM_TERMS)]
ys = [math.sin(x) for x in xs]
xPlot = faUtils.linspace(0, math.pi, MAX_PTS)
yPlot = [faUtils.lagrangeInterp(xs, ys, x) for x in xPlot]
yFn = [math.sin(x) for x in xPlot]

# Absolute error between Lagrange and function
yErr = [abs(yPlot[k] - yFn[k]) for k in range(MAX_PTS)]

# two stacked graphs
fig, axes = plt.subplots(2, 1, figsize=(6, 7), sharex=True)

# Top graph showing plots
axes[0].plot(xPlot, yFn, label="sin(x)")
axes[0].plot(xPlot, yPlot, label="Lagrange")
axes[0].scatter(xs, ys, color="red", zorder=5, label="Data")

# x and y axis lines
axes[0].axhline(0, color="black")
axes[0].axvline(0, color="black")
axes[0].set_xlabel("x")
axes[0].set_ylabel("y")
axes[0].set_title("Lagrange Interpolation")
axes[0].legend()
axes[0].grid()

# Bottom graph shoring  absolute error
axes[1].plot(xPlot, yErr)

# x and y axis lines
axes[1].axhline(0, color="black")
axes[1].axvline(0, color="black")
axes[1].set_xlabel("x")
axes[1].set_ylabel("Error")
axes[1].set_title("Abs Error |Lagrange - sin(x)|")
axes[1].grid()

plt.tight_layout()
plt.show()