Only length-1 arrays can be converted to Python scalars with log - python

from numpy import *
from pylab import *
from scipy import *
from scipy.signal import *
from scipy.stats import *
testimg = imread('path')
hist = hist(testimg.flatten(), 256, range=[0.0,1.0])[0]
hist = hist + 0.000001
prob = hist/sum(hist)
entropia = -1.0*sum(prob*log(prob))#here is error
print 'Entropia: ', entropia
I have this code and I do not know what could be the problem, thanks for any help

This is an example of why you should never use from module import *. You lose sight of where functions come from. When you use multiple from module import * calls, one module's namespace may clobber another module's namespace. Indeed, based on the error message, that appears to be what is happening here.
Notice that when log refers to numpy.log, then -1.0*sum(prob*np.log(prob)) can be computed without error:
In [43]: -1.0*sum(prob*np.log(prob))
Out[43]: 4.4058820963782122
but when log refers to math.log, then a TypeError is raised:
In [44]: -1.0*sum(prob*math.log(prob))
TypeError: only length-1 arrays can be converted to Python scalars
The fix is to use explicit module imports and explicit references to functions from the module's namespace:
import numpy as np
import matplotlib.pyplot as plt
testimg = np.random.random((10,10))
hist = plt.hist(testimg.flatten(), 256, range=[0.0,1.0])[0]
hist = hist + 0.000001
prob = hist/sum(hist)
# entropia = -1.0*sum(prob*np.log(prob))
entropia = -1.0*(prob*np.log(prob)).sum()
print 'Entropia: ', entropia
# prints something like: Entropia: 4.33996609845
The code you posted does not produce the error, but somewhere in your actual code log must be getting bound to math.log instead of numpy.log. Using import module and referencing functions with module.function will help you avoid this kind of error in the future.

Related

Different output with equal input for python program when using iminuit: undefined behavior?

I encountered this wiered bugs that the iminuit cannot converge on a naive linear model. However, the real problem is, if I uncomment the line "#bins = np.linspace(0,4,25)", the result of the program is different, and it can converge.
If "same input" does not produce "same output", it means there is undefined behavior, or segmentation fault. Any ideas?
import numpy as np
import scipy as sp
import scipy.special
import probfit
import pandas as pd
data = pd.read_feather('test.feather').rho2.to_numpy()
print(data)
N,bins = np.histogram(data,bins=24,range=(0,4))
#bins = np.linspace(0,4,25)
print(bins)
x = (bins[:-1]+bins[1:])/2
exposure = 3.8061025098100147
def cost(y0,k):
global x,exposure,N
T = (y0+k*x)*exposure
return -2*np.sum(N*np.log(T)-T-sp.special.loggamma(N+1))
import iminuit
minimizer = iminuit.Minuit(cost,errordef=1,y0=11,k=3,limit_y0=(0,None),limit_k=(0.1,None))
minimizer.migrad()
minimizer.hesse()
minimizer.minos()
display(minimizer.fmin, minimizer.params,minimizer.merrors)
minimizer.draw_mncontour("y0","k")
output:
output
Test input
test.feather.zip
The bug is solved. Although it looks the same using print, the types are different:
data = pd.read_feather('test.feather').rho2.to_numpy()
N,bins = np.histogram(data,bins=24,range=(0,4))
vs
bins = np.linspace(0,4,25)
The first returns float32, and the second returns float64. The iminuit need to calculate the gradient with numerical methods, so the precision of output of cost funciton need to be at least float64.
Best solution is
data = pd.read_feather('test.feather').rho2.to_numpy().astype('float64')

Runtime warning while trying to write equation for line

Equation
This link goes to the picture of the equation i am trying to graph in matplotlib
from matplotlib import pyplot as plt
import numpy as np
x_values = np.arange(1, 10, step=0.1)
y_values = (np.arcsin(np.sqrt(abs(np.sin(x_values) ** (abs(np.cos(x_values)) + abs(np.sin(x_values)) + (2.718281828459045** np.sin(x_values)))))) - x_values)/x_values
The code above throws the following error message:
ipykernel_launcher.py:4: RuntimeWarning: invalid value encountered in power
after removing the cwd from sys.path.
I didn't get to the plotting because this code alone threw an error message
How can i fix this?
numpy does not allow fractional powers of negative numbers, since it expects a complex result and you did not define a complex type. You can inspect your power array like this:
pow = abs(np.cos(x_values)) + abs(np.sin(x_values)) + (2.718281828459045** np.sin(x_values))
a = np.sin(x_values)
and use a workaround like this:
a_pow = np.sign(a) * (np.abs(a)) ** (pow)
y_values = (np.arcsin(np.sqrt(abs(a_pow))) - x_values)/x_values
But make sure in advance that you are not expecting complex numbers as results!
If you do though, change your array dtype to np.complex.

TypeError: only size-1 arrays can be converted to Python scalars + Solution

According to Python Documentation a TypeError is defined as
Raised when an operation or function is applied to an object of inappropriate type. The associated value is a string giving details about the type mismatch.
exception TypeError
The reason I got this Error was because my code looked like this:
import math as m
import pylab as pyl
import numpy as np
#normal distribution function
def normal(x,mu,sigma):
P=(1/(m.sqrt(2*m.pi*sigma**2)))*(m.exp((-(x-mu)**2)/2*sigma**2))
return P
#solution
x = np.linspace(-5,5,1000)
P = normal(x,0,1)
#plotting the function
pyl.plot(x,P)
pyl.show()
P=(1/(m.sqrt(2***m**.pisigma2)))(**m.exp((-(x-mu)2)/2*sigma2))
Notice the m. - This is incorrect, because math. can only handle scalars. And the Error said that a TypeError had occurred.
np. (Numpy) can handle scalers as well as arrays and the problem is solved.
The right code looks like this:
import math as m
import pylab as pyl
import numpy as np
# normal distribution function
def normal(x,mu,sigma):
P = (1/(np.sqrt(2*np.pi*sigma**2))) * (np.exp((-(x-mu)**2)/2*sigma**2))
return P
# solution
x = np.linspace(-5,5,1000)
P = normal(x,0,1)
# plotting the function
pyl.plot(x,P)
pyl.show()
In the end we get a great normal distribution function that looks like this:
This Error occurred in Spyder IDE.

