Spaces:
Sleeping
Sleeping
import os | |
import plotly.express as px | |
import plotly.graph_objects as go | |
import pandas as pd | |
from dash import Dash, html, dcc, Input, Output, callback | |
import plotly.express as px | |
import numpy as np | |
import example_data | |
import core | |
from plotly.subplots import make_subplots | |
outside_temp = example_data.ExampleDailyOutsideTemperature | |
energy_price = example_data.ExampleDailyEnergyCost | |
boiler_temperature = example_data.ExampleBoilerTemperature | |
data = pd.DataFrame(columns=['hour', 'energy_consumption', 'comfort', 'policy_readable']) | |
data = pd.concat([data, pd.DataFrame({'hour': np.arange(0, 24), 'energy_consumption': energy_price.value, 'comfort': np.random.rand(24), | |
'policy_readable': np.random.choice(['A', 'B', 'C', 'D', 'E'], 24) | |
})]) | |
debug = False | |
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] | |
app = Dash(__name__, external_stylesheets=external_stylesheets) | |
app.layout = html.Div([ | |
dcc.Location(id='url', refresh=False), | |
html.Div(id='page-content') | |
]) | |
server = app.server | |
# Solution options | |
solution_options = [ | |
"Discrete Optimization", | |
"Continuous Optimization", | |
"Reinforcement Learning" | |
] | |
solution_options_default_value = solution_options[0] | |
# Datasets | |
dataset_options = [ | |
"16NSJNnjLK4MndjZYaKYGKEV", | |
"7uLwefnSt8CgVlmIGY8emqJK", | |
"8yS04Ddkk3pPL8e9Rku4LJtc", | |
"Cwp33jA19hp9VdoNJUlj6USf", | |
"iBFIAuvh7bCNyOQDo0jkjhRV", | |
"iNVKpGfGW6rU17eOtxpZSFWR", | |
"kaTMmHVh8gXUbHMppzdmdzpv", | |
"KN9Z3gANLftDuUGvgs8O38dI", | |
"LzbMafI31IosheUI7YGhj5at", | |
"PHqaZDuMTRvCZCvA259Z1vJu", | |
"RZngVU6axOdshmfma0yNAajE", | |
"SQUOjMB6zAgYpSJEMy46tKXJ", | |
] | |
dataset_options_default_value = dataset_options[0] | |
dataset_original_dfs = { | |
"16NSJNnjLK4MndjZYaKYGKEV": pd.read_csv('data/original/16NSJNnjLK4MndjZYaKYGKEV.csv'), | |
"7uLwefnSt8CgVlmIGY8emqJK": pd.read_csv('data/original/7uLwefnSt8CgVlmIGY8emqJK.csv'), | |
"8yS04Ddkk3pPL8e9Rku4LJtc": pd.read_csv('data/original/8yS04Ddkk3pPL8e9Rku4LJtc.csv'), | |
"Cwp33jA19hp9VdoNJUlj6USf": pd.read_csv('data/original/Cwp33jA19hp9VdoNJUlj6USf.csv'), | |
"iBFIAuvh7bCNyOQDo0jkjhRV": pd.read_csv('data/original/iBFIAuvh7bCNyOQDo0jkjhRV.csv'), | |
"iNVKpGfGW6rU17eOtxpZSFWR": pd.read_csv('data/original/iNVKpGfGW6rU17eOtxpZSFWR.csv'), | |
"kaTMmHVh8gXUbHMppzdmdzpv": pd.read_csv('data/original/kaTMmHVh8gXUbHMppzdmdzpv.csv'), | |
"KN9Z3gANLftDuUGvgs8O38dI": pd.read_csv('data/original/KN9Z3gANLftDuUGvgs8O38dI.csv'), | |
"LzbMafI31IosheUI7YGhj5at": pd.read_csv('data/original/LzbMafI31IosheUI7YGhj5at.csv'), | |
"PHqaZDuMTRvCZCvA259Z1vJu": pd.read_csv('data/original/PHqaZDuMTRvCZCvA259Z1vJu.csv'), | |
"RZngVU6axOdshmfma0yNAajE": pd.read_csv('data/original/RZngVU6axOdshmfma0yNAajE.csv'), | |
"SQUOjMB6zAgYpSJEMy46tKXJ": pd.read_csv('data/original/SQUOjMB6zAgYpSJEMy46tKXJ.csv'), | |
} | |
dataset_water_consumption_dfs = { | |
"16NSJNnjLK4MndjZYaKYGKEV": pd.read_csv('data/water_consumption/16NSJNnjLK4MndjZYaKYGKEV_water_consumption.csv'), | |
"7uLwefnSt8CgVlmIGY8emqJK": pd.read_csv('data/water_consumption/7uLwefnSt8CgVlmIGY8emqJK_water_consumption.csv'), | |
"8yS04Ddkk3pPL8e9Rku4LJtc": pd.read_csv('data/water_consumption/8yS04Ddkk3pPL8e9Rku4LJtc_water_consumption.csv'), | |
"Cwp33jA19hp9VdoNJUlj6USf": pd.read_csv('data/water_consumption/Cwp33jA19hp9VdoNJUlj6USf_water_consumption.csv'), | |
"iBFIAuvh7bCNyOQDo0jkjhRV": pd.read_csv('data/water_consumption/iBFIAuvh7bCNyOQDo0jkjhRV_water_consumption.csv'), | |
"iNVKpGfGW6rU17eOtxpZSFWR": pd.read_csv('data/water_consumption/iNVKpGfGW6rU17eOtxpZSFWR_water_consumption.csv'), | |
"kaTMmHVh8gXUbHMppzdmdzpv": pd.read_csv('data/water_consumption/kaTMmHVh8gXUbHMppzdmdzpv_water_consumption.csv'), | |
"KN9Z3gANLftDuUGvgs8O38dI": pd.read_csv('data/water_consumption/KN9Z3gANLftDuUGvgs8O38dI_water_consumption.csv'), | |
"LzbMafI31IosheUI7YGhj5at": pd.read_csv('data/water_consumption/LzbMafI31IosheUI7YGhj5at_water_consumption.csv'), | |
"PHqaZDuMTRvCZCvA259Z1vJu": pd.read_csv('data/water_consumption/PHqaZDuMTRvCZCvA259Z1vJu_water_consumption.csv'), | |
"RZngVU6axOdshmfma0yNAajE": pd.read_csv('data/water_consumption/RZngVU6axOdshmfma0yNAajE_water_consumption.csv'), | |
"SQUOjMB6zAgYpSJEMy46tKXJ": pd.read_csv('data/water_consumption/SQUOjMB6zAgYpSJEMy46tKXJ_water_consumption.csv'), | |
} | |
dataset_water_consumption_monthly_dfs = { | |
"16NSJNnjLK4MndjZYaKYGKEV": pd.read_csv('data/water_consumption/monthly/16NSJNnjLK4MndjZYaKYGKEV_month.csv'), | |
"7uLwefnSt8CgVlmIGY8emqJK": pd.read_csv('data/water_consumption/monthly/7uLwefnSt8CgVlmIGY8emqJK_month.csv'), | |
"8yS04Ddkk3pPL8e9Rku4LJtc": pd.read_csv('data/water_consumption/monthly/8yS04Ddkk3pPL8e9Rku4LJtc_month.csv'), | |
"Cwp33jA19hp9VdoNJUlj6USf": pd.read_csv('data/water_consumption/monthly/Cwp33jA19hp9VdoNJUlj6USf_month.csv'), | |
"iBFIAuvh7bCNyOQDo0jkjhRV": pd.read_csv('data/water_consumption/monthly/iBFIAuvh7bCNyOQDo0jkjhRV_month.csv'), | |
"iNVKpGfGW6rU17eOtxpZSFWR": pd.read_csv('data/water_consumption/monthly/iNVKpGfGW6rU17eOtxpZSFWR_month.csv'), | |
"kaTMmHVh8gXUbHMppzdmdzpv": pd.read_csv('data/water_consumption/monthly/kaTMmHVh8gXUbHMppzdmdzpv_month.csv'), | |
"KN9Z3gANLftDuUGvgs8O38dI": pd.read_csv('data/water_consumption/monthly/KN9Z3gANLftDuUGvgs8O38dI_month.csv'), | |
"LzbMafI31IosheUI7YGhj5at": pd.read_csv('data/water_consumption/monthly/LzbMafI31IosheUI7YGhj5at_month.csv'), | |
"PHqaZDuMTRvCZCvA259Z1vJu": pd.read_csv('data/water_consumption/monthly/PHqaZDuMTRvCZCvA259Z1vJu_month.csv'), | |
"RZngVU6axOdshmfma0yNAajE": pd.read_csv('data/water_consumption/monthly/RZngVU6axOdshmfma0yNAajE_month.csv'), | |
"SQUOjMB6zAgYpSJEMy46tKXJ": pd.read_csv('data/water_consumption/monthly/SQUOjMB6zAgYpSJEMy46tKXJ_month.csv'), | |
} | |
# provide a scalar value to enable the slider to select ideal temperature | |
ideal_temperature = 50 | |
dashboard_layout = html.Div([ | |
dcc.Link('About this project', href='/wiki'), | |
html.H1('System Evaluation'), | |
#small subtitle that says of solution is possible or not | |
html.Div(id='solution-status', children='', style={'color': 'lighrgrey'}), | |
html.Div([ | |
html.Div([ | |
html.H3('Dataset'), | |
dcc.Dropdown( | |
id='dataset-dropdown', | |
options=dataset_options, | |
value=dataset_options_default_value, | |
) | |
], className='three columns'), | |
html.Div([ | |
html.H3('Solution'), | |
dcc.Dropdown( | |
id='solution-dropdown', | |
options=solution_options, | |
value=solution_options_default_value, | |
) | |
], className='three columns'), | |
html.Div([ | |
html.H3('Ideal Shower Temperature'), | |
dcc.Slider( | |
id='ideal-temperature-slider', | |
min=0, | |
max=100, | |
step=1, | |
value=ideal_temperature, | |
marks={ | |
0: '0°C', | |
25: '25°C', | |
50: '50°C', | |
75: '75°C', | |
100: '100°C' | |
}, | |
) | |
], className='three columns'), | |
], className='row'), | |
html.Div( | |
[ | |
html.Div( | |
[ | |
html.H3('Dataset'), | |
dcc.Graph(id='dataset-graph') | |
], className='twelve columns', | |
) | |
], className='row'), | |
html.Div( | |
[ | |
html.Div( | |
[ | |
html.H3('Water Comsumption Patterns'), | |
dcc.Graph(id='water-consumption-graph') | |
], className='twelve columns', | |
) | |
], className='row'), | |
html.Div( | |
[ | |
html.Div( | |
[ | |
html.H4('Hourly'), | |
dcc.Graph(id='water_consumption_hourly_graph') | |
], className='six columns', | |
), | |
html.Div( | |
[ | |
html.H4('Day of the Week'), | |
dcc.Graph(id='water_consumption_week_day_graph') | |
], className='six columns', | |
) | |
], className='row'), | |
html.Div( | |
[ | |
html.Div( | |
[ | |
html.H4('Monthly'), | |
dcc.Graph(id='water_consumption_monthly_graph') | |
], className='six columns', | |
) | |
], className='row'), | |
html.Div( | |
[ | |
html.Div( | |
[ | |
html.H3('Policy'), | |
dcc.Graph(id='policy_readable-graph') | |
], className='six columns', | |
), | |
html.Div( | |
[ | |
html.H3('Energy Consumption'), | |
dcc.Graph(id='energy-consumption-graph') | |
], className='six columns' | |
), | |
] | |
), | |
html.Div( | |
[ | |
html.Div( | |
[ | |
html.H3('Comfort'), | |
dcc.Graph(id='comfort-graph') | |
], className='six columns' | |
) | |
], className='row'), | |
], | |
#add background image from local file and make it transparent | |
#, style={'background-image':'url(/assets/background_1.png)'} | |
style={'background-color': '#333', 'font-family': 'Fantasy', 'color': '#999', 'padding': '10px'} | |
) | |
wiki_layout = html.Div([ | |
dcc.Link('Dashboard', href='/'), | |
html.H1('About this project'), | |
html.Div([ | |
html.Div([ | |
html.H3('What is this project about?'), | |
html.P('This project is a simulation of a shower system. The goal is to find the best policy for the boiler to heat the water for the shower. The policy is a function that takes the current hour of the day and the current temperature of the water in the boiler and returns the temperature that the boiler should heat the water to.'), | |
html.P('The best policy is the one that maximizes the comfort of the shower and minimizes the energy consumption of the boiler.'), | |
html.H3('How does it work?'), | |
#Insert image of the system | |
html.H3('\'Bout us'), | |
html.Img(src='/assets/hackatos.png', style={'width': '40%', 'height': 'auto', 'display': 'block', 'margin-left': 'auto', 'margin-right': 'auto'}), | |
html.P('This project was developed by a team of 3, in the context of the Aveiro Tech City 2023 hackathon.'), | |
html.P('The team members are:'), | |
html.H4('Rui Melo'), | |
html.H4('André Catarino'), | |
html.H4('Francisco Petronilho'), | |
html.H4('André Tomás'), | |
html.H4('Zé Miguel'), | |
html.H3('References'), | |
html.P('The boiler model was based on the following paper:'), | |
], className='six columns'),], className='row'), | |
], | |
style={'background-color': '#333', 'font-family': 'Fantasy', 'color': '#999', 'padding': '10px'} | |
) | |
# Update the index | |
def display_page(pathname): | |
if pathname == '/': | |
return dashboard_layout | |
elif pathname == '/wiki': | |
return wiki_layout | |
else: | |
return '404' | |
# You could also return a 404 "URL not found" page here | |
def update_graph(dataset, solution, ideal_temperature): | |
energy_consumption = data['energy_consumption'].values | |
comfort_obtained = data['comfort'].values | |
# Original Dataset Graph | |
original_df = dataset_original_dfs[dataset] | |
dataset_graph = px.line() | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['ActPow'], mode='lines', name='ActPow') | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['HwActive'], mode='lines', name='HwActive') | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['ChActive'], mode='lines', name='ChActive') | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['HwTSet'], mode='lines', name='HwTSet') | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['DHW_E21_T3_START_TEMP'], mode='lines', name='START_TEMP') | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['HwTStor'], mode='lines', name='HwTStor') | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['HwTAct'], mode='lines', name='HwTAct') | |
dataset_graph.add_scatter(x=original_df['ts'], y=original_df['OutTemp'], mode='lines', name='OutTemp') | |
start_time = pd.Timestamp(original_df['ts'][0]) | |
dataset_graph.update_xaxes(range=[start_time, start_time+pd.Timedelta(days=2)]) | |
# Water Consumption Graph | |
water_consumption_df = dataset_water_consumption_dfs[dataset] | |
if len(water_consumption_df) / 24 > 365: | |
water_consumption_df = water_consumption_df.head(365* 24) | |
water_consumption_df.index = pd.to_datetime(water_consumption_df["ts"], errors='coerce') | |
water_consumption_graph = go.Figure() | |
water_consumption_graph = make_subplots(specs=[[{"secondary_y": True}]]) | |
water_consumption_graph.add_trace(go.Scatter(x=water_consumption_df[:]["ts"], y=water_consumption_df[:]['water_consumption_bool'], mode='lines', name='Water consumption'), | |
secondary_y=False,) | |
water_consumption_graph.add_trace(go.Scatter(x=water_consumption_df[:]["ts"], y=water_consumption_df[:]['HwTStor'], mode='lines', name='Water temperature') | |
,secondary_y=True,) | |
water_consumption_graph.update_layout( | |
title_text="Water consumption" | |
) | |
water_consumption_graph.update_xaxes(title_text="time") | |
water_consumption_graph.update_yaxes(title_text="water consumption", secondary_y=False) | |
water_consumption_graph.update_yaxes(title_text="water temperature", secondary_y=True) | |
# Water Consumption Hourly Graph | |
water_consumption_df["ts_hour"] = water_consumption_df["ts"].apply(lambda x: x.split(" ")[1].split(":")[0]) | |
hour_series = water_consumption_df.groupby("ts_hour")["water_consumption_bool"].sum() | |
water_consumption_hourly_graph = go.Figure() | |
water_consumption_hourly_graph.add_trace(go.Bar(x=hour_series.index, y=hour_series.values, name='Water consumption per hour')) | |
water_consumption_hourly_graph.update_layout( | |
title_text="Water consumption per hour" | |
) | |
water_consumption_hourly_graph.update_xaxes(title_text="Hour of day") | |
water_consumption_hourly_graph.update_yaxes(title_text="Number of water usages") | |
# Water Consumption Week Day Graph | |
order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] | |
water_consumption_df["datetime"] = pd.to_datetime(water_consumption_df["ts"], errors='coerce') | |
#create columns with day of week | |
water_consumption_df['day_of_week'] = water_consumption_df["datetime"].apply(lambda x: x.day_name()) | |
#turn day of week number into day of week name | |
#df['day_of_week'] = df['day_of_week'].apply(lambda x: calendar.day_name[x]) | |
week_series = water_consumption_df.groupby("day_of_week")["water_consumption_bool"].sum().loc[order] | |
# Water Consumption Week Day Graph | |
water_consumption_week_day_graph = go.Figure() | |
water_consumption_week_day_graph.add_trace(go.Bar(x=week_series.index, y=week_series.values, name='Water consumption per day of week')) | |
water_consumption_week_day_graph.update_layout( | |
title_text="Water consumption per day of week" | |
) | |
water_consumption_week_day_graph.update_xaxes(title_text="Day of week") | |
water_consumption_week_day_graph.update_yaxes(title_text="Number of water usages") | |
#dataset_water_consumption_monthly_dfs | |
#Water Consumption Monthly Graph | |
water_consumption_monthly_df = dataset_water_consumption_monthly_dfs[dataset] | |
water_consumption_monthly_graph = go.Figure() | |
water_consumption_monthly_graph.add_trace(go.Bar(x=water_consumption_monthly_df["month"], y=water_consumption_monthly_df["water_consumption_bool"], name='Water consumption per month')) | |
water_consumption_monthly_graph.update_layout( | |
title_text="Water consumption per month" | |
) | |
water_consumption_monthly_graph.update_xaxes(title_text="Month") | |
water_consumption_monthly_graph.update_yaxes(title_text="Number of water usages") | |
# Policy Graph | |
policy_readable_graph = px.line(data, x='hour', y='policy_readable', | |
labels={'hour': 'Hour', 'policy_readable': 'Policy'}, | |
color_discrete_sequence=['lightgreen']) | |
policy_readable_graph.update_layout( | |
xaxis_title="Hour", | |
yaxis_title="Temperature (°C)", | |
legend_title="Policy" | |
) | |
# Energy Consumption Graph | |
energy_consumption_graph = px.line(data, x='hour', | |
y='energy_consumption', | |
labels={'hour': 'Hour', 'energy_consumption': 'Energy Consumption (kWh)'}, | |
color_discrete_sequence=['lightgreen']) | |
energy_consumption_graph.update_layout( | |
xaxis_title="Hour", | |
yaxis_title="Energy Consumption (kWh)", | |
legend_title="Energy Consumption", | |
) | |
#add accumulated energy consumption | |
energy_consumption = np.cumsum(energy_consumption) | |
energy_consumption_graph.add_trace(px.line(data, x='hour', | |
y=energy_consumption, | |
labels={'y': 'Acc. Energy Consumption (kWh)'}, | |
color_discrete_sequence=['green']).data[0]) | |
# Comfort Graph | |
comfort_graph = px.line(data, x='hour', y='comfort', | |
labels={'hour': 'Hour', 'comfort': 'comfort Score'}, | |
color_discrete_sequence=['lightgreen']) | |
comfort_graph.update_layout( | |
xaxis_title="Hour", | |
yaxis_title="comfort Score", | |
legend_title="comfort" | |
) | |
#add accumulated comfort | |
comfort_obtained = np.cumsum(comfort_obtained) | |
comfort_graph.add_trace(px.line(data, x='hour', y=comfort_obtained, | |
labels={'y': 'Acc. comfort Score'}, | |
color_discrete_sequence=['green'] | |
).data[0]) | |
result = "No solution found" | |
return policy_readable_graph, energy_consumption_graph, comfort_graph, dataset_graph, water_consumption_graph, water_consumption_hourly_graph, water_consumption_week_day_graph,water_consumption_monthly_graph, result | |
if __name__ == "__main__": | |
app.run_server(host="0.0.0.0", port="8050", debug=debug) |