UCS2014 commited on
Commit
a06cbcb
·
verified ·
1 Parent(s): c40310a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -22
app.py CHANGED
@@ -25,9 +25,11 @@ MODEL_FALLBACKS = [MODELS_DIR / "model.joblib", MODELS_DIR / "model.pkl"]
25
  COLORS = {"pred": "#1f77b4", "actual": "#f2b702", "ref": "#5a5a5a"}
26
 
27
  # ---- Plot sizing controls ----
28
- CROSS_W = 450 # px (matplotlib figure size; Streamlit will still scale)
29
- CROSS_H = 450
30
  TRACK_H = 1000 # px (plotly height; width auto-fits column)
 
 
31
  FONT_SZ = 13
32
  BOLD_FONT = "Arial Black, Arial, sans-serif" # used for bold axis titles & ticks
33
 
@@ -107,6 +109,34 @@ TABLE_CENTER_CSS = [
107
  dict(selector="td", props=[("text-align", "center")]),
108
  ]
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  # =========================
111
  # Password gate
112
  # =========================
@@ -158,7 +188,7 @@ def rmse(y_true, y_pred) -> float:
158
 
159
  def pearson_r(y_true, y_pred) -> float:
160
  a = np.asarray(y_true, dtype=float)
161
- p = np.asarray(y_pred, dtype=float)
162
  if a.size < 2: return float("nan")
163
  return float(np.corrcoef(a, p)[0, 1])
164
 
@@ -207,7 +237,7 @@ def df_centered_rounded(df: pd.DataFrame, hide_index=True):
207
  # =========================
208
  def cross_plot_static(actual, pred):
209
  a = pd.Series(actual, dtype=float)
210
- p = pd.Series(pred, dtype=float)
211
 
212
  fixed_min, fixed_max = 6000, 10000
213
  ticks = np.arange(fixed_min, fixed_max + 1, 1000)
@@ -284,7 +314,9 @@ def track_plot(df, include_actual=True):
284
  ))
285
 
286
  fig.update_layout(
287
- height=TRACK_H, width=None, # width auto-fits the column
 
 
288
  paper_bgcolor="#fff", plot_bgcolor="#fff",
289
  margin=dict(l=64, r=16, t=36, b=48), hovermode="closest",
290
  font=dict(size=FONT_SZ, color="#000"),
@@ -509,10 +541,12 @@ if st.session_state.app_step == "dev":
509
  sh_train = find_sheet(book, ["Train","Training","training2","train","training"])
510
  sh_test = find_sheet(book, ["Test","Testing","testing2","test","testing"])
511
  if sh_train is None or sh_test is None:
512
- st.error("Workbook must include Train/Training/training2 and Test/Testing/testing2 sheets."); st.stop()
 
513
  tr = book[sh_train].copy(); te = book[sh_test].copy()
514
  if not (ensure_cols(tr, FEATURES+[TARGET]) and ensure_cols(te, FEATURES+[TARGET])):
515
- st.error("Missing required columns."); st.stop()
 
516
  tr["UCS_Pred"] = model.predict(tr[FEATURES])
517
  te["UCS_Pred"] = model.predict(te[FEATURES])
518
 
@@ -530,7 +564,7 @@ if st.session_state.app_step == "dev":
530
 
531
  tr_min = tr[FEATURES].min().to_dict(); tr_max = tr[FEATURES].max().to_dict()
532
  st.session_state.train_ranges = {f:(float(tr_min[f]), float(tr_max[f])) for f in FEATURES}
533
- st.success("Case has been built and results are displayed below.")
534
 
535
  def _dev_block(df, m):
536
  c1,c2,c3 = st.columns(3)
@@ -543,7 +577,7 @@ if st.session_state.app_step == "dev":
543
  with col_track:
544
  st.plotly_chart(
545
  track_plot(df, include_actual=True),
546
- use_container_width=True,
547
  config={"displayModeBar": False, "scrollZoom": True}
548
  )
549
 
@@ -577,7 +611,7 @@ if st.session_state.app_step == "validate":
577
  book = read_book_bytes(up.getvalue())
578
  name = find_sheet(book, ["Validation","Validate","validation2","Val","val"]) or list(book.keys())[0]
579
  df = book[name].copy()
580
- if not ensure_cols(df, FEATURES+[TARGET]): st.error("Missing required columns."); st.stop()
581
  df["UCS_Pred"] = model.predict(df[FEATURES])
582
  st.session_state.results["Validate"]=df
583
 
@@ -613,11 +647,12 @@ if st.session_state.app_step == "validate":
613
  with col_track:
614
  st.plotly_chart(
615
  track_plot(st.session_state.results["Validate"], include_actual=True),
616
- use_container_width=True, config={"displayModeBar": False, "scrollZoom": True}
 
617
  )
618
 
619
  sv = st.session_state.results["sv_val"]
620
- if sv["oor"] > 0: st.warning("Some inputs fall outside **training min–max** ranges.")
621
  if st.session_state.results["oor_tbl"] is not None:
622
  st.write("*Out-of-range rows (vs. Training min–max):*")
623
  df_centered_rounded(st.session_state.results["oor_tbl"])
@@ -643,7 +678,7 @@ if st.session_state.app_step == "predict":
643
  if go_btn and up is not None:
644
  book = read_book_bytes(up.getvalue()); name = list(book.keys())[0]
645
  df = book[name].copy()
646
- if not ensure_cols(df, FEATURES): st.error("Missing required columns."); st.stop()
647
  df["UCS_Pred"] = model.predict(df[FEATURES])
648
  st.session_state.results["PredictOnly"]=df
649
 
@@ -674,13 +709,14 @@ if st.session_state.app_step == "predict":
674
  round(sv["pred_std"],2),
675
  f'{sv["oor"]:.1f}%']
