def test_lti_instantiation(self): # Test that lti can be instantiated with sequences, scalars. # See PR-225. # TransferFunction s = lti([1], [-1]) assert_(isinstance(s, TransferFunction)) assert_(isinstance(s, lti)) assert_(not isinstance(s, dlti)) assert_(s.dt is None) # ZerosPolesGain s = lti(np.array([]), np.array([-1]), 1) assert_(isinstance(s, ZerosPolesGain)) assert_(isinstance(s, lti)) assert_(not isinstance(s, dlti)) assert_(s.dt is None) # StateSpace s = lti([], [-1], 1) s = lti([1], [-1], 1, 3) assert_(isinstance(s, StateSpace)) assert_(isinstance(s, lti)) assert_(not isinstance(s, dlti)) assert_(s.dt is None)
def test_from_zpk(self): # 4th order low-pass filter: H(s) = 1 / (s + 1) system = lti([], [-1] * 4, [1]) w = [0.1, 1, 10, 100] w, H = freqresp(system, w=w) s = w * 1j expected = 1 / (s + 1)**4 assert_almost_equal(H.real, expected.real) assert_almost_equal(H.imag, expected.imag)
def test_freq_range(self): # Test that freqresp() finds a reasonable frequency range. # 1st order low-pass filter: H(s) = 1 / (s + 1) # Expected range is from 0.01 to 10. system = lti([1], [1, 1]) n = 10 expected_w = np.logspace(-2, 1, n) w, H = freqresp(system, n=n) assert_almost_equal(w, expected_w)
def test_05(self): # Test that bode() finds a reasonable frequency range. # 1st order low-pass filter: H(s) = 1 / (s + 1) system = lti([1], [1, 1]) n = 10 # Expected range is from 0.01 to 10. expected_w = np.logspace(-2, 1, n) w, mag, phase = bode(system, n=n) assert_almost_equal(w, expected_w)
def test_output(self): # Test freqresp() output calculation. # 1st order low-pass filter: H(s) = 1 / (s + 1) system = lti([1], [1, 1]) w = [0.1, 1, 10, 100] w, H = freqresp(system, w=w) s = w * 1j expected = np.polyval(system.num, s) / np.polyval(system.den, s) assert_almost_equal(H.real, expected.real) assert_almost_equal(H.imag, expected.imag)
def test_04(self): # Test bode() phase calculation. # 1st order low-pass filter: H(s) = 1 / (s + 1) system = lti([1], [1, 1]) w = [0.1, 1, 10, 100] w, mag, phase = bode(system, w=w) jw = w * 1j y = np.polyval(system.num, jw) / np.polyval(system.den, jw) expected_phase = np.arctan2(y.imag, y.real) * 180.0 / np.pi assert_almost_equal(phase, expected_phase)
def test_03(self): # Test bode() magnitude calculation. # 1st order low-pass filter: H(s) = 1 / (s + 1) system = lti([1], [1, 1]) w = [0.1, 1, 10, 100] w, mag, phase = bode(system, w=w) jw = w * 1j y = np.polyval(system.num, jw) / np.polyval(system.den, jw) expected_mag = 20.0 * np.log10(abs(y)) assert_almost_equal(mag, expected_mag)
def test_02(self): # Test bode() phase calculation (manual sanity check). # 1st order low-pass filter: H(s) = 1 / (s + 1), # angle(H(s=0.1)) ~= -5.7 deg # angle(H(s=1)) ~= -45 deg # angle(H(s=10)) ~= -84.3 deg system = lti([1], [1, 1]) w = [0.1, 1, 10] w, mag, phase = bode(system, w=w) expected_phase = [-5.7, -45, -84.3] assert_almost_equal(phase, expected_phase, decimal=1)
def test_output_manual(self): # Test freqresp() output calculation (manual sanity check). # 1st order low-pass filter: H(s) = 1 / (s + 1), # re(H(s=0.1)) ~= 0.99 # re(H(s=1)) ~= 0.5 # re(H(s=10)) ~= 0.0099 system = lti([1], [1, 1]) w = [0.1, 1, 10] w, H = freqresp(system, w=w) expected_re = [0.99, 0.5, 0.0099] expected_im = [-0.099, -0.5, -0.099] assert_almost_equal(H.real, expected_re, decimal=1) assert_almost_equal(H.imag, expected_im, decimal=1)
def test_01(self): # Test bode() magnitude calculation (manual sanity check). # 1st order low-pass filter: H(s) = 1 / (s + 1), # cutoff: 1 rad/s, slope: -20 dB/decade # H(s=0.1) ~= 0 dB # H(s=1) ~= -3 dB # H(s=10) ~= -20 dB # H(s=100) ~= -40 dB system = lti([1], [1, 1]) w = [0.1, 1, 10, 100] w, mag, phase = bode(system, w=w) expected_mag = [0, -3, -20, -40] assert_almost_equal(mag, expected_mag, decimal=1)
def test_from_state_space(self): # Ensure that bode works with a system that was created from the # state space representation matrices A, B, C, D. In this case, # system.num will be a 2-D array with shape (1, n+1), where (n,n) # is the shape of A. # A Butterworth lowpass filter is used, so we know the exact # frequency response. a = np.array([1.0, 2.0, 2.0, 1.0]) A = companion(a).T B = np.array([[0.0], [0.0], [1.0]]) C = np.array([[1.0, 0.0, 0.0]]) D = np.array([[0.0]]) with suppress_warnings() as sup: sup.filter(BadCoefficients) system = lti(A, B, C, D) w, mag, phase = bode(system, n=100) expected_magnitude = 20 * np.log10(np.sqrt(1.0 / (1.0 + w**6))) assert_almost_equal(mag, expected_magnitude)
def test_from_state_space(self): # Ensure that freqresp works with a system that was created from the # state space representation matrices A, B, C, D. In this case, # system.num will be a 2-D array with shape (1, n+1), where (n,n) is # the shape of A. # A Butterworth lowpass filter is used, so we know the exact # frequency response. a = np.array([1.0, 2.0, 2.0, 1.0]) A = companion(a).T B = np.array([[0.0], [0.0], [1.0]]) C = np.array([[1.0, 0.0, 0.0]]) D = np.array([[0.0]]) with suppress_warnings() as sup: sup.filter(BadCoefficients) system = lti(A, B, C, D) w, H = freqresp(system, n=100) s = w * 1j expected = (1.0 / (1.0 + 2 * s + 2 * s**2 + s**3)) assert_almost_equal(H.real, expected.real) assert_almost_equal(H.imag, expected.imag)
def test_07(self): # bode() should not fail on a system with pure imaginary poles. # The test passes if bode doesn't raise an exception. system = lti([1], [1, 0, 100]) w, mag, phase = bode(system, n=2)
def test_pole_zero(self): # Test that freqresp() doesn't fail on a system with a pole at 0. # integrator, pole at zero: H(s) = 1 / s system = lti([1], [1, 0]) w, H = freqresp(system, n=2) assert_equal(w[0], 0.01) # a fail would give not-a-number
def test_08(self): # Test that bode() return continuous phase, issues/2331. system = lti([], [-10, -30, -40, -60, -70], 1) w, mag, phase = system.bode(w=np.logspace(-3, 40, 100)) assert_almost_equal(min(phase), -450, decimal=15)
def test_06(self): # Test that bode() doesn't fail on a system with a pole at 0. # integrator, pole at zero: H(s) = 1 / s system = lti([1], [1, 0]) w, mag, phase = bode(system, n=2) assert_equal(w[0], 0.01) # a fail would give not-a-number
def lti_nowarn(self, *args): with suppress_warnings() as sup: sup.filter(BadCoefficients) system = lti(*args) return system