CarlyneB commited on
Commit
3b61151
·
1 Parent(s): 16ca8f7

[FEAT] Tab4: add Run tab + fix heatmap size + fix export tab reset

Browse files
Files changed (1) hide show
  1. tabs/tab4_optimization.py +57 -36
tabs/tab4_optimization.py CHANGED
@@ -588,7 +588,13 @@ def show_heatmap(df_result, resource_caps, method_costs, custom_resources=None,
588
  customdata=matrix_exact_fmt,
589
  hovertemplate="<b>%{y}</b><br>%{x}<br>% of cap: %{z:.1f}%<br>Exact: %{customdata}<extra></extra>",
590
  )
591
- apply_chart_style(fig, height=max(400, 60 + 30 * len(df_heat.index)))
 
 
 
 
 
 
592
  st.plotly_chart(fig, width='stretch')
593
 
594
  resource_to_group = get_resource_to_group()
@@ -1181,7 +1187,7 @@ def confirm_clear_all():
1181
  clear_all_data()
1182
  st.rerun()
1183
  with col2:
1184
- if st.button("Cancel",width='stretch'):
1185
  st.rerun()
1186
 
1187
  def reset_scenario():
@@ -1198,6 +1204,16 @@ def reset_scenario():
1198
  confirm_clear_all()
1199
 
1200
 
 
 
 
 
 
 
 
 
 
 
1201
  def render_tab():
1202
  """Render the Portfolio Generation tab.
1203
 
@@ -1237,44 +1253,59 @@ def render_tab():
1237
  if "enabled_methods" not in st.session_state:
1238
  st.session_state.enabled_methods = {}
1239
 
1240
- st.markdown("""
1241
- <p class="crra-sub-heading">Run optimization</p>""",
1242
- unsafe_allow_html=True,
1243
- )
1244
- col_inputs, col_scenario = st.columns(2, gap="large")
 
 
1245
 
1246
- with col_inputs:
1247
  st.markdown("""
1248
- <p class="crra-sub-sub-heading">From inputs</p>""",
1249
  unsafe_allow_html=True,
1250
  )
1251
- run_clicked = st.button("Run Optimization", icon=":material/play_arrow:", key="btn-run-optimization", type="primary")
1252
- panel_run_from_tabs()
1253
- panel_load_from_excel()
1254
 
1255
- with col_scenario:
1256
- st.markdown("""
1257
- <p class="crra-sub-sub-heading">From a saved scenario</p>""",
1258
- unsafe_allow_html=True,
1259
- )
1260
- panel_load_from_json_or_csv()
 
 
 
 
 
 
 
 
 
1261
 
1262
- if run_clicked:
1263
- run_and_store_result()
1264
 
1265
- if "latest_result" not in st.session_state:
 
 
 
 
 
 
1266
  return
1267
 
1268
- latest = st.session_state.latest_result
1269
  allocations = latest["allocations"]
1270
  resource_caps = latest["resource_caps"]
1271
  method_costs = latest["method_costs"]
1272
 
1273
  if not allocations or sum(allocations.values()) == 0:
 
 
 
1274
  return
1275
 
1276
- show_metrics(latest)
1277
-
1278
  df_result = build_results_df(
1279
  allocations,
1280
  method_constraints=latest.get("method_constraints")
@@ -1284,14 +1315,8 @@ def render_tab():
1284
  lambda x: f"{x:,.4f}" if pd.notna(x) else x
1285
  )
1286
 
1287
- tab_results, tab_resources, tab_bottleneck, tab_export = st.tabs([
1288
- "📊 Method allocation",
1289
- "🌿 Resource usage",
1290
- "🔍 Bottleneck analysis",
1291
- "💾 Export & Save",
1292
- ])
1293
-
1294
  with tab_results:
 
1295
  st.markdown('<p class="crra-sub-heading">Optimization Summary</p>', unsafe_allow_html=True)
1296
  st.dataframe(df_display, width='stretch')
1297
  st.markdown('<p class="crra-sub-heading">Method allocation breakdown</p>', unsafe_allow_html=True)
@@ -1312,8 +1337,4 @@ def render_tab():
1312
  show_bottleneck_analysis(latest)
1313
 
1314
  with tab_export:
1315
- save_scenario(latest)
1316
- export_scenario()
1317
- export_inputs_only()
1318
- export_all_charts()
1319
- reset_scenario()
 
588
  customdata=matrix_exact_fmt,
589
  hovertemplate="<b>%{y}</b><br>%{x}<br>% of cap: %{z:.1f}%<br>Exact: %{customdata}<extra></extra>",
590
  )
591
+ n_rows = len(df_heat.index)
592
+ n_cols = len(df_heat.columns)
593
+ height = max(500, 80 + 50 * n_rows)
594
+ # For wide heatmaps, force a minimum width so each column stays readable
595
+ if n_cols > 8:
596
+ fig.update_layout(width=max(900, 90 * n_cols))
597
+ apply_chart_style(fig, height=height)
598
  st.plotly_chart(fig, width='stretch')
599
 
600
  resource_to_group = get_resource_to_group()
 
1187
  clear_all_data()
1188
  st.rerun()
1189
  with col2:
1190
+ if st.button("Cancel", width='stretch', type="secondary", key="btn-cancel"):
1191
  st.rerun()
1192
 
1193
  def reset_scenario():
 
1204
  confirm_clear_all()
1205
 
1206
 
1207
+ @st.fragment
1208
+ def render_export_tab(latest):
1209
+ """Render the full export/save section as a fragment so Save reruns only this area."""
1210
+ save_scenario(latest)
1211
+ export_scenario()
1212
+ export_inputs_only()
1213
+ export_all_charts()
1214
+ reset_scenario()
1215
+
1216
+
1217
  def render_tab():
1218
  """Render the Portfolio Generation tab.
