Repository navigation
Diagnostics: operating-curve filter figures for every reference turbine - #153
Merged
Merged
Conversation
…nce turbine too
The kept-vs-removed, kept-only and kept-vs-excluded operating-curve figures were drawn for the
test turbine alone, so a reference with bad data (a stuck anemometer, a mis-scaled power signal,
a special operating mode nobody flagged) was invisible in the run's plots even though it corrupts
a toggle estimate as surely as a bad test turbine. The same three figures are now written for
each reference, from that reference's own power, wind speed, pitch and rpm, as
{ref}_ops_curves.png, {ref}_ops_curves_kept_only.png and {ref}_ops_curves_excluded.png alongside
the test turbine's unchanged files in plots/2_filter.
"Kept" is the method's used timestamps for every turbine (a timestamp is used only when the test
turbine and every reference passed), so a reference's kept-only figure shows exactly which of its
rows fed the estimate. The excluded figure colours each reference by its own exclude_row flag
(new DiagnosticContext.turbine_excluded_mask) rather than the run-wide excluded_ts mask, which is
the union over turbines and would hide which turbine carried the flag. A reference with nothing
excluded, or too little wind speed to draw a curve against, gets no figure.
Shared plots may now return a list of paths for a figure drawn per turbine;
write_common_diagnostics flattens them.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
Diagnostics should use the method’s effective reference set rather than every non-test turbine in the input data.
No open issues 🎉
What changed in this PR
This pull request extends filter-stage operating-curve diagnostics from the test turbine to reference turbines, using each turbine’s own signals and exclusion flags while preserving existing test-turbine filenames.
Changes:
- Generates standard, kept-only, and excluded operating-curve figures for reference turbines.
- Adds per-turbine exclusion-mask handling.
- Supports diagnostic plots returning multiple output paths.
- Adds regression coverage for reference figures, filenames, exclusions, and missing signals.
- The effective reference set used by the estimate is not currently propagated into diagnostics, so figures may be generated for turbines outside the actual reference group.
| File | Description |
|---|---|
tests/benchmarking/diagnostics/test_diagnostics.py |
Tests reference figures, filenames, exclusion behavior, and missing-signal handling. |
benchmarking/diagnostics/curves.py |
Generalizes operating-curve plotting across the test turbine and references. |
benchmarking/diagnostics/context.py |
Adds per-turbine exclusion-mask extraction aligned to the diagnostic index. |
benchmarking/diagnostics/common.py |
Supports diagnostic functions returning lists of output paths. |
Review effort: Lite
aclerc
added a commit
that referenced
this pull request
Nov 3, 2026
…s without operating-state labels #153 drew the kept-vs-removed and kept-only operating-curve figures for every reference turbine; the C3 merge dropped both, since a labelled run draws its used and unused records as the uplift-validity scatters instead. A toggle run carries no operating-state labels, so it was left with neither view of which rows, its references' included, fed the estimate. Both figures are back, per turbine and in the valid-records stage, and stay off for a labelled run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aclerc
added a commit
that referenced
this pull request
Nov 3, 2026
…s without operating-state labels (#155) #153 drew the kept-vs-removed and kept-only operating-curve figures for every reference turbine; the C3 merge dropped both, since a labelled run draws its used and unused records as the uplift-validity scatters instead. A toggle run carries no operating-state labels, so it was left with neither view of which rows, its references' included, fed the estimate. Both figures are back, per turbine and in the valid-records stage, and stay off for a labelled run. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The three filter-stage operating-curve figures (
ops_curves.png,ops_curves_kept_only.png,ops_curves_excluded.png) were drawn for the test turbine only. They are now also written for every reference turbine in the run, from that reference's own power, wind speed, pitch and generator rpm, as{ref}_ops_curves.png,{ref}_ops_curves_kept_only.pngand{ref}_ops_curves_excluded.pngin the sameplots/2_filter/folder (the per-turbine prefix convention{wtg}_coverage_timeseries.png/{wtg}_pairing_gap.pngalready use). The test turbine's filenames are unchanged. Each figure's suptitle names the turbine it shows.Why
In a toggle run a reference with bad data (a stuck anemometer, a mis-scaled power signal, a special operating mode nobody flagged) corrupts the estimate as surely as a bad test turbine, but the test turbine's figures cannot show it. With one set of figures per reference the whole reference group can be eyeballed in the filter stage before the estimate is trusted.
ColumnSchema.exclude_rowflag (newDiagnosticContext.turbine_excluded_mask), not the run-wideexcluded_tsmask, which is the union over turbines and would hide which turbine carried the flag. A reference with nothing excluded gets no excluded figure.common._PLOTSmay now returnPath | list[Path] | None;write_common_diagnosticsflattens the list form.Test plan
TestReferenceOpsCurvesintests/benchmarking/diagnostics/test_diagnostics.py(written first, watched fail, then made green): the three files are written per reference into2_filter; the test turbine's filenames are unchanged and never prefixed; a reference's excluded figure follows its own flag (a flagged reference gets one, an unflagged one does not, while the run-wide mask is set);turbine_excluded_maskreads the per-turbine column; no reference excluded figures without an exclusion concept; a reference with no wind speed draws nothing for itself.uv run python -m pytest tests/benchmarking/diagnostics -q: 30 passeduv run python -m pytest tests/benchmarking/baselines/test_toggle_specialist.py -k "Exclu or exclu or plot or diagnostic": 28 passeduv run poe lint(ruff format, ruff check, mypy) : clean🤖 Generated with Claude Code