Skip to content

feat(extremes): count-stable clustering and transferable replace#104

Draft
FBumann wants to merge 1 commit into
mainfrom
feat/extremes-count-stable
Draft

feat(extremes): count-stable clustering and transferable replace#104
FBumann wants to merge 1 commit into
mainfrom
feat/extremes-count-stable

Conversation

@FBumann

@FBumann FBumann commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Makes extreme periods composable with the wrapper's fan-out (many independent slices → one rectangular array) and transfer (cluster_on, apply()) paths, by consuming the upstream tsam fix FZJ-IEK3-VSA/tsam#414 (closes upstream #410).

Rebased onto the v4-compatible main (#105), so the wrapper now runs on both released tsam 3.4.x and tsam v4.

What changed

  • Count stability. For the additive extreme methods (append / new_cluster), the wrapper now always forces ExtremeConfig(preserve_n_clusters=True). tsam otherwise appends a data-dependent number of extreme clusters (criteria that resolve to the same period, or an extreme that coincides with a medoid, get deduplicated), so independently-aggregated slices ended up with different cluster counts and failed to stack — the _validate_consistent_cluster_counts error. With the flag, every slice yields exactly n_clusters. Extremes count against the cluster budget rather than adding to it.
  • Transferable replace. The cluster_on + method="replace" rejection is lifted when the installed tsam stores the injection (extreme_replacements) and can replay it through apply(). Previously replace silently degraded to the plain medoid on transfer, so the wrapper hard-rejected it.

Feature-detected — safe on every supported tsam

Both behaviours are gated on introspecting the installed tsam (preserve_n_clusters on ExtremeConfig, extreme_replacements on ClusteringResult):

  • On tsam without the fix (released 3.4.x, and current develop-v4) neither exists → the new code is a no-op. Existing behaviour, the replace rejection, and CI are unchanged.
  • They activate automatically on a tsam that ships the fix.

Validation

  • Released tsam 3.4.x (CI): 572 passed, 9 skipped (the flag-gated tests skip); ruff + mypy clean.
  • tsam v4 + #414 (built locally): 576 passed, 5 skipped — the flag-gated count-stability and replace-transfer tests now execute and pass end-to-end. Directly confirmed preserve_n_clusters=True pins the count across datasets and replace round-trips exactly through apply() and JSON.

Remaining dependency

The only thing left is tsam releasing #414 (currently an open PR on develop-v4). Until a tsam version ships with preserve_n_clusters / extreme_replacements, these paths stay dormant (no-op) on the tsam that CI installs. Kept as draft for that reason — ready to mark for review once #414 lands, or now if you'd prefer to merge the staged wrapper-side changes ahead of it.

Tests

test/test_extremes_composability.py:

  • 30-case fuzz over additive extremes on sliced data — asserts the documented fallback contract on tsam without the flag (success with uniform counts, or the specific count-mismatch error, never anything else) and tightens to an exact == n_clusters assertion where the flag is present.
  • Flag-gated count-stability tests (including that an explicit preserve_n_clusters=False is overridden) and replace-transfer tests (cluster_on + apply() round-trip).

test_replace_extremes_rejected is now skipif the running tsam transfers replace.

Refs FZJ-IEK3-VSA/tsam#414, FZJ-IEK3-VSA/tsam#410.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ec3a3bce-4f4a-4d69-8131-1c1bef49c396

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/extremes-count-stable

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…replace

Consume the tsam fix in FZJ-IEK3-VSA/tsam#414 (closes upstream #410) so
extreme periods compose with the wrapper's fan-out and transfer paths.

- Always force ExtremeConfig(preserve_n_clusters=True) for the additive
  methods (append/new_cluster) so every independently-aggregated slice
  yields exactly n_clusters and results stack rectangularly. Extremes now
  count against the cluster budget instead of adding a data-dependent
  number of extra clusters.
- Lift the cluster_on + method="replace" rejection when the installed tsam
  can transfer the hybrid representative (stores extreme_replacements).
- Both behaviours are feature-detected: no-ops on released tsam (which
  lacks the flag), so existing behaviour and CI are unchanged. They
  activate automatically once tsam_xarray runs on a tsam that ships the
  fix — which requires the v4 pipeline architecture the fix is built on.

Adds test/test_extremes_composability.py: a 30-case fuzz over additive
extremes on sliced data (asserts the fallback count contract today,
tightens to exact-count once the flag is present) plus flag-gated
count-stability and replace-transfer tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@FBumann
FBumann force-pushed the feat/extremes-count-stable branch from dcdfb23 to cdae729 Compare July 23, 2026 11:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant