Log average values - #266
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
It silently ignores explicitly requested reserved external signal names (time, time_utc) in external_data.log_channels, which should fail fast to avoid confusing mismatches in output.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR changes Hercules’ log_every_n behavior from downsampling (logging every Nth step) to logging window-averaged values over each N-step window, reducing aliasing artifacts from transient overshoots while keeping the same row cadence (dt_log = dt_sim * log_every_n).
Changes:
- Update HDF5 logging to accumulate per-step values and write per-window arithmetic means, while keeping
time/stepanchored to the first step in each window. - Add
metadata.logging_mode = "window_average"and clarify logging semantics across docs. - Strengthen tests to deterministically validate window-averaged logging (including a short final window).
File summaries
| File | Description |
|---|---|
hercules/hercules_model.py |
Implements window-averaged logging, adds logging mode metadata, and skips reserved external-signal timing columns. |
tests/hercules_model_test.py |
Updates log_every_n tests to verify window averaging using controlled plant.power values. |
docs/output_files.md |
Documents new metadata semantics (logging_mode) and updated meaning of log_every_n. |
docs/hercules_model.md |
Explains window-averaged behavior and its effect on time/step/time_utc. |
docs/hercules_input.md |
Updates user-facing input documentation for log_every_n window averaging. |
docs/h_dict.md |
Updates log_every_n description to reflect window-averaged meaning. |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # "time" and "time_utc" are reserved timing columns from the source | ||
| # CSV; the reader reconstructs time_utc from metadata, so skip them. | ||
| if signal_name in ("time", "time_utc"): | ||
| continue |
|
Instead of changing what It would seem to me that hardcoding the mean is a somewhat significant change in the behavior, although I suppose in most (maybe all?) of the examples we just log every 1, so those wouldn't change. |
That makes sense @misi9170 , so if I code so we keep |
|
@paulf81 or have the default be |
|
I had agreed on |
|
Hmm... might just have to agree to disagree. I see what you mean, but it seems to me that an overshoot could be catastrophic, so shouldn't be "hidden" in a mean unless the user specifically asks for it. But then again, sampling every n can also easily miss overshoots, so perhaps the counterargument is that at least the mean captures all data. The most conservative is probably max, or maybe min, but those are not very good defaults :) |
|
Ok @misi9170 , I take your point here. The overshoot issue is I understand is mostly an artifact of larger time steps, we don't want the controller to cheat, so the true solution would be smaller time steps, but that mostly costs a lot more for a little benefit. Maybe let's just talk this through live tomorrow if you have time, I agree this one is probably worth not rushing a decision on |
Hercules features an input value
log_every_nthat, to save space and make post-processing more efficient, if > 1, logs every nth step to the log file. Previously, this worked exactly as said, iflog_every_nwas 4, and only every 4th step would be logged and the time step of the log file would be that multiple of the underlying time step, ie:This PR mostly keeps that same behavior, but instead of logging every nth value, the average over those n-values is logged (except for step, time and time_utc which are left to be the first step in the n_window.)
The reason for the change is that there can be be minor overshoots in power during simulation, that are corrected in one step. However, if we log say only every 10th step, these overshoots can appear to last 10 steps, which can meaningfully distort the results. This PR corrects by using a simple arithmatic mean in its place to restore the overshoot to a more minor issue.