jasonshaoshun commited on
Commit
ef71549
·
1 Parent(s): dd7b655
Files changed (2) hide show
  1. app.py +223 -71
  2. custom-select-columns.py +345 -0
app.py CHANGED
@@ -128,58 +128,122 @@ from src.about import TasksMib_Subgraph
128
 
129
 
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  # def init_leaderboard_mib_subgraph(dataframe, track):
132
- # """Initialize the subgraph leaderboard with grouped column selection by benchmark."""
133
  # if dataframe is None or dataframe.empty:
134
  # raise ValueError("Leaderboard DataFrame is empty or None.")
135
 
136
  # print("\nDebugging DataFrame columns:", dataframe.columns.tolist())
137
 
138
- # # Create groups of columns by benchmark
 
 
 
 
 
 
 
 
 
139
  # benchmark_groups = []
140
-
141
- # # For each benchmark in our TasksMib_Subgraph enum...
142
  # for task in TasksMib_Subgraph:
143
  # benchmark = task.value.benchmark
144
- # # Get all valid columns for this benchmark's models
145
  # benchmark_cols = [
146
- # f"{benchmark}_{model}"
147
  # for model in task.value.models
148
  # if f"{benchmark}_{model}" in dataframe.columns
149
  # ]
150
- # if benchmark_cols: # Only add if we have valid columns
151
  # benchmark_groups.append(benchmark_cols)
152
  # print(f"\nBenchmark group for {benchmark}:", benchmark_cols)
153
 
154
- # # Create model groups as well
155
  # model_groups = []
156
  # all_models = list(set(model for task in TasksMib_Subgraph for model in task.value.models))
157
 
158
- # # For each unique model...
159
  # for model in all_models:
160
- # # Get all valid columns for this model across benchmarks
161
  # model_cols = [
162
- # f"{task.value.benchmark}_{model}"
163
  # for task in TasksMib_Subgraph
164
  # if model in task.value.models
165
  # and f"{task.value.benchmark}_{model}" in dataframe.columns
166
  # ]
167
- # if model_cols: # Only add if we have valid columns
168
  # model_groups.append(model_cols)
169
  # print(f"\nModel group for {model}:", model_cols)
170
 
171
- # # Combine all groups
172
  # all_groups = benchmark_groups + model_groups
173
-
174
- # # Flatten groups for default selection (show everything initially)
175
  # all_columns = [col for group in all_groups for col in group]
176
- # print("\nAll available columns:", all_columns)
 
 
177
 
178
  # return Leaderboard(
179
- # value=dataframe,
180
  # datatype=[c.type for c in fields(AutoEvalColumn_mib_subgraph)],
181
  # select_columns=SelectColumns(
182
- # default_selection=all_columns, # Show all columns initially
183
  # label="Select Results:"
184
  # ),
185
  # search_columns=["Method"],
@@ -188,71 +252,159 @@ from src.about import TasksMib_Subgraph
188
  # )
189
 
190
 
191
- def init_leaderboard_mib_subgraph(dataframe, track):
192
- """Initialize the subgraph leaderboard with display names for better readability."""
193
- if dataframe is None or dataframe.empty:
194
- raise ValueError("Leaderboard DataFrame is empty or None.")
195
 
196
- print("\nDebugging DataFrame columns:", dataframe.columns.tolist())
197
-
198
- # First, create our display name mapping
199
- # This is like creating a translation dictionary between internal names and display names
200
- display_mapping = {}
201
- for task in TasksMib_Subgraph:
202
- for model in task.value.models:
203
- field_name = f"{task.value.benchmark}_{model}"
204
- display_name = f"{task.value.benchmark}({model})"
205
- display_mapping[field_name] = display_name
206
 
207
- # Now when creating benchmark groups, we'll use display names
208
- benchmark_groups = []
209
- for task in TasksMib_Subgraph:
210
- benchmark = task.value.benchmark
211
- benchmark_cols = [
212
- display_mapping[f"{benchmark}_{model}"] # Use display name from our mapping
213
- for model in task.value.models
214
- if f"{benchmark}_{model}" in dataframe.columns
215
- ]
216
- if benchmark_cols:
217
- benchmark_groups.append(benchmark_cols)
218
- print(f"\nBenchmark group for {benchmark}:", benchmark_cols)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
- # Similarly for model groups
221
- model_groups = []
222
- all_models = list(set(model for task in TasksMib_Subgraph for model in task.value.models))
 
 
223
 
