calling args in a loop-function - python

for MCMC I use emcee package this tutorial. Instead of the equation of thispart which is fractional and so easy I use this form, I mean I use matrix form(not its code) and wrote the following code.
for more explanation of my code:
def new_calculation(n) is the equation for each component of matrix and def log_likelihood(theta,hh): is the mentioned matrix.
the problem is, I need args to use in soln = minimize(nll, initial, args=(hh)) and def log_probability(theta,hh):
I use hh as args but the Python says the hh is not defined. the problem may be for definition of arguments and function. I do not know how to fix it.
import numpy as np
import emcee
import matplotlib.pyplot as plt
from math import *
import numpy as np
from scipy.integrate import quad
from scipy.integrate import odeint
xx=np.array([0.01,0.012,0.014,0.016])
yy=np.array([32.95388698,33.87900347,33.84214074,34.11856704])
Cov=[[137,168],[28155,-2217]]
rc=0.09
c=0.7
H01 = 70
O_m1 = 0.28
z0=0
M1=10
np.random.seed(123)
def ant(z,O_m,O_D):
return 1/sqrt(((1+z)**2)*(1+O_m*z))
def new_calculation(n):
O_D=1-O_m-(1/(2*rc*yyn))
q=quad(ant,0,xx[n],args=(O_m,O_D))[0]
h=log10((1+xx[n])*q)
fn=(yy[n]-M-h)
return fn
def log_likelihood(theta,hh):
H0, O_m,M= theta
f_list = []
for i in range(2): # the value '2' reflects matrix size
f_list.append(new_calculation(i))
rdag=[f_list]
rmat=[[f] for f in f_list]
hh=np.linalg.det(np.dot(rdag,Cov),rmat)*0.000001
return hh
from scipy.optimize import minimize
np.random.seed(42)
nll = lambda *args: -log_likelihood(*args)
initial = np.array([H01, O_m1,M1]) + 0.1*np.random.randn(3)
soln = minimize(nll, initial, args=(hh))
H0_ml, O_m0_ml = soln.x
def log_prior(theta):
H0, O_D = theta
if 65 < H0 < 75 and 0.22 < O_m < 0.32 and 0 < M < 12:
return 0.0
return -np.inf
def log_probability(theta, mm,zz,hh):
lp = log_prior(theta)
if not np.isfinite(lp):
return -np.inf
return lp + log_likelihood(theta, mm,zz,hh)
y0=H0
pos = soln.x + 1e-4*np.random.randn(200, 3)
nwalkers, ndim = pos.shape
sampler = emcee.EnsembleSampler(nwalkers, ndim, log_probability, args=(rdag, rmat))
sampler.run_mcmc(pos, 500);
fig = plt.figure(2,figsize=(10, 10))
fig.clf()
for j in range(ndim):
ax = fig.add_subplot(ndim,1,j+1)
ax.plot(np.array([sampler.chain[:,i,j] for i in range(nwalkers)]),"k", alpha = 0.3)
ax.set_ylabel(("H0", "O_m")[j], fontsize = 15)
plt.xlabel('Steps', fontsize = 15)
fig.show()
I appreciate your help and your attention.

Related

Big numbers problem while "odeint" numerical integration

