File size: 8,572 Bytes
2982a51
281711d
 
1bcb06b
281711d
3edbc93
84fdef4
 
 
 
 
 
01d1575
84fdef4
7a1c35b
3edbc93
8f9985e
 
ba1131a
 
 
1bcb06b
 
11793f2
de75bee
1bcb06b
8f9985e
1bcb06b
11793f2
1bcb06b
8f9985e
84fdef4
 
 
 
 
 
 
 
 
 
 
fe04bb9
57878eb
1bcb06b
5b5ee28
11e5e48
1bcb06b
813ce52
84fdef4
1bcb06b
11793f2
57878eb
1bcb06b
 
8f9985e
1bcb06b
2982a51
8f9985e
1bcb06b
11e5e48
11793f2
8f9985e
813ce52
8f9985e
11793f2
ba1131a
11e5e48
1bcb06b
9e6aa1f
3d4c9af
 
 
813ce52
3d4c9af
813ce52
3d4c9af
3edbc93
 
ba1131a
 
8f9985e
813ce52
 
8f9985e
 
 
 
813ce52
 
8f9985e
 
 
 
 
813ce52
3edbc93
 
1bcb06b
b8be656
3edbc93
 
8f9985e
813ce52
 
1bcb06b
 
8f9985e
 
3edbc93
84fdef4
 
3edbc93
 
 
 
809a553
 
 
a7cc355
 
 
 
8f9985e
3edbc93
a7cc355
 
 
 
 
 
3edbc93
84fdef4
 
 
 
 
 
 
 
 
 
813ce52
3edbc93
01d1575
3edbc93
01d1575
3edbc93
8f9985e
 
3edbc93
84fdef4
5d5df93
 
 
 
 
84fdef4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3edbc93
 
 
8f9985e
 
 
 
3edbc93
 
a7cc355
 
 
 
 
 
 
3edbc93
 
 
 
 
 
ba1131a
 
 
 
 
 
 
8f9985e
ba1131a
281711d
 
1bcb06b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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,
    ANONYMOUS_SUBMISSION_USERNAME,
)
from about import ABOUT_TEXT, FAQS
from submit import make_submission


def format_leaderboard_table(df_results: pd.DataFrame, assay: str | None = None):
    # Previous things that were nice in the constellaration leaderboard:
    # Having a submission time column, and a user column where the username is clickable (this is a pro for usability but con for anonymity)
    # full_df.rename(columns={'submission_time': 'submission time', 'problem_type': 'problem type'}, inplace=True)
    # to_show['user'] = to_show['user'].apply(lambda x: make_user_clickable(x)).astype(str)
    column_order = ["model", "property", "spearman", "spearman_cross_val"]
    df = df_results.query("assay.isin(@ASSAY_RENAME.keys())").copy()
    if assay is not None:
        df = df[df["assay"] == assay]
    df = df[column_order]
    return df.sort_values(by="spearman", ascending=False)


# Cache the results to avoid multiple downloads
_cached_results = None


def get_cached_results():
    global _cached_results
    if _cached_results is None:
        _cached_results = fetch_hf_results()
    return _cached_results


def get_leaderboard_object(assay: str | None = None):
    filter_columns = ["model"]
    if assay is None:
        filter_columns.append("property")
    # TODO how to sort filter columns alphabetically?
    Leaderboard(
        # TODO(Lood) check that this actually refreshes using the function
        value=format_leaderboard_table(df_results=get_cached_results(), assay=assay),
        datatype=["str", "str", "str", "number"],
        select_columns=["model", "property", "spearman", "spearman_cross_val"],
        search_columns=["model"],
        filter_columns=filter_columns,
        every=60,
        render=True,
    )


with gr.Blocks() as demo:
    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_TEXT)
            for question, answer in FAQS.items():
                with gr.Accordion(question):
                    gr.Markdown(answer)

        # Procedurally make these 5 tabs
        for assay in ASSAY_LIST:
            with gr.TabItem(
                f"{ASSAY_EMOJIS[assay]} {ASSAY_RENAME[assay]}",
                elem_id="abdev-benchmark-tab-table",
            ):
                gr.Markdown(f"# {ASSAY_DESCRIPTION[assay]}")
                get_leaderboard_object(assay=assay)

        with gr.TabItem("🚀 Overall", elem_id="abdev-benchmark-tab-table"):
            gr.Markdown(
                "# Antibody Developability Benchmark Leaderboard over all properties"
            )
            get_leaderboard_object()

        with gr.TabItem("✉️ Submit", elem_id="boundary-benchmark-tab-table"):
            gr.Markdown(
                """
            # Antibody Developability Submission
            Upload a CSV to get a score!

            Please use your Hugging Face account name to submit your model - we use this to track separate submissions, but only Hugging Face/Ginkgo will see these usernames (unless you choose to make them public).
            Your submission will be evaluated and added to the leaderboard.
            """
            )
            filename = gr.State(value=None)
            eval_state = gr.State(value=None)
            user_state = gr.State(value=None)
            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 or leave blank for anonymous submissions",
                        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",
                        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",
                        value=EXAMPLE_FILE_DICT["GDPa1"],
                        variant="secondary",
                    )
                    submission_file = gr.File(label="Submission CSV")

            # If username is empty, set to anonymous submission
            username_input.change(
                fn=lambda x: x if x.strip() else ANONYMOUS_SUBMISSION_USERNAME,
                inputs=username_input,
                outputs=user_state,
            )

            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"]
                )
                return (
                    submission_type,
                    download_file,
                    gr.DownloadButton(
                        label="📥 Download example submission CSV",
                        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,
                    user_state,
                    submission_type_state,
                    model_name_input,
                    model_description_input,
                ],
                outputs=[message],
            ).then(
                fn=show_output_box,
                inputs=[message],
                outputs=[message],
            )
    # Footnote
    gr.Markdown(
        """
        <div style="text-align: center; font-size: 14px; color: gray; margin-top: 2em;">
        📬 For questions or feedback, contact <a href="mailto:[email protected]">[email protected]</a> or visit the Community tab at the top of this page.
        </div>
        """,
        elem_id="contact-footer",
    )

if __name__ == "__main__":
    demo.launch()