dna-benchmark / src /data.py
github-actions[bot]
feat: active filter banner, scope/filter tab rename, refactor docs
803219b
Raw History Blame
4.59 kB
import os
import pandas as pd
from dotenv import load_dotenv
from huggingface_hub import HfApi, hf_hub_download
from src.constants import TASK_SEQ_LENGTHS, TASK_TO_CATEGORY
load_dotenv()
HF_TOKEN = os.environ.get("HF_TOKEN")
LEADERBOARD_DATASET = os.environ.get("LEADERBOARD_DATASET", "lokahq/genomic-benchmark-metrics")
def load_data() -> pd.DataFrame:
"""Load all model parquet files from the HF Hub dataset and return a concatenated DataFrame.
Each file under data/*.parquet corresponds to one model. Derived columns task_category and
task_seq_length are added from the constants maps.
"""
api = HfApi(token=HF_TOKEN)
files = [
f
for f in api.list_repo_files(LEADERBOARD_DATASET, repo_type="dataset")
if f.startswith("results/") and f.endswith(".parquet")
]
frames = [
pd.read_parquet(hf_hub_download(LEADERBOARD_DATASET, f, repo_type="dataset", token=HF_TOKEN))
for f in files
]
df = pd.concat(frames, ignore_index=True)
# Normalize task names to lowercase so TASK_TO_CATEGORY mapping works regardless
# of how the benchmark runner capitalizes them (e.g. "H3K27ac" → "h3k27ac")
df["task_name"] = df["task_name"].str.lower()
df["task_category"] = df["task_name"].map(TASK_TO_CATEGORY).fillna("other")
df["task_seq_length"] = df["task_name"].map(TASK_SEQ_LENGTHS)
if "run_at" in df.columns:
df["run_at"] = pd.to_datetime(df["run_at"], utc=True, errors="coerce")
return df
def _subsample_priority(val) -> float:
"""Map subsample_train value to sort priority. NULL/0/1 = production = highest priority."""
if val is None or (isinstance(val, float) and pd.isna(val)) or val == 0 or val == 1:
return float("inf")
return float(val)
def deduplicate(df: pd.DataFrame) -> pd.DataFrame:
"""Keep best run per (embedding_config_hash, head_type).
embedding_config_hash is task-specific: it hashes (model, pooling, layer_selection, dataset, task).
Two rows for the same config but different tasks will have different hashes, so dedup correctly
keeps one row per (config, task, head) — not one row per config globally.
'Best' = production run preferred (subsample_train NULL/0/1 → inf priority),
then highest subsample fraction, then most recent run_at.
"""
if "run_at" not in df.columns:
return df
dedup_cols = []
if "embedding_config_hash" in df.columns:
dedup_cols.append("embedding_config_hash")
if "head_type" in df.columns:
dedup_cols.append("head_type")
if not dedup_cols:
return df
df = df.copy()
df["_sub_priority"] = df.get("subsample_train", pd.Series(dtype=float)).map(_subsample_priority)
df = df.sort_values(["_sub_priority", "run_at"], ascending=[False, False])
return df.drop_duplicates(subset=dedup_cols).drop(columns=["_sub_priority"]).reset_index(drop=True)
def apply_filters(df: pd.DataFrame, filters: dict) -> pd.DataFrame:
"""Apply user-selected filters and return the filtered DataFrame."""
result = df.copy()
subsample_mode = filters.get("subsample_train")
if subsample_mode == "full" and "subsample_train" in result.columns:
result = result[result["subsample_train"].isna() | (result["subsample_train"] == 0)]
elif subsample_mode == "subsampled" and "subsample_train" in result.columns:
result = result[result["subsample_train"].notna() & (result["subsample_train"] > 0)]
for col, min_key, max_key in [
("model_params", "model_params_min", "model_params_max"),
("embedding_dim", "embedding_dim_min", "embedding_dim_max"),
("max_context_size", "max_context_size_min", "max_context_size_max"),
]:
if col not in result.columns:
continue
lo = filters.get(min_key)
hi = filters.get(max_key)
if lo is not None:
result = result[result[col] >= lo]
if hi is not None:
result = result[result[col] <= hi]
excluded_models = filters.get("exclude_models") or []
if excluded_models:
result = result[~result["model_alias"].isin(excluded_models)]
pooling_strategies = filters.get("pooling_strategies") or []
if pooling_strategies and "pooling_strategy" in result.columns:
result = result[result["pooling_strategy"].isin(pooling_strategies)]
excluded_runs = filters.get("exclude_run_ids") or []
if excluded_runs and "run_id" in result.columns:
result = result[~result["run_id"].isin(excluded_runs)]
return result.reset_index(drop=True)