antoniaebner commited on
Commit
fe1a8cf
·
1 Parent(s): 98d346b

refactor leaderboard formatting

Browse files
backend/data_loader.py CHANGED
@@ -4,84 +4,42 @@ Handles loading and processing results from HuggingFace datasets.
4
  """
5
 
6
  import pandas as pd
7
- from datasets import load_dataset
8
  from config.settings import RESULTS_DATASET, TEST_DATASET, HF_TOKEN
9
  from config.tasks import TOX21_TASKS
10
 
11
 
12
- def load_leaderboard_data() -> pd.DataFrame:
13
  """
14
  Load leaderboard data from HuggingFace dataset.
15
  """
16
  print(f"Loading dataset: {RESULTS_DATASET}")
17
-
18
  # Load the dataset
19
  dataset = load_dataset(RESULTS_DATASET, token=HF_TOKEN)
20
  print(f"Dataset loaded successfully. Keys: {dataset.keys()}")
21
-
22
  # Look for test split (more appropriate for results)
23
- if 'test' in dataset:
24
- results_data = dataset['test']
25
  print(f"Test split has {len(results_data)} entries")
26
  if len(results_data) > 0:
27
  print(f"First entry keys: {results_data[0].keys()}")
28
  print(f"First entry: {results_data[0]}")
 
29
  else:
30
  raise ValueError("Dataset does not contain a 'test' split.")
31
-
32
- # Convert to DataFrame (new schema only)
33
- rows = []
34
- for entry in results_data:
35
- config = entry['config']
36
- results = entry['results']
37
-
38
- # Only include approved entries
39
- if not config.get('approved', False):
40
- continue
41
-
42
- # Create a row with all the data
43
- row = {
44
- 'Model': config['model_name'],
45
- 'Model Description': config['model_description'],
46
- 'Publication': config.get('publication_title', ''),
47
- 'Parameters': config.get('model_size', ''),
48
- 'Date Added': str(config.get('date_approved', config.get('date_submitted', ''))).split()[0],
49
- 'Overall Score': results['overall_score']['roc_auc']
50
- }
51
-
52
- # Add individual task scores
53
- for task_key, task_result in results.items():
54
- if task_key != 'overall_score': # Skip overall score
55
- row[task_key] = task_result['roc_auc']
56
-
57
- rows.append(row)
58
-
59
- df = pd.DataFrame(rows)
60
-
61
- # Handle empty dataset case
62
- if df.empty:
63
- print("No approved submissions found. Creating empty DataFrame with proper columns.")
64
- # Create empty DataFrame with expected columns
65
- columns = [
66
- 'Model', 'Model Description', 'Publication', 'Parameters', 'Date Added', 'Overall Score',
67
- 'NR-AR', 'NR-AR-LBD', 'NR-AhR', 'NR-Aromatase', 'NR-ER', 'NR-ER-LBD',
68
- 'NR-PPAR-gamma', 'SR-ARE', 'SR-ATAD5', 'SR-HSE', 'SR-MMP', 'SR-p53'
69
- ]
70
- df = pd.DataFrame(columns=columns)
71
-
72
- print(df)
73
- print(f"Created DataFrame with shape: {df.shape}")
74
- return df
75
 
76
  def load_test_dataset() -> tuple[list[str], dict[str, dict[str, float]]]:
77
- # Get test smiles and labels
78
  dset = load_dataset(TEST_DATASET, token=HF_TOKEN, split="test")
79
 
80
- tasks = [t.key for t in TOX21_TASKS]
81
  smiles = list(dset["smiles"])
82
  labels = {
83
- sample["smiles"]: {task: sample[task] for task in tasks}
84
  for sample in list(dset)
85
  }
86
  print(f"Loaded test dataset")
87
- return smiles, labels
 
4
  """
5
 
6
  import pandas as pd
7
+ from datasets import load_dataset, Dataset
8
  from config.settings import RESULTS_DATASET, TEST_DATASET, HF_TOKEN
9
  from config.tasks import TOX21_TASKS
10
 
11
 
12
+ def load_leaderboard_data() -> Dataset:
13
  """
14
  Load leaderboard data from HuggingFace dataset.
15
  """
