# -*- coding: utf-8 -*-
"""TP_2_Titrage_des_ions_carbonate_à_compléter (1).ipynb

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/1Ofl1uOFl41gSjsW7IH0amtPLt3aEXBWd

#**1. Dosage pH - métrique des ions carbonate par l'acide chlorhydrique**

## Description du protocole :
- On procède à l'étalonnage du pH - mètre grâce aux solutions tampon de $pH = 4,0$ et $pH = 7,0$ ,
- On remplit la burette d'une solution d'acide chlorhydrique ($\mathrm {H_{3}O_{(aq)}^{+}, Cl_{(aq)}^{-})}$ à une concentration de $\mathrm {0,1 \ mol.L^{–1}}$
- On prélève $20,0 \ mL$ d'une solution de carbonate de solution $\mathrm {( CO_{3(aq)}^{2-} , 2 Na_{(aq)} ^{+})}$ à l'aide d'une pipette jaugée deux traits de $20,0 \ mL$ dont on cherche la concentration.

## Mesures
On relève le $pH$ en fonction du volume d'acide chlorhydrique versé en faisant très attention aux variations de $pH$. L'ajout s'arrête vers $\mathrm {V_{acide} = 20, 0 \ mL}$ quand on s'aperçoit que le second saut de pH est bien dépassé.

La courbe est tracée au fur et à mesure de la prise des points.

#Scripts Python
On entre les valeurs de pH et de volumes relevées sous deux tableaux "array" disctincts.

L'idée est de :
  - Tracer la courbe pH - métrique,
  - Ecrire une fonction dérivée pour déterminer le ou les volumes à l'équivalence,
  - Calculer la concentration de la dibase,
  - Tracer l'évolution des quantités de matière en fonction du volume de titrant versé, d'une façon générale :
    - la dibase, ici les ions carbonate
    - l'espèce amphotère, ici les ions hydrogénocarbonate
    - le diacide, ici l'acide carbonique
    - le titrant, ici l'acide chlorhydrique
"""

#Importation des bibliothèques
import matplotlib.pyplot as plt
import numpy as np

