Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5e16344
reorganize travis matrix, extend conftest.py
bnavigator Dec 29, 2020
c220a98
pytestify bdalg_test
bnavigator Dec 29, 2020
90a0059
pytestify canonical_test
bnavigator Jul 26, 2020
79b5bfe
pytestify config_test
bnavigator Dec 29, 2020
74d563c
pytestify convert_test.py
bnavigator Jul 24, 2020
c7cc828
pytestify ctrlutil_test
bnavigator Jul 24, 2020
d899140
pytestify delay_test.py
bnavigator Jul 24, 2020
53520e9
pytestify discrete_test
bnavigator Aug 19, 2020
659aa2d
pytestify flatsys_test
bnavigator Dec 29, 2020
1da4c5c
pytestify frd_test
bnavigator Jul 24, 2020
96f0911
pytestify freqresp_test.py
bnavigator Dec 29, 2020
caed712
pytestify input_element_int_test
bnavigator Jul 26, 2020
55a6119
pytestify iosys_test
bnavigator Dec 29, 2020
521e927
pytestify lti_test.py
bnavigator Jul 26, 2020
2c31029
pytestify mateqn_test
bnavigator Dec 29, 2020
fc2f770
pytestify matlab tests
bnavigator Jul 26, 2020
5880473
pytestify minreal_test
bnavigator Jul 26, 2020
97eedaf
pytestify modelsimp
bnavigator Dec 29, 2020
3eb0a92
pytestify nichols_test
bnavigator Jul 26, 2020
000998f
pytestify phaseplot_test
bnavigator Jul 28, 2020
3177796
pytestify rlocus_test.py
bnavigator Jul 28, 2020
f745bd2
pytestify robust tests
bnavigator Dec 29, 2020
2ee0773
pytestify sisotool_test.py
bnavigator Dec 29, 2020
e660363
pytestify slycot_convert_test.py
bnavigator Jul 28, 2020
952c511
pytestify statefbk tests
bnavigator Dec 29, 2020
6386832
pytestify statesp tests
bnavigator Dec 29, 2020
1dd2525
pytestify timeresp_test.py
bnavigator Dec 29, 2020
29883e8
pytestify xferfcn_input_test.py
bnavigator Jul 31, 2020
ca9476f
pytestify xferfcn tests
bnavigator Dec 29, 2020
2b98769
make tests work with pre #431 source code state
bnavigator Dec 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
pytestify frd_test
  • Loading branch information
bnavigator committed Dec 29, 2020
commit 1da4c5c113d3627f7a73e67c6edf8ddfb2473151
140 changes: 69 additions & 71 deletions control/tests/frd_test.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
#!/usr/bin/env python
#
# frd_test.py - test FRD class
# RvP, 4 Oct 2012
"""frd_test.py - test FRD class

RvP, 4 Oct 2012
"""

import unittest
import sys as pysys

import numpy as np
import matplotlib.pyplot as plt
import pytest

import control as ct
from control.statesp import StateSpace
from control.xferfcn import TransferFunction
from control.frdata import FRD, _convertToFRD, FrequencyResponseData
from control import bdalg
from control import freqplot
from control.exception import slycot_check
import matplotlib.pyplot as plt
from control import bdalg, evalfr, freqplot
from control.tests.conftest import slycotonly


class TestFRD(unittest.TestCase):
class TestFRD:
"""These are tests for functionality and correct reporting of the
frequency response data class."""

def testBadInputType(self):
"""Give the constructor invalid input types."""
self.assertRaises(ValueError, FRD)
self.assertRaises(TypeError, FRD, [1])
with pytest.raises(ValueError):
FRD()
with pytest.raises(TypeError):
FRD([1])

def testInconsistentDimension(self):
self.assertRaises(TypeError, FRD, [1, 1], [1, 2, 3])
with pytest.raises(TypeError):
FRD([1, 1], [1, 2, 3])

