rufimelo's picture
more graphs
2f26201
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
@callback(Output('page-content', 'children'), Input('url', 'pathname'))
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
@app.callback(
Output('policy_readable-graph', 'figure'),
Output('energy-consumption-graph', 'figure'),
Output('comfort-graph', 'figure'),
Output('dataset-graph', 'figure'),
Output('water-consumption-graph', 'figure'),
Output('water_consumption_hourly_graph', 'figure'),
Output('water_consumption_week_day_graph', 'figure'),
Output('water_consumption_monthly_graph', 'figure'),
Output('solution-status', 'children'),
Input('dataset-dropdown', 'value'),
Input('solution-dropdown', 'value'),
Input('ideal-temperature-slider', 'value')
)
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)