# Entrée des valeurs expérimentales
Va = np.array([## à compléter ##])
pH = np.array([## à compléter ##])

"""#**2. Tracé de la courbe du pH en fonction du volume de solution titrante versé**"""

#Tracé de la courbe pH = f(V)

plt.plot(## à compléter ##)
plt.xlabel('Volume de solution titrante versée / mL')
plt.ylabel('pH')
plt.title('Evolution du pH en fonction de Va versé')
plt.grid()
plt.show()

"""# **3. Évaluation du volume équivalent**

On estime numériquement les valeurs de $\frac{\mathrm{d}pH}{\mathrm{d}V}$ pour divers volumes $V$ de solution titrante versée. Les valeurs de $\frac{\mathrm{d}pH}{\mathrm{d}V}$ sont déterminées à l'aide de la dérivée centrée sur un point d'abscisse $V_i$, c'est à dire :

$$ \left( \dfrac{dpH}{dV} \right)_i =  \dfrac {pH_{i+1}-pH_{i-1}}{V_{i+1}-V_{i-1}}. $$

Ce schéma numérique limite en partie l'influence du bruit et n'induit pas de décalage. Il faut noter qu'on ne peut évaluer ainsi la dérivée sur les points extrèmes — on n'en a de toute façon pas besoin. On crée une fonction `VolEq` qui prend en argument les array `V` et `pH`, et qui retourne :
* un array contenant les dérivées numériques ;
* un array contenant les volumes, privés des deux points extrèmes.

Pour évaluer le volume équivalent, on repère le volume qui maximise la dérivée précédemment calculée.

#Calcul de la dérivée :
- Calcul de la dérivée centrée via numpy qui fait tout le travail : élimination des deux points en amont et en aval pour permettre le calcul sur les vecteurs.
- Numpy balaye automatiquement le tableau pour calculer les valeurs de cette dérivée centrée. Cela permet d'éviter de faire des boucles conditionnelles (type for ou while).

 - Exemple de premiers calculs : (10.45 - 10.83) / (1.0-0.0) = -0.38 et ainsi de suite : (10.27-10.63)/(1.5-0.5) = -0.36

- En Python, avec Numpy, pour sélectionner un sous-ensemble de données dans un `array`, on utilise les crochets []. Par exemple :
  * pour avoir un sous-ensemble des 10 _premiers_ éléments d'un `array` `x`, on fait : `x[:9]` ;
  * pour avoir un sous-ensemble des 10 _derniers_ éléments d'un `array` `x`, on fait : `x[-9:]` ;
  * pour avoir un sous ensemble avec les 2e, 3e et 4 éléments d'un `array` `x`, on fait : `x[1:4]` ;
  * si on écrit `x[:-2]`; on enlève les deux *derniers* éléments d'un `array` `x` ;
  * si on écrit `x[2:]`; on enlève les deux *premiers* éléments d'un `array` `x`.
"""

def derivee1(x,y):
    return (y[2:]-y[:-2])/(x[2:]-x[:-2])

derpH = derivee1(Va, pH)

Va_sub = Va[1:-1] # on redimensionne les valeurs de Va pour qu'elles soient de même taille que derpH


plt.plot(## à compléter ##)
plt.xlabel("Va (mL)")
plt.ylabel("$\dfrac{pH}{dV}$'")
plt.grid(linestyle='-.')
plt.title("détermination d'un volume à l'équivalence")
plt.xlim(0,20)
plt.ylim(-10,0)
plt.legend()
plt.show()

print('Vaeq 2 =', Va_sub[np.argmin(derpH)], 'mL')

"""# Détermination des deux volumes à l'équivalence

Pour l'instant, on a obtenu uniquement le second volume à l'équivalence.
Pour obtenir également le premier, on peut également utiliser des opérateurs booléens pour sélectionner certaines valeurs. Par exemple :
* `Va[Va<14]` sélectionne toutes les valeurs de `Va` qui sont plus petites que 14 ;
* `Va[(Va<14) & (Va>1)]` sélectionne toutes les valeurs de `Va` qui sont plus petites que 14 et plus grandes que 1.

On décide d'afficher les valeurs des volumes pour lesquels la dérivée du pH est inférieure à un seuil qu'on se donne en regardant le graphe précédent. Cela permet d'en déduire les deux volumes équivalents.
"""

print( Va_sub[derpH<## à compléter ##], "\n", derpH[derpH<## à compléter ##], sep='' )

"""#Calcul de l'évolution des quantités de matière au cours du dosage


Méthode classique, valeur sûre, qui utilise des boucles conditionnelles et des listes.
"""

#Calcul de la concentration de la dibase
Ca = 0.1  # concentration de la solution titrante de l'acide chlorhydrique
V_0=20.0
Vae1=4.8
Vae2=10

C_b=(## à compléter ##)
print ("La concentration de la dibase est : " , round(C_b,3),  "en mol.L^-1")

#création des listes qui seront retransformées en tableaux numpy"
n_carb=[]
n_amph=[]
n_acide=[]
n_acide_carb=[]

def n_avant_eq1(i):
                                            #La commande append permet de remplir une liste au fur et à mesure des itérations
    n_carb.append((## à compléter ##))
    n_amph.append(## à compléter ##)
    n_acide.append(## à compléter ##)
    n_acide_carb.append(## à compléter ##)

def n_entre_Veq(i):
    n_carb.append(## à compléter ##)
    n_amph.append(## à compléter ##)
    n_acide.append(## à compléter ##)
    n_acide_carb.append(## à compléter ##)

def n_apres_eq(i):
                                         #La commande append permet de remplir une liste au fur et à mesure des itérations
  n_carb.append(## à compléter ##)
  n_amph.append(## à compléter ##)
  n_acide_carb.append(## à compléter ##)
  n_acide.append(## à compléter ##)


for i in Va:
    if i<=Vae1:
     n_avant_eq1(i)

    elif Vae1 < i < Vae2:

     n_entre_Veq(i)

    else:
     n_apres_eq(i)

#transformation des listes en array
n_carb=np.array(n_carb)
n_acide=np.array(n_acide)
n_amph=np.array(n_amph)
n_acide_carb=np.array(n_acide_carb)

#Affichage graphique
plt.plot(Va,n_carb,'+-', color= "blue", label="n(ions carbonate)")
plt.plot(Va,n_amph,'+-',color= "purple", label="n(ions hydrogénocarbonate)")
plt.plot(Va,n_acide_carb,'+-', color= "green", label="n(acide carbonique)")
plt.plot(Va,n_acide,'+-', color= "red", label="n(acide chlorhydrique)")

plt.xlabel('V en mL')
plt.ylabel('n en mmol')
plt.title('Évolution des quantités de matière au cours du titrage')
plt.legend()
plt.grid(linestyle='-.')
plt.show()