How can I fit an equation which is not a function

时光总嘲笑我的痴心妄想 提交于 2019-12-11 15:06:57

问题


Given data points in the xy plane, I would like to use scipy.optimize.leastsq to find fit parameters for an ellipse (which cannot be written as a function of x and y). I tried setting the entire equation equal to zero, and then fitting this function, but the fit is failing to converge with error output

"The relative error between two consecutive iterates is at most 0.000000."

The code is shown below, as well as the output. The fitter clearly does not find any reasonable parameters. My question is whether or not this is a problem with scipy.optimize.leastsq, or whether the "trick" of setting the function equal to zero and instead fitting that is not valid.

from scipy.optimize import leastsq, curve_fit
import numpy as np

import matplotlib.pyplot as plt

def function(x,y,theta,smaj,smin):
    xp = np.cos(theta)*x - np.sin(theta)*y
    yp = np.sin(theta)*x + np.cos(theta)*y

    z = ((xp)**2)/smaj**2 + ((yp)**2)/smin**2

    return z

def g(x,y,smaj,smin):
    return x*x/smaj**2 + y*y/smin**2


def window(array,alt,arange):
        arr = [array[i] for i,a in enumerate(alt) if a > arange[0] and a < arange[1]]
        return np.asarray(arr)

def fitter(p0,x,y,func,errfunc,err):
# the fitter function   
    out = leastsq(errfunc,p0,args=(x,y,func,err),full_output=1)
    pfinal = out[0]
    covar  = out[1]
    mydict = out[2]
    mesg   = out[3]
    ier    = out[4]
    resids = mydict['fvec']
    chisq  = np.sum(resids**2)
    degs_frdm     = len(x)-len(pfinal) 
    reduced_chisq = chisq/degs_frdm
    ls = [pfinal,covar,mydict,mesg,ier,resids,chisq,degs_frdm,reduced_chisq]
    print('fitter status: ', ier, '-- aka -- ', mesg)
    i = 0
    if covar is not None: 
        if (ier == 1 or ier == 2 or ier == 3 or ier == 4):
            for u in pfinal:
                print ('Param', i+1, ': ',u, ' +/- ', np.sqrt(covar[i,i])) 
                i = i + 1
            print ('reduced chisq',reduced_chisq)

        else:
            print('fitter failed')

    return ls

def func(x,y,p):
    x = x-p[3]
    y = y-p[4]
    xp = np.cos(p[0])*(x) - np.sin(p[0])*(y)
    yp = np.sin(p[0])*(x) + np.cos(p[0])*(y)
    z = ((xp)**2)/p[1]**2 + ((yp)**2)/p[2]**2 - 1

    return z

def errfunc(p,x,y,func,err):

    return (y-func(x,y,p))/err    


t = np.linspace(0,2*np.pi,100)
xx = 5*np.cos(t); yy = np.sin(t)


p0 = [0,5,1,0,0]
sigma = np.ones(len(xx))
fit = fitter(p0,xx,yy,func,errfunc,sigma)

params     = fit[0]
covariance = fit[1]
residuals  = fit[5]    
t = np.linspace(0,2*np.pi,100)
xx = 5*np.cos(t); yy = np.sin(t)
plt.plot(xx,yy,'bx',ms = 4)



xx = np.linspace(-10,10, 1000)
yy = np.linspace(-5, 5, 1000)
newx = []
newy = []
for x in xx:
    for y in yy:
        if 0.99 < func(x,y,params) < 1.01:
          #if g(x,y,5,1) == 1:
            newx.append(x)
            newy.append(y)


plt.plot(newx,newy,'kx',ms = 1)
plt.show()        

The blue crosses are the actual data, and the black line is the fitters guess at the parameters.

来源:https://stackoverflow.com/questions/47116977/how-can-i-fit-an-equation-which-is-not-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!