Uh oh!
There was an error while loading. Please reload this page.
refactor!: strip Clustering to minimal wrapper - #655
Conversation
…lude_original_data BREAKING CHANGES: - Remove ClusteringPlotAccessor (compare, heatmap, clusters methods) - Remove original_data and aggregated_data from Clustering - Remove _metrics from Clustering (use aggregation_result.accuracy instead) - Remove include_original_data parameter from to_dataset/to_netcdf - Simplify _create_reference_structure to just serialize ClusteringResult dict - Remove build_metrics from _ReducedFlowSystemBuilder Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 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 |
Uh oh!
There was an error while loading. Please reload this page.
* refactor: replace per-slice tsam loops with single tsam_xarray.aggregate() call
tsam_xarray handles (period, scenario) slicing internally, eliminating
manual iteration, expand_dims/combine helpers, and per-key DataFrame
conversion. Simplifies _ReducedFlowSystemBuilder, ClusteringResults.apply(),
and the main cluster/apply_clustering methods.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: remove dead code and fix outdated docstrings after tsam_xarray migration
- Remove broken Clustering.sel() (ignored args, use aggregation_result instead)
- Remove unused _from_aggregation_result classmethod
- Fix no-op rename({'cluster': 'cluster'}) in build_typical_periods
- Update docstrings: tsam 3.0 → tsam_xarray, DataFrame → DataArray
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor!: remove ClusteringResults, delegate to tsam_xarray ClusteringInfo
BREAKING: ClusteringResults class removed. Clustering now delegates all
structure properties (cluster_assignments, cluster_occurrences, segment_*,
dims, coords, etc.) directly to tsam_xarray.ClusteringInfo.
- Remove ClusteringResults class (~450 lines) and all _build_property_array machinery
- Remove AggregationResults backwards-compat alias
- Remove get_result(), cluster_start_positions, timesteps_per_period
- Serialization uses ClusteringInfo.to_dict()/from_dict() (tsam_xarray>=0.5.1)
- Auto-detect _unrename_map from slice_dims for deserialization
- Update tests: remove TestClusteringResults, simplify test fixtures
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review feedback
- Add TODO comments for object.__setattr__ weight-clearing workaround
- Add tsam as explicit dependency (directly imported for ClusterConfig etc.)
- Fix dev version pin: tsam_xarray>=0.5.1 (was >=0.1.1)
- Add assertions for variable dim detection in build_typical_periods/metrics
- Inline _build_property_array into timestep_mapping (single-use helper)
- Document when legacy 'results' kwarg can be removed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: eliminate two-step cluster-then-reapply flow
When data_vars is specified, instead of clustering a subset and re-applying
to full data, now all time-varying data goes to tsam_xarray with weight=0
for excluded variables. This removes the object.__setattr__ hack in cluster().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor!: remove data_vars, auto-weights, and clustering_group/weight from API
BREAKING CHANGES:
- Remove `data_vars` parameter from `cluster()` — use `ClusterConfig(weights={var: 0})`
to exclude variables from influencing clustering instead
- Remove `clustering_group` and `clustering_weight` from `TimeSeriesData` — use
`ClusterConfig(weights={...})` directly
- Remove `_calculate_clustering_weights` and `_build_cluster_config_with_weights`
- Stop dropping constant arrays before clustering — pass all time-dim data to tsam_xarray
- Weight validation now handled by tsam_xarray directly
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor!: strip Clustering API — remove dims, coords, metrics, clustering_data, etc.
BREAKING CHANGES:
- Remove from Clustering: dims, coords, cluster_centers, segment_centers,
n_representatives, representative_weights, metrics, position_within_segment
- Remove clustering_data() from TransformAccessor
- Move position_within_segment computation into _Expander (only consumer)
- Use clustering_info directly for advanced access (dims, coords, etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: rename clustering_info → clustering_result to match tsam_xarray
Aligns with tsam_xarray's ClusteringResult class name. Renames property,
internal attribute, parameters, and local variables throughout.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor!: replace expand_data/timestep_mapping with tsam_xarray disaggregate()
Replace the entire custom expansion machinery with tsam_xarray's
ClusteringResult.disaggregate(), combined with xarray's built-in
ffill/interpolate_na/fillna for post-processing segmented data.
Removed:
- expand_data(), build_expansion_divisor(), timestep_mapping (Clustering)
- _build_timestep_mapping() helper function
- _interpolate_charge_state_segmented(), _expand_first_timestep_only() (_Expander)
- _compute_position_within_segment() (_Expander)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor!: remove legacy variable category fallback from _Expander
Remove backwards-compat pattern matching (_is_state_variable,
_is_first_timestep_variable, _build_segment_total_varnames) that was
only needed for FlowSystems saved before _variable_categories was added
in v6.0. Now requires _variable_categories to always be present.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor!: remove ClusteringPlotAccessor, metrics, original_data, include_original_data (#655)
BREAKING CHANGES:
- Remove ClusteringPlotAccessor (compare, heatmap, clusters methods)
- Remove original_data and aggregated_data from Clustering
- Remove _metrics from Clustering (use aggregation_result.accuracy instead)
- Remove include_original_data parameter from to_dataset/to_netcdf
- Simplify _create_reference_structure to just serialize ClusteringResult dict
- Remove build_metrics from _ReducedFlowSystemBuilder
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add expansion regression tests for cluster → optimize → expand pipeline
Verifies numerical equivalence of expanded solution values for both
non-segmented and segmented clustering, including flow rates, costs,
objectives, shapes, and NaN-free expansion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs!: consolidate clustering notebooks, remove obsolete ones
BREAKING: Remove 3 clustering notebooks, update 1:
- Remove 08d-clustering-multiperiod.ipynb (tsam_xarray handles this)
- Remove 08e-clustering-internals.ipynb (internals no longer exist)
- Remove 08f-clustering-segmentation.ipynb (just a parameter, covered in 08c)
- Update 08c-clustering.ipynb: remove clustering_data, data_vars, plot.compare,
metrics sections; add tsam_xarray links; update API reference
5 clustering notebooks → 2 (08c + 08c2-storage-modes)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add temporal_resolution to reserved_tsam_keys guard
Prevents users from silently overriding the computed timestep size
via tsam_kwargs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: remove links to notebooks that don't exist yet
Remove references to 08d-clustering-multiperiod, 08e-clustering-internals,
and 08f-clustering-segmentation notebooks that haven't been created yet.
These caused mkdocs --strict to abort with broken link warnings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: address PR review and adapt to tsam_xarray 0.6.0
Bump pins to tsam_xarray>=0.6.0 (handles time_coords natively) and
tsam>=3.4.0 (apply() respects original weights). Drop the corresponding
workarounds: the object.__setattr__(time_coords) hack in Clustering and
the weight-clearing loop in apply_clustering.
Other review follow-ups:
- Remove the legacy `results=` kwarg from Clustering.__init__ and the
matching fallback in from_json — pre-refactor netcdfs can't load anyway.
- Strip dead clustering_arrays plumbing in io.py (always empty post-refactor).
- Remove no-op rename(cluster='cluster') in build_cluster_weights.
- Replace bare assert in build_typical_periods with ValueError.
New: transform.cluster_inputs() returns the Dataset of variables that
cluster() will pass to tsam (every time-dim var, constants included). Use
to enumerate columns for ClusterConfig(weights={...}). Different from v5's
clustering_data() — not a rename, the v5 set isn't meaningful anymore.
Tests:
- TestClusterInputs: enumeration, constants, documented weight-zero pattern,
drift guard between cluster_inputs() and what cluster() feeds tsam.
- test_dim_names_order: Clustering.dim_names == ['period', 'scenario'] for
period+scenario FlowSystems.
- test_cluster_with_constant_columns: clustering must not crash on
zero-variance columns now that drop_constant_arrays is gone.
- Strengthened test_clustering_result_preserved_after_load with deeper
equality on cluster_assignments / cluster_occurrences / dim_names.
- test_expansion_regression: derive reference values from fixture parameters
(mean*hours/eta*price) instead of pinned magic numbers.
Docs:
- Migration guide: removed-API summary table, new cluster_inputs() entry,
default-weight-is-1.0 callout, netcdf-incompat note.
- Notebook 08c: callout explaining which variables get clustered by default
and how to scope clustering via ClusterConfig(weights={...}).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(clustering): correct segmented state expansion and single-slice extremes guard
Two defects found while reviewing the tsam_xarray migration:
- Segmented state variables (e.g. Storage charge_state) were expanded with a
global interpolate_na, which interpolated across period boundaries and left
the final period's last segment as NaN in the solution. Replace with a
segment-aware linear interpolation between the (loss-correct) segment boundary
values, matching the pre-refactor behavior. No NaN, no cross-period bleed.
- The ExtremeConfig guard rejected any system with a period/scenario dimension,
including length-1 indices that produce a single clustering slice where any
extremes method is valid. Gate on slice count (n_periods * n_scenarios > 1)
instead of presence.
Adds regression tests: segmented + storage expand has no NaN in charge_state;
single-period new_cluster is allowed while genuine multi-period still requires
method='replace'.
* style: ruff format test_clustering/test_integration.py
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered) for plotting - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Also restore clustering.plot.compare() as a thin, supported accessor that delegates to compare() and builds a plotly figure (timeseries / duration_curve), matching the pre-v7 look (color=variable, Original=dot / Clustered=solid). Docs: - migration-guide-v7: concrete compare recipe + multi-variable/period/scenario - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) in the migration guide and the 08c-clustering notebook Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered) for plotting - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Also restore clustering.plot.compare() as a thin, supported accessor that delegates to compare() and builds a plotly figure (timeseries / duration_curve), matching the pre-v7 look (color=variable, Original=dot / Clustered=solid). Docs: - migration-guide-v7: concrete compare recipe + multi-variable/period/scenario - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) in the migration guide and the 08c-clustering notebook Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered) for plotting - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Also restore clustering.plot.compare() as a thin, supported accessor that delegates to compare() and builds a plotly figure (timeseries / duration_curve), matching the pre-v7 look (color=variable, Original=dot / Clustered=solid). Signature is compare(variables=None, *, kind=...) — variables first, matching Clustering.compare(). A tsam_xarray-side compare plot is proposed upstream (FBumann/tsam_xarray#95); this accessor will thin to a forward once that lands. Docs: - migration-guide-v7: concrete compare recipe + multi-variable/period/scenario - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - 08c-clustering notebook: demo cell for clustering.plot.compare() - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) in the migration guide and the 08c-clustering notebook Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered), plot-ready - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Plotting is left to the user: compare() returns tidy data, so a chart is a one-liner (px.line(compare(var).to_dataframe()[['original','clustered']])). The tidy data helper is now upstream in tsam_xarray (FBumann/tsam_xarray#92). Docs: - migration-guide-v7: compare recipe (timeseries + duration curve) and multi-variable/period/scenario notes - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - 08c-clustering notebook: demo cell plotting compare() with plotly express - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered), plot-ready - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Plotting is left to the user: compare() returns tidy data, so a chart is a one-liner (px.line(compare(var).to_dataframe()[['original','clustered']])). The tidy data helper is now upstream in tsam_xarray (FBumann/tsam_xarray#92). Docs: - migration-guide-v7: compare recipe (timeseries + duration curve) and multi-variable/period/scenario notes - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - 08c-clustering notebook: demo cell plotting compare() with plotly express - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered), plot-ready - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Plotting is left to the user: compare() returns tidy data, so a chart is a one-liner (px.line(compare(var).to_dataframe()[['original','clustered']])). The tidy data helper is now upstream in tsam_xarray (FBumann/tsam_xarray#92). Docs: - migration-guide-v7: compare recipe (timeseries + duration curve) and multi-variable/period/scenario notes - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - 08c-clustering notebook: demo cell plotting compare() with plotly express - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered), plot-ready - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Plotting is left to the user: compare() returns tidy data, so a chart is a one-liner (px.line(compare(var).to_dataframe()[['original','clustered']])). The tidy data helper is now upstream in tsam_xarray (FBumann/tsam_xarray#92). Docs: - migration-guide-v7: compare recipe (timeseries + duration curve) and multi-variable/period/scenario notes - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - 08c-clustering notebook: demo cell plotting compare() with plotly express - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered), plot-ready - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Plotting is left to the user: compare() returns tidy data, so a chart is a one-liner (px.line(compare(var).to_dataframe()[['original','clustered']])). The tidy data helper is now upstream in tsam_xarray (FBumann/tsam_xarray#92). Docs: - migration-guide-v7: compare recipe (timeseries + duration curve) and multi-variable/period/scenario notes - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - 08c-clustering notebook: demo cell plotting compare() with plotly express - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restore a first-class way to compare original vs clustered profiles, which regressed when clustering.plot.compare() was removed in v7 (#655). Reported in discussion #728. New accessors on Clustering (pre-serialization): - compare(variable=None) -> tidy Dataset(original, clustered), plot-ready - original / reconstructed / residuals / accuracy These un-rename tsam_xarray's internal dims (_period -> period) and align original/reconstructed dim order, so users select with the natural coord names instead of the raw aggregation_result's _period. Plotting is left to the user: compare() returns tidy data, so a chart is a one-liner (px.line(compare(var).to_dataframe()[['original','clustered']])). The tidy data helper is now upstream in tsam_xarray (FBumann/tsam_xarray#92). Docs: - migration-guide-v7: compare recipe (timeseries + duration curve) and multi-variable/period/scenario notes - clustering.md: replace stale clustering.metrics section (removed in v7) with clustering.accuracy / compare() - 08c-clustering notebook: demo cell plotting compare() with plotly express - fix broken tsam_xarray repo links (FZJ-IEK3-VSA -> FBumann) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Builds on #654. Further strips the Clustering class to a minimal wrapper around tsam_xarray.
ClusteringPlotAccessorentirely (~370 lines) — users can plot with tsam_xarray's DataArrays directlyoriginal_data,aggregated_data,_metricsfrom Clustering — no longer stored or serializedinclude_original_dataparameter fromto_dataset()/to_netcdf()build_metrics()from_ReducedFlowSystemBuilder_create_reference_structure()to just serializeClusteringResult.to_dict()+original_timestepsxrandnpimports to TYPE_CHECKING (no longer needed at runtime in base.py)base.py: 1633 → 393 lines (-76%)Test plan
🤖 Generated with Claude Code