Spaces:
Sleeping
Sleeping
Refine dashboard UI with clean borders, adaptive padding, and consistent graphs
Browse files
app.py
CHANGED
|
@@ -125,89 +125,109 @@ with st.sidebar:
|
|
| 125 |
st.session_state.cumulative_reward = 0.0
|
| 126 |
|
| 127 |
# ββ Main UI ββ
|
| 128 |
-
st.title("EcoGrid-OpenEnv Dashboard")
|
| 129 |
-
st.markdown("
|
|
|
|
| 130 |
|
| 131 |
col_live, col_reward, col_emissions = st.columns(3)
|
| 132 |
|
| 133 |
# Panel 1: Live Grid State
|
| 134 |
with col_live:
|
| 135 |
-
st.
|
| 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 |
# Panel 2: Reward Over Time
|
| 161 |
with col_reward:
|
| 162 |
-
st.
|
| 163 |
-
|
| 164 |
-
if st.session_state.history:
|
| 165 |
-
df = pd.DataFrame(st.session_state.history)
|
| 166 |
-
|
| 167 |
-
# Current Episode Reward
|
| 168 |
-
fig3 = go.Figure()
|
| 169 |
-
fig3.add_trace(go.Scatter(x=df['step'], y=df['reward'], mode='lines+markers', name='Total Reward'))
|
| 170 |
-
fig3.update_layout(title="Step Reward", height=200, margin=dict(l=10, r=10, t=30, b=10))
|
| 171 |
-
st.plotly_chart(fig3, use_container_width=True)
|
| 172 |
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
|
| 183 |
# Panel 3: Emissions & Training
|
| 184 |
with col_emissions:
|
| 185 |
-
st.
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
{'
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
st.session_state.cumulative_reward = 0.0
|
| 126 |
|
| 127 |
# ββ Main UI ββ
|
| 128 |
+
st.title("β‘ EcoGrid-OpenEnv Dashboard")
|
| 129 |
+
st.markdown("Reinforcement Learning Environment for Sustainable Energy Grid Management. *(Scaler Γ Meta Hackathon)*")
|
| 130 |
+
st.markdown("---")
|
| 131 |
|
| 132 |
col_live, col_reward, col_emissions = st.columns(3)
|
| 133 |
|
| 134 |
# Panel 1: Live Grid State
|
| 135 |
with col_live:
|
| 136 |
+
with st.container(border=True):
|
| 137 |
+
st.subheader("π‘ Live Grid State")
|
| 138 |
+
state = st.session_state.state
|
| 139 |
+
|
| 140 |
+
st.metric("Timestep", f"{state.time_step} / {st.session_state.env.get_task_config(st.session_state.current_task)['episode_length']}")
|
| 141 |
+
|
| 142 |
+
# Battery Gauge
|
| 143 |
+
fig = go.Figure(go.Indicator(
|
| 144 |
+
mode = "gauge+number",
|
| 145 |
+
value = state.battery_level * 100,
|
| 146 |
+
title = {'text': "Battery Level (%)", 'font': {'size': 14}},
|
| 147 |
+
gauge = {'axis': {'range': [0, 100]}, 'bar': {'color': "#00cc96"}, 'bgcolor': "rgba(0,0,0,0)"}
|
| 148 |
+
))
|
| 149 |
+
fig.update_layout(height=200, margin=dict(l=20, r=20, t=40, b=20))
|
| 150 |
+
st.plotly_chart(fig, use_container_width=True, config={'displayModeBar': False})
|
| 151 |
+
|
| 152 |
+
# Capacity Bars
|
| 153 |
+
fig2 = go.Figure(data=[
|
| 154 |
+
go.Bar(name='Demand', x=['Demand'], y=[state.demand], marker_color='#ef553b'),
|
| 155 |
+
go.Bar(name='Solar', x=['Solar'], y=[state.solar_capacity * 100], marker_color='#ffa15a'),
|
| 156 |
+
go.Bar(name='Wind', x=['Wind'], y=[state.wind_capacity * 100], marker_color='#636efa')
|
| 157 |
+
])
|
| 158 |
+
fig2.update_layout(height=220, margin=dict(l=20, r=20, t=20, b=20), barmode='group', showlegend=False)
|
| 159 |
+
st.plotly_chart(fig2, use_container_width=True, config={'displayModeBar': False})
|
| 160 |
|
| 161 |
|
| 162 |
# Panel 2: Reward Over Time
|
| 163 |
with col_reward:
|
| 164 |
+
with st.container(border=True):
|
| 165 |
+
st.subheader("π Agent Performance")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
+
if st.session_state.history:
|
| 168 |
+
df = pd.DataFrame(st.session_state.history)
|
| 169 |
+
|
| 170 |
+
# Current Episode Reward
|
| 171 |
+
fig3 = go.Figure()
|
| 172 |
+
fig3.add_trace(go.Scatter(x=df['step'], y=df['reward'], mode='lines', fill='tozeroy', name='Reward', line=dict(color='#ab63fa', width=3)))
|
| 173 |
+
fig3.update_layout(title="Step Reward", height=200, margin=dict(l=20, r=20, t=40, b=20), xaxis_title="Step", yaxis_title="Reward (0-1)")
|
| 174 |
+
st.plotly_chart(fig3, use_container_width=True, config={'displayModeBar': False})
|
| 175 |
+
|
| 176 |
+
# Breakdown
|
| 177 |
+
fig4 = go.Figure()
|
| 178 |
+
fig4.add_trace(go.Scatter(x=df['step'], y=df['cost_score'], name='Cost', line=dict(dash='dot')))
|
| 179 |
+
fig4.add_trace(go.Scatter(x=df['step'], y=df['carbon_score'], name='Carbon', line=dict(dash='dash')))
|
| 180 |
+
fig4.add_trace(go.Scatter(x=df['step'], y=df['stability_score'], name='Stability'))
|
| 181 |
+
fig4.update_layout(title="Reward Breakdown", height=220, margin=dict(l=20, r=20, t=40, b=20), legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1))
|
| 182 |
+
st.plotly_chart(fig4, use_container_width=True, config={'displayModeBar': False})
|
| 183 |
+
else:
|
| 184 |
+
st.info("Press 'βΆ Step' or 'β Run Episode' in the sidebar to see performance charts.")
|
| 185 |
+
for _ in range(12): st.empty() # padding to match height
|
| 186 |
|
| 187 |
# Panel 3: Emissions & Training
|
| 188 |
with col_emissions:
|
| 189 |
+
with st.container(border=True):
|
| 190 |
+
st.subheader("π Emissions & Training")
|
| 191 |
+
|
| 192 |
+
# Carbon Budget Gauge
|
| 193 |
+
max_budget = st.session_state.env.get_task_config(st.session_state.current_task)['carbon_budget']
|
| 194 |
+
current_budget = state.carbon_budget_remaining
|
| 195 |
+
|
| 196 |
+
fig5 = go.Figure(go.Indicator(
|
| 197 |
+
mode = "gauge+number",
|
| 198 |
+
value = current_budget,
|
| 199 |
+
title = {'text': "Carbon Budget (kgCO2)", 'font': {'size': 14}},
|
| 200 |
+
number = {'valueformat': ".0f"},
|
| 201 |
+
gauge = {
|
| 202 |
+
'axis': {'range': [0, max_budget]},
|
| 203 |
+
'bar': {'color': "#19d3f3" if current_budget > max_budget * 0.2 else "#ef553b"},
|
| 204 |
+
'steps': [
|
| 205 |
+
{'range': [0, max_budget * 0.2], 'color': "rgba(239, 85, 59, 0.2)"}
|
| 206 |
+
]
|
| 207 |
+
}
|
| 208 |
+
))
|
| 209 |
+
fig5.update_layout(height=200, margin=dict(l=20, r=20, t=40, b=20))
|
| 210 |
+
st.plotly_chart(fig5, use_container_width=True, config={'displayModeBar': False})
|
| 211 |
+
|
| 212 |
+
# RL Training Curve
|
| 213 |
+
st.markdown("**π§ GRPO Training Progress (Unsloth)**")
|
| 214 |
+
curve_data = load_or_mock_reward_curve()
|
| 215 |
+
df_curve = pd.DataFrame(curve_data)
|
| 216 |
+
fig6 = go.Figure()
|
| 217 |
+
fig6.add_trace(go.Scatter(x=df_curve['step'], y=df_curve['reward'], mode='lines', line=dict(color='#00cc96', width=3)))
|
| 218 |
+
fig6.update_layout(height=180, margin=dict(l=20, r=20, t=10, b=20), xaxis_title="Training Steps", yaxis_title="Avg Reward")
|
| 219 |
+
st.plotly_chart(fig6, use_container_width=True, config={'displayModeBar': False})
|
| 220 |
+
|
| 221 |
+
# Global styling tweaks for clean padding
|
| 222 |
+
st.markdown("""
|
| 223 |
+
<style>
|
| 224 |
+
div[data-testid="stMetric"] {
|
| 225 |
+
background-color: rgba(128, 128, 128, 0.05);
|
| 226 |
+
padding: 10px 15px;
|
| 227 |
+
border-radius: 8px;
|
| 228 |
+
}
|
| 229 |
+
div[data-testid="stDecoration"] {
|
| 230 |
+
display: none;
|
| 231 |
+
}
|
| 232 |
+
</style>
|
| 233 |
+
""", unsafe_allow_html=True)
|