Bonjour ou bonsoir, je travaille avec Python (v.3.13) pour modéliser mes données (mesures de spectres de raies en spectrométrie), (x_i, y_i) i=range(n), avec divers types de courbes, dont la base est une somme en nombre variable de gaussiennes (ou autres formes, mais laissons ça de côté). Pour ça, je recours à la fonction du package scipy, "scipy.optimize.curve_fit". Mon problème est que "curve_fit" s'attend à recevoir la fonction à ajuster (enfin, ses paramètres), avec une liste explicite et "figée" de paramètres. Pour simplifier, je suppose ici que je connais exactement la position et la largeur des gaussiennes, et que je n'ai que leurs hauteurs à ajuster. Si par exemple, j'ai 3 raies, ma fonction d'ajustement sera :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
def spectreThéoriq(xdata, haut1, haut2, haut3) :
   return ( haut1*gaus1(xdata) + haut2*gaus2(xdata) + haut3*gaus3(xdata) )
où les (trois) fonctions "gaus1", etc., sont définies avant dans mon code. L'ajustement se fera ainsi :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
parmOptim = scipy.optimize.curve_fit(spectreThéoriq, xDonnées, yDonnées)
où xDonnées est le vecteur des [x_i, i=1..n] (notation non python…) et similairement pour yDonnées.

Mon problème est donc le suivant : je préfèrerais passer, ici le triplet des paramètres à ajuster, via un vecteur : parms = [haut1, haut2, haut3], parce que, comme dit plus haut, le nombre des gaussiennes est variable (et en réalité, j'ai aussi les autres paramètres comme les positions et les largeurs de ces "gaussiennes" à ajuster ; ici j'ai simplifié). Voici un script simplifié qui fonctionne, mais redemande du travail si je veux prendre en compte la 4è raie ! :-(

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env python3
## fit_spectre_exmpl.py
 
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as sop
 
def gaus_(xdata, posit, larg) :
   return np.exp(-0.5*((xdata-posit)/larg)**2)
def gaus1(xdata) : return gaus_(xdata, 2.5, 0.3)
def gaus2(xdata) : return gaus_(xdata, 4.5, 0.4)
def gaus3(xdata) : return gaus_(xdata, 6.0, 0.4)
def gaus4(xdata) : return gaus_(xdata, 8.0, 0.3)
 
np.random.seed(145320) # reproductibilité du hasard
xDonnées = np.linspace(0.5,10.,100)
yDonnées = 1.2 * gaus1(xDonnées) + 3.2 * gaus2(xDonnées)
yDonnées += 2.1 * gaus3(xDonnées) + 0.7 * gaus4(xDonnées)
yDonnées += 0.2 * np.random.randn(len(xDonnées))
 
def spectreThéoriq(xObs, h1, h2, h3) :
   return ( h1 * gaus1(xObs) + h2 * gaus2(xObs) + h3 * gaus3(xObs) )
 
hOpt, hCov = sop.curve_fit(spectreThéoriq, xDonnées, yDonnées)
print("Hauteurs optimisées =", hOpt)
yAjustés = spectreThéoriq(xDonnées, *hOpt)
 
plt.plot(xDonnées, yDonnées, "bo-")
plt.plot(xDonnées, yAjustés, "r-")
plt.show()
##
Comment faire pour travailler avec un "def spectreThéoriq(xObs, hautS) :" où l vecteur hautS contient les (ici 3) paramètres ? Sur la base de l'utilisation des "arguments étoilés", j'ai essayé ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
def spectreThéoriq(xObs, *hautS) :
   hautS = hautS[0]
   nParm = len(hautS)
  ...
mais curve_fit me renvoie cette erreur :
ValueError: Unable to determine number of fit parameters.

Merci par avance de vos suggestions. -- ÉLw.py