rushankg commited on
Commit
b6ae48f
Β·
verified Β·
1 Parent(s): c697283

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -163
app.py CHANGED
@@ -1,30 +1,19 @@
1
- import streamlit as st
2
  import pandas as pd
3
  import os
4
  from pathlib import Path
5
  from datetime import datetime
6
  import random
7
  from PIL import Image
8
- import io
9
 
10
- # Configure page
11
- st.set_page_config(
12
- page_title="X-Ray Quality Evaluation",
13
- page_icon="πŸ₯",
14
- layout="wide"
15
- )
16
-
17
- # Initialize session state
18
- if "session_active" not in st.session_state:
19
- st.session_state.session_active = False
20
- if "image_pairs" not in st.session_state:
21
- st.session_state.image_pairs = []
22
- if "current_index" not in st.session_state:
23
- st.session_state.current_index = 0
24
- if "evaluations" not in st.session_state:
25
- st.session_state.evaluations = []
26
- if "doctor_name" not in st.session_state:
27
- st.session_state.doctor_name = ""
28
 
29
  # Helper functions
30
  def get_image_files(folder_path):
@@ -78,7 +67,7 @@ def load_image(folder, filename):
78
  try:
79
  return Image.open(filepath)
80
  except Exception as e:
81
- st.error(f"Error loading image {filename}: {e}")
82
  return None
83
 
84
  def save_evaluations(evaluations, doctor_name):
@@ -95,153 +84,169 @@ def save_evaluations(evaluations, doctor_name):
95
  df.to_csv(filepath, index=False)
96
  return filepath, filename
97
 
98
- # Main UI
99
- st.title("πŸ₯ X-Ray Quality Evaluation System")
100
- st.markdown("**Pairwise Preference Test for Synthetic X-Ray Images**")
 
 
 
 
 
 
 
 
 
 
 
 
101
 
102
- # Sidebar - Session management
103
- with st.sidebar:
104
- st.header("Session Control")
 
105
 
106
- if not st.session_state.session_active:
107
- doctor_name = st.text_input("Enter your name:", key="doc_input")
108
-
109
- if st.button("Start Session", type="primary"):
110
- if doctor_name.strip():
111
- st.session_state.doctor_name = doctor_name
112
- st.session_state.image_pairs = create_image_pairs()
113
- st.session_state.session_active = True
114
- st.session_state.current_index = 0
115
- st.session_state.evaluations = []
116
- st.rerun()
117
- else:
118
- st.error("Please enter your name to start a session.")
119
  else:
120
- st.success(f"βœ“ Session active for: {st.session_state.doctor_name}")
121
- progress = st.session_state.current_index / len(st.session_state.image_pairs)
122
- st.progress(progress)
123
- st.metric("Progress", f"{st.session_state.current_index}/{len(st.session_state.image_pairs)}")
124
-
125
- if st.button("End Session & Download Results", type="primary"):
126
- if st.session_state.evaluations:
127
- filepath, filename = save_evaluations(
128
- st.session_state.evaluations,
129
- st.session_state.doctor_name
130
- )
131
- st.success(f"βœ“ Results saved: {filename}")
132
-
133
- # Provide download link
134
- with open(filepath, 'r') as f:
135
- csv_data = f.read()
136
- st.download_button(
137
- label="Download CSV",
138
- data=csv_data,
139
- file_name=filename,
140
- mime="text/csv"
141
- )
142
- st.session_state.session_active = False
143
- st.rerun()
144
- else:
145
- st.warning("No evaluations recorded yet.")
146
 
147
- # Main content
148
- if not st.session_state.session_active:
149
- st.info("πŸ‘ˆ Enter your name in the sidebar and click 'Start Session' to begin.")
150
- else:
151
- if st.session_state.current_index >= len(st.session_state.image_pairs):
152
- st.success("βœ… Evaluation complete! All images have been reviewed.")
153
- if st.button("End Session & Download Results"):
154
- if st.session_state.evaluations:
155
- filepath, filename = save_evaluations(
156
- st.session_state.evaluations,
157
- st.session_state.doctor_name
158
- )
159
- st.success(f"Results saved: {filename}")
160
- with open(filepath, 'r') as f:
161
- csv_data = f.read()
162
- st.download_button(
163
- label="Download CSV",
164
- data=csv_data,
165
- file_name=filename,
166
- mime="text/csv"
167
- )
168
- st.session_state.session_active = False
169
- st.rerun()
170
- else:
171
- current_pair = st.session_state.image_pairs[st.session_state.current_index]
172
-
173
- st.subheading(f"Image {st.session_state.current_index + 1} of {len(st.session_state.image_pairs)}")
174
- st.write(f"**Condition:** {current_pair['condition']}")
175
-
176
- # Display images side by side (blinded - no labels about source)
177
- col1, col2 = st.columns(2)
178
-
179
- # Determine which image goes where
180
- if current_pair['roentgen_left']:
181
- left_image = load_image("roentgen", current_pair['roentgen'])
182
- right_image = load_image("pedisynth", current_pair['pedisynth'])
183
- left_source = "roentgen"
184
- right_source = "pedisynth"
185
- else:
186
- left_image = load_image("pedisynth", current_pair['pedisynth'])
187
- right_image = load_image("roentgen", current_pair['roentgen'])
188
- left_source = "pedisynth"
189
- right_source = "roentgen"
190
-
191
- with col1:
192
- st.write("### Option A")
193
- if left_image:
194
- st.image(left_image, use_column_width=True)
195
- else:
196
- st.error("Could not load image A")
197
-
198
- with col2:
199
- st.write("### Option B")
200
- if right_image:
201
- st.image(right_image, use_column_width=True)
202
- else:
203
- st.error("Could not load image B")
204
-
205
- # Preference selection
206
- st.markdown("---")
207
- st.write("**Which image is of better quality?**")
208
 
