Spaces:
Sleeping
Sleeping
File size: 6,628 Bytes
12763b7 7aa7428 12763b7 7aa7428 4f21f44 7aa7428 f44602f 12763b7 f44602f 12763b7 f44602f 12763b7 f44602f 331907c f44602f 331907c f44602f 12763b7 7aa7428 f44602f 7aa7428 12763b7 f44602f 12763b7 f44602f 12763b7 7aa7428 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
import os
import time
import pandas as pd
import numpy as np
import joblib
import requests
import streamlit as st
from streamlit_autorefresh import st_autorefresh
from sklearn.metrics import mean_absolute_error
import plotly.express as px
# Auto-refresh every 5 seconds
st_autorefresh(interval=5000, key="refresh")
# Load model
@st.cache_resource
def load_model():
return joblib.load("rf_model.pkl")
model = load_model()
# Supabase config
SUPABASE_URL = os.environ["SUPABASE_URL"]
SUPABASE_KEY = os.environ["SUPABASE_KEY"]
TABLE = "smart_meter_readings_1year"
# Initialize session state
if "row_index" not in st.session_state:
st.session_state.row_index = 0
if "history" not in st.session_state:
st.session_state.history = pd.DataFrame()
# Fetch all data
@st.cache_data
def fetch_all_data():
url = f"{SUPABASE_URL}/rest/v1/{TABLE}?select=*&order=timestamp.asc"
headers = {
"apikey": SUPABASE_KEY,
"Authorization": f"Bearer {SUPABASE_KEY}"
}
r = requests.get(url, headers=headers)
if r.ok:
return pd.DataFrame(r.json())
else:
st.error(f"โ Error fetching data: {r.status_code}")
return pd.DataFrame()
df_all = fetch_all_data()
# Debug sidebar
st.sidebar.title("๐ Debug Info")
st.sidebar.write("Row index:", st.session_state.row_index)
st.sidebar.write("Total rows:", len(df_all))
if not df_all.empty and st.session_state.row_index < len(df_all):
st.sidebar.write("Next row:", df_all.iloc[st.session_state.row_index].to_dict())
# Get next row
def get_next_row():
if st.session_state.row_index < len(df_all):
row = df_all.iloc[[st.session_state.row_index]]
st.session_state.row_index += 1
return row
return pd.DataFrame()
def forecast_next(df, model, steps=5):
forecasts = []
df_copy = df.copy()
expected_features = model.feature_names_in_.tolist()
for i in range(steps):
df_copy = engineer(df_copy).dropna()
# Ensure all expected features are present
for col in expected_features:
if col not in df_copy.columns:
df_copy[col] = 0
# Select and order input features
input_row = df_copy.iloc[[-1]][expected_features]
y_pred = model.predict(input_row)[0]
# Prepare next row
next_timestamp = df_copy.iloc[-1]["timestamp"] + 1800
new_row = df_copy.iloc[-1].copy()
new_row["power_consumption_kwh"] = y_pred
new_row["timestamp"] = next_timestamp
df_copy = pd.concat([df_copy, pd.DataFrame([new_row])], ignore_index=True)
forecasts.append({"timestamp": next_timestamp, "forecast_kwh": y_pred})
return pd.DataFrame(forecasts)
# Forecast ahead logic (5 steps, 30min intervals)
def forecast_next(df, model, steps=5):
forecasts = []
df_copy = df.copy()
expected_features = model.feature_names_in_.tolist()
for i in range(steps):
df_copy = engineer(df_copy).dropna()
# Ensure columns are aligned to model input
input_row = df_copy.iloc[[-1]][expected_features]
y_pred = model.predict(input_row)[0]
# Update the last row's power consumption with prediction
df_copy.at[df_copy.index[-1], "power_consumption_kwh"] = y_pred
# Prepare the next timestamp: add 1800 seconds (30 mins)
next_timestamp = df_copy.iloc[-1]["timestamp"] + 1800
# Prepare new row: copy last row features but update timestamp and power consumption
new_row = df_copy.iloc[-1].copy()
new_row["power_consumption_kwh"] = y_pred
new_row["timestamp"] = next_timestamp
# Append new row safely
df_copy = pd.concat([df_copy, pd.DataFrame([new_row])], ignore_index=True)
forecasts.append({"timestamp": next_timestamp, "forecast_kwh": y_pred})
return pd.DataFrame(forecasts)
# UI Layout
st.set_page_config(layout="wide")
st.title("โก Gridflux: Real-Time Smart Meter Dashboard")
# Layout structure
col1, col2 = st.columns([2, 1])
# Data ingestion and prediction
new_row = get_next_row()
if not new_row.empty:
st.session_state.history = pd.concat([st.session_state.history, new_row], ignore_index=True)
df_feat = engineer(st.session_state.history).dropna()
if not df_feat.empty:
# Align features exactly to what model expects
expected_features = model.feature_names_in_.tolist()
for col in expected_features:
if col not in df_feat.columns:
df_feat[col] = 0
latest_input = df_feat[expected_features].iloc[[-1]]
prediction = model.predict(latest_input)[0]
actual = new_row["power_consumption_kwh"].values[0]
mae = mean_absolute_error([actual], [prediction])
with col1:
st.subheader("๐ Real-Time Power Usage")
chart_df = st.session_state.history.copy()
chart_df["datetime"] = pd.to_datetime(chart_df["timestamp"])
chart_df.set_index("datetime", inplace=True)
st.line_chart(chart_df["power_consumption_kwh"], use_container_width=True)
st.subheader("๐ฎ Forecast (Next 2.5 Hours)")
future_df = forecast_next(df_feat, model, steps=5)
future_df["datetime"] = pd.to_datetime(future_df["timestamp"])
fig = px.line(future_df, x="datetime", y="forecast_kwh", title="Forecasted Power Usage (Next 2.5h)")
st.plotly_chart(fig, use_container_width=True)
with col2:
st.metric("๐ฎ Predicted Power Usage (kWh)", f"{prediction:.3f}")
st.metric("โ
Actual Power Usage (kWh)", f"{actual:.3f}")
st.metric("๐ MAE", f"{mae:.3f}")
st.subheader("๐ Region-Wise Forecast")
for region in ["east", "west", "north", "south"]:
regional = df_feat[df_feat[f"region_{region}"] == 1]
if not regional.empty:
preds = model.predict(regional[expected_features])
st.write(f"**{region.title()} Region**: Avg Forecast: {np.mean(preds):.3f} kWh")
st.subheader("๐ Property Type Forecast")
for region in ["east", "west", "north", "south"]:
for ptype in ["commercial", "residential"]:
filtered = df_feat[(df_feat[f"region_{region}"] == 1) & (df_feat[f"property_type_{ptype}"] == 1)]
if not filtered.empty:
preds = model.predict(filtered[expected_features])
st.write(f"{region.title()} / {ptype.title()}: {np.mean(preds):.2f} kWh")
else:
st.success("โ
All data processed.")
|