pedisynth-eval / app.py
rushankg's picture
Update app.py
97fde1f verified
# import gradio as gr
# import pandas as pd
# import os
# from pathlib import Path
# from datetime import datetime
# import random
# from PIL import Image
# # Global state
# state = {
# "session_active": False,
# "image_pairs": [],
# "current_index": 0,
# "evaluations": [],
# "doctor_name": "",
# }
# # Helper functions
# def get_image_files(folder_path):
# """Get all image files from a folder."""
# valid_extensions = {'.jpg', '.jpeg', '.png', '.gif'}
# files = {}
# if os.path.exists(folder_path):
# for file in os.listdir(folder_path):
# if Path(file).suffix.lower() in valid_extensions:
# files[file] = file
# return files
# def create_image_pairs():
# """Create paired images from roentgen and pedisynth folders."""
# roentgen_files = get_image_files("roentgen")
# pedisynth_files = get_image_files("pedisynth")
# pairs = []
# # Match files by exact filename across folders
# for filename in roentgen_files:
# if filename in pedisynth_files:
# # Randomly decide which image goes left and which goes right
# is_roentgen_left = random.choice([True, False])
# # Extract condition by removing the file extension and last part (number)
# name_without_ext = Path(filename).stem
# parts = name_without_ext.rsplit(' ', 1)
# condition = parts[0] if len(parts) > 1 else name_without_ext
# pairs.append({
# 'roentgen': filename,
# 'pedisynth': filename,
# 'condition': condition,
# 'base_name': name_without_ext,
# 'roentgen_left': is_roentgen_left
# })
# # Randomize order
# random.shuffle(pairs)
# return pairs
# def load_image(folder, filename):
# """Load image from folder."""
# filepath = os.path.join(folder, filename)
# try:
# return Image.open(filepath)
# except Exception as e:
# print(f"Error loading image {filename}: {e}")
# return None
# def save_evaluations(evaluations, doctor_name):
# """Save evaluations to CSV."""
# df = pd.DataFrame(evaluations)
# timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
# filename = f"evaluations_{doctor_name}_{timestamp}.csv"
# # Save to outputs folder if it exists, otherwise current directory
# output_dir = "outputs"
# os.makedirs(output_dir, exist_ok=True)
# filepath = os.path.join(output_dir, filename)
# df.to_csv(filepath, index=False)
# return filepath, filename
# def start_session(doctor_name):
# """Start a new evaluation session."""
# if not doctor_name.strip():
# return (gr.update(visible=False), "Please enter your name to start a session.")
# state["doctor_name"] = doctor_name
# state["image_pairs"] = create_image_pairs()
# state["session_active"] = True
# state["current_index"] = 0
# state["evaluations"] = []
# if not state["image_pairs"]:
# return (gr.update(visible=False), "No image pairs found. Please ensure both roentgen/ and pedisynth/ folders have matching images.")
# return (gr.update(visible=True), "")
# def get_preference_a():
# """Handle preference for option A."""
# if not state["session_active"]:
# return None, None, "Session not active."
# current_pair = state["image_pairs"][state["current_index"]]
# preferred_source = state["current_left_source"]
# state["evaluations"].append({
# 'timestamp': datetime.now().isoformat(),
# 'condition': current_pair['condition'],
# 'base_name': current_pair['base_name'],
# 'preference': preferred_source.capitalize(),
# 'doctor': state["doctor_name"]
# })
# state["current_index"] += 1
# if state["current_index"] >= len(state["image_pairs"]):
# state["session_active"] = False
# return None, None, "βœ… Evaluation complete! All images have been reviewed."
# current_pair = state["image_pairs"][state["current_index"]]
# if current_pair['roentgen_left']:
# left_image = load_image("roentgen", current_pair['roentgen'])
# right_image = load_image("pedisynth", current_pair['pedisynth'])
# state["current_left_source"] = "roentgen"
# state["current_right_source"] = "pedisynth"
# else:
# left_image = load_image("pedisynth", current_pair['pedisynth'])
# right_image = load_image("roentgen", current_pair['roentgen'])
# state["current_left_source"] = "pedisynth"
# state["current_right_source"] = "roentgen"
# progress = f"Image {state['current_index'] + 1} of {len(state['image_pairs'])} | Condition: {current_pair['condition']}"
# return left_image, right_image, progress
# def get_preference_b():
# """Handle preference for option B."""
# if not state["session_active"]:
# return None, None, "Session not active."
# current_pair = state["image_pairs"][state["current_index"]]
# preferred_source = state["current_right_source"]
# state["evaluations"].append({
# 'timestamp': datetime.now().isoformat(),
# 'condition': current_pair['condition'],
# 'base_name': current_pair['base_name'],
# 'preference': preferred_source.capitalize(),
# 'doctor': state["doctor_name"]
# })
# state["current_index"] += 1
# if state["current_index"] >= len(state["image_pairs"]):
# state["session_active"] = False
# return None, None, "βœ… Evaluation complete! All images have been reviewed."
# current_pair = state["image_pairs"][state["current_index"]]
# if current_pair['roentgen_left']:
# left_image = load_image("roentgen", current_pair['roentgen'])
# right_image = load_image("pedisynth", current_pair['pedisynth'])
# state["current_left_source"] = "roentgen"
# state["current_right_source"] = "pedisynth"
# else:
# left_image = load_image("pedisynth", current_pair['pedisynth'])
# right_image = load_image("roentgen", current_pair['roentgen'])
# state["current_left_source"] = "pedisynth"
# state["current_right_source"] = "roentgen"
# progress = f"Image {state['current_index'] + 1} of {len(state['image_pairs'])} | Condition: {current_pair['condition']}"
# return left_image, right_image, progress
# def display_first_pair():
# """Display the first image pair after session starts."""
# if not state["session_active"]:
# return None, None, ""
# current_pair = state["image_pairs"][state["current_index"]]
# if current_pair['roentgen_left']:
# left_image = load_image("roentgen", current_pair['roentgen'])
# right_image = load_image("pedisynth", current_pair['pedisynth'])
# state["current_left_source"] = "roentgen"
# state["current_right_source"] = "pedisynth"
# else:
# left_image = load_image("pedisynth", current_pair['pedisynth'])
# right_image = load_image("roentgen", current_pair['roentgen'])
# state["current_left_source"] = "pedisynth"
# state["current_right_source"] = "roentgen"
# progress = f"Image {state['current_index'] + 1} of {len(state['image_pairs'])} | Condition: {current_pair['condition']}"
# return left_image, right_image, progress
# def end_session():
# """End the session and return CSV file."""
# if not state["evaluations"]:
# return None, "No evaluations recorded."
# filepath, filename = save_evaluations(state["evaluations"], state["doctor_name"])
# state["session_active"] = False
# state["current_index"] = 0
# state["evaluations"] = []
# return filepath, f"βœ… Evaluations saved as: {filename}"
# # Gradio interface
# with gr.Blocks(title="X-Ray Quality Evaluation") as demo:
# gr.Markdown("# πŸ₯ X-Ray Quality Evaluation System")
# gr.Markdown("**Pairwise Preference Test for Synthetic X-Ray Images**")
# with gr.Row():
# with gr.Column(scale=1):
# gr.Markdown("### Start Session")
# doctor_name_input = gr.Textbox(
# label="Enter your name:",
# placeholder="Dr. Smith"
# )
# start_btn = gr.Button("Start Session", variant="primary", size="lg")
# with gr.Column(scale=1):
# gr.Markdown("### Results")
# download_btn = gr.Button("End Session & Download Results", variant="primary", size="lg")
# result_message = gr.Textbox(
# label="Status",
# interactive=False,
# show_label=True
# )
# error_section = gr.Textbox(
# label="Message",
# interactive=False,
# show_label=True,
# value=""
# )
# # Image comparison section
# with gr.Group(visible=False) as eval_section:
# gr.Markdown("### Compare Images")
# progress_text = gr.Textbox(
# label="Progress",
# interactive=False,
# show_label=True
# )
# with gr.Row():
# image_a = gr.Image(
# label="Option A",
# show_label=True,
# type="pil"
# )
# image_b = gr.Image(
# label="Option B",
# show_label=True,
# type="pil"
# )
# with gr.Row():
# pref_a = gr.Button("πŸ‘ˆ Prefer Option A", size="lg")
# pref_b = gr.Button("πŸ‘‰ Prefer Option B", size="lg")
# # File download
# download_file = gr.File(
# label="CSV Results",
# visible=False
# )
# # Event handlers
# start_btn.click(
# start_session,
# inputs=doctor_name_input,
# outputs=[eval_section, error_section]
# ).then(
# display_first_pair,
# outputs=[image_a, image_b, progress_text]
# )
# pref_a.click(
# get_preference_a,
# outputs=[image_a, image_b, progress_text]
# )
# pref_b.click(
# get_preference_b,
# outputs=[image_a, image_b, progress_text]
# )
# download_btn.click(
# end_session,
# outputs=[download_file, result_message]
# )
# if __name__ == "__main__":
# demo.launch()
import gradio as gr
import pandas as pd
import os
from pathlib import Path
from datetime import datetime
import random
from PIL import Image
# Global state
state = {
"session_active": False,
"image_pairs": [],
"current_index": 0,
"evaluations": [],
"doctor_name": "",
}
# Helper functions
def get_image_files(folder_path):
"""Get all image files from a folder."""
valid_extensions = {'.jpg', '.jpeg', '.png', '.gif'}
files = {}
if os.path.exists(folder_path):
for file in os.listdir(folder_path):
if Path(file).suffix.lower() in valid_extensions:
files[file] = file
return files
def create_image_pairs():
"""Create paired images from roentgen and pedisynth folders."""
roentgen_files = get_image_files("roentgen")
pedisynth_files = get_image_files("pedisynth")
pairs = []
# Match files by exact filename across folders
for filename in roentgen_files:
if filename in pedisynth_files:
# Randomly decide which image goes left and which goes right
is_roentgen_left = random.choice([True, False])
# Extract condition by removing the file extension and last part (number)
name_without_ext = Path(filename).stem
parts = name_without_ext.rsplit(' ', 1)
condition = parts[0] if len(parts) > 1 else name_without_ext
pairs.append({
'roentgen': filename,
'pedisynth': filename,
'condition': condition,
'base_name': name_without_ext,
'roentgen_left': is_roentgen_left
})
# Randomize order
random.shuffle(pairs)
return pairs
def load_image(folder, filename):
"""Load image from folder."""
filepath = os.path.join(folder, filename)
try:
return Image.open(filepath)
except Exception as e:
print(f"Error loading image {filename}: {e}")
return None
def save_evaluations(evaluations, doctor_name):
"""Save evaluations to CSV."""
df = pd.DataFrame(evaluations)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"evaluations_{doctor_name}_{timestamp}.csv"
# Save to outputs folder if it exists, otherwise current directory
output_dir = "outputs"
os.makedirs(output_dir, exist_ok=True)
filepath = os.path.join(output_dir, filename)
df.to_csv(filepath, index=False)
return filepath, filename
def start_session(doctor_name):
"""Start a new evaluation session."""
if not doctor_name.strip():
return (gr.update(visible=False), "Please enter your name to start a session.")
state["doctor_name"] = doctor_name
state["image_pairs"] = create_image_pairs()
state["session_active"] = True
state["current_index"] = 0
state["evaluations"] = []
if not state["image_pairs"]:
return (gr.update(visible=False), "No image pairs found. Please ensure both roentgen/ and pedisynth/ folders have matching images.")
return (gr.update(visible=True), "")
def get_preference_a():
"""Handle preference for option A."""
if not state["session_active"]:
return None, None, "Session not active."
current_pair = state["image_pairs"][state["current_index"]]
preferred_source = state["current_left_source"]
state["evaluations"].append({
'timestamp': datetime.now().isoformat(),
'condition': current_pair['condition'],
'base_name': current_pair['base_name'],
'preference': preferred_source.capitalize(),
'doctor': state["doctor_name"]
})
state["current_index"] += 1
if state["current_index"] >= len(state["image_pairs"]):
state["session_active"] = False
return None, None, "βœ… Evaluation complete! All images have been reviewed."
current_pair = state["image_pairs"][state["current_index"]]
if current_pair['roentgen_left']:
left_image = load_image("roentgen", current_pair['roentgen'])
right_image = load_image("pedisynth", current_pair['pedisynth'])
state["current_left_source"] = "roentgen"
state["current_right_source"] = "pedisynth"
else:
left_image = load_image("pedisynth", current_pair['pedisynth'])
right_image = load_image("roentgen", current_pair['roentgen'])
state["current_left_source"] = "pedisynth"
state["current_right_source"] = "roentgen"
progress = f"Image {state['current_index'] + 1} of {len(state['image_pairs'])} | Condition: {current_pair['condition']}"
return left_image, right_image, progress
def get_preference_b():
"""Handle preference for option B."""
if not state["session_active"]:
return None, None, "Session not active."
current_pair = state["image_pairs"][state["current_index"]]
preferred_source = state["current_right_source"]
state["evaluations"].append({
'timestamp': datetime.now().isoformat(),
'condition': current_pair['condition'],
'base_name': current_pair['base_name'],
'preference': preferred_source.capitalize(),
'doctor': state["doctor_name"]
})
state["current_index"] += 1
if state["current_index"] >= len(state["image_pairs"]):
state["session_active"] = False
return None, None, "βœ… Evaluation complete! All images have been reviewed."
current_pair = state["image_pairs"][state["current_index"]]
if current_pair['roentgen_left']:
left_image = load_image("roentgen", current_pair['roentgen'])
right_image = load_image("pedisynth", current_pair['pedisynth'])
state["current_left_source"] = "roentgen"
state["current_right_source"] = "pedisynth"
else:
left_image = load_image("pedisynth", current_pair['pedisynth'])
right_image = load_image("roentgen", current_pair['roentgen'])
state["current_left_source"] = "pedisynth"
state["current_right_source"] = "roentgen"
progress = f"Image {state['current_index'] + 1} of {len(state['image_pairs'])} | Condition: {current_pair['condition']}"
return left_image, right_image, progress
def display_first_pair():
"""Display the first image pair after session starts."""
if not state["session_active"]:
return None, None, ""
current_pair = state["image_pairs"][state["current_index"]]
if current_pair['roentgen_left']:
left_image = load_image("roentgen", current_pair['roentgen'])
right_image = load_image("pedisynth", current_pair['pedisynth'])
state["current_left_source"] = "roentgen"
state["current_right_source"] = "pedisynth"
else:
left_image = load_image("pedisynth", current_pair['pedisynth'])
right_image = load_image("roentgen", current_pair['roentgen'])
state["current_left_source"] = "pedisynth"
state["current_right_source"] = "roentgen"
progress = f"Image {state['current_index'] + 1} of {len(state['image_pairs'])} | Condition: {current_pair['condition']}"
return left_image, right_image, progress
def end_session():
"""End the session and return CSV file for download."""
if not state["evaluations"]:
return None, "No evaluations recorded."
filepath, filename = save_evaluations(state["evaluations"], state["doctor_name"])
state["session_active"] = False
state["current_index"] = 0
state["evaluations"] = []
return filepath, f"βœ… Evaluations ready to download: {filename}"
# Gradio interface
with gr.Blocks(title="X-Ray Quality Evaluation") as demo:
gr.Markdown("# πŸ₯ X-Ray Quality Evaluation System")
gr.Markdown("**Pairwise Preference Test for Synthetic X-Ray Images**")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Start Session")
doctor_name_input = gr.Textbox(
label="Enter your name:",
placeholder="Dr. Smith"
)
start_btn = gr.Button("Start Session", variant="primary", size="lg")
with gr.Column(scale=1):
gr.Markdown("### Results")
download_btn = gr.Button("End Session & Download Results", variant="primary", size="lg")
result_message = gr.Textbox(
label="Status",
interactive=False,
show_label=True
)
error_section = gr.Textbox(
label="Message",
interactive=False,
show_label=True,
value=""
)
# Image comparison section
with gr.Group(visible=False) as eval_section:
gr.Markdown("### Compare Images")
progress_text = gr.Textbox(
label="Progress",
interactive=False,
show_label=True
)
with gr.Row():
image_a = gr.Image(
label="Option A",
show_label=True,
type="pil"
)
image_b = gr.Image(
label="Option B",
show_label=True,
type="pil"
)
with gr.Row():
pref_a = gr.Button("πŸ‘ˆ Prefer Option A", size="lg")
pref_b = gr.Button("πŸ‘‰ Prefer Option B", size="lg")
# File download
download_file = gr.File(
label="CSV Results",
interactive=False
)
# Event handlers
start_btn.click(
start_session,
inputs=doctor_name_input,
outputs=[eval_section, error_section]
).then(
display_first_pair,
outputs=[image_a, image_b, progress_text]
)
pref_a.click(
get_preference_a,
outputs=[image_a, image_b, progress_text]
)
pref_b.click(
get_preference_b,
outputs=[image_a, image_b, progress_text]
)
download_btn.click(
end_session,
outputs=[download_file, result_message]
)
if __name__ == "__main__":
demo.launch()