feat: validate extremes options against cluster_on#91
Conversation
extremes method 'replace' builds a hybrid representative (some columns from the medoid, some from the extreme period). Under cluster_on the clustering is built on the active subset and transferred to the carried columns via ClusteringResult.apply(), which cannot reproduce that hybrid and silently falls back to the medoid. Rather than degrade quietly, validate up-front and raise, pointing users to 'weights' — a low weight de-emphasises a column without excluding it from the single aggregation pass, so 'replace' stays reproducible. 'append'/'new_cluster' on clustered-on columns are unaffected and keep working (new positive test locks this in). 519 passed, mypy + ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
An ExtremeConfig that names a coordinate cluster_on excluded previously surfaced tsam's misleading "Extreme period columns not found in data" — the column *is* in the user's DataArray; cluster_on dropped it from the active subset. Validate up-front against the passive coords and raise a message that names the real cause and the fix (add it to cluster_on, or drop it from the ExtremeConfig). 520 passed, mypy + ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds validation in ChangesExtremes/cluster_on validation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/tsam_xarray/_core.py (1)
184-200: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd
Args:andRaises:sections to the docstring.This validator's sole purpose is to raise, yet the docstring documents neither its parameters nor the
ValueErrorit raises. Add Google-styleArgs:andRaises:sections.As per coding guidelines: "Use Google-style docstrings with
Args:,Returns:,Raises:,Attributes:sections".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/tsam_xarray/_core.py` around lines 184 - 200, The docstring on the validator in the `_core.py` cluster_on validation helper currently explains the behavior but does not follow the required Google-style structure. Update that docstring to include an `Args:` section for the validator’s inputs and a `Raises:` section documenting the `ValueError` it can emit, keeping the existing explanation tied to the cluster_on/ExtremeConfig checks and the `method="replace"` handling.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/tsam_xarray/_core.py`:
- Around line 184-200: The docstring on the validator in the `_core.py`
cluster_on validation helper currently explains the behavior but does not follow
the required Google-style structure. Update that docstring to include an `Args:`
section for the validator’s inputs and a `Raises:` section documenting the
`ValueError` it can emit, keeping the existing explanation tied to the
cluster_on/ExtremeConfig checks and the `method="replace"` handling.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4deddda6-4048-438b-a328-257165a93455
📒 Files selected for processing (2)
src/tsam_xarray/_core.pytest/test_aggregate.py
What
Follow-up to #89. Adds up-front validation for the two ways an
ExtremeConfigsilently misbehaves when combined withcluster_on.Under
cluster_on, the clustering is built on the active subset and transferred to the carried columns viaClusteringResult.apply(). Two extremes settings don't survive that transfer, and today both fail unhelpfully:method="replace"ValueError, steers toweightscluster_on-excluded coordExtreme period columns not found in data(the column is in the DataArray)ValueErrornaming the real causeappend/new_cluster)Why
replace:apply()can't reproduce the hybridreplacerepresentative (some columns from the medoid, some from the extreme period), so it quietly returns the medoid. The error points users toweightsinstead: a low weight de-emphasises a column without excluding it from the single aggregation pass, soreplacestays reproducible. (The veryweights-clamp that makesweights=0a footgun for exclusion is what makes it the right tool here.)How
Both checks live in one
_validate_extremes_with_cluster_on(), called right aftercluster_onnormalization — so they fail before any aggregation runs. Only active whencluster_onactually restricts.Tests
test_replace_extremes_rejected— rejection + messagetest_extremes_on_excluded_column_rejected— clear cause, not tsam's cryptic errortest_append_extremes_allowed— locks in that we do not over-reject legitimateappendFull suite green, mypy + ruff clean. Docstring updated with both restrictions.
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Documentation