From e23ae7fc6da1b482f8cfd2abc509fc5b99558f82 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 11:33:51 +0300 Subject: [PATCH 01/14] Add spatial parameters --- app/pages/utils/config.yaml | 11 ++++++++++- app/pages/utils/spatial_pre_run.py | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/pages/utils/config.yaml b/app/pages/utils/config.yaml index 98103ee..ee4849f 100644 --- a/app/pages/utils/config.yaml +++ b/app/pages/utils/config.yaml @@ -290,8 +290,14 @@ scenario_names: ########## spatial parameters spatial_parameters: + cf: + nice_name: Capacity Factor + unit: "%" p_nom: - nice_name: Nominal Power + nice_name: Optimal Nominal Power + unit: (MW) + p_nom_opt: + nice_name: Original Nominal Power unit: (MW) marginal_cost: nice_name: Cost During Production @@ -299,6 +305,9 @@ spatial_parameters: capital_cost: nice_name: Cost Of Expanding Generation unit: (euro/MW) + bus_load: + nice_name: Cost Of Expanding Generation + unit: (MW) network_parameters: total_capacity: Total Capacity (GW) diff --git a/app/pages/utils/spatial_pre_run.py b/app/pages/utils/spatial_pre_run.py index ca51c50..8e90a16 100644 --- a/app/pages/utils/spatial_pre_run.py +++ b/app/pages/utils/spatial_pre_run.py @@ -42,7 +42,7 @@ def _get_gen_unique_names(network): gen_unique_names.remove("load") return gen_unique_names -slected_cols_gen = ["p_nom","marginal_cost","capital_cost"] +slected_cols_gen = ["cf", "p_nom", "p_nom_opt", "marginal_cost", "capital_cost", "bus_load"] def _get_gen_df(network,gpd_bus_regions): gen_unique_names=_get_gen_unique_names(network) From f9ac6e3a3bfa0afc468d66e6a0ca0f95dac21a02 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 11:34:02 +0300 Subject: [PATCH 02/14] Minor fixes --- app/pages/2_Spatial_configuration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/pages/2_Spatial_configuration.py b/app/pages/2_Spatial_configuration.py index 2d3c0c0..1c1c467 100644 --- a/app/pages/2_Spatial_configuration.py +++ b/app/pages/2_Spatial_configuration.py @@ -30,7 +30,7 @@ data=helper.make_return_dict() -st.title("System operation") +st.title("Spatial configuration") _, main_col, _ = st.columns([1,90,1]) @@ -80,7 +80,7 @@ def spatial_param_formatter(param): colorpeth_param = st.selectbox( "Regions", colorpeth_nodes_param, - format_func= spatial_param_formatter, + format_func = spatial_param_formatter, key="colorpeth_param_carrier" ) @@ -121,7 +121,7 @@ def spatial_param_formatter(param): with col3: points_param = st.selectbox( "Nodes", colorpeth_nodes_param, - format_func= spatial_param_formatter, + format_func = spatial_param_formatter, key="points_param_carrier" ) From f97ea15390a33a4be57c10d1f66a342f7bec4c86 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 12:58:34 +0300 Subject: [PATCH 03/14] Improve output of spatial parameters for generators --- app/pages/utils/spatial_pre_run.py | 40 ++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/app/pages/utils/spatial_pre_run.py b/app/pages/utils/spatial_pre_run.py index 8e90a16..13ed3de 100644 --- a/app/pages/utils/spatial_pre_run.py +++ b/app/pages/utils/spatial_pre_run.py @@ -42,27 +42,47 @@ def _get_gen_unique_names(network): gen_unique_names.remove("load") return gen_unique_names -slected_cols_gen = ["cf", "p_nom", "p_nom_opt", "marginal_cost", "capital_cost", "bus_load"] +# TODO Add load and stores +selected_cols_gen = ["cf", "p_nom", "p_nom_opt", "marginal_cost", "capital_cost"]# "bus_load"] def _get_gen_df(network,gpd_bus_regions): - gen_unique_names=_get_gen_unique_names(network) - multi_index= pd.MultiIndex.from_product([gen_unique_names, slected_cols_gen], + res_carriers_names = ["solar", "onwind", "offwind-ac", "offwind-dc", "hydro", "ror", "geothermal", "biomass"] + network_carriers = list(network.generators.carrier.unique())#.remove("load") + network_res_carriers = [x for x in res_carriers_names if x in network_carriers] + # network_carriers replaced by network_res_carriers to focus on RES + multi_index= pd.MultiIndex.from_product([network_res_carriers, selected_cols_gen], names=['carrier','parameter']) param_bus_value_df = pd.DataFrame( index=multi_index,columns=gpd_bus_regions.name) + + i_buses = network.buses_t.p.sum(axis=0).index + load_df = pd.DataFrame({"bus_load": network.buses_t.p.sum(axis=0), "name": network.buses_t.p.columns}) + + for carrier_in_unique in network_res_carriers: + i_buses = network.buses_t.p.sum(axis=0).index - for carrier_in_unique in gen_unique_names: generator_network=network.generators.copy() # carrier sorted value from generator_network - carrier_df=generator_network[generator_network["carrier"] == carrier_in_unique] + i_carrier = generator_network["carrier"] == carrier_in_unique + carrier_df = generator_network[i_carrier] + # calculate capacity factors + p_gen = network.generators_t.p[network.generators[i_carrier].index].mean(axis=0) + # TODO since p_nom_opt can be zero, there may be a better way to calculate cf + carrier_df["cf"] = 100 * (p_gen / generator_network[i_carrier].p_nom_opt) + # arranging according to geopandas bus regions temp_name_series = pd.Series([0]*len(gpd_bus_regions), index=gpd_bus_regions.name, name="bus") - # merging both to get all params df - merged_gen_df=carrier_df.merge(temp_name_series, left_on="bus", right_on="name", how="right") - # putting it in the param_bus_value_df - for param in slected_cols_gen: + + merged_gen_df = ( + carrier_df + .merge(temp_name_series, left_on="bus", right_on="name", how="right") + # TODO MultiIndex structure leads to identical load entries for each carrier - should be improved + #.merge(load_df, left_on="bus_x", right_on="name", how="left") + ) + # putting it in the param_bus_value_df for each carrier in generators + for param in selected_cols_gen: param_bus_value_df.loc[(carrier_in_unique, param)]=list(merged_gen_df[param]) - param_bus_value_df.replace([np.inf, -np.inf,np.nan], 0, inplace=True) + param_bus_value_df.replace([np.inf, -np.inf, np.nan], 0, inplace=True) return param_bus_value_df def _make_plot_lines_df(pypsa_network): From 3b4cc623554f662e7ed5de5cc53e9850196a823b Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 13:19:30 +0300 Subject: [PATCH 04/14] Fix config parameters for spatial plots --- app/pages/utils/config.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/pages/utils/config.yaml b/app/pages/utils/config.yaml index ee4849f..ac21dec 100644 --- a/app/pages/utils/config.yaml +++ b/app/pages/utils/config.yaml @@ -306,14 +306,14 @@ spatial_parameters: nice_name: Cost Of Expanding Generation unit: (euro/MW) bus_load: - nice_name: Cost Of Expanding Generation + nice_name: Electricity Load unit: (MW) network_parameters: - total_capacity: Total Capacity (GW) - reinforcement: Reinforcement (GW) - original_capacity: Original Capacity (GW) - max_capacity: Maximum Capacity (GW) + total_capacity: Total Capacity (MVA) + reinforcement: Reinforcement (MVA) + original_capacity: Original Capacity (MVA) + max_capacity: Maximum Capacity (MVA) length: Line Length (km) carrier: From 78f7e2953f55acdc23fe3a840d0fed59d20925f1 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 13:56:18 +0300 Subject: [PATCH 05/14] Fix axis labs --- app/pages/3_System_operation.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/pages/3_System_operation.py b/app/pages/3_System_operation.py index 68c396f..600d501 100644 --- a/app/pages/3_System_operation.py +++ b/app/pages/3_System_operation.py @@ -28,9 +28,9 @@ import datetime -gen_df=helper.get_gen_t_dict() -storage_df=helper.get_storage_t_dict() -links_df=helper.get_links_t_dict() +gen_df = helper.get_gen_t_dict() +storage_df = helper.get_storage_t_dict() +links_df = helper.get_links_t_dict() res_choices = helper.config["operation"]["resolution"] @@ -55,7 +55,7 @@ def scenario_formatter(scenario): selected_network = st.selectbox( "Select which scenario's plot you want to see :", list(gen_df.keys()), - format_func=scenario_formatter, + format_func = scenario_formatter, ) country_data=gen_df.get(selected_network) @@ -65,7 +65,7 @@ def scenario_formatter(scenario): st.subheader("Generators plot is here.") def gen_formatter(gen): - return helper.config["gen_t_parameter"][gen]["nice_name"] + " "+helper.config["gen_t_parameter"][gen]["unit"] + return helper.config["gen_t_parameter"][gen]["nice_name"] _, gen_param_col,_,res_param_col,_,date_range_param, _ = st.columns([1,20,1,20,1,50,1]) _, gen_plot_col, _ = st.columns([1,80,1]) @@ -81,7 +81,7 @@ def gen_formatter(gen): with res_param_col: choices = res_choices - res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x],key="gen_res") + res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x], key="gen_res") with date_range_param: min_index=gen_df.index[0] @@ -98,13 +98,13 @@ def gen_formatter(gen): ) -gen_df=gen_df.loc[values[0]:values[1]].resample(res).mean() +gen_df = gen_df.loc[values[0]:values[1]].resample(res).mean() -gen_area_plot=gen_df.hvplot.area(**kwargs,group_label=helper.config["gen_t_parameter"][selected_gen]["legend_title"] -) -gen_area_plot=gen_area_plot.opts(ylabel=helper.config["gen_t_parameter"][selected_gen]["unit"], - ) -s=hv.render(gen_area_plot,backend='bokeh') +ylab = helper.config["gen_t_parameter"][selected_gen]["nice_name"] + " ["+str(helper.config["gen_t_parameter"][selected_gen]["unit"] + "]") +# Not sure we really need a title, as there is still a header +gen_area_plot = gen_df.hvplot.area(**kwargs, group_label=helper.config["gen_t_parameter"][selected_gen]["legend_title"]) +gen_area_plot = gen_area_plot.opts(xlabel="", ylabel=ylab) +s=hv.render(gen_area_plot, backend='bokeh') with gen_plot_col: st.bokeh_chart(s, use_container_width=True) From bc1d36e7c6ef10809678abe539e43b6193e2f065 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 13:56:38 +0300 Subject: [PATCH 06/14] Remove load from generators data --- app/pages/3_System_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pages/3_System_operation.py b/app/pages/3_System_operation.py index 600d501..133161c 100644 --- a/app/pages/3_System_operation.py +++ b/app/pages/3_System_operation.py @@ -77,7 +77,7 @@ def gen_formatter(gen): format_func=gen_formatter ) -gen_df=country_data[selected_gen] +gen_df=country_data[selected_gen].drop("Load", axis=1) with res_param_col: choices = res_choices From 118329967439db107db5438d1e1e2e13cbc0799e Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 15:00:00 +0300 Subject: [PATCH 07/14] Revise config parameters for the system-operation plot --- app/pages/utils/config.yaml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/app/pages/utils/config.yaml b/app/pages/utils/config.yaml index ac21dec..97ddcf1 100644 --- a/app/pages/utils/config.yaml +++ b/app/pages/utils/config.yaml @@ -361,45 +361,45 @@ carrier_colors: gen_t_parameter: p: - nice_name: Active Power At Bus - unit: (MW) - legend_title: Carriers + nice_name: Supply + unit: MW + legend_title: " " p_max_pu: nice_name: Maximum Output Possible Per Unit Nominal Power - unit: (MW) - legend_title: Carriers + unit: MW + legend_title: " " storage_t_parameter: p: nice_name: Active Power - unit: (MW) + unit: MW legend_title: Region Number and Storage Type inflow: nice_name: Inflow To State Of Charge - unit: (MW) + unit: MW legend_title: Region Number and Storage Type spill: nice_name: Spillage For Each Snapshot - unit: (MW) + unit: MW legend_title: Region Number and Storage Type state_of_charge: nice_name: State Of Charge - unit: (MWh) + unit: MWh legend_title: Region Number and Storage Type links_t_parameter: p0: - nice_name: Active Power Flow - unit: (MW) - legend_title: Not Sure + nice_name: Demand + unit: MW + legend_title: " " mu_upper: nice_name: Shadow Price Of Maximum Nominal Power - unit: (euro/MW) - legend_title: Not Sure + unit: euro/MW + legend_title: " " mu_lower: nice_name: Shadow Price Of Minimum Nominal Power - unit: (euro/MW) - legend_title: Not Sure + unit: euro/MW + legend_title: " " ########### SCENARIO COMPARISION parameters From 51c0c49d83222a5220c5fe62b56f97b1873e750e Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 15:01:43 +0300 Subject: [PATCH 08/14] Revise System Operation tab --- app/pages/3_System_operation.py | 195 +++++++++++++++++--------------- 1 file changed, 101 insertions(+), 94 deletions(-) diff --git a/app/pages/3_System_operation.py b/app/pages/3_System_operation.py index 133161c..8813690 100644 --- a/app/pages/3_System_operation.py +++ b/app/pages/3_System_operation.py @@ -46,7 +46,7 @@ st.title("System operation") -_, main_col, _ = st.columns([1,90,1]) +_, main_col, _, suppl_col, _ = st.columns([1, 35, 1, 20, 1]) def scenario_formatter(scenario): return helper.config["scenario_names"][scenario] @@ -57,31 +57,36 @@ def scenario_formatter(scenario): list(gen_df.keys()), format_func = scenario_formatter, ) +with suppl_col: + choices = res_choices + res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x], key="gen_res") + country_data=gen_df.get(selected_network) ##################### generators ##################### -st.subheader("Generators plot is here.") +# st.subheader("Generators plot is here.") def gen_formatter(gen): return helper.config["gen_t_parameter"][gen]["nice_name"] -_, gen_param_col,_,res_param_col,_,date_range_param, _ = st.columns([1,20,1,20,1,50,1]) -_, gen_plot_col, _ = st.columns([1,80,1]) +# _, gen_param_col, _, res_param_col,_ ,date_range_param, _ = st.columns([1,20,1,20,1,50,1]) +_, date_range_param, _ = st.columns([1, 50, 1]) +_, gen_plot_col, _ = st.columns([1, 80, 1]) -with gen_param_col: - selected_gen = st.selectbox( - "options", - options=list(country_data.keys()), - format_func=gen_formatter - ) +# with gen_param_col: +# selected_gen = st.selectbox( +# "options", +# options=list(country_data.keys()), +# format_func=gen_formatter +# ) -gen_df=country_data[selected_gen].drop("Load", axis=1) +gen_df=country_data["p"].drop("Load", axis=1) -with res_param_col: - choices = res_choices - res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x], key="gen_res") +# with res_param_col: +# choices = res_choices +# res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x], key="gen_res") with date_range_param: min_index=gen_df.index[0] @@ -100,9 +105,9 @@ def gen_formatter(gen): gen_df = gen_df.loc[values[0]:values[1]].resample(res).mean() -ylab = helper.config["gen_t_parameter"][selected_gen]["nice_name"] + " ["+str(helper.config["gen_t_parameter"][selected_gen]["unit"] + "]") +ylab = helper.config["gen_t_parameter"]["p"]["nice_name"] + " ["+str(helper.config["gen_t_parameter"]["p"]["unit"] + "]") # Not sure we really need a title, as there is still a header -gen_area_plot = gen_df.hvplot.area(**kwargs, group_label=helper.config["gen_t_parameter"][selected_gen]["legend_title"]) +gen_area_plot = gen_df.hvplot.area(**kwargs, group_label=helper.config["gen_t_parameter"]["p"]["legend_title"]) gen_area_plot = gen_area_plot.opts(xlabel="", ylabel=ylab) s=hv.render(gen_area_plot, backend='bokeh') @@ -112,108 +117,110 @@ def gen_formatter(gen): ##################### links ##################### -st.subheader("Links plot is here.") -_, links_param_col,_,res_param_col,_,date_range_param, _ = st.columns([1,20,1,20,1,50,1]) -_, links_plot_col, _ = st.columns([1,80,1]) +# st.subheader("Links plot is here.") +# _, links_param_col,_,res_param_col,_,date_range_param, _ = st.columns([1,20,1,20,1,50,1]) +_, links_plot_col, _ = st.columns([1, 80, 1]) links_country_data=links_df.get(selected_network) def links_formatter(link): return helper.config["links_t_parameter"][link]["nice_name"] + " "+helper.config["links_t_parameter"][link]["unit"] -with links_param_col: - selected_link = st.selectbox( - "Select which link's plot you want to see :", - list(links_country_data.keys()), - format_func=links_formatter - ) - -links_df=links_country_data[selected_link] - -with res_param_col: - choices = res_choices - res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x], key="links_res") - -with date_range_param: - min_index=links_df.index[0] - max_index=links_df.index[-1] - min_value = datetime.datetime(min_index.year, min_index.month, min_index.day,max_index.hour,max_index.minute) - max_value = datetime.datetime(max_index.year, max_index.month, max_index.day,max_index.hour,max_index.minute) - values = st.slider( - 'Select a range of values', - min_value, max_value, (min_value, max_value), - # step=datetime.timedelta(hours=int(res[:-1])), - format="D MMM, HH:mm", - label_visibility='hidden', - key="links_date" - ) +# with links_param_col: +# selected_link = st.selectbox( +# "Select which link's plot you want to see :", +# list(links_country_data.keys()), +# format_func=links_formatter +# ) + +links_df = links_country_data["p0"] + +# with res_param_col: +# choices = res_choices +# res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x], key="links_res") + +# with date_range_param: +# min_index = links_df.index[0] +# max_index = links_df.index[-1] +# min_value = datetime.datetime(min_index.year, min_index.month, min_index.day, max_index.hour, max_index.minute) +# max_value = datetime.datetime(max_index.year, max_index.month, max_index.day, max_index.hour, max_index.minute) +# values = st.slider( +# 'Select a range of values', +# min_value, max_value, (min_value, max_value), +# # step=datetime.timedelta(hours=int(res[:-1])), +# format="D MMM, HH:mm", +# label_visibility='hidden', +# key="links_date" +# ) links_df=links_df.loc[values[0]:values[1]].resample(res).mean() +ylab = helper.config["links_t_parameter"]["p0"]["nice_name"] + " ["+str(helper.config["links_t_parameter"]["p0"]["unit"] + "]") + with links_plot_col: - supply_df=pd.DataFrame(index=links_df.index) + # supply_df=pd.DataFrame(index=links_df.index) demand_df=pd.DataFrame(index=links_df.index) - supply_df["battery charger"]=links_df["battery charger"] - supply_df["H2 Electrolysis"]=links_df["H2 Electrolysis"] + # supply_df["battery charger"]=links_df["battery charger"] + # supply_df["H2 Electrolysis"]=links_df["H2 Electrolysis"] demand_df["battery discharger"]=links_df["battery discharger"] demand_df["Fuel Cell"]=links_df["Fuel Cell"] - supply_area_plot=supply_df.hvplot.area(**kwargs,ylabel=helper.config["links_t_parameter"][selected_link]["unit"], - group_label=helper.config["links_t_parameter"][selected_link]["legend_title"]) - demand_area_plot=demand_df.hvplot.area(**kwargs,ylabel=helper.config["links_t_parameter"][selected_link]["unit"], - group_label=helper.config["links_t_parameter"][selected_link]["legend_title"]) - s=hv.render(supply_area_plot,backend='bokeh') - s2=hv.render(demand_area_plot,backend='bokeh') - st.subheader("Supply") - st.bokeh_chart(s, use_container_width=True) - st.subheader("Consumption") + # supply_area_plot=supply_df.hvplot.area(**kwargs,ylabel=helper.config["links_t_parameter"][selected_link]["unit"], + # group_label=helper.config["links_t_parameter"][selected_link]["legend_title"]) + demand_area_plot=demand_df.hvplot.area(**kwargs, ylabel=ylab, + group_label=helper.config["links_t_parameter"]["p0"]["legend_title"]) + # s=hv.render(supply_area_plot,backend='bokeh') + s2=hv.render(demand_area_plot, backend='bokeh') + # st.subheader("Supply") + # st.bokeh_chart(s, use_container_width=True) + # st.subheader("Consumption") st.bokeh_chart(s2, use_container_width=True) -##################### storage ##################### +# ##################### storage ##################### -st.subheader("Storage plot is here.") +# st.subheader("Storage plot is here.") -_, storage_param_col,_,res_param_col,_,date_range_param, _ = st.columns([1,20,1,20,1,50,1]) -_, storage_plot_col, _ = st.columns([1,80,1]) +# _, storage_param_col,_,res_param_col,_,date_range_param, _ = st.columns([1,20,1,20,1,50,1]) +# _, storage_plot_col, _ = st.columns([1,80,1]) -storage_country_data=storage_df.get(selected_network) +# storage_country_data=storage_df.get(selected_network) -def storage_formatter(storage): - return helper.config["storage_t_parameter"][storage]["nice_name"] + " "+helper.config["storage_t_parameter"][storage]["unit"] +# def storage_formatter(storage): +# return helper.config["storage_t_parameter"][storage]["nice_name"] + " "+helper.config["storage_t_parameter"][storage]["unit"] -with storage_param_col: - selected_storage = st.selectbox( - "options", - list(storage_country_data.keys()), - format_func=storage_formatter - ) +# with storage_param_col: +# selected_storage = st.selectbox( +# "options", +# list(storage_country_data.keys()), +# format_func=storage_formatter +# ) -storage_df=storage_country_data[selected_storage] +# storage_df=storage_country_data[selected_storage] -with res_param_col: - choices = res_choices - res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x],key="storage_res") +# with res_param_col: +# choices = res_choices +# res = st.selectbox("Resolution", choices, format_func=lambda x: choices[x],key="storage_res") -with date_range_param: - min_index=storage_df.index[0] - max_index=storage_df.index[-1] - min_value = datetime.datetime(min_index.year, min_index.month, min_index.day,max_index.hour,max_index.minute) - max_value = datetime.datetime(max_index.year, max_index.month, max_index.day,max_index.hour,max_index.minute) - values = st.slider( - 'Select a range of values', - min_value, max_value, (min_value, max_value), - # step=datetime.timedelta(hours=int(res[:-1])), - format="D MMM, HH:mm", - label_visibility='hidden', - key="storage_date" - ) +# with date_range_param: +# min_index=storage_df.index[0] +# max_index=storage_df.index[-1] +# min_value = datetime.datetime(min_index.year, min_index.month, min_index.day,max_index.hour,max_index.minute) +# max_value = datetime.datetime(max_index.year, max_index.month, max_index.day,max_index.hour,max_index.minute) +# values = st.slider( +# 'Select a range of values', +# min_value, max_value, (min_value, max_value), +# # step=datetime.timedelta(hours=int(res[:-1])), +# format="D MMM, HH:mm", +# label_visibility='hidden', +# key="storage_date" +# ) -storage_df=storage_df.loc[values[0]:values[1]].resample(res).mean() +# storage_df=storage_df.loc[values[0]:values[1]].resample(res).mean() -with storage_plot_col: - storage_area_plot=storage_df.hvplot.area(**kwargs, - ylabel=helper.config["storage_t_parameter"][selected_storage]["unit"], - group_label=helper.config["storage_t_parameter"][selected_storage]["legend_title"]) - s=hv.render(storage_area_plot,backend='bokeh') - st.bokeh_chart(s, use_container_width=True) +# with storage_plot_col: +# storage_area_plot=storage_df.hvplot.area(**kwargs, +# ylabel=helper.config["storage_t_parameter"][selected_storage]["unit"], +# group_label=helper.config["storage_t_parameter"][selected_storage]["legend_title"]) +# s=hv.render(storage_area_plot,backend='bokeh') +# st.bokeh_chart(s, use_container_width=True) From 79baf4b928979e18e81068bc44fe7242c0e4e388 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 15:40:48 +0300 Subject: [PATCH 09/14] Use scatterplot for CF only --- app/pages/1_Scenario_comparison.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/app/pages/1_Scenario_comparison.py b/app/pages/1_Scenario_comparison.py index 4a8dd7c..a32206f 100644 --- a/app/pages/1_Scenario_comparison.py +++ b/app/pages/1_Scenario_comparison.py @@ -25,13 +25,23 @@ def main(): df = helper.get_df_for_parameter( network_map, option, helper.add_values_for_statistics, helper.get_stats_col_names ) - _,plot_col,_=st.columns([1,80,1]) + _, plot_col,_ = st.columns([1, 80, 1]) with plot_col: - st.plotly_chart(px.bar(df, y=df.columns,labels={ - "value":get_stat_unit(option), - "index":"scenarios" - }, title=option),use_cointainer_width=True - ) + # TODO bar can be replaced scatter for CF + if option == "Capacity Factor": + st.plotly_chart(px.scatter(df, y=df.columns, + labels={ + "value":get_stat_unit(option), + "index":"scenarios" + }, title=option),use_cointainer_width=True + ) + else: + st.plotly_chart(px.bar(df, y=df.columns, + labels={ + "value":get_stat_unit(option), + "index":"scenarios" + }, title=option),use_cointainer_width=True + ) ##### second dropdown plotting n.carrier ##### option = st.selectbox( From dbd9c8729432478971ec860b7030856e0939756a Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 20:57:27 +0300 Subject: [PATCH 10/14] Fix comments for the scatter plot --- app/pages/1_Scenario_comparison.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/pages/1_Scenario_comparison.py b/app/pages/1_Scenario_comparison.py index a32206f..3fa87f8 100644 --- a/app/pages/1_Scenario_comparison.py +++ b/app/pages/1_Scenario_comparison.py @@ -27,9 +27,10 @@ def main(): ) _, plot_col,_ = st.columns([1, 80, 1]) with plot_col: - # TODO bar can be replaced scatter for CF if option == "Capacity Factor": st.plotly_chart(px.scatter(df, y=df.columns, + # TODO Would be nice to adjust markers + # size=[20], labels={ "value":get_stat_unit(option), "index":"scenarios" From 3010c9bae0bb8a438b472182ea9066f1f8cd0235 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 20:58:27 +0300 Subject: [PATCH 11/14] Fix the consumption time-series --- app/pages/3_System_operation.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/app/pages/3_System_operation.py b/app/pages/3_System_operation.py index 8813690..ec03f0d 100644 --- a/app/pages/3_System_operation.py +++ b/app/pages/3_System_operation.py @@ -27,10 +27,15 @@ from shapely.geometry import Point, LineString, shape import datetime +non_empth_links_keys=[param for param in helper.config["links_t_parameter"]] +non_empth_loads_keys=[param for param in helper.config["loads_t_parameter"]] +non_empth_stores_keys=[param for param in helper.config["stores_t_parameter"]] gen_df = helper.get_gen_t_dict() storage_df = helper.get_storage_t_dict() -links_df = helper.get_links_t_dict() +links_df = helper.get_links_t_dict("links_t", non_empth_links_keys) +loads_df = helper.get_links_t_dict("loads_t", non_empth_loads_keys) +stores_df = helper.get_links_t_dict("stores_t", non_empth_stores_keys) res_choices = helper.config["operation"]["resolution"] @@ -122,6 +127,8 @@ def gen_formatter(gen): _, links_plot_col, _ = st.columns([1, 80, 1]) links_country_data=links_df.get(selected_network) +loads_country_data=loads_df.get(selected_network) +stores_country_data=stores_df.get(selected_network) def links_formatter(link): return helper.config["links_t_parameter"][link]["nice_name"] + " "+helper.config["links_t_parameter"][link]["unit"] @@ -134,6 +141,16 @@ def links_formatter(link): # ) links_df = links_country_data["p0"] +loads_df = loads_country_data["p"] +stores_df = stores_country_data["p"] + +# TODO Remove hard-coding +h2_cols = [col for col in stores_df.columns if "H2" in col] +battery_cols = [col for col in stores_df.columns if "battery" in col] + +demand_df=pd.DataFrame({"load": loads_df.sum(axis=1)}) +demand_df["H2"]=stores_df[h2_cols].sum(axis=1) +demand_df["battery"]=stores_df[battery_cols].sum(axis=1) # with res_param_col: # choices = res_choices @@ -158,21 +175,9 @@ def links_formatter(link): ylab = helper.config["links_t_parameter"]["p0"]["nice_name"] + " ["+str(helper.config["links_t_parameter"]["p0"]["unit"] + "]") with links_plot_col: - # supply_df=pd.DataFrame(index=links_df.index) - demand_df=pd.DataFrame(index=links_df.index) - # supply_df["battery charger"]=links_df["battery charger"] - # supply_df["H2 Electrolysis"]=links_df["H2 Electrolysis"] - demand_df["battery discharger"]=links_df["battery discharger"] - demand_df["Fuel Cell"]=links_df["Fuel Cell"] - # supply_area_plot=supply_df.hvplot.area(**kwargs,ylabel=helper.config["links_t_parameter"][selected_link]["unit"], - # group_label=helper.config["links_t_parameter"][selected_link]["legend_title"]) demand_area_plot=demand_df.hvplot.area(**kwargs, ylabel=ylab, group_label=helper.config["links_t_parameter"]["p0"]["legend_title"]) - # s=hv.render(supply_area_plot,backend='bokeh') s2=hv.render(demand_area_plot, backend='bokeh') - # st.subheader("Supply") - # st.bokeh_chart(s, use_container_width=True) - # st.subheader("Consumption") st.bokeh_chart(s2, use_container_width=True) From e0bfcc51cca25f600c0d72491585df75ab8d98da Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 21:00:24 +0300 Subject: [PATCH 12/14] Add helpers to get consumption data --- app/pages/utils/config.yaml | 10 ++++++++ app/pages/utils/system_operation_prerun.py | 29 ++++++++++++---------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/app/pages/utils/config.yaml b/app/pages/utils/config.yaml index 97ddcf1..d99696b 100644 --- a/app/pages/utils/config.yaml +++ b/app/pages/utils/config.yaml @@ -387,6 +387,16 @@ storage_t_parameter: unit: MWh legend_title: Region Number and Storage Type +loads_t_parameter: + p: + nice_name: Demand + unit: MW + +stores_t_parameter: + p: + nice_name: Load State + unit: MW + links_t_parameter: p0: nice_name: Demand diff --git a/app/pages/utils/system_operation_prerun.py b/app/pages/utils/system_operation_prerun.py index b768bbc..8839038 100644 --- a/app/pages/utils/system_operation_prerun.py +++ b/app/pages/utils/system_operation_prerun.py @@ -107,37 +107,40 @@ def get_storage_t_dict(): return result ############# for links ##################### -def get_links_unique_cols(pypsa_network): - all_cols=pypsa_network.links_t["p0"].columns +def get_links_unique_cols(pypsa_network, pypsa_component, col_name): + #all_cols=pypsa_network.links_t["p0"].columns + all_cols=getattr(pypsa_network, pypsa_component)[col_name].columns split_cols= [] for k in all_cols: split_cols.append(k.split(" ")[-2]+" "+k.split(" ")[-1]) return list(set(split_cols)) -def get_links_df(pypsa_network,links_t_key): - links_t_df=pypsa_network.links_t[links_t_key] - unique_cols=get_links_unique_cols(pypsa_network) - resultant_df=pd.DataFrame(0,columns=unique_cols,index=links_t_df.index) +def get_links_df(pypsa_network, pypsa_component, component_key): + #links_t_df=pypsa_network.links_t[links_t_key] + pypsa_df = getattr(pypsa_network, pypsa_component)[component_key] + unique_cols=get_links_unique_cols(pypsa_network, pypsa_component, component_key) + resultant_df=pd.DataFrame(0,columns=unique_cols, index=pypsa_df.index) for carrier in unique_cols: - for links_carrier in links_t_df.columns: + for links_carrier in pypsa_df.columns: if carrier.split(" ")[-1] in links_carrier.split(" ") : - resultant_df[carrier]+=links_t_df[links_carrier] + resultant_df[carrier]+=pypsa_df[links_carrier] return resultant_df -non_empth_links_keys=[param for param in config["links_t_parameter"]] - +#non_empth_links_keys=[param for param in config["links_t_parameter"]] +#non_empth_loads_keys=[param for param in config["loads_t_parameter"]] +#non_empth_stores_keys=[param for param in config["stores_t_parameter"]] # @st.cache_resource -def get_links_t_dict(): +def get_links_t_dict(component_key, component_keys): result={} for network_key in pypsa_network_map.keys(): network_dict={} network = pypsa_network_map.get(network_key) - for non_empty_key in non_empth_links_keys: - network_dict[non_empty_key]=get_links_df(network,non_empty_key) + for non_empty_key in component_keys: + network_dict[non_empty_key]=get_links_df(network, component_key, non_empty_key) result[network_key]=network_dict return result \ No newline at end of file From 73bb1b0a4b34840b60ceeb3839c264d1d589f3bd Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 21:00:45 +0300 Subject: [PATCH 13/14] Fix drop --- app/pages/3_System_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pages/3_System_operation.py b/app/pages/3_System_operation.py index ec03f0d..db83cde 100644 --- a/app/pages/3_System_operation.py +++ b/app/pages/3_System_operation.py @@ -87,7 +87,7 @@ def gen_formatter(gen): # format_func=gen_formatter # ) -gen_df=country_data["p"].drop("Load", axis=1) +gen_df=country_data["p"].drop("Load", axis=1, errors="ignore") # with res_param_col: # choices = res_choices From 14475f9d639512589da4f918cfc2737b3c03c317 Mon Sep 17 00:00:00 2001 From: ekatef Date: Fri, 11 Aug 2023 21:02:10 +0300 Subject: [PATCH 14/14] Fix lines plotting --- app/pages/utils/spatial_pre_run.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/pages/utils/spatial_pre_run.py b/app/pages/utils/spatial_pre_run.py index 13ed3de..bfd4ef9 100644 --- a/app/pages/utils/spatial_pre_run.py +++ b/app/pages/utils/spatial_pre_run.py @@ -88,8 +88,9 @@ def _get_gen_df(network,gpd_bus_regions): def _make_plot_lines_df(pypsa_network): nLines=pypsa_network.lines.copy() nLines["total_capacity"] = nLines.s_nom_opt.clip(lower=1e-3) - nLines["reinforcement"] = nLines.s_nom.clip(lower=1e-3)- nLines.s_nom_opt.clip(lower=1e-3) + nLines["reinforcement"] = nLines.s_nom_opt.clip(lower=1e-3) - nLines.s_nom.clip(lower=1e-3) nLines["original_capacity"] = nLines.s_nom.clip(lower=1e-3) + # TODO What is the idea of using s_nom_min instead of s_nom_max? nLines["max_capacity"] = nLines.s_nom_min.clip(lower=1e-3) return nLines