ピーム走査のアレーファクタ・アニメーション(等振幅リニアアレー)

モジュールのインポートや初期設定など

import numpy as np
from scipy.signal import find_peaks
from matplotlib import pyplot as plt
from matplotlib import animation
np.set_printoptions(precision=5)
import scienceplots
#Warning : As of version 2.0.0, you need to add import scienceplots before setting the style (plt.style.use('science')).
plt.style.use(['science', 'notebook'])
#plt.rcParams['font.family'] = 'Times New Roman' # font familyの設定
plt.rcParams['font.family'] = 'serif' # font familyの設定
plt.rcParams['mathtext.fontset'] = 'cm' # math fontの設定

ユーザ関数

アニメーションの図の更新をする関数として,
def _update(frame, uoverpi, f, th, p): # グラフを更新するための関数
    def afactor_fourier(n,an,u):
        f = 0
        if np.mod(n,2)==0: # 偶数
            for i0 in range(n//2):
                i = i0+1
                f = f+an[i0]*np.cos((2*i-1)/2*u)
            f = 2.0*f
        else: # 奇数
            for i0 in range((n-1)//2):
                i = i0+1
                f = f+an[i0+1]*np.cos(i*u)
            f = an[0]+2*f
        return f
    
    ax[0].cla() # ax[0] をクリア
    ax[1].cla() # ax[1] をクリア
    # データを更新 (追加) する
    thdeg = th*180/np.pi
    u = akd * (np.cos(th)-np.cos(tth0[frame]))
    uoverpi = u/np.pi
    f = afactor_fourier(n,an,u)
    p = 20.0*np.log10(np.abs(f))
    locs, _ = find_peaks(p) # ピーク値
    locs_null, _ = find_peaks(-p) # ヌル点
    # グラフを再描画する
    ax[0].axis([-4,4,-1,1])
    ax[0].set_xlabel(r'$u/\pi$ [rad], where $u = kd ( \cos \theta - \cos \theta_0)$')
    ax[0].set_ylabel('Array factor $f(u)$')
    ax[0].set_title(fr'$\theta_0 = {tth0[frame]*180/np.pi:.1f}^\circ$')
    ax[0].plot(uoverpi, f)
    ax[0].plot(uoverpi[locs],f[locs],'.')
    ax[0].plot(uoverpi[locs_null],np.zeros(len(locs_null)),'.')
    ax[0].text(0.95,-0.3,'$N=$'+str(n))
    ax[0].text(0.95,-0.55,'Element spacing: $d = $'+str(dd)+r'$\lambda$')
    
    ax[1].axis([0, 180, -40, 0])
    ax[1].set_xlabel(r'Angle $\theta$ [deg]')
    ax[1].set_ylabel(r'$20 \log_{10} |f(\theta)|$ [dB]')
    ax[1].set_xticks(np.linspace(0,180,5))
    ax[1].plot(thdeg, p)
    ax[1].plot(thdeg[locs],p[locs],'o')
    ax[1].plot(thdeg[locs_null],np.ones(len(locs_null))*-40,'o')
    plt.tight_layout()
    return

アニメーション

アレーの素子数,素子間隔,素子の励振振幅を設定して,
n = 5 # N elements
dd = 0.5 # Element spacing normalized by wave-length [mm]
if np.mod(n,2) == 0:
    ii = n//2 
else:
    ii = (n+1)//2
an = np.ones(ii)/n# 等振幅励振
ビームを走査するため,
akd = 2*np.pi*dd
th = np.linspace(0, np.pi, 3600+1)
n_th0 = 181
tth0 = np.linspace(0, np.pi, n_th0)
uoverpi = np.empty(0)
thdeg = np.empty(0)
f = np.empty(0)
p = np.empty(0)
アニメーションはgifファイルとして,
fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(10, 6)) # グラフ領域の作成,nrows=縦に並べる数,ncols=横に並べる数
params = {
    'fig': fig,
    'func': _update,  # グラフを更新する関数
    'fargs': (uoverpi, f, th, p),  # 関数の引数 (フレーム番号を除く)
    'interval': 10,  # 更新間隔 (ミリ秒)
    'frames': np.arange(n_th0),  # フレーム番号を生成するイテレータ
    'repeat': False,  # 繰り返さない
}
anime = animation.FuncAnimation(**params)
# グラフを保存する
anime.save('uniform_array_f_N'+str(n)+'_d'+str(dd)+'wl.gif', writer='pillow')