Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 11 additions & 2 deletions control/frdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,14 @@ def __str__(self):
"""String representation of the transfer function."""

mimo = self.inputs > 1 or self.outputs > 1
outstr = ['frequency response data ']
outstr = ['Frequency response data']

mt, pt, wt = self.freqresp(self.omega)
for i in range(self.inputs):
for j in range(self.outputs):
if mimo:
outstr.append("Input %i to output %i:" % (i + 1, j + 1))
outstr.append('Freq [rad/s] Response ')
outstr.append('Freq [rad/s] Response')
outstr.append('------------ ---------------------')
outstr.extend(
['%12.3f %10.4g%+10.4gj' % (w, m, p)
Expand All @@ -177,6 +177,15 @@ def __str__(self):

return '\n'.join(outstr)

def __repr__(self):
"""Loadable string representation,

limited for number of data points.
"""
return "FrequencyResponseData({d}, {w}{smooth})".format(
d=repr(self.fresp), w=repr(self.omega),
smooth=(self.ifunc and ", smooth=True") or "")

def __neg__(self):
"""Negate a transfer function."""

Expand Down
10 changes: 8 additions & 2 deletions control/statesp.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,14 @@ def __str__(self):
string += "\ndt = " + self.dt.__str__() + "\n"
return string

# represent as string, makes display work for IPython
__repr__ = __str__
# represent to implement a re-loadable version
# TODO: remove the conversion to array when matrix is no longer used
def __repr__(self):
"""Print state-space system in loadable form."""
return "StateSpace({A}, {B}, {C}, {D}{dt})".format(
A=asarray(self.A).__repr__(), B=asarray(self.B).__repr__(),
C=asarray(self.C).__repr__(), D=asarray(self.D).__repr__(),
dt=(isdtime(self, strict=True) and ", {}".format(self.dt)) or '')

# Negation of a system
def __neg__(self):
Expand Down
54 changes: 52 additions & 2 deletions control/tests/frd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import control as ct
from control.statesp import StateSpace
from control.xferfcn import TransferFunction
from control.frdata import FRD, _convertToFRD
from control.frdata import FRD, _convertToFRD, FrequencyResponseData
from control import bdalg
from control import freqplot
from control.exception import slycot_check
Expand Down Expand Up @@ -414,6 +414,56 @@ def test_evalfr_deprecated(self):
# Make sure that we get a pending deprecation warning
self.assertRaises(PendingDeprecationWarning, frd_tf.evalfr, 1.)


def test_repr_str(self):
# repr printing
array = np.array
sys0 = FrequencyResponseData([1.0, 0.9+0.1j, 0.1+2j, 0.05+3j],
[0.1, 1.0, 10.0, 100.0])
sys1 = FrequencyResponseData(sys0.fresp, sys0.omega, smooth=True)
ref0 = "FrequencyResponseData(" \
"array([[[1. +0.j , 0.9 +0.1j, 0.1 +2.j , 0.05+3.j ]]])," \
" array([ 0.1, 1. , 10. , 100. ]))"
ref1 = ref0[:-1] + ", smooth=True)"
sysm = FrequencyResponseData(
np.matmul(array([[1],[2]]), sys0.fresp), sys0.omega)

self.assertEqual(repr(sys0), ref0)
self.assertEqual(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)
sys1r = eval(repr(sys1))
np.testing.assert_array_almost_equal(sys1r.fresp, sys1.fresp)
np.testing.assert_array_almost_equal(sys1r.omega, sys1.omega)
assert(sys1.ifunc is not None)

refs = """Frequency response data
Freq [rad/s] Response
------------ ---------------------
0.100 1 +0j
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)

# print multi-input system
refm = """Frequency response data
Input 1 to output 1:
Freq [rad/s] Response
------------ ---------------------
0.100 1 +0j
1.000 0.9 +0.1j
10.000 0.1 +2j
100.000 0.05 +3j
Input 2 to output 1:
Freq [rad/s] Response
------------ ---------------------
0.100 2 +0j
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()
20 changes: 20 additions & 0 deletions control/tests/statesp_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,25 @@ def test_lft(self):
np.testing.assert_allclose(np.array(pk.C).reshape(-1), Cmatlab)
np.testing.assert_allclose(np.array(pk.D).reshape(-1), Dmatlab)

def test_repr(self):
ref322 = """StateSpace(array([[-3., 4., 2.],
[-1., -3., 0.],
[ 2., 5., 3.]]), array([[ 1., 4.],
[-3., -3.],
[-2., 1.]]), array([[ 4., 2., -3.],
[ 1., 4., 3.]]), array([[-2., 4.],
[ 0., 1.]]){dt})"""
self.assertEqual(repr(self.sys322), ref322.format(dt=''))
sysd = StateSpace(self.sys322.A, self.sys322.B,
self.sys322.C, self.sys322.D, 0.4)
self.assertEqual(repr(sysd), ref322.format(dt=", 0.4"))
array = np.array
sysd2 = eval(repr(sysd))
np.testing.assert_allclose(sysd.A, sysd2.A)
np.testing.assert_allclose(sysd.B, sysd2.B)
np.testing.assert_allclose(sysd.C, sysd2.C)
np.testing.assert_allclose(sysd.D, sysd2.D)

def test_str(self):
"""Test that printing the system works"""
tsys = self.sys322
Expand Down Expand Up @@ -653,5 +672,6 @@ def test_sample_system_prewarping(self):
evalfr(plant_d_warped, np.exp(wwarp*1j*Ts)),
decimal=4)


if __name__ == "__main__":
unittest.main()
41 changes: 41 additions & 0 deletions control/tests/xferfcn_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,46 @@ def test_latex_repr(self):
r'+ 2.3 ' + expmul + ' 10^{-45}'
r'}' + suffix + '$$')
self.assertEqual(H._repr_latex_(), ref)

