Deevyankar commited on
Commit
9472d3b
·
verified ·
1 Parent(s): 834dfa1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -25
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py (FULL REPLACEMENT - openpyxl engine forced + HF stable upload + Grade>=C pass)
2
  import streamlit as st
3
  import pandas as pd
4
  import numpy as np
@@ -21,17 +21,14 @@ def grade_pass_fail(g):
21
  return "Unknown"
22
  g = str(g).strip().upper()
23
 
24
- # Explicit FAIL
25
  if g.startswith(("D", "E", "F")):
26
  return "Fail"
27
 
28
- # C- is FAIL, all other C variants are PASS
29
  if g.startswith("C"):
30
  if g == "C-" or g.startswith("C-"):
31
  return "Fail"
32
  return "Pass"
33
 
34
- # A/B (with any +/-) are PASS
35
  if g.startswith(("A", "B")):
36
  return "Pass"
37
 
@@ -155,10 +152,8 @@ def make_fail_reason_hints(df: pd.DataFrame, component_cols: list[str]) -> pd.Da
155
 
156
 
157
  # -----------------------------
158
- # Upload (HF stable via session_state)
159
  # -----------------------------
160
- uploaded = st.file_uploader("Upload Excel (.xlsx)", type=["xlsx"], key="uploader")
161
-
162
  if "file_bytes" not in st.session_state:
163
  st.session_state["file_bytes"] = None
164
  if "file_name" not in st.session_state:
@@ -166,21 +161,43 @@ if "file_name" not in st.session_state:
166
  if "sheet_names" not in st.session_state:
167
  st.session_state["sheet_names"] = None
168
 
169
- # Persist bytes across reruns
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  if uploaded is not None:
171
- st.session_state["file_bytes"] = uploaded.getvalue()
172
- st.session_state["file_name"] = uploaded.name
173
- st.session_state["sheet_names"] = None # reset on new upload
 
 
 
174
 
175
- if st.session_state["file_bytes"] is None:
 
 
 
176
  st.info("Upload an Excel file to begin.")
177
  st.stop()
178
 
179
- file_bytes = st.session_state["file_bytes"]
180
-
181
- # Quick signature check (xlsx is a zip, starts with PK)
182
- if not (len(file_bytes) >= 2 and file_bytes[:2] == b"PK"):
183
- st.error("This does not look like a valid .xlsx file. Please re-export/download as Excel (.xlsx) and upload again.")
184
  st.stop()
185
 
186
  # Load sheet names (FORCE openpyxl)
@@ -225,7 +242,7 @@ df = add_consistency(df, component_cols)
225
  df = make_fail_reason_hints(df, component_cols)
226
 
227
  # -----------------------------
228
- # Sidebar: "Power BI pages"
229
  # -----------------------------
230
  st.sidebar.header("Perspective")