I'm having some computational problems with the following code:
import numpy as np
from numpy import arange
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from scipy.integrate import quad
import matplotlib as mpl
mpl.rcParams['agg.path.chunksize'] = 10000
# parameters
Ms = 100 #GeV Singlet Mass
Me = 0.511e-3 #Gev Electron Mass
Mp = 1.22e19 #GeV Planck Mass
gs = 106.75 # Entropy dof
H0 = 2.133*(0.7)*1e-42 # GeV Hubble parameter (unused)
gx = 2 # WIMP's dof
g = 100 # total dof
sigmav=[1e-25,1e-11,1e-12] # cross section's order of magnitude
xi=1e-2
xe=1e2
npts=int(1e5)
x = np.linspace(xi, xe, npts)
def fMB(p,x,m):
return np.exp(-x*np.sqrt(1+p*p/(m*m)))*p*p
def neq(x,m):
return (gx/(2*np.pi*np.pi))*quad(fMB, 0, np.inf, args=(x,m))[0]
def neq_nr(x,m):
return 2*(m**2/(2*np.pi*x))**(3/2)*np.exp(-x)
def stot(x):
return (2*np.pi*np.pi/45)*gs*Ms*Ms*Ms/(x*x*x)
def Yeq(x,m):
return neq(x,m)/stot(x)
Yeq2=np.vectorize(Yeq)
def Yeq_nr(x):
return 0.145*(gx/gs)*(x)**(3/2)*np.exp(-x)
def Yeq_r(x):
return 0.278*(3*gx/4)/gs
def Ytot(x):
if np.any(x<=1):
return Yeq_r(x)
else:
return Yeq_nr(x)
def eqd(yl,x,Ms,σv):
'''
Ms [GeV] : Singlet Mass
σv: [1/GeV^2] : ⟨σv⟩
'''
H = 1.67*g**(1/2)*Ms**2/Mp
dyl = -neq(x,Ms)*σv*(yl**2-Yeq(x,Ms)**2)/(x**(-2)*H*x*Yeq(x,Ms)) #occorre ancora dividere per Yeq_nr(x) oppure Yeq(x)
return dyl
y0=1e-15
yl0 = odeint( eqd, y0, x,args=(Ms,sigmav[0]), full_output=True)
yl1 = odeint( eqd, y0, x,args=(Ms,sigmav[1]), full_output=True)
yl2 = odeint( eqd, y0, x,args=(Ms,sigmav[2]), full_output=True)
fig = plt.figure(figsize=(11,8))
plt.loglog(x,yl0[0], label = r'$\langle σ v\rangle = %s {\rm GeV}^{-2}$'%(sigmav[0]))
plt.loglog(x,yl1[0], label = r'$\langle σ v\rangle = %s {\rm GeV}^{-2}$'%(sigmav[1]))
plt.loglog(x,yl2[0], label = r'$\langle σ v\rangle = %s {\rm GeV}^{-2}$'%(sigmav[2]))
plt.loglog(x,Yeq_nr(x), '--', label = '$Y_{EQ}^{nr}$')
plt.loglog(x,Yeq2(x,Ms), '--', label = '$Y_{EQ}$')
plt.ylim(ymax=0.1,ymin=y0)
plt.xlim(xmax=xe,xmin=xi)
plt.xlabel('$x = m_χ/T$', size= 15)
plt.ylabel('$Y$', size= 15)
plt.title('$m_χ = %s$ GeV'%(Ms), size= 15)
plt.legend(loc='best',fontsize=12)
plt.grid(True)
plt.savefig('abundance.jpg',bbox_inches='tight', dpi=150)
In particular, as soon as I use little values of sigmav (ranging from 10^-12 to 10^-25) the solution is well displayed, but making use of bigger values (starting from 10^-11) I obtain problems and I guess is a order of magnitudes problem, but I don't know how to handle it!
Thanks to everyone!
Edit 1:
I'm uploading a plot making use of three different values of sigmav and as you may see the bigger one (1e-10) is showing (I guess) precision problems plot_1

Distribution plot with wrong total value

To create
I have made a distribution plot with code below:
from numpy import *
import numpy as np
import matplotlib.pyplot as plt
sigma = 4.1
x = np.linspace(-6*sigma, 6*sigma, 200)
def distr(n):
def g(x):
return (1/(sigma*sqrt(2*pi)))*exp(-0.5*(x/sigma)**2)
FxSum = 0
a = list()
for i in range(n):
# divide into 200 parts and sum one by one
numb = g(-6*sigma + (12*sigma*i)/n)
FxSum += numb
a.append(FxSum)
return a
plt.plot(x, distr(len(x)))
plt.show()
This is, of course, a way of getting the result without using hist(), cdf() or any other options from Python libraries.
Why the total sum is not 1? It shouldn't depend from (for example) sigma.
Almost right, but in order to integrate you have to multiply the function value g(x) times your tiny interval dx (12*sigma/200). That's the area you sum up:
from numpy import *
import numpy as np
import matplotlib.pyplot as plt
sigma = 4.1
x = np.linspace(-6*sigma, 6*sigma, 200)
def distr(n):
def g(x):
return (1/(sigma*sqrt(2*pi)))*exp(-0.5*(x/sigma)**2)
FxSum = 0
a = list()
for i in range(n):
# divide into 200 parts and sum one by one
numb = g(-6*sigma + (12*sigma*i)/n) * (12*sigma/200)
FxSum += numb
a.append(FxSum)
return a
plt.plot(x, distr(len(x)))
plt.show()

