Integrate square function - python

I need to make the fourier series of an square function.
To get this a have a function y = square(t)
i need to make the integral of (2/p)*(square(t)*cos((2pi/p)*t)) from 0 to a variable I type for example p = 10 but i cant make this integral because every time i try to do this with scipy i get an error with the square function.
from scipy.signal import *
from scipy.integrate import quad
from numpy import *
p = 10
na = arange(0,10,1)
def integrand(t, a, b):
return square(t)*cos(b*((2*pi)/a)*t)
i,err = quad(integrand,0,p, args=(p,na))
y = i
quadpack.error: Supplied function does not return a valid float.

quad returns 2 parameters, the integral and the absolute value of the error, you just have to unpack it.
from scipy.signal import *
from scipy.integrate import quad
from numpy import *
p = 10
def integrand(t, a):
return square(t)*cos(((2*pi)/a)*t)
i, err = quad(integrand,0,p, args=(p,))
y = (2/p)*i
update:
from scipy.signal import *
from scipy.integrate import quad
from numpy import *
p = 10
na = arange(0,10,1)
y = []
def integrand(t, a, b):
return square(t)*cos(b*((2*pi)/a)*t)
for e in na:
i,err = quad(integrand,0,p, args=(p, e))
y.append(i)
print(y)

Related

How to simply integral a function written in Sympy

