| 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], |
| ) |
|
|