16
  print(f"Loading dataset: {RESULTS_DATASET}")
17
+
18
  # Load the dataset
19
  dataset = load_dataset(RESULTS_DATASET, token=HF_TOKEN)
20
  print(f"Dataset loaded successfully. Keys: {dataset.keys()}")
21
+
22
  # Look for test split (more appropriate for results)
23
+ if "test" in dataset:
24
+ results_data = dataset["test"]
25
  print(f"Test split has {len(results_data)} entries")
26
  if len(results_data) > 0:
27
  print(f"First entry keys: {results_data[0].keys()}")
28
  print(f"First entry: {results_data[0]}")
29
+ return results_data
30
  else:
31
  raise ValueError("Dataset does not contain a 'test' split.")
32
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  def load_test_dataset() -> tuple[list[str], dict[str, dict[str, float]]]:
35
+ # Get test smiles and labels
36
  dset = load_dataset(TEST_DATASET, token=HF_TOKEN, split="test")
37
 
38
+ tasks = [t.key for t in TOX21_TASKS]
39
  smiles = list(dset["smiles"])
40
  labels = {
41
+ sample["smiles"]: {task: sample[task] for task in tasks}
42
  for sample in list(dset)
43
  }
44
  print(f"Loaded test dataset")
45
+ return smiles, labels
config/leaderboard.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .tasks import get_all_task_keys
2
+
3
+ # column names
4
+ TASK_NAMES = get_all_task_keys()
5
+
6
+ METADATA_COLUMN_NAMES = [
7
+ "Model",
8
+ "Model Description",
9
+ "Publication",
10
+ "Parameters",
11
+ "Date Added",
12
+ "Overall Score",
13
+ ]
14
+
15
+ COLUMN_NAMES = TASK_NAMES + METADATA_COLUMN_NAMES
16
+
17
+ # column widths
18
+ METADATA_COLUMN_WIDTHS = {
19
+ "Model": 200,
20
+ "Model Description": 300,
21
+ "Publication": 150,
22
+ "Parameters": 100,
23
+ "Date Added": 120,
24
+ "Overall Score": 100,
25
+ }
26
+
27
+ TASK_COLUMN_WIDTH = 80
28
+
29
+ COLUMN_WIDTHS = METADATA_COLUMN_WIDTHS | {
30
+ k: TASK_COLUMN_WIDTH for k in TASK_NAMES
31
+ }
32
+
33
+ assert all(
34
+ [name in COLUMN_WIDTHS for name in COLUMN_NAMES]
35
+ ), "Some leaderboard columns have no assigned width! "
36
+
37
+ # table styling
38
+ MAX_DECIMALS = 3
frontend/layout.py CHANGED
@@ -2,6 +2,7 @@
2
  UI Layout components for the Tox21 leaderboard.
3
  Pure Gradio structure - no content or business logic.
