#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Authors : Raphael Rullan et Timothée Chauvirée

On simule le titrage d'un acide faible par une base forte
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=0.1, 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 = 0.1, description='concentration en titrant (mol/L)', min = 0.00001, max = 10),
              'pKa' : widgets.FloatSlider(value = 4.3, description='pKa du couple', min = 0, max = 11)}

Cini_A = 0




V=np.linspace(0,24,25,  dtype = int)


  
# 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,pKa):
    VE = int(Cini_AH*V_ini/Cini_B)
    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),) 
    def calcul_quantites_avant_et_a_equivalence(Cini_AH,V_ini,Cini_A,i, pKa):
        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,] = pKa + np.log10(i/(VE-i))
        return pH,C_AH,C_B, C_A
    def calcul_quantites_v0(Cini_AH,V_ini,Cini_A,i, pKa):
        C_AH[i,] = Cini_AH
        C_B[i,] = 0
        C_A[i,] = 0
        pH[i,] = 0.5*(pKa - np.log10(Cini_AH))
        return pH,C_AH,C_B, C_A

    def calcul_quantites_equivalence(Cini_AH,V_ini,Cini_A,VE,i, pKa) :
        K = (10**-pKa)/(10**-14)
        C_AH[i,] = np.sqrt((Cini_AH*V_ini)/(V_ini+int(i))/K)
        C_B[i,] = np.sqrt((Cini_AH*V_ini)/(V_ini+int(i))/K)
        C_A[i,] = (Cini_AH*V_ini)/(V_ini+int(i))
        pH[i,] = pKa + np.log10(C_A[i,]/C_AH[i,])
        return pH,C_AH,C_B, C_A

    def calcul_quantites_apres_equivalence(Cini_AH,V_ini,Cini_A,VE,i, pKa) :
        C_AH[i,] = 0
        C_B[i,] =(Cini_B*(i-VE))/((i+V_ini))
        C_A[i,] = (Cini_AH*V_ini)/(V_ini+ i)
        pH[i,] = 14 + np.log10((i-VE)/(V_ini+i))
        return pH,C_AH,C_B, C_A
    
    def dpH(pH):
        dpH = np.gradient(pH)
        return dpH
 


    for i in V:
        if i == 0 : 
            pH,C_AH,C_B,C_A = calcul_quantites_v0(Cini_AH,V_ini,Cini_A,i, pKa)
        elif 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, pKa)
            
        elif i == VE : 
            pH,C_AH,C_B,C_A = calcul_quantites_equivalence(Cini_AH,V_ini,Cini_A,VE,i, pKa)
            
            
        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, pKa)
          
            print(C_B)
            print(i)
    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)
    lines['Courbe derpH'].set_data(V,dpH(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")
lines['Courbe derpH'], = ax2.plot([], [],'r-', linewidth=0.5, label="dérivée du pH")
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.05, 0.4, 0.075])
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()
