Skip to content

Commit a5094e2

Browse files
authored
Merge pull request #135 from jed-frey/InputSanitization
Cleanup TransferFunction Input Sanitization
2 parents c4f1c34 + 8c997ff commit a5094e2

File tree

4 files changed

+377
-48
lines changed

4 files changed

+377
-48
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ __conda_*.txt
99
record.txt
1010
build.log
1111
*.egg-info/
12+
.eggs/
1213
.coverage
1314
doc/_build
1415
doc/generated
@@ -18,3 +19,7 @@ examples/.ipynb_checkpoints/
1819
.project
1920
Untitled*.ipynb
2021
*.idea/
22+
23+
# Files created by or for emacs (RMM, 29 Dec 2017)
24+
*~
25+
TAGS
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# input_element_int_test.py
2+
#
3+
# Author: Kangwon Lee (kangwonlee)
4+
# Date: 22 Oct 2017
5+
#
6+
# Unit tests contributed as part of PR #158, "SISO tf() may not work
7+
# with numpy arrays with numpy.int elements"
8+
#
9+
# Modified:
10+
# * 29 Dec 2017, RMM - updated file name and added header
11+
12+
import unittest
13+
import numpy as np
14+
import control as ctl
15+
16+
class TestTfInputIntElement(unittest.TestCase):
17+
# currently these do not pass
18+
def test_tf_den_with_numpy_int_element(self):
19+
num = 1
20+
den = np.convolve([1, 2, 1], [1, 1, 1])
21+
22+
sys = ctl.tf(num, den)
23+
24+
self.assertAlmostEqual(1.0, ctl.dcgain(sys))
25+
26+
def test_tf_num_with_numpy_int_element(self):
27+
num = np.convolve([1], [1, 1])
28+
den = np.convolve([1, 2, 1], [1, 1, 1])
29+
30+
sys = ctl.tf(num, den)
31+
32+
self.assertAlmostEqual(1.0, ctl.dcgain(sys))
33+
34+
# currently these pass
35+
def test_tf_input_with_int_element_works(self):
36+
num = 1
37+
den = np.convolve([1.0, 2, 1], [1, 1, 1])
38+
39+
sys = ctl.tf(num, den)
40+
41+
self.assertAlmostEqual(1.0, ctl.dcgain(sys))
42+
43+
def test_ss_input_with_int_element(self):
44+
ident = np.matrix(np.identity(2), dtype=int)
45+
a = np.matrix([[0, 1],
46+
[-1, -2]], dtype=int) * ident
47+
b = np.matrix([[0],
48+
[1]], dtype=int)
49+
c = np.matrix([[0, 1]], dtype=int)
50+
d = 0
51+
52+
sys = ctl.ss(a, b, c, d)
53+
sys2 = ctl.ss2tf(sys)
54+
self.assertAlmostEqual(ctl.dcgain(sys), ctl.dcgain(sys2))

