Rafael Freire
Rafael Freire

Reputation: 33

LMFIT on Python: TypeError: only size-1 arrays can be converted to Python scalars

I am trying to create an curve fitting program using LMFIT on python (Anaconda) but I keep receiving the same error message: TypeError: only size-1 arrays can be converted to Python scalars. I was able to perform an optimization using just one function, but when I try to optimize a function that calls other user-defined functions, I get this error.

import numpy as np
from matplotlib import pyplot
import scipy.special as sp
from scipy import integrate
import lmfit as lm


#Defining the first function.
def function1(alpha,q,s,l):

    Intensity = alpha**2 + q -s*alpha / (5*l)
    return Intensity

#Defining a second function that will perform a integration over the first function.
def integrate_function(q,s,l):
    func_parameters = {
        'q':q,
        's':s,
        'l':l,
    }
    to_be_integrated = lambda alpha: function1(alpha, **func_parameters)
    result, error = integrate.quad(to_be_integrated, 0, 10)
    return result

#Setting up the LMFIT model. Here I also provide the initial guess for the parameters.
integrate_function_model = lm.Model(integrate_function, independent_vars=['q'])
integrate_function_model.set_param_hint('s', value=2, min=-10.0, max=20.0, vary=True)
integrate_function_model.set_param_hint('l', value=3, min=1.0, max=10.0, vary=True)
initial_params = integrate_function_model.make_params()

#Creating data to be fitted (I also add some noise)
#Here I set s=1.5 and l=5.0 and I want the optimization routine to be able to find out these numbers.
x_data = np.linspace(0, 10, 100)
y_data = np.zeros(len(x_data))
for i in range(len(x_data)):
    y_data[i] = integrate_function(x_data[i],1.5,5.0)  + 5.0*np.random.random()


#Fitting the data.
fitting = integrate_function_model.fit(y_data, initial_params, q=x_data, method='leastsq')

#Printing original data and fitted model.
pyplot.plot(x_data, y_data, color='green', lw=2)
pyplot.plot(x_data, fitting.best_fit, color='blue', lw=2)
pyplot.show()

Upvotes: 3

Views: 1635

Answers (1)

jdamp
jdamp

Reputation: 1460

The error occurs when your function integrate_function is called with a np.array as an argument for q:

>>> integrate_function(1,1,1)
333.33333333333337
>>> integrate_function(np.array([1,2]),1,1)
TypeError: only size-1 arrays can be converted to Python scalars

This happens during output.fit where integrate.quad is called. quad is not able to handle vectorized input, which is happening in your case.

One option to fix this would be to change integrate_function to handle the case where q is an array accordingly, for example by manually including a loop over all values in q:

def integrate_function(q,s,l):
    # Make q iterable if it is only a float/int
    if not hasattr(q, '__iter__'):
        q = np.array([q])

    result = []
    for q0 in q: 
        func_parameters = {
        'q':q0,
        's':s,
        'l':l,
    }
        to_be_integrated = lambda alpha: function1(alpha, **func_parameters)
        result.append(integrate.quad(to_be_integrated, 0, 10)[0])
    return np.array(result)

Executing your code with the modified integrate_function then yields the following plot:

enter image description here

Upvotes: 3

Related Questions