Create mpf from array

I'm trying to use fsolve in combination with the mpmath package.
However, I get the error cannot create mpf from array([mpf('1.0')], dtype=object).
Here is a minimal example reproducing the error. For this example, I technically do not need the mpmath package, but my actual function contains hyperconfluent functions that do.
from scipy.optimize import fsolve
#from mpmath import hyp1f1 as hyp1f1mp
#from mpmath import gamma as gammamp
import mpmath as mp
#import numpy as np
mp.dps = 250; mp.pretty = True
def cosFunc(p):
vn = p
output = mp.sin(vn)
return output
estimate = mp.mpf(1)
value = fsolve(cosFunc,estimate)
print value
I found a similar question suggesting to use np.frompyfunc (How to mpf an array?), but it tells me that the function is not callable (when I apply it on vn).
The trick is to apply np.frompyfunc to a function instead of a value. I think the following modification would make your function work:
def cosFunc(p):
vn = p
np_sin = np.frompyfunc(mp.sin, 1, 1)
output = np_sin(vn)
return float(output)
value = fsolve(cosFunc, 1)
print value
The specific cause of the error you is this:
(Pdb) x0
array([mpf('1.0')], dtype=object)
(Pdb) mp.sin(x0)
*** TypeError: cannot create mpf from array([mpf('1.0')], dtype=object)
What happens is that fsolve tries to convert your estimate to array and numpy does not know how to handle mpmath objects.
>>> np.asarray(mp.mpf(1))
>>> array(mpf('1.0'), dtype=object)
Changing how fsolve works is not very productive, so your best bet seems to be to teach your function to handle arrays of mpmath objects
def cos_func(p):
vn = p
if isinstance(p, np.ndarray):
if p.size == 0:
vn = p[0]
else:
raise ValueError # or whatever you want to do here"
return mp.sin(vn)

Function that computes rk method/no plotting

import math
import matplotlib
import numpy as np
from numpy import linspace
tmax=10.0
n=2000
G=4
D=-1
m=2
t=np.linspace (0,400,n+1)
phi=10
dphi=delta=phi_dot=np.linspace(0,400,n+1)
def f(delta_dot,t):
return ((G)*(D*delta+m))
def iterate (func,phi,delta,tmax,n):
dt=tmax/(n-1)
t=0.0
for i in range(n):
phi,delta = func (phi,delta,t,dt)
t += dt
return phi
def rk_iter(phi,delta,t,dt):
k1=f(t,phi)
k2=f(t+dt*0.5,phi+k1*0.5*dt)
k3=f(t+dt*0.5,phi*k2*0.5*dt)
k4=f(t*dt,phi*k3*dt)
delta +=dt*(k1+2*k2+2*k3+k4)/6
k1=k2=k3=k4=delta=phi_dot
phi += dt*(k1+2*k2+2*k3+k4)/6
return phi,delta
runge_kutta = lambda delta, phi,tmax,n:iterate(rk_iter,delta,phi,tmax,n)
def plot_result (delta,phi,tmax,n):
dt=tmax/(n-1)
error_rk=[]
r_rk=[]
t=0.0
phi=phi_rk=phi
delta=delta_rk=delta
for i in range(n):
phi_rk,delta_rk=rk_iter(phi_rk,delta_rk,t,dt=tmax/(n-1))
t+=dt
_plot("error.png","Error","time t", "error e",error_rk)
def _plot(title,xlabel,ylabel,rk):
import matplotlib.pyplot as plt
plt.title(title)
plt.ylabel(ylabel)
plt.xlabel(xlabel)
plt.plot(rk,"r--",label="Runge-Kutta")
plt.legend(loc=4)
plt.grid(True)
plt.plot(runge_kutta,t)
print "runge_kutta=", runge_kutta(phi,delta,tmax,n)
print "tmax=",t
I have no idea how to get the function plt.show() to work. What do I have to do to open a plot window?
You haven't defined f; instead, f is being imported from matplotlib by the statement from matplotlib import *:
In [10]: import matplotlib
In [11]: matplotlib.f
Out[11]: Forward: "a"
In [12]: matplotlib.f(1,1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-5843007d7dbe> in <module>()
----> 1 matplotlib.f(1,1)
TypeError: __call__() takes at most 2 arguments (3 given)
You will save yourself many headaches like this in the future if you never use the * form of the import statement in your scripts. For example, instead of from math import *, use one of these two forms:
import math
# Now refer to math.sin, math.pi, etc.
or, explicilty import only the names that you will use:
from math import sin, pi
At no point do you call the plot_result procedure. And even if you called it, you do not fill the rk and error_rk lists. You could simply use the result from the runge_kutta call,...
As commented in the other, duplicate post, you define the system equation as f(y,t) but use it as f(t,y).
There is some confusion in the usage of delta, sometimes it is the integration variable, sometimes the rk4-step update.
In the rk4-step, there are some misplaced multiplications where there should be additions. And the line
k1=k2=k3=k4=delta=phi_dot
is complete nonsense and invalidates the previous computations and makes the rk4-update in the next step meaningless.
Remove the imports of math and linspace, neither is used in the code. Move the aliasing of plt to the top and merge it with the unnecessary import of matplotlib.

Categories