Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -36,38 +36,36 @@ 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 |
-
|
| 47 |
-
background-color: #f0f2f6; /* Adjust to match your app's background color */
|
| 48 |
-
padding: 10px 0;
|
| 49 |
-
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
/* CSS to ensure main content doesn't get hidden under the sticky header */
|
| 53 |
-
.main .block-container {
|
| 54 |
-
padding-top: 250px; /* Adjust this value to match the height of your sticky header */
|
| 55 |
-
}
|
| 56 |
-
|
| 57 |
-
/* General CSS */
|
| 58 |
-
.brand-logo { width: 16px; height: auto; object-fit: contain; }
|
| 59 |
-
.sidebar-header { display:flex; align-items:center; gap:12px; }
|
| 60 |
-
.sidebar-header .text h1 { font-size: 1.05rem; margin:0; line-height:1.1; }
|
| 61 |
-
.sidebar-header .text .tag { font-size: .85rem; color:#6b7280; margin:2px 0 0; }
|
| 62 |
-
.centered-container {
|
| 63 |
display: flex;
|
| 64 |
flex-direction: column;
|
| 65 |
align-items: center;
|
| 66 |
text-align: center;
|
| 67 |
-
}
|
| 68 |
</style>
|
| 69 |
""", unsafe_allow_html=True)
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
# Hide uploader helper text ("Drag and drop file here", limits, etc.)
|
| 73 |
st.markdown("""
|
|
@@ -135,7 +133,7 @@ def add_password_gate() -> None:
|
|
| 135 |
|
| 136 |
st.sidebar.markdown(f"""
|
| 137 |
<div class="centered-container">
|
| 138 |
-
<img src="{inline_logo('logo.png')}" style="width:
|
| 139 |
<div style='font-weight:800;font-size:1.2rem; margin-top: 10px;'>ST_GeoMech_UCS</div>
|
| 140 |
<div style='color:#667085;'>Smart Thinking • Secure Access</div>
|
| 141 |
</div>
|
|
@@ -198,9 +196,9 @@ def df_centered_rounded(df: pd.DataFrame, hide_index=True):
|
|
| 198 |
numcols = out.select_dtypes(include=[np.number]).columns
|
| 199 |
styler = (
|
| 200 |
out.style
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
)
|
| 205 |
st.dataframe(styler, use_container_width=True, hide_index=hide_index)
|
| 206 |
|
|
@@ -426,7 +424,7 @@ st.session_state.setdefault("dev_preview",False)
|
|
| 426 |
# =========================
|
| 427 |
st.sidebar.markdown(f"""
|
| 428 |
<div class="centered-container">
|
| 429 |
-
<img src="{inline_logo('logo.png')}" style="width:
|
| 430 |
<div style='font-weight:800;font-size:1.2rem;'>ST_GeoMech_UCS</div>
|
| 431 |
<div style='color:#667085;'>Real-Time UCS Tracking While Drilling</div>
|
| 432 |
</div>
|
|
@@ -435,36 +433,28 @@ st.sidebar.markdown(f"""
|
|
| 435 |
|
| 436 |
# =========================
|
| 437 |
# Reusable Sticky Header Function
|
| 438 |
-
# This function is now removed, replaced by the fixed-header-container
|
| 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 |
-
|
| 446 |
-
st.markdown(
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
st.markdown("</div>", unsafe_allow_html=True)
|
| 467 |
-
|
| 468 |
|
| 469 |
# =========================
|
| 470 |
# INTRO
|
|
@@ -506,6 +496,14 @@ if st.session_state.app_step == "dev":
|
|
| 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,6 +571,8 @@ if st.session_state.app_step == "validate":
|
|
| 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,6 +638,8 @@ 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 |
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,11 +668,11 @@ if st.session_state.app_step == "predict":
|
|
| 666 |
table = pd.DataFrame({
|
| 667 |
"Metric": ["# points","Pred min","Pred max","Pred mean","Pred std","OOR %"],
|
| 668 |
"Value": [sv["n"],
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
|
| 673 |
-
|
| 674 |
})
|
| 675 |
st.success("Predictions ready ✓")
|
| 676 |
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 |
+
# General CSS (logo helpers etc.)
|
| 40 |
st.markdown("""
|
| 41 |
<style>
|
| 42 |
+
.brand-logo { width: 16px; height: auto; object-fit: contain; }
|
| 43 |
+
.sidebar-header { display:flex; align-items:center; gap:12px; }
|
| 44 |
+
.sidebar-header .text h1 { font-size: 1.05rem; margin:0; line-height:1.1; }
|
| 45 |
+
.sidebar-header .text .tag { font-size: .85rem; color:#6b7280; margin:2px 0 0; }
|
| 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 |
+
# CSS to make sticky headers work correctly by overriding Streamlit's overflow property
|
| 56 |
+
st.markdown("""
|
| 57 |
+
<style>
|
| 58 |
+
/* This targets the main content area */
|
| 59 |
+
.main .block-container {
|
| 60 |
+
overflow: unset !important;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
/* This targets the vertical block that holds all your elements */
|
| 64 |
+
div[data-testid="stVerticalBlock"] {
|
| 65 |
+
overflow: unset !important;
|
| 66 |
+
}
|
| 67 |
+
</style>
|
| 68 |
+
""", unsafe_allow_html=True)
|
| 69 |
|
| 70 |
# Hide uploader helper text ("Drag and drop file here", limits, etc.)
|
| 71 |
st.markdown("""
|
|
|
|
| 133 |
|
| 134 |
st.sidebar.markdown(f"""
|
| 135 |
<div class="centered-container">
|
| 136 |
+
<img src="{inline_logo('logo.png')}" style="width: 100px; height: auto; object-fit: contain;">
|
| 137 |
<div style='font-weight:800;font-size:1.2rem; margin-top: 10px;'>ST_GeoMech_UCS</div>
|
| 138 |
<div style='color:#667085;'>Smart Thinking • Secure Access</div>
|
| 139 |
</div>
|
|
|
|
| 196 |
numcols = out.select_dtypes(include=[np.number]).columns
|
| 197 |
styler = (
|
| 198 |
out.style
|
| 199 |
+
.format({c: "{:.2f}" for c in numcols})
|
| 200 |
+
.set_properties(**{"text-align": "center"})
|
| 201 |
+
.set_table_styles(TABLE_CENTER_CSS)
|
| 202 |
)
|
| 203 |
st.dataframe(styler, use_container_width=True, hide_index=hide_index)
|
| 204 |
|
|
|
|
| 424 |
# =========================
|
| 425 |
st.sidebar.markdown(f"""
|
| 426 |
<div class="centered-container">
|
| 427 |
+
<img src="{inline_logo('logo.png')}" style="width: 100px; height: auto; object-fit: contain;">
|
| 428 |
<div style='font-weight:800;font-size:1.2rem;'>ST_GeoMech_UCS</div>
|
| 429 |
<div style='color:#667085;'>Real-Time UCS Tracking While Drilling</div>
|
| 430 |
</div>
|
|
|
|
| 433 |
|
| 434 |
# =========================
|
| 435 |
# Reusable Sticky Header Function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 436 |
# =========================
|
| 437 |
+
def sticky_header(title, message):
|
| 438 |
+
st.markdown(
|
| 439 |
+
f"""
|
| 440 |
+
<style>
|
| 441 |
+
.sticky-container {{
|
| 442 |
+
position: sticky;
|
| 443 |
+
top: 0;
|
| 444 |
+
background-color: white;
|
| 445 |
+
z-index: 100;
|
| 446 |
+
padding-top: 10px;
|
| 447 |
+
padding-bottom: 10px;
|
| 448 |
+
border-bottom: 1px solid #eee;
|
| 449 |
+
}}
|
| 450 |
+
</style>
|
| 451 |
+
<div class="sticky-container">
|
| 452 |
+
<h3>{title}</h3>
|
| 453 |
+
<p>{message}</p>
|
| 454 |
+
</div>
|
| 455 |
+
""",
|
| 456 |
+
unsafe_allow_html=True
|
| 457 |
+
)
|
|
|
|
|
|
|
| 458 |
|
| 459 |
# =========================
|
| 460 |
# INTRO
|
|
|
|
| 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 |
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 |
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 |
table = pd.DataFrame({
|
| 669 |
"Metric": ["# points","Pred min","Pred max","Pred mean","Pred std","OOR %"],
|
| 670 |
"Value": [sv["n"],
|
| 671 |
+
round(sv["pred_min"],2),
|
| 672 |
+
round(sv["pred_max"],2),
|
| 673 |
+
round(sv["pred_mean"],2),
|
| 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)
|