Plotting the output of integrate.quad with an np.linspace array - python

I am trying to plot an integrated function of E with the range of values of E. I cannot figure out how to make the output of the integrate.quad function compatible with the range of E.
This is the code that I have been using
import numpy as np
import scipy.constants as phys
import scipy.integrate as integrate
import math
import matplotlib.pyplot as plt
E = np.linspace(0, 12, 10000)
fermi = 4.5
kT = 0.04
dfdE = np.exp((E-fermi)/(kT))/((np.exp((E-fermi)/(kT)) + 1)**2) * 1/(kT)
t = 1/(1 + np.exp(-2*np.pi * (E-(0-0.5)*3))) + 1/(1 + np.exp(-2*np.pi * (E-(1-0.5)*3)))+ 1/(1 + np.exp(-2*np.pi * (E-(2-0.5)*3)))+ 1/(1 + np.exp(-2*np.pi * (E-(3-0.5)*3)))+ 1/(1 + np.exp(-2*np.pi * (E-(4-0.5)*3)))+ 1/(1 + np.exp(-2*np.pi * (E-(5-0.5)*3)))+ 1/(1 + np.exp(-2*np.pi * (E-(6-0.5)*3))) -2
f = dfdE*t-2
def f_integral(E):
return f
result_f = integrate.quad_vec(f_integral, fermi-1.5, fermi+1.5 )
print(result_f)
plt.plot(E,result_f)
This is the error that is occurring:
Traceback (most recent call last):
File ~\OneDrive\Documents\BSc_Project\Plot.py:29 in <module>
plt.plot(E,result_f)
File ~\anaconda3\lib\site-packages\matplotlib\pyplot.py:2757 in plot
return gca().plot(
File ~\anaconda3\lib\site-packages\matplotlib\axes\_axes.py:1632 in plot
lines = [*self._get_lines(*args, data=data, **kwargs)]
File ~\anaconda3\lib\site-packages\matplotlib\axes\_base.py:312 in __call__
yield from self._plot_args(this, kwargs)
File ~\anaconda3\lib\site-packages\matplotlib\axes\_base.py:498 in _plot_args
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (10000,) and (2,)
Any help would be appreciated.

Since your result_f is a tuple, you need to slice it with [0] before calling plot.
plt.plot(E, result_f[0]) # <- we slice here

Related

Error, trying to plot a graph of solution to a Second Order ODE using Euler Method

I am doing a project, where I want to use Euler's Method to show a solution to this Second Order Different equation
0=y''+y'+9.81y
So I started by changing the second-order into a system of first-order equations
y'=u, u'=f(t,y,u)
With initial condition
y(0)=180, u(0)=0
So I get two equation in the end
y[n + 1] = y[n] + u[n] * (t[n + 1] - t[n]), u[n + 1] = u[n] + f(u[0], y[n], t[0]) * (t[n + 1] - t[n])
This is my code
import numpy as np
import matplotlib.pyplot as plt
def odeEuler(f, y0, u0, t):
y = np.zeros(len(t))
u = np.zeros(len(t))
y[0] = y0
u[0] = u0
for n in range(0, len(t) - 1):
y[n + 1] = y[n] + u[n] * (t[n + 1] - t[n])
u[n + 1] = u[n] + f(u[0], y[n], t[0]) * (t[n + 1] - t[n])
return y, u
t = np.linspace(0, 100)
y0 = 180
u0 = 0
f = lambda u, y, t: -9.81 * y - u
y = odeEuler(f, y0, u0, t)
plt.plot(t, y, 'b.-')
plt.legend(['Euler'])
plt.axis([0, 100, 0, 200])
plt.grid(True)
plt.show()
However, when I run the code, it give me the error
Traceback (most recent call last):
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/Praying this works.py", line 22, in <module>
plt.plot(t, y, 'b.-')
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/pyplot.py", line 3021, in plot
**({"data": data} if data is not None else {}), **kwargs)
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/axes/_axes.py", line 1605, in plot
lines = [*self._get_lines(*args, data=data, **kwargs)]
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 315, in __call__
yield from self._plot_args(this, kwargs)
File "/Users/huangy15/PycharmProjects/Draft/Damped Driven Pendulum/venv/lib/python3.7/site-packages/matplotlib/axes/_base.py", line 501, in _plot_args
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (50,) and (2, 50)
Can anyone help me check if my idea works, and if not, what other approaches I can take? Thanks!
Your odeEuler function is returning two variables: y and u, you need to select just one of them to plot.
Store the output of the function in two different variables will solve the problem:
y, u = odeEuler(f, y0, u0, t)

