Update app.py
Browse files
app.py
CHANGED
|
@@ -1,83 +1,98 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
|
|
|
|
|
|
| 6 |
model = Prophet()
|
| 7 |
model.fit(df)
|
| 8 |
|
| 9 |
-
future = model.make_future_dataframe(periods=
|
| 10 |
forecast = model.predict(future)
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
peak_row = forecast_tail.loc[forecast_tail['yhat'].idxmax()]
|
| 14 |
-
peak_time = peak_row['ds']
|
| 15 |
-
peak_value = peak_row['yhat']
|
| 16 |
|
| 17 |
-
|
|
|
|
| 18 |
|
| 19 |
-
#
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
fillcolor='rgba(0, 255, 100, 0.2)',
|
| 41 |
-
line=dict(width=0),
|
| 42 |
-
name='Confidence Interval'))
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
name='Peak Demand',
|
| 50 |
-
text=[f'Peak: {peak_value:.0f} MW'],
|
| 51 |
-
textposition="top center",
|
| 52 |
-
marker=dict(size=10, color='red')))
|
| 53 |
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
)
|
| 60 |
-
|
| 61 |
-
peak_text = f"📈 Peak demand of {peak_value:.0f} MW expected at {peak_time.strftime('%Y-%m-%d %H:%M')}."
|
| 62 |
-
return fig, peak_text
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
import gradio as gr
|
| 66 |
|
| 67 |
-
|
| 68 |
|
| 69 |
-
|
|
|
|
| 70 |
fn=forecast_energy,
|
| 71 |
inputs=[
|
| 72 |
gr.Radio([3, 7, 14], label="Select Forecast Period (Days)"),
|
| 73 |
-
gr.
|
| 74 |
],
|
| 75 |
outputs=[
|
| 76 |
-
gr.
|
| 77 |
-
gr.Textbox(label="Peak Demand
|
| 78 |
],
|
| 79 |
-
title="Smart Energy
|
| 80 |
-
description="
|
| 81 |
)
|
| 82 |
|
| 83 |
-
|
|
|
|
| 1 |
+
# Imports
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import matplotlib.pyplot as plt
|
| 4 |
+
from prophet import Prophet
|
| 5 |
+
import gradio as gr
|
| 6 |
+
|
| 7 |
+
# Load and preprocess data
|
| 8 |
+
url = 'https://data.open-power-system-data.org/time_series/2020-10-06/time_series_60min_singleindex.csv'
|
| 9 |
+
data = pd.read_csv(url)
|
| 10 |
+
|
| 11 |
+
df = data[['utc_timestamp', 'DE_load_actual_entsoe_transparency']].copy()
|
| 12 |
+
df.rename(columns={'utc_timestamp': 'ds', 'DE_load_actual_entsoe_transparency': 'y'}, inplace=True)
|
| 13 |
+
df.dropna(inplace=True)
|
| 14 |
+
df['ds'] = pd.to_datetime(df['ds']).dt.tz_localize(None)
|
| 15 |
|
| 16 |
+
# Forecast function with dropdown support
|
| 17 |
+
def forecast_energy(days, graph_type):
|
| 18 |
model = Prophet()
|
| 19 |
model.fit(df)
|
| 20 |
|
| 21 |
+
future = model.make_future_dataframe(periods=24 * days, freq='H')
|
| 22 |
forecast = model.predict(future)
|
| 23 |
+
forecast_future = forecast.tail(24 * days)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
+
# Paths to store each plot
|
| 26 |
+
paths = {}
|
| 27 |
|
| 28 |
+
# Forecast Plot
|
| 29 |
+
plt.figure(figsize=(12, 5))
|
| 30 |
+
plt.plot(forecast_future['ds'], forecast_future['yhat'], label='Predicted Load (MW)', color='blue')
|
| 31 |
+
plt.fill_between(forecast_future['ds'], forecast_future['yhat_lower'], forecast_future['yhat_upper'], color='skyblue', alpha=0.3, label='Confidence Interval')
|
| 32 |
+
plt.xticks(rotation=45)
|
| 33 |
+
plt.xlabel("Date")
|
| 34 |
+
plt.ylabel("Load (MW)")
|
| 35 |
+
plt.title(f"Forecasted Load (Next {days} Days)")
|
| 36 |
+
plt.legend()
|
| 37 |
+
plt.tight_layout()
|
| 38 |
+
paths["Forecast Plot"] = f"forecast_plot_{days}.png"
|
| 39 |
+
plt.savefig(paths["Forecast Plot"])
|
| 40 |
+
plt.close()
|
| 41 |
|
| 42 |
+
# Actual vs Forecast
|
| 43 |
+
plt.figure(figsize=(12, 4))
|
| 44 |
+
plt.plot(df['ds'].tail(24 * 7), df['y'].tail(24 * 7), label='Actual Load (Past Week)', color='black')
|
| 45 |
+
plt.plot(forecast_future['ds'], forecast_future['yhat'], label='Forecast Load', color='green')
|
| 46 |
+
plt.xticks(rotation=45)
|
| 47 |
+
plt.title("Actual vs Forecast")
|
| 48 |
+
plt.xlabel("Date")
|
| 49 |
+
plt.ylabel("Load (MW)")
|
| 50 |
+
plt.legend()
|
| 51 |
+
plt.tight_layout()
|
| 52 |
+
paths["Actual vs Forecast"] = f"actual_vs_forecast_{days}.png"
|
| 53 |
+
plt.savefig(paths["Actual vs Forecast"])
|
| 54 |
+
plt.close()
|
| 55 |
|
| 56 |
+
# Hourly Average
|
| 57 |
+
df['hour'] = df['ds'].dt.hour
|
| 58 |
+
hourly_avg = df.groupby('hour')['y'].mean()
|
| 59 |
+
plt.figure(figsize=(10, 4))
|
| 60 |
+
plt.plot(hourly_avg.index, hourly_avg.values, marker='o', linestyle='-', color='orange')
|
| 61 |
+
plt.title("Average Load by Hour of Day")
|
| 62 |
+
plt.xlabel("Hour")
|
| 63 |
+
plt.ylabel("Average Load (MW)")
|
| 64 |
+
plt.grid(True)
|
| 65 |
+
paths["Hourly Pattern"] = f"hourly_pattern.png"
|
| 66 |
+
plt.savefig(paths["Hourly Pattern"])
|
| 67 |
+
plt.close()
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
+
# Seasonality
|
| 70 |
+
seasonality_fig = model.plot_components(forecast)
|
| 71 |
+
paths["Seasonality"] = f"seasonality_{days}.png"
|
| 72 |
+
seasonality_fig.savefig(paths["Seasonality"])
|
| 73 |
+
plt.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
+
# Peak demand
|
| 76 |
+
peak_row = forecast_future.loc[forecast_future['yhat'].idxmax()]
|
| 77 |
+
peak_time = peak_row['ds']
|
| 78 |
+
peak_value = round(peak_row['yhat'], 2)
|
| 79 |
+
peak_info = f"🔺 Peak Demand Time: {peak_time} — {peak_value} MW"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
|
| 81 |
+
return paths[graph_type], peak_info
|
| 82 |
|
| 83 |
+
# Gradio Interface
|
| 84 |
+
iface = gr.Interface(
|
| 85 |
fn=forecast_energy,
|
| 86 |
inputs=[
|
| 87 |
gr.Radio([3, 7, 14], label="Select Forecast Period (Days)"),
|
| 88 |
+
gr.Dropdown(["Forecast Plot", "Actual vs Forecast", "Hourly Pattern", "Seasonality"], label="Select Graph Type")
|
| 89 |
],
|
| 90 |
outputs=[
|
| 91 |
+
gr.Image(type="filepath", label="Selected Plot"),
|
| 92 |
+
gr.Textbox(label="Peak Demand Info")
|
| 93 |
],
|
| 94 |
+
title="Smart Energy Load Forecasting",
|
| 95 |
+
description="Choose forecast days and which graph you want to visualize."
|
| 96 |
)
|
| 97 |
|
| 98 |
+
iface.launch(share=True)
|