Reputation: 113
I'm converting a code from Python 2.7 to Python 3.8.
In its Python 2.7 version, I had to use downgraded versions of scipy and numpy in order to avoid a TypeError (see below). With Python 3.8, these downgraded versions of scipy and numpy are not available anymore and I get this error, which I'm unable to fix.
1. Setup
Previous : MacOS Catalina 10.15.7, Python 2.7.16, numpy 1.9.0, scipy 1.0.1
New : MacOS Catalina 10.15.7, Python 3.8.6, numpy 1.20.3, scipy 1.4.0
2. Code
It happens when calling scipy.integrate.odeint
:
y_trajectory = scipy.integrate.odeint(growth_a_derivs, y_start, t_array, atol=eps, args=myargs)
With growth_a_derivs
a function, y_start, t_array
numpy arrays with dtype float64
, eps
a float and myargs
a tuple of length 1 containing a dictionary.
3. Error
The following traceback pops :
Traceback (most recent call last):
<long blah blah blah>
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyxcosmo/icosmo_cosmo.py", line 149, in growth_a
result=growth_a_ode(cosmo, a, unnorm=unnorm)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyxcosmo/icosmo_cosmo.py", line 671, in growth_a_ode
y_trajectory = scipy.integrate.odeint(growth_a_derivs, y_start, t_array, atol=eps, args=myargs)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/scipy/integrate/odepack.py", line 242, in odeint
output = _odepack.odeint(func, y0, t, args, Dfun, col_deriv, ml, mu,
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
So the last line is in scipy's integrate pckg, the full call to odeint is :
output = _odepack.odeint(func, y0, t, args, Dfun, col_deriv, ml, mu,
full_output, rtol, atol, tcrit, h0, hmax, hmin,
ixpr, mxstep, mxhnil, mxordn, mxords,
int(bool(tfirst)))
Inside this, the error is in a compiled scipy .so
file, thus I can't analyze this error further. I just know that the call to growth_a_derivs isn't problematic (its print() calls all work). But I don't know whether its a numpy or scipy problem, and how to overcome it.
4. Resolution !
I was able to understand the problem thanks to @RFoxtea answer below.
I believe this issue was caused by the change in numpy version.
The output of growth_a_derivs
is :
np.array([f1,f2])
with :
type(f1) = numpy.float64
type(f2) = numpy.ndarray
f2.shape = (1,)
With numpy 1.9, this gives :
np.array([f1,f2]) = [1.234, np.array([1.234])]
np.array([f1,f2]).dtype = numpy.float64
With numpy 1.20, this gives :
np.array([f1,f2]) = [1.234, np.array([1.234])]
np.array([f1,f2]).dtype = numpy.object
And that is not accepted by scipy.integrate.odeint
.
However, notice that scipy.integrate.solve_ivp
is ok with that.
Thanks for your help !
Upvotes: 0
Views: 232
Reputation: 113
Thanks to @RFoxtea who provided the right solution.
However there is an interesting alternative. You can use scipy.integrate.solve_ivp instead of scipy.integrate.odeint
.
Solve_ivp can handle an output of fun
that is with dtype object
.
Upvotes: 0
Reputation: 128
At some point in running scipy.integrate.odeint
, Numpy is told to convert an array of Python objects into an array of floats, and it's answering you that it can't do that. Your description suggests the problem has to be with y_start
, t_start
or (maybe, I'm not sure) the return value of growth_a_derivs
. Please make sure that these all have an appropriate dtype
that can be converted into a float. Could be very easy to fix.
Upvotes: 1