Fit a curve with a sum using curve_fit

I am having a problem fitting a curve with scipy.
This is the equation I want to fit my data in:
This is the code:
import numpy as np
import os
from mpmath import *
from pandas import read_csv
from scipy.optimize import curve_fit
from matplotlib import pyplot
from sympy import *
M = 0.0129
L = 0.006
PI = np.pi
mp.dps=10
data = np.genfromtxt('Daten.csv',dtype=float,delimiter=',')
x = data[1:,0]
y = data[1:,0]
def objective(x,Mps,B,k,D):
return (M-Mps)*(1-np.exp(-k*x))+ Mps*(-np.exp(-B*x)*np.power(D/(B*L*L),0.5)*np.power(np.tan((B*L*L)/D),0.5)- (8/(PI*PI))*\
nsum(lambda n: np.exp(-(2*n+1)*(2*n+1)*PI*PI*D*x/(4*L*L))/((2*n+1)*(2*n+1)*(1-(2*n+2)*(2*n+2)*(D*PI*PI/(4*B*L*L)))) ,[0,float('inf')]))
def obtainpar(x,y)
popt,_ = curve_fit(objective,x,y)
print '{Mps,B,k,D}=', popt
Then I obtain the following message:
Traceback (most recent call last):
File "C:/Users/gerardo.salazar/Desktop/hector.py", line 29, in <module>
popt,_ = curve_fit(objective,x,y)
File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 763, in curve_fit
res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 388, in leastsq
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 26, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py", line 463, in func_wrapped
return func(xdata, *params) - ydata
File "C:/Users/gerardo.salazar/Desktop/hector.py", line 27, in objective
nsum(lambda n: np.exp(-(2*n+1)*(2*n+1)*PI*PI*D*x/(4*L*L))/((2*n+1)*(2*n+1)*(1-(2*n+2)*(2*n+2)*(D*PI*PI/(4*B*L*L)))) ,[0,float('inf')]))
File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1718, in nsum
return +ctx.adaptive_extrapolation(update, emfun, options)
File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1165, in adaptive_extrapolation
update(partial, xrange(index, index+step))
File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1706, in update
psum = psum + g(ctx.mpf(k))
File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1753, in g
return f(*args)
File "C:\ProgramData\Anaconda3\lib\site-packages\mpmath\calculus\extrapolation.py", line 1808, in g
return f(*args)
File "C:/Users/gerardo.salazar/Desktop/hector.py", line 27, in <lambda>
nsum(lambda n: np.exp(-(2*n+1)*(2*n+1)*PI*PI*D*x/(4*L*L))/((2*n+1)*(2*n+1)*(1-(2*n+2)*(2*n+2)*(D*PI*PI/(4*B*L*L)))) ,[0,float('inf')]))
TypeError: loop of ufunc does not support argument 0 of type mpf which has no callable exp method
I cannot share the data, but it is just a simply (x,y) points, nothing special. Thank you for the help and suggestion how could I make this happens.
As mentioned by #piterbarg there are several problems with mixing numpy and mpmath. My idea was to stay with mpmath and swap to numpy after the calculation of a value.curve_fit, etc. send numpy arrays though, such that I have to take care of the iterable object. Finally, it turns out that negative D and B are a problem. Instead of putting boundaries, which is an option of course, a use the absolute value inside the function. The result can be, hence, negative...but isn't.
Slightly cleaned up and augmented accordingly the code looks like:
import matplotlib.pyplot as plt
import numpy as np
from mpmath import pi as PI
from mpmath import nsum
from mpmath import exp
from mpmath import sqrt
from mpmath import tan
from scipy.optimize import curve_fit
from matplotlib import pyplot
M = 0.0129
L = 0.006
### might be of interest to:
# ~import mpmath
# ~mpmath.dps=10
def objective( x, Mps, b, k, d ):
if isinstance( x, ( list, tuple, np.ndarray ) ):
out = np.fromiter(
( objective( item, Mps, b, k, d ) for item in x ),
np.float
) ## always return np.array
else:
D = abs( d ) ### fails for neg
B = abs( b ) ### fails for neg
dil2 = D / L**2
out = ( M - Mps ) * ( 1 - exp( -k * x ) )
out += Mps * (
-exp( -B * x ) * sqrt( dil2 / B )
* sqrt( tan( B / dil2 ) )
-8 / PI**2
* nsum( lambda n:
exp( -( 2 * n + 1 )**2 * PI**2 * dil2 * x / 4 ) / (
( 2 * n + 1 )**2 * ( 1 - ( 2 * n + 2 )**2
* ( dil2 * PI**2 / ( 4 * B ) ) )
), [ 0, float( 'inf' ) ]
)
)
return out
############ test
xl = np.linspace( -3, 15, 55 )
yl = objective( xl, 0.5, 1, 0.3, 1.2 )
yl *= np.random.normal( loc=1, scale=0.1, size=len( yl ) )
popt, pcov = curve_fit( objective, xl, yl, p0=[ 1, 1, 1, 1 ] )
print( popt )
print( pcov )
### always look at pcov
### shows that fit is basically insenitive to parameter D
xfull = np.linspace( -3, 15, 155 )
yfull = objective( xfull, *popt )
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.plot( xl, yl, ls='', marker='o' )
ax.plot( xfull, yfull )
plt.show()
Note, importing everything via * is usually a bad idea.

