diff --git a/README.md b/README.md index fb362db..95258d4 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/client/brewpi_gui.py b/client/brewpi_gui.py index ecdca4d..3d37a9a 100755 --- a/client/brewpi_gui.py +++ b/client/brewpi_gui.py @@ -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)