I'm new to Python and, for work reason, I'm trying to write a Python code capable to read three files containing float (x,y) data (let's say x1,y1; x2,y2; x3,y3) and combine two of the arrays (y1 and y2) with a linear combination to approach the third (y3) as closely as possible. Moreover, x1 and x2 are identical, whereas x3 is different, so I interpolate x3 and y3 using x1. I'm working on Idle on Mac OSX, and Python 2.7. Here's my code:
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 * spectrum1 + guess * 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()
When I try to run the code I get:
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
I understand that something is wrong with my leastsq usage, but I really can't figure out what it could be, my knowledge of Python is clearly insufficient. Can someone help me ?
The error clearly states what's wrong: you are passing an array instead of a function/callable. In fact the
leastsq documentation states that the first argument should be a callable.
You are passing
ErrorFunc as first argument but this is not a function nor a callable. It's an array. (It may represent a function, but it isn't in the format required by
So you have to follow the description for the argument:
should take at least one (possibly length
Nvector) argument and returns
Mfloating point numbers. It must not return
NaNs or fitting might fail.
ErrorFunc with a callable that given the input returns the error as floats. Basically you should have:
def error_func(input): return input - data
data is your experimental data and
input is the value of the fitting that
scipy is doing. It needs a callable because it will perform more iterations and for each iteration it has to compute the error in order to fit the data.
error_func to match what you are doing, that is only to give the idea of what is expected by