def testSISOtf(self):
# get a SISO transfer function
Expand All @@ -36,8 +39,11 @@ def testSISOtf(self):
frd = FRD(h, omega)
assert isinstance(frd, FRD)

np.testing.assert_array_almost_equal(
frd.freqresp([1.0]), h.freqresp([1.0]))
mag1, phase1, omega1 = frd.freqresp([1.0])
mag2, phase2, omega2 = h.freqresp([1.0])
np.testing.assert_array_almost_equal(mag1, mag2)
np.testing.assert_array_almost_equal(phase1, phase2)
np.testing.assert_array_almost_equal(omega1, omega2)

def testOperators(self):
# get two SISO transfer functions
Expand Down Expand Up @@ -169,7 +175,7 @@ def testFeedback2(self):
def testAuto(self):
omega = np.logspace(-1, 2, 10)
f1 = _convertToFRD(1, omega)
f2 = _convertToFRD(np.matrix([[1, 0], [0.1, -1]]), omega)
f2 = _convertToFRD(np.array([[1, 0], [0.1, -1]]), omega)
f2 = _convertToFRD([[1, 0], [0.1, -1]], omega)
f1, f2 # reference to avoid pyflakes error

Expand All @@ -183,7 +189,7 @@ def testNyquist(self):
freqplot.nyquist(f1, f1.omega)
# plt.savefig('/dev/null', format='svg')

@unittest.skipIf(not slycot_check(), "slycot not installed")
@slycotonly
def testMIMO(self):
sys = StateSpace([[-0.5, 0.0], [0.0, -1.0]],
[[1.0, 0.0], [0.0, 1.0]],
Expand All @@ -198,7 +204,7 @@ def testMIMO(self):
sys.freqresp([0.1, 1.0, 10])[1],
f1.freqresp([0.1, 1.0, 10])[1])

@unittest.skipIf(not slycot_check(), "slycot not installed")
@slycotonly
def testMIMOfb(self):
sys = StateSpace([[-0.5, 0.0], [0.0, -1.0]],
[[1.0, 0.0], [0.0, 1.0]],
Expand All @@ -214,13 +220,15 @@ def testMIMOfb(self):
f1.freqresp([0.1, 1.0, 10])[1],
f2.freqresp([0.1, 1.0, 10])[1])

