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

LMFIT on Python: TypeError: only size-1 arrays can be converted to Python scalars… here is a solution to the problem.

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

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

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

Solution

The error occurs integrate_function your function is called with np.array as an argument to 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. The quad cannot handle vectorized input, which is happening in your case.

One way to solve this problem is to change the case where integrate_function handle q to be an array accordingly, such as by manually containing a loop that contains all the 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)

Execute your code with the modified integrate_function and then produce the following plot:

enter image description here

Related Problems and Solutions