#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ce code a été écrit par Raphael Rullan en se basant des codes de Manon Leconte. Je la remercie pour les codes de base.
Merci de me citer si utilisation (coucou Léo). Pour toute question : raphael.rullan@ens-lyon.fr
L'objectif est d'avoir un code permettant de simuler les diagrammes de Bode pour différents filtre.
"""

## importation des librairies
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize
import scipy.misc
import scipy.integrate
import widgets

parameters = {'R' : widgets.IntSlider(value=1000, description='Résistance (ohm)', min=100, max=10000),
              'C'  : widgets.FloatSlider(value = 1*10e-6, description='Capacité (F)', min = 10e-9, max =10e-3),
              'L'  : widgets.FloatSlider(value = 1e-3, description='Inductance (L)', min =10e-9, max =10e-3)}


points = 10000
coupure = np.zeros(points) - 3
omega = np.linspace(0.1, 10000, points)


## Definition des fonctions
def passe_bas_G(x,R,C):
    omega_c = 1/(R*C)
    return  20*np.log10(1/(np.sqrt(1+x**2/omega_c**2)))

def passe_bas_P(x,R,C):
    omega_c = 1/(R*C)
    return np.arctan(x/omega_c)

def passe_haut_P(x,R,C):
    omega_c = 1/(R*C)
    return (np.pi)/2 - np.arctan(x/omega_c)

def passe_haut_G(x, R, C):
    omega_c = 1/(R*C)
    return 20*np.log10((x/omega_c)/(np.sqrt(1+x**2/omega_c**2)))

def passe_bande_G(x, R, L, C):
    omega_0 = 1/np.sqrt(L*C)
    Q = (1/R)*np.sqrt(L/C)
    z = x/omega_0
    return 20*np.log10(1/((1-z**2)**2 + (z/Q)**2))

def passe_bande_P(x, R, L, C):
    omega_0 = 1/np.sqrt(L*C)
    Q = (1/R)*np.sqrt(L/C)
    z = x/omega_0
    return  - np.arctan(z/(Q*(1-z**2)))

fig=plt.figure(figsize=(12,12))
plt.subplots_adjust(left=0.125,bottom=0.2,right=0.8,top=0.9,wspace=0.3,hspace=0.5)

ax1 = plt.subplot(211)
ax2 = plt.subplot(212)

fig.suptitle("Diagramme de Bode de filtres")
#Pour le gain

def plot_data(R,L,C):
    lines['Gain passe bas'].set_data(omega, passe_bas_G(omega, R, C))
    lines['phase passe haut'].set_data(omega, passe_bas_P(omega, R, C))
    lines['Gain passe haut'].set_data(omega, passe_haut_G(omega, R, C))
    lines['phase passe bas'].set_data(omega, passe_haut_P(omega, R, C))
    #lines['Gain passe bande'].set_data(omega, passe_bande_G(omega, R, L, C))
    #lines['phase passe bande'].set_data(omega, passe_bande_P(omega, R, L, C))
    lines['coupure'].set_data(omega, coupure)
    ax1.set_xlim(0.1,np.max(omega))
    ax1.set_ylim(np.min(passe_bande_G(omega, R, L, C)),5)
    ax2.set_xlim(0.1,np.max(omega))
    ax2.set_ylim(-np.pi/2 - 0.5, np.pi/2+0.5)
    texts1.set_text('fréquence de coupure ωc = {:.2e}Hz'.format(1/(R*C)))
    #texts2.set_text('fréquence ω0 = {:.2e}Hz'.format(1/np.sqrt(L*C)))
    #texts3.set_text('facteur qualité Q = {:.2e}Hz'.format((1/R)*np.sqrt(L/C)))
    
  


lines = {}
ax = {}
texts1=  ax1.text(0.01, 0.05,"Fréquence de coupure ωc =" ,bbox=dict(facecolor='red', alpha=0.5), fontsize=10, transform=ax1.transAxes)
#texts2=  ax1.text(0.01, 0.05,"Fréquence propre  ω0  =" ,bbox=dict(facecolor='red', alpha=0.5), fontsize=10, transform=ax1.transAxes)
#texts3=  ax1.text(0.01, 0.05,"Facteur qualité =" ,bbox=dict(facecolor='red', alpha=0.5), fontsize=10, transform=ax1.transAxes)
lines['Gain passe bas'], = ax1.plot([], [],'r-',lw=2,label='Gain passe bas')
lines['phase passe bas'], = ax2.plot([], [],'r-',lw=2,label='Phase passe bas')
lines['Gain passe haut'], = ax1.plot([], [],'g-',lw=2,label='Gain passe haut')
lines['phase passe haut'], = ax2.plot([], [],'g-',lw=2,label='Phase passe haut')
#lines['phase passe bande'], = ax2.plot([], [],'b-',lw=2,label='Phase passe bande')
#lines['Gain passe bande'], = ax1.plot([], [],'b-',lw=2,label='Gain passe bande')
lines['coupure'], = ax1.plot([],[], '--',lw=2, label='coupure')
ax1.set_xscale('log')
ax1.set_ylabel("Gain")
ax2.set_xscale('log')
ax2.set_ylabel("Phase")
ax1.set_xlabel("ω, en échelle log")
ax2.set_xlabel("ω, en échelle log")
ax1.legend()
ax2.legend()

param_widgets = widgets.make_param_widgets(parameters, plot_data, slider_box=[0.30, 0.01, 0.35, 0.05])
choose_widget = widgets.make_choose_plot(lines, box=[0.82,0.01,0.15, 0.2])
reset_button = widgets.make_reset_button(param_widgets,box=[0.01, 0.01, 0.08, 0.05])

#On peut si on veut afficher la pulsation propre et le facteur de qualité en décommentant les lignes : 77-78-86-87

if __name__=='__main__':
    plt.show()