224
- for model in all_models:
225
- model_cols = [
226
- display_mapping[f"{task.value.benchmark}_{model}"] # Use display name
227
- for task in TasksMib_Subgraph
228
- if model in task.value.models
229
- and f"{task.value.benchmark}_{model}" in dataframe.columns
230
- ]
231
- if model_cols:
232
- model_groups.append(model_cols)
233
- print(f"\nModel group for {model}:", model_cols)
234
 
235
- # Combine all groups using display names
236
- all_groups = benchmark_groups + model_groups
237
- all_columns = [col for group in all_groups for col in group]
238
 
239
- # Important: We need to rename our DataFrame columns to match display names
240
- renamed_df = dataframe.rename(columns=display_mapping)
 
 
 
 
 
241
 
242
- return Leaderboard(
243
- value=renamed_df, # Use DataFrame with display names
244
- datatype=[c.type for c in fields(AutoEvalColumn_mib_subgraph)],
245
- select_columns=SelectColumns(
246
- default_selection=all_columns, # Now contains display names
247
- label="Select Results:"
248
- ),
249
  search_columns=["Method"],
250
  hide_columns=[],
251
- interactive=False,
252
  )
253
 
254
 
255
-
256
  # def init_leaderboard_mib_subgraph(dataframe, track):
257
  # """Initialize the subgraph leaderboard with group-based column selection."""
258
  # if dataframe is None or dataframe.empty:
 
128
 
129
 
130
 
131
+ def init_leaderboard_mib_subgraph(dataframe, track):
132
+ """Initialize the subgraph leaderboard with grouped column selection by benchmark."""
133
+ if dataframe is None or dataframe.empty:
134
+ raise ValueError("Leaderboard DataFrame is empty or None.")
135
+
136
+ print("\nDebugging DataFrame columns:", dataframe.columns.tolist())
137
+
138
+ # Create groups of columns by benchmark
139
+ benchmark_groups = []
140
+
141
+ # For each benchmark in our TasksMib_Subgraph enum...
142
+ for task in TasksMib_Subgraph:
143
+ benchmark = task.value.benchmark
144
+ # Get all valid columns for this benchmark's models
145
+ benchmark_cols = [
146
+ f"{benchmark}_{model}"
147
+ for model in task.value.models
148
+ if f"{benchmark}_{model}" in dataframe.columns
149
+ ]
150
+ if benchmark_cols: # Only add if we have valid columns
151
+ benchmark_groups.append(benchmark_cols)
152
+ print(f"\nBenchmark group for {benchmark}:", benchmark_cols)
153
+
154
+ # Create model groups as well
155
+ model_groups = []
156
+ all_models = list(set(model for task in TasksMib_Subgraph for model in task.value.models))
157
+
158
+ # For each unique model...
159
+ for model in all_models:
160
+ # Get all valid columns for this model across benchmarks
161
+ model_cols = [
162
+ f"{task.value.benchmark}_{model}"
163
+ for task in TasksMib_Subgraph
164
+ if model in task.value.models
165
+ and f"{task.value.benchmark}_{model}" in dataframe.columns
166
+ ]
167
+ if model_cols: # Only add if we have valid columns
168
+ model_groups.append(model_cols)
169
+ print(f"\nModel group for {model}:", model_cols)
170
+
171
+ # Combine all groups
172
+ all_groups = benchmark_groups + model_groups
173
+
174
+ # Flatten groups for default selection (show everything initially)
175
+ all_columns = [col for group in all_groups for col in group]
176
+ print("\nAll available columns:", all_columns)
177
+
178
+ return Leaderboard(
179
+ value=dataframe,
180
+ datatype=[c.type for c in fields(AutoEvalColumn_mib_subgraph)],
181
+ select_columns=SelectColumns(
182
+ default_selection=all_columns, # Show all columns initially
183
+ label="Select Results:"
184
+ ),
185
+ search_columns=["Method"],
186
+ hide_columns=[],
187
+ interactive=False,
188
+ )
189
+
190
+
191
  # def init_leaderboard_mib_subgraph(dataframe, track):
