MedVQA / medvqa /competitions /gi-2025 /submission_portal.py
SushantGautam's picture
Add submission portal and task scripts for MediaEval Medico 2025 challenge
5e6ba6a
import sys
import subprocess
import gradio as gr
import json
from datetime import datetime, timezone
from huggingface_hub import upload_file, snapshot_download
import shutil
import os
import glob
from pathlib import Path
from huggingface_hub import whoami
import platform
print(subprocess.check_output(
[sys.executable, "-m", "pip", "list"]).decode("utf-8"))
print({
"python": platform.python_version(),
"os": platform.system(),
"platform": platform.platform(),
"arch": platform.machine()
})
print("Account token used to connect to HuggingFace: ", whoami()['name'])
SUBMISSION_REPO = "SimulaMet/medvqa-submissions"
hub_path = None
submissions = None
last_submission_update_time = datetime.now(timezone.utc)
def refresh_submissions():
global hub_path, submissions, last_submission_update_time
if hub_path and Path(hub_path).exists():
shutil.rmtree(hub_path, ignore_errors=True)
print("Deleted existing submissions")
hub_path = snapshot_download(
repo_type="dataset", repo_id=SUBMISSION_REPO, allow_patterns=['**/*.json'])
print("Downloaded submissions to:", hub_path)
if not os.path.exists(hub_path):
os.makedirs(hub_path)
all_jsons = glob.glob(hub_path + "/**/*.json", recursive=True)
print("json_files count:", len(all_jsons))
submissions = []
for file in all_jsons:
file_ = file.split("/")[-1]
username, sub_timestamp, task = file_.replace(
".json", "").split("-_-_-")
json_data = json.load(open(file))
public_score = json.dumps(json_data.get("public_scores", {}))
submissions.append({"user": username, "task": task, "public_score": public_score,
"submitted_time": sub_timestamp})
last_submission_update_time = datetime.now(timezone.utc)
return hub_path
hub_path = refresh_submissions()
hub_dir = hub_path.split("snapshot")[0] + "snapshot"
def time_ago(submitted_time):
return str(datetime.fromtimestamp(int(submitted_time), tz=timezone.utc)) + " UTC"
def filter_submissions(task_type, search_query):
if search_query == "":
filtered = [s for s in submissions if task_type ==
"all" or s["task"] == task_type]
else:
filtered = [s for s in submissions if (
task_type == "all" or s["task"] == task_type) and search_query.lower() in s["user"].lower()]
return [{"user": s["user"], "task": s["task"], "public_score": s["public_score"], "submitted_time": time_ago(s["submitted_time"])} for s in filtered]
def display_submissions(task_type="all", search_query=""):
if submissions is None or ((datetime.now(timezone.utc) - last_submission_update_time).total_seconds() > 3600):
refresh_submissions()
filtered_submissions = filter_submissions(task_type, search_query)
return [[s["user"], s["task"], s["submitted_time"], s["public_score"]] for s in filtered_submissions]
def add_submission(file):
global submissions
try:
with open(file, 'r', encoding='utf-8') as f:
data = json.load(f)
filename = os.path.basename(file)
username, sub_timestamp, task = filename.replace(
".json", "").split("-_-_-")
submission_time = datetime.fromtimestamp(
int(sub_timestamp), tz=timezone.utc)
assert task in ["task1", "task2"], "Invalid task type"
assert len(username) > 0, "Invalid username"
assert submission_time < datetime.now(
timezone.utc), "Invalid submission time"
upload_file(
repo_type="dataset",
path_or_fileobj=file,
path_in_repo=task + "/" + filename,
repo_id=SUBMISSION_REPO
)
refresh_submissions()
return "πŸ’ͺπŸ†πŸŽ‰ Submissions registered successfully to the system!"
except Exception as e:
return f"❌ Error adding submission: {e}"
def refresh_page():
return "Pong! Submission server is alive! 😊"
# Define Gradio Interface
with gr.Blocks(title="🌟ImageCLEFmed-MEDVQA-GI 2025 Submissions 🌟") as demo:
gr.Markdown("""
# 🌟 Welcome to the official submission portal for the [MEDVQA-GI 2025](https://www.imageclef.org/2025/medical/vqa) challenge! πŸ₯🧬
### πŸš€ [**Challenge Homepage** in GitHub](https://github.com/simula/ImageCLEFmed-MEDVQA-GI-2025) | πŸ“ [**Register** for ImageCLEF 2025](https://www.imageclef.org/2025#registration) | πŸ“… [**Competition Schedule**](https://github.com/simula/ImageCLEFmed-MEDVQA-GI-2025#:~:text=Schedule) | πŸ“¦ [**Submission Instructions**](https://github.com/simula/ImageCLEFmed-MEDVQA-GI-2025#-submission-system)πŸ”₯πŸ”₯
### πŸ“₯ [**Available Datasets**](https://github.com/simula/ImageCLEFmed-MEDVQA-GI-2025#-data) | πŸ’‘ [Tasks & Example Training **Notebooks**](https://github.com/simula/ImageCLEFmed-MEDVQA-GI-2025#-task-descriptions)πŸ’₯πŸ’₯
""")
with gr.Tab("View Submissions"):
gr.Markdown("### Filter and Search Submissions")
with gr.Row():
with gr.Column(scale=1):
task_type_dropdown = gr.Dropdown(
choices=["all", "task1", "task2"],
value="all",
label="Task Type"
)
search_box = gr.Textbox(
label="Search by Username",
placeholder="Enter username..."
)
with gr.Column(scale=6):
output_table = gr.Dataframe(
headers=["User", "Task", "Submitted Time", "Public Score"],
interactive=False,
wrap=True,
column_widths=["100px", "50px", "80px", "200px"],
label="Submissions"
)
task_type_dropdown.change(
fn=display_submissions,
inputs=[task_type_dropdown, search_box],
outputs=output_table
)
search_box.change(
fn=display_submissions,
inputs=[task_type_dropdown, search_box],
outputs=output_table
)
gr.Markdown(
f'''
πŸ”„ Last refreshed: {last_submission_update_time.strftime('%Y-%m-%d %H:%M:%S')} UTC | πŸ“Š Total Submissions: {len(submissions)}
πŸ’¬ For any questions or issues, [contact the organizers](https://github.com/simula/ImageCLEFmed-MEDVQA-GI-2025#-organizers) or check the documentation in the [GitHub repo](https://github.com/simula/ImageCLEFmed-MEDVQA-GI-2025). Good luck and thank you for contributing to medical AI research! πŸ’ͺπŸ€–πŸŒ
''')
with gr.Tab("Upload Submission", visible=False):
file_input = gr.File(label="Upload JSON", file_types=[".json"])
upload_output = gr.Textbox(label="Upload Result")
file_input.upload(fn=add_submission,
inputs=file_input, outputs=upload_output)
with gr.Tab("Refresh API", visible=False):
refresh_button = gr.Button("Refresh")
status_output = gr.Textbox(label="Status")
refresh_button.click(fn=refresh_page, inputs=[], outputs=status_output)
demo.load(lambda: display_submissions("all", ""),
inputs=[], outputs=output_table)
demo.launch()