Skip to content
Closed
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
fix(timeplot): accept response lists
Route TimeResponseList and plain lists of time responses through the existing TimeResponseList plotting path when calling the public time_response_plot function directly. This keeps response_list.plot() behavior unchanged while fixing the standalone function for list-returning simulation calls.
  • Loading branch information
marko1olo committed Aug 14, 2026
commit 22c7cea2d3e1f169b60132cda9d9f74cfaba50e5
18 changes: 18 additions & 0 deletions control/tests/timeplot_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,24 @@ def test_list_responses(resp_fcn):
assert cplt.lines[row, col][0].get_color() == 'tab:blue'
assert cplt.lines[row, col][1].get_color() == 'tab:orange'

# Make sure the public plotting function also accepts response lists
plt.figure()
cplt = ct.time_response_plot(resp_combined)
assert cplt.lines.shape == shape
for row in range(2): # just look at the outputs
for col in range(shape[1]):
assert cplt.lines[row, col][0].get_color() == 'tab:blue'
assert cplt.lines[row, col][1].get_color() == 'tab:orange'

# Plain Python lists of time responses should follow the same path
plt.figure()
cplt = ct.time_response_plot([resp1, resp2])
assert cplt.lines.shape == shape
for row in range(2): # just look at the outputs
for col in range(shape[1]):
assert cplt.lines[row, col][0].get_color() == 'tab:blue'
assert cplt.lines[row, col][1].get_color() == 'tab:orange'


@pytest.mark.slycot
@pytest.mark.usefixtures('mplcleanup')
Expand Down
20 changes: 19 additions & 1 deletion control/timeplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def time_response_plot(

Parameters
----------
data : `TimeResponseData`
data : `TimeResponseData` or list of `TimeResponseData`
Data to be plotted.
plot_inputs : bool or str, optional
Sets how and where to plot the inputs:
Expand Down Expand Up @@ -176,6 +176,24 @@ def time_response_plot(
"""
from .ctrlplot import _process_ax_keyword, _process_line_labels

# If given a list of time responses, plot them sequentially on the same
# axes using the same path as TimeResponseList.plot().
if isinstance(data, list):
if len(data) == 0:
raise ValueError("response list must contain at least one response")

from .timeresp import TimeResponseList

list_kwargs = dict(
ax=ax, plot_inputs=plot_inputs, plot_outputs=plot_outputs,
transpose=transpose, overlay_traces=overlay_traces,
overlay_signals=overlay_signals, add_initial_zero=add_initial_zero,
trace_labels=trace_labels, title=title, relabel=relabel)
if label is not None:
list_kwargs['label'] = label

return TimeResponseList(data).plot(*fmt, **list_kwargs, **kwargs)

#
# Process keywords and set defaults
#
Expand Down
Loading