# NE MODIFIEZ PAS CE FICHIER
import os
import matplotlib.pyplot as plt
import numpy as np



def plot_1_1(t, x):
    plt.figure(figsize=(8, 4))
    plt.plot(t, x, "*-")
    plt.title(r'Sampled signal $x(t)$')
    plt.xlabel('Time (s)')
    plt.ylabel(r'$x(t)$')
    # plt.grid()
    plt.show()
    
    
def plot_1_2(f, real_X, imag_X, abs_X):
    _, axes = plt.subplots(nrows=1, ncols=3, figsize=(15, 4), sharex=True, sharey=True)

    # Real and imag parts
    axes[0].stem(f, real_X)
    axes[0].set_title("X(f), Real part")


    axes[1].stem(f, imag_X)
    axes[1].set_title("X(f), Imaginary part")

    # Absolute part
    axes[2].stem(f, abs_X, label="|X|")
    axes[2].set_title("X(f), Absolute value")

    # Shared legends
    _ = [a.set_xlabel("Frequency [Hz]") for a in axes]
    
def plot_1_3(t, x1, x2, x, f, X):
    fig = plt.figure(figsize=(15, 6))
    gs = fig.add_gridspec(3, 2)
    ax1 = fig.add_subplot(gs[0, 0])
    ax2 = fig.add_subplot(gs[1, 0])
    ax3 = fig.add_subplot(gs[2, 0])
    ax4 = fig.add_subplot(gs[:, 1])
    axes = [ax1, ax2, ax3, ax4]

    # Time domain
    axes[0].plot(t, x1)
    axes[0].set_title("$x_1(t)$")
    axes[1].plot(t, x2)
    axes[1].set_title("$x_2(t)$")
    axes[2].plot(t, x)
    axes[2].set_title("$x(t) = x_1(t) + x_2(t)$")
    _ = [a.set_xlabel("Time [s]") for a in axes[:3]]

    # Frequency
    axes[3].stem(f, np.abs(X))
    axes[3].set_title("|X(f)|")
    axes[3].set_xlabel("Frequency [Hz]")

    # Fit all text in frame
    plt.tight_layout()
    
    
def plot_1_4(fss, ts, xs, Xs, f_s):
    # Define plots
    _, axes = plt.subplots(nrows=len(fss), ncols=2, figsize=(15, 6))
    
    for i, fs in enumerate(fss):
        t = ts[i]
        x = xs[i]
        X = Xs[i]
        f = f_s[i]
        
        # Plot results
        axes[i, 0].plot(t, x, "-*")
        axes[i, 0].set_title(f"x(t) with $f_s={fs}$Hz")
        axes[i, 0].set_xlabel("time [s]")
        
        axes[i, 1].stem(f, np.abs(X))
        axes[i, 1].set_title(f"X(f) with $f_s={fs}$Hz")
        axes[i, 1].set_xlabel("Frequency [Hz]")
    
    plt.tight_layout()
    plt.show()

def plot_1_5(sigmas, t, f, xns, Xns):
    _, axes = plt.subplots(nrows=len(sigmas), ncols=2, figsize=(15, 10))
    
    for i, sigma in enumerate(sigmas):
        xn = xns[i]
        Xn = Xns[i]
        
        # Time-domain plot
        axes[i, 0].plot(t, xn)
        axes[i, 0].set_xlabel("Time [s]")
        axes[i, 0].set_title(f"Temporal ($\\sigma={sigma}$)")
        
        # Frequency-domain plot
        axes[i, 1].stem(f, np.abs(Xn))
        axes[i, 1].set_xlabel("Frequency [Hz]")
        axes[i, 1].set_title(f"Fourier transform ($\\sigma={sigma}$)")
    
    plt.tight_layout()
    plt.show()
    
def plot_2_2(xs, Xs, t, f):
    _, axes = plt.subplots(nrows=len(xs), ncols=2, figsize=(16, 10))
    
    for i, (x, X) in enumerate(zip(xs, Xs)):
        # Time-domain plot
        axes[i, 0].plot(t, x)
        axes[i, 0].set_title(f"$x_{{{i+1}}}(t)$")
        axes[i, 0].set_xlabel("Time [s]")
        
        # Frequency-domain plot
        axes[i, 1].plot(f, np.abs(X))
        axes[i, 1].set_title(f"$|X_{{{i+1}}}(f)|$")
        axes[i, 1].set_xlabel("Frequency [Hz]")
    
    plt.tight_layout()
    plt.show()
    

def plot_3(Bs, t, pis):
    for B, pi in zip(Bs, pis):
        plt.plot(t, pi, label=f"B={B}")
    
    plt.legend()
    plt.title("Function $\\Pi(t/B)$")
    plt.xlabel("Time [s]")
    plt.show()


