フィルタの周波数特性¶

In [1]:
# モジュールの読み込み
import numpy as np
import pandas as pd
from scipy.special import comb
from scipy.special import eval_chebyt
import matplotlib.pyplot as plt
from matplotlib import style
import skrf as rf
In [2]:
import warnings
warnings.filterwarnings("ignore")
In [3]:
import scienceplots
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の設定
In [4]:
def dbdeg(z,iunwrap): # 電磁界の複素係数から絶対値,デジベル(dB),偏角(deg)の計算
    q = 180.0/np.pi
    amp = np.abs(z)
    db = 20.0*np.log10(amp)
    rad = np.angle(z)
    if iunwrap==1:
        # rad = np.unwrap(rad, discont=np.pi)
        rad = np.unwrap(rad)
    deg = rad*q
    return amp,db,deg

特性関数¶

動作伝送関数(Transducer Function) $H(s)$ は,特性関数(characteristic function)$K(s)$ を用いて($s = j\omega$), \begin{gather} |H(s)|^2= 1+|K(s)|^2 \end{gather} さらに,ポート1から見た反射係数を $\Gamma_1$ とすると, \begin{gather} |\Gamma_1|^2 = 1-\frac{1}{|H|^2} = \frac{|H|^2-1}{|H|^2} = \frac{|K|^2}{|H|^2} = \frac{|K|^2}{1-|K|^2} \end{gather}

最平坦特性¶

最平坦特性の特性関数 $K(s)$ は, \begin{gather} K(s) = s^N \end{gather} 遮断角周波数$\omega _c$で角周波数$\omega$を規格化して, 規格化角周波数$\Omega$を次式によって定義する. \begin{gather} s = j\Omega, \ \ \ \Omega = \frac{\omega}{\omega _c} \end{gather} これより,$|H|^2$は, \begin{gather} |H|^2 = 1 + (-s^2)^N = 1+ \Omega ^{2N} = 1 +\left( \frac{\omega}{\omega _c} \right) ^{2N} \end{gather} ただし,$\Omega =1$,$\omega = \omega _c$を遮断点と呼び, このとき,$|H(\Omega)|^2$は, $|H(1)|^2 = 1+1^{2N} = 2$である. また,$\Omega =0$のとき,$|H(0)|^2 = 1$. $N \to \infty $では,$0 \leq \Omega \leq 1$のとき $|H|^2= 1$で無損失伝送, $\Omega \geq 1$のとき$|H|^2=\infty$で損失が無限大(全く伝送しない)となり, 理想的な低域通過フィルタ(lowpass filter)の特性となる.

In [5]:
def maximally_flat_response(n,omega): # 最平坦特性の動作伝送関数 H, 反射係数の逆数
    n2 = 2.0*n
    h2 = 1.0+omega**n2
    gamma2 = 1.0-1.0/h2
    gamma2i = 1.0/gamma2
    return h2, gamma2i

動作伝送関数の因数分解¶

実際の回路で実現できるように, $H(s)$を複素平面の左半平面内のゼロ点の値を用いて因数分解すると, \begin{gather} H(s) = (s-j\epsilon ) (s-j\epsilon ^3) \cdots (s-j\epsilon ^{2N-1}) = \prod _{n=1}^N \left( s-j\epsilon ^{2n-1} \right) = \prod _{n=1}^N \left( s-s_n \right) \end{gather} ここで, \begin{gather} s_n = j \epsilon ^{2n-1} = j e^{j\frac{2n-1}{2N} \pi} = e^{j\frac{2n-1+N}{2N} \pi} \end{gather} このとき,反射係数$\Gamma(s)$は, \begin{gather} \Gamma(s) = \frac{\pm K(s)}{H(s)} = \pm \frac{s^N}{\displaystyle{\prod _{n=1}^N \left( s-s_n \right)}} \end{gather} ただし,上式の符号は,この時点では定まらないので,プログラムではプラス符号を計算する.後述する等リプル特性の場合も同様である.

In [6]:
def maximally_flat_response_h(n,omega): # 因数分解した最平坦特性の動作伝送関数 H, 反射係数,sn
    s = 1.0j*omega
    h = 1.0
    ssn = np.empty(0)
    for i in range(1,n+1):
        th = (2.0*i-1)/2.0/n*np.pi
        sn = 1.0j*np.exp(1.0j*th)
        ssn = np.append(ssn, sn)
        h = h*(s-sn)
    gammai = h/s**n
    return h, gammai, ssn
