import pylab as plt
import numpy as np
import scipy.optimize
import matplotlib as mpl
from matplotlib.widgets import Slider, Button

mpl.rcParams['text.usetex'] = False #True pour mettre du beau LateX mais ça fait laguer ou False c'est moche mais ça lag pas
mpl.rcParams['axes.titlesize'] = 15
mpl.rcParams['axes.labelsize'] = 22
mpl.rcParams['lines.linewidth'] = 3
mpl.rcParams['lines.markersize'] = 8
mpl.rcParams['xtick.labelsize'] = 20
mpl.rcParams['ytick.labelsize'] = 20
mpl.rcParams['legend.fontsize'] = 15

#Source et Théorie : https://hal.archives-ouvertes.fr/jpa-00245176/document

##Le gros du calcul

# The parametrized function to be plotted
def to_plot(phi,phi_0,Ie,R) : 
    def T1(phi,phi_0,Ie,R) :
        #Fonction de transmission 'classique' du Fabry-Pérot
        return 1/(1+ (4*R)/(1-R)**2 * np.sin(phi/2)**2)
    
    def T2(phi,phi_0,Ie,R) :
        #Fonction de transmission réexprimée avec l'ajout de l'élément non linéaire
        return 1/Ie * (phi - phi_0)
        
    def to_zero(phi,phi_0,Ie,R) :
        #Fait la différence des deux fonctions de transmission pour trouver les 'déphasages d'équilibres'
        return T1(phi,phi_0,Ie,R) - T2(phi,phi_0,Ie,R)
    
    phi_eq = phi[np.where(np.logical_and(to_zero(phi,phi_0,Ie,R)<0.005,to_zero(phi,phi_0,Ie,R)>-0.005))]

    return T1(phi,phi_0,Ie,R),T2(phi,phi_0,Ie,R),phi_eq
    
phi = np.linspace(-5*np.pi,5*np.pi,5000)

##Le plot avec sliders

# Define initial parameters
init_phi_0 = -np.pi
init_Ie = 1
init_R = 0.6

# Create the figure and the line that we will manipulate
fig, (ax1,ax2) = plt.subplots(1,2)
T1,T2,phi_eq=to_plot(phi,init_phi_0,init_Ie,init_R)
line_T1, = ax1.plot(phi, T1,label='Transmission')
line_T2, = ax1.plot(phi, T2,label='Transmission avec élément non linéaire')

ax1.set_xlabel(r'$\Phi$ (rad)')
ax1.set_ylabel('Transmission')
ax1.set_xlim(-5*np.pi, 5*np.pi)
ax1.set_ylim(0,1.05)
ax1.set_xticks([-4*np.pi,-2*np.pi,0,2*np.pi,4*np.pi])
ax1.set_xticklabels([r'$-4\pi$',r'$-2\pi$',r'$0$',r'$2\pi$',r'$4\pi$'])

global Ie_tab,phi_eq_tab
Ie_tab = init_Ie*np.ones(len(phi_eq))
phi_eq_tab=phi_eq

line2, = ax2.plot(Ie_tab,phi_eq_tab,'o')
ax2.set_xlabel(r'$I_e$ (u.a.)')
ax2.set_ylabel(r'$\Phi_\mathrm{éq}$ (rad)')
ax2.set_xlim(0,25)
ax2.set_ylim(-5*np.pi, 5*np.pi)
ax2.set_yticks([-4*np.pi,-2*np.pi,0,2*np.pi,4*np.pi])
ax2.set_yticklabels([r'$-4\pi$',r'$-2\pi$',r'$0$',r'$2\pi$',r'$4\pi$'])

# Adjust the main plot to make room for the sliders
#plt.subplots_adjust(left=0.25, bottom=0.25)
plt.subplots_adjust(left=0.1,bottom=0.25,top=0.95)

# Make horizontal sliders to control the parameters.
ax_phi_0 = plt.axes([0.1, 0.07, 0.8, 0.03])
phi_0_slider = Slider(
    ax=ax_phi_0,
    label=r'$\Phi_0$ (rad)',
    valmin=-5*np.pi,
    valmax=5*np.pi,
    valinit=init_phi_0,
)
phi_0_slider.label.set_size(20)
phi_0_slider.valtext.set_fontsize(20)

ax_Ie = plt.axes([0.1, 0.1, 0.8, 0.03])
Ie_slider = Slider(
    ax=ax_Ie,
    label=r'$I_e$ (u.a.)',
    valmin=0.001,
    valmax=25,
    valinit=init_Ie,
)
Ie_slider.label.set_size(20)
Ie_slider.valtext.set_fontsize(20)

ax_R = plt.axes([0.1, 0.13, 0.8, 0.03])
R_slider = Slider(
    ax=ax_R,
    label=r'$R$',
    valmin=0,
    valmax=0.9999,
    valinit=init_R,
)
R_slider.label.set_size(20)
R_slider.valtext.set_fontsize(20)



# The function to be called anytime a slider's value changes
def update(val):
    T1,T2,phi_eq=to_plot(phi,phi_0_slider.val, Ie_slider.val, R_slider.val)
    line_T1.set_ydata(T1)
    line_T2.set_ydata(T2)
    
    global Ie_tab,phi_eq_tab
    Ie_tab = np.concatenate((Ie_slider.val * np.ones(len(phi_eq)) , Ie_tab ))
    phi_eq_tab = np.concatenate((phi_eq , phi_eq_tab ))
    line2.set_ydata(phi_eq_tab)
    line2.set_xdata(Ie_tab)
    fig.canvas.draw_idle()


# register the update function with each slider
phi_0_slider.on_changed(update)
Ie_slider.on_changed(update)
R_slider.on_changed(update)

# Create a `matplotlib.widgets.Button` to reset the sliders to initial values.
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', hovercolor='0.975')

def reset(event):
    phi_0_slider.reset()
    Ie_slider.reset()
    R_slider.reset()
    global Ie_tab,phi_eq_tab
    phi_eq_tab = []
    Ie_tab = []
    line2.set_ydata(phi_eq_tab)
    line2.set_xdata(Ie_tab)
    
button.on_clicked(reset)

#Bouton pour nettoyer la deuxième subplot avec le cycle d'hystérésis
clean_ax2_ax = plt.axes([0.7, 0.025, 0.1, 0.04])
button2 = Button(clean_ax2_ax, 'Nettoyer', hovercolor='0.975')

def clean_ax2(event):
    global Ie_tab,phi_eq_tab
    phi_eq_tab = []
    Ie_tab = []
    line2.set_ydata(phi_eq_tab)
    line2.set_xdata(Ie_tab)
    
button2.on_clicked(clean_ax2)

ax1.legend(loc='upper right')
plt.show()