192
+ # """Initialize the subgraph leaderboard with display names for better readability."""
193
  # if dataframe is None or dataframe.empty:
194
  # raise ValueError("Leaderboard DataFrame is empty or None.")
195
 
196
  # print("\nDebugging DataFrame columns:", dataframe.columns.tolist())
197
 
198
+ # # First, create our display name mapping
199
+ # # This is like creating a translation dictionary between internal names and display names
200
+ # display_mapping = {}
201
+ # for task in TasksMib_Subgraph:
202
+ # for model in task.value.models:
203
+ # field_name = f"{task.value.benchmark}_{model}"
204
+ # display_name = f"{task.value.benchmark}({model})"
205
+ # display_mapping[field_name] = display_name
206
+
207
+ # # Now when creating benchmark groups, we'll use display names
208
  # benchmark_groups = []
 
 
209
  # for task in TasksMib_Subgraph:
210
  # benchmark = task.value.benchmark
 
211
  # benchmark_cols = [
212
+ # display_mapping[f"{benchmark}_{model}"] # Use display name from our mapping
213
  # for model in task.value.models
214
  # if f"{benchmark}_{model}" in dataframe.columns
215
  # ]
216
+ # if benchmark_cols:
217
  # benchmark_groups.append(benchmark_cols)
218
  # print(f"\nBenchmark group for {benchmark}:", benchmark_cols)
219
 
220
+ # # Similarly for model groups
221
  # model_groups = []
222
  # all_models = list(set(model for task in TasksMib_Subgraph for model in task.value.models))
223
 
 
224
  # for model in all_models:
 
225
  # model_cols = [
226
+ # display_mapping[f"{task.value.benchmark}_{model}"] # Use display name
227
  # for task in TasksMib_Subgraph
228
  # if model in task.value.models
229
  # and f"{task.value.benchmark}_{model}" in dataframe.columns
230
  # ]
231
+ # if model_cols:
232
  # model_groups.append(model_cols)
233
  # print(f"\nModel group for {model}:", model_cols)
234
 
235
+ # # Combine all groups using display names
236
  # all_groups = benchmark_groups + model_groups
 
 
237
  # all_columns = [col for group in all_groups for col in group]
238
+
239
+ # # Important: We need to rename our DataFrame columns to match display names
240
+ # renamed_df = dataframe.rename(columns=display_mapping)
241
 
242
  # return Leaderboard(
243
+ # value=renamed_df, # Use DataFrame with display names
244
  # datatype=[c.type for c in fields(AutoEvalColumn_mib_subgraph)],
245
  # select_columns=SelectColumns(
246
+ # default_selection=all_columns, # Now contains display names
247
  # label="Select Results:"
248
  # ),
249
  # search_columns=["Method"],
 
252
  # )
253
 
254
 
 
 
 
 
255
 
 
 
 
 
 
 
 
 
 
 
256
 