ValueError: x and y must have same first dimension, but have shapes (512,) and (256,)

I tried to use numpy and np.array but it fails. It displays that error: ValueError: x and y must have same first dimension, but have shapes (512,) and (256,).
I dont know how to edit that code. Please help.
import math as mt
import matplotlib.pylab as plt
N = 512
t_min = 0 # [s]
t_max = 2 # [s]
frq = 2 # [Hz]
T_p = (t_max-t_min)/N
lst = range(0, N, 1)
t = []
sinus = []
rect = []
pila1 = []
pila2 = []
for i in lst:
t.extend([t_min + lst[i] * T_p])
sinus.extend([mt.sin(2 * mt.pi * frq * t[i])])
if sinus[i] > 0:
rect.extend([True])
else:
rect.extend([False])
pila1.extend([(t[i] % (1 / frq)) * frq])
pila2.extend([abs((t[i] % (1 / frq)) * frq - 0.5) * 2])
plt.figure(1)
plt.title('Plot')
plt.plot(t, sinus)
plt.plot(t, rect)
plt.plot(t, pila1)
plt.plot(t, pila2)
plt.xlabel('t')
plt.grid(True)
plt.show()
there is full error:
Traceback (most recent call last):
File "venv/zadanieA.py", line 32, in <module>
plt.plot(t, pila1)
File "venv\lib\site-packages\matplotlib\pyplot.py", line 2761, in plot
return gca().plot(
File "venv\lib\site-packages\matplotlib\axes\_axes.py", line 1646, in plot
lines = [*self._get_lines(*args, data=data, **kwargs)]
File "venv\lib\site-packages\matplotlib\axes\_base.py", line 216, in __call__
yield from self._plot_args(this, kwargs)
File "venv\lib\site-packages\matplotlib\axes\_base.py", line 342, in _plot_args
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (512,) and (256,)
Well, your t list contains as many values as the original lst, as you add one item in every iteration of the loop - that gives 512 items. However, your pila1 and pila2 lists are extended only for positive values of sinus[i], ie. half as many - so they contain only 256 items. To fix it, add items to these list as well (oh, and please do not use extend where append suffices).
for i in lst:
t.append(t_min + lst[i] * T_p)
sinus.append(mt.sin(2 * mt.pi * frq * t[i]))
if sinus[i] > 0:
rect.append(True)
pila1.append(0) # or whatever value you deem "neutral"
pila2.append(0)
else:
rect.append(False)
pila1.append((t[i] % (1 / frq)) * frq)
pila2.append(abs((t[i] % (1 / frq)) * frq - 0.5) * 2)

Minimizing a function using python for data fitting

I have a function as the following
q = 1 / sqrt( ((1+z)**2 * (1+0.01*o_m*z) - z*(2+z)*(1-o_m)) )
h = 5 * log10( (1+z)*q ) + 43.1601
I have experimental answers of above equation and once I must to put some data into above function and solve equation below
chi=(q_exp-q_theo)**2/err**2 # this function is a sigma, sigma chi from z=0 to z=1.4 (in the data file)
z, err and q_exp are in the data file(2.txt). Now I have to choose a range for o_m (0.2 to 0.4) and find in what o_m, the chi function will be minimized.
my code is:
from math import *
from scipy.integrate import quad
min = None
l = None
a = None
b = None
c = 0
def ant(z,om,od):
return 1/sqrt( (1+z)**2 * (1+0.01*o_m*z) - z*(2+z)*o_d )
for o_m in range(20,40,1):
o_d=1-0.01*o_m
with open('2.txt') as fp:
for line in fp:
n = list( map(float, line.split()) )
q = quad(ant,n[0],n[1],args=(o_m,o_d))[0]
h = 5.0 * log10( (1+n[1])*q ) + 43.1601
chi = (n[2]-h)**2 / n[3]**2
c = c + chi
if min is None or min>c:
min = c
l = o_m
print('chi=',q,'o_m=',0.01*l)
n[1],n[2],n[3],n[4] are z1, z2, q_exp and err, respectively in the data file. and z1 and z2 are the integration range.
I need your help and I appreciate your time and your attention.
Please do not rate a negative value. I need your answers.
Here is my understanding of the problem.
First I generate some data by the following code
import numpy as np
from scipy.integrate import quad
from random import random
def boxmuller(x0,sigma):
u1=random()
u2=random()
ll=np.sqrt(-2*np.log(u1))
z0=ll*np.cos(2*np.pi*u2)
z1=ll*np.cos(2*np.pi*u2)
return sigma*z0+x0, sigma*z1+x0
def q_func(z, oM, oD):
den= np.sqrt( (1.0 + z)**2 * (1+0.01 * oM * z) - z * (2+z) * (1-oD) )
return 1.0/den
def h_func(z,q):
out = 5 * np.log10( (1.0 + z) * q ) + .25#43.1601
return out
def q_Int(z1,z2,oM,oD):
out=quad(q_func, z1,z2,args=(oM,oD))
return out
ooMM=0.3
ooDD=1.0-ooMM
dataList=[]
for z in np.linspace(.3,20,60):
z1=.1+.1*z*.01*z**2
z2=z1+3.0+.08+z**2
q=q_Int(z1,z2,ooMM,ooDD)[0]
h=h_func(z,q)
sigma=np.fabs(.01*h)
h=boxmuller(h,sigma)[0]
dataList+=[[z,z1,z2,h,sigma]]
dataList=np.array(dataList)
np.savetxt("data.txt",dataList)
which I would then fit in the following way
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as plt
import numpy as np
from scipy.integrate import quad
from scipy.optimize import leastsq
def q_func(z, oM, oD):
den= np.sqrt( (1.0 + z)**2 * (1+0.01 * oM * z) - z * (2+z) * (1-oD) )
return 1.0/den
def h_func(z,q):
out = 5 * np.log10( (1.0 + z) * q ) + .25#43.1601
return out
def q_Int(z1,z2,oM,oD):
out=quad(q_func, z1,z2,args=(oM,oD))
return out
def residuals(parameters,data):
om,od=parameters
zList=data[:,0]
yList=data[:,3]
errList=data[:,4]
qList=np.fromiter( (q_Int(z1,z2, om,od)[0] for z1,z2 in data[ :,[1,2] ]), np.float)
hList=np.fromiter( (h_func(z,q) for z,q in zip(zList,qList)), np.float)
diffList=np.fromiter( ( (y-h)/e for y,h,e in zip(yList,hList,errList) ), np.float)
return diffList
dataList=np.loadtxt("data.txt")
###fitting
startGuess=[.4,.8]
bestFitValues, cov,info,mesg, ier = leastsq(residuals, startGuess , args=( dataList,),full_output=1)
print bestFitValues,cov
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(dataList[:,0],dataList[:,3],marker='x')
###fitresult
fqList=[q_Int(z1,z2,bestFitValues[0], bestFitValues[1])[0] for z1,z2 in zip(dataList[:,1],dataList[:,2])]
fhList=[h_func(z,q) for z,q in zip(dataList[:,0],fqList)]
ax.plot(dataList[:,0],fhList,marker='+')
plt.show()
giving output
>>[ 0.31703574 0.69572673]
>>[[ 1.38135263e-03 -2.06088258e-04]
>> [ -2.06088258e-04 7.33485166e-05]]
and the graph
Note that for leastsq the covariance matrix is in reduced form and needs to be rescaled.
Unconcsiosely, this question overlap my other question. The correct answer is:
from math import *
import numpy as np
from scipy.integrate import quad
min=l=a=b=chi=None
c=0
z,mo,err=np.genfromtxt('Union2.1_z_dm_err.txt',unpack=True)
def ant(z,o_m): #0.01*o_m is steps of o_m
return 1/sqrt(((1+z)**2*(1+0.01*o_m*z)-z*(2+z)*(1-0.01*o_m)))
for o_m in range(20,40):
c=0
for i in range(len(z)):
q=quad(ant,0,z[i],args=(o_m,))[0] #Integration o to z
h=5*log10((1+z[i])*(299000/70)*q)+25 #function of dL
chi=(mo[i]-h)**2/err[i]**2 #chi^2 test function
c=c+chi
l=o_m
print('chi^2=',c,'Om=',0.01*l,'OD=',1-0.01*l)

ValueError: object too deep for desired array

""" ___ """
from scipy.optimize import root
import numpy as np
LENGTH = 3
def process(x):
return x[0, 0] + x[0, 1] * 5
def draw(process, length):
""" """
X = np.matrix(np.random.normal(0, 10, (length, 2)))
y = np.matrix([process(x) for x in X])
y += np.random.normal(3, 1, len(y))
return y.T, X.T
def maximum_likelyhood(y, X):
def objective(b):
return (X.T * (y - X * b.T))
x0 = np.matrix([0, 0])
res = root(objective, x0=x0)
return res.x
y, X = draw(process, LENGTH)
X = X.transpose()
b = np.matrix([[0], [1]])
print maximum_likelyhood(y, X)
produces a
Traceback (most recent call last):
File "ml.py", line 33, in <module>
maximum_likelyhood(y, X)
File "ml.py", line 26, in maximum_likelyhood
res = root(objective, x0=x0)
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/_root.py", line 168, in root
sol = _root_hybr(fun, x0, args=args, jac=jac, **options)
File "/usr/local/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 193, in _root_hybr
ml, mu, epsfcn, factor, diag)
ValueError: object too deep for desired array
I can't even gasp what the problem is is it in the b which goes into the objective
function? or is it in its output?
The problem is that fsolve and root do not accept matrixes as return value of the objective function.
For example this is a solution of above problem:
def maximum_likelyhood(y, X):
def objective(b):
b = np.matrix(b).T
return np.transpose(np.array((X.T * (y - X * b))))[0]
x0 = (1, 1)
res = root(objective, x0=x0)
return res.x

Categories