Modules utiles
Contents
Modules utiles#
Numpy#
Numpy est un module dédié au traitement des données, notamment la gestion de listes et tableaux.
Il est notamment plus rapide que des remplissages de listes avec des boucles for
.
Il fournit aussi des fonctionalités utiles comme la création de listes de variables aléatoires nump.random
ou de fonctions usuelles comme sin
ou cos
.
Matplotlib#
Matplotlib est un module simple permettant de créer des figures, de les afficher et de les sauvegarder. Ce module propose de nombreuses façons de faire des figures, il est donc utile de regarder la documentation.
Tracer une courbe#
L’exemple ci-dessous permet de produire la figure ci-dessous représentant un sinus et un cosinus entre 0 et 20.
import matplotlib.pyplot as plt # importer maplotlib
import numpy as np
def f(x): # definition de la fonction
return np.sin(x)
x = [ 0.2*i for i in range(0,100) ] # liste d'abscisses de la figure
y1 = f(x) # calcul de y = f(x)
y2 = [ np.cos(val) for val in x ] # calcul de y = cos(x)
fig, ax = plt.subplots() # creation d'un plot
ax.plot(x,y1,"--o",label="sin(x)") # plot de y1 vs x
ax.plot(x,y2,"-x",label="cos(x)") # plot de y2 vs x
ax.set_xlabel('Variable x') # titre de l'axe x
ax.set_ylabel('Sinus(x) et cosinus(x)') # titre de l'axe y
leg = ax.legend() # creation de la légende
fig.savefig("mafigure.pdf") # sauvegarder la figure

Les figures sont produites grâce à des points qu’il faut calculer d’abord. Ces points sont placés dans deux listes: une pour les points d’abscisses et une pour les points d’ordonnées. Bien évidemment la taille de chacune des listes doit être identique; si ce n’est pas le cas, Python produira une erreur.
La fonction plt.subplots()
créé et donne en sortie la figure (l’image totale, si on veut) ainsi que ses axes.
On peut alors utiliser ces objets et les méthodes associées:
ax.set_xlabel("titre x")
etax.set_ylabel("titre y")
pour changer les titres des axes,ax.legend()
pour afficher la légende,ax.plot(...)
pour créer la figure,fig.show()
pour afficher la figure à l’écran,fig.savefig("nom.format")
pour sauver la figure.
Tracer un histogramme#
Dans l’exemple suivant, un histogramme contenant des données générés à partir d’une loi de probabilité normale est créé. On affiche sur cette figure la densité de probabilité associée.
import matplotlib.pyplot as plt # importer maplotlib
import numpy as np
from scipy import stats
N_points = 100000
n_bins = 30
# Generer une distribution normale
val = np.random.randn(N_points)
# Définir la courbe d'une distribution normale
x = np.linspace(-5,5,100)
y = stats.norm.pdf(x)
fig, axs = plt.subplots(sharey=True, tight_layout=True)
# Tracé de l'histogramme
axs.hist(val, bins=n_bins, density=True, label="données")
axs.plot(x, y, label = "probabilité")
leg = axs.legend() # creation de la légende
fig.savefig("exemple_hist.pdf") # sauvegarder la figure