257
+ class SmartSelectColumns(gr.SelectColumns):
258
+ """
259
+ Enhanced SelectColumns component for Gradio Leaderboard with smart filtering and mapping capabilities.
260
+ """
261
+ def __init__(
262
+ self,
263
+ column_filters: Optional[Dict[str, List[str]]] = None,
264
+ column_mapping: Optional[Dict[str, str]] = None,
265
+ initial_selected: Optional[List[str]] = None,
266
+ *args,
267
+ **kwargs
268
+ ):
269
+ """
270
+ Initialize SmartSelectColumns with enhanced functionality.
271
+
272
+ Args:
273
+ column_filters: Dict mapping filter names to lists of substrings to match
274
+ column_mapping: Dict mapping actual column names to display names
275
+ initial_selected: List of column names to be initially selected
276
+ *args, **kwargs: Additional arguments passed to parent SelectColumns
277
+ """
278
+ super().__init__(*args, **kwargs)
279
+ self.column_filters = column_filters or {}
280
+ self.column_mapping = column_mapping or {}
281
+ self.reverse_mapping = {v: k for k, v in self.column_mapping.items()} if column_mapping else {}
282
+ self.initial_selected = initial_selected or []
283
+
284
+ def preprocess(self, x: List[str]) -> List[str]:
285
+ """
286
+ Transform selected display names back to actual column names.
287
+
288
+ Args:
289
+ x: List of selected display names
290
+
291
+ Returns:
292
+ List of actual column names
293
+ """
294
+ return [self.reverse_mapping.get(col, col) for col in x]
295
+
296
+ def postprocess(self, y: List[str]) -> List[str]:
297
+ """
298
+ Transform actual column names to display names.
299
+
300
+ Args:
301
+ y: List of actual column names
302
+
303
+ Returns:
304
+ List of display names
305
+ """
306
+ return [self.column_mapping.get(col, col) for col in y]
307
+
308
+ def get_filtered_columns(self, df: pd.DataFrame) -> Dict[str, List[str]]:
309
+ """
310
+ Get columns filtered by substring matches.
311
+
312
+ Args:
313
+ df: Input DataFrame
314
+
315
+ Returns:
316
+ Dict mapping filter names to lists of matching display names
317
+ """
318
+ filtered_cols = {}
319
+
320
+ for filter_name, substrings in self.column_filters.items():
321
+ matching_cols = []
322
+ for col in df.columns:
323
+ if any(substr.lower() in col.lower() for substr in substrings):
324
+ display_name = self.column_mapping.get(col, col)
325
+ matching_cols.append(display_name)
326
+ filtered_cols[filter_name] = matching_cols
327
+
328
+ return filtered_cols
329
+
330
+ def update(
331
+ self,
332
+ value: Union[pd.DataFrame, Dict[str, List[str]], Any],
333
+ interactive: Optional[bool] = None
334
+ ) -> Dict:
335
+ """
336
+ Update component with new values, supporting DataFrame fields.
337
+
338
+ Args:
339
+ value: DataFrame, dict of columns, or fields object
340
+ interactive: Whether component should be interactive
341
+
342
+ Returns:
343
+ Dict containing update configuration
344
+ """
345
+ if isinstance(value, pd.DataFrame):
346
+ filtered_cols = self.get_filtered_columns(value)
347
+ choices = [self.column_mapping.get(col, col) for col in value.columns]
348
+
349
+ # Set initial selection if provided
350
+ value = self.initial_selected if self.initial_selected else choices
351
+
352
+ return {
353
+ "choices": choices,
354
+ "value": value,
355
+ "filtered_cols": filtered_cols,
356
+ "interactive": interactive if interactive is not None else self.interactive
357
+ }
358
+
359
+ # Handle fields object (e.g., from dataclass)
360
+ if hasattr(value, '__dataclass_fields__'):
361
+ field_names = [field.name for field in fields(value)]
362
+ choices = [self.column_mapping.get(name, name) for name in field_names]
363
+ return {
364
+ "choices": choices,
365
+ "value": self.initial_selected if self.initial_selected else choices,
366
+ "interactive": interactive if interactive is not None else self.interactive
367
+ }
368
+
369
+ return super().update(value, interactive)
370
+
371
 
372
+ # Define filters and mappings
373
+ filters = {
374
+ "IOI Metrics": ["ioi"],
375
+ "Performance Metrics": ["performance"]
376
+ }
377
 
378
+ mappings = {
379
+ "ioi_score_1": "IOI Score (Type 1)",
380
+ "ioi_score_2": "IOI Score (Type 2)",
381
+ "other_metric": "Other Metric",
382
+ "performance_1": "Performance Metric 1"
383
+ }
384
+
385
+ column_filters = filters
386
+ column_mapping = mappings
387
+ initial_columns = renamed_df
388
 
 
 
 
389
 
