'''


Informations
------------
Author: Timothee Chauvire
Modificator : Raphael Rullan
Some scripts to create the buttons and sliders taken from https://github.com/araoux/python_agregation (written by P Cladé, A Raoux and F Levrier)

WARNING this program requires the widgets.py file to work

Remarque : on s'intéresse ici à la réaction AH + B = A + H20 (avec B = HO-), on a acide fort base/forte
'''


import matplotlib.pyplot as plt
import numpy as np
import widgets

parameters = {'Cini_AH' : widgets.FloatSlider(value=3e-3, description='concentration en acide (mol/L)', min=0.00001, max=10),
              'V_ini'  : widgets.IntSlider(value = 10, description='volume initial (mL)', min = 0.1, max =100),
              'Cini_B'  : widgets.FloatSlider(value = 3e-3, description='concentration en titrant (mol/L)', min = 0.00001, max = 10)}

#Définition des fonctions

def ConvpH(n_H3O):
    pH=-1*np.log10(n_H3O)
    return pH

def ConvH30(pH):
    n_H3O=-1*10**pH
    return n_H3O

### Programme pHmetrie Dosage Acide Fort Base Forte
Cini_AH = 3e-3
Cini_A = 0
Cini_B = 3e-3
#isize = 26
V_ini = 10
VE = Cini_AH*V_ini/Cini_B  #saisie du volume équivalent en mL


V=np.linspace(0,24,25,  dtype = int)
C_AH, C_B,C_A, pH = np.zeros(np.size(V),),np.zeros(np.size(V),),np.zeros(np.size(V),),np.zeros(np.size(V),)  # initialisation de 4 listes

def calcul_quantites_avant_et_a_equivalence(Cini_AH,V_ini,Cini_A,i):
    C_AH[i,] = (Cini_AH*V_ini-Cini_B*i)/(V_ini+int(i))
    C_B[i,] = 0
    C_A[i,] = (Cini_B*i)/(V_ini+int(i))
    pH[i,] = ConvpH(C_AH[i,])
    return pH,C_AH,C_B, C_A
def calcul_quantites_apres_equivalence(Cini_AH,V_ini,Cini_A,VE,i) :
    C_AH[i,] = 0
    C_B[i,] =(Cini_B*(i-VE)/(int(i)+V_ini))
    C_A[i,] = (Cini_AH*V_ini)/(V_ini+int(i))
    pH[i,] = 14-ConvpH(C_B[i,])
    return pH,C_AH,C_B, C_A

  
# affichage des courbes

fig=plt.figure(figsize=(12,10))
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)

plt.subplots_adjust(left=0.125,bottom=0.2,right=0.8,top=0.9,wspace=0.3,hspace=0.5)
fig.suptitle("Titrage d'un acide fort par une base forte")

def plot_data(Cini_AH, Cini_B, V_ini):
    VE = Cini_AH*V_ini/Cini_B
    for i in V:
        if i < VE :
            #appelle une fonction qui calcule les quantités avant et à l’équivalence
            pH,C_AH,C_B,C_A = calcul_quantites_avant_et_a_equivalence(Cini_AH,V_ini,Cini_B,i)
            
        elif i == VE :
            pH[i,] = 7
            C_A[i,] =  (Cini_AH*V_ini)/(V_ini+VE)
            
        elif i > VE :
            #appelle une fonction qui calcule les quantités après l’équivalence
            pH,C_AH,C_B,C_A = calcul_quantites_apres_equivalence(Cini_AH,V_ini,Cini_B,VE,i)
    print(pH)
    lines['Courbe AH'].set_data(V,C_AH)
    lines['Courbe A'].set_data(V,C_A)
    lines['Courbe B'].set_data(V,C_B)
    a['Courbe pH'].set_data(V, pH)
    texts.set_text('VE (mL) = {:.2e}'.format(VE))
    ax1.set_xlim(0,np.max(V))
    ax1.set_ylim(-0.00005,np.maximum(np.max(C_AH),np.max(C_B))) 
    ax2.set_xlim(0,np.max(V))
    ax2.set_ylim(0, np.max(pH)+1)
    
lines = {}
lines['Courbe AH'], = ax1.plot([], [],'bx-',linewidth=0.1, label="Concentration Acide AH" )
lines['Courbe A'], = ax1.plot([], [],'go-', linewidth=0.1, label="Concentration Base conjuguee A")
lines['Courbe B'], = ax1.plot([], [],'ro-', linewidth=0.1, label="Concentration Base B")
a = {}
a['Courbe pH'], = ax2.plot([], [],'bo', label="Evolution pH")


texts= ax1.text(0.851, 0.9, '$VE=$', bbox=dict(facecolor='red', alpha=0.5), fontsize=10, transform=ax1.transAxes)





ax1.set_xlabel('Volume ajouté (mL)')
ax1.set_ylabel('concentration en espèce (mol/L)')
ax1.legend(bbox_to_anchor=(0.05,0.1, 0.8,1), loc = 2)



ax2.set_xlabel('Volume ajouté (mL)')
ax2.set_ylabel("pH")
ax2.legend()

param_widgets = widgets.make_param_widgets(parameters, plot_data, slider_box=[0.30, 0.0, 0.35, 0.05])
choose_widget = widgets.make_choose_plot(lines, box=[0.9,0.2,0.08, 0.2])
reset_button = widgets.make_reset_button(param_widgets,box=[0.01, 0.01, 0.08, 0.05])

if __name__=='__main__':
    plt.show()
