## Valeurs et écart-types
# Valeurs
# Mettre dans X les valeurs de la grandeur caractérisée par les meilleures (= plus faibles) incertitudes
X = [] # Liste des valeurs x_i
Y = [] # Liste des valeurs y_i

# Incertitudes
X_erreur = [] * len(X)  # Mettre UNE SEULE valeur correspondant à l'incertitude type commune à tous les y_i
Y_erreur = [] * len(Y) # Mettre UNE SEULE valeur correspondant à l'incertitude type commune à tous les y_i


## Représentation graphique
import matplotlib.pyplot as plt

plt.figure('Graphes')
plt.errorbar(X, Y, Y_erreur, X_erreur, fmt = 'bo', label = 'points expérimentaux')
plt.xlabel('valeur de X')
plt.ylabel('valeur de Y')
plt.title("Graphes")
plt.grid()
plt.legend()
plt.show()

## Régression linéaire
import matplotlib.pyplot as plt
import numpy as np

p, o = np.polyfit(X, Y, 1) # régression avec polynôme de degré 1 (régression affine)
print('la pente est :', p)
print("ordonnée à l'origine :", o)

Na = 6.02e23 # Constante d'Avogadro
qe = 1.609e-19 # Charge élementaire
F = Na * qe # Faraday
Delta_r_S0 = # À compléter
Delta_r_H0 = # À compléter

print('Enthalpie standard de réaction', Delta_r_H0, "J/mol")
print('Entropie standard de réaction', Delta_r_S0, "J/K/mol")

def model(t): # Droite modèle de la régression linéiaire
    return p * t + o

borne_inf = min(X)
borne_sup = max(X)

t = np.linspace(borne_inf, borne_sup, 100)

plt.figure('Graphes')
plt.errorbar(X, Y, Y_erreur, X_erreur, fmt = 'bo', label = 'points expérimentaux')
plt.plot(t, model(t), 'k', label = 'modelisation')
plt.xlabel('valeur de X')
plt.ylabel('valeur de Y')
plt.title("Graphes")
plt.grid()
plt.legend()
plt.show()

## Validation par les résidus et les z-scores
def fun_nulle(t): # Fonction nulle pour visualiser résidu
    return 0 * t

# Calcul des résidus
residu = []
for i in range(len(X)): # Calcul des résidus
    ecart = Y[i] - model(X[i])
    residu.append(ecart)

# Calcul des z-scores
z = []
for i in range(len(X)):
    z.append((Y[i] - model(X[i])) / Y_erreur[i])

# Représentations graphiques
plt.figure("Résidus")
plt.plot(X, residu, '+r', label = 'residus')
plt.errorbar(X, residu, Y_erreur, fmt='+r')
plt.plot(t, fun_nulle(t), 'g', label = 'fonction nulle')
plt.title("Tracé des résidus")
plt.grid()
plt.show()

plt.figure("z-scores")
plt.plot(X, z,'bo')
plt.xlabel('valeur de x')
plt.ylabel('z-score')
plt.title("z-score pour chaque mesure")
plt.grid()
plt.show()

## Traitement statistique (incertitude de type A) avec les valeurs de tous les groupes


## Écart-type sur la pente et la valeur à l'origine par Monte-Carlo pour accéder aux incertitudes types sur Delta_rH0 et Delta_rS0
import matplotlib.pyplot as plt
import numpy as np
from math import sqrt

N = 2000 # Nombre de tirages simulés
list_p = []
list_o = []

for i in range(N):
    list_X = []
    list_Y = []

    for j in range(len(X)):
        Xj = np.random.normal(X[j], X_erreur[j])
        Yj = np.random.normal(Y[j], Y_erreur[j])
        list_X.append(Xj)
        list_Y.append(Yj)

    p, o = np.polyfit(list_X, list_Y, 1)
    list_p.append(p)
    list_o.append(o)

p_moy = np.mean(list_p) # Moyenne de la distribution des pentes
up = np.std(list_p, ddof = 1) # Écart-type de la distribution des pentes = incertitude type

o_moy = np.mean(list_o) # Moyenne de la distribution des valeurs à l'origine
uo = np.std(list_o, ddof = 1) # Écart-type de la distribution des valeurs à l'origine = incertitude type

print("pente moyenne", p_moy)
print("incertitude-type sur la pente", up)
print("valeur à l'origine moyenne", o_moy)
print("incertitude-type sur la valeur à l'origine'", uo)

# À faire : en déduire les incertitudes sur Delta_rH0 et Delta_rS0