390
+ # Initialize SmartSelectColumns
391
+ smart_columns = SmartSelectColumns(
392
+ column_filters=filters,
393
+ column_mapping=mappings,
394
+ initial_selected=initial_columns,
395
+ multiselect=True
396
+ )
397
 
398
+ return gr.Leaderboard(
399
+ value=renamed_df,
400
+ datatype=[c.type for c in fields(column_class)],
401
+ select_columns=smart_columns,
 
 
 
402
  search_columns=["Method"],
403
  hide_columns=[],
404
+ interactive=False
405
  )
406
 
407
 
 
408
  # def init_leaderboard_mib_subgraph(dataframe, track):
409
  # """Initialize the subgraph leaderboard with group-based column selection."""
410
  # if dataframe is None or dataframe.empty:
custom-select-columns.py ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ from typing import List, Dict, Union, Optional
4
+
5
+ class SmartSelectColumns(gr.SelectColumns):
6
+ """
7
+ Enhanced SelectColumns component that supports substring matching and column mapping.
8
+ Inherits from gr.SelectColumns but adds additional filtering capabilities.
9
+ """
10
+ def __init__(
11
+ self,
12
+ *args,
13
+ column_filters: Optional[Dict[str, List[str]]] = None,
14
+ column_mapping: Optional[Dict[str, str]] = None,
15
+ **kwargs
16
+ ):
17
+ """
18
+ Initialize the SmartSelectColumns component.
19
+
20
+ Args:
21
+ column_filters: Dict mapping filter names to lists of substrings to match
22
+ column_mapping: Dict mapping display names to actual column names
23
+ *args, **kwargs: Arguments passed to parent SelectColumns
24
+ """
25
+ super().__init__(*args, **kwargs)
26
+ self.column_filters = column_filters or {}
27
+ self.column_mapping = column_mapping or {}
28
+
29
+ def preprocess(self, x: List[str]) -> List[str]:
30
+ """Transform selected display names back to actual column names."""
31
+ if self.column_mapping:
32
+ reverse_mapping = {v: k for k, v in self.column_mapping.items()}
33
+ return [reverse_mapping.get(col, col) for col in x]
34
+ return x
35
+
36
+ def get_filtered_columns(self, df: pd.DataFrame) -> Dict[str, List[str]]:
37
+ """
38
+ Get columns filtered by substring matches.
39
+
40
+ Args:
41
+ df: Input DataFrame
42
+
43
+ Returns:
44
+ Dict mapping filter names to lists of matching columns
45
+ """
46
+ filtered_cols = {}
47
+
48
+ for filter_name, substrings in self.column_filters.items():
49
+ matching_cols = []
50
+ for col in df.columns:
51
+ if any(substr.lower() in col.lower() for substr in substrings):
52
+ matching_cols.append(col)
53
+ filtered_cols[filter_name] = matching_cols
54
+
55
+ return filtered_cols
56
+
57
+ def update(
58
+ self,
59
+ value: Union[pd.DataFrame, Dict[str, List[str]]],
60
+ interactive: Optional[bool] = None
61
+ ) -> Dict:
62
+ """
63
+ Update the component with new values.
64
+
65
+ Args:
66
+ value: Either a DataFrame or dict of predefined column groups
67
+ interactive: Whether the component should be interactive
68
+
69
+ Returns:
70
+ Dict containing the update configuration
71
+ """
72
+ if isinstance(value, pd.DataFrame):
73
+ # Get filtered column groups
74
+ filtered_cols = self.get_filtered_columns(value)
75
+
76
+ # Create display names for columns if mapping exists
77
+ choices = list(value.columns)
78
+ if self.column_mapping:
79
+ choices = [self.column_mapping.get(col, col) for col in choices]
80
+
81
+ return {
82
+ "choices": choices,
83
+ "filtered_cols": filtered_cols,
84
+ "interactive": interactive if interactive is not None else self.interactive
85
+ }
86
+ return super().update(value, interactive)
87
+
88
+ # Example usage
89
+ if __name__ == "__main__":
90
+ df = pd.DataFrame({
91
+ "ioi_score_1": [1, 2, 3],
92
+ "ioi_score_2": [4, 5, 6],
93
+ "other_metric": [7, 8, 9],
94
+ "performance_1": [10, 11, 12]
95
+ })
96
+
97
+ # Define filters and mappings
98
+ column_filters = {
99
+ "IOI Metrics": ["ioi"],
100
+ "Performance Metrics": ["performance"]
101
+ }
102
+
103
+ column_mapping = {
104
+ "ioi_score_1": "IOI Score (Type 1)",
105
+ "ioi_score_2": "IOI Score (Type 2)",
106
+ "other_metric": "Other Metric",
107
+ "performance_1": "Performance Metric 1"
108
+ }
109
+
110
+ # Create interface
111
+ with gr.Blocks() as demo:
112
+ select_cols = SmartSelectColumns(
113
+ column_filters=column_filters,
114
+ column_mapping=column_mapping,
115
+ multiselect=True
116
+ )
117
+
118
+ # Update component with DataFrame
119
+ select_cols.update(df)
120
+
121
+ demo.launch()
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
+ import gradio as gr
155
+ import pandas as pd
156
+ from typing import List, Dict, Union, Optional, Any
157
+ from dataclasses import fields
158
+
159
+ class SmartSelectColumns(gr.SelectColumns):
160
+ """
161
+ Enhanced SelectColumns component for Gradio Leaderboard with smart filtering and mapping capabilities.
162
+ """
163
+ def __init__(
164
+ self,
165
+ column_filters: Optional[Dict[str, List[str]]] = None,
166
+ column_mapping: Optional[Dict[str, str]] = None,
167
+ initial_selected: Optional[List[str]] = None,
168
+ *args,
169
+ **kwargs
170
+ ):
171
+ """
172
+ Initialize SmartSelectColumns with enhanced functionality.
173
+
174
+ Args:
175
+ column_filters: Dict mapping filter names to lists of substrings to match
176
+ column_mapping: Dict mapping actual column names to display names
177
+ initial_selected: List of column names to be initially selected
178
+ *args, **kwargs: Additional arguments passed to parent SelectColumns
179
+ """
180
+ super().__init__(*args, **kwargs)
181
+ self.column_filters = column_filters or {}
182
+ self.column_mapping = column_mapping or {}
183
+ self.reverse_mapping = {v: k for k, v in self.column_mapping.items()} if column_mapping else {}
184
+ self.initial_selected = initial_selected or []
185
+
186
+ def preprocess(self, x: List[str]) -> List[str]:
187
+ """
188
+ Transform selected display names back to actual column names.
189
+
190
+ Args:
191
+ x: List of selected display names
192
+
193
+ Returns:
194
+ List of actual column names
195
+ """
196
+ return [self.reverse_mapping.get(col, col) for col in x]
197
+
198
+ def postprocess(self, y: List[str]) -> List[str]:
199
+ """
200
+ Transform actual column names to display names.
201
+
202
+ Args:
203
+ y: List of actual column names
204
+
205
+ Returns:
206
+ List of display names
207
+ """
208
+ return [self.column_mapping.get(col, col) for col in y]
209
+
210
+ def get_filtered_columns(self, df: pd.DataFrame) -> Dict[str, List[str]]:
211
+ """
212
+ Get columns filtered by substring matches.
213
+
214
+ Args:
215
+ df: Input DataFrame
216
+
217
+ Returns:
218
+ Dict mapping filter names to lists of matching display names
219
+ """
220
+ filtered_cols = {}
221
+
222
+ for filter_name, substrings in self.column_filters.items():
223
+ matching_cols = []
224
+ for col in df.columns:
225
+ if any(substr.lower() in col.lower() for substr in substrings):
226
+ display_name = self.column_mapping.get(col, col)
227
+ matching_cols.append(display_name)
228
+ filtered_cols[filter_name] = matching_cols
229
+
230
+ return filtered_cols
231
+
232
+ def update(
233
+ self,
234
+ value: Union[pd.DataFrame, Dict[str, List[str]], Any],
235
+ interactive: Optional[bool] = None
236
+ ) -> Dict:
237
+ """
238
+ Update component with new values, supporting DataFrame fields.
239
+
240
+ Args:
241
+ value: DataFrame, dict of columns, or fields object
242
+ interactive: Whether component should be interactive
243
+
244
+ Returns:
245
+ Dict containing update configuration
246
+ """
247
+ if isinstance(value, pd.DataFrame):
248
+ filtered_cols = self.get_filtered_columns(value)
249
+ choices = [self.column_mapping.get(col, col) for col in value.columns]
250
+
251
+ # Set initial selection if provided
252
+ value = self.initial_selected if self.initial_selected else choices
253
+
254
+ return {
255
+ "choices": choices,
256
+ "value": value,
257
+ "filtered_cols": filtered_cols,
258
+ "interactive": interactive if interactive is not None else self.interactive
259
+ }
260
+
261
+ # Handle fields object (e.g., from dataclass)
262
+ if hasattr(value, '__dataclass_fields__'):
263
+ field_names = [field.name for field in fields(value)]
264
+ choices = [self.column_mapping.get(name, name) for name in field_names]
265
+ return {
266
+ "choices": choices,
267
+ "value": self.initial_selected if self.initial_selected else choices,
268
+ "interactive": interactive if interactive is not None else self.interactive
269
+ }
270
+
271
+ return super().update(value, interactive)
272
+
273
+ def initialize_leaderboard(df: pd.DataFrame, column_class: Any,
274
+ filters: Dict[str, List[str]],
275
+ mappings: Dict[str, str],
276
+ initial_columns: Optional[List[str]] = None) -> gr.Leaderboard:
277
+ """
278
+ Initialize a Gradio Leaderboard with SmartSelectColumns.
279
+
280
+ Args:
281
+ df: Input DataFrame
282
+ column_class: Class containing column definitions (e.g., AutoEvalColumn_mib_subgraph)
283
+ filters: Column filters for substring matching
284
+ mappings: Column name mappings (actual -> display)
285
+ initial_columns: List of columns to show initially
286
+
287
+ Returns:
288
+ Configured Leaderboard instance
289
+ """
290
+ # Create renamed DataFrame with display names
291
+ renamed_df = df.rename(columns=mappings)
292
+
293
+ # Initialize SmartSelectColumns
294
+ smart_columns = SmartSelectColumns(
295
+ column_filters=filters,
296
+ column_mapping=mappings,
297
+ initial_selected=initial_columns,
298
+ multiselect=True
299
+ )
300
+
301
+ return gr.Leaderboard(
302
+ value=renamed_df,
303
+ datatype=[c.type for c in fields(column_class)],
304
+ select_columns=smart_columns,
305
+ search_columns=["Method"],
306
+ hide_columns=[],
307
+ interactive=False
308
+ )
309
+
310
+ # Example usage
311
+ if __name__ == "__main__":
312
+ # Sample data
313
+ df = pd.DataFrame({
314
+ "ioi_score_1": [1, 2, 3],
315
+ "ioi_score_2": [4, 5, 6],
316
+ "other_metric": [7, 8, 9],
317
+ "performance_1": [10, 11, 12],
318
+ "Method": ["A", "B", "C"]
319
+ })
320
+
321
+ # Define filters and mappings
322
+ filters = {
323
+ "IOI Metrics": ["ioi"],
324
+ "Performance Metrics": ["performance"]
325
+ }
326
+
327
+ mappings = {
328
+ "ioi_score_1": "IOI Score (Type 1)",
329
+ "ioi_score_2": "IOI Score (Type 2)",
330
+ "other_metric": "Other Metric",
331
+ "performance_1": "Performance Metric 1"
332
+ }
333
+
334
+ # Create demo interface
335
+ with gr.Blocks() as demo:
336
+ # Initialize leaderboard with smart columns
337
+ leaderboard = initialize_leaderboard(
338
+ df=df,
339
+ column_class=None, # Replace with your actual column class
340
+ filters=filters,
341
+ mappings=mappings,
342
+ initial_columns=["Method", "IOI Score (Type 1)"]
343
+ )
344
+
345
+ demo.launch()