Search code examples
pythoncurve-fittingleast-squaresbsplinefunction-fitting

leastsq trouble passing parameters Python


I am trying to fit the following function: Detrended SNR enter image description hereinto my data. C1, C2 and h are the parameters I need to obtain from the leastsq's method. C1 and C2 are simple but the problem is that my h(t) is in reality: Function based on B-Splines. What I want to obtain are the coefficients hj inside that function (in my case there are 35 different hj's ). This function is the sum of different basis B-Splines each one weighted different and the number of coefficients is equal to the number of knots of the B-Spline. As I want to obtain C1, C2 and h1..35 I do the following:

funcLine = lambda tpl, eix_x: (tpl[0]*np.sin((4*math.pi*np.sum(bsplines_evaluades * np.transpose([tpl[2],tpl[3],tpl[4],tpl[5],tpl[6],tpl[7],tpl[8],tpl[9],tpl[10],tpl[11],tpl[12],tpl[13],tpl[14],tpl[15],tpl[16],tpl[17],tpl[18],tpl[19],tpl[20],tpl[21],tpl[22],tpl[23],tpl[24],tpl[25],tpl[26],tpl[27],tpl[28],tpl[29],tpl[30],tpl[31],tpl[32],tpl[33],tpl[34],tpl[35],tpl[36],tpl[37]]) , axis=0))*eix_x/lambda1) + tpl[1]*np.cos((4*math.pi*np.sum(bsplines_evaluades * np.transpose([tpl[2],tpl[3],tpl[4],tpl[5],tpl[6],tpl[7],tpl[8],tpl[9],tpl[10],tpl[11],tpl[12],tpl[13],tpl[14],tpl[15],tpl[16],tpl[17],tpl[18],tpl[19],tpl[20],tpl[21],tpl[22],tpl[23],tpl[24],tpl[25],tpl[26],tpl[27],tpl[28],tpl[29],tpl[30],tpl[31],tpl[32],tpl[33],tpl[34],tpl[35],tpl[36],tpl[37]]) , axis=0))*eix_x/lambda1))*np.exp(-4*np.power(k, 2)*lambda_big*np.power(eix_x, 2))
func = funcLine
ErrorFunc = lambda tpl, eix_x, ydata: np.power(func(tpl, eix_x) - ydata,2)
tplFinal1, success = leastsq(ErrorFunc, [2, -2, 8.2*np.ones(35)], args=(eix_x, ydata))

tpl(0)=C1, tpl(1)=C2 and tpl(2..35)=my coefficients. bsplines_evaluades is a matrix [35,86000] where each row is the temporal function of each basis b-spline so I weight each row with its individual coefficient, 86000 is the length of eix_x. ydata(eix_x) is the function I want to aproximate. lambda1= 0.1903 ; lambda_big= 2; k=2*pi/lambda1. The output is the same initial parameters which is not logic. Can anyone help me? I have tried with curvefit too but it does not work. Data is in : http://www.filedropper.com/data_5>http://www.filedropper.com/download_button.png width=127 height=145 border=0/>
http://www.filedropper.com >online backup storage

EDIT The code right now is:

lambda1 = 0.1903
k = 2 * math.pi / lambda1
lambda_big = 2
def funcLine(tpl, eix_x):
    C1, C2, h = tpl[0], tpl(1), tpl[2:]
    hsum = np.sum(bsplines_evaluades * h, axis=1)  # weight each
    theta = 4 * np.pi * np.array(hsum) * np.array(eix_x) / lambda1
    return (C1*np.sin(theta)+C2*np.cos(theta))*np.exp(-4*lambda_big*(k*eix_x)**2)  # lambda_big = 2
if len(eix_x) != 0:
    ErrorFunc = lambda tpl, eix_x, ydata: funcLine(tpl, eix_x) - ydata
    param_values = 7.5 * np.ones(37)
    param_values[0] = 2
    param_values(1) = -2
    tplFinal2, success = leastsq(ErrorFunc, param_values, args=(eix_x, ydata))

The problem is that the output parameters don't change with respect the initial ones. Data (x_axis,ydata,bsplines_evaluades): gist.github.com/hect1995/dcd36a4237fe57791d996bd70e7a9fc7 gist.github.com/hect1995/39ae4768ebb32c27f1ddea97e24d96af gist.github.com/hect1995/bddd02de567f8fcbedc752371b47ff71


Solution

  • It's always helpful (to yourself as well as us) to provide a readable example that is complete enough to be runnable. Your example with lambdas and very long line is definitely not readable, making it very easy for you to miss simple mistakes. One of the points of using Python is to make code easier to read.

    It is fine to have spline coefficients as fit variables, but you want to have the np.ndarray of variables to be exactly 1-dimensional. So your parameter array should be

    param_values = 8.2 * np.ones(37)
    param_values[0] = 2
    param_values[1] = -2.
    result_params, success = leastsq(errorFunc, param_values, ....)
    

    It should be fine to use curve_fit() too. Beyond that, it's hard to give much help, as you give neither a complete runnable program (leaving lots of terms undefined), nor the output or error messages from running your code.