hmgill commited on
Commit
1c3a61d
Β·
verified Β·
1 Parent(s): 666f8a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -34
app.py CHANGED
@@ -5,7 +5,7 @@ import glob
5
  import torch
6
  import sys
7
  import builtins
8
- import pandas as pd # <--- NEW: Required for reading Excel
9
  from pathlib import Path
10
  from PIL import Image
11
 
@@ -47,24 +47,32 @@ def load_models():
47
  load_models()
48
 
49
  # --- Helper: Read Excel Sheets ---
50
- def load_excel_data(filepath):
51
- """Reads the generated Excel file and returns DataFrames for each known sheet."""
52
- empty = pd.DataFrame()
 
 
 
 
 
53
  if not filepath or not os.path.exists(filepath):
54
- return empty, empty, empty
55
 
56
  try:
57
- xls = pd.ExcelFile(filepath)
 
58
 
59
- # safely get sheets if they exist, else return empty
60
- morph = pd.read_excel(xls, "Morphology") if "Morphology" in xls.sheet_names else empty
61
- spatial = pd.read_excel(xls, "Spatial") if "Spatial" in xls.sheet_names else empty
62
- relational = pd.read_excel(xls, "Relational") if "Relational" in xls.sheet_names else empty
63
 
64
  return morph, spatial, relational
65
  except Exception as e:
66
- print(f"Error reading excel: {e}")
67
- return empty, empty, empty
 
 
68
 
69
 
70
  # --- Core Analysis Function ---
@@ -72,14 +80,15 @@ async def run_analysis(image_path_str, user_prompt, progress=gr.Progress()):
72
  """
73
  Async generator that runs the agent and yields updates to the UI.
74
  """
75
- # Initialize empty outputs
76
- empty_df = pd.DataFrame()
77
 
 
78
  if not image_path_str:
79
- yield "⚠️ Please upload an image first.", None, None, empty_df, empty_df, empty_df
80
  return
81
 
82
- # Clean up previous runs
83
  for f in glob.glob("/tmp/out_*.png") + glob.glob("/tmp/data_*.npz") + glob.glob("/tmp/*.xlsx"):
84
  try:
85
  os.remove(f)
@@ -88,7 +97,6 @@ async def run_analysis(image_path_str, user_prompt, progress=gr.Progress()):
88
 
89
  image_path = Path(image_path_str)
90
 
91
- # 1. Setup Dependencies
92
  deps = AnalysisDeps(
93
  sam_model=MODEL_CACHE["model"],
94
  sam_processor=MODEL_CACHE["processor"],
@@ -97,7 +105,6 @@ async def run_analysis(image_path_str, user_prompt, progress=gr.Progress()):
97
  pixel_size_microns=None
98
  )
99
 
100
- # 2. Initialize Runner
101
  runner = InMemoryRunner(agent=root_agent, app_name="cellemetry_demo")
102
  session = await runner.session_service.create_session(
103
  app_name="cellemetry_demo",
@@ -105,7 +112,6 @@ async def run_analysis(image_path_str, user_prompt, progress=gr.Progress()):
105
  state=deps.to_state_dict()
106
  )
107
 
108
- # 3. Prepare Content
109
  image_bytes = image_path.read_bytes()
110
  content = types.Content(
111
  role="user",
@@ -115,11 +121,11 @@ async def run_analysis(image_path_str, user_prompt, progress=gr.Progress()):
115
  ]
116
  )
117
 
118
- # 4. Stream Execution
119
  logs = [f"πŸš€ Starting analysis on {MODEL_CACHE['device']}..."]
120
 
121
- # Helper to yield current state
122
- def yield_state(current_logs, imgs=None, rpt=None, m=empty_df, s=empty_df, r=empty_df):
123
  return "\n\n".join(current_logs), imgs, rpt, m, s, r
124
 
125
  yield yield_state(logs)
@@ -158,20 +164,22 @@ async def run_analysis(image_path_str, user_prompt, progress=gr.Progress()):
158
  yield yield_state(logs)
159
  return
160
 
161
- # 5. Retrieve Final Results
162
- logs.append("\n🏁 **Analysis Complete.** Processing results...")
163
  yield yield_state(logs)
164
 
165
  output_images = glob.glob("/tmp/out_*.png")
166
  excel_files = glob.glob("/tmp/*.xlsx")
167
  report_file = excel_files[0] if excel_files else None
168
 
169
- # Parse Excel Data
170
- df_morph, df_spatial, df_rel = load_excel_data(report_file)
171
 
172
- logs.append(f"\nπŸ“‹ Found {len(output_images)} maps and generated report tables.")
173
-
174
- # Final Yield with all data
 
 
175
  yield yield_state(logs, output_images, report_file, df_morph, df_spatial, df_rel)
176
 
177
 
@@ -189,7 +197,6 @@ with gr.Blocks(title="Cellemetry Agent") as demo:
189
  )
190
  run_btn = gr.Button("πŸ§ͺ Run Analysis", variant="primary", size="lg")
191
 
192
- # Moved download button here for better visibility
193
  gr.Markdown("### πŸ“₯ Download Results")
194
  file_output = gr.File(label="Full Excel Report")
195
 
@@ -203,15 +210,14 @@ with gr.Blocks(title="Cellemetry Agent") as demo:
203
 
204
  with gr.Tab("Data Tables"):
205
  gr.Markdown("### πŸ“ Morphology Stats")
206
- tbl_morph = gr.Dataframe(label="Morphology", interactive=False)
207
 
208
  gr.Markdown("### πŸ“ Spatial Stats")
209
- tbl_spatial = gr.Dataframe(label="Spatial", interactive=False)
210
 