Le nombre de bins d’un histogramme peut etre donné comme argument de la function hist()
; si aucun nombre est donné, matplotlib choisira le nombre de bins.
Ici, on utilise le paramètre density
qui permet de normaliser l’histogramme tel que son intégrale vaut 1.
Scipy#
La librairie Scipy contient des algorithms utiles pour les sciences en général.
Parmi ceux-ci, nous allons utiliser souvent les algorithmes d’optimisation venant du module scipy.optimize
: plus d’informations sur la page de documentation du module.
QExPy#
Un module intéressant pour la physique expérimentale est QExPy (pour “Queen’s Experimental Physics”). Ce module pour Python 3 recueille de nombreux outils permettant, entre autres, de faire facilement et rapidement des analyses de données et des propagations de données. Au cours des différents exercices et travaux pratiques, nous allons voir plusieurs des fonctionalités de ce module; nous résumons ici ceux d’intérêt.
Définition de données et propagation des erreurs#
Le point de départ pour les analyses de données est un ensemble de mesures expérimentales: QExPy définit ce type d’objet grâce à la function Measurement
.
Dans l’exemple suivant, on se donne une série de 6 mesures de vitesses.
import qexpy
liste_donnees = [3.1, 2.9, 3.0, 2.87, 3.02, 3.01]
v = qexpy.Measurement(liste_donnees, unit="m/s", name="vitesse")
print("Moyenne: {}".format(v.mean))
print("Erreur sur la moyenne: {}".format(v.error_on_mean))
print("Déviation standard: {}".format(v.std))
print(v)
Moyenne: 2.983333333333333
Erreur sur la moyenne: 0.0345124776147861
Déviation standard: 0.08453795991545258
vitesse = 2.98 +/- 0.03 [m⋅s^-1]
La variable v
a plusieurs attributs utiles, comme le calcul de la moyenne mean
ou de l’erreur sur la moyenne error_on_mean
comme défini par l’équation (54).
L’affichage de la variable par print
montre la valeur moyenne de cette série de mesures ainsi que l’erreur sur cette moyenne.
On peut utiliser cet outil pour faire des calculs de propagation d’erreurs (voir la Section Propagation des erreurs). Par exemple, si on mesure deux masses \(m_1\) et \(m_2\) à plusieurs reprises, on peut en déduire l’erreur sur la somme de ces deux masses \(M = m1+m_2\):
import qexpy
liste_m1 = [5.2, 5.6, 6, 5.5, 5.1, 6.1]
liste_m2 = [1.2, 1.5, 2.1, 1.4, 1.3, 2.4]
m1 = qexpy.Measurement(liste_m1, unit="kg", name="m1")
m2 = qexpy.Measurement(liste_m2, unit="kg", name="m2")
M = m1 + m2
M.name = "Masse totale"
qexpy.set_sig_figs_for_error(3) # definir le nombre de chiffres significatifs
print(m1)
print(m2)
print(M)
m1 = 5.583 +/- 0.166 [kg]
m2 = 1.650 +/- 0.198 [kg]
Masse totale = 7.233 +/- 0.258 [kg]
L’erreur sur la quantité \(M\) est alors calculée sans corrélation entre les mesures, c’est-à-dire avec l’équation (57).
Cependant, il se peut que les mesures soient corrélées entre elles, ce qui a l’air d’être le cas dans les deux jeux de données m1
et m2
.
Il est alors nécessaire de rajouter les corrélations dans le calcul; une fois fait, le module va utiliser l’équation (56) pour recalculer l’erreur.
qexpy.set_correlation(m1, m2) # explicitation des correlations
M.recalculate()
print(M)
cor = qexpy.get_correlation(m1, m2) # Calcul explicite de la correlation
cov = qexpy.get_covariance(m1, m2) # Calcul explicite de la covariance
print("Covariance: {}\nCorrelation: {}".format(cov, cor))
Masse totale = 7.233 +/- 0.359 [kg]
Covariance: 0.18699999999999994
Correlation: 0.9477419589951331
On peut voir que les données sont presque entièrement corrélées et que la nouvelle erreur est plus grande que celle sans corrélation.
Une autre méthode pour calculer les erreurs propagées consiste à utiliser une simulation Monte Carlo. Cette méthode consiste à générer un grand nombre de valeurs de \(m_1\) et \(m_2\) en supposant qu’elles sont distribuées selon des lois normales dont la moyenne et l’écart type sont calculés comme précédemment; on calcule ensuite \(M = m_1+m_2\) pour chaques valeurs générées Dans ce cas, QExPy permet de faire cela aussi:
M.recalculate()
qexpy.set_error_method(qexpy.ErrorMethod.MONTE_CARLO)
print(M)
# permet d'afficher un histogramme des échantillons du Monte Carlo
# M.mc.show_histogram()
Masse totale = 7.234 +/- 0.360 [kg]
Il est possible de récupérer les valeurs du Monte Carlo en utilisant M.mc.samples()
; la figure ci-dessous montre la distribution des valeurs de \(M\) issues du Monte Carlo.
fig, axs = plt.subplots(sharey=True, tight_layout=True)
axs.hist(M.mc.samples(), bins=n_bins, density=True, label="Monte Carlo")
axs.set_xlabel('M') # titre de l'axe x
leg = axs.legend() # creation de la légende

Figures avec barres d’erreur et ajustements#
QExPy vise à augmenter les fonctionalités d’affichage de figures notamment en permettant la définition de barres d’erreur sur des mesures. On peut en effet définir des jeux de données correspondant à des mesures simultanées des quantités \(X\) et \(Y\) et que l’on arrive à extraire une erreur sur chaque valeur de \(Y\).
import qexpy
import qexpy.plotting as qplt
liste_t = [5.2, 5.6, 6, 5.5, 5.1, 6.1] # liste des x
liste_erreur_t = [0.05]*6 # liste des erreurs sur x
liste_d = [1.2, 1.5, 2.1, 1.4, 1.3, 2.4] # liste des y
liste_erreur_d = [0.2, 0.3, 0.4, 0.2, 0.2, 0.5] # liste des erreurs sur y
t = qexpy.MeasurementArray(liste_t, error=liste_erreur_t, unit="s", name="t")
d = qexpy.MeasurementArray(liste_d, error=liste_erreur_d, unit="m", name="d")
qplt.plot(t, d, name="Distance vs temps") # tracé de y vs x
qplt.show()

