Skip to content

Commit d5666d5

Browse files
authored
print(sys) / str(sys) for StateSpace and TransferFunction (#426)
* indent StateSpace.__str__() * test StateSpace.__str__() * remove obsolete check for 0000 in %.4g format * test _tf_polynomial_to_string code branches * no f-strings in Python 2.7 :( * int division for python2 and python3
1 parent 711a512 commit d5666d5

4 files changed

Lines changed: 53 additions & 15 deletions

File tree

control/statesp.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -267,18 +267,18 @@ def _remove_useless_states(self):
267267
self.outputs = self.C.shape[0]
268268

269269
def __str__(self):
270-
"""String representation of the state space."""
271-
272-
str = "A = " + self.A.__str__() + "\n\n"
273-
str += "B = " + self.B.__str__() + "\n\n"
274-
str += "C = " + self.C.__str__() + "\n\n"
275-
str += "D = " + self.D.__str__() + "\n"
270+
"""Return string representation of the state space system."""
271+
string = "\n".join([
272+
"{} = {}\n".format(Mvar,
273+
"\n ".join(str(M).splitlines()))
274+
for Mvar, M in zip(["A", "B", "C", "D"],
275+
[self.A, self.B, self.C, self.D])])
276276
# TODO: replace with standard calls to lti functions
277277
if (type(self.dt) == bool and self.dt is True):
278-
str += "\ndt unspecified\n"
278+
string += "\ndt unspecified\n"
279279
elif (not (self.dt is None) and type(self.dt) != bool and self.dt > 0):
280-
str += "\ndt = " + self.dt.__str__() + "\n"
281-
return str
280+
string += "\ndt = " + self.dt.__str__() + "\n"
281+
return string
282282

283283
# represent as string, makes display work for IPython
284284
__repr__ = __str__

control/tests/statesp_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,29 @@ def test_lft(self):
519519
np.testing.assert_allclose(np.array(pk.C).reshape(-1), Cmatlab)
520520
np.testing.assert_allclose(np.array(pk.D).reshape(-1), Dmatlab)
521521

522+
def test_str(self):
523+
"""Test that printing the system works"""
524+
tsys = self.sys322
525+
tref = ("A = [[-3. 4. 2.]\n"
526+
" [-1. -3. 0.]\n"
527+
" [ 2. 5. 3.]]\n"
528+
"\n"
529+
"B = [[ 1. 4.]\n"
530+
" [-3. -3.]\n"
531+
" [-2. 1.]]\n"
532+
"\n"
533+
"C = [[ 4. 2. -3.]\n"
534+
" [ 1. 4. 3.]]\n"
535+
"\n"
536+
"D = [[-2. 4.]\n"
537+
" [ 0. 1.]]\n")
538+
assert str(tsys) == tref
539+
tsysdtunspec = StateSpace(tsys.A, tsys.B, tsys.C, tsys.D, True)
540+
assert str(tsysdtunspec) == tref + "\ndt unspecified\n"
541+
sysdt1 = StateSpace(tsys.A, tsys.B, tsys.C, tsys.D, 1.)
542+
assert str(sysdt1) == tref + "\ndt = 1.0\n"
543+
544+
522545
class TestRss(unittest.TestCase):
523546
"""These are tests for the proper functionality of statesp.rss."""
524547

control/tests/xferfcn_test.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,25 @@ def test_printing(self):
806806
self.assertTrue(isinstance(str(sys), str))
807807
self.assertTrue(isinstance(sys._repr_latex_(), str))
808808

809+
def test_printing_polynomial(self):
810+
"""Cover all _tf_polynomial_to_string code branches"""
811+
# Note: the assertions below use plain assert statements instead of
812+
# unittest methods so that debugging with pytest is easier
813+
814+
assert str(TransferFunction([0], [1])) == "\n0\n-\n1\n"
815+
assert str(TransferFunction([1.0001], [-1.1111])) == \
816+
"\n 1\n------\n-1.111\n"
817+
assert str(TransferFunction([0, 1], [0, 1.])) == "\n1\n-\n1\n"
818+
for var, dt, dtstring in zip(["s", "z", "z"],
819+
[None, True, 1],
820+
['', '', '\ndt = 1\n']):
821+
assert str(TransferFunction([1, 0], [2, 1], dt)) == \
822+
"\n {var}\n-------\n2 {var} + 1\n{dtstring}".format(
823+
var=var, dtstring=dtstring)
824+
assert str(TransferFunction([2, 0, -1], [1, 0, 0, 1.2], dt)) == \
825+
"\n2 {var}^2 - 1\n---------\n{var}^3 + 1.2\n{dtstring}".format(
826+
var=var, dtstring=dtstring)
827+
809828
@unittest.skipIf(not slycot_check(), "slycot not installed")
810829
def test_printing_mimo(self):
811830
# MIMO, continuous time

control/xferfcn.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,9 @@ def __str__(self, var=None):
264264

265265
# Center the numerator or denominator
266266
if len(numstr) < dashcount:
267-
numstr = (' ' * int(round((dashcount - len(numstr)) / 2)) +
268-
numstr)
267+
numstr = ' ' * ((dashcount - len(numstr)) // 2) + numstr
269268
if len(denstr) < dashcount:
270-
denstr = (' ' * int(round((dashcount - len(denstr)) / 2)) +
271-
denstr)
269+
denstr = ' ' * ((dashcount - len(denstr)) // 2) + denstr
272270

273271
outstr += "\n" + numstr + "\n" + dashes + "\n" + denstr + "\n"
274272

@@ -1104,8 +1102,6 @@ def _tf_polynomial_to_string(coeffs, var='s'):
11041102

11051103
for k in range(len(coeffs)):
11061104
coefstr = '%.4g' % abs(coeffs[k])
1107-
if coefstr[-4:] == '0000':
1108-
coefstr = coefstr[:-5]
11091105
power = (N - k)
11101106
if power == 0:
11111107
if coefstr != '0':

0 commit comments

Comments
 (0)