Solving system of ODE's using python and graphing (Chua's circuit)

I'm trying to model Chau's Circuit in Python using matplotlib and scipy, which involves solving a system of ordinary differential equations.
This has been done in matlab, and I simply wanted to attempt the problem in python. The matlab code linked is a little confusing; the code on the left doesn't appear to have much relevance to solving the system of ode's that describe Chua's Circuit (page 3, equations (2)(3) and (4)), whilst the code on the right goes beyond that to modelling the circuit component by component.
I'm not familiar with scipy's odeint function so I used some of the examples from the scipy cookbook for guidance.
Can anyone help me troubleshoot my system; why do I get a graph looking like this:
As opposed to one looking like this?
My code is attached below:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
def fV_1(V_1, G_a, G_b, V_b):
if V_1 < -V_b:
fV_1 = G_b*V_1+(G_b-G_a)*V_b
elif -V_b <= V_1 and V_1 <=V_b:
fV_1 = G_a*V_1
elif V_1 > V_b:
fV_1 = G_b*V_1+(G_a-G_b)*V_b
else:
print "Error!"
return fV_1
def ChuaDerivatives(state,t):
#unpack the state vector
V_1 = state[0]
V_2 = state[1]
I_3 = state[2]
#definition of constant parameters
L = 0.018 #H, or 18 mH
C_1 = 0.00000001 #F, or 10 nF
C_2 = 0.0000001 #F, or 100 nF
G_a = -0.000757576 #S, or -757.576 uS
G_b = -0.000409091 #S, or -409.091 uS
V_b = 1 #V (E)
G = 0.000550 #S, or 550 uS VARIABLE
#compute state derivatives
dV_1dt = (G/C_1)*(V_2-V_1)-(1/C_1)*fV_1(V_1, G_a, G_b, V_b)
dV_2dt = -(G/C_2)*(V_2-V_1)+(1/C_2)*I_3
dI_3dt = -(1/L)*V_2
#return state derivatives
return dV_1dt, dV_2dt, dI_3dt
#set up time series
state0 = [0.1, 0.1, 0.0001]
t = np.arange(0.0, 53.0, 0.1)
#populate state information
state = odeint(ChuaDerivatives, state0, t)
# do some fancy 3D plotting
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(state[:,0],state[:,1],state[:,2])
ax.set_xlabel('V_1')
ax.set_ylabel('V_2')
ax.set_zlabel('I_3')
plt.show()
So I managed to work it out for myself after some fiddling; I was interpreting the odeint function wrong; more careful reading of the docstring and starting from scratch to stop me following a difficult method solved it. Code below:
import numpy as np
import scipy.integrate as integrate
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
#define universal variables
c0 = 15.6
c1 = 1.0
c2 = 28.0
m0 = -1.143
m1 = -0.714
#just a little extra, quite unimportant
def f(x):
f = m1*x+(m0-m1)/2.0*(abs(x+1.0)-abs(x-1.0))
return f
#the actual function calculating
def dH_dt(H, t=0):
return np.array([c0*(H[1]-H[0]-f(H[0])),
c1*(H[0]-H[1]+H[2]),
-c2*H[1]])
#computational time steps
t = np.linspace(0, 30, 1000)
#x, y, and z initial conditions
H0 = [0.7, 0.0, 0.0]
H, infodict = integrate.odeint(dH_dt, H0, t, full_output=True)
print infodict['message']
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(H[:,0], H[:,1], H[:,2])
plt.show()
Which gives me this:

Loop and bifurcation diagram

