Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error: [only length-1 arrays can be converted to Python scalars] when changing variable order

Dear Stackoverflow Community,

I am very new to Python and to programming in general, so please don't get mad when I don't get your answers and ask again.

I am trying to fit a curve to experimental data with scipy.optimization.curve_fit. This is my code:

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as nm
from __future__ import division
import cantera as ct
from matplotlib.backends.backend_pdf import PdfPages
import math as ma
import scipy.optimize as so


R = 8.314
T = nm.array([700, 900, 1100, 1300, 1400, 1500, 1600, 1700])
k = nm.array([289, 25695, 763059, 6358040, 14623536, 30098925, 56605969, 98832907])


def func(A, E, T):
    return A*ma.exp(-E/(R*T))
popt, pcov = so.curve_fit(func, T, k)

Now this code works for me, but if I change the function to:

def func(T, A, E)

and keep the rest I get:

TypeError: only length-1 arrays can be converted to Python scalars

Also I am not really convinced by the Parameter solution of the first one. Can anyone tell me what happens when you change the variable order?

like image 960
ffrank Avatar asked May 25 '26 21:05

ffrank


1 Answers

I got the same problem and found the cause and its solution: The problem lies on the implementation of Scipy. After the optimal parameter has been found, Scipy calls your function with the input array xdata as first argument. That is, it calls func(xdata, *args), and the function complains with a type error because xdata is not an scalar. For example:

from math import erf
erf([1, 2]) # TypeError
erf(np.array([1, 2])) # TypeError

To avoid the error, you can add custom code for supporting arrays, or better, as suggested in the answer of Joris, use numpy functions because they have support for scalars and arrays.

If the math function is not in numpy , like erf or any custom function you coded, then I recommend you instead of doing from math import erf, to do as follows:

from math import erf as math_erf # only supports scalars
import numpy as np
erf = np.vectorize(math_erf) # adds array support

def fit_func(t,s):
    return 0.5*(1.0-erf(t/(np.sqrt(2)*s)))

X = np.linspace(-5,5,1000)
Y = np.array([fit_func(x,1) for x in X])
curve_fit(fit_func, X, Y)
like image 85
Carlos Pinzón Avatar answered May 28 '26 10:05

Carlos Pinzón



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!