· 

Pythonでフィルタ(3)

フィルタの構成方法と適用方法について記録を残す。で、FIRフィルタを試してみる。

ところで、フィルタってホントいろいろあって、学問としてどういう風に学ぶのが正解なのかわからん。必要な時に必要なことを学ぶとして、理論はあいかわらずそっちのけですすめる。

FIRフィルタについては、あっちこっちに説明があるので、ここでは一切触れない。まじで、一切。こちらのscipy.signalのリファレンスをのんびり眺めると、firwinってのがきっとそうだろう。

で、これで思った通りの波形になるのかどうか、、、

まずはベースバンドにフィルタしてどうなるのか、

import numpy as np
import scipy.signal as signal
import matplotlib.pyplot as plt

# よく使う変数
pi=np.pi
deg2rad=pi/180.0
rad2deg=180.0/pi
twopi=2*pi
 
# シンボル列を引き延ばす
def extend_symbol_to_simulation_sampling_rate(symbols,t_symbol,t_simulation_sampling):
    # シンボル数
    size_of_symbols=symbols.size
    # 最後のシンボルが終わる時間
    end_time=size_of_symbols*t_symbol
    # 計算タイミング
    t=np.arange(0,end_time,t_simulation_sampling)
    # 各シンボルの開始(終了)時間
    t_periods_of_symbols=np.append(0,np.arange(1,size_of_symbols,1)*t_symbol)
    # 結果データ領域確保
    ex_symbols=np.zeros_like(t)
    # 先頭データは入れておく
    ex_symbols[0]=symbols[0]
    # 各シンボルについて、その期間のインデックスを取得し、データを入れ込む
    for i in range(0,size_of_symbols):
        ex_symbols[np.where(t>t_periods_of_symbols[i])]=symbols[i]
    return ex_symbols,end_time
        
f_sampling_simulation=1e7
f_carrier=500e3

#generate baseband waveform
f_symbol=10e3                 # シンボルレート in Hz
t_sampling_simulation=1/f_sampling_simulation
symbols_in_base=np.array([1,0,1,0,1,0,1,0,1,0,1,0])
baseband_t,t_end=extend_symbol_to_simulation_sampling_rate(symbols_in_base,1/f_symbol,t_sampling_simulation)
t=np.arange(0,t_end,t_sampling_simulation)
number_of_samples=t.size

#フィルタ生成
q_value=10
zeta=1/(2*q_value)
fcut=zeta*f_carrier
print(fcut)
wcut=fcut/(f_sampling_simulation/2)
fircoeff=signal.firwin(1001,wcut)
#fircoeff = signal.firwin(numtaps=21, cutoff=fcut, fs=f_sampling_simulation)
print(fircoeff)
w,h=signal.freqz(fircoeff,1,worN=2**20)
freqs=w*f_sampling_simulation/twopi
h_abs=np.abs(h)
amps_db=20*np.log10(h_abs)
angles=np.angle(h)*rad2deg

#フィルタ適用
baseband_filtered_t=signal.lfilter(fircoeff,1,baseband_t)

#変調フィルタ復調した波形をファイルからロード
npz = np.load('o_t_baseband_filtered_t.npz')
t_from_file=npz['arr_0']
baseband_filtered_t_from_file=npz['arr_1']

#プロット
fig = plt.figure()
ax1=plt.subplot(3,1,1)
ax1.grid(True)
ax1.plot(freqs,amps_db, '-')
ax1.set_xlim(400e3,600e3)
ax1.set_ylim(-50,0)
ax1.set_ylabel('Amplitude [dB]')
ax1_2=ax1.twinx()
ax1_2.grid(True)
ax1_2.plot(freqs,angles, 'r-')
ax1_2.set_xlim(0,1e6)
ax1_2.set_ylim(-180,180)
ax1_2.set_yticks(np.arange(-180,181,step=90))
ax1.set_xlabel('frequency [Hz]')
ax1_2.set_ylabel('Phase [deg.]')

ax2=plt.subplot(3,1,2)
ax2.plot(t,baseband_t)

ax3=plt.subplot(3,1,3)
ax3.plot(t,baseband_filtered_t)
ax3.plot(t_from_file,baseband_filtered_t_from_file)

fig.tight_layout()
plt.show()

なんか違う雰囲気です。(燈色が期待する波形)

では変調波でもやってみる。

import numpy as np
import scipy.signal as signal
import matplotlib.pyplot as plt

# よく使う変数
pi=np.pi
deg2rad=pi/180.0
rad2deg=180.0/pi
twopi=2*pi
 
