Je vous écris ce message afin de vous demander de l'aide pour le fit d'une courbe du temps de vie donné par l'expression suivante :
a1*(np.exp(-(t-t0)/t1)) + a2*(np.exp(-(t-t0)/t2)) + a3*(np.exp(-(t-t0)/t3)) + b avec t0 : temps d'arrivé du pulse, ti : temps d'émission des états neutres, chargés & biexcitons, ai : amplitude de décroissance & b : décalage.
Ainsi, j'ai utilisé ici la fonction scipy.optimize.least_squares.
Etant débutant en Python, je vous mets mon code.
Voici ci-dessous mon code :
############################################################################################################################
#Courbe du temps de vie (avec fit)
############################################################################################################################
#Importation de données d'un fichier CSV
#Importation du module numpy afin de lire le contenu du fichier csv et simplification en np
import numpy as np
#Importation du module matplotlib.pyplot pour construire le graphique et simplification en plt
import matplotlib.pyplot as plt
#Importation du module curve_fit
#Utilisation de la méthode des moindres carrés non linéaires pour ajuster une fonction, f, aux données
from scipy.optimize import curve_fit
#Recherche des coordonnéees des points dans le fichier csv
#Supprime les blancs des lignes & sauts de lignes
#Ou les données sont séparées par des " " à partir de la 2 ème ligne (notée 1)
#pointage = np.loadtxt("em9_life.csv", delimiter=' ', dtype=float, skiprows=1)
with open("em9_life.csv", "r") as infile, open("em9_life1.csv", "w") as outfile:
for line in infile:
line = line.rstrip()
outfile.write(line+"\n")
pointage = np.loadtxt("em9_life1.csv", delimiter=' ',skiprows=1)
#Lecture des abscisses x issues de la deuxième colonne (notée 1) du fichier csv
#Les données se retrouveront dans un tableau d'une ligne
t = pointage[:,1]
#Lecture des ordonnées y issues de la troisième colonne (notée 2) du fichier csv
#Les données se retrouveront dans un tableau d'une ligne
y = pointage[:,2]
print(type(y))
print("Abscisses t (en ns) :",t)
print("Ordonnées y (en counts) :",y)
def dernierIndiceMaximum(liste):
"""
Détermine valeur max des counts
Entrée : liste
Sortie : counts max
"""
maxi = liste[0]
longueur=len(liste)
indice_max = 0
for i in range(longueur):
if liste[i] >= maxi:
maxi = liste[i]
indice_max = i
return indice_max
print("Indice du max :", dernierIndiceMaximum(y))
#Défini le fit théorique
def func(t, a1, a2, a3, b, t0, t1, t2, t3 ):
"""
Détermine le fit théorique
Entrée : Temps, ai (amplitude de décroissance), b (décalage), t0 (temps arrivé pulse), ti (temps d'émission états neutres,
chargés & biexcitons)
Sortie : Fit théorique
"""
return a1*(np.exp(-(t-t0)/t1)) + a2*(np.exp(-(t-t0)/t2)) + a3*(np.exp(-(t-t0)/t3)) + b
#popt : liste (valeurs optimales pour les paramètres)
#pcov : tableau de deux lignes (covariance estimée de popt)
popt, pcov = curve_fit(func, t, y)
print(popt)
#Affiche un repère prédéfini
plt.semilogy() # Affiche une échelle en ordonnée semi-log
plt.axis([0,4e-07,10,100000]) # A commenter pour voir la courbe du temps de vie sans zoom
#plt.title("Emitter 1 lifetime spectrum") # Affiche le titre
plt.gca().xaxis.set_ticklabels([0, 50, 100, 150, 200, 250, 300, 350, 400]) # Redéfini les ticklabels de l'axe x
plt.xlabel('Time (ns)') # Affiche la légende sur l'axe des abscisses
plt.ylabel('Counts') # Affiche la légende sur l'axe des ordonnées
#plt.plot(t,y,"b-") # Trace une liaison entre les points en bleu
plt.plot(t[dernierIndiceMaximum(y):],y[dernierIndiceMaximum(y):],"b-")
plt.plot(t, func(t, *popt), 'r-', label='Fit : t1=%5.3f, t2=%5.3f, t3=%5.3f' % tuple(popt)) # Trace une liaison entre des points en rouge
plt.legend() # Affiche les légendes des courbes
plt.show() # Montre le graphique à l'écran
Ainsi, je ne sais pas trop la façon de procédé pour la définition de la fonction func (plus précisément les arguments, sachant que je souhaiterai déterminer a1, a2, a3, b, t0, t1, t2 et t3). Il en est de même pour la ligne de code plt.plot(t, func(t, *popt), 'r-', label='Fit : t1=%5.3f, t2=%5.3f, t3=%5.3f' % tuple(popt)) où on m'affiche un message d'erreur : "not all arguments converted during string formatting".
Voici ci-dessous le résultats attendu :
Pour finir, pourriez-vous m'éclaircir sur les étapes que je dois entreprendre sur mon code afin de régler ces problèmes, s'il vous plaît.
Tout d'abord, merci pour votre aide. Mais, j'ai néanmoins un problème qui persiste.
Voici ci-dessous mon code :
############################################################################################################################
#Courbe du temps de vie (avec fit)
############################################################################################################################
#Importation de données d'un fichier CSV
#Importation du module numpy afin de lire le contenu du fichier csv et simplification en np
import numpy as np
#Importation du module matplotlib.pyplot pour construire le graphique et simplification en plt
import matplotlib.pyplot as plt
#Importation du module curve_fit
#Utilisation de la méthode des moindres carrés non linéaires pour ajuster une fonction, f, aux données
from scipy.optimize import curve_fit
#Recherche des coordonnéees des points dans le fichier csv
#Supprime les blancs des lignes & sauts de lignes
#Ou les données sont séparées par des " " à partir de la 2 ème ligne (notée 1)
#pointage = np.loadtxt("em9_life.csv", delimiter=' ', dtype=float, skiprows=1)
with open("em9_life.csv", "r") as infile, open("em9_life1.csv", "w") as outfile:
for line in infile:
line = line.rstrip()
outfile.write(line+"\n")
pointage = np.loadtxt("em9_life1.csv", delimiter=' ',skiprows=1)
#Lecture des abscisses x issues de la deuxième colonne (notée 1) du fichier csv
#Les données se retrouveront dans un tableau d'une ligne
t = pointage[:,1]
#Lecture des ordonnées y issues de la troisième colonne (notée 2) du fichier csv
#Les données se retrouveront dans un tableau d'une ligne
y = pointage[:,2]
print(type(y))
print("Abscisses t (en ns) :",t)
print("Ordonnées y (en counts) :",y)
def dernierIndiceMaximum(liste):
"""
Détermine valeur max des counts
Entrée : liste
Sortie : counts max
"""
maxi = liste[0]
longueur=len(liste)
indice_max = 0
for i in range(longueur):
if liste[i] >= maxi:
maxi = liste[i]
indice_max = i
return indice_max
print("Indice du max :", dernierIndiceMaximum(y))
#Défini le fit théorique
def func(t, a1, a2, a3, b, t0, t1, t2, t3 ):
"""
Détermine le fit théorique
Entrée : Temps, ai (amplitude de décroissance), b (décalage), t0 (temps arrivé pulse), ti (temps d'émission états neutres,
chargés & biexcitons)
Sortie : Fit théorique
"""
return a1*(np.exp(-(t-t0)/t1)) + a2*(np.exp(-(t-t0)/t2)) + a3*(np.exp(-(t-t0)/t3)) + b
#popt : liste (valeurs optimales pour les paramètres)
#pcov : tableau de deux lignes (covariance estimée de popt)
popt, pcov = curve_fit(func, t, y)
print(popt)
#Affiche un repère prédéfini
plt.semilogy() # Affiche une échelle en ordonnée semi-log
plt.axis([0,4e-07,10,100000]) # A commenter pour voir la courbe du temps de vie sans zoom
#plt.title("Emitter 1 lifetime spectrum") # Affiche le titre
plt.gca().xaxis.set_ticklabels([0, 50, 100, 150, 200, 250, 300, 350, 400]) # Redéfini les ticklabels de l'axe x
plt.xlabel('Time (ns)') # Affiche la légende sur l'axe des abscisses
plt.ylabel('Counts') # Affiche la légende sur l'axe des ordonnées
#plt.plot(t,y,"b-") # Trace une liaison entre les points en bleu
plt.plot(t[dernierIndiceMaximum(y):],y[dernierIndiceMaximum(y):],"b-")
plt.plot(t, func(t, *popt), 'r-', label='Fit : t1=%5.3f, t2=%5.3f, t3=%5.3f' % tuple(popt)[5:]) # Trace une liaison entre des points en rouge
plt.legend() # Affiche les légendes des courbes
plt.show() # Montre le graphique à l'écran
Voici ci-dessous la courbe obtenue :
Ainsi, le fit n'est pas correct car il doit être du type exponentielle. De plus, les temps t1, t2 et t3 sont négatifs, ce qui est faut sachant qu'ils doivent être t1=4*10^(-9), t2=20*10^(-9), t3=40*10^(-9).
Pour finir, pourriez-vous m'éclaircir sur les étapes que je dois effectuer sur mon code afin de régler ces problèmes, s'il vous plaît.
Répondez-moi quand vous aurez du temps libre.
Je vous en serai très reconnaissant.
Merci de votre compréhension.
- Edité par MilinoKEROWGODAGE 29 juillet 2021 à 18:59:47
Tu affiches tes données au début. Est-ce là que tu découvres que t1, t2 et t3 sont négatifs? Si c'est le cas, il faudrait peutêtre vérifier tes données dans le fichier. Sinon, détermines où ça devient négatif. Pour la fonction dernierIndiceMaximum, on peut simplifier: indice = max((v, i) for i, v in enumerate(liste))[1]
Le Tout est souvent plus grand que la somme de ses parties.
un truc que j'ai vu (mais qui ne résout pas le problème) c'est que l'on veut déterminer l'équation pour cette partie de la courbe (sachant qu'avant et après il y a des valeurs autres), il faut passer à curve_fit la plage de données correspondante en t et en y. et j'ai un doute sur ta formule de func
Fit de courbe
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Le Tout est souvent plus grand que la somme de ses parties.