QExPy se comporte de façon très similaire à Matplotlib et permet de produire des graphes comme sur la figure ci-dessus.
QExPy propose quelques ajustements de données simples:
modèle linéaire \(y=ax+b\),
modèle quadratique \(y=ax^2+bx+c\),
modèle polynomial d’ordre \(n\),
modèle gaussien,
modèle exponentiel \(y=ae^{-bx}\).
Ces ajustements peuvent donc être fait à la méthode fit
: cette méthode va alors appliquer l’ajustement sur le dernier jeu de données ajouté à la figure, comme montré sur la figure ci-dessous.
import qexpy
import qexpy.plotting as qplt
liste_t = [5.2, 5.6, 6, 5.5, 5.1, 6.1] # liste des x
liste_d = [1.2, 1.5, 2.1, 1.4, 1.3, 2.4] # liste des y
liste_erreur_d = [0.2, 0.3, 0.4, 0.2, 0.2, 0.5] # liste des erreurs sur y
t = qexpy.MeasurementArray(liste_t, unit="s", name="t")
d = qexpy.MeasurementArray(liste_d, error=liste_erreur_d, unit="m", name="d")
qplt.plot(t, d, name="Distance vs temps") # tracé de y vs x
figure = qplt.get_plot()
resultats = figure.fit(model=qexpy.FitModel.LINEAR)
print("Afichage des résultats:\n",resultats)
figure.show()
/usr/share/miniconda/envs/physexp2_notebook/lib/python3.8/site-packages/qexpy/data/utils.py:183: UserWarning: Fail to generate a physical correlation matrix for the values provided, using uncorrelated samples instead. Please check that the covariance or correlation factors assigned to the measurements are physical.
warnings.warn(
Afichage des résultats:
----------------- Fit Results -------------------
Fit of Distance vs temps to linear
Result Parameter List:
slope = 0.912 +/- 0.223,
intercept = -3.49 +/- 1.20
Correlation Matrix:
[[ 1. -0.999]
[-0.999 1. ]]
chi2/ndof = 1.68/3
--------------- End Fit Results -----------------

La figure montre le résultat de l’ajustement fait par QExPy. La zone bleue correspond à la zone de confiance du modèle obtenu après l’ajustement, en faisant varier la pente et l’ordonnée à l’origine d’une quantité égale à leur erreur.
Il est possible de définir soi-même la fonction à utiliser comme modèle de l’ajustement et d’utiliser QExPy pour procéder à l’ajustement.
import qexpy
import qexpy.plotting as qplt
# fonction sinus du fit avec les noms des paramètres
def func(x, masse, longueur):
return masse * qexpy.sin(longueur * x)
xdata=[0.00,0.33,0.66,0.99,1.32,1.65,1.98,2.31,2.64,2.97,3.31,
3.64,3.97,4.30,4.63,4.96,5.29,5.62,5.95,6.28]
ydata=[0.09,0.41,1.53,2.23,3.76,2.50,3.89,5.33,5.39,4.05,5.08,
5.84,4.59,4.50,3.48,3.57,2.20,1.95,0.39,-0.18]
# definition des listes de mesures
x = qexpy.MeasurementArray(xdata, name="x")
y = qexpy.MeasurementArray(ydata, name="y")
qplt.plot(x, y, name="Oscillogramme") # tracé de y vs x
figure = qplt.get_plot()
resultats = figure.fit(model=func, parguess=[1, 1],
parunits=["kg", "m"])
print("Afichage des résultats:\n",resultats)
figure.show()
Afichage des résultats:
----------------- Fit Results -------------------
Fit of Oscillogramme to custom
Result Parameter List:
masse = 5.096 +/- 0.334 [kg],
longueur = 0.5005 +/- 0.0158 [m]
Correlation Matrix:
[[1. 0.238]
[0.238 1. ]]
chi2/ndof = 0.00/17
--------------- End Fit Results -----------------

La figure montre le résultat de l’ajustement du modèle \(y = \mathrm{masse} \times \sin(\mathrm{longueur} \times x)\) avec \(\mathrm{masse}\) et \(\mathrm{longueur}\) les deux paramètres libres du modèle.
Remarquons ici que, si aucun nom de paramètres est donné lors de l’ajustement, QExPy nommera le nom des paramètres en utilisant le nom des variables de la fonction func
(ici, masse
et longueur
).