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

from plot_helpers import CO, bold_ticks


def fig7_5(MM=None):
    # error using euler method as a function of M
    # this also produces Table 7.3
    # y' = ry(1-y) with y(0) = y0

    r = 10
    y0 = 0.01
    tmax = 1
    a0 = (1 - y0) / y0

    if MM is None:
        MM = np.array([10, 100, 1000, 1e4, 1e5, 1e6, 1e7], dtype=int)
    else:
        MM = np.asarray(MM, dtype=int)

    maxerror = np.zeros(len(MM))
    pterror = np.zeros(len(MM))
    points = np.zeros(len(MM), dtype=int)

    for im in range(len(MM)):
        M = int(MM[im])
        h = tmax / M
        y = y0
        emax = 0.0
        t = 0.0
        em = 0.0
        for i in range(1, M + 1):
            t = t + h
            yy = y + r * h * y * (1 - y)
            ye = 1 / (1 + a0 * np.exp(-r * t))
            em = abs(yy - ye)
            if emax < em:
                emax = em
            y = yy

        maxerror[im] = emax
        pterror[im] = em
        points[im] = M

        print(f"\\, {M:d} \\, & \\, {h:5.1e} \\, & \\,\\, {emax:5.1e} \\\\\\hline")

    plt.close("all")
    # get(gcf)
    fig, ax = plt.subplots(figsize=(8.8, 3.3))
    fig.subplots_adjust(left=0.10, right=0.98, bottom=0.23, top=0.98)
    ax.set_prop_cycle(cycler(color=CO))

    ax.loglog(points, maxerror, "--bo", markersize=8, linewidth=1.8)
    ax.set_yticks([1e-8, 1e-6, 1e-4, 1e-2, 1])
    ax.set_xlabel("Number of Time Points (M)")
    ax.set_ylabel("Iterative Error")
    ax.grid(True)
    ax.set_xlim(1, 1e7)
    ax.set_ylim(1e-8, 1)
    ax.grid(False, which="minor")
    bold_ticks(ax, 14)
    plt.show()

    # plt.savefig('/Users/mark/Desktop/errorI.eps')


if __name__ == "__main__":
    fig7_5()