209
- col_a, col_b, col_equal = st.columns(3)
 
 
 
 
 
 
 
 
 
 
 
210
 
211
- with col_a:
212
- if st.button("πŸ‘ˆ Prefer Option A", use_container_width=True, key="btn_a"):
213
- preferred_source = left_source
214
- st.session_state.evaluations.append({
215
- 'timestamp': datetime.now().isoformat(),
216
- 'condition': current_pair['condition'],
217
- 'base_name': current_pair['base_name'],
218
- 'preference': preferred_source.capitalize(),
219
- 'doctor': st.session_state.doctor_name
220
- })
221
- st.session_state.current_index += 1
222
- st.rerun()
223
 
224
- with col_b:
225
- if st.button("πŸ‘‰ Prefer Option B", use_container_width=True, key="btn_b"):
226
- preferred_source = right_source
227
- st.session_state.evaluations.append({
228
- 'timestamp': datetime.now().isoformat(),
229
- 'condition': current_pair['condition'],
230
- 'base_name': current_pair['base_name'],
231
- 'preference': preferred_source.capitalize(),
232
- 'doctor': st.session_state.doctor_name
233
- })
234
- st.session_state.current_index += 1
235
- st.rerun()
236
 
237
- with col_equal:
238
- if st.button("↔️ Equal Quality", use_container_width=True, key="btn_equal"):
239
- st.session_state.evaluations.append({
240
- 'timestamp': datetime.now().isoformat(),
241
- 'condition': current_pair['condition'],
242
- 'base_name': current_pair['base_name'],
243
- 'preference': 'Equal',
244
- 'doctor': st.session_state.doctor_name
245
- })
246
- st.session_state.current_index += 1
247
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
  import pandas as pd
3
  import os
4
  from pathlib import Path
5
  from datetime import datetime
6
  import random
7
  from PIL import Image
 
8
 
9
+ # Global state
10
+ state = {
11
+ "session_active": False,
12
+ "image_pairs": [],
13
+ "current_index": 0,
14
+ "evaluations": [],
15
+ "doctor_name": "",
16
+ }
 
 
 
 
 
 
 
 
 
 
17
 
18
  # Helper functions
19
  def get_image_files(folder_path):
 
67
  try:
68
  return Image.open(filepath)
69
  except Exception as e:
70
+ print(f"Error loading image {filename}: {e}")
71
  return None
72
 
73
  def save_evaluations(evaluations, doctor_name):
 
84
  df.to_csv(filepath, index=False)
85
  return filepath, filename
86
 
87
+ def start_session(doctor_name):
88
+ """Start a new evaluation session."""
89
+ if not doctor_name.strip():
90
+ return (gr.update(visible=False), gr.update(visible=True), "Please enter your name to start a session.")
91
+
92
+ state["doctor_name"] = doctor_name
93
+ state["image_pairs"] = create_image_pairs()
94
+ state["session_active"] = True
95
+ state["current_index"] = 0
96
+ state["evaluations"] = []
97
+
98
+ if not state["image_pairs"]:
99
+ return (gr.update(visible=False), gr.update(visible=True), "No image pairs found. Please ensure both roentgen/ and pedisynth/ folders have matching images.")
100
+
101
+ return update_display()
102
 
103
+ def get_current_display():
104
+ """Get current image pair and metadata."""
105
+ if not state["session_active"] or state["current_index"] >= len(state["image_pairs"]):
106
+ return None, None, "", ""
107
 
108
+ current_pair = state["image_pairs"][state["current_index"]]
109
+
110
+ # Determine which image goes where
111
+ if current_pair['roentgen_left']:
112
+ left_image = load_image("roentgen", current_pair['roentgen'])
113
+ right_image = load_image("pedisynth", current_pair['pedisynth'])
114
+ state["current_left_source"] = "roentgen"
115
+ state["current_right_source"] = "pedisynth"
 
 
 
 
 
