问题
I'm new to curve fitting in python, as well as python in general. Currently, I'm trying to use the curve_fit module from scipy to fit 4 spectroscopic peaks.
In a few words, I have data in a text file that has two columns. So my first step was to import the data into two arrays, one containing the xdata, the other the y data. Then I tried to define the function that I was going to fit (four voigt peaks). Finally, when I tried to run the whole thing, I get the following error:
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m)) TypeError: Improper input: N=11 must not exceed M=1
As far as I can tell from the curve_fit help page, this error says that I must have at least as many data points as fit parameters, which makes sense. The problem is that my data set has 250 points in it...
Here's my code
import numpy as n
import pyspec as p
from scipy.optimize import curve_fit
file = open('fileName', "r") #open the file
data = n.loadtxt(file) #load the file into an array
freq = n.array(data[:, 0] - n.median(data[:, 0])) #center data on zero.
counts = n.array(data[:, 1])
error = n.array(data[:, 1]**0.5) #get the error on the counts. Standard poisson error.
# Define a single voigt profile
def voigt(xdata, amp, cent, FWHM, ep) :
x = xdata
C = cent
F = FWHM
A = amp
E = ep
vmodel = A * ((1 - E)*n.exp(-2.77259 * (n.square(x - C))/n.square(F)) + E / (1 + (4 * n.square(x - C)/F**2)))
return[vmodel]
#Define the four peak function
def voigt4(xdata, amp1, amp2, amp3, amp4, pos1, pos2, pos3, pos4, FWHM, ep, Bg):
voigtp1 = voigt(xdata, amp1, pos1, FWHM, ep)
voigtp2 = voigt(xdata, amp2, pos2, FWHM, ep)
voigtp3 = voigt(xdata, amp3, pos3, FWHM, ep)
voigtp4 = voigt(xdata, amp4, pos3, FWHM, ep)
voigt4 = (voigtp1 + voigtp2 + voigtp3 + voigtp4 + Bg) # include a background term
return[voigt4]
# give an initial guess. The *_in params are initial guesses made by the user.
guess = n.array([amp1_in, amp2_in, amp3_in, amp4_in, pos1_in, pos2_in, pos3_in, pos4_in, 500, 0.5, bkgr_in])
fit = curve_fit(voigt4, freq, counts, guess) # try to fit
I have no idea why that error comes up.
回答1:
As already written in the comments, you should remove the brackets in your return statements in your functions voigt
and voigt4
. The problem with the brackets is that you put your array which you want to return in a list and thereby you reduce the dimensions of your returned object. Consider the following example:
import numpy as np
ar = np.array([1, 2, 3, 4])
Then the command
len(ar)
would return 4 and
a[0]
returns 1 as expected. If you now do
b = [ar]
as you did in your return statement
b
would be
[array([1, 2, 3, 4])]
and
b[0]
not a single value anymore but the entire original array:
array([1, 2, 3, 4])
which means that you you receive and error like
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-269-33e961e0e4ea> in <module>()
----> 1 b[1]
IndexError: list index out of range
if you tried to access b[1]
.
So it is then not a big surprise that you receive an error message regarding the dimensions since you reduce the multidimensional object to a one dimensional object.
来源:https://stackoverflow.com/questions/34864656/dimension-issue-with-scipys-curve-fit-function