4
  """
 
5
  import gradio as gr
6
  from typing import Callable, Any
7
  from .content import LeaderboardContent, AboutContent, SubmissionContent
@@ -10,18 +11,21 @@ import os
10
  import pandas as pd
11
  from gradio_leaderboard import Leaderboard
12
 
 
 
13
 
14
  def create_leaderboard_tab(refresh_callback: Callable = None) -> gr.TabItem:
15
  """Create the leaderboard tab layout"""
16
-
17
  with gr.TabItem("🏅 Leaderboard", elem_id="leaderboard-tab", id=0) as tab:
18
-
19
  # Header section
20
  header_html = gr.HTML(LeaderboardContent.get_header_html())
21
-
22
  # Load initial data
23
- result_data = refresh_leaderboard().reset_index(drop=True)
24
  result_data.columns = result_data.columns.map(str)
 
25
 
26
  # Leaderboard at full width
27
  leaderboard_table = Leaderboard(
@@ -34,23 +38,26 @@ def create_leaderboard_tab(refresh_callback: Callable = None) -> gr.TabItem:
34
  height=480,
35
  min_width=160,
36
  wrap=True,
37
- column_widths=[200, 300, 150, 100, 120, 100] + [80] * 12,
38
  )
39
-
40
  # Refresh button below table
41
- refresh_btn = gr.Button("🔄 Refresh Leaderboard", variant="secondary", size="sm")
42
-
 
 
43
  # Connect refresh button
44
  def refresh_data():
45
- new_data = refresh_callback().reset_index(drop=True) if refresh_callback else refresh_leaderboard().reset_index(drop=True)
 
 
 
 
46
  new_data.columns = new_data.columns.map(str)
47
  return new_data
48
-
49
- refresh_btn.click(
50
- fn=refresh_data,
51
- outputs=leaderboard_table
52
- )
53
-
54
  # Info section
55
  info_html = gr.HTML(LeaderboardContent.get_info_html())
56
 
@@ -59,116 +66,135 @@ def create_leaderboard_tab(refresh_callback: Callable = None) -> gr.TabItem:
59
 
60
  def create_about_tab() -> gr.TabItem:
61
  """Create the about tab layout"""
62
-
63
  with gr.TabItem("📝 About", elem_id="about-tab", id=1) as tab:
64
  content_markdown = gr.Markdown(
65
- AboutContent.get_markdown_content(),
66
- elem_classes="markdown-text"
67
  )
68
-
69
  return tab
70
 
71
 
72
  def create_submission_tab(submit_callback: Callable = None) -> gr.TabItem:
73
  """Create the submission tab layout"""
74
-
75
  with gr.TabItem("🚀 Submit", elem_id="submission-tab", id=2) as tab:
76
-
77
  # Header
78
- gr.HTML(f"<h2 style='text-align: center;'>{SubmissionContent.title}</h2>")
79
-
 
 
80
  # Instructions
81
  instructions_html = gr.HTML(SubmissionContent.get_instructions_html())
82
-
83
  # Submission form
84
  with gr.Group():
85
  # Required fields
86
  model_name = gr.Textbox(
87
  label=SubmissionContent.form_labels["model_name"],
88
  placeholder=SubmissionContent.form_placeholders["model_name"],
89
- info=SubmissionContent.form_info["model_name"]
90
  )
91
-
92
  hf_space_tag = gr.Textbox(
93
  label=SubmissionContent.form_labels["hf_space_tag"],
94
  placeholder=SubmissionContent.form_placeholders["hf_space_tag"],
95
- info=SubmissionContent.form_info["hf_space_tag"]
96
  )
97
-
98
  model_description = gr.Textbox(
99
  label=SubmissionContent.form_labels["model_description"],
100
- placeholder=SubmissionContent.form_placeholders["model_description"],
 
 
101
  info=SubmissionContent.form_info["model_description"],
102
- lines=3
103
  )
104
-
105
  # Optional fields in accordion
106
  with gr.Accordion("Additional Information (Optional)", open=False):
107
  organization = gr.Textbox(
108
  label=SubmissionContent.form_labels["organization"],
109
- placeholder=SubmissionContent.form_placeholders["organization"]
 
 
110
  )
111
-
112
  with gr.Row():
113
  model_size = gr.Textbox(
114
  label=SubmissionContent.form_labels["model_size"],
115
- placeholder=SubmissionContent.form_placeholders["model_size"]
 
 
116
  )
117
  pretraining = gr.Textbox(
118
  label=SubmissionContent.form_labels["pretraining"],
119
- placeholder=SubmissionContent.form_placeholders["pretraining"]
 
 
120
  )
121
-
122
  publication_title = gr.Textbox(
123
  label=SubmissionContent.form_labels["publication_title"],
124
- placeholder=SubmissionContent.form_placeholders["publication_title"]
 
 
125
  )
126
-
127
  publication_link = gr.Textbox(
128
  label=SubmissionContent.form_labels["publication_link"],
129
- placeholder=SubmissionContent.form_placeholders["publication_link"]
 
 
130
  )
131
-
132
  # Submit button and result
133
  submit_btn = gr.Button("Submit Model", variant="primary")
134
  result_msg = gr.HTML()
135
-
136
  if submit_callback:
137
  submit_btn.click(
138
  fn=submit_callback,
139
  inputs=[
140
- model_name, hf_space_tag, model_description,
141
- organization, model_size, pretraining,
142
- publication_title, publication_link
 
 
 
 
 
143
  ],
144
- outputs=result_msg
145
  )
146
-
147
  return tab
148
 
149
 
150
  def create_main_interface(
151
- refresh_callback: Callable = None,
152
- submit_callback: Callable = None
153
  ) -> gr.Blocks:
154
  """Create the main application interface"""
155
-
156
  # Load CSS from file
157
- css_path = os.path.join(os.path.dirname(__file__), 'styles.css')
158
- with open(css_path, 'r') as f:
159
  css = f.read()
160
-
161
  with gr.Blocks(css=css, title="Tox21 Leaderboard") as app:
162
-
163
  # Main title
164
  gr.HTML("<h1>🧪 Tox21 Leaderboard</h1>")
165
-
166
  # Tab container
167
  with gr.Tabs(elem_classes="tab-nav") as tabs:
168
-
169
  # Create all tabs
170
- leaderboard_tab, leaderboard_table = create_leaderboard_tab(refresh_callback)
 
 
171
  about_tab = create_about_tab()
172
  submission_tab = create_submission_tab(submit_callback)
173
-
174
- return app, leaderboard_table
 
2
  UI Layout components for the Tox21 leaderboard.
3
  Pure Gradio structure - no content or business logic.
4
  """