In [7]:
def maximally_flat_ssn(n,omega):
    ssn = np.empty(0)
    for i in range(1,n+1):
        th = (2.0*i-1)/2.0/n*np.pi
        sn = 1.0j*np.exp(1.0j*th)
        ssn = np.append(ssn, sn)
    return ssn

最平坦特性を持つ低域通過梯子型回路の規格化素子値¶

低域通過梯子型回路は双対的な次のような回路で表され,$N$次の最平坦特性を有する梯子型リアクタンス回路を合成すると,規格化素子値$g_k$は,次のようになる. \begin{align} g_0 &= 1\\ g_k &= 2 \sin \left( \frac{(2k-1) \pi }{2N} \right) \ \ \ (k=1,2, \cdots ,N)\\ g_{N+1} &= 1 \end{align} ただし,$g_0$は入力の負荷抵抗,$g_{N+1}$は終端負荷の抵抗を示す.

In [8]:
def element_values_maximally_flat(n): # 最平坦特性を持つ低域通過梯子型回路の規格化素子値
    gg = np.empty(0)
    gg = np.append(gg, 1.0)   
    for k in range(1,n+1):
        th = (2.0*k-1.0)*np.pi/2.0/n
        g = 2.0*np.sin(th)
        gg = np.append(gg, g)
    gg = np.append(gg, 1.0)
    return gg

等リプル特性¶

