PoVisLE / views /example_view.py
gamemeine's picture
Improrve ui, fix light theme, add arxiv url
2487097
Raw
History Blame Contribute Delete
7.21 kB
from __future__ import annotations
import gradio as gr
import pandas as pd
ALL_OPTION = "All"
NO_SUBCATEGORY_OPTION = "No subcategory"
TASK_TYPE_OPTIONS = ["mcq", "yes/no", "open"]
TASK_TYPE_FILTER_OPTIONS = [ALL_OPTION, *TASK_TYPE_OPTIONS]
EXAMPLE_COLUMNS = [
"id",
"category",
"subcategory",
"image",
"question",
"choices",
"answer",
"include",
"check_casing",
"check_diacritics",
]
EXAMPLE_DATATYPES = ["str", "str", "str", "html", "str", "str", "str", "str", "str", "str"]
EXAMPLE_COLUMN_WIDTHS = ["90px", "128px", "130px", "110px", "300px", "230px", "170px", "190px", "90px", "100px"]
TASK_TYPE_LABELS = {
"mcq": "mcq",
"yn": "yes/no",
"yes/no": "yes/no",
"yes_no": "yes/no",
"yes-no": "yes/no",
"open": "open",
}
EXAMPLES_SECTION_HTML = """
<section class="povisle-examples-heading">
<div class="povisle-section-label">Examples</div>
<h2 class="povisle-section-title">Dataset Examples</h2>
<p>
Browse representative PoVisLE items across task types, categories, and subcategories.
</p>
</section>
"""
def normalize_text(value: object) -> object:
if not isinstance(value, str):
return value
return value.replace("\r\n", "\n").replace("\r", "\n")
def compact_text(value: object) -> object:
if not isinstance(value, str):
return value
return value.replace("\t", " ").strip()
def normalize_task_type(value: object) -> str:
if not isinstance(value, str):
return ""
return TASK_TYPE_LABELS.get(value.strip().lower(), value.strip().lower())
def category_options(examples_df: pd.DataFrame) -> list[str]:
if examples_df.empty:
return [ALL_OPTION]
categories = sorted(examples_df["category"].dropna().astype(str).unique().tolist())
return [ALL_OPTION, *categories]
def format_subcategory(value: object) -> str:
if pd.isna(value):
return NO_SUBCATEGORY_OPTION
text = str(value).strip()
return text or NO_SUBCATEGORY_OPTION
def subcategory_options(examples_df: pd.DataFrame, selected_category: str) -> list[str]:
if examples_df.empty:
return [ALL_OPTION]
filtered = examples_df
if selected_category and selected_category != ALL_OPTION:
filtered = filtered[filtered["category"].astype(str) == selected_category]
subcategories = sorted(filtered["subcategory"].map(format_subcategory).dropna().unique().tolist())
return [ALL_OPTION, *subcategories]
def filter_examples(
examples_df: pd.DataFrame,
selected_task_type: str | None,
selected_category: str,
selected_subcategory: str,
) -> pd.DataFrame:
if examples_df.empty:
return pd.DataFrame(columns=EXAMPLE_COLUMNS)
filtered = examples_df.copy()
if filtered.empty:
return pd.DataFrame(columns=EXAMPLE_COLUMNS)
if selected_task_type and selected_task_type != ALL_OPTION:
filtered = filtered[filtered["task"].map(normalize_task_type) == selected_task_type]
if selected_category and selected_category != ALL_OPTION:
filtered = filtered[filtered["category"].astype(str) == selected_category]
if selected_subcategory and selected_subcategory != ALL_OPTION:
filtered = filtered[filtered["subcategory"].map(format_subcategory) == selected_subcategory]
filtered["question"] = filtered["question"].map(normalize_text)
filtered["question"] = filtered["question"].map(compact_text)
filtered["choices"] = filtered["choices"].map(normalize_text)
filtered["choices"] = filtered["choices"].map(compact_text)
filtered["include"] = filtered["include"].map(normalize_text)
filtered["include"] = filtered["include"].map(compact_text)
filtered["id"] = filtered["id"].astype(str)
filtered = filtered.sort_values(
by=["id", "question"],
ascending=[False, True],
kind="stable",
)
filtered = filtered[EXAMPLE_COLUMNS]
return filtered.reset_index(drop=True)
def render_examples_tab(examples_df: pd.DataFrame) -> None:
with gr.Group(elem_id="examples-section"):
gr.HTML(EXAMPLES_SECTION_HTML)
initial_category = ALL_OPTION
initial_subcategory = ALL_OPTION
initial_task_type = ALL_OPTION
initial_value = filter_examples(examples_df, initial_task_type, initial_category, initial_subcategory)
filter_label_style = (
"color: #181416; font-size: 0.86rem; font-weight: 700; "
"line-height: 1.2; margin: 0 0 8px;"
)
with gr.Row(elem_id="examples-filter-row"):
with gr.Column(elem_classes=["povisle-filter-field"]):
gr.HTML(f'<div style="{filter_label_style}">Type of task</div>')
task_type_filter = gr.Dropdown(
choices=TASK_TYPE_FILTER_OPTIONS,
value=initial_task_type,
multiselect=False,
allow_custom_value=False,
label="Type of task",
show_label=False,
)
with gr.Column(elem_classes=["povisle-filter-field"]):
gr.HTML(f'<div style="{filter_label_style}">Category</div>')
category_filter = gr.Dropdown(
choices=category_options(examples_df),
value=initial_category,
allow_custom_value=False,
label="Category",
show_label=False,
)
with gr.Column(elem_classes=["povisle-filter-field"]):
gr.HTML(f'<div style="{filter_label_style}">Subcategory</div>')
subcategory_filter = gr.Dropdown(
choices=subcategory_options(examples_df, initial_category),
value=initial_subcategory,
allow_custom_value=False,
label="Subcategory",
show_label=False,
)
examples_table = gr.Dataframe(
value=initial_value,
headers=EXAMPLE_COLUMNS,
datatype=EXAMPLE_DATATYPES,
max_height=660,
interactive=False,
wrap=True,
column_widths=EXAMPLE_COLUMN_WIDTHS,
buttons=[],
elem_id="examples-table",
)
for component in (task_type_filter, subcategory_filter):
component.change(
fn=lambda selected_task_type, selected_category, selected_subcategory: filter_examples(
examples_df,
selected_task_type,
selected_category,
selected_subcategory,
),
inputs=[task_type_filter, category_filter, subcategory_filter],
outputs=examples_table,
)
category_filter.change(
fn=lambda selected_task_type, selected_category: (
gr.update(choices=subcategory_options(examples_df, selected_category), value=ALL_OPTION),
filter_examples(examples_df, selected_task_type, selected_category, ALL_OPTION),
),
inputs=[task_type_filter, category_filter],
outputs=[subcategory_filter, examples_table],
)