676
  })
677
- st.success("Predictions ready ✓")
678
  df_centered_rounded(table, hide_index=True)
679
  st.caption("**★ OOR** = % of rows whose input features fall outside the training min–max range.")
680
  with col_right:
681
  st.plotly_chart(
682
  track_plot(df, include_actual=False),
683
- use_container_width=True, config={"displayModeBar": False, "scrollZoom": True}
 
684
  )
685
 
686
  # =========================
@@ -693,20 +729,20 @@ if st.session_state.show_preview_modal:
693
  book_to_preview = read_book_bytes(st.session_state.dev_file_bytes)
694
  elif st.session_state.app_step in ["validate", "predict"] and up is not None:
695
  book_to_preview = read_book_bytes(up.getvalue())
696
-
697
  # Use a try-except block to handle cases where 'up' might be None
698
  # and the logic tries to access its attributes.
699
  try:
700
  if st.session_state.app_step == "validate" and up is not None:
701
- book_to_preview = read_book_bytes(up.getvalue())
702
  elif st.session_state.app_step == "predict" and up is not None:
703
- book_to_preview = read_book_bytes(up.getvalue())
704
  except NameError:
705
  book_to_preview = {}
706
 
707
  with st.expander("Preview data", expanded=True):
708
  if not book_to_preview:
709
- st.info("No data loaded yet.")
710
  else:
711
  names = list(book_to_preview.keys())
712
  tabs = st.tabs(names)
@@ -718,12 +754,12 @@ if st.session_state.show_preview_modal:
718
  st.pyplot(preview_tracks(df, FEATURES), use_container_width=True)
719
  with t2:
720
  tbl = (df[FEATURES]
721
- .agg(['min','max','mean','std'])
722
- .T.rename(columns={"min":"Min","max":"Max","mean":"Mean","std":"Std"}))
723
  df_centered_rounded(tbl.reset_index(names="Feature"))
724
  # Reset the state variable after the modal is displayed
725
  st.session_state.show_preview_modal = False
726
-
727
  # =========================
728
  # Footer
729
  # =========================
 
25
  COLORS = {"pred": "#1f77b4", "actual": "#f2b702", "ref": "#5a5a5a"}
26
 
27
  # ---- Plot sizing controls ----
28
+ CROSS_W = 350 # px (matplotlib figure size; Streamlit will still scale)
29
+ CROSS_H = 350
30
  TRACK_H = 1000 # px (plotly height; width auto-fits column)