特性関数$K(s)$を,$s = j \Omega$ より, \begin{gather} K(s) = K(j \Omega) \equiv \varepsilon T_N(\Omega) \end{gather} ここで,$T_N(\Omega)$は$N$次のチェビシェフ多項式(Chebyshev polynomial)を示し, \begin{gather} T_N (\Omega) = \left\{ \begin {array}{ll} (-1)^N \cosh \big( N \cosh ^{-1} |\Omega| \big) & (\Omega < -1) \\ \cos \big( N \cos^{-1} \Omega \big) & (|\Omega| \le 1) \\ \cosh \big( N \cosh ^{-1} \Omega \big) & (\Omega > 1) \end{array} \right. \end{gather} また,$\varepsilon$ は通過域のリプルの大きさを決めるパラメータ(実数)である.これより, \begin{align} |K(s)|^2 &= K(s) K(s)^*=K(s) K(-s) =K(j\Omega) K(-j\Omega) \nonumber \\ &= \varepsilon T_N(\Omega) \cdot \varepsilon T_N(-\Omega) = \varepsilon^2 T_N^2(\Omega) \\ |H(s)|^2 &= 1+|K(s)|^2 = 1+\varepsilon^2 T_N^2 (\Omega) \end{align} ここで,遮断点$\Omega =1$のとき,$|H|^2$は,$T_N(1)=1$より, \begin{gather} |H|^2 \Big| _{\Omega=1} = 1+\varepsilon^2 T_N^2 (1) = 1+\varepsilon^2 \end{gather} 通過域のリプルの最大値は, \begin{gather} |H|_{max} = \sqrt{1+\varepsilon^2} \end{gather} デジベル値は,$L_{Ar}=10 \log_{10} (1+\varepsilon^2)$ [dB]. 逆に,$\varepsilon$は, \begin{gather} \varepsilon = \sqrt{10^{\frac{L_{Ar}}{10}}-1} \end{gather}

In [9]:
def chebyshev_response(n,rwdb,omega):
    k2 = 10.0**(rwdb/10.0)-1.0
    che = eval_chebyt(n, omega)
    h2 = 1.0+k2*che**2
    gamma2 = 1.0-1.0/h2
    gamma2i = 1.0/gamma2
    return h2, gamma2i

動作伝送関数の因数分解¶

動作伝送関数$H(s)$,さらには反射係数$\Gamma(s)$は, \begin{gather} H(s) = \pm \varepsilon 2^{N-1} (-j)^N \prod _{n=1}^N \left( s-s_n \right) \\ \Gamma(s) %= \frac{K(s)}{H(s)} = \pm \frac{T_N (\Omega)}{\displaystyle{2^{N-1} (-j)^N \prod _{n=1}^N \left( s-s_n \right)}} \end{gather} ここで,$s_n$は, \begin{align} s_n &=\sigma_n + j \omega_n \\ \sigma_n &= - \sin \frac{(2n+1)\pi}{2N} \sinh a \\ \omega_n &= \cos \frac{(2n+1)\pi}{2N} \cosh a \\ a &= \frac{1}{N} \sinh ^{-1} \frac{1}{\varepsilon} \end{align} このとき,次の関係が成り立つ. \begin{gather} \sin^2 \frac{(2n+1)\pi}{2N} + \cos^2 \frac{(2n+1)\pi}{2N} = \frac{\sigma_n^2}{\sinh ^2a} + \frac{\omega_n^2}{\cosh ^2a} = 1 \end{gather} これより,$s_n$は複素平面のだ円(直交するだ円の軸は実軸と虚軸)上にあることがわかる.

In [10]:
def chebyshev_response_h_(n,rwdb,omega): # 因数分解した等リプル特性の動作伝送関数 H, 反射係数,sn
    s = 1.0j*omega
    k2 = 10.0**(rwdb/10.0)-1.0
    k = np.sqrt(k2)
    ki = 1.0/k
    a = np.sqrt(1.0+ki**2)+ki
    an = a**(1.0/n)
    ani = 1.0/an
    sh = (an-ani)/2.0
    ch = (an+ani)/2.0
    # print("sinh a =",sh, ", cosh a=",ch)
    h = 2.0**(n-1)*k
    ssn = np.empty(0)
    for i in range(1,n+1):
        th = (2.0*i-1.0)/2.0/n*np.pi
        re = -sh*np.sin(th)
        im = ch*np.cos(th)
        sn = re+1.0j*im
        ssn = np.append(ssn, sn)
        h = h*(s-sn)
    che = eval_chebyt(n, omega)
    fn = 1.0j**n*che
    gammai = h/k/fn
    return h, gammai, ssn, sh, ch
In [11]:
def chebyshev_ssn(n,rwdb,omega):
    k2 = 10.0**(rwdb/10.0)-1.0
    k = np.sqrt(k2)
    ki = 1.0/k
    a = np.sqrt(1.0+ki**2)+ki
    an = a**(1.0/n)
    ani = 1.0/an
    sh = (an-ani)/2.0
    ch = (an+ani)/2.0
    ssn = np.empty(0)
    for i in range(1,n+1):
        th = (2.0*i-1.0)/2.0/n*np.pi
        re = -sh*np.sin(th)
        im = ch*np.cos(th)
        sn = re+1.0j*im
        ssn = np.append(ssn, sn)
    return ssn, sh, ch

等リプル特性を持つ低域通過梯子型回路の規格化素子値¶

$N$次のチェビシェフ特性を有する梯子型リアクタンス回路を合成すると,規格化素子値$g_k$は, \begin{align} g_1 &= \frac{2 u_1}{\eta} \\ g_k &= \frac{4u_{k-1} u_k}{v_{k-1} g_{k-1}} \ \ \ (k=2,3, \cdots ,N) \\ g_{N+1} &= \left\{ \begin {array}{cc} \displaystyle{1} & (N:\mbox{奇数}) \\ \displaystyle{\coth ^2 \frac{\zeta}{4}} & (N:\mbox{偶数}) \end{array} \right. \end{align} ただし,$g_0 =1$ である.また,$g_{N+1}$は終端負荷の抵抗(最終段が直列素子の場合)あるいはコンダクタンス(最終段が並列素子の場合)を示す.ここで, \begin{align} \zeta &= \ln \left[ \coth \left( \frac{L_{Ar}}{17.37} \right) \right] \\ \eta &= \sinh \left( \frac{\zeta}{2N} \right) \\ u_k &= \sin \left( \frac{(2k-1)\pi}{2N} \right) \ \ \ (k=1,2, \cdots ,N) \\ v_k &= \eta ^2 + \sin ^2 \left( \frac{k\pi}{N} \right) \ \ \ (k=1,2, \cdots ,N) \end{align} ただし,$L_{Ar}$はリプルのピーク値[dB]を示す.

In [12]:
def element_values_equal_ripple(nn,rwdb):
    ch = 1.0/np.tanh(rwdb/17.37)
    beta = np.log(ch)
    gamma = np.sinh(beta/2.0/nn)
    gg = np.empty(0)
    gg = np.append(gg, 1.0)
    for i in range(1,nn+1):
        th = (2.0*i-1.0)*np.pi/2.0/nn
        ai = np.sin(th)
        bi = gamma**2+(np.sin(i*np.pi/nn))**2
        if i == 1:
            gi = 2.0*ai/gamma
        else:
            gi = 4.0*aim*ai/bim/gim
        aim = ai
        bim = bi
        gim = gi
        gg = np.append(gg, gi)
    if nn % 2 == 1:
        gn1 = 1.0
    else:
        gn1 = (1.0/np.tanh(beta/4.0))**2
    gg = np.append(gg, gn1)
    return gg

入力データ¶

In [13]:
ic = 1 # maximally flat
# ic, rwdb = 2, 0.04321 # equal_ripple, リプル [dB]
# ic, rwdb = 2, -10.0*np.log10(1.0-10.0**(-20.0/10.0)) # equal_ripple, リプル [dB]
if ic == 2:
    print("RW=",rwdb,"[dB], s11=",-10.0*np.log10(1.0-10.0**(-rwdb/10.0)),"[dB]")
In [14]:
ip = 1 # low pass
# ip = 2 # high pass
# ip, rbw = 3, 0.3 # band pass
# ip, rbw = 4, 0.3 # band stop
In [15]:
# 段数
nn = np.array([3, 5, 7])
# nn = np.arange(2, 10, 1) 
# nn = np.arange(3, 8, 2)
# nn = np.array([2,3,4,5])
n_n = len(nn)
print("nn=",nn)
nn= [3 5 7]
In [16]:
n_ome = 501
omega = np.linspace(0.01, 0.1, n_ome)
omega = np.append(omega, np.linspace(0.1, 1.0, n_ome))
omega = np.append(omega, np.linspace(1.0, 3.0, n_ome))
omega = np.append(omega,np.linspace(3.0, 10.0, n_ome))
n_w = len(omega)
print("n_w=",n_w)
n_w= 2004

周波数変換¶

In [17]:
if ip == 1: # 低域通過
    omega_t = 1.0*omega
if ip == 2: # 低域通過から高域通過への周波数変換
    omega_t = -1.0/omega
elif ip == 3: # 低域通過から帯域通過への周波数変換
    omega_t = (omega-1.0/omega)/rbw
elif ip == 4: # 低域通過から帯域阻止への周波数変換
    omega_t = (omega-1.0/omega)/rbw
    omega_t = np.where(omega_t==0.0, 1.0e-10, omega_t)
    omega_t = -1.0/omega_t
In [18]:
hh2 = np.empty((0,n_w))
gg2 = np.empty((0,n_w))
hh = np.empty((0,n_w))
ggi = np.empty((0,n_w))
for n in nn:
    if ic == 1:
        gk = element_values_maximally_flat(n) # 特性関数K(s)=s**n
        h2, g2 = maximally_flat_response(n,omega_t)
        h, gammai, ssn = maximally_flat_response_h(n,omega_t)
    elif ic == 2:
        gk = element_values_equal_ripple(n,rwdb)
        h2, g2 = chebyshev_response(n,rwdb,omega_t)   
        h, gammai, ssn, sh1, ch1 = chebyshev_response_h_(n,rwdb,omega_t)
    n_ssn = len(ssn)
    print(f'{n:2d}',end=' ')
    [print(f"{gk[j]:6.4f}",end=' ') for j in range(n+2)]
    print('')
    hh2 = np.append(hh2, [h2], axis=0)
    gg2 = np.append(gg2, [g2], axis=0)
    hh = np.append(hh, [h], axis=0)
    ggi = np.append(ggi, [gammai], axis=0)

hh2_amp = np.abs(hh2)
hh2_db = 10.0*np.log10(hh2_amp)
gg2_amp = np.abs(gg2)
gg2_db = 10.0*np.log10(gg2_amp)

hh_amp,hh_db,hh_deg = dbdeg(hh,0)
ggi_amp,ggi_db,ggi_deg = dbdeg(ggi,0)
gg = 1.0/ggi
 3 1.0000 1.0000 2.0000 1.0000 1.0000 
 5 1.0000 0.6180 1.6180 2.0000 1.6180 0.6180 1.0000 
 7 1.0000 0.4450 1.2470 1.8019 2.0000 1.8019 1.2470 0.4450 1.0000 

挿入損失 [dB]¶

In [19]:
df = pd.DataFrame({
    f'$N={N}$': hh_db[i, ::100] for i, N in enumerate(nn)
})
df.index = omega[::100]
df.index.name = '$\Omega$'
df.columns.name = '$|H|$ [dB]'
df.style.background_gradient(cmap='rainbow')
Out[19]:
$|H|$ [dB] $N=3$ $N=5$ $N=7$
$\Omega$      
0.010000 0.000000 -0.000000 -0.000000
0.028000 0.000000 0.000000 -0.000000
0.046000 0.000000 0.000000 -0.000000
0.064000 0.000000 0.000000 0.000000
0.082000 0.000001 0.000000 0.000000
0.100000 0.000004 0.000000 0.000000
0.278200 0.002013 0.000012 0.000000
0.458200 0.040005 0.001771 0.000078
0.638200 0.283955 0.048409 0.008068
0.818200 1.139516 0.547894 0.254126
0.998200 2.986890 2.971354 2.955875
1.392000 9.177701 14.520080 20.151636
1.792000 15.329486 25.346500 35.468554
2.192000 20.489408 34.085750 47.717750
2.592000 24.832397 41.363817 57.908907
2.992000 28.563745 47.596234 66.634623
4.358000 38.357867 63.928724 89.500212
5.758000 45.616419 76.027166 106.438032
7.158000 51.287534 85.479169 119.670837
8.558000 55.942348 93.237228 130.532120
9.958000 59.890332 99.817212 139.744097

透過係数の位相特性(主値)[deg]¶

In [20]:
df = pd.DataFrame({
    f'$N={N}$': -hh_deg[i, ::100] for i, N in enumerate(nn)
})
df.index = omega[::100]
df.index.name = '$\Omega$'
df.columns.name = 'Arg $(1/H)$ [deg]'
df.style.background_gradient(cmap='coolwarm')
Out[20]:
Arg $(1/H)$ [deg] $N=3$ $N=5$ $N=7$
$\Omega$      
0.010000 -1.145935 -1.854154 -2.574880
0.028000 -3.208983 -5.192083 -7.210250
0.046000 -5.273075 -8.531300 -11.847289
0.064000 -7.338891 -11.872635 -16.487077
0.082000 -9.407123 -15.216928 -21.130698
0.100000 -11.478482 -18.565027 -25.779249
0.278200 -32.326600 -52.110794 -72.314170
0.458200 -54.729324 -87.516479 -121.226344
0.638200 -79.662947 -126.334273 -174.206298
0.818200 -107.291566 -172.099149 123.530148
0.998200 -134.741937 135.513247 45.795625
1.392000 -178.271451 55.626772 -69.729422
1.792000 158.184256 18.436889 -120.107272
2.192000 144.469126 -2.889910 -149.332770
2.592000 135.480031 -16.997354 -168.781919
2.992000 129.099932 -27.095556 177.258705
4.358000 116.539297 -47.161673 149.461742
5.758000 110.004863 -57.673534 134.880272
7.158000 106.062157 -64.032100 126.055832
8.558000 103.420958 -68.296620 120.136192
9.958000 101.527061 -71.356469 115.888241

反射損失 [dB]¶

In [21]:
df = pd.DataFrame({
    f'$N={N}$': ggi_db[i, ::100] for i, N in enumerate(nn)
})
df.index = omega[::100]
df.index.name = '$\Omega$'
df.columns.name = '$1/|\Gamma_1|$ [dB]'
df.style.background_gradient(cmap='rainbow')
Out[21]:
$1/|\Gamma_1|$ [dB] $N=3$ $N=5$ $N=7$
$\Omega$      
0.010000 120.000000 200.000000 280.000000
0.028000 93.170518 155.284197 217.397876
0.046000 80.234530 133.724217 187.213904
0.064000 71.629202 119.382003 167.134804
0.082000 65.171170 108.618615 152.066061
0.100000 60.000004 100.000000 140.000000
0.278200 33.340585 55.564299 77.790002
0.458200 20.376700 33.896263 47.452366
0.638200 11.986547 19.552729 27.314116
0.818200 6.367947 9.261946 12.453799
0.998200 3.033836 3.049598 3.065416
1.392000 0.559347 0.156157 0.042143
1.792000 0.129205 0.012699 0.001233
2.192000 0.038975 0.001695 0.000073
2.592000 0.014297 0.000317 0.000007
2.992000 0.006049 0.000076 0.000001
4.358000 0.000634 0.000002 0.000000
5.758000 0.000119 0.000000 0.000000
7.158000 0.000032 0.000000 0.000000
8.558000 0.000011 0.000000 0.000000
9.958000 0.000004 0.000000 0.000000
In [22]:
fig1 = plt.figure(figsize=(6, 10)) # グラフ領域の作成
plt.subplot(3, 1, 1) # 上側の図
plt.grid(color = "gray", linestyle="--")
plt.minorticks_on() # #補助目盛りをつける
plt.xlim(0.01, 10.0) # x軸範囲の設定
plt.xticks(fontsize=11)
plt.xlabel("$\Omega$", fontsize=11) # x軸のラベル設定
plt.ylim(0.0, 50.0) # y軸範囲の設定
plt.yticks(np.arange(0.0, 60.0, step=10.0), fontsize=11)
plt.ylabel("Insertion loss [dB]", fontsize=11) # y軸のラベル設定
plt.xscale('log') # log スケール
for i in range(n_n):
#    plt.plot(omega, hh2_db[i,:], label=f"$N=${nn[i]:2d}")
#    plt.plot(omega, gg2_db[i,:], label=f"$1/|\Gamma|^2: N=${nn[i]:2d}")
    plt.plot(omega, hh_db[i,:], label=f"$|H|: N=${nn[i]:2d}")
#    plt.plot(omega, ggi_db[i,:], label=f"$1/|\Gamma|^2: N=${nn[i]:2d}")
plt.legend(ncol=1, loc='upper left', fancybox=False, frameon = True, fontsize=9)

plt.subplot(3, 1, 2) # 下側の図
plt.grid(color = "gray", linestyle="--")
plt.minorticks_on() # #補助目盛りをつける
plt.xlim(0.01, 10.0) # x軸範囲の設定
plt.xticks(fontsize=11)
plt.ylim(-180.0, 180.0) # y軸範囲の設定
plt.yticks(np.arange(-180.0, 270, step=90.0), fontsize=11)
plt.xlabel("$\Omega$", fontsize=11) # x軸のラベル設定
plt.ylabel("Arg $(1/H)$ [deg]", fontsize=11) # y軸のラベル設定
plt.xscale('log') # log スケール
for i in range(n_n):
    plt.plot(omega, -hh_deg[i,:], label=f"$N=${nn[i]:2d}", marker = '.', linewidth=0)
plt.legend(ncol=1, loc='lower left', fancybox=False, frameon = True, fontsize=9)

plt.subplot(3, 1, 3)
plt.grid(color = "gray", linestyle="--")
plt.minorticks_on() # #補助目盛りをつける
plt.xlim(0.01, 10.0) # x軸範囲の設定
plt.xticks(fontsize=11)
plt.xlabel("$\Omega$", fontsize=11) # x軸のラベル設定
plt.ylim(0.0, 50.0) # y軸範囲の設定
plt.yticks(np.arange(0.0, 60.0, step=10.0), fontsize=11)
plt.ylabel("Reflection loss [dB]", fontsize=11) # y軸のラベル設定
plt.xscale('log') # log スケール
for i in range(n_n):
#    plt.plot(omega, hh2_db[i,:], label=f"$N=${nn[i]:2d}")
#    plt.plot(omega, gg2_db[i,:], label=f"$1/|\Gamma|^2: N=${nn[i]:2d}")
#    plt.plot(omega, hh_db[i,:], label=f"$|H|^2: N=${nn[i]:2d}")
    plt.plot(omega, ggi_db[i,:], label=f"$1/|\Gamma|^2: N=${nn[i]:2d}")
plt.legend(ncol=1, loc='upper left', fancybox=False, frameon = True, fontsize=9)
plt.tight_layout()
plt.show()
No description has been provided for this image

挿入損失,位相特性,反射損失¶

In [23]:
hh_amp,hh_db,hh_deg = dbdeg(hh,1)
In [24]:
fig2 = plt.figure(figsize=(9, 6)) # グラフ領域の作成
plt.subplot(2, 2, 1) # 左上側の図
plt.grid(color = "gray", linestyle="--")
plt.minorticks_on() # #補助目盛りをつける
plt.xlim(0.0, 2.0) # x軸範囲の設定
plt.xticks(np.arange(0.0, 2.5, step=0.5), fontsize=11)
plt.xlabel("$\Omega$", fontsize=11) # x軸のラベル設定
plt.ylim(0.0, 3.0) # y軸範囲の設定
plt.yticks(np.arange(0.0, 3.5, step=0.5), fontsize=11)
plt.ylabel("$|H|^2$ [dB]", fontsize=11) # y軸のラベル設定
for i in range(n_n):
    plt.plot(omega, hh2_db[i,:], label=f"$N=${nn[i]:2d}")
#    plt.plot(omega, gg2_amp[i,:], label=f"$1/|\Gamma|^2: N=${nn[i]:2d}")
plt.legend(ncol=1, loc='upper right', fancybox=False, frameon = True, fontsize=11)

plt.subplot(2, 2, 2) # 右上の図
plt.grid(color = "gray", linestyle="--")
plt.minorticks_on() # #補助目盛りをつける
plt.xlim(0.0, 2.0) # x軸範囲の設定
plt.xticks(np.arange(0.0, 2.5, step=0.5), fontsize=11)
plt.xlabel("$\Omega$", fontsize=11) # x軸のラベル設定
plt.ylim(0.0, 40.0) # y軸範囲の設定
plt.yticks(np.arange(0.0, 50.0, step=10.0), fontsize=11)
plt.ylabel("$|H|^2$ [dB]", fontsize=8) # y軸のラベル設定
for i in range(n_n):
    plt.plot(omega, hh2_db[i,:], label=f"$N=${nn[i]:2d}")
#    plt.plot(omega, gg2_db[i,:], label=f"$1/|\Gamma|^2: N=${nn[i]:2d}")
plt.legend(ncol=1, loc='upper left', fancybox=False, frameon = True, fontsize=11)
plt.tight_layout()

plt.subplot(2, 2, 3) # 左下側の図
plt.grid(color = "gray", linestyle="--")
plt.minorticks_on() # #補助目盛りをつける
plt.xlim(0.0, 2.0) # x軸範囲の設定
plt.xticks(np.arange(0.0, 2.5, step=0.5), fontsize=11)
plt.ylim(-1440.0, 180.0) # y軸範囲の設定
plt.yticks(np.arange(-1440.0, 360, step=180.0), fontsize=11)
plt.xlabel("$\Omega$", fontsize=11) # x軸のラベル設定
plt.ylabel("Arg $(1/H)$ [deg]", fontsize=11) # y軸のラベル設定
for i in range(n_n):
    plt.plot(omega, -hh_deg[i,:], label=f"$N=${nn[i]:2d}", marker = '.', linewidth=0)
plt.legend(ncol=1, loc='lower left', fancybox=False, frameon = True, fontsize=11)
plt.tight_layout()

plt.subplot(2, 2, 4) # 右下の図
plt.grid(color = "gray", linestyle="--")
plt.minorticks_on() # #補助目盛りをつける
plt.xlim(0.0, 2.0) # x軸範囲の設定
plt.xticks(np.arange(0.0, 2.5, step=0.5), fontsize=11)
plt.xlabel("$\Omega$", fontsize=11) # x軸のラベル設定
plt.ylim(0.0, 40.0) # y軸範囲の設定
plt.yticks(np.arange(0.0, 50.0, step=10.0), fontsize=11)
plt.ylabel("$1/|\Gamma|^2$ [dB]", fontsize=11) # y軸のラベル設定
for i in range(n_n):
    plt.plot(omega, gg2_db[i,:], label=f"$N=${nn[i]:2d}")
plt.legend(ncol=1, loc='upper right', fancybox=False, frameon = True, fontsize=11)
plt.tight_layout()
plt.show()
No description has been provided for this image

$s_n$の位置¶

In [25]:
n = nn[1]
n
Out[25]:
5
In [26]:
if ic == 1:
    ssn = maximally_flat_ssn(n,omega_t)
elif ic == 2: 
    ssn, sh1, ch1 = chebyshev_ssn(n,rwdb,omega_t)
In [27]:
if ic==1:
    n_th = 361
    th = np.linspace(0.0, 2.0*np.pi, n_th)
    cir = np.exp(1.0j*th)
    s_param = cir.reshape(-1, 1, 1)  # (n_freqs, 1, 1)
    p5 = rf.Network(f=np.ones(n_th), s=s_param, z0=np.ones(n_th))
elif ic==2:
    n_xp = 201
    x_daen = np.linspace(-sh1, sh1, n_xp)
    y_daen = np.sqrt(1.0-x_daen**2/sh1**2)*ch1
    xy_daen1 = x_daen + 1.0j*y_daen
    x_daen = np.linspace(sh1, -sh1, n_xp)
    y_daen = np.sqrt(1.0-x_daen**2/sh1**2)*ch1
    xy_daen2 = x_daen - 1.0j*y_daen
    daen = np.concatenate((xy_daen1, xy_daen2))  # 上下の半楕円を連結
    s_param = daen.reshape(-1, 1, 1)  # (n_freqs, 1, 1)
    p5 = rf.Network(f=np.ones(len(daen)), s=s_param, z0=np.ones(len(daen)))
In [28]:
with plt.style.context('seaborn-v0_8-ticks'):
    fig3, ax = plt.subplots(figsize=(6, 6))
    
    # 軌跡(p5)を描画
    s_data = p5.s[:, 0, 0]  # shape: (n_freqs,)
    ax.plot(s_data.real, s_data.imag, linewidth=1, label='')  # 凡例付き
    
    # 離散点(ssn[i])をプロットして凡例を設定
    for i in range(len(ssn)):
        point = ssn[i]
        i1 = i+1
        ax.plot(point.real, point.imag,
                marker='o', markersize=7, linewidth=0,
                label=f'$s_{i1}$')  # 任意のラベル
    
    ax.set_aspect('equal')  # 円が歪まないように
    ax.set_xlabel('Real Part', fontsize=11)
    ax.set_ylabel('Imaginary Part', fontsize=11)
    ax.tick_params(labelsize=11)
    ax.set_xlim([-1.6, 1.6])
    ax.set_ylim([-1.6, 1.6])
    ax.grid(color="gray", linestyle="--")
    ax.legend(ncol=1, loc='best', fancybox=False, frameon = True, fontsize=13) # 凡例を表示
plt.show()
No description has been provided for this image

スミス図表(反射係数)¶

In [29]:
n_w2 = n_w
fig4 = plt.figure(figsize=(9, 9))
ax = plt.subplot(1, 1, 1)
rf.plotting.smith(ax=ax, chart_type='zy', draw_labels=True)  # smith座標系の準備

colors = plt.cm.tab10.colors  # 10色までの色分け
labels = []  # 凡例ラベル格納用

for i in range(n_n):
    s_param = gg[i, :].reshape(-1, 1, 1)
    p3 = rf.Network(f=omega, s=s_param[:n_w2], z0=np.ones(n_w2))
    data = p3.s[:, 0, 0]  # 1ポートの反射係数(complex)
    
    line, = ax.plot(data.real, data.imag, linewidth=2, color=colors[i % 10])  # プロット
    line.set_label(f'$N= {nn[i]}$')  # ラベル設定

plt.legend(ncol=1, loc='best', fancybox=False, frameon = True, fontsize=12) # 凡例を表示
Out[29]:
<matplotlib.legend.Legend at 0x31bacad10>
No description has been provided for this image
In [30]:
if ic == 1:
    fig1.savefig('maximally_flat_amp_ph_n_.pdf')
    fig2.savefig('maximally_flat_loss_n_.pdf')
    fig3.savefig('maximally_flat_sn.pdf')
    fig4.savefig('maximally_flat_smith_chart_n_.pdf')
elif ic ==2:
    fig1.savefig('equal_ripple_amp_ph_n_.pdf')
    fig2.savefig('equal_ripple_loss_n_.pdf')
    fig3.savefig('equal_ripple_sn.pdf')
    fig4.savefig('equal_ripple_smith_chart_n_.pdf')
In [ ]: