GUI: draw the forecast line solid instead of dashed

Same color, same alpha-based fade distinguishing it from the actual
measured trace - just '-b' instead of '--b'. Updates the surrounding
docstrings/comments and README that described it as dashed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DkkuG48uHFCGKe6dPSERFk
This commit is contained in:
2026-06-22 20:43:07 +02:00
co-authored by Claude Sonnet 4.6
parent 5ccfcef679
commit 1f146dbc0d
2 changed files with 16 additions and 15 deletions
+5 -5
View File
@@ -293,9 +293,9 @@ disabled, its temperature/heat-rate setpoint controls are inactive.
### Forecast vs. actual duration
The GUI's Automatic tab plots two things against the same time axis: a
*forecast* (dashed) and, once a run starts, the *actual* measured trace
(solid) overlaid on top of it - a comparison between predicted and real
control behavior, not just a progress display.
*forecast* (faded, via alpha) and, once a run starts, the *actual*
measured trace (solid, full opacity) overlaid on top of it - a comparison
between predicted and real control behavior, not just a progress display.
The forecast is computed server-side (`components/sud_forecast.py`'s
`SudForecastEstimator`) by actually running the schedule through a
@@ -335,8 +335,8 @@ tripped - the controller stays enabled and actively holding throughout
`WAIT_USER`, so the setpoint is what it was actually converging toward
during the wait, not a possibly-still-mid-ramp snapshot. The corrected
forecast is sent in full each time, so the GUI's `SudForecastPlot.
show_forecast()` simply redraws
the dashed line outright rather than patching it up itself.
show_forecast()` simply redraws the (faded) forecast line outright rather
than patching it up itself.
Comparing the two lines: real-world divergence from the forecast - more
than a transient blip during a ramp's settling - is worth investigating as
+11 -10
View File
@@ -110,8 +110,9 @@ class RealtimePlot(FigureCanvasQTAgg):
class SudForecastPlot(FigureCanvasQTAgg):
"""Compares a Sud schedule's actual control behavior (line, solid)
against a simulation-based forecast (line_projected, dashed) - the
same plant/controller model the real run uses
against a simulation-based forecast (line_projected, also solid but
faded via alpha - see __init__()) - the same plant/controller model
the real run uses
(components/sud_forecast.py's SudForecastEstimator - see
show_computing()/show_forecast()). The forecast covers the whole
schedule from the very first Load, including through any step
@@ -130,7 +131,7 @@ class SudForecastPlot(FigureCanvasQTAgg):
self.ax = figure.subplots(1, 1)
self.line, = self.ax.plot([], [], '-b', linewidth=1.5, zorder=2)
self.line_projected, = self.ax.plot([], [], '--b', linewidth=1.5, alpha=0.5, zorder=2)
self.line_projected, = self.ax.plot([], [], '-b', linewidth=1.5, alpha=0.5, zorder=2)
self.progress_line = self.ax.axvline(0, color='g', linewidth=1.5, visible=False, zorder=2)
# Current temperature - drawn behind (lower zorder than) the
# forecast/progress lines so it never covers them.
@@ -157,7 +158,7 @@ class SudForecastPlot(FigureCanvasQTAgg):
self.draw_idle()
def show_forecast(self, t_min, theta, name, finished):
"""The forecast curve (dashed) - computed by the server simulating
"""The forecast curve (faded, via alpha) - computed by the server simulating
the schedule with its real plant/controller
(components/sud_forecast.py) - see Window.on_sud_forecast_
received(). Called again, with a corrected t_min/theta, each time
@@ -195,12 +196,12 @@ class SudForecastPlot(FigureCanvasQTAgg):
def show_dynamic(self, history):
"""Updates the actual measured trace (solid) only - the forecast
(dashed) is left exactly as show_forecast() last drew it (that's
the whole point: an honest, unmoving baseline - see this class's
docstring), and the axes stay locked to whatever it set, so
divergence between the two is visible rather than auto-hidden by
the view rescaling to chase whichever line is currently
drawing."""
(also solid, but faded via alpha) is left exactly as
show_forecast() last drew it (that's the whole point: an honest,
unmoving baseline - see this class's docstring), and the axes
stay locked to whatever it set, so divergence between the two is
visible rather than auto-hidden by the view rescaling to chase
whichever line is currently drawing."""
hist_t = [t for t, _ in history]
hist_theta = [theta for _, theta in history]
self.line.set_data(hist_t, hist_theta)