def test_repr(self):
"""Test __repr__ printout."""
Hc = TransferFunction([-1., 4.], [1., 3., 5.])
Hd = TransferFunction([2., 3., 0.], [1., -3., 4., 0], 2.0)
Hcm = TransferFunction(
[ [[0, 1], [2, 3]], [[4, 5], [6, 7]] ],
[ [[6, 7], [4, 5]], [[2, 3], [0, 1]] ])
Hdm = TransferFunction(
[ [[0, 1], [2, 3]], [[4, 5], [6, 7]] ],
[ [[6, 7], [4, 5]], [[2, 3], [0, 1]] ], 0.5)

refs = [
"TransferFunction(array([-1., 4.]), array([1., 3., 5.]))",
"TransferFunction(array([2., 3., 0.]),"
" array([ 1., -3., 4., 0.]), 2.0)",
"TransferFunction([[array([1]), array([2, 3])],"
" [array([4, 5]), array([6, 7])]],"
" [[array([6, 7]), array([4, 5])],"
" [array([2, 3]), array([1])]])",
"TransferFunction([[array([1]), array([2, 3])],"
" [array([4, 5]), array([6, 7])]],"
" [[array([6, 7]), array([4, 5])],"
" [array([2, 3]), array([1])]], 0.5)" ]
self.assertEqual(repr(Hc), refs[0])
self.assertEqual(repr(Hd), refs[1])
self.assertEqual(repr(Hcm), refs[2])
self.assertEqual(repr(Hdm), refs[3])

# and reading back
array = np.array
for H in (Hc, Hd, Hcm, Hdm):
H2 = eval(H.__repr__())
for p in range(len(H.num)):
for m in range(len(H.num[0])):
np.testing.assert_array_almost_equal(
H.num[p][m], H2.num[p][m])
np.testing.assert_array_almost_equal(
H.den[p][m], H2.den[p][m])
self.assertEqual(H.dt, H2.dt)

def test_sample_system_prewarping(self):
"""test that prewarping works when converting from cont to discrete time system"""
Expand All @@ -893,5 +933,6 @@ def test_sample_system_prewarping(self):
evalfr(plant_d_warped, np.exp(wwarp*1j*Ts)),
decimal=4)


if __name__ == "__main__":
unittest.main()
13 changes: 11 additions & 2 deletions control/xferfcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,17 @@ def __str__(self, var=None):

return outstr

# represent as string, makes display work for IPython
__repr__ = __str__
# represent to implement a re-loadable version
def __repr__(self):
"""Print transfer function in loadable form"""
if self.issiso():
return "TransferFunction({num}, {den}{dt})".format(
num=self.num[0][0].__repr__(), den=self.den[0][0].__repr__(),
dt=(isdtime(self, strict=True) and ', {}'.format(self.dt)) or '')
else:
return "TransferFunction({num}, {den}{dt})".format(
num=self.num.__repr__(), den=self.den.__repr__(),
dt=(isdtime(self, strict=True) and ', {}'.format(self.dt)) or '')

def _repr_latex_(self, var=None):
"""LaTeX representation of transfer function, for Jupyter notebook"""
Expand Down