Reputation: 1343
I am using sympy
to carry on some symbolic math manipulations.
Start by creating a Fourier series representation of a rectangular pulse train (duty cycle < 50%), then try to access the multiplying factors, i.e. a_n
and b_n
of the standard Fourier series.
In a nutshell:
import sympy as sy
from sympy import fourier_series, pi, cos, sin
from sympy.abc import t
from sympy.functions.special.delta_functions import Heaviside
T = sy.symbols('T')
s = fourier_series(Heaviside(t) - Heaviside(t-1/4), (t, 0, 1))
s.truncate(3)
1/π*sin(2πt)+1/π*sin(4πt)+1/π*cos(2πt)+0.25
I would then like to access the coefficients of the base functions. To this extent, I thought I should use as_coefficient(expr)
.
This produces the expected results in a simpler case:
g = 1/(pi*T)*sin(2*pi*t)
g.as_coefficient(sin(2*pi*t))
1/πT
However, with the object returned by fourier_series
, this does not seem to work:
a = s.truncate(3)
a.as_coefficient(sin(2*pi*t))
returns nothing (not even a warning or message).
Other methods like s.as_Add()
or s.as_Mul()
return both a full expression where the a_n
is tied to its sin(2*pi*n*t)
term (or b_n
to its dual).
Upvotes: 4
Views: 4984
Reputation: 189
The class sympy.series.fourier.FourierSeries
has methods to provide sympy.series.sequences.sequence
objects with the cosine and sine terms of the series: a0
, an
and bn
.
After computing the series by
import sympy as sym
from sympy import fourier_series
from sympy.abc import t
from sympy.functions.special.delta_functions import Heaviside
s = fourier_series(Heaviside(t) - Heaviside(t-1/4), (t, 0, 1))
The cosine coefficients can be obtained by
s.a0
0.25
and
s.an
For the sine coefficients
s.bn
So in order to produce lists of the s
series coefficients up to a given order, let say 4 that can be done with
def cosine_fourier_coeffs(fourierSeries, order):
### returns a list of fourier series cosine coefficients up to order
out = []
out.append(fourierSeries.a0)
for i in range(1,order):
out.append(fourierSeries.an.coeff(i).subs(t, 0 ) )
return out
def sine_fourier_coeffs(fourierSeries, order):
### returns a list of fourier series sine coefficients up to order
out = []
for i in range(1,order):
out.append(fourierSeries.bn.coeff(i).subs(t, 1/(4* i) ) )
return out
cosine_fourier_coeffs(s, 4), sine_fourier_coeffs(s, 4)
that will return
([0.250000000000000, 1/pi, 0, -1/(3*pi)], [1/pi, 1/pi, 1/(3*pi)])
Upvotes: 4
Reputation:
The method as_coefficient
can't handle a sum of terms like 2*sin(x)+3*cos(x)
: it picks the coefficient only if the given expression (like sin(x)
) can be factored out. So, in order to use it you need to separate the series into chunks with one trig function each. This can be done, but it's easier to change the approach:
s.truncate(None)
to get a generator for the series.The reason this works: at 0, sine is 0 and cosine is 1; at 1/4 of length, cosine is 0 and sine is 1.
from sympy import fourier_series, pi, cos, sin
from sympy.abc import t
from sympy.functions.special.delta_functions import Heaviside
s = fourier_series(Heaviside(t) - Heaviside(t-1/4), (t, 0, 1))
iter = s.truncate(None)
cosine_coeffs = []
sine_coeffs = [0] # there is no sine term for k = 0
for k in range(0, 4):
term = next(iter)
cosine_coeffs.append(term.subs(t, 0))
if k > 0:
sine_coeffs.append(term.subs(t, 1/(4*k)))
Result:
cosine_coeffs = [0.250000000000000, 1/pi, 0, -1/(3*pi)]
sine_coeffs = [0, 1/pi, 1/pi, 1/(3*pi)]
Upvotes: 2