231
  view = st.sidebar.radio(
@@ -273,15 +290,15 @@ def executive_view(d: pd.DataFrame):
273
 
274
  with left:
275
  st.subheader("Grade Distribution")
276
- grade_counts = d["Grade"].value_counts(dropna=False).reset_index()
277
- grade_counts.columns = ["Grade", "Count"]
278
- st.plotly_chart(px.bar(grade_counts, x="Grade", y="Count"), use_container_width=True)
279
 
280
  with right:
281
  st.subheader("Pass/Fail Distribution")
282
- pf_counts = d["PassFail"].value_counts(dropna=False).reset_index()
283
- pf_counts.columns = ["Status", "Count"]
284
- st.plotly_chart(px.pie(pf_counts, names="Status", values="Count"), use_container_width=True)
285
 
286
  st.subheader("Hidden Patterns (Quick Signals)")
287
  c1, c2, c3 = st.columns(3)
@@ -375,7 +392,6 @@ def export_view(d: pd.DataFrame):
375
  st.download_button("⬇️ Download Cleaned Data (CSV)", clean_csv, file_name="cleaned_marks_with_passfail.csv", mime="text/csv")
376
 
377
 
378
- # Render view
379
  if view == "Executive (Management)":
380
  executive_view(filtered)
381
  elif view == "Risk & Intervention":
 
1
+ # app.py (FINAL FULL REPLACEMENT - no NoneType crashes + openpyxl forced + Grade>=C pass)
2
  import streamlit as st
3
  import pandas as pd
4
  import numpy as np
 
21
  return "Unknown"
22
  g = str(g).strip().upper()
23
 
 
24
  if g.startswith(("D", "E", "F")):
25
  return "Fail"
26
 
 
27
  if g.startswith("C"):
28
  if g == "C-" or g.startswith("C-"):
29
  return "Fail"
30
  return "Pass"
31
 
 
32
  if g.startswith(("A", "B")):
33
  return "Pass"
34
 
 
152
 
153
 
154
  # -----------------------------
155
+ # Session state init
156
  # -----------------------------
 
 
157
  if "file_bytes" not in st.session_state:
158
  st.session_state["file_bytes"] = None
159
  if "file_name" not in st.session_state:
 
161
  if "sheet_names" not in st.session_state:
162
  st.session_state["sheet_names"] = None
163
 
164
+ # Reset button (helps a lot on HF reruns)
165
+ topc1, topc2 = st.columns([1, 3])
166
+ with topc1:
167
+ if st.button("🔄 Reset upload"):
168
+ st.session_state["file_bytes"] = None
169
+ st.session_state["file_name"] = None
170
+ st.session_state["sheet_names"] = None
171
+ st.rerun()
172
+
173
+ with topc2:
174
+ if st.session_state["file_name"]:
175
+ st.info(f"Current file loaded: {st.session_state['file_name']}")
176
+
177
+ # -----------------------------
178
+ # Upload
179
+ # -----------------------------
180
+ uploaded = st.file_uploader("Upload Excel (.xlsx)", type=["xlsx"], key="uploader")
181
+
182
+ # On upload, store bytes
183
  if uploaded is not None:
184
+ fb = uploaded.getvalue()
185
+ # fb can *rarely* be None/empty on buggy reruns; guard it
186
+ if fb:
187
+ st.session_state["file_bytes"] = fb
188
+ st.session_state["file_name"] = uploaded.name
189
+ st.session_state["sheet_names"] = None
190
 
191
+ # Re-check bytes RIGHT BEFORE use
192
+ file_bytes = st.session_state.get("file_bytes", None)
193
+
194
+ if file_bytes is None or not isinstance(file_bytes, (bytes, bytearray)) or len(file_bytes) == 0:
195
  st.info("Upload an Excel file to begin.")
196
  st.stop()
197
 
198
+ # Signature check for XLSX (zip => PK)
199
+ if len(file_bytes) < 2 or file_bytes[:2] != b"PK":
200
+ st.error("This does not look like a valid .xlsx file. Please Save As Excel Workbook (.xlsx) and upload again.")
 
 
201
  st.stop()
202
 
203
  # Load sheet names (FORCE openpyxl)
 
242
  df = make_fail_reason_hints(df, component_cols)
243
 
244
  # -----------------------------
245
+ # Sidebar: Views + Filters
246
  # -----------------------------
247
  st.sidebar.header("Perspective")
248
  view = st.sidebar.radio(
 
290
 
291
  with left:
292
  st.subheader("Grade Distribution")
293
+ gc = d["Grade"].value_counts(dropna=False).reset_index()
294
+ gc.columns = ["Grade", "Count"]
295
+ st.plotly_chart(px.bar(gc, x="Grade", y="Count"), use_container_width=True)
296
 
297
  with right:
298
  st.subheader("Pass/Fail Distribution")
299
+ pc = d["PassFail"].value_counts(dropna=False).reset_index()
300
+ pc.columns = ["Status", "Count"]
301
+ st.plotly_chart(px.pie(pc, names="Status", values="Count"), use_container_width=True)
302
 
303
  st.subheader("Hidden Patterns (Quick Signals)")
304
  c1, c2, c3 = st.columns(3)
 
392
  st.download_button("⬇️ Download Cleaned Data (CSV)", clean_csv, file_name="cleaned_marks_with_passfail.csv", mime="text/csv")
393
 
394
 
 
395
  if view == "Executive (Management)":
396
  executive_view(filtered)
397
  elif view == "Risk & Intervention":