import numpy as np
import matplotlib.pyplot as plt
from cycler import cycler


def fig2_9():
    #  Plot solution obtained using newton as function of starting value.
    #  The function f(x) used here is a cubic spline (reason: it is easier to
    #  control what it looks like than a regular polynomial)

    #  Input:
    # xa = starting point
    # tol = tolerance for stopping
    # f(x) and df(x) These are at end of file

    tol = 10 ** (-6)

    # evaluate function f(x) for plotting
    a = -3
    b = 6
    np_ = 200
    x = np.linspace(a, b, np_)
    F = np.zeros(np_)
    for ix in range(np_):
        F[ix] = f(x[ix])

    #  run Newton's method for different starting values
    nx = 85
    xI = np.linspace(-3, 6, nx)
    xS = np.zeros(nx)
    for ix in range(nx):
        xa = xI[ix]
        fa = f(xa)
        err = 1
        it = 0
        while err > tol:
            xb = xa - f(xa) / df(xa)
            err = abs(xb - xa)
            xa = xb
        xS[ix] = xb

    plt.close("all")
    # get(gcf)
    fig, (ax1, ax2) = plt.subplots(
        2,
        1,
        figsize=(745 / 100, 386 / 100),
        dpi=100,
        constrained_layout=True,
    )
    co = [
        (0, 0, 1),
        (0, 0.5, 0),
        (1, 0, 0),
        (0, 0.75, 0.75),
        (0.75, 0, 0.75),
        (0.75, 0.75, 0),
        (0.25, 0.25, 0.25),
    ]
    plt.rcParams["axes.prop_cycle"] = cycler(color=co)

    # subplot(2,1,1)
    # subaxis(2,1,1,1,'MT',0.014,'MB',0.075,'MR',-0.02,'ML',0.02,'P',0.04)

    ax1.plot(xI, xS, "or", markersize=6, linewidth=2)
    ax1.axis([-3, 6, -3, 6])
    ax1.set_ylabel("Solution")
    ax1.grid(True)
    for spine in ax1.spines.values():
        spine.set_visible(True)
    ax1.tick_params(labelsize=14)
    for label in ax1.get_xticklabels() + ax1.get_yticklabels():
        label.set_fontweight("bold")
    ax1.yaxis.label.set_fontsize(14)
    ax1.yaxis.label.set_fontweight("bold")

    # subplot(2,1,2)
    # subaxis(2,1,1,2)

    ax2.plot(x, F, "b", linewidth=1.8)
    ax2.plot([a, b], [0, 0], "k", linewidth=0.5)
    ax2.plot([-2, 0, 3, 105 / 20], [0, 0, 0, 0], ".r", markersize=35)
    ax2.set_xlabel("x-axis")
    ax2.set_ylabel("f(x)")
    ax2.set_yticks([0])
    ax2.axis([-3, 6, -35, 40])
    ax2.grid(True)
    for spine in ax2.spines.values():
        spine.set_visible(True)
    ax2.tick_params(labelsize=14)
    for label in ax2.get_xticklabels() + ax2.get_yticklabels():
        label.set_fontweight("bold")
    ax2.xaxis.label.set_fontsize(14)
    ax2.yaxis.label.set_fontsize(14)
    ax2.xaxis.label.set_fontweight("bold")
    ax2.yaxis.label.set_fontweight("bold")

    # fig.savefig('/Users/mark/Desktop/new2.eps')
    plt.show()


def f(x):
    g = x**4 - 25 / 4 * x**3 - 3 / 4 * x**2 + 63 / 2 * x
    return g


def df(x):
    g = 4 * x**3 - 75 / 4 * x**2 - 3 / 2 * x + 63 / 2
    return g


if __name__ == "__main__":
    fig2_9()