# シンボル列を引き延ばす
def extend_symbol_to_simulation_sampling_rate(symbols,t_symbol,t_simulation_sampling):
    # シンボル数
    size_of_symbols=symbols.size
    # 最後のシンボルが終わる時間
    end_time=size_of_symbols*t_symbol
    # 計算タイミング
    t=np.arange(0,end_time,t_simulation_sampling)
    # 各シンボルの開始(終了)時間
    t_periods_of_symbols=np.append(0,np.arange(1,size_of_symbols,1)*t_symbol)
    # 結果データ領域確保
    ex_symbols=np.zeros_like(t)
    # 先頭データは入れておく
    ex_symbols[0]=symbols[0]
    # 各シンボルについて、その期間のインデックスを取得し、データを入れ込む
    for i in range(0,size_of_symbols):
        ex_symbols[np.where(t>t_periods_of_symbols[i])]=symbols[i]
    return ex_symbols,end_time
        
def generate_ask(f_carrier,f_sym,f_samp_generation,phase_carrier_initial,symbols_in_base):
    t_sym=1/f_sym
    t_samp_generation=1/f_samp_generation
    omega_carrier=twopi*f_carrier
    # シンボルを計算用に拡張
    [symbols,t_end]=extend_symbol_to_simulation_sampling_rate(symbols_in_base,t_sym,t_samp_generation)
    # 計算するタイミング
    t=np.arange(0,t_end,t_samp_generation)
    # 波形生成
    amp_t=np.exp(1j*omega_carrier*t+phase_carrier_initial)*symbols
    return t,symbols,amp_t


f_sampling_simulation=1e7
f_carrier=500e3

#generate ask waveform
f_symbol=10e3                 # シンボルレート in Hz
t_sampling_simulation=1/f_sampling_simulation
phase_initial=0*deg2rad      # 搬送波の初期位相(何でもいい) in rad
symbols_in_base=np.array([1,0,1,0,1,0,1,0,1,0,1,0])
t,baseband_t,amp_t=generate_ask(f_carrier,f_symbol,f_sampling_simulation,phase_initial,symbols_in_base)
#amp_t=np.real(amp_t)         #後で復調するので複素数のままにする
number_of_samples=t.size

#フィルタ生成
q_value=10
zeta=1/(2*q_value)
fcut=np.array([f_carrier-zeta*f_carrier,f_carrier+zeta*f_carrier])
print(fcut)
wcut=fcut/(f_sampling_simulation/2)
fircoeff=signal.firwin(1001,wcut,pass_zero=False)
#fircoeff = signal.firwin(numtaps=21, cutoff=fcut, fs=f_sampling_simulation)
print(fircoeff)
w,h=signal.freqz(fircoeff,1,worN=2**20)
freqs=w*f_sampling_simulation/twopi
h_abs=np.abs(h)
amps_db=20*np.log10(h_abs)
angles=np.angle(h)*rad2deg

#フィルタ適用
amp_filtered_t=signal.lfilter(fircoeff,1,amp_t)

#復調
amp_demod_t=np.abs(amp_filtered_t)
np.savez('o_t_amp_demod_t_fir',t,amp_demod_t)

#プロット
fig = plt.figure()
ax1=plt.subplot(4,1,1)
ax1.grid(True)
ax1.plot(freqs,amps_db, '-')
ax1.set_xlim(400e3,600e3)
ax1.set_ylim(-50,0)
ax1.set_ylabel('Amplitude [dB]')
ax1_2=ax1.twinx()
ax1_2.grid(True)
ax1_2.plot(freqs,angles, 'r-')
ax1_2.set_xlim(0,1e6)
ax1_2.set_ylim(-180,180)
ax1_2.set_yticks(np.arange(-180,181,step=90))
ax1_2.set_xlabel('frequency [Hz]')
ax1_2.set_ylabel('Phase [deg.]')

ax2=plt.subplot(4,1,2)
ax2.plot(t,baseband_t)

ax3=plt.subplot(4,1,3)
ax3.plot(t,np.real(amp_t))
ax3.plot(t,np.imag(amp_t))

ax4=plt.subplot(4,1,4)
ax4.plot(t,np.real(amp_filtered_t))
ax4.plot(t,np.imag(amp_filtered_t))
ax4.plot(t,amp_demod_t)

fig.tight_layout()
plt.show()

やっぱちゃうなー。

矩形波に対してFIRフィルタを適用している例をwebで見つけられなかったので、これが正しいかどうかはわからないけど、欲しい波形とは違う。理論には触れない。とりあえず期待と違う。

地面テラス星6アーマーガアはてんねんのヘイラッシャで楽勝(あまごいは必要)。なぜ今まで気づかなかったのか、、、