Update app.py
Browse files
app.py
CHANGED
|
@@ -36,37 +36,44 @@ BOLD_FONT = "Arial Black, Arial, sans-serif" # used for bold axis titles & tick
|
|
| 36 |
# =========================
|
| 37 |
st.set_page_config(page_title="ST_GeoMech_UCS", page_icon="logo.png", layout="wide")
|
| 38 |
|
| 39 |
-
#
|
| 40 |
st.markdown("""
|
| 41 |
<style>
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
.centered-container {
|
| 47 |
-
display: flex;
|
| 48 |
-
flex-direction: column;
|
| 49 |
-
align-items: center;
|
| 50 |
-
text-align: center;
|
| 51 |
-
}
|
| 52 |
-
</style>
|
| 53 |
-
""", unsafe_allow_html=True)
|
| 54 |
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
.main .block-container {
|
| 60 |
-
|
| 61 |
}
|
| 62 |
|
| 63 |
-
/*
|
| 64 |
-
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
}
|
| 67 |
</style>
|
| 68 |
""", unsafe_allow_html=True)
|
| 69 |
|
|
|
|
| 70 |
# Hide uploader helper text ("Drag and drop file here", limits, etc.)
|
| 71 |
st.markdown("""
|
| 72 |
<style>
|
|
@@ -196,9 +203,9 @@ def df_centered_rounded(df: pd.DataFrame, hide_index=True):
|
|
| 196 |
numcols = out.select_dtypes(include=[np.number]).columns
|
| 197 |
styler = (
|
| 198 |
out.style
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
)
|
| 203 |
st.dataframe(styler, use_container_width=True, hide_index=hide_index)
|
| 204 |
|
|
@@ -432,29 +439,32 @@ st.sidebar.markdown(f"""
|
|
| 432 |
)
|
| 433 |
|
| 434 |
# =========================
|
| 435 |
-
#
|
|
|
|
| 436 |
# =========================
|
| 437 |
-
|
| 438 |
-
st.markdown(
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
""
|
| 456 |
-
|
| 457 |
-
|
|
|
|
|
|
|
| 458 |
|
| 459 |
# =========================
|
| 460 |
# INTRO
|
|
@@ -496,14 +506,6 @@ if st.session_state.app_step == "dev":
|
|
| 496 |
if st.sidebar.button("Proceed to Validation â–¶", use_container_width=True): st.session_state.app_step="validate"; st.rerun()
|
| 497 |
if st.sidebar.button("Proceed to Prediction â–¶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 498 |
|
| 499 |
-
# Apply sticky header
|
| 500 |
-
if st.session_state.dev_file_loaded and st.session_state.dev_preview:
|
| 501 |
-
sticky_header("Case Building", "Previewed ✓ — now click **Run Model**.")
|
| 502 |
-
elif st.session_state.dev_file_loaded:
|
| 503 |
-
sticky_header("Case Building", "📄 **Preview uploaded data** using the sidebar button, then click **Run Model**.")
|
| 504 |
-
else:
|
| 505 |
-
sticky_header("Case Building", "**Upload your data to build a case, then run the model to review development performance.**")
|
| 506 |
-
|
| 507 |
if run and st.session_state.dev_file_bytes:
|
| 508 |
book = read_book_bytes(st.session_state.dev_file_bytes)
|
| 509 |
sh_train = find_sheet(book, ["Train","Training","training2","train","training"])
|
|
@@ -571,8 +573,6 @@ if st.session_state.app_step == "validate":
|
|
| 571 |
if st.sidebar.button("⬅ Back to Case Building", use_container_width=True): st.session_state.app_step="dev"; st.rerun()
|
| 572 |
if st.sidebar.button("Proceed to Prediction â–¶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 573 |
|
| 574 |
-
sticky_header("Validate the Model", "Upload a dataset with the same **features** and **UCS** to evaluate performance.")
|
| 575 |
-
|
| 576 |
if go_btn and up is not None:
|
| 577 |
book = read_book_bytes(up.getvalue())
|
| 578 |
name = find_sheet(book, ["Validation","Validate","validation2","Val","val"]) or list(book.keys())[0]
|
|
@@ -638,8 +638,6 @@ if st.session_state.app_step == "predict":
|
|
| 638 |
go_btn = st.sidebar.button("Predict", type="primary", use_container_width=True)
|
| 639 |
if st.sidebar.button("⬅ Back to Case Building", use_container_width=True): st.session_state.app_step="dev"; st.rerun()
|
| 640 |
|
| 641 |
-
sticky_header("Prediction", "Upload a dataset with the feature columns (no **UCS**).")
|
| 642 |
-
|
| 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()
|
|
@@ -668,11 +666,11 @@ if st.session_state.app_step == "predict":
|
|
| 668 |
table = pd.DataFrame({
|
| 669 |
"Metric": ["# points","Pred min","Pred max","Pred mean","Pred std","OOR %"],
|
| 670 |
"Value": [sv["n"],
|
| 671 |
-
|
| 672 |
-
|
| 673 |
-
|
| 674 |
-
|
| 675 |
-
|
| 676 |
})
|
| 677 |
st.success("Predictions ready ✓")
|
| 678 |
df_centered_rounded(table, hide_index=True)
|
|
|
|
| 36 |
# =========================
|
| 37 |
st.set_page_config(page_title="ST_GeoMech_UCS", page_icon="logo.png", layout="wide")
|
| 38 |
|
| 39 |
+
# This is the new CSS block for the sticky header and message box
|
| 40 |
st.markdown("""
|
| 41 |
<style>
|
| 42 |
+
/* Add a light gray background to the main app container */
|
| 43 |
+
.stApp {
|
| 44 |
+
background-color: #f0f2f6;
|
| 45 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
/* CSS to make the header sticky */
|
| 48 |
+
.fixed-header-container {
|
| 49 |
+
position: sticky;
|
| 50 |
+
top: 0;
|
| 51 |
+
z-index: 1000;
|
| 52 |
+
background-color: #f0f2f6; /* Ensure sticky header background matches app background */
|
| 53 |
+
padding: 10px 0;
|
| 54 |
+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
/* CSS to ensure main content doesn't get hidden under the sticky header */
|
| 58 |
.main .block-container {
|
| 59 |
+
padding-top: 250px; /* Adjust this value to match the height of your sticky header */
|
| 60 |
}
|
| 61 |
|
| 62 |
+
/* General CSS */
|
| 63 |
+
.brand-logo { width: 16px; height: auto; object-fit: contain; }
|
| 64 |
+
.sidebar-header { display:flex; align-items:center; gap:12px; }
|
| 65 |
+
.sidebar-header .text h1 { font-size: 1.05rem; margin:0; line-height:1.1; }
|
| 66 |
+
.sidebar-header .text .tag { font-size: .85rem; color:#6b7280; margin:2px 0 0; }
|
| 67 |
+
.centered-container {
|
| 68 |
+
display: flex;
|
| 69 |
+
flex-direction: column;
|
| 70 |
+
align-items: center;
|
| 71 |
+
text-align: center;
|
| 72 |
}
|
| 73 |
</style>
|
| 74 |
""", unsafe_allow_html=True)
|
| 75 |
|
| 76 |
+
|
| 77 |
# Hide uploader helper text ("Drag and drop file here", limits, etc.)
|
| 78 |
st.markdown("""
|
| 79 |
<style>
|
|
|
|
| 203 |
numcols = out.select_dtypes(include=[np.number]).columns
|
| 204 |
styler = (
|
| 205 |
out.style
|
| 206 |
+
.format({c: "{:.2f}" for c in numcols})
|
| 207 |
+
.set_properties(**{"text-align": "center"})
|
| 208 |
+
.set_table_styles(TABLE_CENTER_CSS)
|
| 209 |
)
|
| 210 |
st.dataframe(styler, use_container_width=True, hide_index=hide_index)
|
| 211 |
|
|
|
|
| 439 |
)
|
| 440 |
|
| 441 |
# =========================
|
| 442 |
+
# The main sticky container is defined here, before the app logic
|
| 443 |
+
# This ensures it's rendered at the top of the page regardless of state.
|
| 444 |
# =========================
|
| 445 |
+
with st.container():
|
| 446 |
+
st.markdown("<div class='fixed-header-container'>", unsafe_allow_html=True)
|
| 447 |
+
|
| 448 |
+
# Conditional rendering for the headers and messages
|
| 449 |
+
if st.session_state.app_step == "dev":
|
| 450 |
+
st.header("Case Building")
|
| 451 |
+
if st.session_state.dev_file_loaded and st.session_state.dev_preview:
|
| 452 |
+
st.info("Previewed ✓ — now click **Run Model**.")
|
| 453 |
+
elif st.session_state.dev_file_loaded:
|
| 454 |
+
st.info("📄 Preview uploaded data using the sidebar button, then click **Run Model**.")
|
| 455 |
+
else:
|
| 456 |
+
st.info("Upload your data to build a case, then run the model to review development performance.")
|
| 457 |
+
|
| 458 |
+
elif st.session_state.app_step == "validate":
|
| 459 |
+
st.header("Validate the Model")
|
| 460 |
+
st.info("Upload a dataset with the same **features** and **UCS** to evaluate performance.")
|
| 461 |
+
|
| 462 |
+
elif st.session_state.app_step == "predict":
|
| 463 |
+
st.header("Prediction")
|
| 464 |
+
st.info("Upload a dataset with the feature columns (no **UCS**).")
|
| 465 |
+
|
| 466 |
+
st.markdown("</div>", unsafe_allow_html=True)
|
| 467 |
+
|
| 468 |
|
| 469 |
# =========================
|
| 470 |
# INTRO
|
|
|
|
| 506 |
if st.sidebar.button("Proceed to Validation â–¶", use_container_width=True): st.session_state.app_step="validate"; st.rerun()
|
| 507 |
if st.sidebar.button("Proceed to Prediction â–¶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 508 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 509 |
if run and st.session_state.dev_file_bytes:
|
| 510 |
book = read_book_bytes(st.session_state.dev_file_bytes)
|
| 511 |
sh_train = find_sheet(book, ["Train","Training","training2","train","training"])
|
|
|
|
| 573 |
if st.sidebar.button("⬅ Back to Case Building", use_container_width=True): st.session_state.app_step="dev"; st.rerun()
|
| 574 |
if st.sidebar.button("Proceed to Prediction â–¶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 575 |
|
|
|
|
|
|
|
| 576 |
if go_btn and up is not None:
|
| 577 |
book = read_book_bytes(up.getvalue())
|
| 578 |
name = find_sheet(book, ["Validation","Validate","validation2","Val","val"]) or list(book.keys())[0]
|
|
|
|
| 638 |
go_btn = st.sidebar.button("Predict", type="primary", use_container_width=True)
|
| 639 |
if st.sidebar.button("⬅ Back to Case Building", use_container_width=True): st.session_state.app_step="dev"; st.rerun()
|
| 640 |
|
|
|
|
|
|
|
| 641 |
if go_btn and up is not None:
|
| 642 |
book = read_book_bytes(up.getvalue()); name = list(book.keys())[0]
|
| 643 |
df = book[name].copy()
|
|
|
|
| 666 |
table = pd.DataFrame({
|
| 667 |
"Metric": ["# points","Pred min","Pred max","Pred mean","Pred std","OOR %"],
|
| 668 |
"Value": [sv["n"],
|
| 669 |
+
round(sv["pred_min"],2),
|
| 670 |
+
round(sv["pred_max"],2),
|
| 671 |
+
round(sv["pred_mean"],2),
|
| 672 |
+
round(sv["pred_std"],2),
|
| 673 |
+
f'{sv["oor"]:.1f}%']
|
| 674 |
})
|
| 675 |
st.success("Predictions ready ✓")
|
| 676 |
df_centered_rounded(table, hide_index=True)
|