Spaces:
Sleeping
Sleeping
yolo
Browse files- .DS_Store +0 -0
- Dockerfile +24 -0
- Dockerfile.dev +9 -0
- LICENSE +21 -0
- README.md +45 -6
- app/.DS_Store +0 -0
- app/__pycache__/core.cpython-310.pyc +0 -0
- app/__pycache__/example_data.cpython-310.pyc +0 -0
- app/app.py +96 -0
- app/assets/.DS_Store +0 -0
- app/assets/tourdevino_logo.webp +0 -0
- app/core.py +99 -0
- app/dashboard.ipynb +167 -0
- app/data/.DS_Store +0 -0
- app/requirements.txt +6 -0
- dashboard.py +125 -0
.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10
|
2 |
+
# Set up a new user named "user" with user ID 1000
|
3 |
+
RUN useradd -m -u 1000 user
|
4 |
+
|
5 |
+
# Switch to the "user" user
|
6 |
+
USER user
|
7 |
+
# Set home to the user's home directory
|
8 |
+
ENV HOME=/home/user \
|
9 |
+
PATH=/home/user/.local/bin:$PATH
|
10 |
+
|
11 |
+
# Set the working directory to the user's home directory
|
12 |
+
WORKDIR $HOME/app
|
13 |
+
|
14 |
+
# Copy the current directory contents into the container at $HOME/app setting the owner to the user
|
15 |
+
COPY --chown=user ./app $HOME/app
|
16 |
+
|
17 |
+
|
18 |
+
ENV DASH_DEBUG_MODE False
|
19 |
+
#COPY ./app /app
|
20 |
+
#WORKDIR /app
|
21 |
+
RUN set -ex && \
|
22 |
+
pip install -r requirements.txt
|
23 |
+
EXPOSE 8050
|
24 |
+
CMD ["gunicorn", "-b", "0.0.0.0:8050", "--reload", "app:server"]
|
Dockerfile.dev
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10
|
2 |
+
|
3 |
+
ENV DASH_DEBUG_MODE True
|
4 |
+
COPY ./app /app
|
5 |
+
WORKDIR /app
|
6 |
+
RUN set -ex && \
|
7 |
+
pip install -r requirements.txt
|
8 |
+
EXPOSE 8050
|
9 |
+
CMD ["python", "app.py"]
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2019 Jucy Technologies, Inc.
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
README.md
CHANGED
@@ -1,11 +1,50 @@
|
|
1 |
---
|
2 |
-
title: Showcase
|
3 |
emoji: 📈
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: docker
|
7 |
-
|
8 |
-
license: mit
|
9 |
---
|
|
|
10 |
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
title: Tour de Vino Showcase
|
3 |
emoji: 📈
|
4 |
+
colorFrom: purple
|
5 |
+
colorTo: gray
|
6 |
sdk: docker
|
7 |
+
app_port: 8050
|
|
|
8 |
---
|
9 |
+
# Docker Dash (Plotly)
|
10 |
|
11 |
+
Dockerize a Python Dash app for quick prototyping.
|
12 |
+
|
13 |
+
## Build and run
|
14 |
+
|
15 |
+
`prod` version is served by `gunicorn` instead of the `flask` dev server.
|
16 |
+
|
17 |
+
```sh
|
18 |
+
# dev
|
19 |
+
docker build -f Dockerfile.dev -t docker-dash-example-dev .
|
20 |
+
docker run -p 8050:8050 -v "$(pwd)"/app:/app --rm docker-dash-example-dev
|
21 |
+
|
22 |
+
# prod
|
23 |
+
docker build -f Dockerfile -t docker-dash-example-prod .
|
24 |
+
docker run -p 8050:8050 -v "$(pwd)"/app:/app --rm docker-dash-example-prod
|
25 |
+
```
|
26 |
+
|
27 |
+
## Access the page
|
28 |
+
|
29 |
+
Go to `http://localhost:8050` in browser.
|
30 |
+
|
31 |
+
## Switch debug mode in Dockerfile
|
32 |
+
|
33 |
+
```dockerfile
|
34 |
+
ENV DASH_DEBUG_MODE True # False
|
35 |
+
```
|
36 |
+
|
37 |
+
## Development
|
38 |
+
|
39 |
+
Install the app requirements for development to get better editor support.
|
40 |
+
|
41 |
+
```sh
|
42 |
+
poetry install
|
43 |
+
```
|
44 |
+
|
45 |
+
Optional: clean initialization of `poetry`:
|
46 |
+
|
47 |
+
```sh
|
48 |
+
poetry init
|
49 |
+
cat app/requirements.txt | xargs poetry add
|
50 |
+
```
|
app/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
app/__pycache__/core.cpython-310.pyc
ADDED
Binary file (1.77 kB). View file
|
|
app/__pycache__/example_data.cpython-310.pyc
ADDED
Binary file (2.4 kB). View file
|
|
app/app.py
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import plotly.express as px
|
3 |
+
import plotly.graph_objects as go
|
4 |
+
import pandas as pd
|
5 |
+
from dash import Dash, html, dcc, Input, Output, callback
|
6 |
+
import plotly.express as px
|
7 |
+
import numpy as np
|
8 |
+
from plotly.subplots import make_subplots
|
9 |
+
|
10 |
+
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder_unfiltered.csv')
|
11 |
+
|
12 |
+
debug = False
|
13 |
+
|
14 |
+
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
|
15 |
+
|
16 |
+
app = Dash(__name__, external_stylesheets=external_stylesheets)
|
17 |
+
|
18 |
+
app.layout = html.Div([
|
19 |
+
dcc.Location(id='url', refresh=False),
|
20 |
+
html.Div(id='page-content')
|
21 |
+
])
|
22 |
+
|
23 |
+
server = app.server
|
24 |
+
|
25 |
+
|
26 |
+
dashboard_layout = html.Div([
|
27 |
+
dcc.Link('About this project', href='/wiki'),
|
28 |
+
|
29 |
+
html.H1(children='Title of Dash App', style={'textAlign':'center'}),
|
30 |
+
dcc.Dropdown(df.country.unique(), 'Canada', id='dropdown-selection'),
|
31 |
+
dcc.Graph(id='graph-content')
|
32 |
+
|
33 |
+
])
|
34 |
+
|
35 |
+
|
36 |
+
|
37 |
+
wiki_layout = html.Div([
|
38 |
+
dcc.Link('Dashboard', href='/'),
|
39 |
+
|
40 |
+
html.H1('About this project'),
|
41 |
+
|
42 |
+
html.Div([
|
43 |
+
html.Div([
|
44 |
+
|
45 |
+
html.H3('What is this project about?'),
|
46 |
+
|
47 |
+
html.P('something'),
|
48 |
+
|
49 |
+
html.H3('How does it work?'),
|
50 |
+
|
51 |
+
#Insert image of the system
|
52 |
+
|
53 |
+
html.H3('\'Bout us'),
|
54 |
+
html.Img(src='/assets/tourdevino_logo.webp', style={'width': '40%', 'height': 'auto', 'display': 'block', 'margin-left': 'auto', 'margin-right': 'auto'}),
|
55 |
+
html.P('This project was developed by a team of 4, in the context of the SOGRAPE 2024 hackathon.'),
|
56 |
+
html.P('The team members are:'),
|
57 |
+
html.H4('Rui Melo'),
|
58 |
+
html.H4('André Catarino'),
|
59 |
+
html.H4('Dinis Costa'),
|
60 |
+
html.H4('Paulo Fidalgo'),
|
61 |
+
|
62 |
+
|
63 |
+
|
64 |
+
html.H3('References'),
|
65 |
+
html.P('The boiler model was based on the following paper:'),
|
66 |
+
|
67 |
+
|
68 |
+
], className='six columns'),], className='row'),
|
69 |
+
],
|
70 |
+
style={'background-color': '#333', 'font-family': 'Fantasy', 'color': '#999', 'padding': '10px'}
|
71 |
+
|
72 |
+
)
|
73 |
+
|
74 |
+
# Update the index
|
75 |
+
@callback(Output('page-content', 'children'), Input('url', 'pathname'))
|
76 |
+
def display_page(pathname):
|
77 |
+
if pathname == '/':
|
78 |
+
return dashboard_layout
|
79 |
+
elif pathname == '/wiki':
|
80 |
+
return wiki_layout
|
81 |
+
else:
|
82 |
+
return '404'
|
83 |
+
# You could also return a 404 "URL not found" page here
|
84 |
+
|
85 |
+
|
86 |
+
@app.callback(
|
87 |
+
Output('graph-content', 'figure'),
|
88 |
+
Input('dropdown-selection', 'value')
|
89 |
+
)
|
90 |
+
def update_graph(value):
|
91 |
+
dff = df[df.country==value]
|
92 |
+
return px.line(dff, x='year', y='pop')
|
93 |
+
|
94 |
+
|
95 |
+
if __name__ == "__main__":
|
96 |
+
app.run_server(host="0.0.0.0", port="8050", debug=debug)
|
app/assets/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
app/assets/tourdevino_logo.webp
ADDED
![]() |
app/core.py
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Electric cost(Euros) = energy_price(Euros/kWh) * wasted_energy(kWh)
|
2 |
+
def custo(energy_price_hour, wasted_energy):
|
3 |
+
return energy_price_hour * wasted_energy
|
4 |
+
|
5 |
+
|
6 |
+
# caldeira 20 litros
|
7 |
+
def spent_energy(
|
8 |
+
temperatura_inicial_caldeira_t, # existente na cadeira, t sendo a hora
|
9 |
+
temperatura_objetivo_caldeira_t_plus_1,
|
10 |
+
outside_temp,
|
11 |
+
pressao_caldeira,
|
12 |
+
litros_gastos_no_banho=0,
|
13 |
+
temperatura_entrada_agua_na_caldeira=15, # Temperatura ambiente da iNOVA
|
14 |
+
capacidade_caldeira=20, # 20 litros
|
15 |
+
):
|
16 |
+
# E = (4.2 kJ/kgoC) ((90 oC) - (20 oC)) (1000 liter) (1 kg/liter)
|
17 |
+
# cp = specific heat of water (kJ/kgoC, Btu/lb oF) (4.2 kJ/kgoC, 1 Btu/lbmoF for water)
|
18 |
+
heat_capacity = 4.2
|
19 |
+
# Energy = heat_capacity * (temperatura_saida_agua_na_caldeira - outside_temp) * capacidade_caldeira * 1\
|
20 |
+
delta_t = temperatura_objetivo_caldeira_t_plus_1 - temperatura_inicial_caldeira_t
|
21 |
+
|
22 |
+
energy = (
|
23 |
+
heat_capacity
|
24 |
+
* (delta_t - outside_temp)
|
25 |
+
* (capacidade_caldeira - litros_gastos_no_banho)
|
26 |
+
* 1
|
27 |
+
) # isto vai ser minimo
|
28 |
+
|
29 |
+
delta_t = (
|
30 |
+
temperatura_objetivo_caldeira_t_plus_1 - temperatura_entrada_agua_na_caldeira
|
31 |
+
)
|
32 |
+
energy_incoming_water = (
|
33 |
+
heat_capacity * (delta_t - outside_temp) * litros_gastos_no_banho * 1
|
34 |
+
)
|
35 |
+
|
36 |
+
# 20 Litros totais
|
37 |
+
# Joao gatou 5 litros
|
38 |
+
# Gastar energia em:
|
39 |
+
# 15 litros para manter a temperatura da caldeira -> minimo
|
40 |
+
# 5 litros para aquecer a agua que entra
|
41 |
+
|
42 |
+
total_energy = energy + energy_incoming_water
|
43 |
+
|
44 |
+
# TODO: Correlação entre pressão e temperatura
|
45 |
+
# https://www.engineeringtoolbox.com/boiling-points-water-altitude-d_1344.html
|
46 |
+
# https://www.engineeringtoolbox.com/boiling-point-water-d_926.html
|
47 |
+
"""
|
48 |
+
That depends on whether the pressure is held constant during the heating. If there is a relief valve which maintains
|
49 |
+
constant pressure as the water heats, then no, the 2 samples will heat at the same rate. However, if the pressurised sample
|
50 |
+
has no pressure relief, then it will heat faster because the pressure will increase, and that increase in pressure will increase
|
51 |
+
the heat in addition to the heat applied.
|
52 |
+
"""
|
53 |
+
# kJ
|
54 |
+
|
55 |
+
# TODO: FIND WHAT SHOULD BE THE RELATION BETWEEN TEMPERATURE OF OUTGOING WATER AND BOILER TEMPERATURE
|
56 |
+
temperatura_saida_agua_na_caldeira = temperatura_objetivo_caldeira_t_plus_1 * 0.87
|
57 |
+
|
58 |
+
return total_energy, temperatura_saida_agua_na_caldeira
|
59 |
+
|
60 |
+
|
61 |
+
def calculate_weights_for_all_hours(
|
62 |
+
temperatura_inicial_caldeira,
|
63 |
+
temperatura_objetivo_caldeira,
|
64 |
+
outside_temp,
|
65 |
+
pressao_caldeira,
|
66 |
+
litros_gastos_no_banho,
|
67 |
+
temperatura_entrada_agua_na_caldeira,
|
68 |
+
capacidade_caldeira,
|
69 |
+
):
|
70 |
+
weights = []
|
71 |
+
temperatures = []
|
72 |
+
for i in range(len(temperatura_inicial_caldeira)):
|
73 |
+
energy, temperature_water = spent_energy(
|
74 |
+
temperatura_inicial_caldeira_t=temperatura_inicial_caldeira[i],
|
75 |
+
temperatura_objetivo_caldeira_t_plus_1=temperatura_objetivo_caldeira,
|
76 |
+
outside_temp=outside_temp[i],
|
77 |
+
pressao_caldeira=pressao_caldeira[i],
|
78 |
+
litros_gastos_no_banho=litros_gastos_no_banho,
|
79 |
+
temperatura_entrada_agua_na_caldeira=temperatura_entrada_agua_na_caldeira[
|
80 |
+
i
|
81 |
+
],
|
82 |
+
capacidade_caldeira=capacidade_caldeira,
|
83 |
+
)
|
84 |
+
weights.append(energy)
|
85 |
+
temperatures.append(temperature_water)
|
86 |
+
return weights, temperatures
|
87 |
+
# Output energy wasted
|
88 |
+
|
89 |
+
|
90 |
+
def calculate_confort(temperatura_given, temperatura_ideal):
|
91 |
+
return abs(temperatura_given - temperatura_ideal)
|
92 |
+
|
93 |
+
|
94 |
+
# create exception for no solution found
|
95 |
+
class NoSolutionFound(Exception):
|
96 |
+
pass
|
97 |
+
|
98 |
+
class SoltionFoundWithLargerConfortValue(Exception):
|
99 |
+
pass
|
app/dashboard.ipynb
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 27,
|
6 |
+
"metadata": {},
|
7 |
+
"outputs": [
|
8 |
+
{
|
9 |
+
"data": {
|
10 |
+
"text/html": [
|
11 |
+
"\n",
|
12 |
+
" <iframe\n",
|
13 |
+
" width=\"100%\"\n",
|
14 |
+
" height=\"650\"\n",
|
15 |
+
" src=\"http://0.0.0.0:8050/\"\n",
|
16 |
+
" frameborder=\"0\"\n",
|
17 |
+
" allowfullscreen\n",
|
18 |
+
" \n",
|
19 |
+
" ></iframe>\n",
|
20 |
+
" "
|
21 |
+
],
|
22 |
+
"text/plain": [
|
23 |
+
"<IPython.lib.display.IFrame at 0x2a29674c0>"
|
24 |
+
]
|
25 |
+
},
|
26 |
+
"metadata": {},
|
27 |
+
"output_type": "display_data"
|
28 |
+
}
|
29 |
+
],
|
30 |
+
"source": [
|
31 |
+
"import os\n",
|
32 |
+
"import plotly.express as px\n",
|
33 |
+
"import plotly.graph_objects as go\n",
|
34 |
+
"import pandas as pd\n",
|
35 |
+
"from dash import Dash, html, dcc, Input, Output, callback\n",
|
36 |
+
"import plotly.express as px\n",
|
37 |
+
"import numpy as np\n",
|
38 |
+
"from plotly.subplots import make_subplots\n",
|
39 |
+
"\n",
|
40 |
+
"df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder_unfiltered.csv')\n",
|
41 |
+
"\n",
|
42 |
+
"debug = False\n",
|
43 |
+
"\n",
|
44 |
+
"external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']\n",
|
45 |
+
"\n",
|
46 |
+
"app = Dash(__name__, external_stylesheets=external_stylesheets)\n",
|
47 |
+
"\n",
|
48 |
+
"app.layout = html.Div([\n",
|
49 |
+
" dcc.Location(id='url', refresh=False),\n",
|
50 |
+
" html.Div(id='page-content')\n",
|
51 |
+
"])\n",
|
52 |
+
"\n",
|
53 |
+
"server = app.server\n",
|
54 |
+
"\n",
|
55 |
+
"\n",
|
56 |
+
"dashboard_layout = html.Div([\n",
|
57 |
+
" dcc.Link('About this project', href='/wiki'),\n",
|
58 |
+
"\n",
|
59 |
+
" html.H1(children='Title of Dash App', style={'textAlign':'center'}),\n",
|
60 |
+
" dcc.Dropdown(df.country.unique(), 'Canada', id='dropdown-selection'),\n",
|
61 |
+
" dcc.Graph(id='graph-content')\n",
|
62 |
+
"\n",
|
63 |
+
"])\n",
|
64 |
+
"\n",
|
65 |
+
"\n",
|
66 |
+
"\n",
|
67 |
+
"wiki_layout = html.Div([\n",
|
68 |
+
" dcc.Link('Dashboard', href='/'),\n",
|
69 |
+
"\n",
|
70 |
+
" html.H1('About this project'),\n",
|
71 |
+
"\n",
|
72 |
+
" html.Div([\n",
|
73 |
+
" html.Div([\n",
|
74 |
+
"\n",
|
75 |
+
" html.H3('What is this project about?'),\n",
|
76 |
+
"\n",
|
77 |
+
" 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.'),\n",
|
78 |
+
" html.P('The best policy is the one that maximizes the comfort of the shower and minimizes the energy consumption of the boiler.'),\n",
|
79 |
+
"\n",
|
80 |
+
" html.H3('How does it work?'),\n",
|
81 |
+
"\n",
|
82 |
+
" #Insert image of the system\n",
|
83 |
+
"\n",
|
84 |
+
" html.H3('\\'Bout us'),\n",
|
85 |
+
" html.Img(src='/assets/tourdevino_logo.webp', style={'width': '40%', 'height': 'auto', 'display': 'block', 'margin-left': 'auto', 'margin-right': 'auto'}),\n",
|
86 |
+
" html.P('This project was developed by a team of 3, in the context of the Aveiro Tech City 2023 hackathon.'),\n",
|
87 |
+
" html.P('The team members are:'),\n",
|
88 |
+
" html.H4('Rui Melo'),\n",
|
89 |
+
" html.H4('André Catarino'),\n",
|
90 |
+
" html.H4('Dinis Costa'),\n",
|
91 |
+
" html.H4('Paulo Fidalgo'),\n",
|
92 |
+
" \n",
|
93 |
+
"\n",
|
94 |
+
"\n",
|
95 |
+
" html.H3('References'),\n",
|
96 |
+
" html.P('The boiler model was based on the following paper:'),\n",
|
97 |
+
"\n",
|
98 |
+
"\n",
|
99 |
+
" ], className='six columns'),], className='row'),\n",
|
100 |
+
"],\n",
|
101 |
+
"style={'background-color': '#333', 'font-family': 'Fantasy', 'color': '#999', 'padding': '10px'}\n",
|
102 |
+
"\n",
|
103 |
+
")\n",
|
104 |
+
"\n",
|
105 |
+
"# Update the index\n",
|
106 |
+
"@callback(Output('page-content', 'children'), Input('url', 'pathname'))\n",
|
107 |
+
"def display_page(pathname):\n",
|
108 |
+
" if pathname == '/':\n",
|
109 |
+
" return dashboard_layout\n",
|
110 |
+
" elif pathname == '/wiki':\n",
|
111 |
+
" return wiki_layout\n",
|
112 |
+
" else:\n",
|
113 |
+
" return '404'\n",
|
114 |
+
" # You could also return a 404 \"URL not found\" page here\n",
|
115 |
+
"\n",
|
116 |
+
"\n",
|
117 |
+
"@app.callback(\n",
|
118 |
+
" Output('graph-content', 'figure'),\n",
|
119 |
+
" Input('dropdown-selection', 'value')\n",
|
120 |
+
")\n",
|
121 |
+
"def update_graph(value):\n",
|
122 |
+
" dff = df[df.country==value]\n",
|
123 |
+
" return px.line(dff, x='year', y='pop')\n",
|
124 |
+
"\n",
|
125 |
+
"\n",
|
126 |
+
"if __name__ == \"__main__\":\n",
|
127 |
+
" app.run_server(host=\"0.0.0.0\", port=\"8050\", debug=debug)"
|
128 |
+
]
|
129 |
+
},
|
130 |
+
{
|
131 |
+
"cell_type": "code",
|
132 |
+
"execution_count": null,
|
133 |
+
"metadata": {},
|
134 |
+
"outputs": [],
|
135 |
+
"source": []
|
136 |
+
},
|
137 |
+
{
|
138 |
+
"cell_type": "code",
|
139 |
+
"execution_count": null,
|
140 |
+
"metadata": {},
|
141 |
+
"outputs": [],
|
142 |
+
"source": []
|
143 |
+
}
|
144 |
+
],
|
145 |
+
"metadata": {
|
146 |
+
"kernelspec": {
|
147 |
+
"display_name": "atc-smart-shower-YhjpRjjr-py3.10",
|
148 |
+
"language": "python",
|
149 |
+
"name": "python3"
|
150 |
+
},
|
151 |
+
"language_info": {
|
152 |
+
"codemirror_mode": {
|
153 |
+
"name": "ipython",
|
154 |
+
"version": 3
|
155 |
+
},
|
156 |
+
"file_extension": ".py",
|
157 |
+
"mimetype": "text/x-python",
|
158 |
+
"name": "python",
|
159 |
+
"nbconvert_exporter": "python",
|
160 |
+
"pygments_lexer": "ipython3",
|
161 |
+
"version": "3.10.14"
|
162 |
+
},
|
163 |
+
"orig_nbformat": 4
|
164 |
+
},
|
165 |
+
"nbformat": 4,
|
166 |
+
"nbformat_minor": 2
|
167 |
+
}
|
app/data/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
app/requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
dash
|
2 |
+
plotly
|
3 |
+
pandas
|
4 |
+
gunicorn
|
5 |
+
wandb==0.15.5
|
6 |
+
scipy
|
dashboard.py
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
|
3 |
+
data = pd.DataFrame(columns=["Dataset", "Alpha", "Top K", "Recall", "Precision"])
|
4 |
+
data = pd.concat(
|
5 |
+
[
|
6 |
+
data,
|
7 |
+
pd.DataFrame(
|
8 |
+
[["ml-100k", 0.1, 20, 0.2, 0.2]],
|
9 |
+
columns=["Dataset", "Alpha", "Top K", "Recall", "Precision"],
|
10 |
+
),
|
11 |
+
]
|
12 |
+
)
|
13 |
+
|
14 |
+
import os
|
15 |
+
import plotly.express as px
|
16 |
+
import pandas as pd
|
17 |
+
from dash import Dash, html, dcc, Input, Output, callback
|
18 |
+
import plotly.express as px
|
19 |
+
from dataclasses import dataclass
|
20 |
+
import json
|
21 |
+
|
22 |
+
data = pd.DataFrame(columns=["Dataset", "Alpha", "Top K", "Recall", "Precision"])
|
23 |
+
data = pd.concat(
|
24 |
+
[
|
25 |
+
data,
|
26 |
+
pd.DataFrame(
|
27 |
+
[["ml-100k", 0.1, 20, 0.2, 0.2]],
|
28 |
+
columns=["Dataset", "Alpha", "Top K", "Recall", "Precision"],
|
29 |
+
),
|
30 |
+
]
|
31 |
+
)
|
32 |
+
debug = False
|
33 |
+
|
34 |
+
|
35 |
+
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
|
36 |
+
|
37 |
+
app = Dash(__name__, external_stylesheets=external_stylesheets)
|
38 |
+
|
39 |
+
server = app.server
|
40 |
+
|
41 |
+
|
42 |
+
dataset_options = [
|
43 |
+
{"label": entry, "value": entry} for entry in data["Dataset"].unique()
|
44 |
+
]
|
45 |
+
dataset_options_default_value = data["Dataset"].unique()[0]
|
46 |
+
|
47 |
+
alpha_options = [{"label": entry, "value": entry} for entry in data["Alpha"].unique()]
|
48 |
+
alpha_options_default_value = data["Alpha"].unique()[0]
|
49 |
+
|
50 |
+
top_k_options = [{"label": entry, "value": entry} for entry in data["Top K"].unique()]
|
51 |
+
top_k_options_default_value = data["Top K"].unique()[0]
|
52 |
+
|
53 |
+
app.layout = html.Div(
|
54 |
+
[
|
55 |
+
html.H1("System Evaluation"),
|
56 |
+
html.Div(
|
57 |
+
[
|
58 |
+
html.Div(
|
59 |
+
[
|
60 |
+
html.H3("Dataset"),
|
61 |
+
dcc.Dropdown(
|
62 |
+
id="dataset-dropdown",
|
63 |
+
options=dataset_options,
|
64 |
+
value=dataset_options_default_value,
|
65 |
+
),
|
66 |
+
],
|
67 |
+
className="three columns",
|
68 |
+
),
|
69 |
+
html.Div(
|
70 |
+
[
|
71 |
+
html.H3("Alpha"),
|
72 |
+
dcc.Dropdown(
|
73 |
+
id="alpha-dropdown",
|
74 |
+
options=alpha_options,
|
75 |
+
value=alpha_options_default_value,
|
76 |
+
),
|
77 |
+
],
|
78 |
+
className="three columns",
|
79 |
+
),
|
80 |
+
html.Div(
|
81 |
+
[
|
82 |
+
html.H3("Top K"),
|
83 |
+
dcc.Dropdown(
|
84 |
+
id="top_k-dropdown",
|
85 |
+
options=top_k_options,
|
86 |
+
value=top_k_options_default_value,
|
87 |
+
),
|
88 |
+
],
|
89 |
+
className="three columns",
|
90 |
+
),
|
91 |
+
],
|
92 |
+
className="row",
|
93 |
+
),
|
94 |
+
html.Div(
|
95 |
+
[
|
96 |
+
html.Div([dcc.Graph(id="recall-graph")], className="six columns"),
|
97 |
+
html.Div([dcc.Graph(id="precision-graph")], className="six columns"),
|
98 |
+
],
|
99 |
+
className="row",
|
100 |
+
),
|
101 |
+
]
|
102 |
+
)
|
103 |
+
|
104 |
+
|
105 |
+
@app.callback(
|
106 |
+
Output("recall-graph", "figure"),
|
107 |
+
Output("precision-graph", "figure"),
|
108 |
+
Input("alpha-dropdown", "value"),
|
109 |
+
Input("dataset-dropdown", "value"),
|
110 |
+
Input("top_k-dropdown", "value"),
|
111 |
+
)
|
112 |
+
def update_graph(alpha, dataset, top_k):
|
113 |
+
filtered_data = data[
|
114 |
+
(data["Alpha"] == alpha)
|
115 |
+
& (data["Dataset"] == dataset)
|
116 |
+
& (data["Top K"] == top_k)
|
117 |
+
]
|
118 |
+
recall_fig = px.bar(filtered_data, x="Dataset", y="Recall")
|
119 |
+
precision_fig = px.bar(filtered_data, x="Dataset", y="Precision")
|
120 |
+
return recall_fig, precision_fig
|
121 |
+
|
122 |
+
|
123 |
+
# Run app and display result inline in the notebook
|
124 |
+
if __name__ == "__main__":
|
125 |
+
app.run_server(debug=debug, port=8050)
|