Skip to content

Commit c7b9355

Browse files
committed
Fix linear bounds rendering in plots
1 parent e8fbc72 commit c7b9355

2 files changed

Lines changed: 34 additions & 4 deletions

File tree

bioptim/gui/plot.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,6 @@ def _add_bounds_to_plot(
705705
else self.t
706706
)
707707

708-
# TODO: introduce repeat for the COLLOCATIONS min/max_bounds only for states graphs.
709-
# For now the plots in COLLOCATIONS with LINEAR are not giving the right values
710708
nlp.plot[variable].bounds.check_and_adjust_dimensions(n_elements=len(mapping_to_first_index), n_shooting=ns)
711709

712710
idx = mapping_to_first_index.index(ctr)
@@ -717,8 +715,11 @@ def _add_bounds_to_plot(
717715
bounds_min = np.concatenate((bounds_min, [bounds_min[-1]]))
718716
bounds_max = np.concatenate((bounds_max, [bounds_max[-1]]))
719717

720-
self.plots_bounds.append([ax.step(t[i], bounds_min, where="post", **self.plot_options["bounds"]), i])
721-
self.plots_bounds.append([ax.step(t[i], bounds_max, where="post", **self.plot_options["bounds"]), i])
718+
is_linear = nlp.plot[variable].bounds.type == InterpolationType.LINEAR
719+
plot_function = ax.plot if is_linear else ax.step
720+
plot_options = {} if is_linear else {"where": "post"}
721+
self.plots_bounds.append([plot_function(t[i], bounds_min, **plot_options, **self.plot_options["bounds"]), i])
722+
self.plots_bounds.append([plot_function(t[i], bounds_max, **plot_options, **self.plot_options["bounds"]), i])
722723

723724
def _add_new_axis(self, variable: Str, nb: Int, n_rows: Int, n_cols: Int) -> np.ndarray[plt.Axes]:
724725
"""

tests/shard1/test_plot.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
from types import SimpleNamespace
2+
13
import numpy as np
4+
import matplotlib.pyplot as plt
25
from casadi import DM
36

47
from bioptim import (
@@ -11,6 +14,8 @@
1114
InitialGuessList,
1215
PlotType,
1316
CustomPlot,
17+
Bounds,
18+
InterpolationType,
1419
)
1520
from bioptim.gui.plot import DEFAULT_COLORS, PlotOcp
1621

@@ -91,6 +96,30 @@ def test_default_colors():
9196
assert PlotType.POINT in DEFAULT_COLORS
9297

9398

99+
def test_linear_bounds_are_plotted_with_linear_interpolation():
100+
"""Linear bounds must not be rendered as steps on integrated state plots."""
101+
plot_ocp = PlotOcp.__new__(PlotOcp)
102+
plot_ocp.t = [np.linspace(0, 1, 3)]
103+
plot_ocp.plots_bounds = []
104+
plot_ocp.plot_options = {"bounds": {"color": "k"}}
105+
106+
bounds = Bounds(
107+
"q",
108+
min_bound=np.array([[0.0, 1.0]]),
109+
max_bound=np.array([[2.0, 4.0]]),
110+
interpolation=InterpolationType.LINEAR,
111+
)
112+
nlp = SimpleNamespace(ns=2, plot={"q_states": SimpleNamespace(bounds=bounds)})
113+
figure, axis = plt.subplots()
114+
115+
plot_ocp._add_bounds_to_plot(0, nlp, "q_states", 0, axis, [0])
116+
117+
np.testing.assert_allclose(plot_ocp.plots_bounds[0][0][0].get_ydata(), [0.0, 0.5, 1.0])
118+
np.testing.assert_allclose(plot_ocp.plots_bounds[1][0][0].get_ydata(), [2.0, 3.0, 4.0])
119+
assert plot_ocp.plots_bounds[0][0][0].get_drawstyle() == "default"
120+
plt.close(figure)
121+
122+
94123
def test_plot_options():
95124
"""Test the plot options of PlotOcp"""
96125
from tests.utils import TestUtils

0 commit comments

Comments
 (0)