1219
 
 
1253
  if "enabled_methods" not in st.session_state:
1254
  st.session_state.enabled_methods = {}
1255
 
1256
+ tab_run, tab_results, tab_resources, tab_bottleneck, tab_export = st.tabs([
1257
+ "▶️ Run",
1258
+ "📊 Method allocation",
1259
+ "🌿 Resource usage",
1260
+ "🔍 Bottleneck analysis",
1261
+ "💾 Export & Save",
1262
+ ])
1263
 
1264
+ with tab_run:
1265
  st.markdown("""
1266
+ <p class="crra-sub-heading">Run optimization</p>""",
1267
  unsafe_allow_html=True,
1268
  )
1269
+ col_inputs, col_scenario = st.columns(2, gap="large")
 
 
1270
 
1271
+ with col_inputs:
1272
+ st.markdown("""
1273
+ <p class="crra-sub-sub-heading">From inputs</p>""",
1274
+ unsafe_allow_html=True,
1275
+ )
1276
+ run_clicked = st.button("Run Optimization", icon=":material/play_arrow:", key="btn-run-optimization", type="primary")
1277
+ panel_run_from_tabs()
1278
+ panel_load_from_excel()
1279
+
1280
+ with col_scenario:
1281
+ st.markdown("""
1282
+ <p class="crra-sub-sub-heading">From a saved scenario</p>""",
1283
+ unsafe_allow_html=True,
1284
+ )
1285
+ panel_load_from_json_or_csv()
1286
 
1287
+ if run_clicked:
1288
+ run_and_store_result()
1289
 
1290
+ _no_results = '<p class="caption">Run the optimization first to see results here.</p>'
1291
+
1292
+ latest = st.session_state.get("latest_result")
1293
+ if not latest:
1294
+ for _tab in [tab_results, tab_resources, tab_bottleneck, tab_export]:
1295
+ with _tab:
1296
+ st.markdown(_no_results, unsafe_allow_html=True)
1297
  return
1298
 
 
1299
  allocations = latest["allocations"]
1300
  resource_caps = latest["resource_caps"]
1301
  method_costs = latest["method_costs"]
1302
 
1303
  if not allocations or sum(allocations.values()) == 0:
1304
+ for _tab in [tab_results, tab_resources, tab_bottleneck, tab_export]:
1305
+ with _tab:
1306
+ st.markdown(_no_results, unsafe_allow_html=True)
1307
  return
1308
 
 
 
1309
  df_result = build_results_df(
1310
  allocations,
1311
  method_constraints=latest.get("method_constraints")
 
1315
  lambda x: f"{x:,.4f}" if pd.notna(x) else x
1316
  )
1317
 
 
 
 
 
 
 
 
1318
  with tab_results:
1319
+ show_metrics(latest)
1320
  st.markdown('<p class="crra-sub-heading">Optimization Summary</p>', unsafe_allow_html=True)
1321
  st.dataframe(df_display, width='stretch')
1322
  st.markdown('<p class="crra-sub-heading">Method allocation breakdown</p>', unsafe_allow_html=True)
 
1337
  show_bottleneck_analysis(latest)
1338
 
1339
  with tab_export:
1340
+ render_export_tab(latest)