def plot_4(Ks, t, x, x_hats, K_error, errs):
    _, axes = plt.subplots(1, 3, figsize=(15, 5))

    # Base function
    axes[0].plot(t, x(t), c='k', linewidth=3, label='$x(t)$')
    axes[0].set_title('$x(t)$')
    axes[0].set_xlabel('Time [s]')
    axes[0].legend()

    # Approximations
    axes[1].plot(t, x(t), c='k', linewidth=3, label='$x(t)$')
    for K, x_hat in zip(Ks, x_hats):
        axes[1].plot(t, x_hat,
             label='$\\hat{{x}}(t)$, $k={}$'.format(K),
             linewidth=2)
    axes[1].set_title('Approximation - Chebyshev')
    axes[1].set_xlabel('Time [s]')
    axes[1].legend()

    # Error vs number of coefficients
    axes[2].semilogy(K_error, errs, label='error = $||x - \\hat{x}||^2$')
    axes[2].set_title('Reconstruction error')
    axes[2].set_ylabel('Error')
    axes[2].set_xlabel('K')
    axes[2].legend()

    plt.tight_layout()
    plt.show()


def plot_5_2(t, Sn):
    fig, ax = plt.subplots(figsize=(15, 4))
    for i in range(Sn.shape[0]):
        ax.plot(t, Sn[i], label=f"$s_{i}(t)$")
    ax.set_title("$s_n(t)$")
    ax.set_xlabel("time t")
    ax.legend()
    plt.show()

def plot_5_2_2(t, Phi):
    fig, ax = plt.subplots(figsize=(15, 4))
    for i in range(Phi.shape[0]):
        ax.plot(t, Phi[i], label=fr"$\phi_{{{i}}}(t)$")
    ax.set_title(r"$\phi_n(t)$")
    ax.set_xlabel("Time [s]")
    ax.legend()
    plt.show()

def plot_5_3(t, S, B):
    fig, axes = plt.subplots(1, 2, figsize=(15, 4))
    
    for i in range(S.shape[0]):
        axes[0].plot(t, S[i], label=fr"$s_{{{i}}}(t)$")
    
    for i in range(B.shape[0]):
        axes[1].plot(t, B[i], label=fr"$\phi_{{{i}}}(t)$")
    
    axes[0].set_xlabel("time [s]")
    axes[0].set_title(r"$s_n(t)$")
    axes[1].set_xlabel("time [s]")
    axes[1].set_title(r"$\phi_n(t)$")
    
    for a in axes:
        a.legend()
    
    plt.show()

def plot_5_proj(t, f, Ks, f_hats, mses):
    fig, axes = plt.subplots(1, 2, figsize=(15, 5))

    axes[0].plot(t, f, label=r"$f(t)$", linewidth=2)
    for K, fk in zip(Ks, f_hats):
        axes[0].plot(t, fk, linestyle="--", label=fr"$\hat{{f}}_K(t)$, $K={K}$")
    axes[0].set_title(r"Projection sur la base $\{\phi_n\}$")
    axes[0].set_xlabel("time [s]")
    axes[0].legend()

    axes[1].plot(Ks, mses, marker="*")
    axes[1].set_xlabel("K")
    axes[1].set_ylabel("MSE")
    axes[1].set_title("Erreur de reconstruction (MSE) vs K")

    plt.tight_layout()
    plt.show()

def plot_6(t, f, x_real, x_imag, X_real, X_imag):
    fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(15, 8))

    axes[0].plot(t, x_real, label="real")
    axes[0].plot(t, x_imag, label="imag")
    axes[0].set_title(r"Temporal signal $x(t)$")
    axes[0].set_xlabel("Time [s]")
    axes[0].legend(loc=1)

    axes[1].stem(f, X_real, label="real")
    axes[1].set_ylim([-0.3, 0.3])
    axes[1].set_title("FFT Real part")
    axes[1].set_xlabel("Frequency [Hz]")

    axes[2].hlines(3/16, xmin=f[0], xmax=f[-1], ls='--', color='k', label=r"$j\frac{3}{16}$")
    axes[2].hlines(1/16, xmin=f[0], xmax=f[-1], ls='-.', color='k', label=r"$j\frac{1}{16}$")
    axes[2].stem(f, X_imag, label="imag")
    axes[2].set_ylim([-0.3, 0.3])
    axes[2].set_title("FFT Imaginary part")
    axes[2].set_xlabel("Frequency [Hz]")
    axes[2].legend(loc=1)

    plt.tight_layout()
    plt.show()