5
+
6
  import gradio as gr
7
  from typing import Callable, Any
8
  from .content import LeaderboardContent, AboutContent, SubmissionContent
 
11
  import pandas as pd
12
  from gradio_leaderboard import Leaderboard
13
 
14
+ from config.leaderboard import COLUMN_WIDTHS
15
+
16
 
17
  def create_leaderboard_tab(refresh_callback: Callable = None) -> gr.TabItem:
18
  """Create the leaderboard tab layout"""
19
+
20
  with gr.TabItem("🏅 Leaderboard", elem_id="leaderboard-tab", id=0) as tab:
21
+
22
  # Header section
23
  header_html = gr.HTML(LeaderboardContent.get_header_html())
24
+
25
  # Load initial data
26
+ result_data = refresh_leaderboard()
27
  result_data.columns = result_data.columns.map(str)
28
+ column_widths = [COLUMN_WIDTHS[c] for c in result_data.columns]
29
 
30
  # Leaderboard at full width
31
  leaderboard_table = Leaderboard(
 
38
  height=480,
39
  min_width=160,
40
  wrap=True,
41
+ column_widths=column_widths,
42
  )
43
+
44
  # Refresh button below table
45
+ refresh_btn = gr.Button(
46
+ "🔄 Refresh Leaderboard", variant="secondary", size="sm"
47
+ )
48
+
49
  # Connect refresh button
50
  def refresh_data():
51
+ new_data = (
52
+ refresh_callback().reset_index(drop=True)
53
+ if refresh_callback
54
+ else refresh_leaderboard().reset_index(drop=True)
55
+ )
56
  new_data.columns = new_data.columns.map(str)
57
  return new_data
58
+
59
+ refresh_btn.click(fn=refresh_data, outputs=leaderboard_table)
60
+
 
 
 
61
  # Info section
62
  info_html = gr.HTML(LeaderboardContent.get_info_html())
63
 
 
66
 
67
  def create_about_tab() -> gr.TabItem:
68
  """Create the about tab layout"""
69
+
70
  with gr.TabItem("📝 About", elem_id="about-tab", id=1) as tab:
71
  content_markdown = gr.Markdown(
72
+ AboutContent.get_markdown_content(), elem_classes="markdown-text"
 
73
  )
74
+
75
  return tab
76
 
77
 
78
  def create_submission_tab(submit_callback: Callable = None) -> gr.TabItem:
79
  """Create the submission tab layout"""
80
+
81
  with gr.TabItem("🚀 Submit", elem_id="submission-tab", id=2) as tab:
82
+
83
  # Header
84
+ gr.HTML(
85
+ f"<h2 style='text-align: center;'>{SubmissionContent.title}</h2>"
86
+ )
87
+
88
  # Instructions
