Skip to content

Commit 50fbb67

Browse files
committed
Improve indexer in results plotting
1 parent 3626517 commit 50fbb67

1 file changed

Lines changed: 31 additions & 12 deletions

File tree

flixopt/results.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,8 @@ def plot_heatmap(
626626
show: Whether to show the plot or not.
627627
engine: The engine to use for plotting. Can be either 'plotly' or 'matplotlib'.
628628
indexer: Optional selection dict, e.g., {'scenario': 'base', 'year': 2024}.
629-
If None, uses first value for each dimension.
629+
If None, uses first value for each dimension.
630+
If empty dict {}, uses all values.
630631
631632
Examples:
632633
Basic usage (uses first scenario, first year, all time):
@@ -844,15 +845,16 @@ def plot_node_balance(
844845
colors: The colors to use for the plot. See `flixopt.plotting.ColorType` for options.
845846
engine: The engine to use for plotting. Can be either 'plotly' or 'matplotlib'.
846847
indexer: Optional selection dict, e.g., {'scenario': 'base', 'year': 2024}.
847-
If None, uses first value for each dimension (except time).
848+
If None, uses first value for each dimension (except time).
849+
If empty dict {}, uses all values.
848850
mode: The mode to use for the dataset. Can be 'flow_rate' or 'flow_hours'.
849851
- 'flow_rate': Returns the flow_rates of the Node.
850852
- 'flow_hours': Returns the flow_hours of the Node. [flow_hours(t) = flow_rate(t) * dt(t)]. Renames suffixes to |flow_hours.
851853
drop_suffix: Whether to drop the suffix from the variable names.
852854
"""
853-
ds = self.node_balance(with_last_timestep=True, mode=mode, drop_suffix=drop_suffix)
855+
ds = self.node_balance(with_last_timestep=True, mode=mode, drop_suffix=drop_suffix, indexer=indexer)
854856

855-
ds, suffix_parts = _apply_indexer_to_data(ds, indexer)
857+
ds, suffix_parts = _apply_indexer_to_data(ds, indexer, drop=True)
856858
suffix = '--' + '-'.join(suffix_parts) if suffix_parts else ''
857859

858860
title = f'{self.label} (flow rates){suffix}' if mode == 'flow_rate' else f'{self.label} (flow hours){suffix}'
@@ -906,7 +908,8 @@ def plot_node_balance_pie(
906908
show: Whether to show the figure.
907909
engine: Plotting engine to use. Only 'plotly' is implemented atm.
908910
indexer: Optional selection dict, e.g., {'scenario': 'base', 'year': 2024}.
909-
If None, uses first value for each dimension.
911+
If None, uses first value for each dimension.
912+
If empty dict {}, uses all values.
910913
"""
911914
inputs = sanitize_dataset(
912915
ds=self.solution[self.inputs] * self._calculation_results.hours_per_timestep,
@@ -923,8 +926,8 @@ def plot_node_balance_pie(
923926
drop_suffix='|',
924927
)
925928

926-
inputs, suffix_parts = _apply_indexer_to_data(inputs, indexer)
927-
outputs, suffix_parts = _apply_indexer_to_data(outputs, indexer)
929+
inputs, suffix_parts = _apply_indexer_to_data(inputs, indexer, drop=True)
930+
outputs, suffix_parts = _apply_indexer_to_data(outputs, indexer, drop=True)
928931
suffix = '--' + '-'.join(suffix_parts) if suffix_parts else ''
929932

930933
title = f'{self.label} (total flow hours){suffix}'
@@ -976,6 +979,7 @@ def node_balance(
976979
with_last_timestep: bool = False,
977980
mode: Literal['flow_rate', 'flow_hours'] = 'flow_rate',
978981
drop_suffix: bool = False,
982+
indexer: Optional[Dict['FlowSystemDimensions', Any]] = None,
979983
) -> xr.Dataset:
980984
"""
981985
Returns a dataset with the node balance of the Component or Bus.
@@ -988,6 +992,9 @@ def node_balance(
988992
- 'flow_rate': Returns the flow_rates of the Node.
989993
- 'flow_hours': Returns the flow_hours of the Node. [flow_hours(t) = flow_rate(t) * dt(t)]. Renames suffixes to |flow_hours.
990994
drop_suffix: Whether to drop the suffix from the variable names.
995+
indexer: Optional selection dict, e.g., {'scenario': 'base', 'year': 2024}.
996+
If None, uses first value for each dimension.
997+
If empty dict {}, uses all values.
991998
"""
992999
ds = self.solution[self.inputs + self.outputs]
9931000

@@ -1007,6 +1014,8 @@ def node_balance(
10071014
drop_suffix='|' if drop_suffix else None,
10081015
)
10091016

1017+
ds, _ = _apply_indexer_to_data(ds, indexer, drop=True)
1018+
10101019
if mode == 'flow_hours':
10111020
ds = ds * self._calculation_results.hours_per_timestep
10121021
ds = ds.rename_vars({var: var.replace('flow_rate', 'flow_hours') for var in ds.data_vars})
@@ -1054,19 +1063,20 @@ def plot_charge_state(
10541063
engine: Plotting engine to use. Only 'plotly' is implemented atm.
10551064
style: The plotting mode for the flow_rate
10561065
indexer: Optional selection dict, e.g., {'scenario': 'base', 'year': 2024}.
1057-
If None, uses first value for each dimension.
1066+
If None, uses first value for each dimension.
1067+
If empty dict {}, uses all values.
10581068
10591069
Raises:
10601070
ValueError: If the Component is not a Storage.
10611071
"""
10621072
if not self.is_storage:
10631073
raise ValueError(f'Cant plot charge_state. "{self.label}" is not a storage')
10641074

1065-
ds = self.node_balance(with_last_timestep=True)
1075+
ds = self.node_balance(with_last_timestep=True, indexer=indexer)
10661076
charge_state = self.charge_state
10671077

1068-
ds, suffix_parts = _apply_indexer_to_data(ds, indexer)
1069-
charge_state, suffix_parts = _apply_indexer_to_data(charge_state, indexer)
1078+
ds, suffix_parts = _apply_indexer_to_data(ds, indexer, drop=True)
1079+
charge_state, suffix_parts = _apply_indexer_to_data(charge_state, indexer, drop=True)
10701080
suffix = '--' + '-'.join(suffix_parts) if suffix_parts else ''
10711081

10721082
title=f'Operation Balance of {self.label}{suffix}'
@@ -1340,6 +1350,9 @@ def plot_heatmap(
13401350
save: Whether to save the plot or not. If a path is provided, the plot will be saved at that location.
13411351
show: Whether to show the plot or not.
13421352
engine: The engine to use for plotting. Can be either 'plotly' or 'matplotlib'.
1353+
indexer: Optional selection dict, e.g., {'scenario': 'base', 'year': 2024}.
1354+
If None, uses first value for each dimension.
1355+
If empty dict {}, uses all values.
13431356
"""
13441357
dataarray, suffix_parts = _apply_indexer_to_data(dataarray, indexer, drop=True)
13451358
suffix = '--' + '-'.join(suffix_parts) if suffix_parts else ''
@@ -1608,13 +1621,19 @@ def apply_filter(array, coord_name: str, coord_values: Union[Any, List[Any]]):
16081621
return da
16091622

16101623

1611-
def _apply_indexer_to_data(data: Union[xr.DataArray, xr.Dataset], indexer: Optional[Dict[str, Any]] = None, drop=False):
1624+
def _apply_indexer_to_data(
1625+
data: Union[xr.DataArray, xr.Dataset],
1626+
indexer: Optional[Dict[str, Any]] = None,
1627+
drop=False
1628+
) -> Tuple[Union[xr.DataArray, xr.Dataset], List[str]]:
16121629
"""
16131630
Apply indexer selection or auto-select first values for non-time dimensions.
16141631
16151632
Args:
16161633
data: xarray Dataset or DataArray
16171634
indexer: Optional selection dict
1635+
If None, uses first value for each dimension (except time).
1636+
If empty dict {}, uses all values.
16181637
16191638
Returns:
16201639
Tuple of (selected_data, selection_string)

0 commit comments

Comments
 (0)