@unittest.skipIf(not slycot_check(), "slycot not installed")
@slycotonly
def testMIMOfb2(self):
sys = StateSpace(np.matrix('-2.0 0 0; 0 -1 1; 0 0 -3'),
np.matrix('1.0 0; 0 0; 0 1'),
sys = StateSpace(np.array([[-2.0, 0, 0],
[0, -1, 1],
[0, 0, -3]]),
np.array([[1.0, 0], [0, 0], [0, 1]]),
np.eye(3), np.zeros((3, 2)))
omega = np.logspace(-1, 2, 10)
K = np.matrix('1 0.3 0; 0.1 0 0')
K = np.array([[1, 0.3, 0], [0.1, 0, 0]])
f1 = FRD(sys, omega).feedback(K)
f2 = FRD(sys.feedback(K), omega)
np.testing.assert_array_almost_equal(
Expand All @@ -230,7 +238,7 @@ def testMIMOfb2(self):
f1.freqresp([0.1, 1.0, 10])[1],
f2.freqresp([0.1, 1.0, 10])[1])

@unittest.skipIf(not slycot_check(), "slycot not installed")
@slycotonly
def testMIMOMult(self):
sys = StateSpace([[-0.5, 0.0], [0.0, -1.0]],
[[1.0, 0.0], [0.0, 1.0]],
Expand All @@ -246,13 +254,13 @@ def testMIMOMult(self):
(f1*f2).freqresp([0.1, 1.0, 10])[1],
(sys*sys).freqresp([0.1, 1.0, 10])[1])

@unittest.skipIf(not slycot_check(), "slycot not installed")
@slycotonly
def testMIMOSmooth(self):
sys = StateSpace([[-0.5, 0.0], [0.0, -1.0]],
[[1.0, 0.0], [0.0, 1.0]],
[[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]],
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]])
sys2 = np.matrix([[1, 0, 0], [0, 1, 0]]) * sys
sys2 = np.array([[1, 0, 0], [0, 1, 0]]) * sys
omega = np.logspace(-1, 2, 10)
f1 = FRD(sys, omega, smooth=True)
f2 = FRD(sys2, omega, smooth=True)
Expand All @@ -271,47 +279,54 @@ def testAgainstOctave(self):
# sys = ss([-2 0 0; 0 -1 1; 0 0 -3],
# [1 0; 0 0; 0 1], eye(3), zeros(3,2))
# bfr = frd(bsys, [1])
sys = StateSpace(np.matrix('-2.0 0 0; 0 -1 1; 0 0 -3'),
np.matrix('1.0 0; 0 0; 0 1'),
sys = StateSpace(np.array([[-2.0, 0, 0], [0, -1, 1], [0, 0, -3]]),
np.array([[1.0, 0], [0, 0], [0, 1]]),
np.eye(3), np.zeros((3, 2)))
omega = np.logspace(-1, 2, 10)
f1 = FRD(sys, omega)
np.testing.assert_array_almost_equal(
(f1.freqresp([1.0])[0] *
np.exp(1j*f1.freqresp([1.0])[1])).reshape(3, 2),
np.matrix('0.4-0.2j 0; 0 0.1-0.2j; 0 0.3-0.1j'))
np.exp(1j * f1.freqresp([1.0])[1])).reshape(3, 2),
np.array([[0.4 - 0.2j, 0], [0, 0.1 - 0.2j], [0, 0.3 - 0.1j]]))

def test_string_representation(self):
def test_string_representation(self, capsys):
sys = FRD([1, 2, 3], [4, 5, 6])
print(sys) # Just print without checking

def test_frequency_mismatch(self):
def test_frequency_mismatch(self, recwarn):
# recwarn: there may be a warning before the error!
# Overlapping but non-equal frequency ranges
sys1 = FRD([1, 2, 3], [4, 5, 6])
sys2 = FRD([2, 3, 4], [5, 6, 7])
self.assertRaises(NotImplementedError, FRD.__add__, sys1, sys2)
with pytest.raises(NotImplementedError):
FRD.__add__(sys1, sys2)

# One frequency range is a subset of another
sys1 = FRD([1, 2, 3], [4, 5, 6])
sys2 = FRD([2, 3], [4, 5])
self.assertRaises(NotImplementedError, FRD.__add__, sys1, sys2)
with pytest.raises(NotImplementedError):
FRD.__add__(sys1, sys2)

def test_size_mismatch(self):
sys1 = FRD(ct.rss(2, 2, 2), np.logspace(-1, 1, 10))

# Different number of inputs
sys2 = FRD(ct.rss(3, 1, 2), np.logspace(-1, 1, 10))
self.assertRaises(ValueError, FRD.__add__, sys1, sys2)
with pytest.raises(ValueError):
FRD.__add__(sys1, sys2)

# Different number of outputs
sys2 = FRD(ct.rss(3, 2, 1), np.logspace(-1, 1, 10))
self.assertRaises(ValueError, FRD.__add__, sys1, sys2)
with pytest.raises(ValueError):
FRD.__add__(sys1, sys2)

# Inputs and outputs don't match
self.assertRaises(ValueError, FRD.__mul__, sys2, sys1)
with pytest.raises(ValueError):
FRD.__mul__(sys2, sys1)

# Feedback mismatch
self.assertRaises(ValueError, FRD.feedback, sys2, sys1)
with pytest.raises(ValueError):
FRD.feedback(sys2, sys1)

def test_operator_conversion(self):
sys_tf = ct.tf([1], [1, 2, 1])
Expand Down Expand Up @@ -365,7 +380,8 @@ def test_operator_conversion(self):
np.testing.assert_array_almost_equal(sys_pow.fresp, chk_pow.fresp)