Through using the ways and obtaining help from Stackoverflow users, I could find half of the solution and I need to complete it.
Through using Sympy I could produce my function parametrically and it became 100 different items similar to 0.03149536*exp(-4.56*s)*sin(2.33*s) 0.03446408*exp(-4.56*s)*sin(2.33*s). By using f = lambdify(s,f) I converted it to a NumPy function and I needed to do integral of in the different sthat I already have. The upper limit of the integral is a constant value and the lower limit must be done through afor loop`.
When I try to do, I get some error which I post below. The code that I wrote is below, but for being a reproducible question I have to put a generated data. TypeError: cannot determine truth value of Relational
from sympy import exp, sin, symbols, integrate, lambdify
import pandas as pd
import matplotlib.pyplot as plt
from scipy import integrate
import numpy as np
S = np.linspace(0,1000,100)
C = np.linspace(0,1,100)
s, t = symbols('s t')
lanr = -4.56
lani = -2.33
ID = S[-1]
result=[]
f = C * exp(lanr * s) * sin (lani * s)
f = lambdify(s,f)
#vff = np.vectorize(f)
for i in (S):
I = integrate.quad(f,s,(i,ID))
result.append(I)
print(result)
EDIT
I tried to do the same without havingSympy by using just Scipy and wrote the code below and again I could not solve the problem.
from scipy.integrate import quad
import numpy as np
lanr = -6.55
lani = -4.22
def integrand(c,s):
return c * np.exp(lanr * s) * np.sin (lani * s)
def self_integrate(c,s):
return quad(integrand,s,1003,1200)
import pandas as pd
file = pd.read_csv('1-100.csv',sep="\s+",header=None)
s = np.linspace(0,1000,100)
c = np.linspace(0,1,100)
ID = s[-1]
for i in s:
I = self_integrate(integrand,c,s)
print(I)
and I got this TypeError: self_integrate() takes 2 positional arguments but 3 were given
Assuming you want to integrate over s, and use c as a fixed parameter (for a given quad call), define:
In [198]: lanr = 1
...: lani = 2
...: def integrand(s, c):
...: return c * np.exp(lanr * s) * np.sin (lani * s)
...:
test it by itself:
In [199]: integrand(10,1.23)
Out[199]: 24734.0175253505
and test it in quad:
In [200]: quad(integrand, 0, 10, args=(1.23,))
Out[200]: (524.9015616747192, 3.381048596651226e-08)
doing the same for a range of c values:
In [201]: alist = []
...: for c in range(0,10):
...: x,y = quad(integrand, 0, 10, args=(c,))
...: alist.append(x)
...:
In [202]: alist
Out[202]:
[0.0,
426.74923713391905,
853.4984742678381,
1280.2477114017531,
1706.9969485356762,
2133.7461856695877,
2560.4954228035062,
2987.244659937424,
3413.9938970713524,
3840.743134205258]
From the quad docs:
quad(func, a, b, args=(),...)
func : {function, scipy.LowLevelCallable}
A Python function or method to integrate. If `func` takes many
arguments, it is integrated along the axis corresponding to the
first argument.
and an example:
>>> f = lambda x,a : a*x
>>> y, err = integrate.quad(f, 0, 1, args=(1,))
The docs are a bit long, but the basics should be straight forward.
I was tempted to say you were stuck on the sympy calling pattern, but the second argument for that is either the integration symbol, or a tuple.
>>> integrate(log(x), (x, 1, a))
a*log(a) - a + 1
So I'm puzzled as to why you were stuck on using
quad(integrand,s,1003,1200)
The s, whether a sympy variable or a linspace array does not make sense.

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()

calling args in a loop-function

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.

indexing in lambda function to optimize multiple variables of a sum

I want to solve an optimization problem as proposed in this thread. Now, I not only want to solve for the x[1]...x[n], but also for the variable y. It looks like something is wrong with the indexing.
from sympy import Sum, symbols, Indexed, lambdify
from scipy.optimize import minimize
import numpy as np
def _eqn(y, variables, periods, sign=-1.0):
x, i = symbols("x i")
n = periods-1
s = Sum(Indexed('x', i)/(1+0.06)**i, (i, 1, n))
f = lambdify(x, s, modules=['sympy'])
return float(sign*(y + f(variables)))
z = 3
results = minimize(lambda xy: _eqn(xy[0], xy[1:z], z),np.zeros(z))
print(results.x)
From the error message it seems there is an issue in your indexing. The summation runs from 1 to n but by default indexing of list type objects in Python goes from 0 to n-1. If I change this in your code it seems to work. Check it out.
import sympy as sp
from scipy.optimize import minimize
import numpy as np
sp.init_printing()
def _eqn(y, variables, periods, sign=-1.0):
x, i = sp.symbols("x i")
n = periods-1
s = sp.Sum(sp.Indexed('x', i)/(1+0.06)**(i+1), (i, 0, n-1)).doit()
f = sp.lambdify(x, s, modules=['sympy'])
return float(sign*(y + f(variables)))
z = 3
results = minimize(lambda xy: _eqn(xy[0], xy[1:z], z),np.zeros(z))
print(results.x)
If all you need is variable number of arguments for minimization then does the following code work for you?
from sympy import var
from scipy.optimize import minimize
import numpy as np
def _eqn(y, variables, periods, sign=-1.0):
f = 0
for i,x in enumerate(variables):
f += x/(1+0.06)**(i+1)
return float(sign*(y + f))
z = 3
results = minimize(lambda xy: _eqn(xy[0], xy[1:z], z),np.zeros(z))
print(results.x)

Constructing SymPy rational functions from Scipy filter design

Why aren't num_den_to_sympy(b, a) and sy.simplify(sy.expand(tf)) the same? The expanded version contains an additional s ** 4 and I don't know where it came from.
import numpy as np
import sympy as sy
from scipy.signal import *
from IPython.display import display
sy.init_printing()
def num_den_to_sympy(num, den, symplify=True):
s = sy.Symbol('s')
G = sy.Poly(num, s) / sy.Poly(den, s)
return sy.simplify(G) if symplify else G
b, a = iirdesign(wp=2 * np.pi * 2.5e3, ws=2 * np.pi * 4.5e3, gpass=1, gstop=26,
analog=True, ftype='cheby1', output='ba')
tf = 1
for sos in tf2sos(b, a):
tf *= num_den_to_sympy(sos[0:3], sos[3:6])
display(num_den_to_sympy(b, a))
display(sy.simplify(sy.expand(tf)))
The issue is the inconsistent order of coefficients. SciPy orders them from lowest to highest degrees. SymPy's Poly constructor expects them to be from highest to lowest: for example, Poly([1, 0, 0], s) is s**2
If you reverse the coefficients when using Poly, the two results are identical.
G = sy.Poly(num[::-1], s) / sy.Poly(den[::-1], s)

Categories