def _gauss_norm(self, n: int): """ Returns zeros, poles and gain of Gauss normalized approximation """ transfer_function = self._get_tf(n) trans_zpk = transfer_function.to_zpk() z, p, k = trans_zpk.zeros, trans_zpk.poles, trans_zpk.gain w, h = ss.freqs_zpk(z, p, k) norm_gd = -np.diff(np.unwrap(np.angle(h))) / np.diff(w) trans_zpk.poles = trans_zpk.poles * norm_gd[0] trans_zpk.gain = np.prod(abs(trans_zpk.poles)) return trans_zpk.zeros, trans_zpk.poles, trans_zpk.gain
def _gauss_des(self, z_n, p_n): """ Returns zeros, poles and gain of Gauss denormalized approximation """ p = p_n / (self.group_delay * 1e-3) # user's group delay in ms k = prod(abs(p)) w, h = ss.freqs_zpk([], p, k) #norm_gd = -diff(unwrap(angle(h))) / diff(w) #f_n = w / (2 * pi) #plt.semilogx(f_n[:-1], norm_gd) #plt.show() return z_n, p, k
def plot_zpk(z, p, k, fp, fs, Amax, Amin): w, h = signal.freqs_zpk(z, p, k, 2 * np.pi * np.logspace(2, 4, 500)) plt.plot(w / (2 * np.pi), 20 * np.log10(abs(h))) plt.xscale('log') plt.title('Lowpass filter fit to constraints') plt.xlabel('Frequency [Hz]') plt.ylabel('Amplitude [dB]') plt.grid(True, which='both', axis='both') plt.fill([1e2, 1e2, fp, fp], [-Amin, -Amax, -Amax, -Amin], '0.9', lw=0) # pass plt.fill([fs, fs, 1e4, 1e4], [-Amin, 0, 0, -Amin], '0.9', lw=0) # stop plt.axis([1e2, 1e4, -50, 1])
def test_freq_resp(self): # Test that frequency response meets tolerance from ITU-R BS.468-4 upper = responses + upper_limits lower = responses + lower_limits z, p, k = ITU_R_468_weighting_analog() w, h = signal.freqs_zpk(z, p, k, 2*pi*frequencies) levels = 20 * np.log10(abs(h)) if mpl: plt.figure('468') plt.title('ITU 468 weighting limits') plt.semilogx(frequencies, levels, alpha=0.7, label='analog') plt.semilogx(frequencies, upper, 'r:', alpha=0.7) plt.semilogx(frequencies, lower, 'r:', alpha=0.7) plt.grid(True, color='0.7', linestyle='-', which='major') plt.grid(True, color='0.9', linestyle='-', which='minor') plt.legend() assert all(np.less_equal(levels, upper)) assert all(np.greater_equal(levels, lower))
def test_freq_resp(self): # Test that frequency response meets tolerance from ITU-R BS.468-4 upper = responses + upper_limits lower = responses + lower_limits z, p, k = ITU_R_468_weighting_analog() w, h = signal.freqs_zpk(z, p, k, 2 * pi * frequencies) levels = 20 * np.log10(abs(h)) if mpl: plt.figure('468') plt.title('ITU 468 weighting limits') plt.semilogx(frequencies, levels, alpha=0.7, label='analog') plt.semilogx(frequencies, upper, 'r:', alpha=0.7) plt.semilogx(frequencies, lower, 'r:', alpha=0.7) plt.grid(True, color='0.7', linestyle='-', which='major') plt.grid(True, color='0.9', linestyle='-', which='minor') plt.legend() assert all(np.less_equal(levels, upper)) assert all(np.greater_equal(levels, lower))
def test_freq_resp(self): # Test that frequency response meets tolerance from ANSI S1.4-1983 for curve in {'A', 'B', 'C'}: N = len(responses[curve]) # Number of frequencies in spec f_test = frequencies[:N] upper = responses[curve] + upper_limits[:N] lower = responses[curve] + lower_limits[:N] z, p, k = ABC_weighting(curve) w, h = signal.freqs_zpk(z, p, k, 2 * pi * f_test) levels = 20 * np.log10(abs(h)) if mpl: plt.figure(curve) plt.title('{}-weighting limits (Type 0)'.format(curve)) plt.semilogx(f_test, levels, alpha=0.7, label='analog') plt.semilogx(f_test, upper, 'r:', alpha=0.7) plt.semilogx(f_test, lower, 'r:', alpha=0.7) plt.grid(True, color='0.7', linestyle='-', which='major') plt.grid(True, color='0.9', linestyle='-', which='minor') plt.legend() assert all(np.less_equal(levels, upper)) assert all(np.greater_equal(levels, lower))
1, 0.7, 1, 1, 1, 1, 1, 1, 1.5, 1.5, 1.5, 2, 2, 2.5, 3]) low1 = np.array([np.inf, np.inf, 4, 2, 1.5, 1.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.7, 1, 1, 1, 1, 1, 1, 1.5, 2, 2.5, 3, 5, 8, np.inf]) up0 = np.array([2, 2, 2, 2, 1.5, 1, 1, 1, 1, 1, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 1, 1, 1, 2, 2, 2, 2]) low0 = np.array([5, 3, 3, 2, 1.5, 1, 1, 1, 1, 1, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 1, 1.5, 2, 3, 3, 3, 3]) # FS_list = [4] for fs in FS_list: f = np.logspace(1, np.log10(30000), 1024) wn = f * 2 * np.pi/fs [ba, aa] = vf.awt_design(fs) [bc, ac] = vf.cwt_design(fs) # compute the frequency response of the analog weighting filter [wa, ha] = sg.freqs_zpk(Za, Pa, Ka, wn*fs) [wc, hc] = sg.freqs_zpk(Zc, Pc, Kc, wn*fs) [wza, hza] = sg.freqz(ba, aa, wn) [wzc, hzc] = sg.freqz(bc, ac, wn) # end for fs in FS_list hadb = 20*np.log10(np.abs(ha)) hcdb = 20*np.log10(np.abs(hc)) hzadb = 20*np.log10(np.abs(hza)) hzcdb = 20*np.log10(np.abs(hzc)) diffa = hzadb - hadb diffc = hzcdb - hcdb plt.figure(figsize=[10, 6])
def splane_eval(s): """ `s` is a value on the analog S plane. The frequency response at 10 Hz would be s = 1j*2*pi*10, for instance. """ return freqs_zpk(z, p, k, -1j * s)[1]
gs = gridspec.GridSpec(2, 3, width_ratios=[2.5, 1, 1], height_ratios=[2.5, 1]) fig = plt.figure(figsize=(9, 7)) ax_cplot = fig.add_subplot(gs[0, 0]) cplot(splane_eval, re=(-r, r), im=(-r, r), axes=ax_cplot) ax_cplot.set_xlabel('$\sigma$') ax_cplot.set_ylabel('$j \omega$') ax_cplot.axhline(0, color='white', alpha=0.15) ax_cplot.axvline(0.5, color='white', alpha=0.15) ax_cplot.set_title('S plane') ax_cplot.axis('equal') w, h = freqs_zpk(z, p, k, np.linspace(-r, r, 500)) ax_fr = fig.add_subplot(gs[0, 1], sharey=ax_cplot) ax_fr.plot(abs(h), w) ax_fr.invert_xaxis() ax_fr.tick_params( axis='y', left=False, right=True, labelleft=False, ) ax_fr.set_xlabel('Magnitude') ax_fr.grid(True, which='both') ax_ph = fig.add_subplot(gs[0, 2], sharey=ax_cplot) ax_ph.plot(np.rad2deg(np.angle(h)), w)
def s2z_zpk(s_zeros, s_poles, s_gain, s2z, fs, f0): z_zeros, z_poles, z_gain = s2z(s_zeros, s_poles, s_gain, fs=fs) z_gain *= _np.abs(_sig.freqs_zpk(s_zeros, s_poles, s_gain, worN=[2*_np.pi*f0])[1])\ / _np.abs(_sig.freqz_zpk(z_zeros, z_poles, z_gain, worN=[f0], fs=fs)[1]) return z_zeros, z_poles, z_gain
from scipy.signal import freqs_zpk, iirfilter z, p, k = iirfilter(4, [1, 10], 1, 60, analog=True, ftype='cheby1', output='zpk') w, h = freqs_zpk(z, p, k, worN=np.logspace(-1, 2, 1000)) import matplotlib.pyplot as plt plt.semilogx(w, 20 * np.log10(abs(h))) plt.xlabel('Frequency') plt.ylabel('Amplitude response [dB]') plt.grid() plt.show()
return z * wc, p * wc, k # shelving filter N = 4 f_cutoff = 1000 w_cutoff = 2 * np.pi * f_cutoff Gd = -12 z, p, k = higher_order_shelving_holters(Gd, N, wc=w_cutoff, normalize=True) b, a = zpk2tf(z, p, k) # frequency response fmin, fmax, num_f = 20, 22000, 2000 f = np.logspace(np.log10(fmin), np.log10(fmax), num=num_f, endpoint=True) w = 2 * np.pi * f _, H_zpk = freqs_zpk(z, p, k, worN=w) _, gd_zpk = zpk_group_delays(z, p, k, w=w) _, H_tf = freqs(b, a, worN=w) _, gd_tf = group_delays(b, a, w=w) gd_zorp = 0 # adding up group delays of individual zeros and poles for z_i in z: gd_zorp += zorp_group_delays(z_i, w=w)[1] for p_i in p: gd_zorp -= zorp_group_delays(p_i, w=w)[1] # plots kw_zpk = dict(color='lightgray', lw=5, ls='-', alpha=1, label='zpk') kw_tf = dict(color='C0', lw=2, ls='-', alpha=0.85, label='tf') kw_zorp = dict(color='k', lw=2, ls=':', alpha=0.85, label='zorp') flim = fmin, fmax
from scipy import signal import matplotlib.pyplot as plt fs = 100 bf = 2 * np.pi * np.array([7, 13]) filts = signal.lti(*signal.butter(4, bf, btype='bandpass', analog=True, output='zpk')) filtz = signal.lti(*signal.bilinear_zpk(filts.zeros, filts.poles, filts.gain, fs)) wz, hz = signal.freqz_zpk(filtz.zeros, filtz.poles, filtz.gain) ws, hs = signal.freqs_zpk(filts.zeros, filts.poles, filts.gain, worN=fs*wz) plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hz).clip(1e-15)), label=r'$|H(j \omega)|$') plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hs).clip(1e-15)), label=r'$|H_z(e^{j \omega})|$') plt.legend() plt.xlabel('Frequency [Hz]') plt.ylabel('Magnitude [dB]') plt.grid()
def hoge(exc, hor): fname = './OSTM_TM_{0}_EXC.xml'.format(exc) data = DiagAccess(fname) hor1 = data.xfer('K1:VIS-OSTM_TM_DAMP_L_IN1', 'K1:VIS-OSTM_TM_TEST_{0}_EXC'.format(exc)).xfer hor2 = data.xfer('K1:VIS-OSTM_TM_DAMP_P_IN1', 'K1:VIS-OSTM_TM_TEST_{0}_EXC'.format(exc)).xfer hor3 = data.xfer('K1:VIS-OSTM_TM_DAMP_Y_IN1', 'K1:VIS-OSTM_TM_TEST_{0}_EXC'.format(exc)).xfer w = data.xfer('K1:VIS-OSTM_TM_DAMP_L_IN1', 'K1:VIS-OSTM_TM_TEST_{0}_EXC'.format(exc)).FHz # def p(w0, Q): p1 = -w0 / (2 * Q) + 1j * np.sqrt((w0)**2 - w0**2 / (4 * Q**2)) p2 = -w0 / (2 * Q) - 1j * np.sqrt((w0)**2 - w0**2 / (4 * Q**2)) return [p1, p2] # for H1_EXC if hor == 'L': w0, Q0, k0 = 1.3, 4, 1.0e-0 # Len w1, Q1, k1 = 8, 5, 1.0e-1 # w2, Q2, k2 = 15, 50, -1.0e-0 # Len w3, Q3, k3 = 20, 20, 1.0e-4 # w4, Q4, k4 = 15, 20, 3.0e-4 # w5, Q5, k5 = 17, 20, 2.0e-4 # elif hor == 'P': w0, Q0, k0 = 1.3, 4, 1.5e-0 w1, Q1, k1 = 8, 5, -1.0e-4 w2, Q2, k2 = 20, 7, 2.0e-4 w3, Q3, k3 = 20, 20, 2.0e-4 # w4, Q4, k4 = 15, 20, 1.0e-4 # w5, Q5, k5 = 17, 20, -1.0e-4 # elif hor == 'Y': w0, Q0, k0 = 1.3, 4, 1.0e-0 w1, Q1, k1 = 8, 5, -8.0e-4 w2, Q2, k2 = 20, 7, 1.5e-4 w3, Q3, k3 = 20, 20, -1.0e-4 # w4, Q4, k4 = 15, 20, 1.0e-4 # w5, Q5, k5 = 17, 20, -7.0e-4 # else: pass _w1, h1 = freqs_zpk([], p(w0, Q0), k0, w) _w2, h2 = freqs_zpk([], p(w1, Q1), k1, w) _w3, h3 = freqs_zpk([], p(w2, Q2), k2, w) _w4, h4 = freqs_zpk([], p(w3, Q3), k3, w) _w5, h5 = freqs_zpk([], p(w4, Q4), k4, w) _w6, h6 = freqs_zpk([], p(w5, Q5), k5, w) # unknown Delay if hor == 'L': _w1, delay = freqs_zpk([-0.46], [-12.3], -7, w) # de-white _w1, delay = freqs_zpk( [-0.1], [-10], -8, w) # de-white and minus sign caused from dtt2hdf else: _w1, delay = freqs_zpk([-0.46], [-12.3], -7, w) # de-white _w1, delay = freqs_zpk([-0.1], [-10], -8, w) # de-white _w, h = _w1, (h1 + h2 + h3 + h4 + h5 + h6) * delay _w, h = _w1, (h1 + h2 + h3) * delay if hor == 'L': hor1 = hor1 coh = data.xfer('K1:VIS-OSTM_TM_DAMP_L_IN1', 'K1:VIS-OSTM_TM_TEST_{0}_EXC'.format(exc)).coh elif hor == 'P': hor1 = hor2 coh = data.xfer('K1:VIS-OSTM_TM_DAMP_P_IN1', 'K1:VIS-OSTM_TM_TEST_{0}_EXC'.format(exc)).coh elif hor == 'Y': hor1 = hor3 coh = data.xfer('K1:VIS-OSTM_TM_DAMP_Y_IN1', 'K1:VIS-OSTM_TM_TEST_{0}_EXC'.format(exc)).coh else: pass return w, hor1, w1, _w1, h1, _w2, h2, _w3, h3, _w4, h4, _w5, h5, _w6, h6, _w, h, coh
def hoge(exc, hor): fname = './measurements/OSTM_TM_{0}_EXC.xml'.format(exc) data = DiagAccess(fname) hor1 = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H1_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).xfer hor2 = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H2_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).xfer hor3 = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H3_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).xfer hor4 = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H4_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).xfer w = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H1_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).FHz # def p(w0, Q): p1 = -w0 / (2 * Q) + 1j * np.sqrt((w0)**2 - w0**2 / (4 * Q**2)) p2 = -w0 / (2 * Q) - 1j * np.sqrt((w0)**2 - w0**2 / (4 * Q**2)) return [p1, p2] # for H1_EXC if hor == 'H1': w0, Q0, k0 = 1.3, 4, 1.5e-1 # Len w1, Q1, k1 = 8, 5, 3.0e-2 # w2, Q2, k2 = 15, 30, 1.0e-2 # Len w3, Q3, k3 = 20, 20, 1.0e-4 # w4, Q4, k4 = 15, 20, 3.0e-4 # w5, Q5, k5 = 17, 20, 2.0e-4 # elif hor == 'H2': w0, Q0, k0 = 1.3, 4, 1.5e-1 w1, Q1, k1 = 8, 5, -1.0e-1 w2, Q2, k2 = 20, 7, 2.0e-4 w3, Q3, k3 = 20, 20, 2.0e-4 # w4, Q4, k4 = 15, 20, 1.0e-4 # w5, Q5, k5 = 17, 20, -1.0e-4 # elif hor == 'H3': w0, Q0, k0 = 1.3, 4, 1.5e-1 w1, Q1, k1 = 8, 5, -8.0e-3 w2, Q2, k2 = 20, 7, 1.5e-4 w3, Q3, k3 = 20, 20, -1.0e-4 # w4, Q4, k4 = 15, 20, 1.0e-4 # w5, Q5, k5 = 17, 20, -7.0e-4 # elif hor == 'H4': w0, Q0, k0 = 1.3, 4, 1.5e-1 # Len w1, Q1, k1 = 8, 5, 1.5e-3 # w2, Q2, k2 = 20, 7, 3.5e-4 # Len w3, Q3, k3 = 20, 20, -3.0e-4 # w4, Q4, k4 = 15, 20, 3.5e-4 # w5, Q5, k5 = 17, 20, -4.5e-4 # else: pass _w1, h1 = freqs_zpk([], p(w0, Q0), k0, w) _w2, h2 = freqs_zpk([], p(w1, Q1), k1, w) _w3, h3 = freqs_zpk([], p(w2, Q2), k2, w) _w4, h4 = freqs_zpk([], p(w3, Q3), k3, w) _w5, h5 = freqs_zpk([], p(w4, Q4), k4, w) _w6, h6 = freqs_zpk([], p(w5, Q5), k5, w) # unknown Delay if hor == 'H3': _w1, delay = freqs_zpk([-0.46], [-12.3], -7, w) # de-white #_w1,delay = freqs_zpk([-0.5],[-1],-8,w) # de-white and minus sign caused from dtt2hdf else: _w1, delay = freqs_zpk([-0.46], [-12.3], -7, w) # de-white #_w1,delay = freqs_zpk([-0.5],[-1],-8,w) # de-white _w, h = _w1, (h1 + h2 + h3 + h4 + h5 + h6) * delay if hor == 'H1': hor1 = hor1 coh = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H1_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).coh elif hor == 'H2': hor1 = hor2 coh = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H2_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).coh elif hor == 'H3': hor1 = hor3 coh = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H3_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).coh elif hor == 'H4': hor1 = hor4 coh = data.xfer('K1:VIS-OSTM_TM_OSEMINF_H4_IN1_DQ', 'K1:VIS-OSTM_TM_COILOUTF_{0}_EXC'.format(exc)).coh else: pass return w, hor1, w1, _w1, h1, _w2, h2, _w3, h3, _w4, h4, _w5, h5, _w6, h6, _w, h, coh
set_rcparams() outdir = set_outdir() wc = 2**0 Gd = -12 max_order = 6 orders = np.arange(1, max_order + 1) wmin, wmax, num_w = 2**-9.5, 2**4.5, 1000 w = np.logspace(np.log10(wmin), np.log10(wmax), num=num_w) H = np.zeros((max_order, len(w)), dtype='complex') for i, M in enumerate(orders): zpk = higher_order_shelving_holters(Gd, M, wc=wc, normalize=True) H[i] = freqs_zpk(*zpk, worN=w)[1] z, p, _ = zpk wlim = w[0], w[-1] wticks = 2**(np.arange( np.ceil(np.log2(w)[0] / 4) * 4, np.floor(np.log2(w[-1]) / 4) * 4 + 4, 4)) kw = dict(linewidth=2, alpha=1, basex=2) kw_z = dict(c='C0', marker='o', ms=9, ls='none', mew=1, mfc='none', alpha=1) kw_p = dict(c='k', marker='x', ms=9, ls='none', mew=1) kw_artist = dict(edgecolor='gray', linestyle=':', linewidth=1) colors = [ cm.get_cmap('Oranges')(x)[:3] for x in np.linspace(0.33, 1, num=max_order, endpoint=False) ]