I'm writing a script which plots the bifurcation diagram of a damped pendulum with a small direct forcing.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
epsi = 0.01
# Declare the model
f_dir = np.arange(0,1.3,0.01)
A_s = np.zeros(len(f_dir))
i = 0
for f in f_dir:
def myModel(y, t):
dy0 = y[1]
dy1 = -epsi*y[1]-np.sin(y[0]) - f*np.cos((1.01)*t)*np.cos(y[0])
return [dy0, dy1]
time = np.arange(0.0, 2000,0.01)
yinit = np.array([np.pi/2, 0])
y = odeint(myModel, yinit, time)
A_s.insert(i,np.abs(np.max(y[-600:-1,0])- np.min(y[-600:-1,0])))
i += 1
plt.plot(f_dir,A_s,'*')
plt.xlabel(r'$f_s$')
plt.ylabel(r'$A_s$')
plt.hold
plt.show()
The problem is that I am not inserting anything into A_s, and I do not know why because the variable i is increased at each step of the loop.
It's a little hard to follow your code, but this is probably closer to what you want. You only need to define your model once, even if f is a variable argument: you can pass such arguments to odeint in the args tuple and they get handed on to the model function.
Also note that NumPy arrays don't have an insert method.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
epsi = 0.01
# Declare the model
f_dir = np.arange(0,1.3,0.01)
A_s = np.zeros(len(f_dir))
def myModel(y, t, f):
dy0 = y[1]
dy1 = -epsi*y[1]-np.sin(y[0]) - f*np.cos((1.01)*t)*np.cos(y[0])
return [dy0, dy1]
i = 0
for f in f_dir:
time = np.arange(0.0, 2000,0.01)
yinit = np.array([np.pi/2, 0])
y = odeint(myModel, yinit, time, args=(f,))
A_s[i] = np.abs(np.max(y[-600:-1,0])- np.min(y[-600:-1,0]))
i += 1
plt.plot(f_dir,A_s,'*')
plt.xlabel(r'$f_s$')
plt.ylabel(r'$A_s$')
plt.hold
plt.show()
You defined the myModel function, but it's not actually being called anywhere - it's just referenced from within the function itself.

Why does scipy.optimize.curve_fit give an error?

I have been trying to make a function that solves a set of ordinary differential equations and then fit it to experimental data using the the scipy.optimize.curve_fit function, but I get an error message containing:
"ValueError: object too deep for desired array
odepack.error: Result from function call is not a proper array of floats."
Any help would be much appreciated.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from pylab import *
from scipy.optimize import curve_fit
kB = 8.6173324e-5 #eV/K
P_H2O = 0.05 # bar
H_H2O = -0.8 #eV
S_H2O = -0.0016
def K_H2O(T):
return np.exp(-H_H2O/(kB*T))*np.exp(S_H2O/(kB))
def FracA(T):
return K_H2O(T)*P_H2O / (1+K_H2O(T)*P_H2O)
def FracB(T):
return 1-FracA(T)
EA1_A = 0.725 # eV (from experimental data)
def k1_A(A1_A,T):
return A1_A*np.exp(-EA1_A/(kB*T))
A1_B = 5.e3 #
EA1_B = 0.8 #eV
def k1_B(T):
return A1_B*np.exp(-EA1_B/(kB*T))
A2_B = 8.e3 #
EA2_B = 1.0 #eV
def k2_B(T):
return A2_B*np.exp(-EA2_B/(kB*T))
# initial conditions
P_NO0 = 500.e-6 # initial NO
P_NH30 = 530.e-6 # initial NH3
y0 = [P_NO0, P_NH30] # initial condition vector
t = np.linspace(0, 30., 1000) # time grid
def conv(T,A1_A):
def f(y, t):
P_NOi = y[0]
P_NH3i = y[1]
# the differential equations
if y[0] and y[1] > 0:
f0 = -k1_A(A1_A,T)*FracA(T)*P_NOi -k1_B(T)*FracB(T)*P_NOi*P_NH3i**(-0.25)
else:
f0 = 0
if y[0] and y[1] > 0:
f1 = -k1_A(A1_A,T)*FracA(T)*P_NOi -k1_B(T)*FracB(T)*P_NOi*P_NH3i**(-0.25)-k2_B(T)*P_NH3i
else:
f1 = 0
return [f0, f1]
# solve the DEs
soln = odeint(f, y0, t)
P_NO = soln[:, 0]
P_NH3 = soln[:, 1]
NO_conv = 1-P_NO[-1]/P_NO0
return NO_conv
x_real = np.array([433.1,443.1,453.2,463.1,473.1,483.7,494.2,503.5,523.9,553.7,573.6,623.4,673.4,723.3,773.4,823.2])
y_real =np.array([0.064305859, 0.098333053, 0.151494329, 0.217225336, 0.296164608, 0.397472394, 0.508515308, 0.612339428, 0.793549257, 0.892454094, 0.895511489, 0.861625527, 0.949118344, 0.940025727, 0.852439418, 0.727332885])
popt, pcov = curve_fit(conv, x_real, y_real)

Categories