Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -27,36 +27,16 @@ COLORS = {"pred": "#1f77b4", "actual": "#f2b702", "ref": "#5a5a5a"}
|
|
| 27 |
# ---- Plot sizing controls (edit here) ----
|
| 28 |
CROSS_W = 500; CROSS_H = 500 # square cross-plot
|
| 29 |
TRACK_W = 400; TRACK_H = 950 # log-strip style (tall, slightly wider)
|
| 30 |
-
FONT_SZ
|
| 31 |
-
PLOT_COLS = [14, 0.3, 10]
|
| 32 |
-
with left:
|
| 33 |
-
st.markdown("<div class='align-right'>", unsafe_allow_html=True)
|
| 34 |
-
st.plotly_chart(
|
| 35 |
-
cross_plot(df[TARGET], df["UCS_Pred"]),
|
| 36 |
-
use_container_width=False,
|
| 37 |
-
config={"displayModeBar": False, "scrollZoom": True}
|
| 38 |
-
)
|
| 39 |
-
st.markdown("</div>", unsafe_allow_html=True)
|
| 40 |
-
|
| 41 |
-
# spacer: leave empty
|
| 42 |
-
|
| 43 |
-
with right:
|
| 44 |
-
st.plotly_chart(
|
| 45 |
-
track_plot(df, include_actual=True), # or False on the Prediction page
|
| 46 |
-
use_container_width=False,
|
| 47 |
-
config={"displayModeBar": False, "scrollZoom": True}
|
| 48 |
-
)
|
| 49 |
-
|
| 50 |
|
| 51 |
# =========================
|
| 52 |
# Page / CSS
|
| 53 |
# =========================
|
| 54 |
st.set_page_config(page_title="ST_GeoMech_UCS", page_icon="logo.png", layout="wide")
|
| 55 |
st.markdown("<style>header, footer{visibility:hidden !important;}</style>", unsafe_allow_html=True)
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
unsafe_allow_html=True
|
| 59 |
-
)
|
| 60 |
st.markdown(
|
| 61 |
"""
|
| 62 |
<style>
|
|
@@ -180,6 +160,15 @@ def _nice_tick0(xmin: float, step: int = 100) -> float:
|
|
| 180 |
return xmin
|
| 181 |
return step * math.floor(xmin / step)
|
| 182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
# ---------- Plot builders ----------
|
| 184 |
def cross_plot(actual, pred):
|
| 185 |
a = pd.Series(actual).astype(float)
|
|
@@ -237,7 +226,8 @@ def track_plot(df, include_actual=True):
|
|
| 237 |
x_lo, x_hi = float(x_series.min()), float(x_series.max())
|
| 238 |
x_pad = 0.03 * (x_hi - x_lo if x_hi > x_lo else 1.0)
|
| 239 |
xmin, xmax = x_lo - x_pad, x_hi + x_pad
|
| 240 |
-
tick0 = _nice_tick0(xmin, step=100)
|
|
|
|
| 241 |
|
| 242 |
fig = go.Figure()
|
| 243 |
fig.add_trace(go.Scatter(
|
|
@@ -267,7 +257,7 @@ def track_plot(df, include_actual=True):
|
|
| 267 |
fig.update_xaxes(
|
| 268 |
title_text="<b>UCS (psi)</b>", side="top", range=[xmin, xmax],
|
| 269 |
ticks="outside", tickformat=",.0f",
|
| 270 |
-
tickmode="
|
| 271 |
showline=True, linewidth=1.2, linecolor="#444", mirror=True,
|
| 272 |
showgrid=True, gridcolor="rgba(0,0,0,0.12)", automargin=True
|
| 273 |
)
|
|
@@ -422,16 +412,7 @@ if st.session_state.app_step == "dev":
|
|
| 422 |
df0 = next(iter(tmp.values()))
|
| 423 |
st.sidebar.caption(f"**Data loaded:** {st.session_state.dev_file_name} • {df0.shape[0]} rows × {df0.shape[1]} cols")
|
| 424 |
|
| 425 |
-
|
| 426 |
-
preview_modal(read_book_bytes(st.session_state.dev_file_bytes))
|
| 427 |
-
st.session_state.dev_preview = True
|
| 428 |
-
|
| 429 |
-
run = st.sidebar.button("Run Model", type="primary", use_container_width=True)
|
| 430 |
-
# always available nav
|
| 431 |
-
if st.sidebar.button("Proceed to Validation ▶", use_container_width=True): st.session_state.app_step="validate"; st.rerun()
|
| 432 |
-
if st.sidebar.button("Proceed to Prediction ▶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 433 |
-
|
| 434 |
-
# ---- Pinned helper at the very top of the page ----
|
| 435 |
helper_top = st.container()
|
| 436 |
with helper_top:
|
| 437 |
st.subheader("Case Building (Development)")
|
|
@@ -442,6 +423,15 @@ if st.session_state.app_step == "dev":
|
|
| 442 |
else:
|
| 443 |
st.write("**Upload your data to build a case, then run the model to review development performance.**")
|
| 444 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 445 |
if run and st.session_state.dev_file_bytes:
|
| 446 |
book = read_book_bytes(st.session_state.dev_file_bytes)
|
| 447 |
sh_train = find_sheet(book, ["Train","Training","training2","train","training"])
|
|
@@ -467,11 +457,13 @@ if st.session_state.app_step == "dev":
|
|
| 467 |
c1.metric("R²", f"{m['R2']:.4f}"); c2.metric("RMSE", f"{m['RMSE']:.4f}"); c3.metric("MAE", f"{m['MAE']:.4f}")
|
| 468 |
left, spacer, right = st.columns(PLOT_COLS)
|
| 469 |
with left:
|
|
|
|
| 470 |
st.plotly_chart(
|
| 471 |
cross_plot(df[TARGET], df["UCS_Pred"]),
|
| 472 |
use_container_width=False,
|
| 473 |
config={"displayModeBar": False, "scrollZoom": True}
|
| 474 |
)
|
|
|
|
| 475 |
with right:
|
| 476 |
st.plotly_chart(
|
| 477 |
track_plot(df, include_actual=True),
|
|
@@ -497,15 +489,16 @@ if st.session_state.app_step == "validate":
|
|
| 497 |
if book:
|
| 498 |
df0 = next(iter(book.values()))
|
| 499 |
st.sidebar.caption(f"**Data loaded:** {up.name} • {df0.shape[0]} rows × {df0.shape[1]} cols")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 500 |
if st.sidebar.button("Preview data", use_container_width=True, disabled=(up is None)):
|
| 501 |
preview_modal(read_book_bytes(up.getvalue()))
|
| 502 |
go_btn = st.sidebar.button("Predict", type="primary", use_container_width=True)
|
| 503 |
if st.sidebar.button("⬅ Back to Case Building", use_container_width=True): st.session_state.app_step="dev"; st.rerun()
|
| 504 |
if st.sidebar.button("Proceed to Prediction ▶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 505 |
|
| 506 |
-
st.subheader("Validate the Model")
|
| 507 |
-
st.write("Upload a dataset with the same **features** and **UCS** to evaluate performance.")
|
| 508 |
-
|
| 509 |
if go_btn and up is not None:
|
| 510 |
book = read_book_bytes(up.getvalue())
|
| 511 |
name = find_sheet(book, ["Validation","Validate","validation2","Val","val"]) or list(book.keys())[0]
|
|
@@ -532,11 +525,13 @@ if st.session_state.app_step == "validate":
|
|
| 532 |
|
| 533 |
left, spacer, right = st.columns(PLOT_COLS)
|
| 534 |
with left:
|
|
|
|
| 535 |
st.plotly_chart(
|
| 536 |
cross_plot(st.session_state.results["Validate"][TARGET],
|
| 537 |
st.session_state.results["Validate"]["UCS_Pred"]),
|
| 538 |
use_container_width=False, config={"displayModeBar": False, "scrollZoom": True}
|
| 539 |
)
|
|
|
|
| 540 |
with right:
|
| 541 |
st.plotly_chart(
|
| 542 |
track_plot(st.session_state.results["Validate"], include_actual=True),
|
|
|
|
| 27 |
# ---- Plot sizing controls (edit here) ----
|
| 28 |
CROSS_W = 500; CROSS_H = 500 # square cross-plot
|
| 29 |
TRACK_W = 400; TRACK_H = 950 # log-strip style (tall, slightly wider)
|
| 30 |
+
FONT_SZ = 13
|
| 31 |
+
PLOT_COLS = [14, 0.3, 10] # 3-column band: left • spacer • right
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
# =========================
|
| 34 |
# Page / CSS
|
| 35 |
# =========================
|
| 36 |
st.set_page_config(page_title="ST_GeoMech_UCS", page_icon="logo.png", layout="wide")
|
| 37 |
st.markdown("<style>header, footer{visibility:hidden !important;}</style>", unsafe_allow_html=True)
|
| 38 |
+
# helper class to right-align the cross-plot inside its column
|
| 39 |
+
st.markdown("<style>.align-right{display:flex;justify-content:flex-end;width:100%;}</style>", unsafe_allow_html=True)
|
|
|
|
|
|
|
| 40 |
st.markdown(
|
| 41 |
"""
|
| 42 |
<style>
|
|
|
|
| 160 |
return xmin
|
| 161 |
return step * math.floor(xmin / step)
|
| 162 |
|
| 163 |
+
def _nice_dtick(xmin: float, xmax: float) -> int:
|
| 164 |
+
width = max(xmax - xmin, 1.0)
|
| 165 |
+
candidates = [50, 100, 200, 250, 500, 1000]
|
| 166 |
+
for dt in candidates:
|
| 167 |
+
n = width / dt
|
| 168 |
+
if 5 <= n <= 12:
|
| 169 |
+
return dt
|
| 170 |
+
return 100
|
| 171 |
+
|
| 172 |
# ---------- Plot builders ----------
|
| 173 |
def cross_plot(actual, pred):
|
| 174 |
a = pd.Series(actual).astype(float)
|
|
|
|
| 226 |
x_lo, x_hi = float(x_series.min()), float(x_series.max())
|
| 227 |
x_pad = 0.03 * (x_hi - x_lo if x_hi > x_lo else 1.0)
|
| 228 |
xmin, xmax = x_lo - x_pad, x_hi + x_pad
|
| 229 |
+
tick0 = _nice_tick0(xmin, step=100)
|
| 230 |
+
dtick = _nice_dtick(xmin, xmax)
|
| 231 |
|
| 232 |
fig = go.Figure()
|
| 233 |
fig.add_trace(go.Scatter(
|
|
|
|
| 257 |
fig.update_xaxes(
|
| 258 |
title_text="<b>UCS (psi)</b>", side="top", range=[xmin, xmax],
|
| 259 |
ticks="outside", tickformat=",.0f",
|
| 260 |
+
tickmode="linear", tick0=tick0, dtick=dtick,
|
| 261 |
showline=True, linewidth=1.2, linecolor="#444", mirror=True,
|
| 262 |
showgrid=True, gridcolor="rgba(0,0,0,0.12)", automargin=True
|
| 263 |
)
|
|
|
|
| 412 |
df0 = next(iter(tmp.values()))
|
| 413 |
st.sidebar.caption(f"**Data loaded:** {st.session_state.dev_file_name} • {df0.shape[0]} rows × {df0.shape[1]} cols")
|
| 414 |
|
| 415 |
+
# ---- Pinned helper at the very top of the page (before preview call) ----
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 416 |
helper_top = st.container()
|
| 417 |
with helper_top:
|
| 418 |
st.subheader("Case Building (Development)")
|
|
|
|
| 423 |
else:
|
| 424 |
st.write("**Upload your data to build a case, then run the model to review development performance.**")
|
| 425 |
|
| 426 |
+
# preview modal call AFTER helper, so helper stays pinned above
|
| 427 |
+
if st.sidebar.button("Preview data", use_container_width=True, disabled=not st.session_state.dev_file_loaded):
|
| 428 |
+
preview_modal(read_book_bytes(st.session_state.dev_file_bytes))
|
| 429 |
+
st.session_state.dev_preview = True
|
| 430 |
+
|
| 431 |
+
run = st.sidebar.button("Run Model", type="primary", use_container_width=True)
|
| 432 |
+
if st.sidebar.button("Proceed to Validation ▶", use_container_width=True): st.session_state.app_step="validate"; st.rerun()
|
| 433 |
+
if st.sidebar.button("Proceed to Prediction ▶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 434 |
+
|
| 435 |
if run and st.session_state.dev_file_bytes:
|
| 436 |
book = read_book_bytes(st.session_state.dev_file_bytes)
|
| 437 |
sh_train = find_sheet(book, ["Train","Training","training2","train","training"])
|
|
|
|
| 457 |
c1.metric("R²", f"{m['R2']:.4f}"); c2.metric("RMSE", f"{m['RMSE']:.4f}"); c3.metric("MAE", f"{m['MAE']:.4f}")
|
| 458 |
left, spacer, right = st.columns(PLOT_COLS)
|
| 459 |
with left:
|
| 460 |
+
st.markdown("<div class='align-right'>", unsafe_allow_html=True)
|
| 461 |
st.plotly_chart(
|
| 462 |
cross_plot(df[TARGET], df["UCS_Pred"]),
|
| 463 |
use_container_width=False,
|
| 464 |
config={"displayModeBar": False, "scrollZoom": True}
|
| 465 |
)
|
| 466 |
+
st.markdown("</div>", unsafe_allow_html=True)
|
| 467 |
with right:
|
| 468 |
st.plotly_chart(
|
| 469 |
track_plot(df, include_actual=True),
|
|
|
|
| 489 |
if book:
|
| 490 |
df0 = next(iter(book.values()))
|
| 491 |
st.sidebar.caption(f"**Data loaded:** {up.name} • {df0.shape[0]} rows × {df0.shape[1]} cols")
|
| 492 |
+
|
| 493 |
+
st.subheader("Validate the Model")
|
| 494 |
+
st.write("Upload a dataset with the same **features** and **UCS** to evaluate performance.")
|
| 495 |
+
|
| 496 |
if st.sidebar.button("Preview data", use_container_width=True, disabled=(up is None)):
|
| 497 |
preview_modal(read_book_bytes(up.getvalue()))
|
| 498 |
go_btn = st.sidebar.button("Predict", type="primary", use_container_width=True)
|
| 499 |
if st.sidebar.button("⬅ Back to Case Building", use_container_width=True): st.session_state.app_step="dev"; st.rerun()
|
| 500 |
if st.sidebar.button("Proceed to Prediction ▶", use_container_width=True): st.session_state.app_step="predict"; st.rerun()
|
| 501 |
|
|
|
|
|
|
|
|
|
|
| 502 |
if go_btn and up is not None:
|
| 503 |
book = read_book_bytes(up.getvalue())
|
| 504 |
name = find_sheet(book, ["Validation","Validate","validation2","Val","val"]) or list(book.keys())[0]
|
|
|
|
| 525 |
|
| 526 |
left, spacer, right = st.columns(PLOT_COLS)
|
| 527 |
with left:
|
| 528 |
+
st.markdown("<div class='align-right'>", unsafe_allow_html=True)
|
| 529 |
st.plotly_chart(
|
| 530 |
cross_plot(st.session_state.results["Validate"][TARGET],
|
| 531 |
st.session_state.results["Validate"]["UCS_Pred"]),
|
| 532 |
use_container_width=False, config={"displayModeBar": False, "scrollZoom": True}
|
| 533 |
)
|
| 534 |
+
st.markdown("</div>", unsafe_allow_html=True)
|
| 535 |
with right:
|
| 536 |
st.plotly_chart(
|
| 537 |
track_plot(st.session_state.results["Validate"], include_actual=True),
|