31
+ # NEW: Add a TRACK_W variable to control the width
32
+ TRACK_W = 800 # px (plotly width)
33
  FONT_SZ = 13
34
  BOLD_FONT = "Arial Black, Arial, sans-serif" # used for bold axis titles & ticks
35
 
 
109
  dict(selector="td", props=[("text-align", "center")]),
110
  ]
111
 
112
+ # NEW: CSS for the message box
113
+ st.markdown("""
114
+ <style>
115
+ .st-message-box {
116
+ background-color: #f0f2f6;
117
+ color: #333333;
118
+ padding: 10px;
119
+ border-radius: 10px;
120
+ border: 1px solid #e6e9ef;
121
+ }
122
+ .st-message-box.st-success {
123
+ background-color: #d4edda;
124
+ color: #155724;
125
+ border-color: #c3e6cb;
126
+ }
127
+ .st-message-box.st-warning {
128
+ background-color: #fff3cd;
129
+ color: #856404;
130
+ border-color: #ffeeba;
131
+ }
132
+ .st-message-box.st-error {
133
+ background-color: #f8d7da;
134
+ color: #721c24;
135
+ border-color: #f5c6cb;
136
+ }
137
+ </style>
138
+ """, unsafe_allow_html=True)
139
+
140
  # =========================
141
  # Password gate
142
  # =========================
 
188
 
189
  def pearson_r(y_true, y_pred) -> float:
190
  a = np.asarray(y_true, dtype=float)
191
+ p = np.asarray(y_pred, dtype=float)
192
  if a.size < 2: return float("nan")
193
  return float(np.corrcoef(a, p)[0, 1])
194
 
 
237
  # =========================
238
  def cross_plot_static(actual, pred):
239
  a = pd.Series(actual, dtype=float)
240
+ p = pd.Series(pred, dtype=float)
241
 
242
  fixed_min, fixed_max = 6000, 10000
243
  ticks = np.arange(fixed_min, fixed_max + 1, 1000)
 
314
  ))
315
 
316
  fig.update_layout(
317
+ height=TRACK_H,
318
+ width=TRACK_W, # Set the width here
319
+ autosize=False, # Disable autosizing to respect the width
320
  paper_bgcolor="#fff", plot_bgcolor="#fff",
321
  margin=dict(l=64, r=16, t=36, b=48), hovermode="closest",
322
  font=dict(size=FONT_SZ, color="#000"),
 
541
  sh_train = find_sheet(book, ["Train","Training","training2","train","training"])
542
  sh_test = find_sheet(book, ["Test","Testing","testing2","test","testing"])
543
  if sh_train is None or sh_test is None:
544
+ st.markdown('<div class="st-message-box st-error">Workbook must include Train/Training/training2 and Test/Testing/testing2 sheets.</div>', unsafe_allow_html=True)
545
+ st.stop()
546
  tr = book[sh_train].copy(); te = book[sh_test].copy()
547
  if not (ensure_cols(tr, FEATURES+[TARGET]) and ensure_cols(te, FEATURES+[TARGET])):
548
+ st.markdown('<div class="st-message-box st-error">Missing required columns.</div>', unsafe_allow_html=True)
549
+ st.stop()
550
  tr["UCS_Pred"] = model.predict(tr[FEATURES])
551
  te["UCS_Pred"] = model.predict(te[FEATURES])
552
 
 
564
 
565
  tr_min = tr[FEATURES].min().to_dict(); tr_max = tr[FEATURES].max().to_dict()
566
  st.session_state.train_ranges = {f:(float(tr_min[f]), float(tr_max[f])) for f in FEATURES}
567
+ st.markdown('<div class="st-message-box st-success">Case has been built and results are displayed below.</div>', unsafe_allow_html=True)
568
 
569
  def _dev_block(df, m):
570
  c1,c2,c3 = st.columns(3)
 
577
  with col_track:
578
  st.plotly_chart(
579
  track_plot(df, include_actual=True),
580
+ use_container_width=False, # Set to False to honor the width in track_plot()
581
  config={"displayModeBar": False, "scrollZoom": True}
582
  )
583
 
 
611
  book = read_book_bytes(up.getvalue())
612
  name = find_sheet(book, ["Validation","Validate","validation2","Val","val"]) or list(book.keys())[0]
613
  df = book[name].copy()
614
+ if not ensure_cols(df, FEATURES+[TARGET]): st.markdown('<div class="st-message-box st-error">Missing required columns.</div>', unsafe_allow_html=True); st.stop()
615
  df["UCS_Pred"] = model.predict(df[FEATURES])
616
  st.session_state.results["Validate"]=df
617
 
 
647
  with col_track:
648
  st.plotly_chart(
649
  track_plot(st.session_state.results["Validate"], include_actual=True),
650
+ use_container_width=False, # Set to False to honor the width in track_plot()
651
+ config={"displayModeBar": False, "scrollZoom": True}
652
  )
653
 
654
  sv = st.session_state.results["sv_val"]
655
+ if sv["oor"] > 0: st.markdown('<div class="st-message-box st-warning">Some inputs fall outside **training min–max** ranges.</div>', unsafe_allow_html=True)
656
  if st.session_state.results["oor_tbl"] is not None:
657
  st.write("*Out-of-range rows (vs. Training min–max):*")
658
  df_centered_rounded(st.session_state.results["oor_tbl"])
 
678
  if go_btn and up is not None:
679
  book = read_book_bytes(up.getvalue()); name = list(book.keys())[0]
680
  df = book[name].copy()
681
+ if not ensure_cols(df, FEATURES): st.markdown('<div class="st-message-box st-error">Missing required columns.</div>', unsafe_allow_html=True); st.stop()
682
  df["UCS_Pred"] = model.predict(df[FEATURES])
683
  st.session_state.results["PredictOnly"]=df
684
 
 
709
  round(sv["pred_std"],2),
710
  f'{sv["oor"]:.1f}%']
