Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ examples/output
~$*.xlsx

# Development environment files
.idea/
.idea/

# Files from editable installs of pip
/InOutModule.egg-info/
80 changes: 79 additions & 1 deletion CaseStudy.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import copy
import warnings
from typing import Optional
from typing import Optional, Self

import numpy as np
import pandas as pd
Expand All @@ -12,6 +12,7 @@ class CaseStudy:

def __init__(self, data_folder: str, do_not_merge_single_node_buses: bool = False,
global_parameters_file: str = "Global_Parameters.xlsx", dGlobal_Parameters: pd.DataFrame = None,
global_scenarios_file: str = "Global_Scenarios.xlsx", dGlobal_Scenarios: pd.DataFrame = None,
power_parameters_file: str = "Power_Parameters.xlsx", dPower_Parameters: pd.DataFrame = None,
power_businfo_file: str = "Power_BusInfo.xlsx", dPower_BusInfo: pd.DataFrame = None,
power_network_file: str = "Power_Network.xlsx", dPower_Network: pd.DataFrame = None,
Expand All @@ -36,6 +37,12 @@ def __init__(self, data_folder: str, do_not_merge_single_node_buses: bool = Fals
self.global_parameters_file = global_parameters_file
self.dGlobal_Parameters = self.get_dGlobal_Parameters()

if dGlobal_Scenarios is not None:
self.dGlobal_Scenarios = dGlobal_Scenarios
else:
self.global_scenarios_file = global_scenarios_file
self.dGlobal_Scenarios = ExcelReader.get_dGlobal_Scenarios(self.data_folder + self.global_scenarios_file)

if dPower_Parameters is not None:
self.dPower_Parameters = dPower_Parameters
else:
Expand Down Expand Up @@ -147,6 +154,8 @@ def get_dGlobal_Parameters(self):
dGlobal_Parameters = dGlobal_Parameters.drop(dGlobal_Parameters.columns[0], axis=1)
dGlobal_Parameters = dGlobal_Parameters.set_index('Sectors')

self.yesNo_to_bool(dGlobal_Parameters, ['pEnablePower', 'pEnableGas', 'pEnableHeat', 'pEnableH2', 'pEnableRMIP'])

# Transform to make it easier to access values
dGlobal_Parameters = dGlobal_Parameters.drop(dGlobal_Parameters.columns[1:], axis=1) # Drop all columns but "Value" (rest is just for information in the Excel)
dGlobal_Parameters = dict({(parameter_name, parameter_value["Value"]) for parameter_name, parameter_value in dGlobal_Parameters.iterrows()}) # Transform into dictionary
Expand Down Expand Up @@ -190,6 +199,10 @@ def get_dPower_RoR(self):

dPower_RoR['InvestCostEUR'] = dPower_RoR['MaxProd'] * 1e-3 * (dPower_RoR['InvestCostPerMW'] * 1e-3 + dPower_RoR['InvestCostPerMWh'] * 1e-3 * dPower_RoR['Ene2PowRatio'])
dPower_RoR['MaxProd'] *= 1e-3

# If column 'scenario' is not present, add it
if 'scenario' not in dPower_RoR.columns:
dPower_RoR['scenario'] = 'ScenarioA' # TODO: Fill this dynamically, once the Excel file is updated
return dPower_RoR

def get_dPower_Storage(self):
Expand All @@ -201,6 +214,10 @@ def get_dPower_Storage(self):
dPower_Storage['InvestCostEUR'] = dPower_Storage['MaxProd'] * 1e-3 * (dPower_Storage['InvestCostPerMW'] * 1e-3 + dPower_Storage['InvestCostPerMWh'] * 1e-3 * dPower_Storage['Ene2PowRatio'])
dPower_Storage['MaxProd'] *= 1e-3
dPower_Storage['MaxCons'] *= 1e-3

# If column 'scenario' is not present, add it
if 'scenario' not in dPower_Storage.columns:
dPower_Storage['scenario'] = 'ScenarioA' # TODO: Fill this dynamically, once the Excel file is updated
return dPower_Storage

def get_dPower_Inflows(self):
Expand All @@ -209,6 +226,8 @@ def get_dPower_Inflows(self):
dPower_Inflows = dPower_Inflows.rename(columns={dPower_Inflows.columns[0]: "rp", dPower_Inflows.columns[1]: "g"})
dPower_Inflows = dPower_Inflows.melt(id_vars=['rp', 'g'], var_name='k', value_name='Inflow')
dPower_Inflows = dPower_Inflows.set_index(['rp', 'g', 'k'])

dPower_Inflows['scenario'] = 'ScenarioA' # TODO: Fill this dynamically, once the Excel file is updated
return dPower_Inflows

def get_dPower_ImpExpHubs(self):
Expand All @@ -234,6 +253,10 @@ def get_dPower_ImpExpHubs(self):
dPower_ImpExpHubs["Pmax Import"] *= 1e-3
dPower_ImpExpHubs["Pmax Export"] *= 1e-3

# If column 'scenario' is not present, add it
if 'scenario' not in dPower_ImpExpHubs.columns:
dPower_ImpExpHubs['scenario'] = 'ScenarioA' # TODO: Fill this dynamically, once the Excel file is updated

return dPower_ImpExpHubs

def get_dPower_ImpExpProfiles(self):
Expand Down Expand Up @@ -282,6 +305,10 @@ def get_dPower_ImpExpProfiles(self):
error_information *= 1e3 # Convert back to input format
raise ValueError(f"At least one hub has ExpFix exports which exceed the sum of Pmax of all connections. Please check: \n{error_information}\n")

# If column 'scenario' is not present, add it
if 'scenario' not in dPower_ImpExpProfiles.columns:
dPower_ImpExpProfiles['scenario'] = "ScenarioA" # TODO: Fill this dynamically, once the Excel file is updated

return dPower_ImpExpProfiles

@staticmethod
Expand Down Expand Up @@ -515,3 +542,54 @@ def to_full_hourly_model(self, inplace: bool) -> Optional['CaseStudy']:
return caseStudy
else:
return None

def _filter_dataframe(self, df_name: str, scenario_name: str) -> None:
"""
Filters the dataframe with the given name to only include the scenario with the given name.
:param df_name: The name of the dataframe to filter.
:param scenario_name: The name of the scenario to filter for.
:return: None
"""
if not hasattr(self, df_name):
raise ValueError(f"Dataframe '{df_name}' not found in the case study. Please check the input data.")
df = getattr(self, df_name)

filtered_df = df.loc[df['scenario'] == scenario_name]

if len(df) > 0 and len(filtered_df) == 0:
raise ValueError(f"Scenario '{scenario_name}' not found in '{df_name}'. Please check the input data.")

setattr(self, df_name, filtered_df)

def filter_scenario(self, scenario_name) -> Self:
"""
Filters each (relevant) dataframe in the case study to only include the scenario with the given name.
:param scenario_name: The name of the scenario to filter for.
:return: Copy of the case study with the filtered dataframes.
"""
caseStudy = self.copy()

# dGlobal_Parameters is not filtered, as it is the same for all scenarios
# dPower_Parameters is not filtered, as it is the same for all scenarios
caseStudy._filter_dataframe("dPower_BusInfo", scenario_name)
caseStudy._filter_dataframe("dPower_Network", scenario_name)
caseStudy._filter_dataframe("dPower_Demand", scenario_name)
caseStudy._filter_dataframe("dPower_WeightsRP", scenario_name)
caseStudy._filter_dataframe("dPower_WeightsK", scenario_name)
caseStudy._filter_dataframe("dPower_Hindex", scenario_name)

if hasattr(caseStudy, "dPower_ThermalGen"):
caseStudy._filter_dataframe("dPower_ThermalGen", scenario_name)
if hasattr(caseStudy, "dPower_RoR") and len(caseStudy.dPower_RoR) > 0:
caseStudy._filter_dataframe("dPower_RoR", scenario_name)
caseStudy._filter_dataframe("dPower_Inflows", scenario_name)
if hasattr(caseStudy, "dPower_VRES"):
caseStudy._filter_dataframe("dPower_VRES", scenario_name)
caseStudy._filter_dataframe("dPower_VRESProfiles", scenario_name)
if hasattr(caseStudy, "dPower_Storage"):
caseStudy._filter_dataframe("dPower_Storage", scenario_name)
if hasattr(caseStudy, "dPower_ImpExpHubs") and caseStudy.dPower_ImpExpHubs is not None:
caseStudy._filter_dataframe("dPower_ImpExpHubs", scenario_name)
caseStudy._filter_dataframe("dPower_ImpExpProfiles", scenario_name)

return caseStudy
21 changes: 21 additions & 0 deletions ExcelReader.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,27 @@ def __read_pivoted_file(excel_file_path: str, version_specifier: str, indices: l
return df


def get_dGlobal_Scenarios(excel_file_path: str, keep_excluded_entries: bool = False, do_not_convert_values: bool = False) -> pd.DataFrame:
"""
Read the dGlobal_Scenarios data from the Excel file.
:param excel_file_path: Path to the Excel file
:param keep_excluded_entries: Unused but kept for compatibility with other functions
:param do_not_convert_values: Unused but kept for compatibility with other functions
:return: dGlobal_Scenarios
"""
dGlobal_Scenarios = __read_non_pivoted_file(excel_file_path, "v0.1.0", ["scenarioID"], True, keep_excluded_entries)

if do_not_convert_values:
printer.warning("'do_not_convert_values' is set for 'get_dGlobal_Scenarios', although no values are converted anyway - please check if this is intended.")

# Check that there is only one sheet with the name 'Scenario'
check = dGlobal_Scenarios["scenario"].to_numpy()
if not (check[0] == check).all():
raise ValueError(f"There are multiple or falsely named sheets for '{excel_file_path}'. There should only be one sheet with the name 'Scenario', please check the Excel file.")

return dGlobal_Scenarios


def get_dPower_Hindex(excel_file_path: str, keep_excluded_entries: bool = False, do_not_convert_values: bool = False) -> pd.DataFrame:
"""
Read the dPower_Hindex data from the Excel file.
Expand Down
10 changes: 10 additions & 0 deletions ExcelWriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ def _write_Excel_from_definition(self, data: pd.DataFrame, folder_path: str, exc
wb.save(path)
printer.information(f"Saved Excel file to '{path}' after {time.time() - start_time:.2f} seconds")

def write_dGlobal_Scenarios(self, dGlobal_Scenarios: pd.DataFrame, folder_path: str) -> None:
"""
Write the dGlobal_Scenarios DataFrame to an Excel file in LEGO format.
:param dGlobal_Scenarios: DataFrame containing the dGlobal_Scenarios data.
:param folder_path: Path to the folder where the Excel file will be saved.
:return: None
"""
self._write_Excel_from_definition(dGlobal_Scenarios, folder_path, "Global_Scenarios")

def write_dPower_Hindex(self, dPower_Hindex: pd.DataFrame, folder_path: str) -> None:
"""
Write the dPower_Hindex DataFrame to an Excel file in LEGO format.
Expand Down Expand Up @@ -316,6 +325,7 @@ def write_dData_Packages(self, dData_Packages: pd.DataFrame, folder_path: str) -
printer.separator()

combinations = [
("Global_Scenarios", f"{args.caseStudyFolder}Global_Scenarios.xlsx", ExcelReader.get_dGlobal_Scenarios, ew.write_dGlobal_Scenarios),
("Power_Hindex", f"{args.caseStudyFolder}Power_Hindex.xlsx", ExcelReader.get_dPower_Hindex, ew.write_dPower_Hindex),
("Power_WeightsRP", f"{args.caseStudyFolder}Power_WeightsRP.xlsx", ExcelReader.get_dPower_WeightsRP, ew.write_dPower_WeightsRP),
("Power_WeightsK", f"{args.caseStudyFolder}Power_WeightsK.xlsx", ExcelReader.get_dPower_WeightsK, ew.write_dPower_WeightsK),
Expand Down
26 changes: 26 additions & 0 deletions TableDefinitions.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<TableDefinitions>
<TableDefinition id="Global_Scenarios">
<Version>v0.1.0</Version>
<TableHeader>Global - Scenarios and Probabilities</TableHeader>
<DescriptionRowHeight>30.0</DescriptionRowHeight>
<Columns>
<Column id="excl" scenarioDependent="False"/>
<Column id="id" scenarioDependent="False"/>
<Column id="scenarioID" scenarioDependent="False"/>
<Column id="relativeWeight" scenarioDependent="False"/>
<Column id="comments" scenarioDependent="False"/>
</Columns>
</TableDefinition>
<TableDefinition id="Power_Hindex">
<Version>v0.1.2</Version>
<TableHeader>Power - Relation among periods and representative periods</TableHeader>
Expand Down Expand Up @@ -598,13 +610,27 @@
<ColumnWidth>16.86</ColumnWidth>
<CellStyle>rightFloat1</CellStyle>
</Column>
<Column id="relativeWeight">
<ReadableName>Relative Weight</ReadableName>
<Description>Relative weight of scenario (gets calculated relatively to all other scenarios)</Description>
<Unit>[float]</Unit>
<ColumnWidth>15.0</ColumnWidth>
<CellStyle>rightFloat2</CellStyle>
</Column>
<Column id="rp">
<ReadableName>rp</ReadableName>
<Description>Representative period</Description>
<Unit>[rp]</Unit>
<ColumnWidth>15.0</ColumnWidth>
<CellStyle>general</CellStyle>
</Column>
<Column id="scenarioID">
<ReadableName>Scenario ID</ReadableName>
<Description>Scenario name</Description>
<Unit>[scenario]</Unit>
<ColumnWidth>41.0</ColumnWidth>
<CellStyle>general</CellStyle>
</Column>
<Column id="sources">
<ReadableName>Source(s)</ReadableName>
<Description>List of used sources (detailing which values are from where)</Description>
Expand Down
Loading
Loading