89
  instructions_html = gr.HTML(SubmissionContent.get_instructions_html())
90
+
91
  # Submission form
92
  with gr.Group():
93
  # Required fields
94
  model_name = gr.Textbox(
95
  label=SubmissionContent.form_labels["model_name"],
96
  placeholder=SubmissionContent.form_placeholders["model_name"],
97
+ info=SubmissionContent.form_info["model_name"],
98
  )
99
+
100
  hf_space_tag = gr.Textbox(
101
  label=SubmissionContent.form_labels["hf_space_tag"],
102
  placeholder=SubmissionContent.form_placeholders["hf_space_tag"],
103
+ info=SubmissionContent.form_info["hf_space_tag"],
104
  )
105
+
106
  model_description = gr.Textbox(
107
  label=SubmissionContent.form_labels["model_description"],
108
+ placeholder=SubmissionContent.form_placeholders[
109
+ "model_description"
110
+ ],
111
  info=SubmissionContent.form_info["model_description"],
112
+ lines=3,
113
  )
114
+
115
  # Optional fields in accordion
116
  with gr.Accordion("Additional Information (Optional)", open=False):
117
  organization = gr.Textbox(
118
  label=SubmissionContent.form_labels["organization"],
119
+ placeholder=SubmissionContent.form_placeholders[
120
+ "organization"
121
+ ],
122
  )
123
+
124
  with gr.Row():
125
  model_size = gr.Textbox(
126
  label=SubmissionContent.form_labels["model_size"],
127
+ placeholder=SubmissionContent.form_placeholders[
128
+ "model_size"
129
+ ],
130
  )
131
  pretraining = gr.Textbox(
132
  label=SubmissionContent.form_labels["pretraining"],
133
+ placeholder=SubmissionContent.form_placeholders[
134
+ "pretraining"
135
+ ],
136
  )
137
+
138
  publication_title = gr.Textbox(
139
  label=SubmissionContent.form_labels["publication_title"],
140
+ placeholder=SubmissionContent.form_placeholders[
141
+ "publication_title"
142
+ ],
143
  )
144
+
145
  publication_link = gr.Textbox(
146
  label=SubmissionContent.form_labels["publication_link"],
147
+ placeholder=SubmissionContent.form_placeholders[
148
+ "publication_link"
149
+ ],
150
  )
151
+
152
  # Submit button and result
153
  submit_btn = gr.Button("Submit Model", variant="primary")
154
  result_msg = gr.HTML()
155
+
156
  if submit_callback:
157
  submit_btn.click(
158
  fn=submit_callback,
159
  inputs=[
160
+ model_name,
161
+ hf_space_tag,
162
+ model_description,
163
+ organization,
164
+ model_size,
165
+ pretraining,
166
+ publication_title,
167
+ publication_link,
168
  ],
169
+ outputs=result_msg,
170
  )
171
+
172
  return tab
173
 
174
 
175
  def create_main_interface(
176
+ refresh_callback: Callable = None, submit_callback: Callable = None
 
177
  ) -> gr.Blocks:
178
  """Create the main application interface"""
179
+
180
  # Load CSS from file
181
+ css_path = os.path.join(os.path.dirname(__file__), "styles.css")
182
+ with open(css_path, "r") as f:
183
  css = f.read()
184
+
185
  with gr.Blocks(css=css, title="Tox21 Leaderboard") as app:
186
+
187
  # Main title
188
  gr.HTML("<h1>🧪 Tox21 Leaderboard</h1>")
189
+
190
  # Tab container
191
  with gr.Tabs(elem_classes="tab-nav") as tabs:
192
+
193
  # Create all tabs
194
+ leaderboard_tab, leaderboard_table = create_leaderboard_tab(
195
+ refresh_callback
196
+ )
197
  about_tab = create_about_tab()
198
  submission_tab = create_submission_tab(submit_callback)
199
+
200
+ return app, leaderboard_table
frontend/leaderboard.py CHANGED
@@ -2,10 +2,12 @@
2
  Leaderboard-specific business logic.
3
  Handles data processing, backend communication, and state management.
