Skip to content

Commit

Permalink
Improve Webapp with multi page
Browse files Browse the repository at this point in the history
  • Loading branch information
Antoine TAVANT committed Jun 26, 2024
1 parent 9c57cee commit ef3a925
Show file tree
Hide file tree
Showing 9 changed files with 722 additions and 2 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

name : Deploy Panel App

concurrency: production

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
deploy:
name: Deploy Panel App
runs-on: ubuntu-latest
environment: production

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up SSH
run: |
mkdir -p ~/.ssh/
echo "${{secrets.SSH_PRIVATE_KEY}}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -t ed25519 -H ${{secrets.PROD_IP}} >> ~/.ssh/known_hosts
- name: Deploy to Server
run: |
ssh ubuntu@${{secrets.PROD_IP}} << 'EOF'
# Arrêter le serveur Panel
pkill -f 'streamlit run'
cd ${{vars.PROD_PATH}}
git pull
git lfs pull
nohup hatch run serve:prod </dev/null >./log-prod.log 2>&1 &
EOF
7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ dependencies = [
"numpy>=1.25.0,<2.0.0", # numpy 2.0.0 is released but not yet supported by all dependencies
"pandas",
"xarray",
"netCDF4",
"watchfiles",
"scikit-learn",
"matplotlib",
"eccodes",
Expand Down Expand Up @@ -61,17 +63,18 @@ extra-dependencies = [
"sphinx_design",
"nbsphinx",
"taipy",
"streamlit",
]
[tool.hatch.envs.docs.scripts]
build = "sphinx-build -b html doc/ doc/_build"

[tool.hatch.envs.serve]
extra-dependencies = [
"taipy",
"streamlit",
]

[tool.hatch.envs.serve.scripts]
prod = "python src/energy_forecast/dashboard/dashboard.py"
prod = "streamlit run src/energy_forecast/dashboard/dashboard_streamlit.py"

[tool.coverage.run]
source_pkgs = ["energy_forecast", "tests"]
Expand Down
2 changes: 2 additions & 0 deletions src/energy_forecast/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from pathlib import Path
ROOT_DIR = Path(__file__).parent.parent.parent
version = "0.1.0"
19 changes: 19 additions & 0 deletions src/energy_forecast/dashboard/dashboard_streamlit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import streamlit as st

st.set_page_config(
page_title="ENR Forecast",
page_icon="🌞",
)

st.markdown("""# Welcome to Energy Forecast! 🌞
This App is a demo of a simple energy forecast dashboard.
It is divided into three sections:
- <a href="weather" target = "_self">Weather Forecast</a>
- <a href="power_generation" target = "_self">Energy Forecast</a>
- <a href="consumption_prediction" target = "_self">Consumption Forecast</a>
- <a href="prediction_tempo" target = "_self">Prediction Tempo</a>
""", unsafe_allow_html=True)

st.sidebar.success("Select a demo above.")
43 changes: 43 additions & 0 deletions src/energy_forecast/dashboard/pages/1_weather.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from energy_forecast.meteo import ArpegeSimpleAPI
from energy_forecast.energy import ECO2MixDownloader
from energy_forecast.consumption_forecast import PredictionForecastAPI
import pandas as pd
import streamlit as st
import altair as alt

def compute_data_sun()->pd.Series:
sun_data = ArpegeSimpleAPI().region_sun()
data = sun_data.sum(axis=1).to_frame()
data.reset_index(inplace=True)
data.columns = ["time", "sun_flux"]
# data.name = "sun_flux"
return data

def compute_data_wind()->pd.Series:
wind_data = ArpegeSimpleAPI().region_wind()
data = wind_data.sum(axis=1).to_frame()
data.reset_index(inplace=True)
data.columns = ["time", "wind_speed"]
return data

st.title("Prévision meteo")

wind_data = compute_data_wind()

wind_barplot = alt.Chart(wind_data).mark_bar().encode(
y="wind_speed",
x="time"

)
st.altair_chart(wind_barplot,
use_container_width=True
)

sun_data = compute_data_sun()
sun_barplot = alt.Chart(sun_data).mark_bar().encode(
y="sun_flux",
x="time"
)
st.altair_chart(sun_barplot,
use_container_width=True
)
91 changes: 91 additions & 0 deletions src/energy_forecast/dashboard/pages/2_power_generation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from energy_forecast.energy import ECO2MixDownloader
from energy_forecast.meteo import ArpegeSimpleAPI
from energy_forecast.consumption_forecast import PredictionForecastAPI
import pandas as pd
import streamlit as st
import altair as alt


def compute_data_pv_power()->pd.Series:
sun_data = ArpegeSimpleAPI().region_sun()
sun_data.columns = [
c.replace(" ", "_").replace("'", "_").replace("-", "_").lower()
for c in sun_data.columns
]
model_params = pd.read_csv("notebooks/datascience/sun_model_2_params.csv")
model_params.columns = ["region", "coef"]
model_params_ser = model_params.set_index("region").iloc[:, 0]
production = sun_data * model_params_ser
pv_power = production.sum(axis=1).to_frame() / 24
pv_power.reset_index(inplace=True)
pv_power.columns = ["time", "pv_power"]
return pv_power

def compute_data_eolien()->pd.Series:
wind_data = ArpegeSimpleAPI().region_wind()
wind_data.columns = [
c.replace(" ", "_").replace("'", "_").replace("-", "_").lower()
for c in wind_data.columns
]
model_params = pd.read_csv("notebooks/datascience/wind_model_2_params.csv")
model_params.columns = ["region", "coef"]
model_params_ser = model_params.set_index("region").iloc[:, 0]
production = wind_data * model_params_ser
eolien_power = production.sum(axis=1).to_frame() / 24
eolien_power.reset_index(inplace=True)
eolien_power.columns = ["time", "eolien_power"]
return eolien_power


pv_power = compute_data_pv_power()
eolien_power = compute_data_eolien()
print(pv_power)

def compute_energy():
r = ECO2MixDownloader(year=2024)
r.download()
energy = r.read_file()

energy = energy[["Eolien", "Solaire"]]
energy = energy["2024-06-17":]
energy.index = energy.index.tz_localize("Europe/Paris").tz_convert("UTC").tz_localize(None)
energy = pd.concat([
energy,
pv_power.set_index("time").rename(columns={"pv_power": "PV Prediction"}),
eolien_power.set_index("time").rename(columns={"eolien_power": "Eolien Prediction"})
], axis=1).reset_index()

return energy

energy = compute_energy()
# keep only full hours
energy = energy[energy["time"].dt.minute == 0]

st.title("Prévision de production ENR")


wind_history = alt.Chart(energy).mark_line().encode(
y="Eolien",
x="time"
)
wind_prediction = alt.Chart(energy).mark_line(color="red").encode(
y="Eolien Prediction",
x="time"
)
wind_barplot = wind_prediction + wind_history
st.altair_chart(wind_barplot,
use_container_width=True
)

sun_history = alt.Chart(energy).mark_line().encode(
y="Solaire",
x="time"
)
sun_prediction = alt.Chart(energy).mark_line(color="red").encode(
y="PV Prediction",
x="time"
)
sun_barplot = sun_prediction + sun_history
st.altair_chart(sun_barplot,
use_container_width=True
)
29 changes: 29 additions & 0 deletions src/energy_forecast/dashboard/pages/3_consumption_prediction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from energy_forecast.energy import ECO2MixDownloader
from energy_forecast.meteo import ArpegeSimpleAPI
from energy_forecast.consumption_forecast import PredictionForecastAPI
from energy_forecast import ROOT_DIR
import pandas as pd
import streamlit as st
import altair as alt


env_file = ROOT_DIR / ".env"
with env_file.open("r") as f:
secret = f.readline().strip().split("=", 1)[1]

consumption_forecast_api = PredictionForecastAPI(secret=secret)
consumption_forecast = consumption_forecast_api.get_weekly_forecast(
start_date=pd.Timestamp.now().date()
).reset_index()

st.title("Prévision de production ENR")



consumption_chart = alt.Chart(consumption_forecast).mark_line().encode(
y="predicted_consumption",
x="time"
)
st.altair_chart(consumption_chart,
use_container_width=True
)
15 changes: 15 additions & 0 deletions src/energy_forecast/dashboard/pages/4_prediction_tempo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import streamlit as st
import pandas as pd


st.title("Prévision de production ENR")

col1, col2, col3 = st.columns(3)

today = pd.Timestamp.now().date()

for offset, col in zip(range(3), [col1, col2, col3]):
text = f"Prévision pour le {today + pd.Timedelta(days=offset)}"
text += "\n\n <h1 style='color: white;'> Jour Bleu </h1>"
# an html blue square the size of the column with the text and H1 in white
col.markdown(f"<div style='background-color: blue ; padding: 10px ; border-radius: 10px ; color: white ; text-align: center'>{text}</div>", unsafe_allow_html=True)
Loading

0 comments on commit ef3a925

Please sign in to comment.