Code python
#!/usr/bin/env python
# coding: utf-8
# In[1]:
## Importation des bibliothèques
import numpy as np
import numpy.random as rd
import matplotlib.pyplot as plt
## Entrée des données du problème
C_mère = 0.1 # Concentration de la solution mère en mol/L
deltaC_mère = 0.001 # Demi-étendue associée à chaque observation de C_mère
V_fiole = np.array([100,100,100,100]) # à remplir : volumes des fioles jaugées utilisées (6
fois la même valeur !)
deltaV_fiole = np.array([0.1,0.1,0.1,0.1]) # à remplir : Tolérance des fioles jaugées (6 fois
la même valeur !)
V_burette = np.array([1,5,10,20]) # à remplir
deltaV_burette = np.array([0.05,0.05,0.05,0.05]) # à remplir : Tolérance de la burette (6
fois la même valeur !)
C_étalon = (C_mère*V_burette)/V_fiole # Calcul des valeurs de C_étalon associées à
chaque dilution (donner la relation permettant d'obtenir C_étalon)
print('Les valeurs de C_étalon sont', C_étalon)
X = np.array([148,515,954,1800]) # à remplir : entrée des valeurs de la grandeur X
mesurée
deltaX = (5/100) *X # Demi-étendue associée à chaque observation de la grandeur X
u_X = deltaX / np.sqrt(3) # Incertitude-type de chaque valeur issue d'une observation sur
X pour une loi uniforme
## Simulation de N dosages par la méthode Monte Carlo
N = 100000 # Nombre de simulations souhaitées
C_étalon_sim = [] # définition d'une liste utilisée ensuite
a_sim = [] # définition d'une liste utilisée ensuite
b_sim = [] # définition d'une liste utilisée ensuite
for i in range(N):
# Génère des valeurs aléatoires
C_mère_sim = rd.uniform(C_mère - deltaC_mère, C_mère + deltaC_mère)
V_fiole_sim = rd.uniform(V_fiole - deltaV_fiole, V_fiole + deltaV_fiole)
V_burette_sim = rd.uniform(V_burette - deltaV_burette, V_burette + deltaV_burette)
X_sim = rd.uniform(X - deltaX, X + deltaX) # Génère des valeurs aléatoires de X avec une
demie-étendue delta_X
C_étalon_sim_i = C_mère_sim * V_burette_sim / V_fiole_sim # Calcul des concentrations
simulées
C_étalon_sim.append(C_étalon_sim_i)
# Régression linéaire de X en fonction de C pour chaque expérience virtuelle
p_sim = np.polyfit(C_étalon_sim_i, X_sim, 1)
a_sim.append(p_sim[0]) # Stocke la pente
b_sim.append(p_sim[1]) # Stocke l'ordonnée à l'origine
## Incertitudes-type associées aux concentrations étalon
u_C_étalon = np.std(C_étalon_sim, 0, ddof=1)
print('Les valeurs de u_C_étalon sont', u_C_étalon)
## Paramètres de la droite de régression
a_moy = np.mean(a_sim) # Moyenne des valeurs de la pente
u_a = np.std(a_sim, ddof=1) # Ecart-type de la série des pentes
b_moy = np.mean(b_sim) # Moyenne des valeurs des ordonnées à l'origine
u_b = np.std(b_sim, ddof=1) # Ecart-type de la série des ordonnées
print('La pente de la droite est a = ', format(a_moy, "#.4g"), 'S·m2·mol-1') # Unité de a à
adapter
print('Incertitude-type u(a) = ', format(u_a, "#.2g"), 'S·m2·mol-1') # Unité de u(a) à
adapter
print("L'ordonnée à l'origine de la droite est b = ", format(b_moy, "#.3g"), 'S·m-1') # Unité
de b à adapter
print('Incertitude-type : u(b) = ', format(u_b, "#.2g"), 'S·m-1') # Unité de u(b) à adapter
## Tracé de X en fonction de C_étalon
plt.figure(1)
plt.plot(C_étalon, X, 'go')
plt.xlabel('C_étalon/ mol/L')
plt.ylabel('conductivité/S·m-1') # Nom et unité de X à adapter
plt.xlim(0, 1.1 * np.max(C_étalon)), plt.ylim(0, 1.1 * np.max(X))
plt.ticklabel_format(axis='x', style='sci', scilimits=(0, 0))
plt.title('Évolution de la conductivité en fonction de C_étalon') # Nom de X à adapter
p = np.polyfit(C_étalon, X, 1) # Régression linéaire de X en fonction de C
plt.plot(C_étalon, np.polyval(p, C_étalon), alpha=0.3) # Tracé de la droite de régression en
transparence
plt.errorbar(C_étalon, X, xerr=u_C_étalon, yerr=u_X, fmt=',k') # Tracé des points avec
barres d'incertitude
plt.text(1e-5, 0.2, "σ=a*C+b") #Affichage sur le graphe de l'équation de la droite de
régression, symbole de X à adapter
plt.text(1e-5, 0.18, ' a=' + '{:.4}'.format(a_moy) + ' S·m2·mol-1') #adapter la position du
texte (abscisse et ordonnée) selon le graphe + adapter unité de a!
plt.text(1e-5, 0.165,' avec u(a)=' + '{:.2}'.format(u_a) + 'L/mol')
#plt.text(1e-5, 0.12, 'b =' + '{:.4}'.format(b_moy) + 'S·m-1')
plt.text(1e-5, 0.135,' avec u(b)=' + '{:.2}'.format(u_b) + 'sans unité')
plt.grid()
plt.show()
## Tracé des résidus
z = (X - np.polyval(p, C_étalon))
plt.figure(2)
plt.errorbar(C_étalon, z, xerr=2 * u_C_étalon, yerr=2 * u_X, fmt='m.')
plt.plot(C_étalon, np.zeros(len(C_étalon)))
plt.xlabel('C_étalon/ mol/L')
plt.ylabel(r'Résidus $X - X_{\mathrm{ajusté}}$ / unité')
plt.ticklabel_format(axis='both', style='sci', scilimits=(0, 0))
plt.title('Résidus')
plt.grid()
plt.show()
## Tracé des écarts normalisés
z = (X - np.polyval(p, C_étalon)) / u_X
plt.figure(3)
plt.plot(C_étalon, z, 'bo')
plt.xlabel('C_étalon/ mol/L')
plt.ylabel('Résidus normalisés de $X$')
plt.ticklabel_format(axis='x', style='sci', scilimits=(0, 0))
plt.title('Résidus normalisés')
plt.grid()
plt.show()
## Détermination "directe" de la concentration inconnue
X_mesuré = 1530 # Valeur de la grandeur X mesurée pour la solution analysée
deltaX_mesuré = (5/100)*X_mesuré
C_inconnue = (X_mesuré - b_moy) / a_moy
print('La concentration en permanganate de potassium de la solution de Dakin est = ',
format(C_inconnue, "#.5g"), 'mol/L')
## Détermination de l'incertitude-type sur la concentration C_inconnue
X_mesuré_sim = [] # définition d'une liste utilisée ensuite
for i in range(N):
# Génère des valeurs aléatoires pour X_mesuré en fonction de deltaX_mesuré
X_sim2 = rd.uniform(X_mesuré - deltaX_mesuré, X_mesuré + deltaX_mesuré)
X_mesuré_sim.append(X_sim2) # Simulation de N valeurs de X_mesuré
# Calcul de C_inconnue pour chaque simulation
C_inconnue_sim = (np.array(X_mesuré_sim) - np.array(b_sim)) / np.array(a_sim)
## Résultats de la mesure
C_inconnue_moy = np.mean(C_inconnue_sim) # Moyenne des valeurs simulées
u_C_inconnue = np.std(C_inconnue_sim, ddof=1) # Incertitude-type (écart-type des
simulations)
print('La concentration en permanganate de potassium de la solution du sérum calculée
avec MC est = ',
format(C_inconnue_moy, "#.5g"), 'mol/L')
print('Incertitude-type u(C_inconnue) =', format(u_C_inconnue, "#.2g"), 'mol/L')
## Vérification des résultats avant le tracé de l'histogramme
print("Nombre de valeurs simulées pour C_inconnue:", len(C_inconnue_sim))
## Histogramme des valeurs de C_inconnue
plt.figure(4)
plt.hist(C_inconnue_sim, bins='rice', edgecolor='black') # Ajout d'une bordure aux bins
pour meilleure visibilité
plt.title('Histogramme des valeurs de C_inconnue')
plt.ticklabel_format(axis='x', style='sci', scilimits=(0, 0), useMathText=True) # Notation
scientifique sur l'axe x
plt.xlabel(r'valeur de $C_{\mathrm{inconnue}}$ / $(mol\; L^{-1})$') # Légende de l'axe
des abscisses
plt.ylabel('Effectif') # Légende de l'axe des ordonnées
plt.grid(True) # Ajout de la grille pour plus de clarté
plt.show() # Affichage de la figure
# In[ ]:
Les valeurs de C_étalon sont [0.001 0.005 0.01 0.02 ]
Les valeurs de u_C_étalon sont [2.93967413e-05 4.09124687e-05 6.48271010e-05
1.19600593e-04]
La pente de la droite est a = 8.671e+04 S·m2·mol-1
Incertitude-type u(a) = 2.9e+03 S·m2·mol-1
L'ordonnée à l'origine de la droite est b = 74.0 S·m-1
Incertitude-type : u(b) = 15. S·m-1
La concentration en permanganate de potassium de la solution de Dakin est = 0.016792
mol/L
La concentration en permanganate de potassium de la solution du sérum calculée avec MC
est = 0.016806 mol/L
Incertitude-type u(C_inconnue) = 0.00067 mol/L
Nombre de valeurs simulées pour C_inconnue: 100000