Spaces:
Sleeping
Sleeping
devjas1
commited on
Commit
·
c8f5637
1
Parent(s):
df6f1ab
(FIX/UI): stabalize app.py — deprecation, sample-data run, layout jitter
Browse files- Replace deprecated 'st.image(use_column_width= ...)' with 'use_container_width=True'
- Fix 'Run Analysis' no-op after selecting Sample Data:
• Stop storing open file handles (StringIO) in 'session_state'
• Persist raw 'input_text' + 'filename' instead; compute inference ready from 'input_text'
• Add stable widget keys ('upload_txt','sample_select','run_btn')
- Reduce right-column reflow/jitter:
• 'use_container_width()' on plot image
• stable keys reduce tab-induced redraw instability
NOTES:
- No changes to model APIs or weights path logic.
- Keeps earlier portability improvements(Agg backend, dual import, 'logits.detach()') intact.'
app.py
CHANGED
|
@@ -107,7 +107,10 @@ def load_model(model_name):
|
|
| 107 |
# Load weights
|
| 108 |
state_dict = torch.load(model_path, map_location="cpu")
|
| 109 |
model.load_state_dict(state_dict, strict=False)
|
| 110 |
-
model
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
return model, True
|
| 113 |
|
|
@@ -205,7 +208,8 @@ def init_session_state():
|
|
| 205 |
defaults = {
|
| 206 |
'status_message': "Ready to analyze polymer spectra 🔬",
|
| 207 |
'status_type': "info",
|
| 208 |
-
'uploaded_file': None,
|
|
|
|
| 209 |
'filename': None,
|
| 210 |
'inference_run_once': False,
|
| 211 |
'x_raw': None,
|
|
@@ -278,36 +282,44 @@ def main():
|
|
| 278 |
uploaded_file = st.file_uploader(
|
| 279 |
"Upload Raman spectrum (.txt)",
|
| 280 |
type="txt",
|
| 281 |
-
help="Upload a text file with wavenumber and intensity columns"
|
|
|
|
| 282 |
)
|
| 283 |
|
| 284 |
if uploaded_file:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 285 |
st.success(f"✅ Loaded: {uploaded_file.name}")
|
| 286 |
|
| 287 |
with tab2:
|
| 288 |
sample_files = get_sample_files()
|
| 289 |
if sample_files:
|
| 290 |
sample_options = ["-- Select Sample --"] + [f.name for f in sample_files]
|
| 291 |
-
selected_sample = st.selectbox("Choose sample spectrum:", sample_options)
|
| 292 |
|
| 293 |
if selected_sample != "-- Select Sample --":
|
| 294 |
selected_path = Path(SAMPLE_DATA_DIR) / selected_sample
|
| 295 |
try:
|
| 296 |
with open(selected_path, "r", encoding="utf-8") as f:
|
| 297 |
file_contents = f.read()
|
| 298 |
-
|
| 299 |
-
|
|
|
|
|
|
|
| 300 |
st.success(f"✅ Loaded sample: {selected_sample}")
|
| 301 |
-
except
|
| 302 |
st.error(f"Error loading sample: {e}")
|
| 303 |
else:
|
| 304 |
st.info("No sample data available")
|
| 305 |
|
| 306 |
# Update session state
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
st.session_state['
|
| 310 |
-
st.session_state['status_message'] = f"📁 File '{uploaded_file.name}' ready for analysis"
|
| 311 |
st.session_state['status_type'] = "success"
|
| 312 |
|
| 313 |
# Status display
|
|
@@ -325,27 +337,20 @@ def main():
|
|
| 325 |
# Load model
|
| 326 |
model, model_loaded = load_model(model_choice)
|
| 327 |
|
| 328 |
-
#
|
| 329 |
-
inference_ready = (
|
| 330 |
-
'uploaded_file' in st.session_state and
|
| 331 |
-
st.session_state['uploaded_file'] is not None and
|
| 332 |
-
model is not None
|
| 333 |
-
)
|
| 334 |
|
| 335 |
if not model_loaded:
|
| 336 |
st.warning("⚠️ Model weights not available - using demo mode")
|
| 337 |
|
| 338 |
-
if st.button("▶️ Run Analysis", disabled=not inference_ready, type="primary"):
|
| 339 |
if inference_ready:
|
| 340 |
try:
|
| 341 |
-
#
|
| 342 |
-
|
| 343 |
-
filename = st.session_state
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
uploaded_file.seek(0)
|
| 347 |
-
raw_data = uploaded_file.read()
|
| 348 |
-
raw_text = raw_data.decode("utf-8") if isinstance(raw_data, bytes) else raw_data
|
| 349 |
|
| 350 |
# Parse spectrum
|
| 351 |
with st.spinner("Parsing spectrum data..."):
|
|
@@ -386,7 +391,7 @@ def main():
|
|
| 386 |
# Create and display plot
|
| 387 |
try:
|
| 388 |
spectrum_plot = create_spectrum_plot(x_raw, y_raw, y_resampled)
|
| 389 |
-
st.image(spectrum_plot, caption="Spectrum Preprocessing Results",
|
| 390 |
except Exception as e:
|
| 391 |
st.warning(f"Could not generate plot: {e}")
|
| 392 |
|
|
@@ -462,10 +467,10 @@ def main():
|
|
| 462 |
|
| 463 |
st.markdown("**Spectrum Statistics**")
|
| 464 |
st.json({
|
| 465 |
-
"Original Length": len(x_raw),
|
| 466 |
"Resampled Length": TARGET_LEN,
|
| 467 |
-
"Wavenumber Range": f"{min(x_raw):.1f} - {max(x_raw):.1f} cm⁻¹",
|
| 468 |
-
"Intensity Range": f"{min(y_raw):.1f} - {max(y_raw):.1f}",
|
| 469 |
"Model Confidence": confidence_desc
|
| 470 |
})
|
| 471 |
|
|
|
|
| 107 |
# Load weights
|
| 108 |
state_dict = torch.load(model_path, map_location="cpu")
|
| 109 |
model.load_state_dict(state_dict, strict=False)
|
| 110 |
+
if model is not None:
|
| 111 |
+
model.eval()
|
| 112 |
+
else:
|
| 113 |
+
raise ValueError("Model is not loaded. Please check the model configuration or weights.")
|
| 114 |
|
| 115 |
return model, True
|
| 116 |
|
|
|
|
| 208 |
defaults = {
|
| 209 |
'status_message': "Ready to analyze polymer spectra 🔬",
|
| 210 |
'status_type': "info",
|
| 211 |
+
'uploaded_file': None, # legacy; kept for compatibility
|
| 212 |
+
'input_text': None, # ←←← NEW: canonical store for spectrum text
|
| 213 |
'filename': None,
|
| 214 |
'inference_run_once': False,
|
| 215 |
'x_raw': None,
|
|
|
|
| 282 |
uploaded_file = st.file_uploader(
|
| 283 |
"Upload Raman spectrum (.txt)",
|
| 284 |
type="txt",
|
| 285 |
+
help="Upload a text file with wavenumber and intensity columns",
|
| 286 |
+
key="upload_text"
|
| 287 |
)
|
| 288 |
|
| 289 |
if uploaded_file:
|
| 290 |
+
# Read now and persist raw text; avoid holding open buffers in session_state
|
| 291 |
+
raw = uploaded_file.read()
|
| 292 |
+
text = raw.decode("utf-8") if isinstance(raw, bytes) else raw
|
| 293 |
+
st.session_state['input_text'] = text
|
| 294 |
+
st.session_state['filename'] = uploaded_file.name
|
| 295 |
+
st.session_state['uploaded_file'] = None # avoid stale buffers
|
| 296 |
st.success(f"✅ Loaded: {uploaded_file.name}")
|
| 297 |
|
| 298 |
with tab2:
|
| 299 |
sample_files = get_sample_files()
|
| 300 |
if sample_files:
|
| 301 |
sample_options = ["-- Select Sample --"] + [f.name for f in sample_files]
|
| 302 |
+
selected_sample = st.selectbox("Choose sample spectrum:", sample_options, key="sample_select")
|
| 303 |
|
| 304 |
if selected_sample != "-- Select Sample --":
|
| 305 |
selected_path = Path(SAMPLE_DATA_DIR) / selected_sample
|
| 306 |
try:
|
| 307 |
with open(selected_path, "r", encoding="utf-8") as f:
|
| 308 |
file_contents = f.read()
|
| 309 |
+
# Persist raw text + name; no open file handles in session_state
|
| 310 |
+
st.session_state['input_text'] = file_contents
|
| 311 |
+
st.session_state['filename'] = selected_sample
|
| 312 |
+
st.session_state['uploaded_file'] = None
|
| 313 |
st.success(f"✅ Loaded sample: {selected_sample}")
|
| 314 |
+
except (FileNotFoundError, IOError) as e:
|
| 315 |
st.error(f"Error loading sample: {e}")
|
| 316 |
else:
|
| 317 |
st.info("No sample data available")
|
| 318 |
|
| 319 |
# Update session state
|
| 320 |
+
# If we captured text via either tab, reflect readiness in status
|
| 321 |
+
if st.session_state.get('input_text'):
|
| 322 |
+
st.session_state['status_message'] = f"📁 File '{st.session_state.get('filename', '(unnamed)')}' ready for analysis"
|
|
|
|
| 323 |
st.session_state['status_type'] = "success"
|
| 324 |
|
| 325 |
# Status display
|
|
|
|
| 337 |
# Load model
|
| 338 |
model, model_loaded = load_model(model_choice)
|
| 339 |
|
| 340 |
+
# Ready if we have cached text and a model instance
|
| 341 |
+
inference_ready = bool(st.session_state.get('input_text')) and (model is not None)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
|
| 343 |
if not model_loaded:
|
| 344 |
st.warning("⚠️ Model weights not available - using demo mode")
|
| 345 |
|
| 346 |
+
if st.button("▶️ Run Analysis", disabled=not inference_ready, type="primary", key="run_btn"):
|
| 347 |
if inference_ready:
|
| 348 |
try:
|
| 349 |
+
# Use persisted text + filename (works for uploads and samples)
|
| 350 |
+
raw_text = st.session_state.get('input_text')
|
| 351 |
+
filename = st.session_state.get('filename') or "unknown.txt"
|
| 352 |
+
if not raw_text:
|
| 353 |
+
raise ValueError("No input text available. Please upload or select a sample.")
|
|
|
|
|
|
|
|
|
|
| 354 |
|
| 355 |
# Parse spectrum
|
| 356 |
with st.spinner("Parsing spectrum data..."):
|
|
|
|
| 391 |
# Create and display plot
|
| 392 |
try:
|
| 393 |
spectrum_plot = create_spectrum_plot(x_raw, y_raw, y_resampled)
|
| 394 |
+
st.image(spectrum_plot, caption="Spectrum Preprocessing Results", use_container_width=True)
|
| 395 |
except Exception as e:
|
| 396 |
st.warning(f"Could not generate plot: {e}")
|
| 397 |
|
|
|
|
| 467 |
|
| 468 |
st.markdown("**Spectrum Statistics**")
|
| 469 |
st.json({
|
| 470 |
+
"Original Length": len(x_raw) if x_raw is not None else 0,
|
| 471 |
"Resampled Length": TARGET_LEN,
|
| 472 |
+
"Wavenumber Range": f"{min(x_raw):.1f} - {max(x_raw):.1f} cm⁻¹" if x_raw is not None else "N/A",
|
| 473 |
+
"Intensity Range": f"{min(y_raw):.1f} - {max(y_raw):.1f}" if y_raw is not None else "N/A",
|
| 474 |
"Model Confidence": confidence_desc
|
| 475 |
})
|
| 476 |
|