You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AI-written analysis (Claude Code, prompted by @FBumann). This is a scope question for #717 — the decision window closes when v1 ships, because afterwards any change here is a breaking change with a deprecation cycle.
The question
Every difficult problem in the #732 → #737 → #742 → #717 chain traces back to one root: linopy supports stacked pd.MultiIndex dimensions as a first-class data model. Should v1 keep that — or replace it with a representation that needs none of the machinery?
This is the radical version of the "learn from the xarray community, which struggled a lot with MIs" argument that decided scenario B.
Verified against the current #717 branch (all snippets run):
x=m.add_variables(coords=[snapshots], name="x") # ✅ worksexpr= (1*x).assign_coords(period=period) # ✅ aux coords attach# per-period weighting — same explicit recipe as the MI case:w=xr.DataArray(weights[period.values].values, dims="snapshot", ...)
expr*w# ✅ works, no projection machinery involved# groupby a level:expr.drop_vars("period").groupby(period.rename("inv_period")).sum() # ⚠️ works, but needs the# drop/rename dance — naming# conflict otherwise (fixable)
Sparse indexes (not every combination exists) are naturally representable — that's what a flat list is. The stacked/unstacked round-trip, the projection, the coverage-gap concept: none of them exist in this representation.
Three options
Internal complexity
PyPSA impact
Tuple .sel() / .unstack()
A. Disallow MI (TypeError → point to flat+aux)
deleted
n.snapshots API migration
gone
B. Convert at the boundary (MI accepted as input, stored flat+aux, re-stacked on output)
#717 currently implements C — including the machinery that the legacy-removal checklist says survives 1.0. If the answer is A or B, that machinery (and the spec section, and the tests) should not ship in v1 at all. After v1 ships with C, moving to A/B is a user-facing breaking change.
No position is taken here — the trade-off is real on both sides (PyPSA's n.snapshots API is the crux). But it should be a decision, not a default.
Note
AI-written analysis (Claude Code, prompted by @FBumann). This is a scope question for #717 — the decision window closes when v1 ships, because afterwards any change here is a breaking change with a deprecation cycle.
The question
Every difficult problem in the #732 → #737 → #742 → #717 chain traces back to one root: linopy supports stacked
pd.MultiIndexdimensions as a first-class data model. Should v1 keep that — or replace it with a representation that needs none of the machinery?This is the radical version of the "learn from the xarray community, which struggled a lot with MIs" argument that decided scenario B.
What MultiIndex support costs
_project_onto_multiindex_levels,_LevelProjection,_as_multiindex_coords_to_dict,validate_alignment,_broadcast_to_coords(expand-via-template)assign_multiindex_safe(~20 call sites),get_dims_with_index_levels, MI serialization incoords_to_dataset_varsTestMultiIndexProjection+ MI tests across 6 filesPlus a permanent tax: every future feature must answer "and what about MultiIndex?".
The alternative: flat dim + auxiliary level coords
The same information, no
pd.MultiIndexanywhere — and §11 already governs auxiliary coords:Verified against the current #717 branch (all snippets run):
Sparse indexes (not every combination exists) are naturally representable — that's what a flat list is. The stacked/unstacked round-trip, the projection, the coverage-gap concept: none of them exist in this representation.
Three options
.sel()/.unstack()TypeError→ point to flat+aux)n.snapshotsAPI migrationWhat B would mean concretely
coords=[multiindex]still works — linopy decomposes it into flat dim + level aux-coords on entry.solution/dualcome back flat-indexed with level coords as columns; PyPSA re-stacks for its users (oneset_index(levels)call).Why this needs deciding now
#717 currently implements C — including the machinery that the legacy-removal checklist says survives 1.0. If the answer is A or B, that machinery (and the spec section, and the tests) should not ship in v1 at all. After v1 ships with C, moving to A/B is a user-facing breaking change.
No position is taken here — the trade-off is real on both sides (PyPSA's
n.snapshotsAPI is the crux). But it should be a decision, not a default.