我正在研究使用“ x,y”数据集的类。数据通常来自txt文件,其中数据的第一列存储在“ x”中,第二列存储在“ y”中。
我正在向类添加一些“曲线拟合”功能。我在这篇文章的标题中遇到了错误。
这是课程:
class XY(object):
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
def __init__(self,f=None):
self.file(f)
self.read()
return
def file(self,f=None):
self.filename=self.get_filename(f)
return
def filename(self):
return self.filename
def get_filename(self,f):
if(type(f)==str):
filename=f
elif(type(f)==file):
filename=f.name
else:
filename=None
return filename
def read(self,f=None):
if(f is None):
if(self.filename is None):
return
else: # Use internal filename
filename=self.filename
else: # Change/set internal filename
self.filename=self.get_filename(f)
filename=self.filename
data=[]
try:
with open(filename,'r') as F:
for line in F:
data.append(line.split())
except IOError as e:
print("%s"%e)
return
F.close()
for r in range(0,len(data)):
for c in range(0,len(data[r])):
data[r][c]=float(data[r][c])
self.data=data
self.x=[self.data[i][0] for i in range(0,len(self.data))]
self.y=[self.data[i][1] for i in range(0,len(self.data))]
return self.data
def f00(self,x,a,b,c,d):
return a*x**b*self.np.exp(-c*x)+d
def cf00(self):
popt,pcov=self.curve_fit(self.f00,self.x,self.y)
self.y=self.f00(self.x,*popt)
return self.y
我以交互模式将类粘贴到python中。然后尝试以下操作:
$ python
Python 2.7.14 (default, Oct 31 2017, 21:12:13)
[GCC 6.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
我粘贴上面显示的类,然后尝试以下操作:
>>> xy=XY("rot-03-05.dat")
>>> len(xy.x)
220
>>> len(xy.y)
220
>>> xy.cf00()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 56, in cf00
File "/usr/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 751, in curve_fit
res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
File "/usr/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 383, in leastsq
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
File "/usr/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 27, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "/usr/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 463, in func_wrapped
return func(xdata, *params) - ydata
TypeError: 'XY' object is not callable
>>> xy.cf00
<bound method XY.cf00 of <__main__.XY object at 0x6ff5ea25fd0>>
我尝试从self
和f00()
中取出cf00()
。没用。
我尝试从实例中调用f00()
,并且可以正常工作:
>>> xy=XY()
>>> xy.f00(1,1,1,1,1)
1.3678794411714423
我在其他地方使用了此曲线拟合功能,并且可以正常工作。现在,我正在尝试在一个类中实现它。
以下是独立的函数,当它们不属于类时可以使用:
def f00(x,a,b,c,d): return a*x**b*np.exp(-c*x)+d
def cf00(x,y):
popt,pcov=curve_fit(f00,x,y,maxfev=1200000)
return f00(x,*popt)
y1=cf00(x,y)
没问题。
答案 0 :(得分:2)
因此,您正在类定义中导入from scipy.optimize import curve_fit
,并且python将该名称绑定到了类名称空间,因此,当您调用self.curve_fit
时,它是有效的,但请记住curve_fit
函数在scipy
内部定义。
当您致电self.method()
时,实际上是:
type(self).method(self)
,因此,当您调用self.curve_fit
时,它将类XY
作为第一个参数传递,并且它需要一个函数。
为解决此问题,我建议将导入内容放在文件的最顶部,然后仅调用curve_fit
而不使用self
答案 1 :(得分:0)
这是一个很大的代码块,但我概述了您的代码中应修复的所有内容,包括注释:
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
from io import TextIOWrapper # to check file-handle type
# Import modules at the global level, makes life easier
class XY(object):
def __init__(self,f=None):
self.filename = self.get_filename(f)
self.data, self.x, self.y = self.read()
# Don't return from __init__
# return
# This function is unnecessary
# def file(self,f=None):
# self.filename=self.get_filename(f)
# return
# This doesn't do anything, just access the attribute like instance.filename
# def filename(self):
# return self.filename
def get_filename(self,f):
if isinstance(f, str): # use isinstance for type checking
filename=f
elif isinstance(f, TextIOWrapper):
filename=f.name
else:
filename=None # I'd probably raise an exception here
return filename
def read(self): # the f param wasn't used otherwise
# The whole block here was just a repeat of self.get_filename, no
# need for it
data=[]
try:
with open(filename,'r') as F:
for line in F:
data.append(line.split())
except IOError as e:
# I would just let the exception happen and raise it
print("%s"%e)
raise
# return # Don't just return None, you'll get weird behavior
# F is already closed, that's what with does
# F.close()
for r in range(0,len(data)):
for c in range(0,len(data[r])):
data[r][c]=float(data[r][c])
x = [self.data[i][0] for i in range(0,len(self.data))]
y = [self.data[i][1] for i in range(0,len(self.data))]
return data, x, y # It's generally bad form to assign self.attr outside of __init__
def f00(self,x,a,b,c,d):
return a*x**b*np.exp(-c*x)+d
def cf00(self):
popt, pcov = curve_fit(self.f00, self.x, self.y) # you don't need self.curve fit since it's now globally imported
self.y=self.f00(self.x, *popt)
return self.y # Not sure you need to return this, since you can just access it after the function is called
作为以后的参考,最好仅包含复制您面临的问题所需的内容,仅此而已。这样可以更轻松地找出问题所在。一个最小的工作示例可能如下所示:
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
def XY(object):
def __init__(self):
self.x = [float(a) for a in range(100)]
self.y = [float(a) for a in range(100)]
self.data = list(zip(self.x, self.y))
def f00(self,x,a,b,c,d):
return a*x**b*np.exp(-c*x)+d
def cf00(self):
popt, pcov = curve_fit(self.f00, self.x, self.y)
return self.f00(self.x, *popt)
更容易发现问题所在