Feature/v3/feature/367 rename year dimension to period 2#370
Conversation
…me and "periodic" instead of "nontemporal" for the effect domain
|
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 You can disable this status message by setting the WalkthroughRenames “nontemporal/year” to “periodic/period” across the codebase. Public APIs change accordingly (e.g., FlowSystem years→periods; Effect parameters and modes switch to periodic). Coordinates/dims rekeyed to period. Results/calculation keys updated to periodic. One control-flow tweak in FlowSystemModel.weights consolidates weight fitting/normalization. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User
participant FS as FlowSystem
participant ECM as EffectCollectionModel
participant SOL as Solver
participant RES as Results
U->>FS: build(model with period coords)
FS->>ECM: add Effect(temporal, periodic)
note right of ECM: total = temporal + periodic
ECM->>SOL: optimize (period/time/scenario dims)
SOL-->>ECM: solution vars
ECM-->>RES: effects dataset (temporal/periodic/total)
RES-->>U: costs(periodic), shares, totals
sequenceDiagram
autonumber
participant FSM as FlowSystemModel
participant FIT as fit_to_model_coords
FSM->>FSM: get weights
alt weights provided
FSM-->>FSM: return provided weights
else weights missing
FSM->>FIT: fit weights over ('period','scenario')
FIT-->>FSM: fitted weights
FSM-->>FSM: normalize (divide by sum)
end
FSM-->>FSM: use weights in modeling
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (3 warnings)
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 |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
flixopt/components.py (1)
833-839: Discharge efficiency applied in the wrong direction (physics + doc mismatch)Docstring states charge[t+1] subtracts discharge_flow / eta_discharge. Implementation multiplies by eta_discharge, which increases effective storage energy for η<1.
Apply discharge efficiency as a divisor:
- - discharge_rate * eff_discharge * hours_per_step, + - discharge_rate * hours_per_step / xr.where(eff_discharge != 0, eff_discharge, np.nan),If xarray import scope disallows np.nan here, precompute a safe divisor. Update tests that hard-code the previous (incorrect) formulation (see tests/test_storage.py lossy case).
I can adjust the affected tests and add a regression test for η_discharge handling. Want a patch?
flixopt/flow_system.py (1)
273-283: from_dataset passes an unexpected constructor argument.FlowSystem.init has no periods_of_last_period parameter, but from_dataset passes it. This raises TypeError during restore.
Apply one of the fixes (A: remove arg, B: add optional param):
- periods_of_last_period=reference_structure.get('periods_of_last_period'),Or, if needed elsewhere, add it to init with default and store in attrs. Choose A unless you use it later.
</blockquote></details> <details> <summary>flixopt/effects.py (1)</summary><blockquote> `171-179`: **Type hints for min/max fields should be Data, not Effects mappings.** minimum_temporal/maximum_temporal/minimum_periodic/maximum_periodic should accept PeriodicDataUser (or Scalar), not PeriodicEffectsUser (which maps effect→value). This will confuse type checkers and readers. ```diff - minimum_temporal: PeriodicEffectsUser | None = None, - maximum_temporal: PeriodicEffectsUser | None = None, - minimum_periodic: PeriodicEffectsUser | None = None, - maximum_periodic: PeriodicEffectsUser | None = None, + minimum_temporal: PeriodicDataUser | None = None, + maximum_temporal: PeriodicDataUser | None = None, + minimum_periodic: PeriodicDataUser | None = None, + maximum_periodic: PeriodicDataUser | None = None,
🧹 Nitpick comments (8)
CHANGELOG.md (1)
125-126: Clarify deprecation vs breaking/removal for renamed Effect params.
- Lines 125–126 are under “Deprecated” but look like immediate renames that will break users if old names stop working.
- Line 135 states the share parameter change happened WITHOUT DEPRECATION.
To avoid ambiguity, either:
- Move truly breaking renames to “Breaking Changes”/“Removed”, or
- Explicitly state old names are still accepted and scheduled for removal in version X.Y with a deprecation window.
Proposed wording tweak:
-### 🗑️ Deprecated -* Renamed `Effect` parameters: +### 🗑️ Deprecated +* Effect parameters deprecated (old names still accepted until 3.0, then removed): - `minimum_investment` → `minimum_periodic` - `maximum_investment` → `maximum_periodic`And under “🔥 Removed” add the explicit note that the
specific_share_to_other_effects_*→share_from_*happened without deprecation (already present).Also applies to: 135-135
tests/conftest.py (1)
45-63: Fixture updates to periods/scenarios — LGTM. Consider adding time+scenarios (no periods).A fourth param set with periods=None and scenarios non‑None would increase coverage for logging/summary paths that assume periodic keys.
params=[ { 'timesteps': pd.date_range('2020-01-01', periods=10, freq='h', name='time'), 'periods': None, 'scenarios': None, }, + { + 'timesteps': pd.date_range('2020-01-01', periods=10, freq='h', name='time'), + 'periods': None, + 'scenarios': pd.Index(['A', 'B'], name='scenario'), + }, { 'timesteps': pd.date_range('2020-01-01', periods=10, freq='h', name='time'), 'periods': pd.Index([2020, 2030, 2040], name='period'), 'scenarios': None, }, { 'timesteps': pd.date_range('2020-01-01', periods=10, freq='h', name='time'), 'periods': pd.Index([2020, 2030, 2040], name='period'), 'scenarios': pd.Index(['A', 'B'], name='scenario'), }, ], - ids=['time_only', 'time+periods', 'time+periods+scenarios'], + ids=['time_only', 'time+scenarios', 'time+periods', 'time+periods+scenarios'],flixopt/modeling.py (1)
661-673: Infercoordfromlevel_variable.dimsto reduce coupling.
To support custom time-dimension names and avoid silent mismatches, auto-detect the time-like dim when the default'period'isn’t present:@@ def link_changes_to_level_with_binaries(...): - coord: str = 'period', + coord: str = 'period', @@ - # 1. Initial period: level[0] - initial_level = increase[0] - decrease[0] + # Auto-infer time dimension if needed + if coord not in level_variable.dims: + candidates = [d for d in ('period', 'time') if d in level_variable.dims] + coord = candidates[0] if candidates else level_variable.dims[0] + # 1. Initial period: level[0] - initial_level = increase[0] - decrease[0]flixopt/core.py (1)
626-629: Backward-compat aliases present; consider deprecation messaging.If you plan to drop NonTemporal* soon, add a DeprecationWarning on access or document the removal timeline (e.g., in CHANGELOG).
tests/test_effect.py (1)
65-66: Zeroing periodic totals in “minimal/bounds” tests may mask real shares.Both tests force periodic totals to 0. If future components/effects provide periodic shares, these asserts will fail unexpectedly. Prefer asserting presence/shape or non-negativity unless explicitly testing zero-share scenarios.
- assert_conequal(model.constraints['Effect1(periodic)'], model.variables['Effect1(periodic)'] == 0) + # Assert variable exists and has expected coords; value depends on model inputs + assert 'Effect1(periodic)' in model.variables + assert set(model.variables['Effect1(periodic)'].dims) == set(model.get_coords(['period','scenario']).keys())Also applies to: 139-142
flixopt/results.py (1)
621-676: Effects dataset construction: strengthen naming and guard template.
- On scalar-NaN paths, use xr.full_like with dtype=float (good). After concatenation, ensure var names are consistent.
- ds[effect] = xr.concat(component_arrays, dim='component', coords='minimal') + ds[effect] = xr.concat(component_arrays, dim='component', coords='minimal').rename(effect)Also consider raising on mismatch instead of only logging critical; tests will catch regressions earlier.
- if not np.allclose(computed.values, found.fillna(0).values): - logger.critical( + if not np.allclose(computed.values, found.fillna(0).values): + raise ValueError( f'Results for {effect}({mode}) in effects_dataset doesnt match {label}\n{computed=}\n, {found=}' )flixopt/flow_system.py (1)
429-441: Weights normalization: consider normalizing instead of warning.Currently logs a warning but proceeds. Optional auto-normalization would avoid scaling surprises.
if self.weights is not None: total = float(self.weights.sum().item()) if not np.isclose(total, 1.0, atol=1e-12): - logger.warning( - 'Scenario weights are not normalized to 1. Normalizing to 1 is recommended for a better scaled model. ' - f'Sum of weights={total}' - ) + logger.warning('Scenario weights sum to %s. Auto-normalizing to 1.', total) + self.weights = self.weights / totalflixopt/effects.py (1)
769-837: BFS accumulation in conversion paths: confirm intended sum semantics.You sum parallel paths’ factors. If shares are meant to combine additively, fine; if they should multiply or choose shortest-path, document it. Consider casting all factors to consistent dtype early.
- result = {} + result: dict[tuple[str,str], xr.DataArray | np.ndarray | float | int] = {}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
CHANGELOG.md(3 hunks)examples/04_Scenarios/scenario_example.py(2 hunks)examples/05_Two-stage-optimization/two_stage_optimization.py(1 hunks)flixopt/calculation.py(1 hunks)flixopt/components.py(3 hunks)flixopt/core.py(2 hunks)flixopt/effects.py(18 hunks)flixopt/elements.py(4 hunks)flixopt/features.py(10 hunks)flixopt/flow_system.py(13 hunks)flixopt/interface.py(6 hunks)flixopt/modeling.py(1 hunks)flixopt/results.py(17 hunks)flixopt/structure.py(1 hunks)tests/conftest.py(1 hunks)tests/test_effect.py(12 hunks)tests/test_flow.py(16 hunks)tests/test_integration.py(2 hunks)tests/test_storage.py(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: test (3.12)
- GitHub Check: test (3.13)
- GitHub Check: test (3.11)
- GitHub Check: test (3.10)
🔇 Additional comments (32)
CHANGELOG.md (1)
58-59: Example aligns with new “periodic” naming — LGTM.Snippet correctly uses share_from_periodic alongside share_from_temporal.
examples/05_Two-stage-optimization/two_stage_optimization.py (1)
149-151: Variables verified:costs(periodic)andcosts(temporal)are present; nocosts(nontemporal)risk
The selection keys'costs','costs(periodic)', and'costs(temporal)'all exist intwo_stage_optimization.py, and there is no longer any reference to'costs(nontemporal)'. No KeyError is expected.flixopt/calculation.py (1)
106-115: Periodic submodel always present — no guard needed
EffectModel._do_modelingunconditionally createsself.periodicfor every effect, soeffect.submodel.periodicis always defined and won’t raise an AttributeError.Likely an incorrect or invalid review comment.
tests/test_storage.py (1)
291-296: Rename to period/scenario looks correctInvestment variables now use coords over ['period','scenario'], matching the new API.
tests/test_integration.py (3)
131-136: Updated to periodic keysExpectation strings updated to costs(periodic). Aligns with API.
137-141: Updated storage costs keySpeicher->costs(periodic) reference matches rename.
148-152: CO2(periodic) key renameMatches the new output naming.
examples/04_Scenarios/scenario_example.py (2)
14-15: Introduce periods IndexUsing periods=pd.Index([...]) is correct for the new API.
24-25: FlowSystem weights broadcasting confirmed: 1D scenario weights are aligned to bothperiodandscenariodims and broadcast across periods as intended.flixopt/components.py (2)
374-387: Storage ctor: PeriodicDataUser typesParameter typing updated for period-based data. Looks consistent with the rename.
445-468: Ensure final relative charge-state dims align with temporal concat
The hard-coded dims=['period','scenario'] forrelative_minimum_final_charge_stateandrelative_maximum_final_charge_statemay not match the time-based dims of the originalrelative_*_charge_state, causingxr.concat(..., dim='time')to misalign or fail. Verify and update thedimspassed toflow_system.fit_to_model_coordsfor these final states so they match the existing temporal dims (i.e., drop 'time' from the original dims) before concatenation.tests/test_flow.py (4)
30-32: LGTM on period-dimension migration in tests.Assertions now consistently use model.get_coords(['period','scenario']) and '(periodic)' effect channels; they align with implementation changes in features/elements.
Also applies to: 69-70, 182-183, 243-248, 315-323, 388-392, 471-478, 483-487, 508-513, 566-568, 1015-1016, 1060-1061, 1132-1133, 1159-1160, 1231-1232, 440-441
471-478: Nice coverage for periodic investment/divest effects.Checks for costs/CO2(periodic) variables and constraints look correct and validate both fixed/specific and divest cases.
Also applies to: 508-513, 1015-1016, 1060-1061
243-248: Good consistency on size/on_hours_total bounds over ['period','scenario'].Bounds for size, on_hours_total, and switch|count match the new periodic API.
Also applies to: 317-323, 390-392, 441-441, 567-568, 1132-1133, 1159-1160, 1231-1232
1-1329: No stale ‘year’ dimensions found outside documentation. Repo-wide scan returned matches only in CHANGELOG, plotting docstrings, and project metadata.flixopt/features.py (4)
61-62: Periodic coords and targets applied correctly.Size/is_invested now over ['period','scenario']; investment effects target='periodic'. Matches tests.
Also applies to: 67-68, 100-101, 110-111, 117-118
173-179: Use None instead of np.inf for unbounded upper.np.inf as an upper bound can inflate coefficients and degrade solver stability. Prefer None to indicate “unbounded” (consistent with FlowModel usage).
[ suggest_recommended_refactor ]
Apply this diff:- bounds=( - self.parameters.on_hours_total_min if self.parameters.on_hours_total_min is not None else 0, - self.parameters.on_hours_total_max if self.parameters.on_hours_total_max is not None else np.inf, - ), # TODO: self._model.hours_per_step.sum('time').item() + self._get_previous_on_duration()) + bounds=( + self.parameters.on_hours_total_min if self.parameters.on_hours_total_min is not None else 0, + self.parameters.on_hours_total_max, # None → unbounded upper + ), # TODO: self._model.hours_per_step.sum('time').item() + self._get_previous_on_duration())
328-346: PieceModel dims switch to ('time','period','scenario') / ('period','scenario') looks correct.Matches the tests and periodic API.
570-572: Good guard on 'period' in ShareAllocationModel.add_share.Prevents accidental period-dim shares where the model wasn’t created with a period dim.
flixopt/elements.py (3)
432-443: Periodic migration in Flow.transform_data looks consistent.flow_hours_total*, load_factor*, and size now fitted over ['period','scenario']; matches tests.
Also applies to: 450-451
533-535: Correct: total_flow_hours tracked over ['period','scenario'].Aligns with assertions in tests and with OnOff on_hours_total handling.
319-321: Doc nit: “Maximum 200 starts per period” update is accurate.Comment change reflects new nomenclature.
flixopt/interface.py (3)
17-19: API/type migration to Periodic and period dims looks good.*InvestParameters and effects now use PeriodicData/User and map to ['period','scenario']; Piece.transform_data handles time vs non-time pieces correctly.
Also applies to: 856-870, 879-906, 898-906, 880-892
1143-1150: OnOffParameters periodic bounds mapping matches features/tests.on_hours_total_{min,max} and switch_on_total_max now bound over ['period','scenario']; aligns with OnOffModel and tests.
Also applies to: 1146-1147
1-1180: TemporalEffectsUser and PeriodicEffectsUser exist and are exported in flixopt/effects.py. No further changes required.flixopt/flow_system.py (1)
744-752: coords property: good—ensure period/scenario are present only when provided.LGTM; dynamic inclusion aligns with API rename.
flixopt/effects.py (4)
409-421: Dim choices for share factors: correct after rename.Temporal shares: ('time','period','scenario'); Periodic: ('period','scenario'). Looks consistent. Nice.
487-496: Total = temporal + periodic: clear and matches tests.Modeling equality and coords use ['period','scenario']—LGTM.
586-603: Cycle detection and unknown-source validation are solid.Good safeguards for share graphs; error messages are explicit.
915-917: Compat aliases are helpful.Thanks for keeping NonTemporal* aliases.
tests/test_effect.py (1)
202-221: Add dims alignment assertion for periodic share variableInsert an assertion after the existing
assert_conequalchecks intests/test_effect.pyto verify that the periodic share variable carries the expected dimensions:assert model.variables['Effect1(periodic)->Effect2(periodic)'].dims == ('period', 'scenario')Manual verification of dims in your test environment is required to ensure this guard catches any coordinate misalignments.
flixopt/results.py (1)
356-364: ‘period’ dimension is present and consumers use name-based dims
Thetransposewithmissing_dims='ignore'includesperiodas a dataset coord, and all downstream code (including tests) reference dims by name rather than by position, so no further action is needed.
| PeriodicDataUser = int | float | np.integer | np.floating | np.ndarray | pd.Series | pd.DataFrame | xr.DataArray | ||
| """User data which has no time dimension. Internally converted to a Scalar or an xr.DataArray without a time dimension.""" | ||
|
|
||
| NonTemporalData = xr.DataArray | ||
| """Internally used datatypes for non-temporal data. Can be a Scalar or an xr.DataArray.""" | ||
| PeriodicData = xr.DataArray | ||
| """Internally used datatypes for periodic data. Can be a Scalar or an xr.DataArray.""" | ||
|
|
||
| FlowSystemDimensions = Literal['time', 'year', 'scenario'] | ||
| FlowSystemDimensions = Literal['time', 'period', 'scenario'] | ||
| """Possible dimensions of a FlowSystem.""" |
There was a problem hiding this comment.
Doc/type mismatch for PeriodicData.
Type alias sets PeriodicData = xr.DataArray, but the docstring says “Can be a Scalar or an xr.DataArray.” Clarify one of:
- If only DataArray is intended, update docstring.
- If scalars are allowed, change the alias to Scalar | xr.DataArray.
🤖 Prompt for AI Agents
In flixopt/core.py around lines 20 to 27, the PeriodicData type alias is
declared as xr.DataArray but the docstring says it can be a Scalar or an
xr.DataArray; update one to match the other: either change the docstring to
state it is strictly an xr.DataArray, or change the type alias to include Scalar
(e.g., PeriodicData = Scalar | xr.DataArray) so the type annotation and
docstring are consistent; make the chosen fix and update the docstring
accordingly.
| self.zero_point = self.add_variables( | ||
| coords=self._model.get_coords(('year', 'scenario') if self._as_time_series else None), | ||
| coords=self._model.get_coords(('period', 'scenario') if self._as_time_series else None), | ||
| binary=True, | ||
| short_name='zero_point', | ||
| ) |
There was a problem hiding this comment.
Bug: zero_point coords ignore 'time' when as_time_series=True and drop all coords when False.
For time-series piecewise, zero_point must include 'time' (and period, scenario); for non-time-series, it should include ['period','scenario']. Current conditional inverts this.
Apply this fix:
- self.zero_point = self.add_variables(
- coords=self._model.get_coords(('period', 'scenario') if self._as_time_series else None),
- binary=True,
- short_name='zero_point',
- )
+ dims = ('time', 'period', 'scenario') if self._as_time_series else ('period', 'scenario')
+ self.zero_point = self.add_variables(
+ coords=self._model.get_coords(dims),
+ binary=True,
+ short_name='zero_point',
+ )This aligns zero_point dims with inside_piece/lambda variables and avoids broadcasting errors in single_segment constraints.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| self.zero_point = self.add_variables( | |
| coords=self._model.get_coords(('year', 'scenario') if self._as_time_series else None), | |
| coords=self._model.get_coords(('period', 'scenario') if self._as_time_series else None), | |
| binary=True, | |
| short_name='zero_point', | |
| ) | |
| # ensure zero_point has the right dims for time-series vs. non-time-series | |
| dims = ('time', 'period', 'scenario') if self._as_time_series else ('period', 'scenario') | |
| self.zero_point = self.add_variables( | |
| coords=self._model.get_coords(dims), | |
| binary=True, | |
| short_name='zero_point', | |
| ) |
🤖 Prompt for AI Agents
In flixopt/features.py around lines 419–423, the conditional that builds coords
for zero_point is inverted: when self._as_time_series is True zero_point must
include time (i.e., period, scenario, time) and when False it should include
only period and scenario; change the conditional so get_coords receives
('period','scenario','time') if self._as_time_series else ('period','scenario')
(do not pass None), matching the dims used by inside_piece/lambda variables to
prevent broadcasting errors in single_segment constraints.
flixopt/flow_system.py
Outdated
| def calculate_periods_per_period(periods: pd.Index, periods_of_last_period: int | None = None) -> xr.DataArray: | ||
| """Calculate duration of each timestep as a 1D DataArray.""" | ||
| years_per_year = np.diff(years) | ||
| periods_per_period = np.diff(periods) | ||
| return xr.DataArray( | ||
| np.append(years_per_year, years_of_last_year or years_per_year[-1]), | ||
| coords={'year': years}, | ||
| dims='year', | ||
| name='years_per_year', | ||
| np.append(periods_per_period, periods_of_last_period or periods_per_period[-1]), | ||
| coords={'period': periods}, | ||
| dims='period', | ||
| name='periods_per_period', | ||
| ) |
There was a problem hiding this comment.
calculate_periods_per_period: docstring and falsy-last-period edge.
- Docstring still refers to timesteps; rename to periods.
- Using
ortreats 0 as falsy; if 0 is a valid last span, it will be overridden.
- def calculate_periods_per_period(periods: pd.Index, periods_of_last_period: int | None = None) -> xr.DataArray:
- """Calculate duration of each timestep as a 1D DataArray."""
+ def calculate_periods_per_period(periods: pd.Index, periods_of_last_period: int | None = None) -> xr.DataArray:
+ """Calculate length of each period; last value can be overridden."""
@@
- np.append(periods_per_period, periods_of_last_period or periods_per_period[-1]),
+ np.append(periods_per_period, periods_per_period[-1] if periods_of_last_period is None else periods_of_last_period),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def calculate_periods_per_period(periods: pd.Index, periods_of_last_period: int | None = None) -> xr.DataArray: | |
| """Calculate duration of each timestep as a 1D DataArray.""" | |
| years_per_year = np.diff(years) | |
| periods_per_period = np.diff(periods) | |
| return xr.DataArray( | |
| np.append(years_per_year, years_of_last_year or years_per_year[-1]), | |
| coords={'year': years}, | |
| dims='year', | |
| name='years_per_year', | |
| np.append(periods_per_period, periods_of_last_period or periods_per_period[-1]), | |
| coords={'period': periods}, | |
| dims='period', | |
| name='periods_per_period', | |
| ) | |
| def calculate_periods_per_period(periods: pd.Index, periods_of_last_period: int | None = None) -> xr.DataArray: | |
| """Calculate length of each period; last value can be overridden.""" | |
| periods_per_period = np.diff(periods) | |
| return xr.DataArray( | |
| np.append( | |
| periods_per_period, | |
| periods_per_period[-1] if periods_of_last_period is None else periods_of_last_period, | |
| ), | |
| coords={'period': periods}, | |
| dims='period', | |
| name='periods_per_period', | |
| ) |
🤖 Prompt for AI Agents
In flixopt/flow_system.py around lines 179 to 187, the function docstring
incorrectly mentions "timesteps" and the logic for the fallback last period uses
`or` which treats 0 as falsy; change the docstring to say "periods" and replace
the fallback with an explicit None check (use periods_of_last_period if
periods_of_last_period is not None else periods_per_period[-1]) so that a valid
0 value is preserved when appending the last span.
| if periodic.isnull().all() and temporal.isnull().all(): | ||
| return xr.DataArray(np.nan) | ||
| if temporal.isnull().all(): | ||
| return nontemporal.rename(f'{element}->{effect}') | ||
| return periodic.rename(f'{element}->{effect}') | ||
| temporal = temporal.sum('time') | ||
| if nontemporal.isnull().all(): | ||
| if periodic.isnull().all(): | ||
| return temporal.rename(f'{element}->{effect}') | ||
| if 'time' in temporal.indexes: | ||
| temporal = temporal.sum('time') | ||
| return nontemporal + temporal | ||
| return periodic + temporal | ||
|
|
There was a problem hiding this comment.
Fix double time-summing and missing rename in total aggregation.
- temporal is summed over time twice (once unconditionally, then conditionally).
- When both parts exist, the returned DataArray keeps the periodic name, not '{element}->{effect}'.
Apply this diff:
- temporal = temporal.sum('time')
- if periodic.isnull().all():
+ # Reduce temporal along time once
+ temporal = temporal.sum('time')
+ if periodic.isnull().all():
return temporal.rename(f'{element}->{effect}')
- if 'time' in temporal.indexes:
- temporal = temporal.sum('time')
- return periodic + temporal
+ total = periodic + temporal
+ return total.rename(f'{element}->{effect}')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if periodic.isnull().all() and temporal.isnull().all(): | |
| return xr.DataArray(np.nan) | |
| if temporal.isnull().all(): | |
| return nontemporal.rename(f'{element}->{effect}') | |
| return periodic.rename(f'{element}->{effect}') | |
| temporal = temporal.sum('time') | |
| if nontemporal.isnull().all(): | |
| if periodic.isnull().all(): | |
| return temporal.rename(f'{element}->{effect}') | |
| if 'time' in temporal.indexes: | |
| temporal = temporal.sum('time') | |
| return nontemporal + temporal | |
| return periodic + temporal | |
| if periodic.isnull().all() and temporal.isnull().all(): | |
| return xr.DataArray(np.nan) | |
| if temporal.isnull().all(): | |
| return periodic.rename(f'{element}->{effect}') | |
| # Reduce temporal along time once | |
| temporal = temporal.sum('time') | |
| if periodic.isnull().all(): | |
| return temporal.rename(f'{element}->{effect}') | |
| total = periodic + temporal | |
| return total.rename(f'{element}->{effect}') |
🤖 Prompt for AI Agents
In flixopt/results.py around lines 579 to 589, temporal is being summed over
'time' twice and the final combined result isn't renamed; fix by removing the
unconditional temporal = temporal.sum('time') so temporal is summed only if it
contains the 'time' index, and when returning the combined periodic + temporal
DataArray, apply .rename(f'{element}->{effect}') so the total aggregation has
the correct name; keep the existing early-return renames for the single-part
cases and preserve the initial all-null check.
| def weights(self) -> int | xr.DataArray: | ||
| """Returns the scenario weights of the FlowSystem. If None, return weights that are normalized to 1 (one)""" | ||
| if self.flow_system.weights is None: | ||
| weights = self.flow_system.fit_to_model_coords( | ||
| 'weights', | ||
| 1 if self.flow_system.years is None else self.flow_system.years_per_year, | ||
| dims=['year', 'scenario'], | ||
| ) | ||
|
|
||
| return weights / weights.sum() | ||
| if self.flow_system.weights is not None: | ||
| return self.flow_system.weights | ||
|
|
||
| return self.flow_system.weights | ||
| weights = self.flow_system.fit_to_model_coords('weights', 1, dims=['period', 'scenario']) | ||
| return weights / weights.sum() | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Weights semantics changed (scenario → period×scenario); clarify and test
Doc says “scenario weights”, but missing-weights path now creates a period×scenario grid and normalizes across all cells. This is a behavior change that can silently alter aggregation if consumers expect scenario-only weighting.
- Either update the docstring to reflect combined period×scenario weights and add tests, or
- Keep scenario-only defaults and handle period weighting where needed.
Optional diff to clarify intent via explicit dim-sum and docstring:
- def weights(self) -> int | xr.DataArray:
- """Returns the scenario weights of the FlowSystem. If None, return weights that are normalized to 1 (one)"""
+ def weights(self) -> int | xr.DataArray:
+ """Returns normalized weights aligned to model coords.
+ If self.flow_system.weights is None, create equal weights over ['period','scenario'] and normalize their sum to 1."""
if self.flow_system.weights is not None:
return self.flow_system.weights
- weights = self.flow_system.fit_to_model_coords('weights', 1, dims=['period', 'scenario'])
- return weights / weights.sum()
+ weights = self.flow_system.fit_to_model_coords('weights', 1, dims=['period', 'scenario'])
+ total = weights.sum(dim=list(weights.dims))
+ return xr.where(total != 0, weights / total, weights)🏁 Script executed:
#!/bin/bash
# Find usages of model.weights and check expected dims/normalization.
rg -nP -C2 '\bweights\b' -g "flixopt/**" | sed -n '1,200p'Length of output: 7553
Fix weights() docstring to reflect period×scenario grid flixopt/structure.py:171-178
- Docstring currently states “scenario weights” but this always returns a period×scenario DataArray normalized across both dims.
- Update the docstring and add/adjust tests for this behavior.
- [optional] Use explicit
sum(dim=list(weights.dims))and guard against divide-by-zero.
🤖 Prompt for AI Agents
In flixopt/structure.py around lines 171 to 178, the weights() docstring
incorrectly says "scenario weights" but the method returns a period×scenario
DataArray normalized across both dimensions; update the docstring to state it
returns period×scenario weights normalized to sum to 1 across all periods and
scenarios, and add/adjust tests to assert the shape (period, scenario) and that
weights.sum(dim=list(weights.dims)) == 1; when normalizing, compute total =
weights.sum(dim=list(weights.dims)) and guard against divide-by-zero by
returning zeros or raising a clear error if total == 0 before doing weights /
total.
| assert_conequal(model.constraints['Effect1(periodic)'], model.variables['Effect1(periodic)'] == 0) | ||
| assert_conequal( |
There was a problem hiding this comment.
Constraint contradicts bounds for periodic mode.
You set Effect1(periodic) with lower/upper 2.0–2.1 (Lines 121–123) but still assert a constraint enforcing Effect1(periodic) == 0. This will be infeasible. Drop or adapt the zero-equality for the bounds test.
Apply this diff:
- assert_conequal(model.constraints['Effect1(periodic)'], model.variables['Effect1(periodic)'] == 0)
+ # No zero-equality here: periodic total is bounded [2.0, 2.1] above
+ assert 'Effect1(periodic)' in model.constraints📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| assert_conequal(model.constraints['Effect1(periodic)'], model.variables['Effect1(periodic)'] == 0) | |
| assert_conequal( | |
| # No zero‐equality here: periodic total is bounded [2.0, 2.1] above | |
| assert 'Effect1(periodic)' in model.constraints | |
| assert_conequal( |
* V3.0.0/main (#284) * Bugfix plot_node_balance_pie() * Scenarios/fixes (#252) * BUGFIX missing conversion to TimeSeries * BUGFIX missing conversion to TimeSeries * Bugfix node_balance with flow_hours: Negate correctly * Scenarios/filter (#253) * Add containts and startswith to filter_solution * Scenarios/drop suffix (#251) Drop suffixes in plots and add the option to drop suffixes to sanitize_dataset() * Scenarios/bar plot (#254) * Add stacked bar style to plotting methods * Rename mode to style (line, bar, area, ...) * Bugfix plotting * Fix example_calculation_types.py * Scenarios/fixes (#255) * Fix indexing issue with only one scenario * Bugfix Cooling Tower * Add option for balanced Storage Flows (equalize size of charging and discharging) * Add option for balanced Storage Flows * Change error to warning (non-fixed size with piecewise conversion AND fixed_flow_rate with OnOff) * Bugfix in DataConverter * BUGFIX: Typo (total_max/total_min in Effect) * Bugfix in node_balance() (negating did not work when using flow_hours mode * Scenarios/effects (#256) * Add methods to track effect shares of components and Flows * Add option to include flows when retrieving effects * Add properties and methods to store effect results in a dataset * Reorder methods * Rename and improve docs * Bugfix test class name * Fix the Network algorithm to calculate the sum of parallel paths, and be independent on nr of nodes and complexity of the network * Add tests for the newtork chaining and the results of effect shares * Add methods to check for circular references * Add test to check for circular references * Update cycle checker to return the found cycles * Add checks in results to confirm effects are computed correctly * BUGFIX: Remove +1 from prior testing * Add option for grouped bars to plotting.with_plotly() and make lines of stacked bar plots invisible * Reconstruct FlowSystem in CalculationResults on demand. DEPRECATION in CalculationResults * ruff check * Bugfix: save flow_system data, not the flow_system * Update tests * Scenarios/datasets results (#257) * Use dataarray instead of dataset * Change effects dataset to dataarray and use nan when no share was found * Add method for flow_rates dataset * Add methods to get flow_rates and flow_hours as datasets * Rename the dataarrays to the flow * Preserve index order * Improve filter_edges_dataset() * Simplify _create_flow_rates_dataarray() * Add dataset for sizes of Flows * Extend results structure to contain flows AND start/end infos * Add FlowResults Object * BUGFIX:Typo in _ElementResults.constraints * Add flows to results of Nodes * Simplify dataarray creation and improve FlowResults * Add nice docstrings * Improve filtering of flow results * Improve filtering of flow results. Add attribute of component * Add big dataarray with all variables but indexed * Revert "Add big dataarray with all variables but indexed" This reverts commit 08cd8a1. * Improve filtering method for coords filter and add error handling for restoring the flow system * Remove unnecessary methods in results .from_json() * Ensure consistent coord ordering in Effects dataarray * Rename get_effects_per_component() * Make effects_per_component() a dataset instead of a dataarray * Improve backwards compatability * ruff check * ruff check * Scenarios/deprecation (#258) * Deprecate .active_timesteps * Improve logger warning * Starting release notes * Bugfix in plausibility_check: Index 0 * Set bargap to 0 in stacked bars * Ensure the size is always properly indexed in results. * ruff check * BUGFIX in extract data, that causes coords in linopy to be incorrect (scalar xarray.DataArrays) * Improve yaml formatting for model documentation (#259) * Make the size/capacity a TimeSeries (#260) * Scenarios/plot network (#262) * Catch bug in plot_network with 2D arrays * Add plot_network() to test_io.py * Update deploy-docs.yaml: Run on Release publishing instead of creation and only run for stable releases (vx.y.z) * Bugfix DataConverter and add tests (#263) * Fix doc deployment to not publish on non stable releases * Remove unused code * Remove legend placing for better auto placing in plotly * Fix plotly dependency * Improve validation when adding new effects * Moved release notes to CHANGELOG.md * Try to add to_dataset to Elements * Remove TimeSeries * Remove TimeSeries * Rename conversion method to pattern: to_... * Move methods to FlowSystem * Drop nan values across time dimension if present * Allow lists of values to create DataArray * Update resolving of FlowSystem * Simplify TimeSeriesData * Move TImeSeriesData to Structure and simplyfy to inherrit from xarray.DataArray * Adjust IO * Move TimeSeriesData back to core.py and fix Conversion * Adjust IO to account for attrs of DataArrays in a Dataset * Rename transforming and connection methods in FlowSystem * Compacted IO methods * Remove infos() * remove from_dict() and to_dict() * Update __str__ of Interface * Improve str and repr * Improve str and repr * Add docstring * Unify IO stuff in Interface class * Improve test tu utilize __eq__ method * Make Interface class more robust and improve exceptions * Add option to copy Interfaces (And the FlowSystem) * Make a copy of a FLowSytsem that gets reused in a second Calculation * Remove test_timeseries.py * Reorganizing Datatypes * Remove TImeSeries and TimeSeriesCollection entirely * Remove old method * Add option to get structure with stats of dataarrays * Change __str__ method * Remove old methods * remove old imports * Add isel, sel and resample methods to FlowSystem * Remove need for timeseries with extra timestep * Simplify IO of FLowSystem * Remove parameter timesteps from IO * Improve Exceptions and Docstrings * Improve isel sel and resample methods * Change test * Bugfix * Improve * Improve * Add test for Storage Bounds * Add test for Storage Bounds * CHANGELOG.md * ruff check * Improve types * CHANGELOG.md * Bugfix in Storage * Revert changes in example_calculation_types.py * Revert changes in simple_example.py * Add convenient access to Elements in FlowSystem * Get Aggregated Calculation Working * Segmented running with wrong results * Use new persistent FLowSystem to create Calculations upfront * Improve SegmentedCalcualtion * Improve SegmentedCalcualtion * Fix SegmentedResults IO * ruff check * Update example * Updated logger essages to use .label_full instead of .label * Re-add parameters. Use deprecation warning instead * Update changelog * Improve warning message * Merge * Merge * Fit scenario weights to model coords when transforming * Merge * Removing logic between minimum, maximum and fixed size from InvestParameters * Remove selected_timesteps * Improve TypeHints * New property on InvestParameters for min/max/fixed size * Move logic for InvestParameters in Transmission to from Model to Interface * Make transformation of data more hierarchical (Flows after Components) * Add scenario validation * Change Transmission to have a "balanced" attribute. Change Tests accordingly * Improve index validations * rename method in tests * Update DataConverter * Add DataFrame Support back * Add copy() to DataConverter * Update fit_to_model_coords to take a list of coords * Make the DataConverter more universal by accepting a list of coords/dims * Update DataConverter for n-d arrays * Update DataConverter for n-d arrays * Add extra tests for 3-dims * Add FLowSystemDimension Type * Revert some logic about the fit_to_model coords * Adjust FLowSystem IO for scenarios * BUGFIX: Raise Exception instead of logging * Change usage of TimeSeriesData * Adjust logic to handle non scalars * Adjust logic to _resolve_dataarray_reference into separate method * Update IO of FlowSystem * Improve get_coords() * Adjust FlowSystem init for correct IO * Add scenario to sel and isel methods, and dont normalize scenario weights * Improve scenario_weights_handling * Add warning for not scaled weights * Update test_scenarios.py * Improve util method * Add objective to solution dataset. * Update handling of scenario_weights update tests * Ruff check. Fix type hints * Fix type hints and improve None handling * Fix coords in AggregatedCalculation * Improve Error Messages of DataConversion * Allow multi dim data conversion and broadcasting by length * Improve DataConverter to handle multi-dim arrays * Rename methods and remove unused code * Improve DataConverter by better splitting handling per datatype. Series only matches index (for one dim). Numpy matches shape * Add test for error handling * Update scenario example * Fix Handling of TimeSeriesData * Improve DataConverter * Fix resampling of the FlowSystem * Improve Warning Message * Add example that leverages resampling * Add example that leverages resampling adn fixing of Investments * Add flag to Calculation if its modeled * Make flag for connected_and_transformed FLowSystem public * Make Calcualtion Methods return themselfes to make them chainable * Improve example * Improve Unreleased CHANGELOG.md * Add year coord to FlowSystem * Improve dimension handling * Change plotting to use an indexer instead * Change plotting to use an indexer instead * Use tuples to set dimensions in Models * Bugfix in validation logic and test * Improve Errors * Improve weights handling and rescaling if None * Fix typehint * Update Broadcasting in Storage Bounds and improve type hints * Make .get_model_coords() return an actual xr.Coordinates Object * Improve get_coords() * Rename SystemModel to FlowSystemModel * First steps * Improve Feature Patterns * Improve acess to variables via short names * Improve * Add naming options to big_m_binary_bounds() * Fix and improve FLowModeling with Investment * Improve * Tyring to improve the Methods for bounding variables in different scenarios * Improve BoundingPatterns * Improve BoundingPatterns * Improve BoundingPatterns * Fix duration Modeling * Fix On + Size * Fix InvestmentModel * Fix Models * Update constraint names in test * Fix OnOffModel for multiple Flows * Update constraint names in tests * Simplify * Improve handling of vars/cons and models * Revising the basic structure of a class Model * Revising the basic structure of a class Model * Simplify and focus more on own Model class * Update tests * Improve state computation in ModelingUtilities * Improve handling of previous flowrates * Imropove repr and submodel acess * Update access pattern in tests * Fix PiecewiseEffects and StorageModel * Fix StorageModel and Remove PreventSimultaniousUseModel * Fix Aggregation and SegmentedCalculation * Update tests * Loosen precision in tests * Update test_on_hours_computation.py and some types * Rename class Model to Submodel * rename sub_model to submodel everywhere * rename self.model to self.submodel everywhere * Rename .model with .submodel if its only a submodel * Rename .sub_models with .submodels * Improve repr * Improve repr * Include def do_modeling() into __init__() of models * Make properties private * Improve Inheritance of Models * V3.0.0/plotting (#285) * Use indexer to reliably plot solutions with and wihtout scenarios/years * ruff check * Improve typehints * Update CHANGELOG.md * Bugfix from renaming to .submodel * Bugfix from renaming to .submodel * Improve indexer in results plotting * rename register_submodel() to .add_submodels() adn add SUbmodels collection class * Add nice repr to FlowSystemModel and Submodel * Bugfix .variables and .constraints * Add type checks to modeling.py * Improve assertion in tests * Improve docstrings and register ElementModels directly in FlowSystemModel * Improve __repr__() * ruff check * Use new method to compare sets in tests * ruff check * Update Contribute.md, some dependencies and add pre-commit * Pre commit hook * Run Pre-Commit Hook for the first time * Fix link in README.md * Update Effect name in tests to be 'costs' instead of 'Costs' Everywhere Simplify testing by creating a Element Library * Improve some of the modeling and coord handling * Add tests with years and scenarios * Update tests to run with multiple coords * Fix Effects dataset computation in case of empty effects * Update Test for multiple dims Fix Dim order in scaled_bounds_with_state Bugfix logic in .use_switch_on * Fix test with multiple dims * Fix test with multiple dims * New test * New test for previous flow_rates * V3.0.0/main fit to model coords improve (#295) * Change fit_to_model_coords to work with a Collection of dims * Improve fit_to_model_coords * Improve CHANGELOG.md * Update pyproject.toml * new ruff check * Merge branch 'main' into dev # Conflicts: # CHANGELOG.md # flixopt/network_app.py * Update CHANGELOG.md * Fix Error message * Revert changes * Feature/v3/update (#352) * Remove need for timeseries with extra timestep * Simplify IO of FLowSystem * Remove parameter timesteps from IO * Improve Exceptions and Docstrings * Improve isel sel and resample methods * Change test * Bugfix * Improve * Improve * Add test for Storage Bounds * Add test for Storage Bounds * CHANGELOG.md * ruff check * Improve types * CHANGELOG.md * Bugfix in Storage * Revert changes in example_calculation_types.py * Revert changes in simple_example.py * Add convenient access to Elements in FlowSystem * Get Aggregated Calculation Working * Segmented running with wrong results * Use new persistent FLowSystem to create Calculations upfront * Improve SegmentedCalcualtion * Improve SegmentedCalcualtion * Fix SegmentedResults IO * ruff check * Update example * Updated logger essages to use .label_full instead of .label * Re-add parameters. Use deprecation warning instead * Update changelog * Improve warning message * Merge * Merge * Fit scenario weights to model coords when transforming * Merge * Removing logic between minimum, maximum and fixed size from InvestParameters * Remove selected_timesteps * Improve TypeHints * New property on InvestParameters for min/max/fixed size * Move logic for InvestParameters in Transmission to from Model to Interface * Make transformation of data more hierarchical (Flows after Components) * Add scenario validation * Change Transmission to have a "balanced" attribute. Change Tests accordingly * Improve index validations * rename method in tests * Update DataConverter * Add DataFrame Support back * Add copy() to DataConverter * Update fit_to_model_coords to take a list of coords * Make the DataConverter more universal by accepting a list of coords/dims * Update DataConverter for n-d arrays * Update DataConverter for n-d arrays * Add extra tests for 3-dims * Add FLowSystemDimension Type * Revert some logic about the fit_to_model coords * Adjust FLowSystem IO for scenarios * BUGFIX: Raise Exception instead of logging * Change usage of TimeSeriesData * Adjust logic to handle non scalars * Adjust logic to _resolve_dataarray_reference into separate method * Update IO of FlowSystem * Improve get_coords() * Adjust FlowSystem init for correct IO * Add scenario to sel and isel methods, and dont normalize scenario weights * Improve scenario_weights_handling * Add warning for not scaled weights * Update test_scenarios.py * Improve util method * Add objective to solution dataset. * Update handling of scenario_weights update tests * Ruff check. Fix type hints * Fix type hints and improve None handling * Fix coords in AggregatedCalculation * Improve Error Messages of DataConversion * Allow multi dim data conversion and broadcasting by length * Improve DataConverter to handle multi-dim arrays * Rename methods and remove unused code * Improve DataConverter by better splitting handling per datatype. Series only matches index (for one dim). Numpy matches shape * Add test for error handling * Update scenario example * Fix Handling of TimeSeriesData * Improve DataConverter * Fix resampling of the FlowSystem * Improve Warning Message * Add example that leverages resampling * Add example that leverages resampling adn fixing of Investments * Add flag to Calculation if its modeled * Make flag for connected_and_transformed FLowSystem public * Make Calcualtion Methods return themselfes to make them chainable * Improve example * Improve Unreleased CHANGELOG.md * Add year coord to FlowSystem * Improve dimension handling * Change plotting to use an indexer instead * Change plotting to use an indexer instead * Use tuples to set dimensions in Models * Bugfix in validation logic and test * Improve Errors * Improve weights handling and rescaling if None * Fix typehint * Update Broadcasting in Storage Bounds and improve type hints * Make .get_model_coords() return an actual xr.Coordinates Object * Improve get_coords() * Rename SystemModel to FlowSystemModel * First steps * Improve Feature Patterns * Improve acess to variables via short names * Improve * Add naming options to big_m_binary_bounds() * Fix and improve FLowModeling with Investment * Improve * Tyring to improve the Methods for bounding variables in different scenarios * Improve BoundingPatterns * Improve BoundingPatterns * Improve BoundingPatterns * Fix duration Modeling * Fix On + Size * Fix InvestmentModel * Fix Models * Update constraint names in test * Fix OnOffModel for multiple Flows * Update constraint names in tests * Simplify * Improve handling of vars/cons and models * Revising the basic structure of a class Model * Revising the basic structure of a class Model * Simplify and focus more on own Model class * Update tests * Improve state computation in ModelingUtilities * Improve handling of previous flowrates * Imropove repr and submodel acess * Update access pattern in tests * Fix PiecewiseEffects and StorageModel * Fix StorageModel and Remove PreventSimultaniousUseModel * Fix Aggregation and SegmentedCalculation * Update tests * Loosen precision in tests * Update test_on_hours_computation.py and some types * Rename class Model to Submodel * rename sub_model to submodel everywhere * rename self.model to self.submodel everywhere * Rename .model with .submodel if its only a submodel * Rename .sub_models with .submodels * Improve repr * Improve repr * Include def do_modeling() into __init__() of models * Make properties private * Improve Inheritance of Models * V3.0.0/plotting (#285) * Use indexer to reliably plot solutions with and wihtout scenarios/years * ruff check * Improve typehints * Update CHANGELOG.md * Bugfix from renaming to .submodel * Bugfix from renaming to .submodel * Improve indexer in results plotting * rename register_submodel() to .add_submodels() adn add SUbmodels collection class * Add nice repr to FlowSystemModel and Submodel * Bugfix .variables and .constraints * Add type checks to modeling.py * Improve assertion in tests * Improve docstrings and register ElementModels directly in FlowSystemModel * Improve __repr__() * ruff check * Use new method to compare sets in tests * ruff check * Update Contribute.md, some dependencies and add pre-commit * Pre commit hook * Run Pre-Commit Hook for the first time * Fix link in README.md * Update Effect name in tests to be 'costs' instead of 'Costs' Everywhere Simplify testing by creating a Element Library * Improve some of the modeling and coord handling * Add tests with years and scenarios * Update tests to run with multiple coords * Fix Effects dataset computation in case of empty effects * Update Test for multiple dims Fix Dim order in scaled_bounds_with_state Bugfix logic in .use_switch_on * Fix test with multiple dims * Fix test with multiple dims * New test * New test for previous flow_rates * Add Model for YearAwareInvestments * Add FlowSystem.years_per_year attribute and "years_of_last_year" parameter to FlowSystem() * Add YearAwareInvestmentModel * Add new Interface * Improve YearAwareInvestmentModel * Rename and improve * Move piecewise_effects * COmbine TImingInvestment into a single interface * Add model tests for investment * Add size_changes variables * Add size_changes variables * Improve InvestmentModel * Improve InvestmentModel * Rename parameters * remove old code * Add a duration_in_years to the InvestTimingParameters * Improve handling of fixed_duration * Improve validation and make Investment/divestment optional by default * Rename some vars and improve previous handling * Add validation for previous size * Change fit_to_model_coords to work with a Collection of dims * Improve fit_to_model_coords * Improve test * Update transform_data() * Add new "year of investment" coord to FlowSystem * Add 'year_of_investment' dimension to FlowSystem * Improve InvestmentTiming * Improve InvestmentTiming * Add specific_effect back * add effects_by_investment_year back * Add year_of_investment to FLowSystem.sel() * Improve Interface * Handle selection of years properly again * Temp * Make ModelingPrimitives.consecutive_duration_tracking() dim-agnostic * Use new lifetime variable and constraining methods * Improve Plausibility check * Improve InvestmentTImingParameters * Improve weights * Adjust test * Remove old classes * V3.0.0/main fit to model coords improve (#295) * Change fit_to_model_coords to work with a Collection of dims * Improve fit_to_model_coords * ruff format * Revert changes * Update type hints * Revert changes introduced by new Multiperiod Invest parameters * Improve CHnagelog and docstring of Storage * Improve Changelog * Improve InvestmentModel * Improve InvestmentModel to have 2 cases. One without years and one with * Improve InvestmentModel to have 2 cases. One without years and one with years. Further, remove investment_scenarios parameter * Revert some changes regarding Investments * Typo * Remove Investment test file (only local testing) * More reverted changes * More reverted changes * Add years_of_last_year to docstring * Revert change from Investment * Revert change from Investment * Remove old todos.txt file * Fix typos in CHANGELOG.md * Improve usage of name_prefix to intelligently join with the label * Ensure IO of years_of_last_year * Typo * Typo * activat tests on pulls to feature/v3 * activat tests on pulls to feature/v3/main * Feature/v3/low-impact-improvements (#355) * Fix typo * Prefer robust scalar extraction for timestep sizes in aggregation * Improve docs and error messages * Update examples * Use validated timesteps * Remove unnessesary import * Use FlowSystem.model instead of FlowSystem.submodel * Fix Error message * Improve CHANGELOG.md * Use self.standard_effect instead of provate self._standard_effect and update docstring * in calculate_all_conversion_paths, use `collections.deque` for efficiency on large graphs * Make aggregation_parameters.hours_per_period more robust by using rounding * Improve import and typos * Improve docstring * Use validated timesteps * Improve error * Improve warning * Improve type hint * Improve CHANGELOG.md: typos, wording and duplicate entries * Improve CI (#357) Separate example testing from other tests by marking them. By default, purest doesn't run the example tests * Feature/v3/data converter (#356) * Update DataConverter * Update tests of error messages * Update tests of error messages * Update Dataconverter to allow bool values * fix tests * Improve code order of prefix in transform_data() * Move pytest-xdist to dev deps * Fix transform_data to not pass a prefix to flow * Move to unreleased Add emojis to CHANGELOG.md * Feature/v3/feature/308 rename effect domains (#365) * Rename effect domains * Rename effect domains * Ensure backwards compatability * Improve * Improve * Bugfix IO with deprectaed params * Add guards for extra kwargs * Add guards for extra kwargs * centralize logic for deprectaed params * Move handlign from centralized back to classes in a dedicated method * Improce property handling * Move handling to Interface class * Getting lost * Revert "Getting lost" This reverts commit 3c0db76. * Revert "Move handling to Interface class" This reverts commit 09bdeec. * Revert "Improce property handling" This reverts commit 5fe2c64. * Revert "Move handlign from centralized back to classes in a dedicated method" This reverts commit 9f4c1f6. * Revert "centralize logic for deprectaed params" This reverts commit 4a82574. * Add "" to warnings * Revert change in examples * Improve BackwardsCompatibleDataset * Add unit tests for backwards compatability * Remove backwards compatible dataset * Renamed maximum_temporal_per_hour to maximum_per_hour and minimum_temporal_per_hour to minimum_per_hour * Add entires to CHANGELOG.md * Remove backwards compatible dataset * Remove unused imports * Move to unreleased * Catch up on missed renamings from merge * Catch up on missed renamings from merge * Typo * Typo * Several small improvements or potential future bug preventions * Feature/v3/feature/305 rename specific share to other effects to specific share from effect (#366) * Step 1 * Bugfix * Make fit_effects_to_model_coords() more flexible * Fix dims * Update conftest.py * Typos * Improve Effect examples * Add extra validation for Effect Shares * Feature/v3/feature/367 rename year dimension to period (#370) * The framework now uses "period" instead of "year" as the dimension name and "periodic" instead of "nontemporal" for the effect domain * Update CHANGELOG.md * Remove periods_of_last_period parameter and adjust weights calculation * Bugfix * Bugfix * Switch from "as_time_series": bool to "dims": [time, period, scenario] arguments * Improve normalization of weights * Update tests * Typos in docs * Improve docstrings * Improve docstrings * Update CHANGELOG.md * Improved tests: added extra time+scenarios combination * Add rename and improve CHANGELOG.md * Made CHANGELOG.md more concise * Simplify array summation and improve `np.isclose` usage in `modeling` and `aggregation` modules. * Make storage and load profile methods flexible by introducing `timesteps_length` parameter; update test configurations accordingly. * Refine error messages in `ModelingPrimitives` to correctly reference updated method names. * Enhance test fixtures by adding `ids` for parameterized tests, improve input flexibility with dynamic timestep length, and refine error message sorting logic. * Refactor variable selection and constraint logic in `aggregation.py` for handling more than only a time dimension * Adjust constraint in `aggregation.py` to enforce stricter summation limit (1 instead of 1.1) * Reverse transition constraint inequality for consistency in `modeling.py`. * Update dependency to use h5netcdf instead of netcdf4 * Feature/v3/several improvements (#372) * Update deprecated properties to use new aggregation attributes in `core.py`. * Refactor `drop_constant_arrays` in `core.py` to improve clarity, add type hints, and enhance logging for dropped variables. * Bugfix example_calculation_types.py and two_stage_optimization.py * Use time selection more explicitly * Refactor plausibility checks in `components.py` to handle string-based `initial_charge_state` more robustly and simplify capacity bounds retrieval using `InvestParameters`. * Refactor `create_transmission_equation` in `components.py` to handle `relative_losses` gracefully when unset and simplify the constraint definition. * Update pytest `addopts` formatting in `pyproject.toml` to work with both unix and windows * Refine null value handling when resolving dataarrays` to check for 'time' dimension before dropping all-null values. * Refactor flow system restoration to improve exception handling and ensure logger state resets. * Refactor imports in `elements.py` to remove unused `ModelingPrimitives` from `features` and include it from `modeling` instead. * Refactor `count_consecutive_states` in `modeling.py` to enhance documentation, improve edge case handling, and simplify array processing. * Refactor `drop_constant_arrays` to handle NaN cases with `skipna` and sort dropped variables for better logging; streamline logger state restoration in `results.py`. * Temp * Improve NAN handling in count_consecutive_states() * Refactor plausibility checks in `components.py` to prevent initial capacity from constraining investment decisions and improve error messaging. * Feature/v3/feature/no warnings in tests (#373) * Refactor examples to not use deprectaed patterns * Refactor tests to replace deprecated `sink`/`source` properties with `inputs`/`outputs` in component definitions. * Use 'h' instead of deprectaed 'H' in coordinate freq in tests; adjust `xr.concat` in `results.py` to use `join='outer'` for safer merging. * Refactor plot tests to use non-interactive backends, save plots as files, and close figures to prevent memory leaks. * Refactor plot tests to use non-interactive Plotly renderer (`json`), add cleanup with `tearDown`, and ensure compatibility with non-interactive Matplotlib backends. * Configure pytest filters to treat most warnings as errors, ignore specific third-party warnings, and display all warnings from internal code. * Revert "Configure pytest filters to treat most warnings as errors, ignore specific third-party warnings, and display all warnings from internal code." This reverts commit 0928b26. * Refactor plotting logic to prevent memory leaks, improve backend handling, and add test fixtures for cleanup and non-interactive configurations. * Update pytest filterwarnings to treat most warnings as errors, ignore specific third-party warnings, and display all internal warnings. * Suppress specific third-party warnings in `__init__.py` to reduce noise for end users. * Update pytest warning filters: treat internal warnings as errors, revert treating most third-party warnings as errors. * Suppress additional third-party warnings in `__init__.py` to minimize runtime noise. * Update pytest warning filters: suppress specific third-party warnings and add detailed context for `__init__.py` filters. * Sync and consolidate third-party warning filters in `__init__.py` and `pyproject.toml` to suppress runtime noise effectively. * Expand and clarify third-party warning filters in `__init__.py` and `pyproject.toml` for improved runtime consistency and reduced noise. * Update deprecated code in tests * Refactor backend checks in `plotting.py` and streamline test fixtures for consistency in handling non-interactive backends. * Refactor plotting logic to handle test environments explicitly, remove unused Plotly configuration, and improve figure cleanup in tests. * Add entry to CHANGELOG.md * Typos in example * Reogranize Docs (#377) * Improve effects parameter naming in InvestParameters (#389) * FIrst Try * Improve deprecation * Update usage of deprectated parameters * Improve None handling * Add extra kwargs handling * Improve deprecation * Use custom method for kwargs * Add deprecation method * Apply deprecation method to other classes * Apply to effects.py as well * Update usage of deprectaed parameters * Update CHANGELOG.md * Update Docs * Feature/v3/feature/test examples dependent (#390) * Update example test to run dependent examples in order * Update example test to run dependent examples in order * Update CHANGELOG.md * Improve test directory handling * Improve test directory handling * Typo * Feature/v3/feature/rename investparameter optional to mandatory (#392) * Change .optional to .mandatory * Change .optional to .mandatory * Remove not needed properties * Improve deprectation warnings * Improve deprectation of "optional" * Remove all usages of old "optional" parameter in code * Typo * Imrpove readability * Adjust some logging levels * Add scenarios and periods to repr and str of FlowSystem * Feature/v3/feature/386 use better default logging colors and dont log to file by default (#394) * Fix `charge_state` Constraint in `Storage` leading to incorrect losses in discharge and therefore incorrect charge states and discharge values (#347) * Fix equation in Storage * Fix test for equation in Storage * Update CHANGELOG.md * Improve Changelog Message * Fix CHANGELOG.md * Simplify changes from next release * Update CHANGELOG.md * Fix CHANGELOG.md * chore(deps): update dependency mkdocs-material to v9.6.20 (#369) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Improve renovate.json to automerge ruff despite 0.x version * chore(deps): update dependency tsam to v2.3.9 (#379) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency ruff to v0.13.2 (#378) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Feature/Improve Configuration options and handling (#385) * Refactor configuration management: remove dataclass-based schema and simplify CONFIG structure. * Refactor configuration loading: switch from `os` to `pathlib`, streamline YAML loading logic. * Refactor logging setup: split handler creation into dedicated functions, simplify configuration logic. * Improve logging configurability and safety - Add support for `RotatingFileHandler` to prevent large log files. - Introduce `console` flag for optional console logging. - Default to `NullHandler` when no handlers are configured for better library behavior. * Temp * Temp * Temp * Temp * Temp * Temp * Refactor configuration and logging: remove unused `merge_configs` function, streamline logging setup, and encapsulate `_setup_logging` as an internal function. * Remove unused `change_logging_level` import and export. * Add tests for config.py * Expand `config.py` test coverage: add tests for custom config loading, logging setup, dict roundtrip, and attribute modification. * Expand `test_config.py` coverage: add modeling config persistence test, refine logging reset, and improve partial config load assertions. * Expand `test_config.py` coverage: add teardown for state cleanup and reset modeling config in setup. * Add `CONFIG.reset()` method and expand test coverage to verify default restoration * Refactor `CONFIG` to centralize defaults in `_DEFAULTS` and ensure `reset()` aligns with them; add test to verify consistency. * Refactor `_DEFAULTS` to use `MappingProxyType` for immutability, restructure config hierarchy, and simplify `reset()` implementation for maintainability; update tests accordingly. * Mark `TestConfigModule` tests to run in a single worker with `@pytest.mark.xdist_group` to prevent global config interference. * Add default log file * Update CHANGELOG.md * Readd change_logging_level() for backwards compatability * Add more options to config.py * Add a docstring to config.y * Add a docstring to config.y * rename parameter message_format * Improve color config * Improve color config * Update CHANGELOG.md * Improve color handling * Improve color handling * Remove console Logging explicityl from examples * Make log to console the default * Make log to console the default * Add individual level parameters for console and file * Add extra Handler section * Use dedicated levels for both handlers * Switch back to not use Handlers * Revert "Switch back to not use Handlers" This reverts commit 05bbccb. * Revert "Use dedicated levels for both handlers" This reverts commit ed0542b. * Revert "Add extra Handler section" This reverts commit a133cc8. * Revert "Add individual level parameters for console and file" This reverts commit 19f81c9. * Fix CHANGELOG.md * Update CHANGELOG.md * Fix CHANGELOG.md * Allow blank issues * Change default logging behaviour to other colors and no file logging * Use white for INFO * Use terminal default for INFO * Explicitly use stdout for StreamHandler * Use terminal default for Logging color * Add option for loggger name * Update CHANGELOG.md * Ensure custom formats are being applied * Catch empty config files * Update test to match new defaults --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Fix warnings filter * Remove config file (#391) * Remove config file * Remove yaml in MANIFEST.in * Improve config console logger: Allow stderr and improve multiline format (#395) * Add some validation to config.py * Improve file Permission handling in config.py * Remove unwanted return * Improve Docstrings in config.py * Improve Docstrings in config.py * Typo * Use code block in docstring * Allow stderr for console logging * Make docstrings more compact * Make docstrings more compact * Updated to actually use stderr * Simplify format() * Improve format * Add extra validation * Update CHANGELOG.md * Feature/v3/feature/381 feature equalize sizes and or flow rates between scenarios (#396) * First try * Centralize in FlowSystem * Add centralized handling * Logical Bug * Add to IO * Add test * Add some error handling and logging * Rename variable * Change parameter naming * Remove not needed method * Refactor to reduce duplication * Change defaults * Change defaults * Change defaults * Update docs * Update docs * Update docs * Update docs * Feature/v3/feature/Linked investments over multiple periods * Reorganize InvestmentParameters to always create the binary investment variable * Add new variable that indicates wether investment was taken, independent of period and allow linked periods * Improve Handling of linked periods * Improve Handling of linked periods * Add examples * Typos * Fix: reference invested only after it exists * Improve readbility of equation * Update from Merge * Improve InvestmentModel * Improve readability * Improve readability and reorder methods * Improve logging * Improve InvestmentModel * Rename to "invested" * Update CHANGELOG.md * Bugfix * Improve docstring * Improve InvestmentModel to be more inline with the previous Version * Improve Exceptions and add a meaningfull comment in InvestParameters * Typo * Feature/v3/feature/common resources in examples (#401) * Typo * Typos in scenario_example.py * Improve data files in examples * Improve data files in examples * Handle local install more gracefully with __version__ * Remove bad example * Increase timeout in examples * Improve test_examples.py * Improve example * Fixx Error message in test * Fix: Dependecy issue with python 3.10 * run ci on more branches if there are prs * Minor improvements and Update to the CHANGELOG.md * Feature/v3/feature/last minute improvements (#403) * Typos oin CHANGELOG.md * Add error handling in exmaple * Surface warnings during tests (avoid hiding deprecations) * Add missing docs file * Imrpve Releasnotes of v2.2.0 * Improve docs * Remove some filterwarnings from tsam --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Description
Brief description of the changes in this PR.
Type of Change
Related Issues
#367
Testing
Checklist
Summary by CodeRabbit
New Features
Refactor
Documentation
Examples