# Assertion error if we try to raise to a non-integer power
self.assertRaises(ValueError, FRD.__pow__, frd_tf, 0.5)
with pytest.raises(ValueError):
FRD.__pow__(frd_tf, 0.5)

# Selected testing on transfer function conversion
sys_add = frd_2 + sys_tf
Expand All @@ -375,44 +391,29 @@ def test_operator_conversion(self):

# Input/output mismatch size mismatch in rmul
sys1 = FRD(ct.rss(2, 2, 2), np.logspace(-1, 1, 10))
self.assertRaises(ValueError, FRD.__rmul__, frd_2, sys1)
with pytest.raises(ValueError):
FRD.__rmul__(frd_2, sys1)

# Make sure conversion of something random generates exception
self.assertRaises(TypeError, FRD.__add__, frd_tf, 'string')
with pytest.raises(TypeError):
FRD.__add__(frd_tf, 'string')

def test_eval(self):
sys_tf = ct.tf([1], [1, 2, 1])
frd_tf = FRD(sys_tf, np.logspace(-1, 1, 3))
np.testing.assert_almost_equal(sys_tf.evalfr(1), frd_tf.eval(1))
np.testing.assert_almost_equal(evalfr(sys_tf, 1J), frd_tf.eval(1))

# Should get an error if we evaluate at an unknown frequency
self.assertRaises(ValueError, frd_tf.eval, 2)
with pytest.raises(ValueError):
frd_tf.eval(2)


# This test only works in Python 3 due to a conflict with the same
# warning type in other test modules (frd_test.py). See
# https://bugs.python.org/issue4180 for more details
@unittest.skipIf(pysys.version_info < (3, 0), "test requires Python 3+")
def test_evalfr_deprecated(self):
sys_tf = ct.tf([1], [1, 2, 1])
frd_tf = FRD(sys_tf, np.logspace(-1, 1, 3))

# Deprecated version of the call (should generate warning)
import warnings
with warnings.catch_warnings():
# Make warnings generate an exception
warnings.simplefilter('error')

# Make sure that we get a pending deprecation warning
self.assertRaises(PendingDeprecationWarning, frd_tf.evalfr, 1.)

# FRD.evalfr() is being deprecated
import warnings
with warnings.catch_warnings():
# Make warnings generate an exception
warnings.simplefilter('error')

# Make sure that we get a pending deprecation warning
self.assertRaises(PendingDeprecationWarning, frd_tf.evalfr, 1.)
with pytest.deprecated_call():
frd_tf.evalfr(1.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pytest takes care of this just fine

def test_repr_str(self):
# repr printing
Expand All @@ -427,8 +428,8 @@ def test_repr_str(self):
sysm = FrequencyResponseData(
np.matmul(array([[1],[2]]), sys0.fresp), sys0.omega)

self.assertEqual(repr(sys0), ref0)
self.assertEqual(repr(sys1), ref1)
assert repr(sys0) == ref0
assert repr(sys1) == ref1
sys0r = eval(repr(sys0))
np.testing.assert_array_almost_equal(sys0r.fresp, sys0.fresp)
np.testing.assert_array_almost_equal(sys0r.omega, sys0.omega)
Expand All @@ -444,8 +445,8 @@ def test_repr_str(self):
1.000 0.9 +0.1j
10.000 0.1 +2j
100.000 0.05 +3j"""
self.assertEqual(str(sys0), refs)
self.assertEqual(str(sys1), refs)
assert str(sys0) == refs
assert str(sys1) == refs

# print multi-input system
refm = """Frequency response data
Expand All @@ -463,7 +464,4 @@ def test_repr_str(self):
1.000 1.8 +0.2j
10.000 0.2 +4j
100.000 0.1 +6j"""
self.assertEqual(str(sysm), refm)

if __name__ == "__main__":
unittest.main()
assert str(sysm) == refm