0

I have the following code which is part of a practice I'm working on: Here is a function that obtains 2*N+1 coefficients of the Fourier series for the input function "ft" written in terms of sym.Heaviside(t), the goal is to get from this function only the numerical values so it is possible to perform operations with the obtained Power Spectral Density (PSD):

def ck_power(ft,f,N=5):
c_k_coeff=f*sym.integrate(ft*sym.exp(-2*j*np.pi*t*k*f),(t,-1/(2*f),1/(2*f)))
#C_k_coeff=sym.lambdify(k,c_k_coeff,modules=['numpy'])
#PSD=[abs((c_k_coeff(i)))**2 for i in range(-N,N+1)]
##PSD=[(c_k_coeff.subs(k,i))*(c_k_coeff.subs(k,-i)) for i in range(-N,N+1)]
### "worked" but keeps the same behavior. PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
PSD=[sym.N(abs(i.subs({u(0):0.5})).evalf(3)) for i in PSD]
positive_PSD=PSD[len(PSD)//2:]
# because the k=0 c_k isn't twice in the k axis apporting power:
positive_PSD[1:]=[2*i for i in positive_PSD[1:]]
PSD=np.array(PSD)
positive_PSD=np.array(positive_PSD)
return PSD,positive_PSD

The problem is that when I use the function with the code below the figures I'm still having a weird piecewise function as the output (especially with the sawtooth wave)

The other functions apparently doesn't have the same problem The other functions don't have the same problem

But the sawtooth shows directly the piecewise output But the sawtooth shows directly the piecewise output

these are the output expressions for k=0: description

#vertical
type_hash=("Frequency","Power")
frequency_hash=("100KHz","1MHz","100MHz")
frequency=(100e+3,1e+6,100e+6)
waveform_hash=("Pulsetrain","Sawtooth","Triangle")
#horizontal
armonic=list(range(6))

signal={
    "Pulsetrain":my.pulsetrain,
    "Sawtooth":my.sawtooth,
    "Triangle":my.triangle
}

t1={"waveform":[],"frequency":[],"type\\armonic":[]}
for i in armonic:
    t1[str(i)]=[]
(A,D,Aoff,toff)=(1,0.5,0,0)
for iwav in waveform_hash:
    for ifreq in range(len(frequency)):
        ftemp=frequency[ifreq]
        for itype in range(len(type_hash)):
            f_now=signal[iwav](A,1/ftemp,D,Aoff,toff)
            PSD,pPSD=my.ck_power(f_now,ftemp,N=5) #<<--right here is where the functions is called
            for i in armonic:
                if not itype:
                    t1[str(i)].append(f"{ftemp*i:.2e}")
                else:
                    t1[str(i)].append(pPSD[i])# add here Power

            t1["type\\armonic"].append(type_hash[itype])
            t1["frequency"].append(frequency_hash[ifreq])
            t1["waveform"].append(iwav)
d1=pd.DataFrame(t1)
d1

these are my imports:

import numpy as np
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
from scipy import signal
import sympy as sym
import sigplot as my
import pandas as pd

Lastly, this is part of my sigplot.py file

import numpy as np
import matplotlib.pyplot as plt
from scipy.io.wavfile import read
from scipy import signal
import sympy as sym
from sympy import Heaviside as u
from IPython.display import display, Math
import pandas as pd

t=sym.symbols('t')
k=sym.symbols('k', integer=True)
j=sym.I

#Fourier
def ck(ft,T):
    c_k=1/T*sym.integrate(ft*sym.exp(-j*k*(2*np.pi/T)*t),(t,-T/2,T/2))
    c_0=c_k.subs(k,0)
    #c_k_mag =[sym.simplify((abs(c_n_coeff.subs(n,i)))) for i in range (-N,N+1)]
    return (c_k,c_0)

def espectral(c_k,f,N):
    PSD=[abs((c_k.subs(k,i)))**2 for i in range(-N,N+1)]
    positive_PSD=[2*abs((c_k.subs(k,i)))**2 if i!=0 else (c_k.subs(k,0))**2 for i in range(N+1)]
    return PSD,positive_PSD

def ck_power(ft,f,N=5):
    c_k_coeff=f*sym.integrate(ft*sym.exp(-2*j*np.pi*t*k*f),(t,-1/(2*f),1/(2*f)))
    #C_k_coeff=sym.lambdify(k,c_k_coeff,modules=['numpy'])
    #PSD=[abs((c_k_coeff(i)))**2 for i in range(-N,N+1)]
    ##PSD=[(c_k_coeff.subs(k,i))*(c_k_coeff.subs(k,-i)) for i in range(-N,N+1)]
    ### worked. PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
    PSD=[(c_k_coeff.evalf(subs={k:i}))*(c_k_coeff.evalf(subs={k:-i})) for i in range(-N,N+1)]
    PSD=[sym.N(abs(i.subs({u(0):0.5})).evalf(3)) for i in PSD]
    positive_PSD=PSD[len(PSD)//2:]
    # because the k=0 c_k isn't twice in the k axis apporting power.
    positive_PSD[1:]=[2*i for i in positive_PSD[1:]]
    PSD=np.array(PSD)
    positive_PSD=np.array(positive_PSD)
    return PSD,positive_PSD

def espectrump(c_k,f,N):
    # this function should not be used for performance purposes
    PSD=[abs((c_k.subs(k,i)))**2 for i in range(-N,N+1)]
    positive_PSD=[2*abs((c_k.subs(k,i)))**2 if i!=0 else (c_k.subs(k,0))**2 for i in range(N+1)]
    plt.stem(list(range(-N,N+1)),PSD,markerfmt='^',use_line_collection=True)
    plt.xlabel("$k$")
    plt.grid()
    plt.show()
    return positive_PSD

def psdplot(N,PSD):
    plt.stem(list(range(-N,N+1)),PSD,markerfmt='^',use_line_collection=True)
    plt.xlabel("$k$")
    plt.ylabel("$y=10{log()}$")
    plt.grid()
    plt.show()
    return None #excuse me, I can't hide it. Is that simple

#waveforms
def pulsetrain(A,T,D,off=0,toff=0):
    f=A*(-u(t+T/2)+2*(u(t+D*T/2)-u(t-D*T/2))+u(t-T/2))
    foff=f+off*(u(t+T/2)-u(t-T/2))
    foff=foff.subs(t,t-toff)
    return foff

def triangle(A,T,D=None,off=0,toff=0):
    m = (2*A)/T
    toff_temp=0.5
    tri=m*t*u(t+T/2)-2*m*t*u(t)+m*t*u(t-T/2)
    foff = tri+(off+toff_temp)*(u(t+T/2)-u(t-T/2))
    foff = foff.subs(t,t-toff)
    return foff

def sawtooth(A,T,D=None,off=0,toff=0):
    m = A/T
    saw =m*t*u(t+T/2)-m*t*u(t-T/2)-(m/2)*u(t-T/2)
    foff = saw+off*(u(t+T/2)-u(t-T/2))
    foff = foff.subs(t,t-toff)
    return foff

Thanks in advance!

ego2509
  • 75
  • 1
  • 1
  • 11

0 Answers0