0

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[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()

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 ?

2 Answers 2

2

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 leastsq).

So you have to follow the description for the argument:

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

So replace ErrorFunc with a callable that given the input returns the error as floats. Basically you should have:

def error_func(input):
    return input - data

Where data is your experimental data andinput 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.

Obviously change error_func to match what you are doing, that is only to give the idea of what is expected by leastsq.

Sign up to request clarification or add additional context in comments.

2 Comments

OK, I understand your response. But, as I'm new to Python, I've searched for examples, and I've found this one: [link]stackoverflow.com/questions/19791581/…, from which I've copied the leastsq use. Why in that case it was OK and not in my case? Thanks!
I think that I've caught the point re-reading the example in the link above. I'll try again. Thanks for helping.
0

Just in case it could help other people, I've made the code work with:

<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()
...

Thanks Bakuriu!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.