import os
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import streamlit as st
from plotly.subplots import make_subplots
# ---------------------------------------------------------------------
# Page config (must be the first Streamlit command)
# ---------------------------------------------------------------------
st.set_page_config(
page_title="NTv3 Benchmark",
layout="wide",
)
import initial_release # noqa: E402 (reads its CSV on import, so after the page config)
# ---------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------
COLORS = {
'blue_0': '#004697',
'blue_1': '#3973fc',
'blue_2': '#7ea4fc',
'blue_3': '#c3d5fc',
'red_1': '#ff554d',
'green_1': '#00b050',
'green_3': '#c6e0b4',
'gold_1': '#fdb932',
'orange_1': '#ff975e',
'purple_1': '#9a6ce4',
'purple_2': '#bb9aef',
'gray_1': '#808080',
'gray_2': '#b3b3b3',
'cyan_1': '#0096b4',
'magenta_1': '#b428a0',
}
ASSAY_TYPE_MAPPING = {
'ATAC-seq': 'chromatin accessibility',
'DNase-seq': 'chromatin accessibility',
'Histone ChIP-seq': 'histone modifications',
'TF ChIP-seq': 'TF binding',
'PRO-cap': 'transcription initiation',
'eCLIP': 'RNA binding sites',
'RNA-seq': 'gene expression',
'ribo-seq': 'mRNA translation',
}
ASSAY_COLORS = {
'chromatin accessibility': '#004697',
'histone modifications': '#cc0000',
'TF binding': '#00b050',
'transcription initiation': '#ff9900',
'RNA binding sites': '#9933cc',
'gene expression': '#009900',
'mRNA translation': '#ff6699',
'other': '#808080',
}
CLADE_COLORS = {
"Animals": COLORS['blue_1'],
"Plants": COLORS['green_1'],
"Fungi": COLORS['gold_1'],
"Protists": COLORS['purple_1'],
}
# CSV model name -> the label the paper figure uses. Other models in the CSV (v1 NTv3
# checkpoints, small BPNet / Residual CNN) are kept in the data but not shown.
MODEL_LABELS = {
"BPNet arch. 6M": "BPNet",
"Residual CNN 44M": "Residual CNN",
"HyenaDNA 7M": "HyenaDNA",
"Caduceus 7M": "Caduceus",
"NTv2 500M": "NTv2",
"Evo2 1B": "Evo2",
"PlantCAD2 88M": "PlantCAD2",
"Borzoi": "Borzoi",
"AlphaGenome": "AlphaGenome",
"NTv3 700M (tracks)": "NTv3",
}
NTV3 = "NTv3"
# In the paper figure's architecture blocks, with its colours.
MODEL_COLORS = {
"BPNet": COLORS['cyan_1'],
"Residual CNN": COLORS['magenta_1'],
"HyenaDNA": COLORS['gold_1'],
"Caduceus": COLORS['purple_2'],
"NTv2": COLORS['gray_1'],
"Evo2": COLORS['green_3'],
"PlantCAD2": COLORS['purple_1'],
"Borzoi": COLORS['gray_2'],
"AlphaGenome": COLORS['orange_1'],
NTV3: COLORS['blue_0'],
}
MODEL_TRAINING_STATUS = {
"BPNet": "SCRATCH",
"Residual CNN": "SCRATCH",
"HyenaDNA": "PRE",
"Caduceus": "PRE",
"NTv2": "PRE",
"Evo2": "PRE",
"PlantCAD2": "PRE",
"Borzoi": "PRE",
"AlphaGenome": "PRE",
NTV3: "POS",
}
MODEL_NAMES = list(MODEL_COLORS.keys())
# CSV species key -> label, grouped by clade, in the paper's order.
SPECIES_GROUPS = {
"Animals": {"human": "Human", "cattle": "Cattle", "rat": "Rat"},
"Plants": {
"arabidopsis": "A. thaliana",
"rice": "Rice",
"maize": "Maize",
"tomato": "Tomato",
},
"Fungi": {"yeast": "S. cerevisiae", "fission yeast": "S. pombe"},
"Protists": {"plasmodium": "P. falciparum", "dictyostelium": "D. discoideum"},
}
SPECIES_LABEL = {k: v for group in SPECIES_GROUPS.values() for k, v in group.items()}
SPECIES_ORDER = list(SPECIES_LABEL)
SPECIES_CLADE = {s: name for name, group in SPECIES_GROUPS.items() for s in group}
SPECIES_ICON = {
"human": "๐ง",
"cattle": "๐",
"rat": "๐",
"arabidopsis": "๐ฑ",
"rice": "๐พ",
"maize": "๐ฝ",
"tomato": "๐
",
"yeast": "๐",
"fission yeast": "๐บ",
"plasmodium": "๐ฆ",
"dictyostelium": "๐ฆ ",
}
SPECIES_COMMON_NAME = {
"arabidopsis": "thale cress",
"yeast": "baker's yeast",
"fission yeast": "fission yeast",
"plasmodium": "malaria parasite",
"dictyostelium": "social amoeba",
}
METRIC_LABEL = "Pearson correlation"
_LAST_UPDATED = "Sep 24, 2026"
_INTRO = """
The **NTv3 Benchmark** is 155 long-range functional genomics tracks for evaluating models
under realistic 32 kb input, single-base-pair output settings. The tracks span chromatin accessibility (ATAC-seq),
histone modifications and transcription factor binding (ChIP-seq), transcription initiation (PRO-cap),
RNA binding (eCLIP), gene expression (RNA-seq) and translation (Ribo-seq).
The benchmark covers 11 phylogenetically diverse species:
**animals** (human, cattle, rat), **plants** (*A. thaliana*, rice, maize, tomato),
**fungi** (*S. cerevisiae*, *S. pombe*) and **protists** (*P. falciparum*, *D. discoideum*).
The metric is the **Pearson correlation** on the test set, per track, averaged over three
seeds where available. Not every model was run on every species, so scores are never
averaged across species: pick a species in the sidebar for its own leaderboard, where every
model shown was evaluated on all of that species' tracks. AlphaGenome is fine-tuned from its
fold-1 checkpoint on human, whose test regions the all-folds checkpoint saw, and from its
all-folds checkpoint on every other species.
"""
HERE = os.path.dirname(os.path.abspath(__file__)) # /app/src
PROJECT_ROOT = os.path.dirname(HERE) # /app
DATA_DIR = os.path.join(PROJECT_ROOT, "data")
SINGLE_TABLE_PATH = os.path.join(DATA_DIR, "ntv3_benchmark_results.csv")
# ---------------------------------------------------------------------
# Data loading & preprocessing
# ---------------------------------------------------------------------
@st.cache_data
def load_raw_data() -> pd.DataFrame:
df = pd.read_csv(SINGLE_TABLE_PATH)
df.columns = [c.strip() for c in df.columns]
return df
@st.cache_data
def load_track_data() -> pd.DataFrame:
"""One row per (species, track, model): the score averaged over seeds."""
df = load_raw_data().rename(columns={"Metric": "Score", "model_name": "Model"})
df["Model"] = df["Model"].map(MODEL_LABELS)
df = df[df["Model"].notna() & df["species"].isin(SPECIES_ORDER)]
df["Score"] = pd.to_numeric(df["Score"], errors="coerce")
keys = ["species", "datasets", "Model", "assay_type", "track_name_clean"]
out = df.groupby(keys, as_index=False, dropna=False).agg(
Score=("Score", "mean"), Seeds=("Score", "size")
)
out["assay_type"] = out["assay_type"].map(ASSAY_TYPE_MAPPING).fillna("other")
return out
@st.cache_data
def load_run_data() -> pd.DataFrame:
"""One row per training run: its best checkpoint's step and GPU hours."""
df = load_raw_data().rename(columns={"model_name": "Model"})
df["Model"] = df["Model"].map(MODEL_LABELS)
df = df[df["Model"].notna() & df["species"].isin(SPECIES_ORDER)]
run_cols = ["species", "Model", "best_step", "best_step_time", "running_time"]
runs = df.drop_duplicates(run_cols).copy()
# Training steps only: excludes job setup and validation, whose cadence differs
# between runs of the benchmark.
# Parsed one by one: pandas 3 misparses a column mixing fraction lengths.
hours = runs["best_step_train_time"].map(
lambda v: pd.Timedelta(v).total_seconds() / 3600 if pd.notna(v) else np.nan
)
runs["GPU hours"] = hours * pd.to_numeric(runs["num_gpus"], errors="coerce")
runs["Tokens (billions)"] = pd.to_numeric(runs["best_step"], errors="coerce") / 1e9
return runs
_TRACKS = load_track_data()
_RUNS = load_run_data()
def models_in(df: pd.DataFrame) -> list[str]:
"""Models present in `df`, in the paper's block order."""
present = set(df["Model"])
return [m for m in MODEL_NAMES if m in present]
# ---------------------------------------------------------------------
# Computation helpers
# ---------------------------------------------------------------------
def build_species_scores(df: pd.DataFrame) -> pd.DataFrame:
"""Mean over tracks per (species, model): the paper figure's points."""
return df.groupby(["species", "Model"], as_index=False).agg(
Score=("Score", "mean"),
Tracks=("datasets", "nunique"),
Seeds=("Seeds", "max"),
)
def build_leaderboard(df: pd.DataFrame) -> pd.DataFrame:
if df.empty:
return pd.DataFrame(columns=["Model", "Training", "Num entries", "Mean score"])
agg = df.groupby("Model").agg(
**{
"Num entries": ("Score", "count"),
"Seeds": ("Seeds", "max"),
"Mean score": ("Score", "mean"),
}
).reset_index()
agg["Mean score"] = agg["Mean score"].round(3)
agg["Training"] = agg["Model"].map(MODEL_TRAINING_STATUS).fillna("UNKNOWN")
agg = agg.sort_values("Mean score", ascending=False).reset_index(drop=True)
agg = agg[["Model", "Training", "Num entries", "Seeds", "Mean score"]]
agg.index += 1
return agg
def build_category_model_df(df: pd.DataFrame) -> pd.DataFrame:
"""Mean score per (assay category, model)."""
if df.empty:
return pd.DataFrame(columns=["Category", "Model", "Mean score"])
out = (
df.groupby(["assay_type", "Model"], as_index=False)["Score"].mean()
.rename(columns={"assay_type": "Category", "Score": "Mean score"})
)
out["Mean score"] = out["Mean score"].round(3)
return out
def build_pairwise_scatter_df(df: pd.DataFrame, model_a: str, model_b: str) -> pd.DataFrame:
"""Scores of two models on the tracks both were evaluated on."""
sub = df[df["Model"].isin([model_a, model_b])]
wide = sub.pivot_table(
index=["species", "assay_type", "datasets", "track_name_clean"],
columns="Model",
values="Score",
).reset_index()
if model_a not in wide.columns or model_b not in wide.columns:
return pd.DataFrame()
wide = wide.dropna(subset=[model_a, model_b])
wide["Species"] = wide["species"].map(SPECIES_LABEL)
wide["Track"] = wide["Species"] + " / " + wide["track_name_clean"].astype(str)
return wide.rename(columns={model_a: "Model A", model_b: "Model B"})
def aggregate_pairs_by_species(pairs: pd.DataFrame) -> pd.DataFrame:
"""One point per species: both models' means over the tracks they share there."""
clade = {s: name for name, group in SPECIES_GROUPS.items() for s in group}
out = pairs.groupby(["species", "Species"], as_index=False).agg(
**{
"Model A": ("Model A", "mean"),
"Model B": ("Model B", "mean"),
"Shared tracks": ("datasets", "size"),
}
)
out["Clade"] = out["species"].map(clade)
out["Track"] = out["Species"]
return out
# ---------------------------------------------------------------------
# Plots
# ---------------------------------------------------------------------
def plot_species_overview(scores: pd.DataFrame, models: list[str]) -> go.Figure:
"""The paper figure: one column per species, one point per model evaluated on it."""
cols = [s for s in SPECIES_ORDER if s in set(scores["species"])]
labels = [SPECIES_LABEL[s] for s in cols]
fig = go.Figure()
# Thin guide line per species, from the weakest to the strongest model.
span = scores.groupby("species")["Score"].agg(["min", "max"]).reindex(cols)
for label, (lo, hi) in zip(labels, span.itertuples(index=False)):
fig.add_shape(
type="line", x0=label, x1=label, y0=lo, y1=hi, layer="below",
line=dict(color="rgba(128,128,128,0.35)", width=2),
)
# AlphaGenome is drawn last so it stays visible where it sits on NTv3's marker;
# `legendrank` keeps the legend in the paper's block order.
draw_order = [m for m in models if m != "AlphaGenome"] + (
["AlphaGenome"] if "AlphaGenome" in models else []
)
for model in draw_order:
sub = scores[scores["Model"] == model].set_index("species").reindex(cols)
is_ntv3 = model == NTV3
fig.add_trace(
go.Scatter(
x=labels,
y=sub["Score"],
mode="markers",
name=model,
legendrank=models.index(model),
marker=dict(
color=MODEL_COLORS[model],
size=16 if is_ntv3 else 11,
symbol="diamond" if is_ntv3 else "circle",
line=dict(color="rgba(0,0,0,0.5)", width=1),
),
customdata=np.stack([sub["Tracks"], sub["Seeds"]], axis=-1),
hovertemplate=(
f"{model}
%{{x}}
{METRIC_LABEL}: %{{y:.3f}}"
"
%{customdata[0]} tracks, %{customdata[1]} seed(s)"
),
)
)
# Clade separators and clade names above the plot.
x = 0
for name, group in SPECIES_GROUPS.items():
n = sum(1 for s in group if s in cols)
if n == 0:
continue
fig.add_annotation(
x=x + (n - 1) / 2, y=1.0, xref="x", yref="paper", yanchor="bottom",
text=f"{name}", showarrow=False,
)
x += n
if x < len(cols):
fig.add_vline(x=x - 0.5, line=dict(color="rgba(128,128,128,0.4)", dash="dot"))
fig.update_xaxes(categoryorder="array", categoryarray=labels, title_text="")
fig.update_yaxes(
title_text=f"{METRIC_LABEL} on test set",
showgrid=True,
gridcolor="rgba(128,128,128,0.15)",
automargin=True,
tickformat=".1f",
)
fig.update_layout(
height=600,
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
legend=dict(orientation="h", yanchor="top", y=-0.1, x=0.5, xanchor="center"),
margin=dict(t=40, l=80, r=10, b=40),
)
return fig
def plot_mean_bars(leaderboard: pd.DataFrame) -> go.Figure:
bar_df = leaderboard.sort_values("Mean score", ascending=True)
fig = px.bar(
bar_df,
x="Model",
y="Mean score",
color="Model",
color_discrete_map=MODEL_COLORS,
category_orders={"Model": bar_df["Model"].tolist()},
)
fig.update_layout(
height=500,
xaxis_title="",
yaxis_title=METRIC_LABEL,
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
bargap=0.08,
)
fig.update_xaxes(showticklabels=False)
return fig
def plot_breakdown_facets_sorted_models(breakdown_df: pd.DataFrame, height: int = 300):
categories = sorted(breakdown_df["Category"].dropna().unique())
if not categories:
return None
y_min = breakdown_df["Mean score"].min()
y_max = breakdown_df["Mean score"].max()
pad = 0.05 * (y_max - y_min if y_max > y_min else 1.0)
y_range = [min(0, y_min - pad), y_max + pad]
fig = make_subplots(
rows=1,
cols=len(categories),
subplot_titles=categories,
shared_yaxes=True,
horizontal_spacing=0.04,
)
for i, cat in enumerate(categories):
sub = breakdown_df[breakdown_df["Category"] == cat].sort_values("Mean score")
fig.add_trace(
go.Bar(
x=sub["Model"],
y=sub["Mean score"],
marker_color=[MODEL_COLORS.get(m, "#808080") for m in sub["Model"]],
showlegend=False,
hovertemplate="%{x}: %{y:.3f}",
),
row=1,
col=i + 1,
)
fig.update_xaxes(showticklabels=False, title_text="", row=1, col=i + 1)
fig.update_yaxes(range=y_range, title_text="", row=1, col=i + 1)
fig.update_layout(
height=height,
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
margin=dict(t=60, l=10, r=10, b=10),
)
fig.update_yaxes(title_text=METRIC_LABEL, row=1, col=1)
return fig
def show_head_to_head(
df: pd.DataFrame, key: str, per_species: bool = False, title: str | None = None
) -> None:
"""Two models on their shared tracks only, with the number of tracks compared.
Per track by default, one point per track coloured by assay; `per_species` shows
one point per species instead, each the mean over that species' shared tracks.
"""
st.markdown(title or "#### โ๏ธ Head-to-head (per track)")
options = models_in(df)
if len(options) < 2:
st.info("Fewer than two models were evaluated here.")
return
default_a = options.index(NTV3) if NTV3 in options else 0
c_a, c_b = st.columns([1, 1])
with c_a:
model_a = st.selectbox(
"Model A (y-axis)", options=options, index=default_a, key=f"a_{key}"
)
with c_b:
b_options = [m for m in options if m != model_a]
default_b = b_options.index("AlphaGenome") if "AlphaGenome" in b_options else 0
model_b = st.selectbox(
"Model B (x-axis)", options=b_options, index=default_b, key=f"b_{key}"
)
scatter_df = build_pairwise_scatter_df(df, model_a, model_b)
if scatter_df.empty:
st.info(f"{model_a} and {model_b} share no evaluated track.")
return
n_tracks = len(scatter_df)
n_species = scatter_df["species"].nunique()
if per_species:
scatter_df = aggregate_pairs_by_species(scatter_df)
wins = int((scatter_df["Model A"] > scatter_df["Model B"]).sum())
st.caption(
f"Compared on **n = {n_species} shared species** ({n_tracks} shared "
f"tracks). {model_a} is higher on {wins} of them."
)
color_col, hover = "Clade", {"Shared tracks": True}
else:
wins = int((scatter_df["Model A"] > scatter_df["Model B"]).sum())
st.caption(
f"Compared on **n = {n_tracks} shared tracks** over {n_species} "
f"species. {model_a} is higher on {wins} of them."
)
color_col, hover = "assay_type", {"Species": True, "datasets": True}
min_v = float(min(scatter_df["Model A"].min(), scatter_df["Model B"].min()))
max_v = float(max(scatter_df["Model A"].max(), scatter_df["Model B"].max()))
pad = 0.05 * (max_v - min_v if max_v > min_v else 1.0)
axis_range = [min_v - pad, max_v + pad]
color_map = ASSAY_COLORS if color_col == "assay_type" else CLADE_COLORS
fig = px.scatter(
scatter_df,
x="Model B",
y="Model A",
color=color_col,
color_discrete_map=color_map,
category_orders={"Clade": list(SPECIES_GROUPS)},
hover_name="Track",
hover_data={**hover, "Model A": ":.3f", "Model B": ":.3f"},
text="Species" if per_species else None,
)
if per_species:
fig.update_traces(marker=dict(size=13), textposition="top center")
fig.add_shape(
type="line",
x0=axis_range[0], y0=axis_range[0], x1=axis_range[1], y1=axis_range[1],
xref="x", yref="y",
line=dict(color="red", dash="dot", width=2),
)
fig.update_layout(
height=620,
margin=dict(l=60, r=20, t=20, b=110),
xaxis=dict(
title=f"{model_b} โ {METRIC_LABEL}",
range=axis_range, dtick=0.1, tickformat=".1f", constrain="domain",
),
yaxis=dict(
title=f"{model_a} โ {METRIC_LABEL}",
range=axis_range, dtick=0.1, tickformat=".1f",
scaleanchor="x", scaleratio=1, constrain="domain",
),
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
legend=dict(
title="",
orientation="h",
x=0.5, xanchor="center", y=-0.15, yanchor="top",
),
)
st.plotly_chart(fig, width="stretch")
def build_convergence_df(tracks: pd.DataFrame, runs: pd.DataFrame, x_col: str) -> pd.DataFrame:
"""Per model: mean score and the mean cost of reaching its best checkpoint."""
perf = tracks.groupby("Model", as_index=False)["Score"].mean()
cost = runs.groupby("Model", as_index=False).agg(X=(x_col, "mean"), Runs=(x_col, "count"))
out = perf.merge(cost, on="Model").dropna(subset=["X"])
out["Score"] = out["Score"].round(3)
return out
def show_convergence(tracks: pd.DataFrame, runs: pd.DataFrame, key: str) -> None:
st.markdown("#### โฑ๏ธ Time to convergence")
x_mode = st.selectbox(
"X-axis",
options=["GPU hours", "Tokens (billions)"],
index=0,
key=f"conv_{key}",
)
conv_df = build_convergence_df(tracks, runs, x_mode)
if conv_df.empty:
st.info("No convergence data for this species.")
return
if x_mode == "GPU hours":
caption = (
"GPU hours spent in training steps until the best validation checkpoint "
"(the one scored on the test set), ร GPUs used, averaged over seeds. Job "
"setup and validation are excluded. All runs on H100s."
)
else:
caption = (
"Training tokens seen at the best validation checkpoint, averaged over "
"seeds. Validation ran every 1.05B tokens on most runs, so this is "
"resolved to about 1B tokens."
)
st.caption(caption)
fig = px.scatter(
conv_df,
x="X",
y="Score",
text="Model",
color="Model",
color_discrete_map=MODEL_COLORS,
hover_data={"Model": True, "X": ":.2f", "Score": ":.3f", "Runs": True},
)
fig.update_traces(marker=dict(size=14), textposition="middle right")
fig.update_layout(
height=620,
xaxis_title=x_mode + (" (log scale)" if x_mode == "GPU hours" else ""),
yaxis_title=METRIC_LABEL,
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
showlegend=False,
)
if x_mode == "GPU hours":
lo, hi = np.log10(conv_df["X"].min()), np.log10(conv_df["X"].max())
fig.update_xaxes(
type="log", dtick=1, range=[lo - 0.15, hi + 0.45],
minor=dict(ticks="", showgrid=False),
)
else:
lo, hi = conv_df["X"].min(), conv_df["X"].max()
fig.update_xaxes(range=[lo - 0.05 * (hi - lo), hi + 0.3 * (hi - lo)])
st.plotly_chart(fig, width="stretch")
def plot_violin(df: pd.DataFrame) -> go.Figure:
order = df.groupby("Model")["Score"].median().sort_values().index.tolist()
fig = px.violin(
df,
x="Model",
y="Score",
color="Model",
color_discrete_map=MODEL_COLORS,
box=True,
points=False,
category_orders={"Model": order},
hover_data=["track_name_clean"],
)
fig.update_layout(
height=650,
xaxis_title="",
yaxis_title=METRIC_LABEL,
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
showlegend=False,
)
fig.update_traces(box_visible=True, meanline_visible=False)
return fig
# ---------------------------------------------------------------------
# Pages
# ---------------------------------------------------------------------
SIDEBAR_CSS = """
"""
def overview_page() -> None:
df = _TRACKS
st.title("๐งฌ NTv3 Benchmark")
st.markdown(_INTRO)
st.markdown(f"_Last updated: **{_LAST_UPDATED}**_")
st.divider()
st.subheader("๐ Every model on every species")
st.caption(
"One point per model and species: the mean over that species' tracks. "
"A model with no point on a species was not evaluated on it. Hover for values."
)
scores = build_species_scores(df)
st.plotly_chart(plot_species_overview(scores, models_in(df)), width="stretch")
left, right = st.columns([1, 1], gap="large")
with left:
show_head_to_head(df, key="overview_track")
with right:
show_head_to_head(
df,
key="overview_species",
per_species=True,
title="#### โ๏ธ Head-to-head (per species)",
)
def species_page(species: str) -> None:
sub = _TRACKS[_TRACKS["species"] == species]
runs = _RUNS[(_RUNS["species"] == species) & _RUNS["Model"].isin(set(sub["Model"]))]
n_tracks = sub["datasets"].nunique()
common = SPECIES_COMMON_NAME.get(species)
st.title(f"{SPECIES_ICON[species]} {SPECIES_LABEL[species]}")
st.caption(
f"{SPECIES_CLADE[species]}{f' ยท {common}' if common else ''} ยท {n_tracks} tracks ยท "
f"{sub['Model'].nunique()} models, each evaluated on all {n_tracks} tracks."
)
leaderboard = build_leaderboard(sub)
col1, col2 = st.columns([1, 1])
with col1:
st.subheader("๐
Leaderboard")
st.write("\n")
st.write("\n")
st.write("\n")
st.dataframe(leaderboard, width="stretch")
with col2:
st.subheader("๐ Mean score per model")
st.plotly_chart(plot_mean_bars(leaderboard), width="stretch")
breakdown_df = build_category_model_df(sub)
if breakdown_df["Category"].nunique() > 1:
st.subheader("๐งช Mean score by assay type")
st.plotly_chart(plot_breakdown_facets_sorted_models(breakdown_df), width="stretch")
left, right = st.columns([1, 1], gap="large")
with left:
show_head_to_head(sub, key=species)
with right:
show_convergence(sub, runs, key=species)
st.subheader("๐ป Performance across tracks")
st.plotly_chart(plot_violin(sub), width="stretch")
def make_species_page(species: str) -> st.Page:
def render() -> None:
species_page(species)
render.__name__ = f"page_{species.replace(' ', '_')}"
return st.Page(
render,
title=SPECIES_LABEL[species],
icon=SPECIES_ICON[species],
url_path=species.replace(" ", "-"),
)
# ---------------------------------------------------------------------
# Streamlit UI
# ---------------------------------------------------------------------
def main():
st.markdown(SIDEBAR_CSS, unsafe_allow_html=True)
available = set(_TRACKS["species"])
sections = {
"": [st.Page(overview_page, title="Overview", icon="๐", default=True)],
}
for clade, group in SPECIES_GROUPS.items():
pages = [make_species_page(s) for s in group if s in available]
if pages:
sections[clade] = pages
sections["Initial release (2025)"] = [
st.Page(initial_release.main, title="2025 leaderboard", icon="๐๏ธ", url_path="initial-release")
]
st.navigation(sections, position="sidebar").run()
if __name__ == "__main__":
main()