711
  })
712
+ st.markdown('<div class="st-message-box st-success">Predictions ready ✓</div>', unsafe_allow_html=True)
713
  df_centered_rounded(table, hide_index=True)
714
  st.caption("**★ OOR** = % of rows whose input features fall outside the training min–max range.")
715
  with col_right:
716
  st.plotly_chart(
717
  track_plot(df, include_actual=False),
718
+ use_container_width=False, # Set to False to honor the width in track_plot()
719
+ config={"displayModeBar": False, "scrollZoom": True}
720
  )
721
 
722
  # =========================
 
729
  book_to_preview = read_book_bytes(st.session_state.dev_file_bytes)
730
  elif st.session_state.app_step in ["validate", "predict"] and up is not None:
731
  book_to_preview = read_book_bytes(up.getvalue())
732
+
733
  # Use a try-except block to handle cases where 'up' might be None
734
  # and the logic tries to access its attributes.
735
  try:
736
  if st.session_state.app_step == "validate" and up is not None:
737
+ book_to_preview = read_book_bytes(up.getvalue())
738
  elif st.session_state.app_step == "predict" and up is not None:
739
+ book_to_preview = read_book_bytes(up.getvalue())
740
  except NameError:
741
  book_to_preview = {}
742
 
743
  with st.expander("Preview data", expanded=True):
744
  if not book_to_preview:
745
+ st.markdown('<div class="st-message-box">No data loaded yet.</div>', unsafe_allow_html=True)
746
  else:
747
  names = list(book_to_preview.keys())
748
  tabs = st.tabs(names)
 
754
  st.pyplot(preview_tracks(df, FEATURES), use_container_width=True)
755
  with t2:
756
  tbl = (df[FEATURES]
757
+ .agg(['min','max','mean','std'])
758
+ .T.rename(columns={"min":"Min","max":"Max","mean":"Mean","std":"Std"}))
759
  df_centered_rounded(tbl.reset_index(names="Feature"))
760
  # Reset the state variable after the modal is displayed
761
  st.session_state.show_preview_modal = False
762
+
763
  # =========================
764
  # Footer
765
  # =========================