2016-03-26 4 views
0

Я новичок в Python и, по причине работы, я пытаюсь написать код Python, способный читать три файла, содержащие float (x, y) (скажем, x1, y1; x2, y2; x3, y3) и объединить два массива (y1 и y2) с линейной комбинацией, чтобы как можно ближе подойти к третьей (y3). Более того, x1 и x2 идентичны, тогда как x3 отличается, поэтому я интерполирую x3 и y3 с помощью x1. Я работаю над Idle на Mac OSX и Python 2.7. Вот мой код:TypeError: объект «numpy.ndarray» не может быть вызван в scipy.optimize lesssq

import numpy as np 
import matplotlib.pyplot as plt 
import Tkinter as tk 
import tkFileDialog 
from scipy.optimize import leastsq 

root1 = tk.Tk() 
root1.geometry() #window centered on desktop? 
root1.withdraw() #the main app window doesn't remain in the background 
filename1 = tkFileDialog.askopenfilename(parent=root1, title="Ouvrir le spectre n° 1", 
    filetypes=[('dat files', '.dat'), ('all files', '.*')], 
    initialdir="/Users//Science/Manips/2011_10_05_Nb_W/") 
filename2 = tkFileDialog.askopenfilename(parent=root1,title="Ouvrir le spectre n° 2", 
    filetypes=[('dat files', '.dat'), ('all files', '.*')], 
    initialdir="/Users/Science/Manips/2011_10_05_Nb_W/") 
filenameexp = tkFileDialog.askopenfilename(parent=root1, title="Ouvrir le spectre exp", 
    filetypes=[('txt files', '.txt'), ('all files', '.*')], 
    initialdir="/Users/Science/Manips/2011_10_05_Nb_W/spectres_exp") 

print 'Fichiers choisis = ' 
print filename1 
print filename2 
print filenameexp 

energy1, spectrum1 = np.loadtxt(filename1, delimiter=' ', usecols=(0, 1), 
          unpack=True, skiprows=0) 
energy2, spectrum2 = np.loadtxt(filename2, delimiter=' ', usecols=(0, 1), 
          unpack=True, skiprows=0) 
energyexp, spectrumexp = np.loadtxt(filenameexp, delimiter='\t', usecols=(0, 1), 
          unpack=True, skiprows=0) 

#Interpolating experimental energy grid on theoretical energy grid 
sp_exp_int = np.interp(energy1, energyexp, spectrumexp) 

#guess contains the first guess of the parameters 
guess=[1.0,1.0] 
spec_theo = guess[0] * spectrum1 + guess[1] * spectrum2 

# ErrorFunc is the difference between the "fit" and the y experimental data 
ErrorFunc = spec_theo - sp_exp_int 
# leastsq finds the set of parameters in the tuple tpl that minimizes 
# ErrorFunc=yfit-yExperimental 
tplFinal, success = leastsq(ErrorFunc, guess[:], args=(energy1, sp_exp_int)) 
print "best choice = ", tplFinal 

fig, ax1 = plt.subplots() 
theory = ax1.plot(energy1, spec_theo, 'b-', label='Theory') 
ax1.set_xlabel('Energy (eV)') 
# Make the y-axis label and match the line color. 
ax1.set_ylabel('Theory', color='b') 

ax2 = ax1.twinx() 
experiment = ax2.plot(energy1, sp_exp_int, 'r-', label='Experiment') 
ax2.set_ylabel('Experiment', color='r', rotation=-90, labelpad=15) 

#one legend for all axes 
lns = theory + experiment 
labs = [l.get_label() for l in lns] 
ax1.legend(lns, labs, loc=0) 

plt.show() 

Когда я пытаюсь запустить код, я получаю:

Traceback (most recent call last): 
File "/Users/Science/Manips/2011_05_Nb_W/Mars2016/comblin_leastsquares.py", line 79, in <module> 
tplFinal, success = leastsq(ErrorFunc, guess[:], args=(energy1, sp_exp_int)) 
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site- packages/scipy/optimize/minpack.py", line 377, in leastsq 
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n) 
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/minpack.py", line 26, in _check_func 
res = atleast_1d(thefunc(*((x0[:numinputs],) + args))) 
TypeError: 'numpy.ndarray' object is not callable 

Я понимаю, что что-то не так с моим использованием leastsq, но я действительно не могу понять, что это может быть, мои знания о Питоне явно недостаточны. Может кто-нибудь мне помочь?

ответ

2

Ошибка ясно указывает, что не так: вы передаете массив вместо функции/вызываемого. Фактически в документации leastsq указано, что первым аргументом должен быть , вызываемый.

Вы передаете ErrorFunc в качестве первого аргумента, но это не функция или вызываемая. Это массив. (Возможно, представляет функцию, но она не соответствует формату, требуемому leastsq).

Таким образом, вы должны следовать описание аргумента:

should take at least one (possibly length N vector) argument and returns M floating point numbers. It must not return NaN s or fitting might fail.

Так заменить ErrorFunc с вызываемым, что данный вход возвращает ошибку, как поплавки. В общем, вы должны иметь:

def error_func(input): 
    return input - data 

Где data ваши экспериментальные данные и input это значение фитинга, что scipy делает. Он нуждается в вызове, потому что он будет выполнять больше итераций, и для каждой итерации он должен вычислить ошибку, чтобы соответствовать данным.

Очевидно, что измените команду error_func, чтобы соответствовать тому, что вы делаете, то есть только для того, чтобы дать представление о том, что ожидается от leastsq.

+0

ОК, я понимаю ваш ответ. Но, поскольку я новичок в Python, я искал примеры, и я нашел это: [link] http://stackoverflow.com/questions/19791581/how-to-use-leastsq-function- от-scipy-optimize-in-python-to-fit-both-a-straight, из которого я скопировал использование наименьших значений. Почему в этом случае все в порядке, а не в моем случае? Благодаря! – ariel67

+0

Я думаю, что я понял, что перечитал пример в приведенной выше ссылке. Я попробую еще раз. Спасибо за помощь. – ariel67

0

Только в случае, если это может помочь другим людям, я сделал код работы с:

<same code as in my question> 
#guess contains the first guess of the parameters 
guess=[1.0,1.0] 

# error_func is the difference between the "fit" and the y experimental data 
#error_func = spec_theo - sp_exp_int 
def error_func(coeff, sp1, sp2, y): 
    return (coeff[0] * sp1 + coeff[1] * sp2) - y 

# leastsq finds the set of parameters in the tuple tpl that minimizes 
# error_func=yfit-yExperimental 
guess_fin, success = leastsq(error_func, guess[:], args=(spectrum1, \ 
          spectrum2, sp_exp_int)) 
print 'best choice = ', guess_fin 
print 'success = ', success 

spec_theo = guess_fin[0] * spectrum1 + guess_fin[1] * spectrum2 

fig, ax1 = plt.subplots() 
... 

Благодаря Bakuriu!

Смежные вопросы