import pandas as pd import gradio as gr from gradio_leaderboard import Leaderboard from utils import fetch_hf_results, show_output_box from constants import ( ASSAY_LIST, ASSAY_RENAME, ASSAY_EMOJIS, ASSAY_DESCRIPTION, EXAMPLE_FILE_DICT, LEADERBOARD_DISPLAY_COLUMNS, ) from about import ABOUT_INTRO, ABOUT_TEXT, FAQS from submit import make_submission def format_leaderboard_table(df_results: pd.DataFrame, assay: str | None = None): df = df_results.query("assay.isin(@ASSAY_RENAME.keys())").copy() if assay is not None: df = df[df["assay"] == assay] df = df[LEADERBOARD_DISPLAY_COLUMNS] return df.sort_values(by="spearman", ascending=False) def get_leaderboard_object(assay: str | None = None): filter_columns = ["dataset"] if assay is None: filter_columns.append("property") # TODO how to sort filter columns alphabetically? # Bug: Can't leave search_columns empty because then it says "Column None not found in headers" # Note(Lood): Would be nice to make it clear that the Search Column is searching on model name # TODO(Lood) check that this actually refreshes using the function lb = Leaderboard( value=format_leaderboard_table(df_results=current_dataframe, assay=assay), datatype=["str", "str", "str", "number"], select_columns=["model", "property", "spearman", "dataset"], search_columns=["model"], filter_columns=filter_columns, every=15, render=True, ) return lb # Initialize global dataframe current_dataframe = fetch_hf_results() with gr.Blocks() as demo: timer = gr.Timer(3) # Run every 3 seconds when page is focused data_version = gr.State(value=0) # Track data changes def update_current_dataframe(): global current_dataframe new_dataframe = fetch_hf_results() # Check if data has actually changed if not current_dataframe.equals(new_dataframe): current_dataframe = new_dataframe return data_version.value + 1 # Increment version to trigger updates return data_version.value timer.tick(fn=update_current_dataframe, outputs=data_version) # TODO: Add Ginkgo logo here on the top right gr.Markdown(""" ## Welcome to the Ginkgo Antibody Developability Benchmark! **Beta version, not publicly launched yet** Participants can submit their model to the leaderboard by uploading a CSV file (see the "✉️ Submit" tab). See more details in the "❔About" tab. """) with gr.Tabs(elem_classes="tab-buttons"): with gr.TabItem("❔About", elem_id="abdev-benchmark-tab-table"): gr.Image( value="./assets/competition_logo.jpg", show_label=False, # elem_classes=["resized-image"], show_download_button=False, width="50vw", # 50% of the "viewport width" ) gr.Markdown(ABOUT_INTRO) gr.Image(value="./assets/prediction_explainer.png", show_label=False, show_download_button=False, width="50vw") gr.Markdown(ABOUT_TEXT) gr.Markdown("### FAQs") for i, (question, answer) in enumerate(FAQS.items()): # Would love to make questions bold but accordion doesn't support it question = f"{i+1}. {question}" with gr.Accordion(question, open=False): gr.Markdown(f"*{answer}*") # Italics for answers # Procedurally make these 5 tabs for i, assay in enumerate(ASSAY_LIST): with gr.TabItem( f"{ASSAY_EMOJIS[assay]} {ASSAY_RENAME[assay]}", elem_id="abdev-benchmark-tab-table", ) as tab_item: gr.Markdown(f"# {ASSAY_DESCRIPTION[assay]}") lb = get_leaderboard_object(assay=assay) def refresh_leaderboard(assay=assay): return format_leaderboard_table(df_results=current_dataframe, assay=assay) # Refresh when data version changes data_version.change(fn=refresh_leaderboard, outputs=lb) with gr.TabItem("🚀 Overall", elem_id="abdev-benchmark-tab-table") as overall_tab: gr.Markdown( "# Antibody Developability Benchmark Leaderboard over all properties" ) lb = get_leaderboard_object() def refresh_overall_leaderboard(): return format_leaderboard_table(df_results=current_dataframe) # Refresh when data version changes data_version.change(fn=refresh_overall_leaderboard, outputs=lb) with gr.TabItem("✉️ Submit", elem_id="boundary-benchmark-tab-table"): gr.Markdown( f""" # Antibody Developability Submission Upload a CSV to get a score! List of valid property names: `{', '.join(ASSAY_LIST)}`. Please use your Hugging Face account name to submit your model - we use this to track separate submissions, and if you would like to remain anonymous please set up an anonymous huggingface account. Your submission will be evaluated and added to the leaderboard. """ ) submission_type_state = gr.State(value="GDPa1") download_file_state = gr.State(value=EXAMPLE_FILE_DICT["GDPa1"]) with gr.Row(): with gr.Column(): username_input = gr.Textbox( label="Username", placeholder="Enter your Hugging Face username", info="This will be used to track your submissions, and to update your results if you submit again.", ) model_name_input = gr.Textbox( label="Model Name", placeholder="Enter your model name (e.g., 'MyProteinLM-v1')", info="This will be displayed on the leaderboard.", ) model_description_input = gr.Textbox( label="Model Description (optional)", placeholder="Brief description of your model and approach", info="Describe your model, training data, or methodology.", lines=3, ) with gr.Column(): submission_type_dropdown = gr.Dropdown( choices=["GDPa1", "GDPa1_cross_validation"], value="GDPa1", label="Submission Type", ) download_button = gr.DownloadButton( label="📥 Download example submission CSV for GDPa1", value=EXAMPLE_FILE_DICT["GDPa1"], variant="secondary", ) submission_file = gr.File(label="Submission CSV") def update_submission_type_and_file(submission_type): """ Based on the submission type selected in the dropdown, Update the submission type state Dynamically update example file for download """ download_file = EXAMPLE_FILE_DICT.get( submission_type, EXAMPLE_FILE_DICT["GDPa1"] ) download_label = ( f"📥 Download example submission CSV for {submission_type}" ) return ( submission_type, download_file, gr.DownloadButton( label=download_label, value=download_file, variant="secondary", ), ) # Update submission type state and download button when dropdown changes submission_type_dropdown.change( fn=update_submission_type_and_file, inputs=submission_type_dropdown, outputs=[submission_type_state, download_file_state, download_button], ) submit_btn = gr.Button("Evaluate") message = gr.Textbox(label="Status", lines=1, visible=False) # help message gr.Markdown( "If you have issues with submission or using the leaderboard, please start a discussion in the Community tab of this Space." ) submit_btn.click( make_submission, inputs=[ submission_file, username_input, submission_type_state, model_name_input, model_description_input, ], outputs=[message], ).then( fn=show_output_box, inputs=[message], outputs=[message], ) # Footnote gr.Markdown( """