From b34667772e560a38d67ae0e74f548098c155d65e Mon Sep 17 00:00:00 2001 From: Camilo Ramirez Gomez Date: Fri, 20 Sep 2019 16:06:47 +0200 Subject: [PATCH 1/6] Fixed dataframe copy problem --- dashboard/app.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dashboard/app.py b/dashboard/app.py index 8f3b9ca..1eb9252 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -12,6 +12,7 @@ scenarios = ['BAU', 'Current Policies', 'SDG7'] my_path = os.path.abspath(os.path.dirname(__file__)) +#my_path = "C:\\Users\\camilorg\\Box Sync\\UNESCAP\\unescap_model\\dashboard" folder = os.path.join(my_path, 'Data') input_tfec = pd.read_excel(os.path.join(folder, 'TFEC.xlsx')) input_production = pd.read_excel(os.path.join(folder, 'Electricity_generation.xlsx')) @@ -216,7 +217,7 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): dff = df.loc[(df['y'] >= year_slider[0]) & (df['y'] <= year_slider[1])] dff = dff.groupby(['y', 'Scenario']).agg({variable: 'sum'}) dff = dff.reset_index() - dff[variable] *= units_dict[units] + dff.loc[:, variable] *= units_dict[units] data = [ dict( @@ -529,7 +530,7 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): dcc.Dropdown( id='tfec_scenario', options=[{'label': i, 'value': i} for i in scenarios], - value='BAU', + #value='BAU', ), html.P( 'Select the range of years to visualize:', @@ -910,7 +911,7 @@ def update_tfec(scenario, year_slider, filter, units): elif filter == 'sector': dff = df_tfec.loc[ (df_tfec['Scenario'] == scenario) & ((df_tfec['y'] >= year_slider[0]) & (df_tfec['y'] <= year_slider[1]))] - dff[tfec_variable] *= units_dict[units] + dff.loc[:, tfec_variable] *= units_dict[units] data = [ dict( @@ -928,7 +929,7 @@ def update_tfec(scenario, year_slider, filter, units): elif filter == 'fuel': dff = df_tfec.loc[ (df_tfec['Scenario'] == scenario) & ((df_tfec['y'] >= year_slider[0]) & (df_tfec['y'] <= year_slider[1]))] - dff[tfec_variable] *= units_dict[units] + dff.loc[:, tfec_variable] *= units_dict[units] data = [ dict( @@ -971,7 +972,7 @@ def update_supply(scenario, year_slider, visualization, type, units): else: dff = df_elec_demand.loc[ (df_elec_demand['Scenario'] == scenario) & ((df_elec_demand['y'] >= year_slider[0]) & (df_elec_demand['y'] <= year_slider[1]))] - dff[elec_demand_variable] *= units_dict[units] + dff.loc[:, elec_demand_variable] *= units_dict[units] data = [ dict( @@ -995,7 +996,7 @@ def update_supply(scenario, year_slider, visualization, type, units): else: dff = df_supply.loc[ (df_supply['Scenario'] == scenario) & ((df_supply['y'] >= year_slider[0]) & (df_supply['y'] <= year_slider[1]))] - dff[supply_variable] *= units_dict[units] + dff.loc[:, supply_variable] *= units_dict[units] data = [ dict( @@ -1091,7 +1092,7 @@ def el_access_graph(year_slider, units): layout_access = copy.deepcopy(layout) dff = df_elec_access.loc[(df_elec_access['Scenario'] == 'SDG7') & ((df_elec_access['y'] >= year_slider[0]) & (df_elec_access['y'] <= year_slider[1]))] - dff[elec_access_variable] *= units_dict[units] + dff.loc[:, elec_access_variable] *= units_dict[units] data = [ dict( @@ -1122,7 +1123,7 @@ def cooking_graph(year_slider, units): layout_cooking = copy.deepcopy(layout) dff = df_cooking.loc[(df_cooking['Scenario'] == 'SDG7') & ((df_cooking['y'] >= year_slider[0]) & (df_cooking['y'] <= year_slider[1]))] - dff[cooking_variable] *= units_dict[units] + dff.loc[:, cooking_variable] *= units_dict[units] data = [ dict( @@ -1154,7 +1155,7 @@ def efficiency_graph(year_slider, units): dff = df_efficiency.loc[ (df_efficiency['Scenario'] == 'SDG7') & ((df_efficiency['y'] >= year_slider[0]) & (df_efficiency['y'] <= year_slider[1]))] - dff[efficiency_variable] *= units_dict[units] + dff.loc[:, efficiency_variable] *= units_dict[units] data = [ dict( From 528f4ac8eecc32e86f424a7a4f54c28791d79a51 Mon Sep 17 00:00:00 2001 From: Camilo Ramirez Gomez Date: Fri, 20 Sep 2019 16:51:09 +0200 Subject: [PATCH 2/6] Changed default energy units for Mtoe --- dashboard/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dashboard/app.py b/dashboard/app.py index 1eb9252..c4ae795 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -410,7 +410,7 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): {'label': 'Mtoe', 'value': 'Mtoe'}, {'label': 'MMboe', 'value': 'MMboe'}, ], - value='PJ', + value='Mtoe', ), html.P( [ From d1d90c0a7462a9ef1e692cfcd02cc9060f92d75a Mon Sep 17 00:00:00 2001 From: Camilo Ramirez Gomez Date: Fri, 20 Sep 2019 17:33:57 +0200 Subject: [PATCH 3/6] Fixed warning regarding pairwise comparison --- dashboard/app.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/dashboard/app.py b/dashboard/app.py index c4ae795..ee38b56 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -530,7 +530,7 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): dcc.Dropdown( id='tfec_scenario', options=[{'label': i, 'value': i} for i in scenarios], - #value='BAU', + value='BAU' ), html.P( 'Select the range of years to visualize:', @@ -812,8 +812,23 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): ##### Callbacks ##### @app.callback( [ - Output('tfec_scenario', 'disabled'), + Output('tfec_scenario', 'options'), + ], + [ + Input('tfec_type', 'value'), + ], +) +def set_state(value): + if value == 'all': + options = [{'label': 'Select...', 'value': 'BAU'}] + else: + options = [{'label': i, 'value': i} for i in scenarios], + return options + +@app.callback( + [ Output('tfec_scenario', 'value'), + Output('tfec_scenario', 'disabled'), ], [ Input('tfec_type', 'value'), @@ -822,11 +837,11 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): def set_state(value): if value == 'all': state = True - scenario = None + scenario = scenarios[0] else: state = False scenario = scenarios[0] - return state, scenario + return scenario, state @app.callback( Output('electricity_type_drop', 'value'), From ec0f7cfea73789853a2d87c598af666eb5dd4c24 Mon Sep 17 00:00:00 2001 From: Camilo Ramirez Gomez Date: Mon, 23 Sep 2019 19:30:14 +0200 Subject: [PATCH 4/6] work on adding the feature of selecting demand by sector sowing use --- dashboard/app.py | 194 +++++++++++++++++++++++++++++++---------------- 1 file changed, 128 insertions(+), 66 deletions(-) diff --git a/dashboard/app.py b/dashboard/app.py index ee38b56..7909655 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -12,7 +12,6 @@ scenarios = ['BAU', 'Current Policies', 'SDG7'] my_path = os.path.abspath(os.path.dirname(__file__)) -#my_path = "C:\\Users\\camilorg\\Box Sync\\UNESCAP\\unescap_model\\dashboard" folder = os.path.join(my_path, 'Data') input_tfec = pd.read_excel(os.path.join(folder, 'TFEC.xlsx')) input_production = pd.read_excel(os.path.join(folder, 'Electricity_generation.xlsx')) @@ -265,7 +264,7 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): style={"margin-bottom": "0px"}, ), html.H5( - "OseMOSYS application", + "OSeMOSYS application", style={"margin-top": "0px"}, ), ], @@ -607,21 +606,35 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): value='el_demand' ), - html.P("Filter by:", className="control_label"), - dcc.Dropdown( - id='electricity_type_drop', - value='All' - ), - html.P( 'Select the scenario:', className="control_label", ), dcc.Dropdown( - id='scenario_supply', - options=[{'label': i, 'value': i} for i in scenarios], - value='BAU', + id='electricity_scenario', + options=[{'label': 'All', 'value': 'All'}]+[{'label': i, 'value': i} for i in scenarios], + value='All', + clearable=False ), + html.P("Filter by:", className="control_label"), + dcc.Dropdown( + id='electricity_type_drop', + options=[{'label': 'Select...', 'value': 'Select'}], + value='Select', + clearable=False + ), + html.Div( + [ + html.P("Select sector:", className="control_label"), + dcc.Dropdown( + id='electricity_sector', + value='All', + clearable=False, + ), + ], + id='electricity_sector_div', + ), + html.P( 'Select the range of years to visualize:', className="control_label", @@ -844,71 +857,104 @@ def set_state(value): return scenario, state @app.callback( - Output('electricity_type_drop', 'value'), + [ + Output('electricity_scenario', 'value'), + Output('electricity_scenario', 'disabled'), + Output('electricity_type_drop', 'value'), + ], [ Input('electricity_visualization_drop', 'value'), ], ) def update_elec_value(value): - if value == 'el_prod': - val = 'All' + if value == 'el_cost': + state = True else: - val = 'All' - return val + state = False + return 'All', state, 'Select' @app.callback( Output('electricity_type_drop', 'options'), [ Input('electricity_visualization_drop', 'value'), + Input('electricity_scenario', 'value'), ], ) -def update_elec_type(value): - if value == 'el_prod': - options = [ - {'label': 'All', 'value': 'All'}, - {'label': 'Source', 'value': 'Source'}, - {'label': 'Type', 'value': 'Use'}, - ] - elif value == 'el_demand': - options = [ - {'label': 'All', 'value': 'All'}, - {'label': 'Sector', 'value': 'Sector'}, - {'label': 'Use', 'value': 'Use'}, - ] - elif value == 'el_co2': +def update_elec_type(visualization, scenario): + if scenario == 'All': options = [ - {'label': 'All', 'value': 'All'}, {'label': 'Source', 'value': 'Source'}, + {'label': 'Sector', 'value': 'Sector'}, {'label': 'Type', 'value': 'Use'}, + {'label': 'Select...', 'value': 'Select', 'disabled': True}, ] - elif value == 'el_inv': - options = [ - {'label': 'All', 'value': 'All'}, - {'label': 'Source', 'value': 'Source'}, - ] - elif value == 'el_cost': - options = [ - {'label': 'All', 'value': 'All'}, - ] + else: + if visualization == 'el_prod': + options = [ + {'label': 'Source', 'value': 'Source'}, + {'label': 'Type', 'value': 'Use'}, + {'label': 'Select...', 'value': 'Select', 'disabled': True}, + ] + elif visualization == 'el_demand': + options = [ + {'label': 'Sector', 'value': 'Sector'}, + {'label': 'Use', 'value': 'Use'}, + {'label': 'Select...', 'value': 'Select', 'disabled': True}, + ] + elif visualization == 'el_co2': + options = [ + {'label': 'Source', 'value': 'Source'}, + {'label': 'Type', 'value': 'Use'}, + {'label': 'Select...', 'value': 'Select', 'disabled': True}, + ] + elif (visualization == 'el_inv') or (visualization == 'el_cost'): + options = [ + {'label': 'Select...', 'value': 'Select', 'disabled': True}, + ] return options @app.callback( + Output('electricity_type_drop', 'disabled'), [ - Output('scenario_supply', 'disabled'), - Output('scenario_supply', 'value'), + Input('electricity_scenario', 'value'), + Input('electricity_visualization_drop', 'value'), ], +) +def set_state(scenario, visualization): + if (scenario == 'All') or (visualization == 'el_inv') or (visualization == 'el_cost'): + state = True + else: + state = False + return state + +@app.callback( + Output('electricity_sector_div', 'style'), [ Input('electricity_type_drop', 'value'), ], ) def set_state(value): - if value == 'All': - state = True - scenario = None + if value == 'Use': + style = None else: - state = False - scenario = scenarios[0] - return state, scenario + style = {'display': 'none'} + return style + +@app.callback( + Output('electricity_sector', 'options'), + [ + Input('electricity_type_drop', 'value'), + Input('electricity_scenario', 'value'), + Input('year_slider_supply', 'value'), + ], +) +def set_state(value, scenario, year_slider): + dff = df_elec_demand.loc[ + (df_elec_demand['Scenario'] == scenario) & ( + (df_elec_demand['y'] >= year_slider[0]) & (df_elec_demand['y'] <= year_slider[1]))] + if value == 'Use': + options = [{'label': 'All', 'value': 'All'}] + [{'label': i, 'value': i} for i in dff['Sector'].unique()] + return options @app.callback( Output('tfec_graph', 'figure'), @@ -970,42 +1016,58 @@ def update_tfec(scenario, year_slider, filter, units): @app.callback( Output('supply_graph', 'figure'), [ - Input('scenario_supply', 'value'), + Input('electricity_scenario', 'value'), Input('year_slider_supply', 'value'), Input('electricity_visualization_drop', 'value'), Input('electricity_type_drop', 'value'), Input('electricity_units', 'value'), + Input('electricity_sector', 'value'), ], ) -def update_supply(scenario, year_slider, visualization, type, units): +def update_supply(scenario, year_slider, visualization, type, units, sector): layout_supply = copy.deepcopy(layout) if visualization == 'el_demand': - if type == 'All': + if scenario == 'All': data, layout_supply = get_general_graph(df_elec_demand, year_slider, elec_demand_variable, layout, "Electricity demand ({})".format(units), units) else: dff = df_elec_demand.loc[ (df_elec_demand['Scenario'] == scenario) & ((df_elec_demand['y'] >= year_slider[0]) & (df_elec_demand['y'] <= year_slider[1]))] dff.loc[:, elec_demand_variable] *= units_dict[units] + if (type == 'Use') & (sector != 'All'): + data = [ + dict( + type="bar", + x=dff.loc[(dff['Sector'] == sector) & (dff[type] == tech)].groupby('y').sum().index, + y=dff.loc[(dff['Sector'] == sector) & (dff[type] == tech)].groupby('y').sum()[elec_demand_variable], + name=tech, + hovertemplate=hover_template, + ) - data = [ - dict( - type="bar", - x=dff.loc[dff[type] == tech].groupby('y').sum().index, - y=dff.loc[dff[type] == tech].groupby('y').sum()[elec_demand_variable], - name=tech, - hovertemplate=hover_template, - ) + for tech in input_elec_demand[type].unique() + ] - for tech in input_elec_demand[type].unique() - ] + layout_supply["title"] = "Electricity demand in the {} sector ({})".format(sector, units) + layout_supply["barmode"] = 'stack' + else: + data = [ + dict( + type="bar", + x=dff.loc[dff[type] == tech].groupby('y').sum().index, + y=dff.loc[dff[type] == tech].groupby('y').sum()[elec_demand_variable], + name=tech, + hovertemplate=hover_template, + ) - layout_supply["title"] = "Electricity demand ({})".format(units) - layout_supply["barmode"] = 'stack' + for tech in input_elec_demand[type].unique() + ] + + layout_supply["title"] = "Electricity demand ({})".format(units) + layout_supply["barmode"] = 'stack' elif visualization == 'el_prod': - if type == 'All': + if scenario == 'All': data, layout_supply = get_general_graph(df_supply, year_slider, supply_variable, layout, "Electricity production ({})".format(units), units) else: @@ -1028,7 +1090,7 @@ def update_supply(scenario, year_slider, visualization, type, units): layout_supply["barmode"] = 'stack' elif visualization == 'el_co2': - if type == 'All': + if scenario == 'All': data, layout_supply = get_general_graph(df_emissions, year_slider, emissions_variable, layout, "Total CO2 Emissions (Mton)") @@ -1052,7 +1114,7 @@ def update_supply(scenario, year_slider, visualization, type, units): layout_supply["barmode"] = 'stack' elif visualization == 'el_inv': - if type == 'All': + if scenario == 'All': data, layout_supply = get_general_graph(df_investment, year_slider, investment_variable, layout, "Capital Investment (M$)") else: From 14f96143f68dae70da1faa0c81b5a79b4ae2326b Mon Sep 17 00:00:00 2001 From: Camilo Ramirez Gomez Date: Tue, 24 Sep 2019 11:03:55 +0200 Subject: [PATCH 5/6] Added option to filter each sector by use and fixed several backend bugs --- dashboard/app.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/dashboard/app.py b/dashboard/app.py index 7909655..4f8f285 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -410,6 +410,7 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): {'label': 'MMboe', 'value': 'MMboe'}, ], value='Mtoe', + clearable=False, ), html.P( [ @@ -435,6 +436,7 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): {'label': 'TWh', 'value': 'TWh'}, ], value='TWh', + clearable=False, ), ], className="container", @@ -529,7 +531,8 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): dcc.Dropdown( id='tfec_scenario', options=[{'label': i, 'value': i} for i in scenarios], - value='BAU' + value='BAU', + clearable = False, ), html.P( 'Select the range of years to visualize:', @@ -603,7 +606,8 @@ def get_general_graph(df, year_slider, variable, layout, title, units = None): {'label': 'Annual investment required', 'value': 'el_inv'}, {'label': 'Annual discounted cost', 'value': 'el_cost'}, ], - value='el_demand' + value='el_demand', + clearable = False, ), html.P( @@ -883,16 +887,13 @@ def update_elec_value(value): def update_elec_type(visualization, scenario): if scenario == 'All': options = [ - {'label': 'Source', 'value': 'Source'}, - {'label': 'Sector', 'value': 'Sector'}, - {'label': 'Type', 'value': 'Use'}, {'label': 'Select...', 'value': 'Select', 'disabled': True}, ] else: if visualization == 'el_prod': options = [ {'label': 'Source', 'value': 'Source'}, - {'label': 'Type', 'value': 'Use'}, + {'label': 'Type', 'value': 'Type'}, {'label': 'Select...', 'value': 'Select', 'disabled': True}, ] elif visualization == 'el_demand': @@ -904,7 +905,7 @@ def update_elec_type(visualization, scenario): elif visualization == 'el_co2': options = [ {'label': 'Source', 'value': 'Source'}, - {'label': 'Type', 'value': 'Use'}, + {'label': 'Type', 'value': 'Type'}, {'label': 'Select...', 'value': 'Select', 'disabled': True}, ] elif (visualization == 'el_inv') or (visualization == 'el_cost'): @@ -952,6 +953,8 @@ def set_state(value, scenario, year_slider): dff = df_elec_demand.loc[ (df_elec_demand['Scenario'] == scenario) & ( (df_elec_demand['y'] >= year_slider[0]) & (df_elec_demand['y'] <= year_slider[1]))] + # options = [{'label': 'Select...', 'value': 'Select'}] + options = '' if value == 'Use': options = [{'label': 'All', 'value': 'All'}] + [{'label': i, 'value': i} for i in dff['Sector'].unique()] return options @@ -1026,12 +1029,12 @@ def update_tfec(scenario, year_slider, filter, units): ) def update_supply(scenario, year_slider, visualization, type, units, sector): layout_supply = copy.deepcopy(layout) - + data = '' if visualization == 'el_demand': if scenario == 'All': data, layout_supply = get_general_graph(df_elec_demand, year_slider, elec_demand_variable, layout, "Electricity demand ({})".format(units), units) - else: + elif scenario != 'Select': dff = df_elec_demand.loc[ (df_elec_demand['Scenario'] == scenario) & ((df_elec_demand['y'] >= year_slider[0]) & (df_elec_demand['y'] <= year_slider[1]))] dff.loc[:, elec_demand_variable] *= units_dict[units] @@ -1050,7 +1053,7 @@ def update_supply(scenario, year_slider, visualization, type, units, sector): layout_supply["title"] = "Electricity demand in the {} sector ({})".format(sector, units) layout_supply["barmode"] = 'stack' - else: + elif (sector != 'Select') & (type != 'Select'): data = [ dict( type="bar", @@ -1070,7 +1073,7 @@ def update_supply(scenario, year_slider, visualization, type, units, sector): if scenario == 'All': data, layout_supply = get_general_graph(df_supply, year_slider, supply_variable, layout, "Electricity production ({})".format(units), units) - else: + elif (sector != 'Select') & (type != 'Select'): dff = df_supply.loc[ (df_supply['Scenario'] == scenario) & ((df_supply['y'] >= year_slider[0]) & (df_supply['y'] <= year_slider[1]))] dff.loc[:, supply_variable] *= units_dict[units] @@ -1094,7 +1097,7 @@ def update_supply(scenario, year_slider, visualization, type, units, sector): data, layout_supply = get_general_graph(df_emissions, year_slider, emissions_variable, layout, "Total CO2 Emissions (Mton)") - else: + elif (sector != 'Select') & (type != 'Select'): dff = df_emissions.loc[ (df_emissions['Scenario'] == scenario) & ( (df_emissions['y'] >= year_slider[0]) & (df_emissions['y'] <= year_slider[1]))] From 47a2205d900597bc8abb0c9a7fd8d4812b819128 Mon Sep 17 00:00:00 2001 From: Camilo Ramirez Gomez Date: Tue, 24 Sep 2019 13:05:41 +0200 Subject: [PATCH 6/6] solves legend outside opaque area in hovering --- dashboard/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dashboard/app.py b/dashboard/app.py index 4f8f285..72d5461 100644 --- a/dashboard/app.py +++ b/dashboard/app.py @@ -185,7 +185,7 @@ showlegend=True, ) -hover_template = '
Value: %{y:.2f}' + '
Year: %{x}' +hover_template = 'Value: %{y:.2f}' + '
Year: %{x}' units_dict = {'PJ': 1, 'Mtoe': 0.0238845897, 'MMboe': 0.163456, 'TWh': 0.277777778, None: 1}