def test_from_zpk(self): # 1st order low-pass filter: H(s) = 0.3 / (z - 0.2), system_ZPK = dlti([],[0.2],0.3) system_TF = dlti(0.3, [1, -0.2]) w = [0.1, 1, 10, 100] w1, H1 = dfreqresp(system_ZPK, w=w) w2, H2 = dfreqresp(system_TF, w=w) assert_almost_equal(H1, H2)
def test_pole_one(self): # Test that freqresp() doesn't fail on a system with a pole at 0. # integrator, pole at zero: H(s) = 1 / s system = TransferFunction([1], [1, -1], dt=0.1) with warnings.catch_warnings(): warnings.simplefilter("ignore", RuntimeWarning) w, H = dfreqresp(system, n=2) assert_equal(w[0], 0.) # a fail would give not-a-number
def test_from_state_space(self): # H(z) = 2 / z^3 - 0.5 * z^2 system_TF = dlti([2], [1, -0.5, 0, 0]) A = np.array([[0.5, 0, 0], [1, 0, 0], [0, 1, 0]]) B = np.array([[1, 0, 0]]).T C = np.array([[0, 0, 2]]) D = 0 system_SS = dlti(A, B, C, D) w = 10.0**np.arange(-3, 0, .5) with suppress_warnings() as sup: sup.filter(BadCoefficients) w1, H1 = dfreqresp(system_TF, w=w) w2, H2 = dfreqresp(system_SS, w=w) assert_almost_equal(H1, H2)
def test_freq_range(self): # Test that freqresp() finds a reasonable frequency range. # 1st order low-pass filter: H(z) = 1 / (z - 0.2), # Expected range is from 0.01 to 10. system = TransferFunction(1, [1, -0.2], dt=0.1) n = 10 expected_w = np.linspace(0, np.pi, 10, endpoint=False) w, H = dfreqresp(system, n=n) assert_almost_equal(w, expected_w)
def test_pole_one(self): # Test that freqresp() doesn't fail on a system with a pole at 0. # integrator, pole at zero: H(s) = 1 / s system = TransferFunction([1], [1, -1], dt=0.1) with suppress_warnings() as sup: sup.filter(RuntimeWarning, message="divide by zero") sup.filter(RuntimeWarning, message="invalid value encountered") w, H = dfreqresp(system, n=2) assert_equal(w[0], 0.) # a fail would give not-a-number
def test_from_state_space(self): # H(z) = 2 / z^3 - 0.5 * z^2 system_TF = dlti([2], [1, -0.5, 0, 0]) A = np.array([[0.5, 0, 0], [1, 0, 0], [0, 1, 0]]) B = np.array([[1, 0, 0]]).T C = np.array([[0, 0, 2]]) D = 0 system_SS = dlti(A, B, C, D) w = 10.0**np.arange(-3,0,.5) with warnings.catch_warnings(): warnings.simplefilter("ignore", BadCoefficients) w1, H1 = dfreqresp(system_TF, w=w) w2, H2 = dfreqresp(system_SS, w=w) assert_almost_equal(H1, H2)
def test_manual(self): # Test dfreqresp() real part calculation (manual sanity check). # 1st order low-pass filter: H(z) = 1 / (z - 0.2), system = TransferFunction(1, [1, -0.2], dt=0.1) w = [0.1, 1, 10] w, H = dfreqresp(system, w=w) # test real expected_re = [1.2383, 0.4130, -0.7553] assert_almost_equal(H.real, expected_re, decimal=4) # test imag expected_im = [-0.1555, -1.0214, 0.3955] assert_almost_equal(H.imag, expected_im, decimal=4)
def test_auto(self): # Test dfreqresp() real part calculation. # 1st order low-pass filter: H(z) = 1 / (z - 0.2), system = TransferFunction(1, [1, -0.2], dt=0.1) w = [0.1, 1, 10, 100] w, H = dfreqresp(system, w=w) jw = np.exp(w * 1j) y = np.polyval(system.num, jw) / np.polyval(system.den, jw) # test real expected_re = y.real assert_almost_equal(H.real, expected_re) # test imag expected_im = y.imag assert_almost_equal(H.imag, expected_im)
t = t1 * t2 * t3 tf = algebra.conseguir_tf(t, s) k = 1e3 fs = 20 * k tf2 = signal.dlti(*signal.bilinear(tf.num, tf.den, fs)) w_range = linspace(0, fs, 100000) * 2 * pi w, h = signal.freqresp(tf, w_range) w2, h2 = signal.dfreqresp(tf2, w_range / fs) f = w / 2 / pi f2 = w2 / 2 / pi CombinedPlot() \ .setTitle("Legendre") \ .setXTitle("Frecuencia (hz)") \ .setYTitle("Amplitud (Db)") \ .addSignalPlot( signal=Senial.Senial( f, 20 * log10(abs(h)) ), color="red", name="Analógica" ) \
# Generating the Nyquist plot of a transfer function from scipy import signal import matplotlib.pyplot as plt # Transfer function: H(z) = 1 / (z^2 + 2z + 3) sys = signal.TransferFunction([1], [1, 2, 3], dt=0.05) w, H = signal.dfreqresp(sys) plt.figure() plt.plot(H.real, H.imag, "b") plt.plot(H.real, -H.imag, "r") plt.show()
# make the panes transparent ax.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0)) ax.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0)) ax.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0)) plt.xlabel("Im(z)") plt.ylabel("Re(z)") plt.savefig("../fig/z_plane_%d.png" % indice) # Réponse impulsionnelle plt.figure() t, yout = sig.dimpulse(tf_temp, n=30) plt.stem(t, yout[0]) np.savetxt("../csv/ri_%d.txt" % indice, yout[0], delimiter=',') # Réponse frequentielle w, h = sig.dfreqresp(tf_temp, n=200) amp = abs(h) angles = np.unwrap(np.angle(h)) M = np.matrix([w, amp, angles]).T plt.figure() plt.plot(w, amp) plt.figure() plt.plot(w, angles) np.savetxt("../csv/rf_%d.txt" % indice, M, delimiter=',') #reponse à une sinusoide output = sig.lfilter(tf_temp.num, tf_temp.den, input) M = np.array([n_vect, input, output]).T np.savetxt("../csv/r_sine_%d.txt" % indice, M, delimiter=',')
plt.show() plot_dbode_ML(b_coef_traces[:, -1::-1], f_coef_traces[:, -1::-1], b_true.flatten(), f_true.flatten(), B_ML.flatten(), F_ML.flatten(), B_ML2.flatten(), F_ML2.flatten(), Ts, w_plot, save=True) import scipy.signal as signal w, _ = signal.dfreqresp((b_true.flatten(), f_true.flatten(), Ts)) # plot_d_nyquist(b_coef_traces[:,-1::-1],f_coef_traces[:,-1::-1],b_true.flatten(),f_true.flatten(),B_unit.flatten(),F_unit.flatten(),Ts,w, no_plot=300,xlims=[-2.75, 1.5], ylims=[-2,2], save='figures/oe_nyquist.png') plot_d_nyquist(b_coef_traces[:, -1::-1], f_coef_traces[:, -1::-1], b_true.flatten(), f_true.flatten(), B_ML2.flatten(), F_ML2.flatten(), Ts, w, no_plot=300, xlims=[-2.75, 1.5], ylims=[-2, 2], save='figures/oe_nyquist.png') # b_mean = np.mean(b_coef_traces,axis=0)
Hs = (s_ * R_ * C_) / (s_**2 * L_ * C_ + s_ * R_ * C_ + 1) print("H(s)=", Hs) Hz = Hs.copy().subs(s_, 2 / T_ * (z_ - 1) / (z_ + 1)) print("H(z)=", Hz.cancel().collect(z_)) systemD = signal.cont2discrete((system.num, system.den), 1 / Fs, method='bilinear') systemD = (systemD[0][0], systemD[1], systemD[2]) plt.figure(figsize=(8, 3)) plt.subplot(121) w = 2 * np.pi * np.linspace(100, 2e4, 50000) / Fs _, gd = signal.group_delay(systemD[:2], w=w) # calculate group delay _, H = signal.dfreqresp(systemD, w=w) # calculate frequency response # calculate phase and group delay at the specific frequencies indf0 = np.argmin(abs(w - 2 * np.pi * f0 / Fs)) indf1 = np.argmin(abs(w - 2 * np.pi * f1 / Fs)) tau_gf0 = gd[indf0] * 1000 / Fs tau_gf1 = gd[indf1] * 1000 / Fs tau_phif0 = (-np.angle(H[indf0]) / w[indf0] / Fs * 1000) tau_phif1 = (-np.angle(H[indf1]) / w[indf1] / Fs * 1000) plt.plot(w / (2 * np.pi) * Fs, gd / Fs * 1000, 'navy') plt.grid(True) plt.xlabel('$f$ [Hz]') plt.ylabel(r'$\tau_g$ [ms]') plt.title("Group Delay") plt.axhline(tau_gf0, color='r', ls='dashed')
def calcularPlotImpinvar(f0, fs, mode="butter", n=4, filename="out.png", title="noTitle"): w0 = 2 * pi * f0 print("f0 = ", f0) if mode == "butter": b, a = signal.butter(n, w0, 'low', analog=True) elif mode == "cheby": b, a = signal.cheby1(n, 1, w0, 'low', analog=True) sys = signal.lti(b, a) w_range = linspace(0, fs, 100000) * 2 * pi w, h = signal.freqresp(sys, w_range) # signal.freqs(b, a, 100000) w_m2 = -1 for i in range(len(w)): if 20 * log10(abs(h[i])) <= -2 and w_m2 == -1: w_m2 = w[i] if mode == "butter": b, a = signal.butter(n, w0 * (w0 / w_m2), 'low', analog=True) elif mode == "cheby": b, a = signal.cheby1(n, 1, w0 * (w0 / w_m2), 'low', analog=True) sys = signal.lti(b, a) sys_original = sys w, h = signal.freqresp(sys, w_range) f = w / 2 / pi b2, a2 = impinvar_causal(b, a, fs=fs, tol=0.0001) sys = signal.dlti(b2, a2) w2, h2 = signal.dfreqresp(sys, w_range / fs) factor = h[0] / h2[0] sys = signal.dlti(b2 / factor, a2) f2 = w2 / 2 / pi * fs CombinedPlot() \ .setTitle(title) \ .setXTitle("Frecuencia (hz)") \ .setYTitle("Amplitud (Db)") \ .addSignalPlot( signal=Senial.Senial( f, 20 * log10(abs(h)) ), color="red", name="Analógica" ).addSignalPlot( signal=Senial.Senial( f2, 20 * log10(abs(h2) * factor) ), color="blue", name="Digital método invariante al impulso" ).plot().save("output/" + filename)
""" Impulse Invariance""" num = np.array([0.000000000001, 0.00931, 0.000000000001]) den = np.array([1, -1.8588, 0.8681]) H = sig.TransferFunction(num, den, dt=Te) print(H) """Bilinear transform""" c = wc / np.tan(wc * Te / 2) num = np.array([10000, 20000, 10000]) den = np.array([(10000 - 200 * c * np.cos(3 * np.pi / 4) + c * c), (20000 - 2 * c * c), (10000 + 200 * c * np.cos(3 * np.pi / 4) + c * c)]) H2 = sig.TransferFunction(num, den, dt=Te) # Affichage w_vect = np.logspace(1, 3.49, 1000) w, Hij = sig.dfreqresp(H, w=w_vect * Te) wb, Hbj = sig.dfreqresp(H2, w=w_vect * Te) wa, Haj = sig.freqresp(Ha, w=w_vect) plt.semilogx(wa, 20 * np.log10(np.abs(Hij))) plt.semilogx(wa, 20 * np.log10(np.abs(Hbj))) plt.semilogx(wa, 20 * np.log10(np.abs(Haj))) plt.figure() plt.semilogx(wa, np.unwrap(np.angle(Hij))) plt.semilogx(wa, np.unwrap(np.angle(Hbj))) plt.semilogx(wa, np.angle(Haj)) M = np.matrix([ wa, 20 * np.log10(np.abs(Haj)), 20 * np.log10(np.abs(Hij)), 20 * np.log10(np.abs(Hbj))
resbrute = optimize.brute(cost_function, rranges, full_output=True, finish=optimize.fmin) print(resbrute[0]) x0 = resbrute[0] res = minimize(cost_function, x0) omega = res.x print(omega) num, den = extract_num_den(omega) H = sig.TransferFunction(num, den, dt=Te) w_vect = np.logspace(1, 3.49, 100) wb, Hj = sig.dfreqresp(H, w=w_vect * Te) t, rit = sig.dimpulse(H, n=200) plt.figure() plt.plot(np.ravel(rit)) plt.figure() plt.semilogx(w_vect, 20 * np.log10(np.abs(Hj))) RF = np.zeros((len(w_vect), 2)) RF[:, 0] = w_vect RF[:, 1] = 20 * np.log10(np.abs(Hj)) #np.savetxt("../csv/iir_prony_rf.txt",RF,delimiter=',') plt.show()
def plot_d_nyquist(num_samples, den_samples, num_true, den_true, num_ML, den_ML, Ts, omega, no_plot=300, xlims=None, ylims=None, max_samples=1000, save=False): """plot nyquist diagram from estimated discrete time system samples and true sys""" no_samples = np.shape(num_samples)[0] no_eval = min(no_samples, max_samples) sel = np.random.choice(np.arange(no_samples), no_eval, False) omega_res = max(np.shape(omega)) H_real_samples = np.zeros((omega_res, no_eval)) H_imag_samples = np.zeros((omega_res, no_eval)) count = 0 for s in sel: den_sample = np.concatenate(([1.0], den_samples[s, :]), 0) num_sample = num_samples[s, :] w, H_samp = signal.dfreqresp((num_sample, den_sample, Ts), omega) H_real_samples[:, count] = H_samp.real H_imag_samples[:, count] = H_samp.imag # w, mag_samples[:, count], phase_samples[:, count] = signal.dbode((num_sample, den_sample, Ts), omega) count = count + 1 # calculate the true bode diagram # plot the true bode diagram w, H_true = signal.dfreqresp((num_true.flatten(), den_true.flatten(), Ts), omega) w, H_ML = signal.dfreqresp((num_ML.flatten(), den_ML.flatten(), Ts), omega) # plot the samples plt.subplot(1, 1, 1) h2, = plt.plot(H_real_samples[:, 0], H_imag_samples[:, 0], color='green', alpha=0.1, label='hmc samples') # Bode magnitude plot plt.plot(H_real_samples[:, 1:no_plot], H_imag_samples[:, 1:no_plot], color='green', alpha=0.1) # Bode magnitude plot # plt.plot(H_real_samples[:,:no_plot], -H_imag_samples[:,:no_plot], color='green', alpha=0.1) # Bode magnitude plot h1, = plt.plot(H_true.real, H_true.imag, color='blue', label='True system') # Bode magnitude plot # plt.plot(H_true.real, -H_true.imag, color='blue') # Bode magnitude plot h_ML, = plt.plot(H_ML.real, H_ML.imag, '--', color='purple', label='ML Estimate') # Bode magnitude plot # plt.plot(H_ML.real, -H_ML.imag,'--', color='purple') # Bode magnitude plot hm, = plt.plot(np.mean(H_real_samples, axis=1), np.mean(H_imag_samples, axis=1), '-.', color='orange', label='hmc mean') # Bode magnitude plot # plt.plot(np.mean(H_real_samples,axis=1), -np.mean(H_imag_samples,axis=1), '-.', color='orange') # Bode magnitude plot plt.xlabel('Real') plt.ylabel('Imaginary') if xlims is not None: plt.xlim(xlims) if ylims is not None: plt.ylim(ylims) plt.legend(handles=[h1, h2, hm, h_ML]) if save is not None: plt.savefig(save, format='png') plt.show()
def calcularPlotMatchedZ(f0, fs, mode="butter", n=4, filename="out.png", title="noTitle"): w0 = 2 * pi * f0 if mode == "butter": b, a = signal.butter(n, w0, 'low', analog=True) elif mode == "cheby": b, a = signal.cheby1(n, 1, w0, 'low', analog=True) sys = signal.lti(b, a) w_range = linspace(0, fs, 100000) * 2 * pi w, h = signal.freqresp(sys, w_range) # signal.freqs(b, a, 100000) w_m2 = -1 for i in range(len(w)): if 20 * log10(abs(h[i])) <= -2 and w_m2 == -1: w_m2 = w[i] if mode == "butter": b, a = signal.butter(n, w0 * (w0 / w_m2), 'low', analog=True) elif mode == "cheby": b, a = signal.cheby1(n, 1, w0 * (w0 / w_m2), 'low', analog=True) sys = signal.lti(b, a) w, h = signal.freqresp(sys, w_range) f = w / 2 / pi poles = sys.poles zeros = sys.zeros new_poles = exp(poles / fs) new_zeros = exp(zeros / fs) new_zeros = np.hstack([new_zeros, [-1] * n]) # print(new_poles, new_zeros) sys = signal.dlti(new_zeros, new_poles, 1) w2, h2 = signal.dfreqresp(sys, w_range / fs) f = w / 2 / pi factor = h[0] / h2[0] f2 = w2 / 2 / pi * fs CombinedPlot() \ .setTitle(title) \ .setXTitle("Frecuencia (hz)") \ .setYTitle("Amplitud (Db)") \ .addSignalPlot( signal=Senial.Senial( f, 20 * log10(abs(h)) ), color="red", name="Analógica" ) \ .addSignalPlot( signal=Senial.Senial( f2, 20 * log10(abs(h2) * factor) ), color="blue", name="Digital método invariante al impulso" ).plot().save("output/" + filename)