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.'

Files changed (1) hide show
  1. app.py +35 -30
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.eval()
 
 
 
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
- uploaded_file = StringIO(file_contents)
299
- uploaded_file.name = selected_sample
 
 
300
  st.success(f"✅ Loaded sample: {selected_sample}")
301
- except Exception as e:
302
  st.error(f"Error loading sample: {e}")
303
  else:
304
  st.info("No sample data available")
305
 
306
  # Update session state
307
- if uploaded_file is not None:
308
- st.session_state['uploaded_file'] = uploaded_file
309
- st.session_state['filename'] = uploaded_file.name
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
- # Inference button
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
- # Get file data
342
- uploaded_file = st.session_state['uploaded_file']
343
- filename = st.session_state['filename']
344
-
345
- # Read file content
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", use_column_width=True)
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