4
  """
 
5
  import pandas as pd
6
  from typing import Optional
7
 
8
  from .content import LeaderboardContent
 
9
 
10
 
11
  def refresh_leaderboard() -> pd.DataFrame:
@@ -14,91 +16,148 @@ def refresh_leaderboard() -> pd.DataFrame:
14
  Currently returns sample data - will connect to backend later.
15
  """
16
  print("= Refreshing leaderboard data...")
17
-
18
  # Load data from backend
19
  from backend.data_loader import load_leaderboard_data
20
-
21
  results_data = load_leaderboard_data()
 
 
 
 
22
  return results_data
23
 
24
 
25
  def format_leaderboard_data(raw_data: dict) -> pd.DataFrame:
26
  """
27
  Format raw leaderboard data for display.
28
-
29
  Args:
30
  raw_data: Raw data from backend/datasets
31
-
32
  Returns:
33
  Formatted DataFrame for Gradio display
34
  """
35
  # TODO: Implement data formatting logic
36
  # This will process raw evaluation results into the display format
37
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
 
40
  def calculate_average_score(task_scores: dict) -> float:
41
  """
42
  Calculate average ROC-AUC score across all tasks.
43
-
44
  Args:
45
  task_scores: Dictionary of task_name -> score
46
-
47
  Returns:
48
  Average score across all tasks
49
  """
50
  if not task_scores:
51
  return 0.0
52
-
53
- valid_scores = [score for score in task_scores.values() if score is not None]
 
 
54
  if not valid_scores:
55
  return 0.0
56
-
57
  return sum(valid_scores) / len(valid_scores)
58
 
59
 
60
  def sort_by_performance(leaderboard_data: pd.DataFrame) -> pd.DataFrame:
61
  """
62
  Sort leaderboard by average performance score.
63
-
64
  Args:
65
  leaderboard_data: DataFrame with leaderboard data
66
-
67
  Returns:
68
  Sorted DataFrame with rank column updated
69
  """
70
  # Sort by average score (descending)
71
  sorted_data = leaderboard_data.sort_values(by="Average", ascending=False)
72
-
73
  # Update rank column
74
  sorted_data["Rank"] = range(1, len(sorted_data) + 1)
75
-
76
  return sorted_data
77
 
78
 
79
  def filter_leaderboard(
80
- data: pd.DataFrame,
81
  min_score: Optional[float] = None,
82
  model_type: Optional[str] = None,
83
- date_range: Optional[tuple] = None
84
  ) -> pd.DataFrame:
85
  """
86
  Filter leaderboard data based on criteria.
87
-
88
  Args:
89
  data: Original leaderboard data
90
  min_score: Minimum average score threshold
91
  model_type: Filter by model type
92
  date_range: Filter by submission date range
93
-
94
  Returns:
95
  Filtered DataFrame
96
  """
97
  filtered_data = data.copy()
98
-
99
  if min_score is not None:
100
  filtered_data = filtered_data[filtered_data["Average"] >= min_score]
101
-
102
  # TODO: Add more filtering logic as needed
103
-
104
- return filtered_data
 
2
  Leaderboard-specific business logic.
3
  Handles data processing, backend communication, and state management.
4
  """
5
+
6
  import pandas as pd
7
  from typing import Optional
8
 
9
  from .content import LeaderboardContent
10
+ from config.leaderboard import MAX_DECIMALS, COLUMN_NAMES
11
 
12
 
13
  def refresh_leaderboard() -> pd.DataFrame:
 
16
  Currently returns sample data - will connect to backend later.
17
  """
18
  print("= Refreshing leaderboard data...")
19
+
20
  # Load data from backend
21
  from backend.data_loader import load_leaderboard_data
22
+
23
  results_data = load_leaderboard_data()
24
+ results_data = format_leaderboard_data(results_data)
25
+ assert all(
26
+ [c in COLUMN_NAMES for c in results_data.columns]
27
+ ), "Some required columns not found in dataset!"
28
  return results_data
29
 
30
 
31
  def format_leaderboard_data(raw_data: dict) -> pd.DataFrame:
