Skip to content

Commit 5076298

Browse files
committed
update state space system repr() to include signal/system names
1 parent f363e7b commit 5076298

3 files changed

Lines changed: 64 additions & 12 deletions

File tree

control/iosys.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,44 @@ def __str__(self):
250250
str += f"States ({self.nstates}): {self.state_labels}"
251251
return str
252252

253+
def _label_repr(self, show_count=True):
254+
out, count = "", 0
255+
256+
# Include the system name if not generic
257+
if not self._generic_name_check():
258+
name_spec = f"name='{self.name}'"
259+
count += len(name_spec)
260+
out += name_spec
261+
262+
# Include the state, output, and input names if not generic
263+
for sig_name, sig_default, sig_labels in zip(
264+
['states', 'outputs', 'inputs'],
265+
['x', 'y', 'u'], # TODO: replace with defaults
266+
[self.state_labels, self.output_labels, self.input_labels]):
267+
if sig_name == 'states' and self.nstates is None:
268+
continue
269+
270+
# Check if the signal labels are generic
271+
if any([re.match(r'^' + sig_default + r'\[\d*\]$', label) is None
272+
for label in sig_labels]):
273+
spec = f"{sig_name}={sig_labels}"
274+
elif show_count:
275+
spec = f"{sig_name}={len(sig_labels)}"
276+
277+
# Append the specification string to the output, with wrapping
278+
if count == 0:
279+
count = len(spec) # no system name => suppress comma
280+
elif count + len(spec) > 72:
281+
# TODO: check to make sure a single line is enough (minor)
282+
out += ",\n"
283+
count = len(spec)
284+
else:
285+
out += ", "
286+
count += len(spec) + 2
287+
out += spec
288+
289+
return out
290+
253291
# Find a list of signals by name, index, or pattern
254292
def _find_signals(self, name_list, sigdict):
255293
if not isinstance(name_list, (list, tuple)):

control/statesp.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,19 @@ def __str__(self):
392392
# represent to implement a re-loadable version
393393
def __repr__(self):
394394
"""Print state-space system in loadable form."""
395-
# TODO: add input/output names (?)
396-
return "StateSpace({A}, {B}, {C}, {D}{dt})".format(
395+
out = "StateSpace(\n{A},\n{B},\n{C},\n{D}".format(
397396
A=self.A.__repr__(), B=self.B.__repr__(),
398-
C=self.C.__repr__(), D=self.D.__repr__(),
399-
dt=(isdtime(self, strict=True) and ", {}".format(self.dt)) or '')
397+
C=self.C.__repr__(), D=self.D.__repr__())
398+
399+
if config.defaults['control.default_dt'] != self.dt:
400+
out += ",\ndt={dt}".format(
401+
dt='None' if self.dt is None else self.dt)
402+
403+
if len(labels := self._label_repr()) > 0:
404+
out += ",\n" + labels
405+
406+
out += ")"
407+
return out
400408

401409
def _latex_partitioned_stateless(self):
402410
"""`Partitioned` matrix LaTeX representation for stateless systems

control/tests/statesp_test.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -735,17 +735,23 @@ def test_lft(self):
735735

736736
def test_repr(self, sys322):
737737
"""Test string representation"""
738-
ref322 = "\n".join(["StateSpace(array([[-3., 4., 2.],",
739-
" [-1., -3., 0.],",
740-
" [ 2., 5., 3.]]), array([[ 1., 4.],",
741-
" [-3., -3.],",
742-
" [-2., 1.]]), array([[ 4., 2., -3.],",
743-
" [ 1., 4., 3.]]), array([[-2., 4.],",
744-
" [ 0., 1.]]){dt})"])
738+
ref322 = "\n".join(
739+
["StateSpace(",
740+
"array([[-3., 4., 2.],",
741+
" [-1., -3., 0.],",
742+
" [ 2., 5., 3.]]),",
743+
"array([[ 1., 4.],",
744+
" [-3., -3.],",
745+
" [-2., 1.]]),",
746+
"array([[ 4., 2., -3.],",
747+
" [ 1., 4., 3.]]),",
748+
"array([[-2., 4.],",
749+
" [ 0., 1.]]){dt},",
750+
"name='sys322', states=3, outputs=2, inputs=2)"])
745751
assert repr(sys322) == ref322.format(dt='')
746752
sysd = StateSpace(sys322.A, sys322.B,
747753
sys322.C, sys322.D, 0.4)
748-
assert repr(sysd), ref322.format(dt=" == 0.4")
754+
assert repr(sysd), ref322.format(dt="\ndt=0.4")
749755
array = np.array # noqa
750756
sysd2 = eval(repr(sysd))
751757
np.testing.assert_allclose(sysd.A, sysd2.A)

0 commit comments

Comments
 (0)