116
  else:
117
+ left_image = load_image("pedisynth", current_pair['pedisynth'])
118
+ right_image = load_image("roentgen", current_pair['roentgen'])
119
+ state["current_left_source"] = "pedisynth"
120
+ state["current_right_source"] = "roentgen"
121
+
122
+ condition = current_pair['condition']
123
+ progress = f"Image {state['current_index'] + 1} of {len(state['image_pairs'])}"
124
+
125
+ return left_image, right_image, condition, progress
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
+ def update_display():
128
+ """Update the display with current image pair."""
129
+ left_img, right_img, condition, progress = get_current_display()
130
+
131
+ if left_img is None:
132
+ # Session complete
133
+ state["session_active"] = False
134
+ return (
135
+ gr.update(visible=False),
136
+ gr.update(visible=True),
137
+ "βœ… Evaluation complete! All images have been reviewed."
138
+ )
139
+
140
+ return (
141
+ gr.update(visible=True, value=(left_img, right_img)),
142
+ gr.update(visible=True, value=f"{progress} | Condition: {condition}"),
143
+ ""
144
+ )
145
+
146
+
147
+
148
+ state["current_index"] += 1
149
+
150
+ return update_display()
151
+
152
+ def end_session():
153
+ """End the session and return CSV file."""
154
+ if not state["evaluations"]:
155
+ return None, "No evaluations recorded."
156
+
157
+ filepath, filename = save_evaluations(state["evaluations"], state["doctor_name"])
158
+
159
+ with open(filepath, 'rb') as f:
160
+ csv_data = f.read()
161
+
162
+ state["session_active"] = False
163
+ state["current_index"] = 0
164
+ state["evaluations"] = []
165
+
166
+ return filepath, f"βœ… Evaluations saved as: {filename}"
167
+
168
+ # Gradio interface
169
+ with gr.Blocks(title="X-Ray Quality Evaluation") as demo:
170
+ gr.Markdown("# πŸ₯ X-Ray Quality Evaluation System")
171
+ gr.Markdown("**Pairwise Preference Test for Synthetic X-Ray Images**")
172
+
173
+ with gr.Row():
174
+ with gr.Column(scale=1):
175
+ gr.Markdown("### Start Session")
176
+ doctor_name_input = gr.Textbox(
177
+ label="Enter your name:",
178
+ placeholder="Dr. Smith"
179
+ )
180
+ start_btn = gr.Button("Start Session", variant="primary", size="lg")
 
 
 
 
 
 
 
181
 
182
+ with gr.Column(scale=1):
183
+ gr.Markdown("### Results")
184
+ download_btn = gr.Button("End Session & Download Results", variant="primary", size="lg")
185
+ result_message = gr.Textbox(
186
+ label="Status",
187
+ interactive=False,
188
+ show_label=True
189
+ )
190
+
191
+ # Image comparison section
192
+ with gr.Group(visible=False) as eval_section:
193
+ gr.Markdown("### Compare Images")
194
 
195
+ progress_text = gr.Textbox(
196
+ label="Progress",
197
+ interactive=False,
198
+ show_label=True
199
+ )
 
 
 
 
 
 
 
200
 
201
+ image_display = gr.Image(
202
+ label="Options A (left) and B (right)",
203
+ show_label=True,
204
+ type="pil"
205
+ )
 
 
 
 
 
 
 
206
 
207
+ with gr.Row():
208
+ pref_a = gr.Button("πŸ‘ˆ Prefer Option A", size="lg")
209
+ pref_b = gr.Button("πŸ‘‰ Prefer Option B", size="lg")
210
+
211
+ error_section = gr.Textbox(
212
+ label="Message",
213
+ interactive=False,
214
+ show_label=True,
215
+ visible=True
216
+ )
217
+
218
+ # File download
219
+ download_file = gr.File(
220
+ label="CSV Results",
221
+ visible=False
222
+ )
223
+
224
+ # Event handlers
225
+ start_btn.click(
226
+ start_session,
227
+ inputs=doctor_name_input,
228
+ outputs=[eval_section, error_section, result_message]
229
+ ).then(
230
+ update_display,
231
+ outputs=[image_display, progress_text, error_section]
232
+ )
233
+
234
+ pref_a.click(
235
+ record_preference,
236
+ inputs=gr.State("A"),
237
+ outputs=[image_display, progress_text, error_section]
238
+ )
239
+
240
+ pref_b.click(
241
+ record_preference,
242
+ inputs=gr.State("B"),
243
+ outputs=[image_display, progress_text, error_section]
244
+ )
245
+
246
+ download_btn.click(
247
+ end_session,
248
+ outputs=[download_file, result_message]
249
+ )
250
+
251
+ if __name__ == "__main__":
252
+ demo.launch()