211
  gr.Markdown("### πŸ”— Relational Stats")
212
- tbl_rel = gr.Dataframe(label="Relational", interactive=False)
213
 
214
- # Connect the Async Function
215
  run_btn.click(
216
  fn=run_analysis,
217
  inputs=[img_input, prompt_input],
 
5
  import torch
6
  import sys
7
  import builtins
8
+ import pandas as pd
9
  from pathlib import Path
10
  from PIL import Image
11
 
 
47
  load_models()
48
 
49
  # --- Helper: Read Excel Sheets ---
50
+ def load_excel_data(filepath, logs):
51
+ """
52
+ Reads the generated Excel file and returns DataFrames for each known sheet.
53
+ Logs errors directly to the UI list if reading fails.
54
+ """
55
+ # Create a default "No Data" dataframe to show instead of broken tables
56
+ placeholder = pd.DataFrame({"Status": ["No Data Available"]})
57
+
58
  if not filepath or not os.path.exists(filepath):
59
+ return placeholder, placeholder, placeholder
60
 
61
  try:
62
+ # EXPLICITLY use openpyxl engine to avoid read errors
63
+ xls = pd.ExcelFile(filepath, engine='openpyxl')
64
 
65
+ # Load sheets if they exist, else return placeholder
66
+ morph = pd.read_excel(xls, "Morphology") if "Morphology" in xls.sheet_names else placeholder
67
+ spatial = pd.read_excel(xls, "Spatial") if "Spatial" in xls.sheet_names else placeholder
68
+ relational = pd.read_excel(xls, "Relational") if "Relational" in xls.sheet_names else placeholder
69
 
70
  return morph, spatial, relational
71
  except Exception as e:
72
+ error_msg = f"⚠️ Error reading Excel report: {str(e)}"
73
+ print(error_msg)
74
+ logs.append(f"\n{error_msg}")
75
+ return placeholder, placeholder, placeholder
76
 
77
 
78
  # --- Core Analysis Function ---
 
80
  """
81
  Async generator that runs the agent and yields updates to the UI.
82
  """
83
+ # Initialize "Waiting" dataframes so UI looks clean at start
84
+ waiting_df = pd.DataFrame({"Status": ["Waiting for analysis..."]})
85
 
86
+ # 0. Validate Input
87
  if not image_path_str:
88
+ yield "⚠️ Please upload an image first.", None, None, waiting_df, waiting_df, waiting_df
89
  return
90
 
91
+ # 1. Cleanup & Setup
92
  for f in glob.glob("/tmp/out_*.png") + glob.glob("/tmp/data_*.npz") + glob.glob("/tmp/*.xlsx"):
93
  try:
94
  os.remove(f)
 
97
 
98
  image_path = Path(image_path_str)
99
 
 
100
  deps = AnalysisDeps(
101
  sam_model=MODEL_CACHE["model"],
102
  sam_processor=MODEL_CACHE["processor"],
 
105
  pixel_size_microns=None
106
  )
107
 
 
108
  runner = InMemoryRunner(agent=root_agent, app_name="cellemetry_demo")
109
  session = await runner.session_service.create_session(
110
  app_name="cellemetry_demo",
 
112
  state=deps.to_state_dict()
113
  )
114
 
 
115
  image_bytes = image_path.read_bytes()
116
  content = types.Content(
117
  role="user",
 
121
  ]
122
  )
123
 
124
+ # 2. Start Stream
125
  logs = [f"πŸš€ Starting analysis on {MODEL_CACHE['device']}..."]
126
 
127
+ # Helper to yield state easily
128
+ def yield_state(current_logs, imgs=None, rpt=None, m=waiting_df, s=waiting_df, r=waiting_df):
129
  return "\n\n".join(current_logs), imgs, rpt, m, s, r
130
 
131
  yield yield_state(logs)
 
164
  yield yield_state(logs)
165
  return
166
 
167
+ # 3. Retrieve Results
168
+ logs.append("\n🏁 **Analysis Complete.** Processing report...")
169
  yield yield_state(logs)
170
 
171
  output_images = glob.glob("/tmp/out_*.png")
172
  excel_files = glob.glob("/tmp/*.xlsx")
173
  report_file = excel_files[0] if excel_files else None
174
 
175
+ # 4. Parse Excel (Pass logs to catch errors)
176
+ df_morph, df_spatial, df_rel = load_excel_data(report_file, logs)
177
 
178
+ if report_file:
179
+ logs.append(f"πŸ“‹ Generated report tables successfully.")
180
+ else:
181
+ logs.append(f"⚠️ No report file generated.")
182
+
183
  yield yield_state(logs, output_images, report_file, df_morph, df_spatial, df_rel)
184
 
185
 
 
197
  )
198
  run_btn = gr.Button("πŸ§ͺ Run Analysis", variant="primary", size="lg")
199
 
 
200
  gr.Markdown("### πŸ“₯ Download Results")
201
  file_output = gr.File(label="Full Excel Report")
202
 
 
210
 
211
  with gr.Tab("Data Tables"):
212
  gr.Markdown("### πŸ“ Morphology Stats")
213
+ tbl_morph = gr.Dataframe(label="Morphology", interactive=False, wrap=True)
214
 
215
  gr.Markdown("### πŸ“ Spatial Stats")
216
+ tbl_spatial = gr.Dataframe(label="Spatial", interactive=False, wrap=True)
217
 
218
  gr.Markdown("### πŸ”— Relational Stats")
219
+ tbl_rel = gr.Dataframe(label="Relational", interactive=False, wrap=True)
220
 
 
221
  run_btn.click(
222
  fn=run_analysis,
223
  inputs=[img_input, prompt_input],