32
  """
33
  Format raw leaderboard data for display.
34
+
35
  Args:
36
  raw_data: Raw data from backend/datasets
37
+
38
  Returns:
39
  Formatted DataFrame for Gradio display
40
  """
41
  # TODO: Implement data formatting logic
42
  # This will process raw evaluation results into the display format
43
+
44
+ # Convert to DataFrame (new schema only)
45
+ rows = []
46
+ for entry in raw_data:
47
+ config = entry["config"]
48
+ results = entry["results"]
49
+
50
+ # Only include approved entries
51
+ if not config.get("approved", False):
52
+ continue
53
+
54
+ # Create a row with all the data
55
+ row = {
56
+ "Model": config["model_name"],
57
+ "Model Description": config["model_description"],
58
+ "Publication": config.get("publication_title", ""),
59
+ "Parameters": config.get("model_size", ""),
60
+ "Pretrained (y/n)": config.get("pretraining", ""),
61
+ "Date Added": str(
62
+ config.get("date_approved", config.get("date_submitted", ""))
63
+ ).split()[0],
64
+ "Overall Score": results["overall_score"]["roc_auc"],
65
+ }
66
+
67
+ # Add individual task scores
68
+ for task_key, task_result in results.items():
69
+ if task_key != "overall_score": # Skip overall score
70
+ row[task_key] = task_result["roc_auc"]
71
+
72
+ rows.append(row)
73
+
74
+ df = pd.DataFrame(rows)
75
+
76
+ # Handle empty dataset case
77
+ if df.empty:
78
+ print(
79
+ "No approved submissions found. Creating empty DataFrame with proper columns."
80
+ )
81
+ # Create empty DataFrame with expected columns
82
+ df = pd.DataFrame(columns=COLUMN_NAMES)
83
+ else:
84
+ # rank according to overall score
85
+ df = df.sort_values(by="Overall Score", ascending=False).reset_index(
86
+ drop=True
87
+ )
88
+ # set different precision
89
+
90
+ print(df)
91
+ print(f"Created DataFrame with shape: {df.shape}")
92
+ df = df.round(decimals=MAX_DECIMALS)
93
+
94
+ return df
95
 
96
 
97
  def calculate_average_score(task_scores: dict) -> float:
98
  """
99
  Calculate average ROC-AUC score across all tasks.
100
+
101
  Args:
102
  task_scores: Dictionary of task_name -> score
103
+
104
  Returns:
105
  Average score across all tasks
106
  """
107
  if not task_scores:
108
  return 0.0
109
+
110
+ valid_scores = [
111
+ score for score in task_scores.values() if score is not None
112
+ ]
113
  if not valid_scores:
114
  return 0.0
115
+
116
  return sum(valid_scores) / len(valid_scores)
117
 
118
 
119
  def sort_by_performance(leaderboard_data: pd.DataFrame) -> pd.DataFrame:
120
  """
121
  Sort leaderboard by average performance score.
122
+
123
  Args:
124
  leaderboard_data: DataFrame with leaderboard data
125
+
126
  Returns:
127
  Sorted DataFrame with rank column updated
128
  """
129
  # Sort by average score (descending)
130
  sorted_data = leaderboard_data.sort_values(by="Average", ascending=False)
131
+
132
  # Update rank column
133
  sorted_data["Rank"] = range(1, len(sorted_data) + 1)
134
+
135
  return sorted_data
136
 
137
 
138
  def filter_leaderboard(
139
+ data: pd.DataFrame,
140
  min_score: Optional[float] = None,
141
  model_type: Optional[str] = None,
142
+ date_range: Optional[tuple] = None,
143
  ) -> pd.DataFrame:
144
  """
145
  Filter leaderboard data based on criteria.
146
+
147
  Args:
148
  data: Original leaderboard data
149
  min_score: Minimum average score threshold
150
  model_type: Filter by model type
151
  date_range: Filter by submission date range
152
+
153
  Returns:
154
  Filtered DataFrame
155
  """
156
  filtered_data = data.copy()
157
+
158
  if min_score is not None:
159
  filtered_data = filtered_data[filtered_data["Average"] >= min_score]
160
+
161
  # TODO: Add more filtering logic as needed
162
+
163
+ return filtered_data