control/tests/xferfcn_input_test.py

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
#!/usr/bin/env python
2+
#
3+
# xferfcn_input_test.py - test inputs to TransferFunction class
4+
# jed-frey, 18 Feb 2017 (based on xferfcn_test.py)
5+
6+
import unittest
7+
import numpy as np
8+
9+
from numpy import int, int8, int16, int32, int64
10+
from numpy import float, float16, float32, float64, float128
11+
from numpy import all, ndarray, array
12+
13+
from control.xferfcn import _cleanPart
14+
15+
class TestXferFcnInput(unittest.TestCase):
16+
"""These are tests for functionality of cleaning and validating
17+
XferFucnInput."""
18+
19+
# Tests for raising exceptions.
20+
def testBadInputType(self):
21+
"""Give the part cleaner invalid input type."""
22+
23+
self.assertRaises(TypeError, _cleanPart, [[0., 1.], [2., 3.]])
24+
25+
def testBadInputType2(self):
26+
"""Give the part cleaner another invalid input type."""
27+
self.assertRaises(TypeError, _cleanPart, [1,"a"])
28+
29+
def testScalar(self):
30+
"""Test single scalar value."""
31+
num = 1
32+
num_ = _cleanPart(num)
33+
34+
assert isinstance(num_, list)
35+
assert np.all([isinstance(part, list) for part in num_])
36+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
37+
38+
def testListScalar(self):
39+
"""Test single scalar value in list."""
40+
num = [1]
41+
num_ = _cleanPart(num)
42+
43+
assert isinstance(num_, list)
44+
assert np.all([isinstance(part, list) for part in num_])
45+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
46+
47+
def testTupleScalar(self):
48+
"""Test single scalar value in tuple."""
49+
num = (1)
50+
num_ = _cleanPart(num)
51+
52+
assert isinstance(num_, list)
53+
assert np.all([isinstance(part, list) for part in num_])
54+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
55+
56+
def testList(self):
57+
"""Test multiple values in a list."""
58+
num = [1, 2]
59+
num_ = _cleanPart(num)
60+
61+
assert isinstance(num_, list)
62+
assert np.all([isinstance(part, list) for part in num_])
63+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
64+
65+
def testTuple(self):
66+
"""Test multiple values in tuple."""
67+
num = (1, 2)
68+
num_ = _cleanPart(num)
69+
70+
assert isinstance(num_, list)
71+
assert np.all([isinstance(part, list) for part in num_])
72+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
73+
74+
def testAllScalarTypes(self):
75+
"""Test single scalar value for all valid data types."""
76+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
77+
num = dtype(1)
78+
num_ = _cleanPart(num)
79+
80+
assert isinstance(num_, list)
81+
assert np.all([isinstance(part, list) for part in num_])
82+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
83+
84+
def testNpArray(self):
85+
"""Test multiple values in numpy array."""
86+
num = np.array([1, 2])
87+
num_ = _cleanPart(num)
88+
89+
assert isinstance(num_, list)
90+
assert np.all([isinstance(part, list) for part in num_])
91+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
92+
93+
def testAllNumpyArrayTypes(self):
94+
"""Test scalar value in numpy array of ndim=0 for all data types."""
95+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
96+
num = np.array(1, dtype=dtype)
97+
num_ = _cleanPart(num)
98+
99+
assert isinstance(num_, list)
100+
assert np.all([isinstance(part, list) for part in num_])
101+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
102+
103+
def testAllNumpyArrayTypes2(self):
104+
"""Test numpy array for all types."""
105+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
106+
num = np.array([1, 2], dtype=dtype)
107+
num_ = _cleanPart(num)
108+
109+
assert isinstance(num_, list)
110+
assert np.all([isinstance(part, list) for part in num_])
111+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
112+
113+
def testListAllTypes(self):
114+
"""Test list of a single value for all data types."""
115+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
116+
num = [dtype(1)]
117+
num_ = _cleanPart(num)
118+
assert isinstance(num_, list)
119+
assert np.all([isinstance(part, list) for part in num_])
120+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
121+
122+
def testListAllTypes2(self):
123+
"""List of list of numbers of all data types."""
124+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
125+
num = [dtype(1), dtype(2)]
126+
num_ = _cleanPart(num)
127+
assert isinstance(num_, list)
128+
assert np.all([isinstance(part, list) for part in num_])
129+
np.testing.assert_array_equal(num_[0][0], array([1.0, 2.0], dtype=float))
130+
131+
def testTupleAllTypes(self):
132+
"""Test tuple of a single value for all data types."""
133+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
134+
num = (dtype(1),)
135+
num_ = _cleanPart(num)
136+
assert isinstance(num_, list)
137+
assert np.all([isinstance(part, list) for part in num_])
138+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
139+
140+
def testTupleAllTypes2(self):
141+
"""Test tuple of a single value for all data types."""
142+
for dtype in [int, int8, int16, int32, int64, float, float16, float32, float64, float128]:
143+
num = (dtype(1), dtype(2))
144+
num_ = _cleanPart(num)
145+
assert isinstance(num_, list)
146+
assert np.all([isinstance(part, list) for part in num_])
147+
np.testing.assert_array_equal(num_[0][0], array([1, 2], dtype=float))
148+
149+
def testListListListInt(self):
150+
""" Test an int in a list of a list of a list."""
151+
num = [[[1]]]
152+
num_ = _cleanPart(num)
153+
assert isinstance(num_, list)
154+
assert np.all([isinstance(part, list) for part in num_])
155+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
156+
157+
def testListListListFloat(self):
158+
""" Test a float in a list of a list of a list."""
159+
num = [[[1.0]]]
160+
num_ = _cleanPart(num)
161+
assert isinstance(num_, list)
162+
assert np.all([isinstance(part, list) for part in num_])
163+
np.testing.assert_array_equal(num_[0][0], array([1.0], dtype=float))
164+
165+
def testListListListInts(self):
166+
"""Test 2 lists of ints in a list in a list."""
167+
num = [[[1,1],[2,2]]]
168+
num_ = _cleanPart(num)
169+
170+
assert isinstance(num_, list)
171+
assert np.all([isinstance(part, list) for part in num_])
172+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
173+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
174+
175+
def testListListListFloats(self):
176+
"""Test 2 lists of ints in a list in a list."""
177+
num = [[[1.0,1.0],[2.0,2.0]]]
178+
num_ = _cleanPart(num)
179+
180+
assert isinstance(num_, list)
181+
assert np.all([isinstance(part, list) for part in num_])
182+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
183+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
184+
185+
def testListListArray(self):
186+
"""List of list of numpy arrays for all valid types."""
187+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
188+
num = [[array([1,1], dtype=dtype),array([2,2], dtype=dtype)]]
189+
num_ = _cleanPart(num)
190+
191+
assert isinstance(num_, list)
192+
assert np.all([isinstance(part, list) for part in num_])
193+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
194+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
195+
196+
def testTupleListArray(self):
197+
"""Tuple of list of numpy arrays for all valid types."""
198+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
199+
num = ([array([1,1], dtype=dtype),array([2,2], dtype=dtype)],)
200+
num_ = _cleanPart(num)
201+
202+
assert isinstance(num_, list)
203+
assert np.all([isinstance(part, list) for part in num_])
204+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
205+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
206+
207+
def testListTupleArray(self):
208+
"""List of tuple of numpy array for all valid types."""
209+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
210+
num = [(array([1,1], dtype=dtype),array([2,2], dtype=dtype))]
211+
num_ = _cleanPart(num)
212+
213+
assert isinstance(num_, list)
214+
assert np.all([isinstance(part, list) for part in num_])
215+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
216+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
217+
218+
def testTupleTuplesArrays(self):
219+
"""Tuple of tuples of numpy arrays for all valid types."""
220+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
221+
num = ((array([1,1], dtype=dtype),array([2,2], dtype=dtype)),
222+
(array([3,4], dtype=dtype),array([4,4], dtype=dtype)))
223+
num_ = _cleanPart(num)
224+
225+
assert isinstance(num_, list)
226+
assert np.all([isinstance(part, list) for part in num_])
227+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
228+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
229+
230+
def testListTuplesArrays(self):
231+
"""List of tuples of numpy arrays for all valid types."""
232+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
233+
num = [(array([1,1], dtype=dtype),array([2,2], dtype=dtype)),
234+
(array([3,4], dtype=dtype),array([4,4], dtype=dtype))]
235+
num_ = _cleanPart(num)
236+
237+
assert isinstance(num_, list)
238+
assert np.all([isinstance(part, list) for part in num_])
239+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
240+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
241+
242+
def testListListArrays(self):
243+
"""List of list of numpy arrays for all valid types."""
244+
for dtype in int, int8, int16, int32, int64, float, float16, float32, float64, float128:
245+
num = [[array([1,1], dtype=dtype),array([2,2], dtype=dtype)],
246+
[array([3,3], dtype=dtype),array([4,4], dtype=dtype)]]
247+
num_ = _cleanPart(num)
248+
249+
assert len(num_) == 2
250+
assert np.all([isinstance(part, list) for part in num_])
251+
assert np.all([len(part) == 2 for part in num_])
252+
np.testing.assert_array_equal(num_[0][0], array([1.0, 1.0], dtype=float))
253+
np.testing.assert_array_equal(num_[0][1], array([2.0, 2.0], dtype=float))
254+
np.testing.assert_array_equal(num_[1][0], array([3.0, 3.0], dtype=float))
255+
np.testing.assert_array_equal(num_[1][1], array([4.0, 4.0], dtype=float))
256+
257+
def suite():
258+
return unittest.TestLoader().loadTestsFromTestCase(TestXferFcnInput)
259+
260+
if __name__ == "__main__":
261+
unittest.main()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy