Spaces:
Running
Running
New LB
#3
by LennartPurucker - opened
This view is limited to 50 files because it contains too many changes. See the raw diff here.
- .gitignore +0 -4
- AGENTS.md +0 -429
- CLAUDE.md +0 -28
- README.md +4 -31
- api.py +0 -592
- constants.py +1 -22
- data/full-imputed-cls/leaderboard.tex +53 -0
- data/full-imputed-cls/tabarena_leaderboard.csv +46 -0
- data/full-imputed-reg/leaderboard.tex +52 -0
- data/full-imputed-reg/tabarena_leaderboard.csv +45 -0
- data/{imputation_no/splits_all/tasks_multiclass/datasets_medium/tuning-impact-elo.png.zip → full-imputed-reg/time_plot.png.zip} +2 -2
- data/full-imputed/leaderboard.tex +53 -0
- data/full-imputed/tabarena_leaderboard.csv +46 -0
- data/imputation_no/splits_all/tasks_all/datasets_all/leaderboard_overview_explorer.html +0 -1411
- data/imputation_no/splits_all/tasks_all/datasets_all/leaderboard_table.html +0 -1162
- data/imputation_no/splits_all/tasks_all/datasets_all/n_datasets_51 +0 -0
- data/imputation_no/splits_all/tasks_all/datasets_all/pareto_front_explorer.html +0 -1230
- data/imputation_no/splits_all/tasks_all/datasets_all/pareto_front_improvability_vs_time_infer.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_all/pareto_front_points.csv +0 -63
- data/imputation_no/splits_all/tasks_all/datasets_all/pareto_n_configs_imp.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_all/tuning-impact-elo.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_all/tuning_trajectories.csv +0 -163
- data/imputation_no/splits_all/tasks_all/datasets_all/tuning_trajectories_explorer.html +0 -1230
- data/imputation_no/splits_all/tasks_all/datasets_all/website_leaderboard.csv +0 -71
- data/imputation_no/splits_all/tasks_all/datasets_all/winrate_explorer.html +0 -1169
- data/imputation_no/splits_all/tasks_all/datasets_all/winrate_matrix.csv +0 -29
- data/imputation_no/splits_all/tasks_all/datasets_all/winrate_matrix.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_medium/leaderboard_overview_explorer.html +0 -1411
- data/imputation_no/splits_all/tasks_all/datasets_medium/leaderboard_table.html +0 -1162
- data/imputation_no/splits_all/tasks_all/datasets_medium/n_datasets_15 +0 -0
- data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_front_explorer.html +0 -1230
- data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_front_improvability_vs_time_infer.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_front_points.csv +0 -63
- data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_n_configs_imp.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_medium/tuning-impact-elo.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_medium/tuning_trajectories.csv +0 -163
- data/imputation_no/splits_all/tasks_all/datasets_medium/tuning_trajectories_explorer.html +0 -1230
- data/imputation_no/splits_all/tasks_all/datasets_medium/website_leaderboard.csv +0 -71
- data/imputation_no/splits_all/tasks_all/datasets_medium/winrate_explorer.html +0 -1169
- data/imputation_no/splits_all/tasks_all/datasets_medium/winrate_matrix.csv +0 -29
- data/imputation_no/splits_all/tasks_all/datasets_medium/winrate_matrix.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_small/leaderboard_overview_explorer.html +0 -1411
- data/imputation_no/splits_all/tasks_all/datasets_small/leaderboard_table.html +0 -1162
- data/imputation_no/splits_all/tasks_all/datasets_small/n_datasets_36 +0 -0
- data/imputation_no/splits_all/tasks_all/datasets_small/pareto_front_explorer.html +0 -1230
- data/imputation_no/splits_all/tasks_all/datasets_small/pareto_front_improvability_vs_time_infer.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_small/pareto_front_points.csv +0 -63
- data/imputation_no/splits_all/tasks_all/datasets_small/pareto_n_configs_imp.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_small/tuning-impact-elo.png.zip +0 -3
- data/imputation_no/splits_all/tasks_all/datasets_small/tuning_trajectories.csv +0 -163
.gitignore
CHANGED
|
@@ -8,7 +8,3 @@ wheels/
|
|
| 8 |
|
| 9 |
# Virtual environments
|
| 10 |
.venv
|
| 11 |
-
|
| 12 |
-
*.png
|
| 13 |
-
|
| 14 |
-
.idea/
|
|
|
|
| 8 |
|
| 9 |
# Virtual environments
|
| 10 |
.venv
|
|
|
|
|
|
|
|
|
|
|
|
AGENTS.md
DELETED
|
@@ -1,429 +0,0 @@
|
|
| 1 |
-
# AGENTS.md
|
| 2 |
-
|
| 3 |
-
Guidance for AI coding agents working in this repository.
|
| 4 |
-
|
| 5 |
-
## What this repo is
|
| 6 |
-
|
| 7 |
-
Frontend code for the TabArena leaderboard, deployed as a Gradio app on a Hugging Face Space. The leaderboard ranks tabular ML models across tasks, splits, and dataset subsets.
|
| 8 |
-
|
| 9 |
-
- Entrypoint: `main.py` (Gradio app plus the page's CSS/JS/head; HF Space runs it via the `app_file` declared in `README.md` frontmatter).
|
| 10 |
-
- Pages and their layout: `pages.py` (one entry per leaderboard in `PAGES`); component builders: `views.py`.
|
| 11 |
-
- Data paths and CSV parsing: `data_loading.py`. Agent-facing endpoints: `api.py`.
|
| 12 |
-
- UI text and copy: `website_texts.py`.
|
| 13 |
-
- Static constants (e.g. model-type emoji map): `constants.py`.
|
| 14 |
-
- Precomputed artifacts (CSVs + zipped PNGs): `data/imputation_{no,yes}/splits_{...}/tasks_{...}/datasets_{...}/` for TabArena, `data_beyondarena/subsets/{subset}/` for BeyondArena.
|
| 15 |
-
- Python: requires 3.12+. Gradio 6 (`sdk_version` in `README.md` must match the pin in `requirements.txt`).
|
| 16 |
-
|
| 17 |
-
## Local dev
|
| 18 |
-
|
| 19 |
-
```bash
|
| 20 |
-
pip install -e ".[dev]" # or: uv pip install -r pyproject.toml
|
| 21 |
-
python main.py # launches the Gradio app
|
| 22 |
-
```
|
| 23 |
-
|
| 24 |
-
## Data pipeline (not regenerated in this repo)
|
| 25 |
-
|
| 26 |
-
Leaderboard data is produced upstream and dropped into `data/`:
|
| 27 |
-
|
| 28 |
-
1. Run `run_generate_website_artifacts.py` in the autogluon/tabarena repo.
|
| 29 |
-
2. Clear the local `data/` directory.
|
| 30 |
-
3. Unzip `clean_website_artifacts.zip` into `data/`.
|
| 31 |
-
|
| 32 |
-
Do not edit files under `data/` by hand — they are generated artifacts.
|
| 33 |
-
|
| 34 |
-
## Architecture notes
|
| 35 |
-
|
| 36 |
-
- A leaderboard view is one cell of a grid, described by the frozen `Subset` dataclass (`imputation`, `splits`, `tasks`, `datasets`) whose `rel_path` *is* the artifact directory. BeyondArena uses `BeyondSubset` with a single `subset` axis. The axis dicts in `data_loading.py` (`TASK_LABELS`, `DATASET_LABELS`, `BEYOND_SUBSET_LABELS`) define both the valid values and the tab order; the first entry of each is the default.
|
| 37 |
-
- `LBContainer` (`data_loading.py`) loads one subset's `website_leaderboard.csv`, lazily unzips its PNGs, and inlines its interactive HTML plots.
|
| 38 |
-
- The reactive render is driven by one `gr.State` per axis: selecting a tab or toggle updates that state, and the `@gr.render` block in `pages.py` rebuilds the subset's figures and table.
|
| 39 |
-
- The full leaderboard table is `views.make_leaderboard`: a native `gr.Dataframe` (sorting, search, fullscreen, copy) inside one card with its filters, column picker and column key. Filtering is `views.filter_leaderboard`, kept pure so it can be tested without a Gradio context. It replaced the `gradio_leaderboard` custom component, which pinned Gradio < 6 — do not reintroduce that dependency.
|
| 40 |
-
|
| 41 |
-
## The agent-facing API (`api.py`)
|
| 42 |
-
|
| 43 |
-
Hugging Face serves a generated `agents.md` for every Gradio Space at
|
| 44 |
-
`huggingface.co/spaces/<id>/agents.md`, reachable from the **Agents** button on the Space page. It is not
|
| 45 |
-
this file and cannot be overridden from the repo: it tells an agent to read `/gradio_api/info` and call
|
| 46 |
-
what it finds. So `/gradio_api/info` is the real contract, and `api.py` owns it.
|
| 47 |
-
|
| 48 |
-
- Four endpoints, registered by `register_api()` from inside the `gr.Blocks` context in `main.py`:
|
| 49 |
-
`list_leaderboards`, `get_tabarena_leaderboard`, `get_beyondarena_leaderboard` and
|
| 50 |
-
`get_pareto_frontier`. They read the same published CSVs the UI reads and reuse
|
| 51 |
-
`data_loading.parse_model`, so the API cannot disagree with the table.
|
| 52 |
-
- `get_pareto_frontier` is the one to point "which model should I use" at: the leaderboard's top row
|
| 53 |
-
is often orders of magnitude slower than a model just behind it, so it returns the outright best,
|
| 54 |
-
the non-dominated frontier on quality vs train/predict time (each entry with its speedup and
|
| 55 |
-
quality gap), the best model inside a stated time budget, and a summary sentence to relay.
|
| 56 |
-
- `kind` separates individual models from whole AutoML systems (rows the artifacts mark
|
| 57 |
-
`Reference Pipeline`, i.e. AutoGluon). It defaults to `models`, because "the best tabular model"
|
| 58 |
-
answered with an AutoML system is a wrong answer.
|
| 59 |
-
- **Every UI event listener must pass `api_visibility="private"`.** Without it, each `.click` / `.change` /
|
| 60 |
-
`.select` lambda lands in the public schema as `/lambda_7` with a parameter named `value_11`. Before this
|
| 61 |
-
rule the Space advertised 23 such endpoints and nothing callable.
|
| 62 |
-
- The same three functions are served as MCP tools at `/gradio_api/mcp/` (`launch(mcp_server=True)`,
|
| 63 |
-
`gradio[mcp]` extra). Gradio derives each tool's schema from the type hints and its description from the
|
| 64 |
-
docstring, so those are load-bearing for agents, not just for readers.
|
| 65 |
-
- Record keys are the CSV headers with the sort-direction marker stripped and snake_cased
|
| 66 |
-
(`Improvability (%) [⬇️]` becomes `improvability_pct`); `Model` is split into `model`, `variant` and
|
| 67 |
-
`model_url`; `Verified` becomes a bool. `_api_key` in `api.py` is the single place that mapping lives.
|
| 68 |
-
- Bulk readers should be pointed at the raw CSV instead, which `list_leaderboards` returns as a URL
|
| 69 |
-
template. It serves identical numbers with no queue and no token.
|
| 70 |
-
|
| 71 |
-
The generated `agents.md` tells agents to POST to `/gradio_api/call/v2/<endpoint>` with named parameters.
|
| 72 |
-
That route only exists in Gradio 6, which is why the Space is pinned there; on 5.x it returned 405 and
|
| 73 |
-
agents had to fall back to `/gradio_api/call/<endpoint>` with a positional `{"data": [...]}` body. Both
|
| 74 |
-
work now.
|
| 75 |
-
|
| 76 |
-
## Conventions
|
| 77 |
-
|
| 78 |
-
- Keep changes minimal — this is a small display app, not a framework. Avoid speculative abstraction.
|
| 79 |
-
- Don't add comments that just describe what code does; the file is short enough to read.
|
| 80 |
-
- User-facing copy lives in `website_texts.py`. Update it there, not inline.
|
| 81 |
-
- Version bumps: edit `version` in `pyproject.toml` and the matching changelog entry in `website_texts.py` (`VERSION_HISTORY_BUTTON_TEXT`).
|
| 82 |
-
- Prose you write, including user-facing copy in `website_texts.py`, follows [AI Writing Tropes to Avoid](#ai-writing-tropes-to-avoid) at the bottom of this file.
|
| 83 |
-
|
| 84 |
-
## Things to verify before reporting a UI change as done
|
| 85 |
-
|
| 86 |
-
- Launch `python main.py` and click through the affected tabs in a browser.
|
| 87 |
-
- Type checks and unit tests aren't meaningful here (none configured) — manual verification is the bar.
|
| 88 |
-
|
| 89 |
-
---
|
| 90 |
-
|
| 91 |
-
# AI Writing Tropes to Avoid
|
| 92 |
-
|
| 93 |
-
Applies to everything you write in this repo that a human reads: docstrings,
|
| 94 |
-
comments, markdown docs, commit messages, PR descriptions, user-facing copy,
|
| 95 |
-
and your replies in the chat.
|
| 96 |
-
|
| 97 |
-
Source: [tropes.fyi](https://tropes.fyi) by [ossama.is](https://ossama.is)
|
| 98 |
-
|
| 99 |
-
---
|
| 100 |
-
|
| 101 |
-
## Word Choice
|
| 102 |
-
|
| 103 |
-
### "Quietly" and Other Magic Adverbs
|
| 104 |
-
|
| 105 |
-
Overuse of "quietly" and similar adverbs to convey subtle importance or understated power. AI reaches for these adverbs to make mundane descriptions feel significant. Also includes: "deeply", "fundamentally", "remarkably", "arguably".
|
| 106 |
-
|
| 107 |
-
**Avoid patterns like:**
|
| 108 |
-
- "quietly orchestrating workflows, decisions, and interactions"
|
| 109 |
-
- "the one that quietly suffocates everything else"
|
| 110 |
-
- "a quiet intelligence behind it"
|
| 111 |
-
|
| 112 |
-
### "Delve" and Friends
|
| 113 |
-
|
| 114 |
-
Used to be the most infamous AI tell. "Delve" went from an uncommon English word to appearing in a staggering percentage of AI-generated text. Part of a family of overused AI vocabulary including "certainly", "utilize", "leverage" (as a verb), "robust", "streamline", and "harness".
|
| 115 |
-
|
| 116 |
-
**Avoid patterns like:**
|
| 117 |
-
- "Let's delve into the details..."
|
| 118 |
-
- "Delving deeper into this topic..."
|
| 119 |
-
- "We certainly need to leverage these robust frameworks..."
|
| 120 |
-
|
| 121 |
-
### "Tapestry" and "Landscape"
|
| 122 |
-
|
| 123 |
-
Overuse of ornate or grandiose nouns where simpler words would do. "Tapestry" is used to describe anything interconnected. "Landscape" is used to describe any field or domain. Other offenders: "paradigm", "synergy", "ecosystem", "framework".
|
| 124 |
-
|
| 125 |
-
**Avoid patterns like:**
|
| 126 |
-
- "The rich tapestry of human experience..."
|
| 127 |
-
- "Navigating the complex landscape of modern AI..."
|
| 128 |
-
- "The ever-evolving landscape of technology..."
|
| 129 |
-
|
| 130 |
-
### The "Serves As" Dodge
|
| 131 |
-
|
| 132 |
-
Replacing simple "is" or "are" with pompous alternatives like "serves as", "stands as", "marks", or "represents". AI avoids basic copulas because its repetition penalty pushes it toward fancier constructions (I've studied this!).
|
| 133 |
-
|
| 134 |
-
**Avoid patterns like:**
|
| 135 |
-
- "The building serves as a reminder of the city's heritage."
|
| 136 |
-
- "Gallery 825 serves as LAAA's exhibition space for contemporary art."
|
| 137 |
-
- "The station marks a pivotal moment in the evolution of regional transit."
|
| 138 |
-
|
| 139 |
-
---
|
| 140 |
-
|
| 141 |
-
## Sentence Structure
|
| 142 |
-
|
| 143 |
-
### Negative Parallelism
|
| 144 |
-
|
| 145 |
-
The "It's not X -- it's Y" pattern, often with an em dash. The single most commonly identified AI writing tell. Man I f*cking hate it. AI uses this to create false profundity by framing everything as a surprising reframe. One in a piece can be effective; ten in a blog post is a genuine insult to the reader. Before LLMs, people simply did not write like this at scale. Includes the causal variant "not because X, but because Y" where every explanation is framed as a surprise reveal, the em-dash dismissal "X -- not Y", and the cross-sentence reframe where the same noun is negated then repositioned: "The question isn't X. The question is Y."
|
| 146 |
-
|
| 147 |
-
**Avoid patterns like:**
|
| 148 |
-
- "It's not bold. It's backwards."
|
| 149 |
-
- "Feeding isn't nutrition. It's dialysis."
|
| 150 |
-
- "Half the bugs you chase aren't in your code. They're in your head."
|
| 151 |
-
|
| 152 |
-
### "Not X. Not Y. Just Z."
|
| 153 |
-
|
| 154 |
-
The dramatic countdown pattern. AI builds tension by negating two or more things before revealing the actual point. Creates a false sense of narrowing down to the truth.
|
| 155 |
-
|
| 156 |
-
**Avoid patterns like:**
|
| 157 |
-
- "Not a bug. Not a feature. A fundamental design flaw."
|
| 158 |
-
- "Not ten. Not fifty. Five hundred and twenty-three lint violations across 67 files."
|
| 159 |
-
- "not recklessly, not completely, but enough"
|
| 160 |
-
|
| 161 |
-
### "The X? A Y."
|
| 162 |
-
|
| 163 |
-
Self-posed rhetorical questions answered immediately in the next sentence or clause. The model asks a question nobody was asking, then answers it for dramatic effect. Thinks this is the epitome of great writing.
|
| 164 |
-
|
| 165 |
-
**Avoid patterns like:**
|
| 166 |
-
- "The result? Devastating."
|
| 167 |
-
- "The worst part? Nobody saw it coming."
|
| 168 |
-
- "The scary part? This attack vector is perfect for developers."
|
| 169 |
-
|
| 170 |
-
### Anaphora Abuse
|
| 171 |
-
|
| 172 |
-
Repeating the same sentence opening multiple times in quick succession.
|
| 173 |
-
|
| 174 |
-
**Avoid patterns like:**
|
| 175 |
-
- "They assume that users will pay... They assume that developers will build... They assume that ecosystems will emerge... They assume that..."
|
| 176 |
-
- "They could expose... They could offer... They could provide... They could create... They could let... They could unlock..."
|
| 177 |
-
- "They have built engines, but not vehicles. They have built power, but not leverage. They have built walls, but not doors."
|
| 178 |
-
|
| 179 |
-
### Tricolon Abuse
|
| 180 |
-
|
| 181 |
-
Overuse of the rule-of-three pattern, often extended to four or five. A single tricolon is elegant; three back-to-back tricolons are a pattern recognition failure.
|
| 182 |
-
|
| 183 |
-
**Avoid patterns like:**
|
| 184 |
-
- "Products impress people; platforms empower them. Products solve problems; platforms create worlds. Products scale linearly; platforms scale exponentially."
|
| 185 |
-
- "identity, payments, compute, distribution"
|
| 186 |
-
- "workflows, decisions, and interactions"
|
| 187 |
-
|
| 188 |
-
### "It's Worth Noting"
|
| 189 |
-
|
| 190 |
-
Filler transitions that signal nothing. AI uses these phrases to introduce new points without actually connecting them to the previous argument. Also includes: "It bears mentioning", "Importantly", "Interestingly", "Notably".
|
| 191 |
-
|
| 192 |
-
**Avoid patterns like:**
|
| 193 |
-
- "It's worth noting that this approach has limitations."
|
| 194 |
-
- "Importantly, we must consider the broader implications."
|
| 195 |
-
- "Interestingly, this pattern repeats across industries."
|
| 196 |
-
|
| 197 |
-
### Superficial Analyses
|
| 198 |
-
|
| 199 |
-
Tacking a present participle ("-ing") phrase onto the end of a sentence to inject shallow analysis that says nothing. The model attaches significance, legacy, or broader meaning to mundane facts using phrases like "highlighting its importance", "reflecting broader trends", or "contributing to the development of...".
|
| 200 |
-
|
| 201 |
-
**Avoid patterns like:**
|
| 202 |
-
- "contributing to the region's rich cultural heritage"
|
| 203 |
-
- "This etymology highlights the enduring legacy of the community's resistance and the transformative power of unity in shaping its identity."
|
| 204 |
-
- "underscoring its role as a dynamic hub of activity and culture"
|
| 205 |
-
|
| 206 |
-
### False Ranges
|
| 207 |
-
|
| 208 |
-
Using "from X to Y" constructions where X and Y aren't on any real scale. In legitimate use, "from X to Y" implies a spectrum with a meaningful middle. AI uses it as a fancy way to list two loosely related things. "From innovation to cultural transformation" -- what's in between???? Nothing!
|
| 209 |
-
|
| 210 |
-
**Avoid patterns like:**
|
| 211 |
-
- "From innovation to implementation to cultural transformation."
|
| 212 |
-
- "From the singularity of the Big Bang to the grand cosmic web."
|
| 213 |
-
- "From problem-solving and tool-making to scientific discovery, artistic expression, and technological innovation."
|
| 214 |
-
|
| 215 |
-
---
|
| 216 |
-
|
| 217 |
-
## Paragraph Structure
|
| 218 |
-
|
| 219 |
-
### Short Punchy Fragments
|
| 220 |
-
|
| 221 |
-
Excessive use of very short sentences or sentence fragments as standalone paragraphs for manufactured emphasis. RLHF training has pushed models toward "writing for readability" aimed at the lowest common denominator: one thought per sentence, no mental state-keeping required. It's an inhuman style. No real person writes first drafts this way because it doesn't match how humans think or speak.
|
| 222 |
-
|
| 223 |
-
**Avoid patterns like:**
|
| 224 |
-
- "He published this. Openly. In a book. As a priest."
|
| 225 |
-
- "These weren't just products. And the software side matched. Then it professionalised. But I adapted."
|
| 226 |
-
- "Platforms do."
|
| 227 |
-
|
| 228 |
-
### Listicle in a Trench Coat
|
| 229 |
-
|
| 230 |
-
Numbered or labeled points dressed up as continuous prose. The model writes what is essentially a listicle but wraps each point in a paragraph that starts with "The first... The second... The third..." to disguise the format. Perhaps you told it to stop generating lists and it decided to do this instead... still very common.
|
| 231 |
-
|
| 232 |
-
**Avoid patterns like:**
|
| 233 |
-
- "The first wall is the absence of a free, scoped API... The second wall is the lack of delegated access... The third wall is the absence of scoped permissions..."
|
| 234 |
-
- "The second takeaway is that... The third takeaway is that... The fourth takeaway is that..."
|
| 235 |
-
|
| 236 |
-
---
|
| 237 |
-
|
| 238 |
-
## Tone
|
| 239 |
-
|
| 240 |
-
### "Here's the Kicker"
|
| 241 |
-
|
| 242 |
-
False suspense transitions that promise a revelation but deliver a point that did NOT need the buildup. The model uses these phrases to manufacture drama before an otherwise unremarkable observation LOL. Also includes: "Here's the thing", "Here's where it gets interesting", "Here's what most people miss", "Here's the starting point", "Here's the deal".
|
| 243 |
-
|
| 244 |
-
**Avoid patterns like:**
|
| 245 |
-
- "Here's the kicker."
|
| 246 |
-
- "Here's the thing about AI adoption."
|
| 247 |
-
- "Here's where it gets interesting."
|
| 248 |
-
|
| 249 |
-
### "Think of It As..."
|
| 250 |
-
|
| 251 |
-
The patronizing analogy. AI constantly reaches for "Think of it as..." or "It's like a..." to simplify concepts. The model defaults to teacher mode and assumes the reader needs a metaphor to understand anything. Often produces analogies that are less clear than the original concept.
|
| 252 |
-
|
| 253 |
-
**Avoid patterns like:**
|
| 254 |
-
- "Think of it like a highway system for data."
|
| 255 |
-
- "Think of it as a Swiss Army knife for your workflow."
|
| 256 |
-
- "It's like asking someone to buy a car they're only allowed to sit in while it's parked."
|
| 257 |
-
|
| 258 |
-
### "Imagine a World Where..."
|
| 259 |
-
|
| 260 |
-
The classic AI invitation to futurism. To sell the argument usually begins with "Imagine" followed by a list of wonderful things that will happen if the reader agrees with the premise.
|
| 261 |
-
|
| 262 |
-
**Avoid patterns like:**
|
| 263 |
-
- "Imagine a world where every tool you use -- your calendar, your inbox, your documents, your CRM, your code editor -- has a quiet intelligence behind it..."
|
| 264 |
-
- "In that world, workflows stop being collections of manual steps and start becoming orchestrations."
|
| 265 |
-
|
| 266 |
-
### False Vulnerability
|
| 267 |
-
|
| 268 |
-
Simulated self-awareness or honesty that reads as performative. The model pretends to break the fourth wall or admit a bias, creating a false sense of authenticity. Real vulnerability is specific and uncomfortable; AI vulnerability is polished and risk-free!!!!
|
| 269 |
-
|
| 270 |
-
**Avoid patterns like:**
|
| 271 |
-
- "And yes, I'm openly in love with the platform model"
|
| 272 |
-
- "And yes, since we're being honest: I'm looking at you, OpenAI, Google, Anthropic, Meta"
|
| 273 |
-
- "This is not a rant; it's a diagnosis"
|
| 274 |
-
|
| 275 |
-
### "The Truth Is Simple"
|
| 276 |
-
|
| 277 |
-
Asserting that something is obvious, clear or simple instead of actually proving it. If you have to tell the reader your point is clear, it very likely isn't. Also includes the dramatic reveal variant: "but none of them is the real story. The real story is..." -- claiming privileged insight while waving away everything before it.
|
| 278 |
-
|
| 279 |
-
**Avoid patterns like:**
|
| 280 |
-
- "The reality is simpler and less flattering"
|
| 281 |
-
- "History is unambiguous on this point"
|
| 282 |
-
- "History is clear, the metrics are clear, the examples are clear"
|
| 283 |
-
|
| 284 |
-
### Grandiose Stakes Inflation
|
| 285 |
-
|
| 286 |
-
Everything is the most important thing ever. AI inflates the stakes of every argument to world-historical significance. A blog post about API pricing becomes a meditation on the fate of civilization.
|
| 287 |
-
|
| 288 |
-
**Avoid patterns like:**
|
| 289 |
-
- "This will fundamentally reshape how we think about everything."
|
| 290 |
-
- "will define the next era of computing"
|
| 291 |
-
- "something entirely new"
|
| 292 |
-
|
| 293 |
-
### "Let's Break This Down"
|
| 294 |
-
|
| 295 |
-
The pedagogical voice that assumes the reader needs hand-holding. AI defaults to a teacher-student dynamic even when writing for expert audiences. Also includes: "Let's unpack this", "Let's explore", "Let's dive in".
|
| 296 |
-
|
| 297 |
-
**Avoid patterns like:**
|
| 298 |
-
- "Let's break this down step by step."
|
| 299 |
-
- "Let's unpack what this really means."
|
| 300 |
-
- "Let's explore this idea further."
|
| 301 |
-
|
| 302 |
-
### Vague Attributions
|
| 303 |
-
|
| 304 |
-
Attributing claims to unnamed authorities instead of being specific. AI loves to invoke "experts", "observers", "industry reports", and "several publications" without naming anyone. It also inflates the quantity of sources -- presenting what one person said as a widely held view, or writing "several publications have cited" when it means two. If you can't name the expert, you don't have a source.
|
| 305 |
-
|
| 306 |
-
**Avoid patterns like:**
|
| 307 |
-
- "Experts argue that this approach has significant drawbacks."
|
| 308 |
-
- "Industry reports suggest that adoption is accelerating."
|
| 309 |
-
- "Observers have cited the initiative as a turning point."
|
| 310 |
-
|
| 311 |
-
### Invented Concept Labels
|
| 312 |
-
|
| 313 |
-
AI clusters invented compound labels that sound analytical without being grounded. It appends abstract problem-nouns (paradox, trap, creep, divide, vacuum, inversion) to domain words -- "supervision paradox", "acceleration trap", "workload creep" -- and uses them as if they're established, rigorously defined terms. They function as rhetorical shorthand: name a thing, skip the argument. Multiple such labels in the same piece is a strong signal of AI slop.
|
| 314 |
-
|
| 315 |
-
**Avoid patterns like:**
|
| 316 |
-
- "the supervision paradox"
|
| 317 |
-
- "the acceleration trap"
|
| 318 |
-
- "workload creep"
|
| 319 |
-
|
| 320 |
-
---
|
| 321 |
-
|
| 322 |
-
## Formatting
|
| 323 |
-
|
| 324 |
-
### Em-Dash Addiction
|
| 325 |
-
|
| 326 |
-
Compulsive overuse of em dashes for dramatic pauses, parenthetical asides and pivot points. A human writer might use 2-3 per piece (and naturally); AI will use 20+.
|
| 327 |
-
|
| 328 |
-
**Avoid patterns like:**
|
| 329 |
-
- "The problem -- and this is the part nobody talks about -- is systemic."
|
| 330 |
-
- "The tinkerer spirit didn't die of natural causes -- it was bought out."
|
| 331 |
-
- "Not recklessly, not completely -- but enough -- enough to matter."
|
| 332 |
-
|
| 333 |
-
### Double-Hyphen Dash
|
| 334 |
-
|
| 335 |
-
The em dash wearing a false moustache. Once "em dash means AI" became common knowledge, the character started getting swapped for a double hyphen: sometimes because the text passed through a markdown conversion, sometimes because someone ran a find-and-replace to look more human, sometimes because the model was steered off the character while keeping the habit. Either way the compulsive mid-sentence pivot survives the substitution, which is what actually gives it away. Writers who reach for double hyphens honestly do so once or twice out of typographic laziness, rarely fifteen times in one post. Flagged at five or more per thousand words.
|
| 336 |
-
|
| 337 |
-
**Avoid patterns like:**
|
| 338 |
-
- "The problem -- and this is the part nobody talks about -- is systemic."
|
| 339 |
-
- "It's not a rewrite -- it's a reckoning."
|
| 340 |
-
- "We shipped it fast -- maybe too fast -- and paid for it later."
|
| 341 |
-
|
| 342 |
-
### Bold-First Bullets
|
| 343 |
-
|
| 344 |
-
Every bullet point or list item starts with a bolded phrase or sentence. Extremely common in Claude and ChatGPT markdown output. Almost nobody formats lists this way when writing by hand. It's a telltale sign of AI-generated documentation and blog posts AND README files (especially with emojis).
|
| 345 |
-
|
| 346 |
-
**Avoid patterns like:**
|
| 347 |
-
- "Every single bullet point begins with a bold keyword."
|
| 348 |
-
- "**Security**: Environment-based configuration with..."
|
| 349 |
-
- "**Performance**: Lazy loading of expensive resources..."
|
| 350 |
-
|
| 351 |
-
### Unicode Decoration
|
| 352 |
-
|
| 353 |
-
Use of unicode arrows (->), smart/curly quotes, and other special characters that can't be easily typed on a standard keyboard. Real writers typing in a text editor produce straight quotes and -> or =>. Claude in particular loves the -> arrow.
|
| 354 |
-
|
| 355 |
-
**Avoid patterns like:**
|
| 356 |
-
- "Input → Processing → Output"
|
| 357 |
-
- "This leads to better outcomes → which means higher engagement"
|
| 358 |
-
- "“Smart quotes” instead of straight "quotes" that you’d actually type"
|
| 359 |
-
|
| 360 |
-
---
|
| 361 |
-
|
| 362 |
-
## Composition
|
| 363 |
-
|
| 364 |
-
### Fractal Summaries
|
| 365 |
-
|
| 366 |
-
"What I'm going to tell you; what I'm telling you; what I just told you" -- applied at every level of the document. Every subsection gets a summary. Every section gets a summary. The document itself gets a summary.
|
| 367 |
-
|
| 368 |
-
**Avoid patterns like:**
|
| 369 |
-
- "In this section, we'll explore... [3000 words later] ...as we've seen in this section."
|
| 370 |
-
- "A conclusion that restates every point already made in the previous 3000 words"
|
| 371 |
-
- "And so we return to where we began."
|
| 372 |
-
|
| 373 |
-
### The Dead Metaphor
|
| 374 |
-
|
| 375 |
-
Latching onto a single metaphor and beating it into the ground across the entire thing. A human writer would introduce a metaphor, use it then move on. AI will repeat the same metaphor 5-10 times.
|
| 376 |
-
|
| 377 |
-
**Avoid patterns like:**
|
| 378 |
-
- "The ecosystem needs ecosystems to build ecosystem value."
|
| 379 |
-
- "Walls and doors used 30+ times in the same article"
|
| 380 |
-
- "Every paragraph finds a way to say "primitives" again"
|
| 381 |
-
|
| 382 |
-
### Historical Analogy Stacking
|
| 383 |
-
|
| 384 |
-
ESPECIALLY COMMON IN TECHNICAL WRITING: Rapid-fire listing of historical companies or tech revolutions to build false authority.
|
| 385 |
-
|
| 386 |
-
**Avoid patterns like:**
|
| 387 |
-
- "Apple didn't build Uber. Facebook didn't build Spotify. Stripe didn't build Shopify. AWS didn't build Airbnb."
|
| 388 |
-
- "Every major technological shift -- the web, mobile, social, cloud -- followed the same pattern."
|
| 389 |
-
- "Take Spotify... Or consider Uber... Airbnb followed a similar path... Shopify is another example... Even Discord..."
|
| 390 |
-
|
| 391 |
-
### One-Point Dilution
|
| 392 |
-
|
| 393 |
-
Making a single argument and restating it in 10 different ways across thousands of words. The model pads a simple thesis to feel "comprehensive" by rephrasing the same idea with different metaphors, examples, and framings. An 800-word argument becomes 4000 words of circular repetition.
|
| 394 |
-
|
| 395 |
-
**Avoid patterns like:**
|
| 396 |
-
- "The same point, restated eight ways across 4000 words."
|
| 397 |
-
- "Each section rephrases the thesis with a different metaphor but adds nothing new"
|
| 398 |
-
|
| 399 |
-
### Content Duplication
|
| 400 |
-
|
| 401 |
-
Repeating entire sections or paragraphs verbatim within the same piece. This happens when the model loses track of what it has already written, especially in longer pieces. A dead giveaway of unedited AI output. Less common nowadays.
|
| 402 |
-
|
| 403 |
-
**Avoid patterns like:**
|
| 404 |
-
- "The same section appeared twice, word-for-word identical."
|
| 405 |
-
- "Paragraph 3 and paragraph 17 are the same sentence reworded"
|
| 406 |
-
|
| 407 |
-
### The Signposted Conclusion
|
| 408 |
-
|
| 409 |
-
Explicitly announcing the conclusion with "In conclusion", "To sum up", or "In summary". Competent writing doesn't need to tell you it's concluding. The reader can feel it. AI signals its structural moves because it's following a template, not writing organically.
|
| 410 |
-
|
| 411 |
-
**Avoid patterns like:**
|
| 412 |
-
- "In conclusion, the future of AI depends on..."
|
| 413 |
-
- "To sum up, we've explored three key themes..."
|
| 414 |
-
- "In summary, the evidence suggests..."
|
| 415 |
-
|
| 416 |
-
### "Despite Its Challenges..."
|
| 417 |
-
|
| 418 |
-
The rigid formula where AI acknowledges problems only to immediately dismiss them. Always follows the same beat: "Despite its [positive words], [subject] faces challenges..." then ends with "Despite these challenges, [optimistic conclusion].".
|
| 419 |
-
|
| 420 |
-
**Avoid patterns like:**
|
| 421 |
-
- "Despite these challenges, the initiative continues to thrive."
|
| 422 |
-
- "Despite its industrial and residential prosperity, Korattur faces challenges typical of urban areas."
|
| 423 |
-
- "Despite their promising applications, pyroelectric materials face several challenges that must be addressed for broader adoption."
|
| 424 |
-
|
| 425 |
-
---
|
| 426 |
-
|
| 427 |
-
Remember: any of these patterns used once might be fine. The problem is when
|
| 428 |
-
multiple tropes appear together or when a single trope is used repeatedly.
|
| 429 |
-
Write like a human: varied, imperfect, specific.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CLAUDE.md
DELETED
|
@@ -1,28 +0,0 @@
|
|
| 1 |
-
# CLAUDE.md
|
| 2 |
-
|
| 3 |
-
The primary agent guide for this repo is [`AGENTS.md`](./AGENTS.md). Read it
|
| 4 |
-
first; everything in it applies here, including the writing-style rules in its
|
| 5 |
-
"AI Writing Tropes to Avoid" section.
|
| 6 |
-
|
| 7 |
-
This file only records Claude-specific notes.
|
| 8 |
-
|
| 9 |
-
## TL;DR
|
| 10 |
-
|
| 11 |
-
* Repo: the Gradio frontend for the TabArena leaderboard, deployed as a
|
| 12 |
-
Hugging Face Space. `main.py` is the entrypoint (`app_file` in the
|
| 13 |
-
`README.md` frontmatter).
|
| 14 |
-
* Copy lives in `website_texts.py`, constants in `constants.py`, generated
|
| 15 |
-
artifacts in `data/`. Never hand-edit `data/`.
|
| 16 |
-
* Verification bar is manual: run `python main.py` with this repo's own
|
| 17 |
-
`.venv` and click through the affected tabs. No tests are configured.
|
| 18 |
-
* Don't commit or push without an explicit ask. Pushing here deploys the
|
| 19 |
-
Space, and `data/` is tracked via Git LFS + Xet.
|
| 20 |
-
|
| 21 |
-
## Refreshing the data
|
| 22 |
-
|
| 23 |
-
`data/` is generated in the tabarena repo, not here. The `update-leaderboard`
|
| 24 |
-
skill in `../tabarena/.claude/skills/` drives the whole flow: it generates the
|
| 25 |
-
website artifacts, swaps them into this repo's `data/` (deleting the old
|
| 26 |
-
subtree first, otherwise stale unzipped PNGs survive), and bumps the version
|
| 27 |
-
history in `website_texts.py`. Invoke that skill from the tabarena repo rather
|
| 28 |
-
than reproducing the steps by hand, and pass it the path to this repo.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -7,8 +7,8 @@ sdk: gradio
|
|
| 7 |
app_file: main.py
|
| 8 |
pinned: true
|
| 9 |
license: apache-2.0
|
| 10 |
-
short_description: '
|
| 11 |
-
sdk_version:
|
| 12 |
---
|
| 13 |
|
| 14 |
# TabArena Leaderboard Code
|
|
@@ -18,38 +18,11 @@ The leaderboard is hosted on a HuggingFace space.
|
|
| 18 |
|
| 19 |
Reference:
|
| 20 |
* Website: https://tabarena.ai
|
| 21 |
-
* Paper:
|
| 22 |
* TabArena Codebase: https://tabarena.ai/code
|
| 23 |
|
| 24 |
# Install LB Code for Development
|
| 25 |
|
| 26 |
```bash
|
| 27 |
pip install -e ".[dev]"
|
| 28 |
-
|
| 29 |
-
uv pip install -r pyproject.toml
|
| 30 |
-
```
|
| 31 |
-
|
| 32 |
-
# Reading the leaderboard programmatically
|
| 33 |
-
|
| 34 |
-
The published numbers are plain CSVs in this repo, so the cheapest way to read
|
| 35 |
-
them is a direct fetch (no queue, no token, `-L` because the raw path redirects
|
| 36 |
-
to the resolve cache):
|
| 37 |
-
|
| 38 |
-
```bash
|
| 39 |
-
curl -sL https://huggingface.co/spaces/TabArena/leaderboard/resolve/main/data/imputation_yes/splits_all/tasks_all/datasets_all/website_leaderboard.csv
|
| 40 |
-
```
|
| 41 |
-
|
| 42 |
-
The path is `data/imputation_{yes,no}/splits_{all,lite}/tasks_{...}/datasets_{...}/`
|
| 43 |
-
for TabArena and `data_beyondarena/subsets/{subset}/` for BeyondArena.
|
| 44 |
-
|
| 45 |
-
The Space also serves three JSON endpoints for agents, defined in `api.py`:
|
| 46 |
-
`list_leaderboards`, `get_tabarena_leaderboard`, `get_beyondarena_leaderboard`.
|
| 47 |
-
Hugging Face advertises them through the **Agents** button on the Space page,
|
| 48 |
-
which points at a generated `agents.md`. See AGENTS.md for the contract and its
|
| 49 |
-
one caveat.
|
| 50 |
-
|
| 51 |
-
# Current Steps to get results:
|
| 52 |
-
1. Run https://github.com/autogluon/tabarena/blob/main/scripts/run_generate_website_artifacts.py
|
| 53 |
-
2. Delete the current `data` folder contents in this repo to remove old results.
|
| 54 |
-
3. Unzip the generated `clean_website_artifacts.zip` zip file into the `data` folder in this repo.
|
| 55 |
-
4. Test the LB locally, otherwise you are done :)
|
|
|
|
| 7 |
app_file: main.py
|
| 8 |
pinned: true
|
| 9 |
license: apache-2.0
|
| 10 |
+
short_description: 'TabArena'
|
| 11 |
+
sdk_version: 5.33.2
|
| 12 |
---
|
| 13 |
|
| 14 |
# TabArena Leaderboard Code
|
|
|
|
| 18 |
|
| 19 |
Reference:
|
| 20 |
* Website: https://tabarena.ai
|
| 21 |
+
* Paper: TBA
|
| 22 |
* TabArena Codebase: https://tabarena.ai/code
|
| 23 |
|
| 24 |
# Install LB Code for Development
|
| 25 |
|
| 26 |
```bash
|
| 27 |
pip install -e ".[dev]"
|
| 28 |
+
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api.py
DELETED
|
@@ -1,592 +0,0 @@
|
|
| 1 |
-
"""The Space's machine-readable API, for agents rather than browsers.
|
| 2 |
-
|
| 3 |
-
Hugging Face serves a generated ``agents.md`` for every Gradio Space
|
| 4 |
-
(``huggingface.co/spaces/<id>/agents.md``). It is not a repo file and cannot be
|
| 5 |
-
overridden: it tells an agent to read ``/gradio_api/info`` and call whatever it
|
| 6 |
-
finds there. So the endpoints registered here *are* the agent-facing contract.
|
| 7 |
-
|
| 8 |
-
Two rules keep that contract readable. Everything in this file is a named,
|
| 9 |
-
described, typed endpoint; and every UI event listener elsewhere in the app
|
| 10 |
-
passes ``api_visibility="private"``, so render callbacks stay out of the schema
|
| 11 |
-
(a public listener would otherwise show up as ``/lambda_7`` with a parameter
|
| 12 |
-
called ``value_11``).
|
| 13 |
-
|
| 14 |
-
The same three functions are also served as MCP tools at ``/gradio_api/mcp/``,
|
| 15 |
-
from these type hints and docstrings, because ``main.py`` launches with
|
| 16 |
-
``mcp_server=True``. Anything written here is read by an agent twice over.
|
| 17 |
-
|
| 18 |
-
Records are the published CSVs with agent-friendly keys, not a second source of
|
| 19 |
-
truth: the same files the site reads, the same model-cell parser the table uses.
|
| 20 |
-
For bulk access, skip the queue and fetch the CSV directly (see
|
| 21 |
-
:func:`list_leaderboards`, which hands out the URL template).
|
| 22 |
-
"""
|
| 23 |
-
|
| 24 |
-
from __future__ import annotations
|
| 25 |
-
|
| 26 |
-
import os
|
| 27 |
-
import re
|
| 28 |
-
from pathlib import Path
|
| 29 |
-
from typing import Any, Literal, get_args
|
| 30 |
-
|
| 31 |
-
import gradio as gr
|
| 32 |
-
import pandas as pd
|
| 33 |
-
|
| 34 |
-
from constants import Constants
|
| 35 |
-
from data_loading import (
|
| 36 |
-
BEYOND_DATA_DIR,
|
| 37 |
-
BEYOND_SUBSET_LABELS,
|
| 38 |
-
DATA_DIR,
|
| 39 |
-
DATASET_LABELS,
|
| 40 |
-
BeyondSubset,
|
| 41 |
-
LBContainer,
|
| 42 |
-
Subset,
|
| 43 |
-
TASK_LABELS,
|
| 44 |
-
parse_model,
|
| 45 |
-
)
|
| 46 |
-
|
| 47 |
-
# Axis values as Literals, so /gradio_api/info carries an enum per parameter.
|
| 48 |
-
# That schema is the only place an agent reliably learns the valid values: a
|
| 49 |
-
# rejected call comes back over the REST route as a bare `event: error` with a
|
| 50 |
-
# null payload, message dropped. _validate_axes below keeps these in step with
|
| 51 |
-
# the label dicts that define the data layout.
|
| 52 |
-
# A leaderboard row is either a single model (evaluated in its default / tuned /
|
| 53 |
-
# tuned+ensembled variants) or a whole AutoML system such as AutoGluon, which the
|
| 54 |
-
# artifacts mark as a reference pipeline. Agents conflate the two otherwise, and
|
| 55 |
-
# "the best tabular model" answered with an AutoML system is a wrong answer, so the
|
| 56 |
-
# endpoints return models only unless asked for something else.
|
| 57 |
-
KindAxis = Literal["models", "systems", "all"]
|
| 58 |
-
SYSTEM_TYPE = Constants.reference
|
| 59 |
-
|
| 60 |
-
# Which benchmark a cross-benchmark endpoint should read.
|
| 61 |
-
BenchmarkAxis = Literal["tabarena", "beyondarena"]
|
| 62 |
-
# What "best" means. The leaderboards rank by Elo; the rest are complementary.
|
| 63 |
-
QualityAxis = Literal["elo", "score", "rank", "harmonic_rank", "improvability_pct"]
|
| 64 |
-
_QUALITY_HIGHER_IS_BETTER = {
|
| 65 |
-
"elo": True,
|
| 66 |
-
"score": True,
|
| 67 |
-
"rank": False,
|
| 68 |
-
"harmonic_rank": False,
|
| 69 |
-
"improvability_pct": False,
|
| 70 |
-
}
|
| 71 |
-
# What "cheap" means, and the record key each maps to.
|
| 72 |
-
CostAxis = Literal["predict_time", "train_time"]
|
| 73 |
-
_COST_KEY = {
|
| 74 |
-
"predict_time": "median_predict_time_s_per_1k",
|
| 75 |
-
"train_time": "median_train_time_s_per_1k",
|
| 76 |
-
}
|
| 77 |
-
_COST_UNITS = {
|
| 78 |
-
"median_predict_time_s_per_1k": "seconds per 1000 rows to predict",
|
| 79 |
-
"median_train_time_s_per_1k": "seconds per 1000 rows to train",
|
| 80 |
-
}
|
| 81 |
-
|
| 82 |
-
TasksAxis = Literal["all", "classification", "regression", "binary", "multiclass"]
|
| 83 |
-
DatasetsAxis = Literal["all", "small", "medium"]
|
| 84 |
-
ImputationAxis = Literal["yes", "no"]
|
| 85 |
-
SplitsAxis = Literal["all", "lite"]
|
| 86 |
-
BeyondSubsetAxis = Literal[
|
| 87 |
-
"full",
|
| 88 |
-
"random",
|
| 89 |
-
"temporal",
|
| 90 |
-
"grouped",
|
| 91 |
-
"tiny",
|
| 92 |
-
"small",
|
| 93 |
-
"medium",
|
| 94 |
-
"large",
|
| 95 |
-
"low-dim",
|
| 96 |
-
"high-dim",
|
| 97 |
-
"text",
|
| 98 |
-
"high-cardinality",
|
| 99 |
-
]
|
| 100 |
-
|
| 101 |
-
IMPUTATION_VALUES = list(get_args(ImputationAxis))
|
| 102 |
-
SPLITS_VALUES = list(get_args(SplitsAxis))
|
| 103 |
-
KIND_VALUES = list(get_args(KindAxis))
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
def _validate_axes() -> None:
|
| 107 |
-
"""Fail at import if an axis Literal has drifted from the data layout."""
|
| 108 |
-
for name, literal, allowed in (
|
| 109 |
-
("TasksAxis", TasksAxis, TASK_LABELS),
|
| 110 |
-
("DatasetsAxis", DatasetsAxis, DATASET_LABELS),
|
| 111 |
-
("BeyondSubsetAxis", BeyondSubsetAxis, BEYOND_SUBSET_LABELS),
|
| 112 |
-
):
|
| 113 |
-
if set(get_args(literal)) != set(allowed):
|
| 114 |
-
raise RuntimeError(
|
| 115 |
-
f"api.{name} is out of sync with data_loading: "
|
| 116 |
-
f"{sorted(set(get_args(literal)) ^ set(allowed))} on one side only."
|
| 117 |
-
)
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
_validate_axes()
|
| 121 |
-
|
| 122 |
-
# The Space serving this app; HF sets SPACE_ID in the container.
|
| 123 |
-
SPACE_ID = os.environ.get("SPACE_ID", "TabArena/leaderboard")
|
| 124 |
-
_RAW_URL = f"https://huggingface.co/spaces/{SPACE_ID}/resolve/main"
|
| 125 |
-
|
| 126 |
-
# Column headers carry a sort-direction marker for the table widget; it is not
|
| 127 |
-
# part of the data, so it is stripped before the header becomes a JSON key.
|
| 128 |
-
_DIRECTION_RE = re.compile(r"\s*\[[⬆⬇]️?\]$")
|
| 129 |
-
_KEY_OVERRIDES = {"#": "position", "TypeName": "type_name"}
|
| 130 |
-
|
| 131 |
-
# Bulk-download URLs, templated on the same rel_path the app reads from so the
|
| 132 |
-
# two cannot drift.
|
| 133 |
-
_TABARENA_CSV_TEMPLATE = (
|
| 134 |
-
f"{_RAW_URL}/{DATA_DIR.name}/"
|
| 135 |
-
+ Subset("{imputation}", "{splits}", "{tasks}", "{datasets}").rel_path
|
| 136 |
-
+ "/website_leaderboard.csv"
|
| 137 |
-
)
|
| 138 |
-
_BEYOND_CSV_TEMPLATE = (
|
| 139 |
-
f"{_RAW_URL}/{BEYOND_DATA_DIR.name}/"
|
| 140 |
-
+ BeyondSubset("{subset}").rel_path
|
| 141 |
-
+ "/website_leaderboard.csv"
|
| 142 |
-
)
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
def _api_key(column: str) -> str:
|
| 146 |
-
"""Turn a CSV header into a JSON key: ``Improvability (%) [⬇️]`` -> ``improvability_pct``."""
|
| 147 |
-
if column in _KEY_OVERRIDES:
|
| 148 |
-
return _KEY_OVERRIDES[column]
|
| 149 |
-
name = _DIRECTION_RE.sub("", column).replace("%", "pct").replace("/", "_per_")
|
| 150 |
-
return re.sub(r"[^0-9a-zA-Z]+", "_", name).strip("_").lower()
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
def _records(df: pd.DataFrame) -> list[dict[str, Any]]:
|
| 154 |
-
"""One JSON record per leaderboard row."""
|
| 155 |
-
# NaN is not JSON; None is. Casting to object first keeps ints from turning
|
| 156 |
-
# into floats on the way through.
|
| 157 |
-
df = df.astype(object).where(pd.notna(df), None)
|
| 158 |
-
records = []
|
| 159 |
-
for row in df.to_dict("records"):
|
| 160 |
-
record = {_api_key(key): value for key, value in row.items()}
|
| 161 |
-
# The Model cell is markdown (`[TabFM (default)](url)`); agents want the
|
| 162 |
-
# three parts separately.
|
| 163 |
-
name, variant, url = parse_model(str(row["Model"]))
|
| 164 |
-
record["model"] = name
|
| 165 |
-
record["variant"] = variant
|
| 166 |
-
record["model_url"] = url
|
| 167 |
-
record["verified"] = str(row.get("Verified") or "").strip() == "✔️"
|
| 168 |
-
record["kind"] = "system" if row.get("TypeName") == SYSTEM_TYPE else "model"
|
| 169 |
-
records.append(record)
|
| 170 |
-
return records
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
def _select_kind(records: list[dict[str, Any]], kind: str) -> list[dict[str, Any]]:
|
| 174 |
-
if kind == "all":
|
| 175 |
-
return records
|
| 176 |
-
wanted = "system" if kind == "systems" else "model"
|
| 177 |
-
return [r for r in records if r["kind"] == wanted]
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
def _check(axis: str, value: str, allowed: list[str]) -> None:
|
| 181 |
-
if value not in allowed:
|
| 182 |
-
raise gr.Error(f"Unknown {axis}={value!r}. Valid values: {', '.join(allowed)}.")
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
def _pareto_frontier(
|
| 186 |
-
records: list[dict[str, Any]], quality: str, cost_key: str
|
| 187 |
-
) -> list[dict[str, Any]]:
|
| 188 |
-
"""The non-dominated records: nothing is both better and cheaper.
|
| 189 |
-
|
| 190 |
-
Walks cheapest-first and keeps a record only when it beats every cheaper one on
|
| 191 |
-
quality, which is the 2-D skyline. Ties on cost keep the better-quality record.
|
| 192 |
-
"""
|
| 193 |
-
higher_is_better = _QUALITY_HIGHER_IS_BETTER[quality]
|
| 194 |
-
usable = [
|
| 195 |
-
r
|
| 196 |
-
for r in records
|
| 197 |
-
if isinstance(r.get(quality), (int, float)) and isinstance(r.get(cost_key), (int, float))
|
| 198 |
-
]
|
| 199 |
-
ordered = sorted(
|
| 200 |
-
usable,
|
| 201 |
-
key=lambda r: (r[cost_key], -r[quality] if higher_is_better else r[quality]),
|
| 202 |
-
)
|
| 203 |
-
frontier: list[dict[str, Any]] = []
|
| 204 |
-
best = None
|
| 205 |
-
for record in ordered:
|
| 206 |
-
value = record[quality]
|
| 207 |
-
if best is None or (value > best if higher_is_better else value < best):
|
| 208 |
-
frontier.append(record)
|
| 209 |
-
best = value
|
| 210 |
-
return frontier
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
def _best(records: list[dict[str, Any]], quality: str) -> dict[str, Any] | None:
|
| 214 |
-
"""The single best record on `quality`, ignoring rows that lack it."""
|
| 215 |
-
usable = [r for r in records if isinstance(r.get(quality), (int, float))]
|
| 216 |
-
if not usable:
|
| 217 |
-
return None
|
| 218 |
-
return max(
|
| 219 |
-
usable,
|
| 220 |
-
key=lambda r: r[quality] if _QUALITY_HIGHER_IS_BETTER[quality] else -r[quality],
|
| 221 |
-
)
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
def _brief(record: dict[str, Any] | None, quality: str, cost_key: str) -> dict[str, Any] | None:
|
| 225 |
-
"""The fields worth returning for one model in a Pareto answer."""
|
| 226 |
-
if record is None:
|
| 227 |
-
return None
|
| 228 |
-
return {
|
| 229 |
-
"model": record.get("model"),
|
| 230 |
-
"variant": record.get("variant"),
|
| 231 |
-
"kind": record.get("kind"),
|
| 232 |
-
"type_name": record.get("type_name"),
|
| 233 |
-
"verified": record.get("verified"),
|
| 234 |
-
"model_url": record.get("model_url"),
|
| 235 |
-
quality: record.get(quality),
|
| 236 |
-
cost_key: record.get(cost_key),
|
| 237 |
-
"median_train_time_s_per_1k": record.get("median_train_time_s_per_1k"),
|
| 238 |
-
"median_predict_time_s_per_1k": record.get("median_predict_time_s_per_1k"),
|
| 239 |
-
}
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
def _describe(name: str | None, variant: str | None) -> str:
|
| 243 |
-
return f"{name} ({variant})" if variant else str(name)
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
def _load(data_root: Path, subset: Subset | BeyondSubset) -> list[dict[str, Any]]:
|
| 247 |
-
lb = LBContainer(data_root=data_root, subset=subset, name="")
|
| 248 |
-
try:
|
| 249 |
-
return _records(lb.load_df())
|
| 250 |
-
except FileNotFoundError:
|
| 251 |
-
raise gr.Error(
|
| 252 |
-
f"No results for {subset.rel_path!r} in this deployment. "
|
| 253 |
-
"Call list_leaderboards for the subsets that are available."
|
| 254 |
-
) from None
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
def get_tabarena_leaderboard(
|
| 258 |
-
tasks: TasksAxis = "all",
|
| 259 |
-
datasets: DatasetsAxis = "all",
|
| 260 |
-
kind: KindAxis = "models",
|
| 261 |
-
imputation: ImputationAxis = "yes",
|
| 262 |
-
splits: SplitsAxis = "all",
|
| 263 |
-
) -> list[dict[str, Any]]:
|
| 264 |
-
"""Ranked TabArena results for one subset of the IID benchmark.
|
| 265 |
-
|
| 266 |
-
Args:
|
| 267 |
-
tasks: Task subset, one of ``all``, ``classification``, ``regression``,
|
| 268 |
-
``binary``, ``multiclass``.
|
| 269 |
-
datasets: Dataset-size subset, one of ``all``, ``small``, ``medium``.
|
| 270 |
-
kind: What to rank. ``models`` (the default) returns individual models
|
| 271 |
-
such as TabPFN, RealMLP or LightGBM. ``systems`` returns whole AutoML
|
| 272 |
-
systems such as AutoGluon, which tune and ensemble many models
|
| 273 |
-
internally and are therefore not comparable to a single model.
|
| 274 |
-
``all`` returns both, as the website's table does. Ask for ``models``
|
| 275 |
-
when the question is "which model should I use" and ``systems`` when
|
| 276 |
-
it is "which AutoML framework should I use"; every record also
|
| 277 |
-
carries its own ``kind``.
|
| 278 |
-
imputation: ``yes`` includes models that cannot run on every dataset,
|
| 279 |
-
imputing the missing runs with a default RandomForest (this is what
|
| 280 |
-
the website shows by default); ``no`` drops them.
|
| 281 |
-
splits: ``all`` for the full repeated-CV protocol, ``lite`` for the
|
| 282 |
-
single-split TabArena-Lite results.
|
| 283 |
-
|
| 284 |
-
Returns:
|
| 285 |
-
One record per model variant, best first, with ``model``, ``variant``,
|
| 286 |
-
``elo``, ``score``, ``rank``, ``median_train_time_s_per_1k`` and the
|
| 287 |
-
remaining leaderboard columns. ``variant`` is ``default``, ``tuned`` or
|
| 288 |
-
``tuned + ensembled``, and empty for reference pipelines such as
|
| 289 |
-
AutoGluon, which are whole pipelines rather than one model's variant
|
| 290 |
-
(``type_name`` identifies those). Note the website's variant filter
|
| 291 |
-
groups them with the tuned ensembles instead.
|
| 292 |
-
"""
|
| 293 |
-
_check("tasks", tasks, list(TASK_LABELS))
|
| 294 |
-
_check("datasets", datasets, list(DATASET_LABELS))
|
| 295 |
-
_check("kind", kind, KIND_VALUES)
|
| 296 |
-
_check("imputation", imputation, IMPUTATION_VALUES)
|
| 297 |
-
_check("splits", splits, SPLITS_VALUES)
|
| 298 |
-
subset = Subset(imputation=imputation, splits=splits, tasks=tasks, datasets=datasets)
|
| 299 |
-
return _select_kind(_load(DATA_DIR, subset), kind)
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
def get_beyondarena_leaderboard(
|
| 303 |
-
subset: BeyondSubsetAxis = "full", kind: KindAxis = "models"
|
| 304 |
-
) -> list[dict[str, Any]]:
|
| 305 |
-
"""Ranked BeyondArena results for one subset, on the recommended core protocol.
|
| 306 |
-
|
| 307 |
-
BeyondArena goes beyond the IID assumption: it spans random, temporal and
|
| 308 |
-
grouped splits. It has a single subset axis rather than TabArena's grid.
|
| 309 |
-
|
| 310 |
-
Args:
|
| 311 |
-
subset: One of ``full``, ``random``, ``temporal``, ``grouped``, ``tiny``,
|
| 312 |
-
``small``, ``medium``, ``large``, ``low-dim``, ``high-dim``, ``text``,
|
| 313 |
-
``high-cardinality``.
|
| 314 |
-
kind: ``models`` (the default), ``systems`` for whole AutoML systems, or
|
| 315 |
-
``all``. See :func:`get_tabarena_leaderboard` for the distinction.
|
| 316 |
-
|
| 317 |
-
Returns:
|
| 318 |
-
One record per model variant, best first, in the same shape as
|
| 319 |
-
:func:`get_tabarena_leaderboard`.
|
| 320 |
-
"""
|
| 321 |
-
_check("subset", subset, list(BEYOND_SUBSET_LABELS))
|
| 322 |
-
_check("kind", kind, KIND_VALUES)
|
| 323 |
-
return _select_kind(_load(BEYOND_DATA_DIR, BeyondSubset(subset=subset)), kind)
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
def get_pareto_frontier(
|
| 327 |
-
benchmark: BenchmarkAxis = "tabarena",
|
| 328 |
-
quality: QualityAxis = "elo",
|
| 329 |
-
cost: CostAxis = "predict_time",
|
| 330 |
-
kind: KindAxis = "models",
|
| 331 |
-
tasks: TasksAxis = "all",
|
| 332 |
-
datasets: DatasetsAxis = "all",
|
| 333 |
-
beyond_subset: BeyondSubsetAxis = "full",
|
| 334 |
-
max_train_time_s_per_1k: float = 0.0,
|
| 335 |
-
max_predict_time_s_per_1k: float = 0.0,
|
| 336 |
-
imputation: ImputationAxis = "yes",
|
| 337 |
-
splits: SplitsAxis = "all",
|
| 338 |
-
) -> dict[str, Any]:
|
| 339 |
-
"""The accuracy-versus-time trade-off, for answering "which model should I use".
|
| 340 |
-
|
| 341 |
-
The top of a leaderboard is only one answer, and often the wrong one: the
|
| 342 |
-
highest-Elo model can be orders of magnitude slower than one a hair behind it.
|
| 343 |
-
This returns the whole trade-off instead — the outright best, the models that
|
| 344 |
-
nothing beats on both axes at once, and the best model that fits a time budget.
|
| 345 |
-
|
| 346 |
-
Args:
|
| 347 |
-
benchmark: ``tabarena`` (IID) or ``beyondarena`` (temporal / grouped splits).
|
| 348 |
-
quality: What "better" means: ``elo`` (default) or ``score``, where higher
|
| 349 |
-
wins, or ``rank`` / ``harmonic_rank`` / ``improvability_pct``, where
|
| 350 |
-
lower wins.
|
| 351 |
-
cost: What "cheaper" means: ``predict_time`` (default, what matters for
|
| 352 |
-
serving) or ``train_time`` (what matters for retraining).
|
| 353 |
-
kind: ``models`` (default), ``systems``, or ``all``. See
|
| 354 |
-
:func:`get_tabarena_leaderboard`.
|
| 355 |
-
tasks: TabArena task subset; ignored when `benchmark` is ``beyondarena``.
|
| 356 |
-
datasets: TabArena dataset-size subset; ignored for ``beyondarena``.
|
| 357 |
-
beyond_subset: BeyondArena subset; ignored when `benchmark` is ``tabarena``.
|
| 358 |
-
max_train_time_s_per_1k: Optional ceiling on median train seconds per 1000
|
| 359 |
-
rows. 0 means no limit.
|
| 360 |
-
max_predict_time_s_per_1k: Optional ceiling on median predict seconds per
|
| 361 |
-
1000 rows. 0 means no limit. Use this for "what is the best model I can
|
| 362 |
-
afford to serve".
|
| 363 |
-
imputation: TabArena only; see :func:`get_tabarena_leaderboard`.
|
| 364 |
-
splits: TabArena only; see :func:`get_tabarena_leaderboard`.
|
| 365 |
-
|
| 366 |
-
Returns:
|
| 367 |
-
``best_overall`` (the outright leader, ignoring cost), ``frontier`` (the
|
| 368 |
-
non-dominated models, cheapest first, each with ``speedup_vs_best`` and
|
| 369 |
-
``quality_gap_vs_best``), ``best_within_limits`` (the leader among models
|
| 370 |
-
satisfying the time ceilings, absent when no ceiling was given),
|
| 371 |
-
``dominated_count``, and a ``summary`` sentence to relay.
|
| 372 |
-
"""
|
| 373 |
-
_check("benchmark", benchmark, list(get_args(BenchmarkAxis)))
|
| 374 |
-
_check("quality", quality, list(_QUALITY_HIGHER_IS_BETTER))
|
| 375 |
-
_check("cost", cost, list(_COST_KEY))
|
| 376 |
-
_check("kind", kind, KIND_VALUES)
|
| 377 |
-
if benchmark == "beyondarena":
|
| 378 |
-
records = get_beyondarena_leaderboard(subset=beyond_subset, kind=kind)
|
| 379 |
-
where = f"BeyondArena ({beyond_subset}, core protocol)"
|
| 380 |
-
else:
|
| 381 |
-
records = get_tabarena_leaderboard(
|
| 382 |
-
tasks=tasks, datasets=datasets, kind=kind, imputation=imputation, splits=splits
|
| 383 |
-
)
|
| 384 |
-
where = f"TabArena ({tasks} tasks, {datasets} datasets)"
|
| 385 |
-
|
| 386 |
-
cost_key = _COST_KEY[cost]
|
| 387 |
-
best_overall = _best(records, quality)
|
| 388 |
-
frontier = _pareto_frontier(records, quality, cost_key)
|
| 389 |
-
|
| 390 |
-
limits = {
|
| 391 |
-
"median_train_time_s_per_1k": max_train_time_s_per_1k,
|
| 392 |
-
"median_predict_time_s_per_1k": max_predict_time_s_per_1k,
|
| 393 |
-
}
|
| 394 |
-
active_limits = {key: value for key, value in limits.items() if value and value > 0}
|
| 395 |
-
within = records
|
| 396 |
-
for key, ceiling in active_limits.items():
|
| 397 |
-
within = [
|
| 398 |
-
r for r in within if isinstance(r.get(key), (int, float)) and r[key] <= ceiling
|
| 399 |
-
]
|
| 400 |
-
best_within = _best(within, quality) if active_limits else None
|
| 401 |
-
|
| 402 |
-
entries = []
|
| 403 |
-
for record in frontier:
|
| 404 |
-
entry = _brief(record, quality, cost_key)
|
| 405 |
-
if best_overall and isinstance(best_overall.get(cost_key), (int, float)):
|
| 406 |
-
reference = best_overall[cost_key]
|
| 407 |
-
entry["speedup_vs_best"] = (
|
| 408 |
-
round(reference / record[cost_key], 2) if record[cost_key] else None
|
| 409 |
-
)
|
| 410 |
-
entry["quality_gap_vs_best"] = round(
|
| 411 |
-
abs(best_overall[quality] - record[quality]), 4
|
| 412 |
-
)
|
| 413 |
-
entries.append(entry)
|
| 414 |
-
|
| 415 |
-
return {
|
| 416 |
-
"benchmark": benchmark,
|
| 417 |
-
"subset": where,
|
| 418 |
-
"quality": quality,
|
| 419 |
-
"higher_is_better": _QUALITY_HIGHER_IS_BETTER[quality],
|
| 420 |
-
"cost": cost_key,
|
| 421 |
-
"kind": kind,
|
| 422 |
-
"best_overall": _brief(best_overall, quality, cost_key),
|
| 423 |
-
"frontier": entries,
|
| 424 |
-
"dominated_count": max(0, len(records) - len(frontier)),
|
| 425 |
-
"limits": active_limits or None,
|
| 426 |
-
"best_within_limits": _brief(best_within, quality, cost_key),
|
| 427 |
-
"summary": _pareto_summary(
|
| 428 |
-
where, quality, cost_key, best_overall, entries, active_limits, best_within
|
| 429 |
-
),
|
| 430 |
-
}
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
def _pareto_summary(
|
| 434 |
-
where: str,
|
| 435 |
-
quality: str,
|
| 436 |
-
cost_key: str,
|
| 437 |
-
best_overall: dict[str, Any] | None,
|
| 438 |
-
frontier: list[dict[str, Any]],
|
| 439 |
-
limits: dict[str, float],
|
| 440 |
-
best_within: dict[str, Any] | None,
|
| 441 |
-
) -> str:
|
| 442 |
-
"""One paragraph an agent can relay instead of reciting the whole frontier."""
|
| 443 |
-
if best_overall is None:
|
| 444 |
-
return f"No {quality} values are available for {where}."
|
| 445 |
-
lead = _describe(best_overall.get("model"), best_overall.get("variant"))
|
| 446 |
-
units = _COST_UNITS.get(cost_key, cost_key)
|
| 447 |
-
parts = [
|
| 448 |
-
f"On {where}, the best {quality} is {lead} at {best_overall[quality]} "
|
| 449 |
-
f"({best_overall.get(cost_key)} {units})."
|
| 450 |
-
]
|
| 451 |
-
if len(frontier) > 1:
|
| 452 |
-
cheapest = frontier[0]
|
| 453 |
-
parts.append(
|
| 454 |
-
f"{len(frontier)} models are on the accuracy/time frontier. The cheapest, "
|
| 455 |
-
f"{_describe(cheapest.get('model'), cheapest.get('variant'))}, is "
|
| 456 |
-
f"{cheapest.get('speedup_vs_best')}x faster but {cheapest.get('quality_gap_vs_best')} "
|
| 457 |
-
f"{quality} behind."
|
| 458 |
-
)
|
| 459 |
-
# The trade-off worth naming is the smallest sacrifice that still buys a real
|
| 460 |
-
# speedup, not the biggest speedup (that is just the cheapest model again).
|
| 461 |
-
bargains = [
|
| 462 |
-
entry
|
| 463 |
-
for entry in frontier
|
| 464 |
-
if (entry.get("speedup_vs_best") or 0) >= 2 and entry.get("quality_gap_vs_best")
|
| 465 |
-
]
|
| 466 |
-
if bargains:
|
| 467 |
-
pick = min(bargains, key=lambda e: e["quality_gap_vs_best"])
|
| 468 |
-
parts.append(
|
| 469 |
-
# "at a cost of" rather than "less", which reads backwards for the
|
| 470 |
-
# metrics where lower is better.
|
| 471 |
-
f"The best compromise is {_describe(pick.get('model'), pick.get('variant'))}: "
|
| 472 |
-
f"{pick.get('speedup_vs_best')}x faster at a cost of "
|
| 473 |
-
f"{pick.get('quality_gap_vs_best')} {quality}."
|
| 474 |
-
)
|
| 475 |
-
if limits:
|
| 476 |
-
stated = ", ".join(f"{key} <= {value}" for key, value in limits.items())
|
| 477 |
-
if best_within:
|
| 478 |
-
parts.append(
|
| 479 |
-
f"Within {stated}, the best is "
|
| 480 |
-
f"{_describe(best_within.get('model'), best_within.get('variant'))} at "
|
| 481 |
-
f"{best_within[quality]}."
|
| 482 |
-
)
|
| 483 |
-
else:
|
| 484 |
-
parts.append(f"No model satisfies {stated}.")
|
| 485 |
-
return " ".join(parts)
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
def list_leaderboards() -> dict[str, Any]:
|
| 489 |
-
"""Describe the available leaderboards, their subset axes, and the bulk-download URLs.
|
| 490 |
-
|
| 491 |
-
Call this first: it lists the valid argument values for the other endpoints
|
| 492 |
-
and the record keys they return. It also gives the raw CSV URL template for
|
| 493 |
-
each benchmark, which serves the identical numbers over plain HTTP with no
|
| 494 |
-
queue or session, and is the better choice for reading many subsets.
|
| 495 |
-
"""
|
| 496 |
-
default_rows = _load(DATA_DIR, Subset())
|
| 497 |
-
return {
|
| 498 |
-
"leaderboards": [
|
| 499 |
-
{
|
| 500 |
-
"name": "tabarena",
|
| 501 |
-
"endpoint": "/get_tabarena_leaderboard",
|
| 502 |
-
"description": "Tabular ML on 51 curated IID datasets, ranked by Elo.",
|
| 503 |
-
"axes": {
|
| 504 |
-
"tasks": list(TASK_LABELS),
|
| 505 |
-
"datasets": list(DATASET_LABELS),
|
| 506 |
-
"kind": KIND_VALUES,
|
| 507 |
-
"imputation": IMPUTATION_VALUES,
|
| 508 |
-
"splits": SPLITS_VALUES,
|
| 509 |
-
},
|
| 510 |
-
"csv_url_template": _TABARENA_CSV_TEMPLATE,
|
| 511 |
-
},
|
| 512 |
-
{
|
| 513 |
-
"name": "beyondarena",
|
| 514 |
-
"endpoint": "/get_beyondarena_leaderboard",
|
| 515 |
-
"description": (
|
| 516 |
-
"Tabular ML beyond the IID assumption: random, temporal and grouped "
|
| 517 |
-
"splits across dataset sizes and feature types."
|
| 518 |
-
),
|
| 519 |
-
"axes": {"subset": list(BEYOND_SUBSET_LABELS), "kind": KIND_VALUES},
|
| 520 |
-
"csv_url_template": _BEYOND_CSV_TEMPLATE,
|
| 521 |
-
},
|
| 522 |
-
],
|
| 523 |
-
"record_keys": sorted(default_rows[0]) if default_rows else [],
|
| 524 |
-
"kinds": {
|
| 525 |
-
"models": "Individual models (TabPFN, RealMLP, LightGBM, ...). The default.",
|
| 526 |
-
"systems": (
|
| 527 |
-
f"Whole AutoML systems (AutoGluon, ...), marked '{SYSTEM_TYPE}' in the "
|
| 528 |
-
"artifacts. They tune and ensemble many models internally, so ranking them "
|
| 529 |
-
"against a single model compares different things."
|
| 530 |
-
),
|
| 531 |
-
"all": "Both, as the website's table shows them.",
|
| 532 |
-
},
|
| 533 |
-
"choosing_a_model": (
|
| 534 |
-
"For 'which model should I use', call get_pareto_frontier rather than reading the "
|
| 535 |
-
"top row here: it returns the accuracy/time trade-off, since the highest-Elo model "
|
| 536 |
-
"is often orders of magnitude slower than one just behind it. It also takes "
|
| 537 |
-
"train- and predict-time budgets."
|
| 538 |
-
),
|
| 539 |
-
"notes": (
|
| 540 |
-
"Scores are read from the published artifacts, so they match the website exactly. "
|
| 541 |
-
"Higher is better for elo and score; lower is better for rank, harmonic_rank, "
|
| 542 |
-
"improvability_pct and the time columns. Every record carries a `kind` of "
|
| 543 |
-
"'model' or 'system'; the get_* endpoints return models only unless asked."
|
| 544 |
-
),
|
| 545 |
-
}
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
def register_api() -> None:
|
| 549 |
-
"""Register the endpoints. Call inside the app's ``gr.Blocks`` context."""
|
| 550 |
-
gr.api(
|
| 551 |
-
list_leaderboards,
|
| 552 |
-
api_name="list_leaderboards",
|
| 553 |
-
api_description=(
|
| 554 |
-
"List the available TabArena leaderboards, the valid subset values for each, "
|
| 555 |
-
"the difference between models and systems, the keys every record carries, and "
|
| 556 |
-
"the raw CSV URLs for bulk download. Call this before the get_* endpoints."
|
| 557 |
-
),
|
| 558 |
-
)
|
| 559 |
-
gr.api(
|
| 560 |
-
get_tabarena_leaderboard,
|
| 561 |
-
api_name="get_tabarena_leaderboard",
|
| 562 |
-
api_description=(
|
| 563 |
-
"Ranked TabArena results (Elo, score, ranks, train/predict time) for one subset "
|
| 564 |
-
"of the IID benchmark, selected by tasks, datasets, imputation and splits. "
|
| 565 |
-
"Pass kind='models' (the default) for individual models such as TabPFN or "
|
| 566 |
-
"LightGBM, kind='systems' for whole AutoML systems such as AutoGluon, or "
|
| 567 |
-
"kind='all' for both. A question about the best model wants 'models'; a "
|
| 568 |
-
"question about the best AutoML framework wants 'systems'."
|
| 569 |
-
),
|
| 570 |
-
)
|
| 571 |
-
gr.api(
|
| 572 |
-
get_beyondarena_leaderboard,
|
| 573 |
-
api_name="get_beyondarena_leaderboard",
|
| 574 |
-
api_description=(
|
| 575 |
-
"Ranked BeyondArena results for one subset (random, temporal, grouped splits; "
|
| 576 |
-
"size and feature-type buckets), on the recommended core protocol. Takes the "
|
| 577 |
-
"same kind='models' | 'systems' | 'all' distinction as the TabArena endpoint."
|
| 578 |
-
),
|
| 579 |
-
)
|
| 580 |
-
gr.api(
|
| 581 |
-
get_pareto_frontier,
|
| 582 |
-
api_name="get_pareto_frontier",
|
| 583 |
-
api_description=(
|
| 584 |
-
"The accuracy-versus-time trade-off for one subset: the outright best model, "
|
| 585 |
-
"the models nothing beats on both accuracy and speed at once (each with its "
|
| 586 |
-
"speedup and accuracy gap versus the leader), and the best model that fits a "
|
| 587 |
-
"train- or predict-time budget. Prefer this over get_*_leaderboard for "
|
| 588 |
-
"'which model should I use', 'what is the best model', or any question about "
|
| 589 |
-
"models that are faster to fit or to serve: the top of the leaderboard is "
|
| 590 |
-
"often far slower than a model just behind it. Returns a summary sentence."
|
| 591 |
-
),
|
| 592 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constants.py
CHANGED
|
@@ -8,33 +8,12 @@ class Constants:
|
|
| 8 |
# Not Used
|
| 9 |
other: str = "Other"
|
| 10 |
|
| 11 |
-
# Order here defines the display order of the type legend and filters.
|
| 12 |
model_type_emoji = {
|
|
|
|
| 13 |
Constants.foundational: "🧠⚡",
|
| 14 |
Constants.neural_network:"🧠🔁",
|
| 15 |
-
Constants.tree: "🌳",
|
| 16 |
Constants.baseline: "📏",
|
| 17 |
# Not used
|
| 18 |
Constants.other: "❓",
|
| 19 |
Constants.reference:"📊",
|
| 20 |
}
|
| 21 |
-
|
| 22 |
-
# Per-variant accent color, taken from the interactive Leaderboard Overview
|
| 23 |
-
# explorer's --var-* (dark theme) so its variant toggles and the leaderboard
|
| 24 |
-
# table's agree. Keys must match views.VARIANT_VALUES.
|
| 25 |
-
variant_color = {
|
| 26 |
-
"default": "#4386d5",
|
| 27 |
-
"tuned": "#c05f38",
|
| 28 |
-
"tuned + ensembled": "#289972",
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
# Per-type accent color (readable as text/border on the dark theme). Used for the
|
| 32 |
-
# type legend and to color-code model names in the cross-subset overview.
|
| 33 |
-
model_type_color = {
|
| 34 |
-
Constants.foundational: "#b07cf0", # purple
|
| 35 |
-
Constants.neural_network: "#5aa9e6", # blue
|
| 36 |
-
Constants.tree: "#5cb85c", # green
|
| 37 |
-
Constants.baseline: "#9e9e9e", # gray
|
| 38 |
-
Constants.other: "#9e9e9e", # gray
|
| 39 |
-
Constants.reference: "#f0a35a", # orange
|
| 40 |
-
}
|
|
|
|
| 8 |
# Not Used
|
| 9 |
other: str = "Other"
|
| 10 |
|
|
|
|
| 11 |
model_type_emoji = {
|
| 12 |
+
Constants.tree: "🌳",
|
| 13 |
Constants.foundational: "🧠⚡",
|
| 14 |
Constants.neural_network:"🧠🔁",
|
|
|
|
| 15 |
Constants.baseline: "📏",
|
| 16 |
# Not used
|
| 17 |
Constants.other: "❓",
|
| 18 |
Constants.reference:"📊",
|
| 19 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/full-imputed-cls/leaderboard.tex
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llcccccrr}
|
| 2 |
+
\toprule
|
| 3 |
+
\textbf{Model} & \textbf{Elo ($\uparrow$)} & \textbf{Norm.} & \textbf{Avg.} & \textbf{Harm.} & \textbf{\#wins ($\uparrow$)} & \textbf{Improva-} & \textbf{Train time} & \textbf{Predict time} \\
|
| 4 |
+
& & \textbf{score ($\uparrow$)} & \textbf{rank ($\downarrow$)} & \textbf{mean} & & \textbf{bility ($\downarrow$)} & \textbf{per 1K [s]} & \textbf{per 1K [s]} \\
|
| 5 |
+
& & & & \textbf{rank ($\downarrow$)} & & & & \\
|
| 6 |
+
\midrule
|
| 7 |
+
TabM (T+E) & \textcolor{gold}{\textbf{1574${}_{-28,+28}$}} & \textcolor{bronze}{\textbf{0.505}} & \textcolor{gold}{\textbf{9.6}} & 4.5 & 3 & \textcolor{bronze}{\textbf{8.2\%}} & 2466.21 & 1.50 \\
|
| 8 |
+
AutoGluon 1.3 (4h) & \textcolor{silver}{\textbf{1573${}_{-34,+30}$}} & \textcolor{gold}{\textbf{0.577}} & \textcolor{silver}{\textbf{9.7}} & \textcolor{silver}{\textbf{3.3}} & \textcolor{silver}{\textbf{6}} & \textcolor{gold}{\textbf{6.9\%}} & 1322.72 & 2.36 \\
|
| 9 |
+
RealMLP (T+E) & \textcolor{bronze}{\textbf{1552${}_{-30,+32}$}} & 0.470 & \textcolor{bronze}{\textbf{10.5}} & 7.4 & 0 & \textcolor{bronze}{\textbf{8.2\%}} & 6519.69 & 10.84 \\
|
| 10 |
+
LightGBM (T+E) & 1537${}_{-30,+26}$ & 0.421 & 11.1 & 6.4 & 1 & 9.8\% & 382.05 & 1.49 \\
|
| 11 |
+
TabICL (D) & 1530${}_{-31,+23}$ & \textcolor{silver}{\textbf{0.512}} & 11.4 & \textcolor{bronze}{\textbf{3.5}} & \textcolor{silver}{\textbf{6}} & \textcolor{silver}{\textbf{7.9\%}} & 8.68 & 1.74 \\
|
| 12 |
+
TabM (T) & 1487${}_{-30,+29}$ & 0.420 & 13.2 & 6.4 & 1 & 9.3\% & 2466.21 & 0.18 \\
|
| 13 |
+
CatBoost (T+E) & 1479${}_{-26,+24}$ & 0.395 & 13.6 & 8.7 & 0 & 9.1\% & 1372.94 & 0.56 \\
|
| 14 |
+
CatBoost (T) & 1469${}_{-27,+25}$ & 0.379 & 13.9 & 7.0 & 1 & 9.3\% & 1372.94 & 0.07 \\
|
| 15 |
+
LightGBM (T) & 1463${}_{-29,+30}$ & 0.336 & 14.3 & 12.1 & 0 & 10.6\% & 382.05 & 0.25 \\
|
| 16 |
+
CatBoost (D) & 1454${}_{-28,+23}$ & 0.362 & 14.7 & 7.1 & 1 & 10.3\% & 5.72 & 0.08 \\
|
| 17 |
+
TabPFNv2 (T+E) & 1454${}_{-31,+25}$ & 0.497 & 14.7 & \textcolor{gold}{\textbf{3.1}} & \textcolor{gold}{\textbf{8}} & 9.7\% & 3008.22 & 20.85 \\
|
| 18 |
+
XGBoost (T+E) & 1452${}_{-28,+31}$ & 0.332 & 14.8 & 9.3 & 0 & 10.7\% & 685.87 & 1.45 \\
|
| 19 |
+
ModernNCA (T) & 1416${}_{-34,+24}$ & 0.289 & 16.5 & 9.7 & 1 & 10.5\% & 4879.89 & 0.52 \\
|
| 20 |
+
XGBoost (T) & 1412${}_{-26,+28}$ & 0.279 & 16.6 & 13.3 & 0 & 11.1\% & 685.87 & 0.21 \\
|
| 21 |
+
ModernNCA (T+E) & 1410${}_{-28,+27}$ & 0.382 & 16.7 & 7.5 & 0 & 10.4\% & 4879.89 & 8.74 \\
|
| 22 |
+
TabPFNv2 (T) & 1388${}_{-30,+33}$ & 0.385 & 17.8 & 5.2 & 1 & 12.1\% & 3008.22 & 0.51 \\
|
| 23 |
+
TabM (D) & 1375${}_{-26,+30}$ & 0.280 & 18.3 & 11.8 & 0 & 12.6\% & 10.21 & 0.14 \\
|
| 24 |
+
TabPFNv2 (D) & 1366${}_{-31,+25}$ & 0.354 & 18.8 & 4.8 & 4 & 13.0\% & 3.37 & 0.32 \\
|
| 25 |
+
TorchMLP (T+E) & 1364${}_{-28,+29}$ & 0.233 & 19.1 & 14.8 & 0 & 11.6\% & 2389.22 & 2.16 \\
|
| 26 |
+
RealMLP (T) & 1357${}_{-27,+29}$ & 0.188 & 19.4 & 16.7 & 0 & 12.0\% & 6519.69 & 0.53 \\
|
| 27 |
+
EBM (T+E) & 1356${}_{-28,+26}$ & 0.188 & 19.3 & 13.5 & 0 & 14.9\% & 914.23 & 0.22 \\
|
| 28 |
+
FastaiMLP (T+E) & 1323${}_{-29,+23}$ & 0.203 & 21.0 & 12.4 & 0 & 14.6\% & 618.90 & 4.77 \\
|
| 29 |
+
ModernNCA (D) & 1306${}_{-28,+26}$ & 0.140 & 21.8 & 12.3 & 1 & 14.7\% & 14.78 & 0.35 \\
|
| 30 |
+
EBM (T) & 1295${}_{-30,+26}$ & 0.130 & 22.4 & 17.9 & 0 & 15.6\% & 914.23 & 0.03 \\
|
| 31 |
+
EBM (D) & 1265${}_{-36,+29}$ & 0.143 & 23.9 & 11.4 & 1 & 16.6\% & 4.31 & 0.05 \\
|
| 32 |
+
RealMLP (D) & 1253${}_{-27,+23}$ & 0.088 & 24.5 & 21.0 & 0 & 14.6\% & 21.83 & 0.90 \\
|
| 33 |
+
XGBoost (D) & 1253${}_{-31,+29}$ & 0.116 & 24.5 & 19.3 & 0 & 14.1\% & 1.77 & 0.12 \\
|
| 34 |
+
ExtraTrees (T+E) & 1252${}_{-29,+24}$ & 0.110 & 24.6 & 16.8 & 0 & 15.8\% & 189.76 & 0.74 \\
|
| 35 |
+
TabDPT (D) & 1239${}_{-35,+28}$ & 0.180 & 25.1 & 8.1 & 2 & 15.5\% & 22.61 & 8.55 \\
|
| 36 |
+
TorchMLP (T) & 1237${}_{-26,+26}$ & 0.106 & 25.1 & 21.7 & 0 & 14.1\% & 2389.22 & 0.15 \\
|
| 37 |
+
FastaiMLP (T) & 1220${}_{-29,+28}$ & 0.093 & 26.1 & 20.7 & 0 & 16.6\% & 618.90 & 0.30 \\
|
| 38 |
+
RandomForest (T+E) & 1214${}_{-24,+25}$ & 0.105 & 26.3 & 14.4 & 0 & 16.6\% & 323.74 & 0.74 \\
|
| 39 |
+
LightGBM (D) & 1198${}_{-28,+29}$ & 0.087 & 27.0 & 23.6 & 0 & 15.4\% & 1.79 & 0.12 \\
|
| 40 |
+
ExtraTrees (T) & 1196${}_{-33,+24}$ & 0.080 & 27.1 & 17.2 & 0 & 17.2\% & 189.76 & 0.08 \\
|
| 41 |
+
RandomForest (T) & 1159${}_{-33,+33}$ & 0.078 & 28.8 & 16.5 & 0 & 17.8\% & 323.74 & 0.08 \\
|
| 42 |
+
TorchMLP (D) & 1082${}_{-30,+22}$ & 0.023 & 32.0 & 29.3 & 0 & 19.3\% & 6.83 & 0.15 \\
|
| 43 |
+
FastaiMLP (D) & 1053${}_{-31,+29}$ & 0.031 & 33.1 & 29.9 & 0 & 22.1\% & 2.91 & 0.37 \\
|
| 44 |
+
RandomForest (D) & 1000${}_{-0,+0}$ & 0.013 & 34.8 & 32.9 & 0 & 24.1\% & 0.38 & 0.04 \\
|
| 45 |
+
Linear (T+E) & 998${}_{-37,+26}$ & 0.042 & 34.9 & 25.5 & 0 & 29.2\% & 51.79 & 0.22 \\
|
| 46 |
+
Linear (T) & 962${}_{-28,+24}$ & 0.027 & 36.1 & 30.6 & 0 & 30.1\% & 51.79 & 0.08 \\
|
| 47 |
+
Linear (D) & 951${}_{-30,+28}$ & 0.019 & 36.3 & 27.8 & 0 & 31.1\% & 1.61 & 0.10 \\
|
| 48 |
+
ExtraTrees (D) & 915${}_{-31,+32}$ & 0.010 & 37.3 & 34.3 & 0 & 26.7\% & 0.25 & 0.04 \\
|
| 49 |
+
KNN (T+E) & 688${}_{-46,+39}$ & 0.000 & 41.7 & 41.4 & 0 & 48.5\% & 2.97 & 0.19 \\
|
| 50 |
+
KNN (T) & 605${}_{-45,+48}$ & 0.000 & 42.7 & 42.5 & 0 & 50.3\% & 2.97 & 0.04 \\
|
| 51 |
+
KNN (D) & 462${}_{-71,+70}$ & 0.000 & 43.9 & 43.7 & 0 & 58.7\% & 0.07 & 0.02 \\
|
| 52 |
+
\bottomrule
|
| 53 |
+
\end{tabular}
|
data/full-imputed-cls/tabarena_leaderboard.csv
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
method,time_train_s,time_infer_s,time_train_s_per_1K,time_infer_s_per_1K,normalized-error,normalized-error-task,imputed,champ_delta,loss_rescaled,time_train_s_rescaled,time_infer_s_rescaled,rank,median_metric_error,median_time_train_s,median_time_infer_s,median_time_train_s_per_1K,median_time_infer_s_per_1K,median_normalized-error,median_normalized-error-task,median_imputed,median_champ_delta,median_loss_rescaled,median_time_train_s_rescaled,median_time_infer_s_rescaled,median_rank,rank=1_count,rank=2_count,rank=3_count,rank>3_count,elo,elo+,elo-,winrate,mrr
|
| 2 |
+
TABM_GPU (tuned + ensemble),34341.376551290836,9.60910518720136,4223.58680397795,3.4317121842487635,0.4949870968434646,0.5299923578456494,0.0,0.08239957044412496,0.05800528924519605,45864.929770826835,134.55326674312073,9.644736842105264,0.17047,8245.070318195554,2.6588550435172187,2466.2108648716858,1.5022465694891438,0.4807674997729695,0.5356016471758118,0.0,0.0374695276183053,0.02990990162448854,39661.48674821285,121.43882105497326,9.0,3,2,2,31,1574.1,27.7,27.1,0.8035287081339713,0.22390813053432343
|
| 3 |
+
AutoGluon 1.3 (4h),7918.9967654708535,21.9962719316371,2834.6060407147975,3.0873029091200266,0.4234797507066772,0.42851773721350084,0.0,0.06891082208685434,0.03901042356832644,31011.170971980166,263.893057970457,9.710526315789474,0.159155,7086.632828738954,3.4718479580349393,1322.7174946761893,2.35500290690449,0.33567162503552783,0.4181224156574922,0.0,0.03226297629046343,0.018303111934730745,23372.022224152715,142.27612475951975,6.0,6,3,1,28,1573.4,30.0,33.4,0.8020334928229665,0.3009017525052929
|
| 4 |
+
REALMLP (tuned + ensemble),88520.97457650169,55.83305884453288,9129.519936677754,18.43403910125304,0.5303101151258073,0.5509587531175434,0.0,0.08216963958005759,0.04917872511787768,141789.21603781544,866.2933837817693,10.460526315789474,0.16568,30350.410282479395,23.161008212301468,6519.687377737515,10.838853332215592,0.4880190327087218,0.5530787180349611,0.0,0.046844798741680516,0.023927651830585747,114204.24024987879,769.6999972028425,9.25,0,1,1,36,1552.0,31.2,29.1,0.784988038277512,0.1359044319221565
|
| 5 |
+
GBM (tuned + ensemble),2957.8209862183407,11.98416593290909,759.1477152793035,2.5417865978850473,0.579228860288798,0.5992528140715053,0.0,0.09787395108553403,0.0587719228886129,8568.794143617388,184.93302208876983,11.131578947368421,0.16698000000000002,1552.8742877377404,3.4757837878333198,382.05361557599804,1.4876036641335277,0.6139242992830947,0.6320945623165324,0.0,0.050681941850522993,0.0219954442643497,7514.342598912193,103.35126359750211,10.0,1,1,2,34,1536.6,25.3,29.4,0.7697368421052632,0.15602996440606
|
| 6 |
+
TABICL_GPU (default),107.96023476381747,19.280086713506464,9.625347263659664,2.230965763361112,0.4883393558984766,0.5463468792496827,0.05263157894736842,0.0794222885606876,0.05664734932761992,168.76491644336255,230.09998232516136,11.394736842105264,0.17207,25.732762111557854,3.449363695250617,8.684246340890724,1.7433667301105085,0.49313937962268345,0.5681798960380293,0.0,0.03858333399786745,0.018532235328146802,137.81489160855577,127.65482709424812,10.0,6,4,1,27,1529.5,22.7,30.1,0.763755980861244,0.2848797584062183
|
| 7 |
+
TABM_GPU (tuned),34341.376551290836,1.0683778852050068,4223.58680397795,0.37888409513825755,0.580460857439686,0.5850736457317778,0.0,0.0927595492056652,0.07202518163358282,45864.929770826835,13.890136033418576,13.223684210526315,0.172585,8245.070318195554,0.2723346948623657,2466.2108648716858,0.17557376557934842,0.5594681994427791,0.6408535524589001,0.0,0.04800849593484757,0.03209545871697756,39661.48674821285,10.546435553124088,14.0,1,3,2,32,1487.1,28.6,29.5,0.722188995215311,0.15718600055013962
|
| 8 |
+
CAT (tuned + ensemble),16504.07579820414,2.581779239609925,3201.0265707590415,0.8915752484646539,0.6052324431308997,0.6079016429921736,0.0,0.09115569260254941,0.05171280995480023,27193.868813721343,44.08651163500922,13.552631578947368,0.16040500000000002,5046.900271190538,1.2630292971928916,1372.9411122807264,0.5562989902961428,0.6047135908900858,0.6538224316024461,0.0,0.05787378892595674,0.023358345198772973,20541.46486167592,37.76547447057217,13.0,0,1,3,34,1479.0,23.4,25.1,0.7147129186602871,0.11519163508706867
|
| 9 |
+
CAT (tuned),16504.07579820414,0.42638187025025576,3201.0265707590415,0.12024042770987867,0.6205816792872123,0.6195401164987226,0.0,0.09330164070819684,0.05138375883564522,27193.868813721343,6.229177098348047,13.881578947368421,0.161705,5046.900271190538,0.12877851062350804,1372.9411122807264,0.07385371803542701,0.6259023413364113,0.6684527369967126,0.0,0.05645008601114826,0.027822328565894415,20541.46486167592,4.9725379405984995,14.0,1,2,1,34,1469.3,24.3,26.2,0.7072368421052632,0.14306281114130998
|
| 10 |
+
GBM (tuned),2957.8209862183407,1.875632255676894,759.1477152793035,0.5049369881097493,0.664414327281209,0.6568405029860219,0.0,0.10551185264608158,0.06848969063218771,8568.794143617388,32.37091249654915,14.302631578947368,0.16877999999999999,1552.8742877377404,0.5045170254177518,382.05361557599804,0.2538713244201605,0.7037360500796572,0.6730961643801268,0.0,0.05207128139882822,0.031112468640158004,7514.342598912193,15.175591971121808,12.5,0,0,0,38,1463.4,29.5,28.3,0.6976674641148325,0.08286433502159408
|
| 11 |
+
TABPFNV2_GPU (tuned + ensemble),10002.759252123178,101.4355180454533,2653.4255131981217,44.749282859570734,0.5025912169508552,0.5552745352373752,0.3157894736842105,0.09695040281680861,0.08124534064551475,49565.00539849654,3444.4876051657507,14.671052631578947,0.17261500000000002,2077.023049354553,12.760541562239329,3008.2157047151595,20.848616639963154,0.508383993403513,0.5777919166792829,0.0,0.04061436251124223,0.031106953519191773,28624.579287895787,825.5109643363919,8.5,8,3,2,25,1453.8,24.8,30.9,0.6892942583732058,0.3228293379761294
|
| 12 |
+
CAT (default),220.2627424415789,0.2710267032099049,109.9732905896213,0.13662992734425208,0.6377213723455996,0.653981819624179,0.0,0.10281875743582664,0.05525161599592243,404.9759898295662,6.476751807794606,14.68421052631579,0.16373,18.264583627382912,0.17750852637820774,5.723546572951673,0.0761539571798428,0.6679727149434583,0.668034897235229,0.0,0.05481736123368691,0.025874497523709752,103.69107151573829,5.120402547941957,16.0,1,3,1,33,1454.1,22.2,27.3,0.6889952153110048,0.14085028107005457
|
| 13 |
+
XGB (tuned + ensemble),5957.374200563333,6.456417350253166,1167.526219278486,2.7907218103162132,0.6678696607918362,0.667447365405449,0.0,0.1067022658124541,0.0693895201734448,10832.944520166355,137.58836217438702,14.763157894736842,0.165745,1680.0658507664998,2.2809726662105985,685.86510540535,1.4547593315263065,0.7199373388598738,0.7259505715046674,0.0,0.0603611320440825,0.027448205694685396,8251.297786111467,74.47019952683146,13.0,0,1,1,36,1452.0,30.3,27.2,0.687200956937799,0.1077066830171761
|
| 14 |
+
MNCA_GPU (tuned),57356.284085895306,20.170870465214488,5990.817791505437,2.0485901061394993,0.7110105277591534,0.6595940582554153,0.0,0.1050159299928894,0.0724200510289198,80456.91211763977,129.4389431731015,16.526315789473685,0.17054999999999998,14186.536935488384,0.6020842525694106,4879.890404506269,0.5247194359730172,0.7789380151687756,0.6741481297678236,0.0,0.06755655006003625,0.04344719805270737,66956.02864547497,27.735396922747526,16.5,1,0,0,37,1415.9,23.5,33.3,0.6471291866028708,0.10295238153020833
|
| 15 |
+
XGB (tuned),5957.374200563333,1.301870340352867,1167.526219278486,0.6678561539347552,0.7214356698637235,0.7066756243519319,0.0,0.11080653156459744,0.07384263953337422,10832.944520166355,28.47499330573137,16.63157894736842,0.16848000000000002,1680.0658507664998,0.3827125522825453,685.86510540535,0.2050912539994952,0.7533869940641466,0.7531012522750911,0.0,0.0694652487234973,0.03410738014755424,8251.297786111467,11.461364611937853,15.5,0,0,0,38,1412.1,27.2,25.8,0.6447368421052632,0.07527320270823155
|
| 16 |
+
MNCA_GPU (tuned + ensemble),57356.284085895306,531.7593351699455,5990.817791505437,50.07821547982156,0.6178778787330054,0.6105886884096879,0.0,0.10389701155615068,0.07981152020070442,80456.91211763977,3301.6213661597712,16.68421052631579,0.183035,14186.536935488384,14.17156207561493,4879.890404506269,8.743516387788919,0.6004419642795275,0.5800963441226324,0.0,0.06497462948315735,0.039747452446492706,66956.02864547497,548.1975258046007,12.5,0,2,4,32,1410.4,26.7,27.6,0.6435406698564593,0.13300821802463408
|
| 17 |
+
TABPFNV2_GPU (tuned),10002.759252123178,3.410806728176206,2653.4255131981217,1.555769686886014,0.6152128339751168,0.6368249005546318,0.3157894736842105,0.12130685228554555,0.0956967324044558,49565.00539849654,114.00749994252256,17.842105263157894,0.1868,2077.023049354553,0.5060818235079447,3008.2157047151595,0.5144277113236544,0.6861393226426085,0.651413564581804,0.0,0.08561151707807774,0.042273687584978896,28624.579287895787,25.570859321617846,13.0,1,8,1,28,1387.8,32.2,29.9,0.6172248803827751,0.19384505458173865
|
| 18 |
+
TABM_GPU (default),150.0762373017289,1.2507152029645372,19.886819500646006,0.46487430096802723,0.7200913651969231,0.7318128476710409,0.0,0.1257035538283091,0.09205633408961793,189.61145131944258,14.042337078320946,18.32894736842105,0.17246,31.126562476158142,0.20260944763819377,10.213381764059356,0.1381032773929915,0.8315398727681542,0.7950654471852272,0.0,0.06154427249600947,0.03281090889681732,144.96049255349743,10.968725907290855,18.0,0,0,1,37,1375.0,29.4,25.1,0.6061602870813397,0.08448030842994195
|
| 19 |
+
TABPFNV2_GPU (default),11.400364582092442,0.8958970822786029,4.227300497658887,0.4575723059305235,0.646401200043383,0.6913643236884485,0.3157894736842105,0.13032850434642715,0.10434014574898658,53.73712299744585,29.471362460513575,18.842105263157894,0.1886,7.994279013739691,0.2908047080039978,3.368600991426515,0.3152861168047789,0.777395370386663,0.7325492470622512,0.0,0.07929605277196083,0.04313507441518306,41.34560285308973,17.75894630310718,17.0,4,1,4,29,1366.1,24.9,30.7,0.5944976076555024,0.21051957029694982
|
| 20 |
+
NN_TORCH (tuned + ensemble),24331.947126566527,16.31368946276213,3050.9102763481856,4.325404104362444,0.7674791714524483,0.751965702834341,0.0,0.11637811814114107,0.08020239923609776,56038.718047349466,227.24142067178357,19.05263157894737,0.17071999999999998,9097.789536105262,5.056680162747702,2389.2199648500327,2.157502904371376,0.8880043848397714,0.8073663594549582,0.0,0.06782479524801643,0.04484831234958845,44480.90343297912,173.17543399472862,19.5,0,0,0,38,1364.3,29.0,27.1,0.5897129186602871,0.06737424255513398
|
| 21 |
+
EBM (tuned + ensemble),36729.440274559965,1.3371900389766136,6141.104384884199,0.5036823041953499,0.811594312476448,0.8073262691422789,0.0,0.14906209202998957,0.10957472519228896,25271.27145534202,19.518642702178116,19.342105263157894,0.17122500000000002,2366.879786974854,0.4240463972091675,914.2329798556116,0.21634762578811195,0.9034396658321221,0.8509428943624828,0.0,0.0823298574360965,0.040258063765572304,15273.913117491418,11.254406005139426,19.0,0,0,1,37,1356.1,25.2,27.9,0.5831339712918661,0.07392904855395822
|
| 22 |
+
REALMLP (tuned),88520.97457650169,2.4448067613512454,9129.519936677754,0.9659323148202512,0.8116906333552832,0.7529096930561373,0.0,0.11967014747000536,0.08502935951276701,141789.21603781544,39.671058690327705,19.355263157894736,0.17194500000000001,30350.410282479395,0.9911958641476102,6519.687377737515,0.5341468926001405,0.8954815082143113,0.7906338583190218,0.0,0.076222073390521,0.04561771439992753,114204.24024987879,35.28258688191838,18.75,0,0,0,38,1356.9,28.2,26.5,0.5828349282296651,0.059857762488610834
|
| 23 |
+
FASTAI (tuned + ensemble),7309.51755415473,18.692008190266574,1376.1098802486467,8.473426897342513,0.7967114176056229,0.7935375376704039,0.0,0.14576367767903883,0.08697133573600783,18964.092381812123,455.5897128961598,21.013157894736842,0.178125,3087.37076303694,11.787012616793314,618.8953909329178,4.7655686359255345,0.9993616733332265,0.8596726175256504,0.0,0.08731644523471122,0.054465543302125864,15284.817189242676,443.8905026950689,22.75,0,1,0,37,1323.2,22.6,28.2,0.5451555023923444,0.08034444085096946
|
| 24 |
+
MNCA_GPU (default),304.22019695963775,10.484658345144394,17.60828380729721,1.3061868722894623,0.8600476423581978,0.8133618407225838,0.0,0.14684370064110588,0.09623286753523605,254.62493914649235,74.63976386946672,21.789473684210527,0.18519,31.500762327512106,0.5732622504234314,14.777266169000828,0.34634581634079226,1.0,0.893695279008777,0.0,0.09230605494417649,0.051103226670839136,209.09978531409226,23.91921150117286,23.0,1,0,0,37,1306.1,25.7,27.4,0.527511961722488,0.08099601234817519
|
| 25 |
+
EBM (tuned),36729.440274559965,0.18373215324000308,6141.104384884199,0.08212434505580339,0.8701293455239967,0.8449855604868557,0.0,0.15617886229027844,0.11711713769734972,25271.27145534202,2.5019643980329747,22.42105263157895,0.17203000000000002,2366.879786974854,0.0449512971772088,914.2329798556116,0.02528246646038782,1.0,0.8943570495572675,0.0,0.08835084225135731,0.04420635043937865,15273.913117491418,1.252412448907763,23.5,0,0,0,38,1295.1,25.2,29.9,0.5131578947368421,0.05576760659451273
|
| 26 |
+
EBM (default),119.68166406294058,0.19009479611937763,11.429209024387047,0.10185762188607354,0.8572475476046651,0.8539911315322448,0.0,0.16604276757956396,0.12380006768435853,109.6134925105603,3.4110931424674527,23.894736842105264,0.17447000000000001,9.92618230978648,0.06371633741590713,4.31382445805991,0.0475851422516083,1.0,0.9282824912353611,0.0,0.09554880640873625,0.03755874966541475,60.70178540099199,2.7834768100426253,24.0,1,0,2,35,1264.9,28.3,35.7,0.4796650717703349,0.08753724330105657
|
| 27 |
+
REALMLP (default),302.86446626785903,3.0018129969200893,26.277581916467653,2.856467141391241,0.9122374081508348,0.85760098469969,0.0,0.14572889637854225,0.10212034328423684,472.82883048215837,115.85189921010567,24.5,0.17367,103.08245442973242,2.582352219687568,21.83278809042843,0.8957992336206358,1.0,0.8896440117833417,0.0,0.11770994919600164,0.06845697585035651,372.59928806765174,52.85349774079455,25.5,0,0,0,38,1253.4,23.0,26.4,0.4659090909090909,0.04751011701630104
|
| 28 |
+
XGB (default),13.116732126927516,0.5742131232518202,3.202512268619222,0.2981186068489448,0.8843514041095932,0.8510762104833869,0.0,0.14066462097580287,0.11671766984062094,31.46292861336276,13.4756369742995,24.5,0.17317,5.653352538744608,0.30113152662913,1.771208861779989,0.11707781619763814,1.0,0.9410060237993583,0.0,0.09869044613168698,0.06054796407572259,28.26053761224749,9.127662964815336,24.0,0,0,0,38,1253.3,28.1,30.7,0.4659090909090909,0.05191659220532364
|
| 29 |
+
XT (tuned + ensemble),1317.4209560674533,2.9519454171085915,472.65138083581655,1.3657584923642982,0.889559570547466,0.8556261516301992,0.0,0.1579271337121436,0.11679174830217959,4571.615940832833,75.60244638381447,24.57894736842105,0.17667500000000003,756.8230986197789,1.8136235740449693,189.76252609436062,0.7431041876698922,1.0,0.93225990863037,0.0,0.09299076955407681,0.0685642717298475,2805.66154207989,66.39288968996527,27.5,0,0,1,37,1251.6,23.8,28.6,0.46411483253588515,0.05948664377868326
|
| 30 |
+
TABDPT_GPU (default),171.71139350780967,66.09824930987163,27.724576482795502,22.626481529214185,0.8200159004748209,0.8098229820925923,0.0,0.1548400388440821,0.1161870388203104,481.10896045076544,1338.9171702872993,25.105263157894736,0.190385,97.80311637454562,28.07416233751509,22.609050986069803,8.552450841932743,1.0,0.9583506424916117,0.0,0.1092338236572048,0.046097964205681456,400.67828468381333,1123.8959746745188,30.0,2,0,3,33,1238.6,27.7,34.6,0.45215311004784686,0.12327697073991685
|
| 31 |
+
NN_TORCH (tuned),24331.947126566527,0.8716282456241854,3050.9102763481856,0.24396545036982029,0.8935160561232315,0.8422311335793125,0.0,0.14120278296028227,0.10508427239733291,56038.718047349466,12.138164397560297,25.144736842105264,0.17446499999999998,9097.789536105262,0.29952494303385413,2389.2199648500327,0.15177921475257505,1.0,0.9030726729865997,0.0,0.10379368194908523,0.06014400941853005,44480.90343297912,9.196372470124006,25.5,0,0,0,38,1237.2,25.5,25.3,0.451255980861244,0.046101906732064955
|
| 32 |
+
FASTAI (tuned),7309.51755415473,1.0496307073977955,1376.1098802486467,0.623937267000547,0.9066743837597047,0.8621224292232853,0.0,0.16578900249006634,0.10852452399743645,18964.092381812123,32.00078545496663,26.06578947368421,0.18023499999999998,3087.37076303694,0.8054822285970051,618.8953909329178,0.2978802219128553,1.0,0.9088593404454739,0.0,0.09789639604232409,0.0649858160039401,15284.817189242676,26.536834640421894,26.0,0,0,0,38,1220.2,27.5,28.1,0.43032296650717705,0.04823155314220717
|
| 33 |
+
RF (tuned + ensemble),2309.3465478268977,2.3587986137434753,541.3031953907538,1.2662572218585502,0.8949088487058612,0.8653921072161802,0.0,0.16581458532483917,0.12803665978914544,5371.163113535875,67.79453318661523,26.31578947368421,0.177925,871.1966819789675,1.9029027620951335,323.74369638605225,0.7428875097152683,1.0,0.976443274983263,0.0,0.10359622790389916,0.07479078376008455,4278.677975908691,61.67862848692378,28.5,0,1,1,36,1213.5,24.8,23.2,0.4246411483253589,0.06923937840225046
|
| 34 |
+
GBM (default),7.9087888545460165,0.5753568479889317,2.951996847158713,0.17011749256975625,0.9125347540697407,0.8867856543564054,0.0,0.15377361970482045,0.11510537200611927,31.85523047906877,10.81395814590769,27.026315789473685,0.172975,5.532836645179325,0.2585195038053725,1.7913477923414471,0.12049981156984965,1.0,0.953002789600119,0.0,0.11068698010353623,0.0625734900521432,25.045220341015206,6.549914554959342,28.0,0,0,0,38,1197.8,28.8,27.4,0.4084928229665072,0.04242553702308852
|
| 35 |
+
XT (tuned),1317.4209560674533,0.3043035832762021,472.65138083581655,0.1722314796858175,0.9201818360376706,0.887453690669917,0.0,0.1716073337665082,0.12727956433250776,4571.615940832833,8.349379059762423,27.11842105263158,0.17796,756.8230986197789,0.18769407272338867,189.76252609436062,0.07878183958882805,1.0,0.9660073423997149,0.0,0.10587649481110034,0.07275368947647169,2805.66154207989,8.013491457037578,30.0,0,1,0,37,1195.6,24.0,32.1,0.4063995215311005,0.05828850461349728
|
| 36 |
+
RF (tuned),2309.3465478268977,0.23789871352457861,541.3031953907538,0.15647241398955916,0.9224816586070888,0.8914900089794889,0.0,0.17793267481613345,0.14008678334835084,5371.163113535875,7.241889916329925,28.763157894736842,0.178915,871.1966819789675,0.17230602105458576,323.74369638605225,0.07643497412773152,1.0,0.9949804738019044,0.0,0.11788865245982966,0.07710393358859187,4278.677975908691,6.216263662191708,31.5,0,1,1,36,1159.2,32.8,32.1,0.36901913875598086,0.060732505395188326
|
| 37 |
+
NN_TORCH (default),48.66164081361559,0.6504810580733227,11.536659167937149,0.237589986723434,0.9768277299582552,0.9516276223313249,0.0,0.19345935921063773,0.14725824727620437,155.18773864824473,10.878820110101595,31.986842105263158,0.180355,26.916632894674937,0.2675716214709811,6.83469910157457,0.14703020953097523,1.0,0.9983912483912485,0.0,0.142508632176782,0.09058242754644441,137.05069981706868,8.619821917518276,33.0,0,0,0,38,1081.6,21.3,29.3,0.29575358851674644,0.0341695156824269
|
| 38 |
+
FASTAI (default),31.12571889106293,1.103970385504048,5.0919225272079345,0.5139922583887925,0.9692956872023926,0.9418353795989344,0.0,0.2205946249171078,0.17081144202844967,74.47424680202033,27.97257070113272,33.078947368421055,0.19183499999999998,12.713354892200893,0.7982388072543674,2.9120182447539116,0.36810695156439827,1.0,1.0,0.0,0.16584224786083723,0.11423976777713259,60.1261932941261,24.301698162325565,36.0,0,0,0,38,1052.8,28.1,30.9,0.27093301435406697,0.03346355889150736
|
| 39 |
+
RF (default),3.928520040972191,0.1435067986187182,0.8021093004373405,0.07125612411976835,0.9873793306417248,0.9675347593198196,0.0,0.24146620137116087,0.23100094778843142,6.102631035159317,3.7416299644570024,34.80263157894737,0.21025,1.1966572999954224,0.08589340580834282,0.3813090053938437,0.03721195658349352,1.0,1.0,0.0,0.17586669886220047,0.11692775501298655,5.480722222590385,3.4579154094346745,36.5,0,0,0,38,1000.0,0.0,0.0,0.23175837320574164,0.03044058622007152
|
| 40 |
+
LR (tuned + ensemble),310.9206490230839,1.856038474618343,112.43523004573552,0.6244822981818133,0.9583388751756515,0.9525027008333006,0.0,0.2917619246531289,0.2639449201736458,1090.6543235756506,24.154836057241496,34.94736842105263,0.20569500000000002,172.99803659651013,0.33067578077316284,51.78500762114817,0.22385943240534312,1.0,1.0,0.0,0.23092004636837282,0.1418450851884247,696.2608974821628,13.25530093456624,38.0,0,0,1,37,998.1,25.5,37.0,0.2284688995215311,0.039205008884686546
|
| 41 |
+
LR (tuned),310.9206490230839,0.5155129476597434,112.43523004573552,0.17331679222553462,0.9727265210610188,0.9599648989348959,0.0,0.30105734113761295,0.27391129557139166,1090.6543235756506,6.903044838007482,36.05263157894737,0.20751,172.99803659651013,0.12874411212073433,51.78500762114817,0.07805190196778514,1.0,1.0,0.0,0.23702586233900474,0.14460038903245942,696.2608974821628,4.422167155622043,38.5,0,0,0,38,961.6,23.9,27.7,0.20334928229665072,0.0327143779465347
|
| 42 |
+
LR (default),7.59960079534709,0.5285763780973111,2.68894957171299,0.18897855365485863,0.9811233759976523,0.9657118387068965,0.0,0.3109312407898901,0.298004116613438,27.747857838408066,7.876763349331487,36.3421052631579,0.21230500000000002,5.359276652336121,0.13779839674631755,1.6116061178401027,0.09774404154712064,1.0,1.0,0.0,0.23702577885376547,0.1541261802297627,18.023625361427616,4.735441569338942,40.0,0,0,1,37,950.6,27.1,29.7,0.19677033492822968,0.03600631416753817
|
| 43 |
+
XT (default),2.7359117016457675,0.18087529669031066,0.7550887156747417,0.07422230753863952,0.9896376739572407,0.9751584322493536,0.0,0.26658722117284267,0.26095559827613696,5.173741811459425,4.243951698357253,37.26315789473684,0.21292,1.01790091726515,0.09051434199015299,0.24605929188859293,0.04072451222400395,1.0,1.0,0.0,0.18424442460299273,0.13780186094528035,4.456264068369281,3.7424721126192138,39.0,0,0,0,38,914.9,32.0,30.5,0.17583732057416268,0.0291505121116296
|
| 44 |
+
KNN (tuned + ensemble),167.0455302492917,11.66904854404996,12.260943976874097,0.77695539036087,1.0,0.9962934098751769,0.13157894736842105,0.48462823969745605,0.5970228537293082,72.48328913141673,77.9475913060204,41.671052631578945,0.318405,9.821025305324131,0.2367298404375712,2.969713103492417,0.18997109296167614,1.0,1.0,0.0,0.42625485653324524,0.6596342220080722,56.9019152818522,12.487074071232104,43.0,0,0,0,38,688.4,38.7,45.5,0.0756578947368421,0.024178278159192945
|
| 45 |
+
KNN (tuned),167.0455302492917,1.8054817143936601,12.260943976874097,0.13106223823409818,1.0,0.9976590626673897,0.13157894736842105,0.5033620273790689,0.6430012930336472,72.48328913141673,12.511864612142434,42.671052631578945,0.322975,9.821025305324131,0.0851174063152737,2.969713103492417,0.040417757021976156,1.0,1.0,0.0,0.4549174904387682,0.7006933550921264,56.9019152818522,2.342964973116946,44.0,0,0,0,38,605.3,48.0,44.4,0.05293062200956938,0.02351625016097909
|
| 46 |
+
KNN (default),1.7449495283483762,0.22627578220869365,0.489346568018936,0.038714559202156204,1.0,1.0,0.13157894736842105,0.5871637410556744,0.939313827722613,1.0055419249185589,2.3649007838074403,43.921052631578945,0.382765,0.27595198154449463,0.036337282922532826,0.07126887487893994,0.021006283652748647,1.0,1.0,0.0,0.5463314318406584,1.0,1.0,1.2165713596834893,45.0,0,0,0,38,462.1,69.7,70.6,0.02452153110047847,0.022868529201343697
|
data/full-imputed-reg/leaderboard.tex
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llcccccrr}
|
| 2 |
+
\toprule
|
| 3 |
+
\textbf{Model} & \textbf{Elo ($\uparrow$)} & \textbf{Norm.} & \textbf{Avg.} & \textbf{Harm.} & \textbf{\#wins ($\uparrow$)} & \textbf{Improva-} & \textbf{Train time} & \textbf{Predict time} \\
|
| 4 |
+
& & \textbf{score ($\uparrow$)} & \textbf{rank ($\downarrow$)} & \textbf{mean} & & \textbf{bility ($\downarrow$)} & \textbf{per 1K [s]} & \textbf{per 1K [s]} \\
|
| 5 |
+
& & & & \textbf{rank ($\downarrow$)} & & & & \\
|
| 6 |
+
\midrule
|
| 7 |
+
AutoGluon 1.3 (4h) & \textcolor{gold}{\textbf{1795${}_{-55,+67}$}} & \textcolor{gold}{\textbf{0.740}} & \textcolor{gold}{\textbf{4.6}} & \textcolor{silver}{\textbf{2.5}} & 2 & \textcolor{silver}{\textbf{2.7\%}} & 1625.74 & 6.76 \\
|
| 8 |
+
RealMLP (T+E) & \textcolor{silver}{\textbf{1766${}_{-64,+61}$}} & \textcolor{silver}{\textbf{0.732}} & \textcolor{silver}{\textbf{5.3}} & 3.4 & 0 & \textcolor{gold}{\textbf{2.0\%}} & 7141.94 & 9.66 \\
|
| 9 |
+
ModernNCA (T+E) & \textcolor{bronze}{\textbf{1632${}_{-52,+51}$}} & 0.625 & \textcolor{bronze}{\textbf{8.3}} & \textcolor{bronze}{\textbf{2.8}} & \textcolor{silver}{\textbf{3}} & 3.8\% & 3779.52 & 7.69 \\
|
| 10 |
+
TabDPT (D) & 1620${}_{-62,+53}$ & \textcolor{bronze}{\textbf{0.651}} & 8.8 & \textcolor{gold}{\textbf{2.3}} & \textcolor{gold}{\textbf{5}} & \textcolor{bronze}{\textbf{2.9\%}} & 22.53 & 8.55 \\
|
| 11 |
+
CatBoost (T+E) & 1616${}_{-51,+59}$ & 0.547 & 8.9 & 7.2 & 0 & 4.5\% & 3552.96 & 0.97 \\
|
| 12 |
+
LightGBM (T+E) & 1609${}_{-53,+58}$ & 0.542 & 9.2 & 7.1 & 0 & 5.0\% & 700.15 & 9.32 \\
|
| 13 |
+
CatBoost (T) & 1568${}_{-46,+64}$ & 0.524 & 10.3 & 6.9 & 0 & 4.6\% & 3552.96 & 0.10 \\
|
| 14 |
+
TabM (T+E) & 1562${}_{-64,+54}$ & 0.494 & 10.5 & 6.5 & 0 & 3.3\% & 4158.29 & 1.41 \\
|
| 15 |
+
XGBoost (T+E) & 1496${}_{-51,+43}$ & 0.447 & 12.8 & 12.3 & 0 & 5.5\% & 834.93 & 2.61 \\
|
| 16 |
+
LightGBM (T) & 1490${}_{-50,+55}$ & 0.445 & 12.9 & 10.8 & 0 & 5.6\% & 700.15 & 0.97 \\
|
| 17 |
+
XGBoost (T) & 1474${}_{-46,+46}$ & 0.414 & 13.7 & 13.1 & 0 & 5.6\% & 834.93 & 0.39 \\
|
| 18 |
+
ModernNCA (T) & 1446${}_{-49,+52}$ & 0.360 & 14.6 & 7.2 & 0 & 5.9\% & 3779.52 & 0.40 \\
|
| 19 |
+
TabM (T) & 1440${}_{-54,+39}$ & 0.392 & 15.0 & 11.6 & 0 & 4.3\% & 4158.29 & 0.17 \\
|
| 20 |
+
CatBoost (D) & 1439${}_{-57,+48}$ & 0.400 & 15.0 & 11.5 & 0 & 6.2\% & 10.89 & 0.09 \\
|
| 21 |
+
RealMLP (T) & 1405${}_{-53,+53}$ & 0.350 & 16.4 & 13.9 & 0 & 4.6\% & 7141.94 & 0.39 \\
|
| 22 |
+
TabPFNv2 (T+E) & 1381${}_{-47,+55}$ & 0.414 & 17.2 & 3.1 & \textcolor{silver}{\textbf{3}} & 5.1\% & 4223.87 & 27.54 \\
|
| 23 |
+
ModernNCA (D) & 1340${}_{-54,+50}$ & 0.216 & 18.8 & 14.1 & 0 & 7.4\% & 15.50 & 0.30 \\
|
| 24 |
+
TabM (D) & 1329${}_{-48,+53}$ & 0.300 & 19.2 & 15.6 & 0 & 6.0\% & 13.32 & 0.13 \\
|
| 25 |
+
TorchMLP (T+E) & 1306${}_{-57,+46}$ & 0.182 & 20.2 & 14.6 & 0 & 7.6\% & 4608.59 & 1.23 \\
|
| 26 |
+
TabPFNv2 (T) & 1300${}_{-55,+53}$ & 0.287 & 20.6 & 8.4 & 0 & 6.2\% & 4223.87 & 0.45 \\
|
| 27 |
+
RealMLP (D) & 1284${}_{-48,+47}$ & 0.152 & 21.3 & 18.4 & 0 & 7.0\% & 21.86 & 0.84 \\
|
| 28 |
+
ExtraTrees (T+E) & 1272${}_{-60,+53}$ & 0.162 & 21.5 & 13.6 & 0 & 10.0\% & 158.22 & 0.84 \\
|
| 29 |
+
LightGBM (D) & 1264${}_{-54,+53}$ & 0.091 & 21.9 & 21.3 & 0 & 8.1\% & 2.11 & 0.27 \\
|
| 30 |
+
ExtraTrees (T) & 1255${}_{-53,+42}$ & 0.136 & 22.3 & 16.9 & 0 & 10.3\% & 158.22 & 0.15 \\
|
| 31 |
+
TabPFNv2 (D) & 1231${}_{-61,+59}$ & 0.238 & 23.3 & 11.5 & 0 & 7.6\% & 2.80 & 0.31 \\
|
| 32 |
+
TorchMLP (T) & 1230${}_{-47,+46}$ & 0.131 & 23.3 & 20.1 & 0 & 8.4\% & 4608.59 & 0.10 \\
|
| 33 |
+
XGBoost (D) & 1215${}_{-46,+42}$ & 0.114 & 24.1 & 21.5 & 0 & 8.8\% & 2.24 & 0.24 \\
|
| 34 |
+
RandomForest (T+E) & 1203${}_{-48,+46}$ & 0.076 & 24.5 & 22.4 & 0 & 10.9\% & 515.73 & 0.77 \\
|
| 35 |
+
RandomForest (T) & 1153${}_{-58,+49}$ & 0.055 & 26.2 & 24.5 & 0 & 11.4\% & 515.73 & 0.12 \\
|
| 36 |
+
EBM (T+E) & 1136${}_{-61,+46}$ & 0.171 & 27.0 & 13.4 & 0 & 13.7\% & 1890.68 & 0.13 \\
|
| 37 |
+
ExtraTrees (D) & 1100${}_{-63,+56}$ & 0.069 & 28.1 & 25.0 & 0 & 12.2\% & 0.47 & 0.06 \\
|
| 38 |
+
EBM (T) & 1092${}_{-57,+50}$ & 0.150 & 28.5 & 17.0 & 0 & 14.2\% & 1890.68 & 0.01 \\
|
| 39 |
+
FastaiMLP (T+E) & 1040${}_{-50,+62}$ & 0.024 & 30.0 & 28.0 & 0 & 12.2\% & 540.06 & 2.67 \\
|
| 40 |
+
TorchMLP (D) & 1038${}_{-63,+58}$ & 0.017 & 30.2 & 28.2 & 0 & 11.9\% & 20.48 & 0.08 \\
|
| 41 |
+
EBM (D) & 1034${}_{-67,+44}$ & 0.109 & 30.6 & 27.7 & 0 & 15.1\% & 6.33 & 0.04 \\
|
| 42 |
+
RandomForest (D) & 1000${}_{-0,+0}$ & 0.000 & 31.3 & 30.7 & 0 & 12.9\% & 0.53 & 0.06 \\
|
| 43 |
+
FastaiMLP (T) & 992${}_{-65,+49}$ & 0.014 & 31.7 & 30.4 & 0 & 12.7\% & 540.06 & 0.32 \\
|
| 44 |
+
FastaiMLP (D) & 858${}_{-70,+53}$ & 0.000 & 34.9 & 34.3 & 0 & 17.1\% & 2.60 & 0.39 \\
|
| 45 |
+
KNN (T+E) & 532${}_{-96,+78}$ & 0.000 & 39.8 & 39.6 & 0 & 36.1\% & 2.43 & 0.14 \\
|
| 46 |
+
Linear (T+E) & 489${}_{-95,+53}$ & 0.000 & 40.3 & 40.2 & 0 & 35.4\% & 45.74 & 0.11 \\
|
| 47 |
+
KNN (T) & 442${}_{-135,+68}$ & 0.000 & 40.8 & 40.6 & 0 & 36.8\% & 2.43 & 0.03 \\
|
| 48 |
+
Linear (T) & 421${}_{-95,+82}$ & 0.000 & 40.9 & 40.8 & 0 & 35.6\% & 45.74 & 0.05 \\
|
| 49 |
+
Linear (D) & 290${}_{-113,+87}$ & 0.000 & 42.2 & 42.1 & 0 & 38.1\% & 1.19 & 0.09 \\
|
| 50 |
+
KNN (D) & 239${}_{-146,+87}$ & 0.000 & 42.6 & 42.4 & 0 & 40.8\% & 0.04 & 0.02 \\
|
| 51 |
+
\bottomrule
|
| 52 |
+
\end{tabular}
|
data/full-imputed-reg/tabarena_leaderboard.csv
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
method,time_train_s,time_infer_s,time_train_s_per_1K,time_infer_s_per_1K,normalized-error,normalized-error-task,imputed,champ_delta,loss_rescaled,time_train_s_rescaled,time_infer_s_rescaled,rank,median_metric_error,median_time_train_s,median_time_infer_s,median_time_train_s_per_1K,median_time_infer_s_per_1K,median_normalized-error,median_normalized-error-task,median_imputed,median_champ_delta,median_loss_rescaled,median_time_train_s_rescaled,median_time_infer_s_rescaled,median_rank,rank=1_count,rank=2_count,rank=3_count,rank>3_count,elo,elo+,elo-,winrate,mrr
|
| 2 |
+
AutoGluon 1.3 (4h),10053.09853225386,65.70725388180496,3138.716102354025,8.201870690838728,0.2604881581536672,0.2971194348020468,0.0,0.026995880876839205,0.03762065178367739,79227.35072832079,1344.7158520024777,4.615384615384615,4.16484,12938.261539538702,10.17258334159851,1625.738447135909,6.759745919437983,0.23036881663552905,0.30366624015393634,0.0,0.015883109174547605,0.016643068102528722,85166.92529682687,517.5224332581762,4.0,2,3,1,7,1795.1,67.0,54.8,0.9159212880143113,0.3928904428904429
|
| 3 |
+
REALMLP (tuned + ensemble),66543.44573790843,35.91296550086421,7325.429690273165,14.32081689268905,0.2681319612182075,0.3168526714039812,0.0,0.019775498611648384,0.029999838203468132,290863.52338623884,790.182850123545,5.3076923076923075,4.13253,35612.93265602324,25.25520912806193,7141.940159399529,9.664030993978182,0.21463277228840488,0.3314660386375113,0.0,0.015498759976369625,0.017118693739991864,262171.8658686582,808.3809230744637,3.0,0,4,3,6,1765.6,60.7,63.8,0.8998211091234347,0.2966880341880342
|
| 4 |
+
MNCA_GPU (tuned + ensemble),31759.101002019288,48.99773550746787,6166.048475961011,17.643273328787647,0.37486519261010337,0.3801843857676789,0.0,0.038093035353910405,0.03729025388197337,186080.1526868885,677.6872983460363,8.307692307692308,4.48697,16310.556293937894,10.227302259869045,3779.5248398651206,7.690422738079533,0.33564273912263787,0.35100871313945403,0.0,0.019057076597787104,0.02404483039332963,198038.2195884601,507.5335424076248,7.0,3,1,1,8,1632.5,51.0,51.8,0.8300536672629696,0.35811118705855544
|
| 5 |
+
TABDPT_GPU (default),150.02111775732448,54.38835432835114,28.728808967170515,25.042434382939593,0.34889596641909676,0.3868397999855826,0.0,0.0290119218252697,0.03451422020936026,859.9949957462201,1916.4746059233426,8.846153846153847,4.26747,137.4807067182329,29.239719518025716,22.52690614988171,8.547073882575031,0.2832974905649298,0.3551487188815256,0.0,0.024988993973347418,0.022011234994563023,904.9754515353668,1821.0928942426492,8.0,5,0,0,8,1620.5,52.9,61.7,0.817531305903399,0.44424741924741923
|
| 6 |
+
CAT (tuned + ensemble),30302.612278386874,4.803950041991014,6846.603031359736,1.23549623448159,0.4533481852287783,0.4926936982252365,0.0,0.04475906131711523,0.05586568278238831,150000.99966111325,116.73562230823504,8.923076923076923,4.20864,22090.5574801498,2.685193909539117,3552.958864906998,0.9657383741190037,0.4197753110205541,0.5095036442102125,0.0,0.0214910315460225,0.0360010253274791,164350.82166574517,80.04598787510639,9.0,0,0,1,12,1615.9,58.2,51.0,0.815742397137746,0.13981452645420256
|
| 7 |
+
GBM (tuned + ensemble),3469.6354441180188,51.50608464469258,806.792675338677,8.57889161766087,0.4578704418351117,0.4915767713552377,0.0,0.049628721858481745,0.06009436123338137,20529.34803212188,1135.938430886033,9.153846153846153,4.21165,3055.419878217909,17.84196005927192,700.1537746143185,9.321818212785747,0.41469312312474516,0.4239687696189567,0.0,0.026696516466175324,0.03428340330572247,21786.570035668443,556.5446710812895,7.0,0,0,0,13,1608.9,57.6,52.5,0.8103756708407871,0.14022351917088757
|
| 8 |
+
CAT (tuned),30302.612278386874,0.5550543483505901,6846.603031359736,0.16909210735792113,0.47626653515508005,0.5114892609915386,0.0,0.04596154469633722,0.059493084445231575,150000.99966111325,13.40589862804556,10.26923076923077,4.23064,22090.5574801498,0.3789627022213406,3552.958864906998,0.10450043094654878,0.5098664416231588,0.5042459184199164,0.0,0.026006470182449948,0.03741223775007456,164350.82166574517,10.277501137463553,10.0,0,1,1,11,1568.5,63.6,45.8,0.7844364937388193,0.14579928618390156
|
| 9 |
+
TABM_GPU (tuned + ensemble),42663.03407314721,6.401903104782104,7337.2216133773,2.4450322937588758,0.5064842509501634,0.5097062474762206,0.0,0.03285461585754071,0.07923986245243698,180683.6213219068,120.23686774247648,10.538461538461538,4.1458,20820.912871148852,3.0152715841929116,4158.291053548661,1.4096720886484275,0.41808698686448353,0.44811012371201403,0.0,0.031023728849073895,0.02730307401826167,166291.5239595113,107.26839105814781,6.0,0,0,1,12,1562.3,53.2,63.1,0.778175313059034,0.15363693425074498
|
| 10 |
+
XGB (tuned + ensemble),6384.208144447945,12.513759183476113,1409.0815132938305,4.086239880001324,0.5528907467847085,0.5842672042727117,0.0,0.05501928538394466,0.06767162618009932,26398.72664659111,353.2622484982949,12.846153846153847,4.22219,2596.930354913076,6.618133616447449,834.9300717202715,2.614265349176195,0.6061614351314211,0.632068655632026,0.0,0.03390767360912417,0.047976586381100285,26370.57574541831,164.97865636299682,13.0,0,0,0,13,1495.9,43.0,50.2,0.7245080500894454,0.0815581414563315
|
| 11 |
+
GBM (tuned),3469.6354441180188,7.385669826034806,806.792675338677,1.273710690539978,0.5553229125473071,0.5751848987218714,0.0,0.0557293790854645,0.07273694432227554,20529.34803212188,170.85098129275468,12.923076923076923,4.23482,3055.419878217909,2.690451833936903,700.1537746143185,0.9682498776019389,0.5552965190223861,0.5297118411020986,0.0,0.027972044011269404,0.03922298758674819,21786.570035668443,130.77892053638826,12.0,0,0,0,13,1490.1,54.7,49.3,0.7227191413237924,0.09231764967059085
|
| 12 |
+
XGB (tuned),6384.208144447945,2.5463058025409016,1409.0815132938305,0.7958717570786976,0.5861202672596529,0.6108958009331424,0.0,0.056497224579359025,0.07175664097406265,26398.72664659111,74.35901041305158,13.73076923076923,4.23559,2596.930354913076,1.7797584003872342,834.9300717202715,0.3883258596259137,0.6620816436761664,0.6284024475165967,0.0,0.03317270939304562,0.04927060675426248,26370.57574541831,37.05707269936294,12.0,0,0,0,13,1474.5,45.4,45.1,0.7039355992844365,0.07642316833493304
|
| 13 |
+
MNCA_GPU (tuned),31759.101002019288,2.180037997319148,6166.048475961011,0.7699041848491119,0.640014197538291,0.6006804484966409,0.0,0.05893528628182787,0.07225555979752735,186080.1526868885,32.66971509741366,14.615384615384615,4.74895,16310.556293937894,0.48738079600863987,3779.5248398651206,0.3958729871859153,0.6568741279318248,0.634131414678689,0.0,0.027829209062692706,0.05013010527584701,198038.2195884601,22.639832589759934,16.0,0,1,2,10,1446.4,51.4,48.7,0.6833631484794276,0.13858206746510898
|
| 14 |
+
TABM_GPU (tuned),42663.03407314721,0.6790118826760185,7337.2216133773,0.2826346699151617,0.6078346969283082,0.6089177873032084,0.0,0.04291459744083105,0.1000977395685804,180683.6213219068,13.142332198971314,15.0,4.26932,20820.912871148852,0.3543446593814426,4158.291053548661,0.16724776809008424,0.5483643325463751,0.5720139858507244,0.0,0.039608740417227284,0.035365730806074164,166291.5239595113,12.524825096296247,13.0,0,0,0,13,1440.3,38.9,53.5,0.6744186046511628,0.08607273216026531
|
| 15 |
+
CAT (default),101.69209800418625,0.27084102752881173,23.09400681118272,0.13269262448628016,0.5995482740998302,0.6304472090224245,0.0,0.06246023871361243,0.07708318676535167,496.3567653671193,9.26273127760114,15.038461538461538,4.21395,62.699359814325966,0.2736650307973226,10.889876924735699,0.09199146861016888,0.5823029883647647,0.640700383892448,0.0,0.030438989353365198,0.03712451320809096,412.72250349454265,8.72239577968297,13.0,0,0,0,13,1438.7,47.7,56.4,0.6735241502683363,0.08685217342752263
|
| 16 |
+
REALMLP (tuned),66543.44573790843,1.7411092819311682,7325.429690273165,0.8126671252939139,0.6503917944927049,0.6335765314526475,0.0,0.04638057342567833,0.08360703671071543,290863.52338623884,43.982520909683025,16.384615384615383,4.34383,35612.93265602324,1.0202796989017062,7141.940159399529,0.394499832888234,0.6897823031948702,0.6773094419226776,0.0,0.042257970846457216,0.05482988743609004,262171.8658686582,39.332347707117826,17.0,0,0,0,13,1404.9,52.4,52.4,0.6422182468694096,0.07190526635498172
|
| 17 |
+
TABPFNV2_GPU (tuned + ensemble),7396.527001981857,78.03043969614893,3418.770967200307,56.25472027093109,0.5864638170450713,0.6417803537075669,0.46153846153846156,0.05066211692688948,0.09308967259297021,101895.60372403836,4530.894138806997,17.192307692307693,4.11819,3945.7989165067675,13.798940539360046,4223.8673583405725,27.542795487744606,0.7230870148989033,0.7944604017471419,0.0,0.03408450486195502,0.03467029575770307,99491.49864758716,2157.1863969834576,19.0,3,1,1,8,1380.7,54.4,46.1,0.6234347048300537,0.31937392494449274
|
| 18 |
+
MNCA_GPU (default),99.58075828980176,2.0463109099966847,18.34482305470451,0.7039566701063034,0.7844574247003018,0.7513144031861464,0.0,0.07422761878566567,0.09797180456330291,547.7971597202185,27.012858819060174,18.76923076923077,4.94033,49.107323222690155,0.41290783882141113,15.50085128260229,0.29868905742963153,0.9390070942659281,0.8904304199346637,0.0,0.03934956674595991,0.09658469357099869,536.5510136544884,15.897990578305649,18.0,0,0,0,13,1340.3,49.6,53.2,0.5867620751341681,0.07094113282642321
|
| 19 |
+
TABM_GPU (default),109.08048485323914,0.5565733836247371,30.11061011517182,0.2424694191265854,0.6999854926260701,0.720056022702389,0.0,0.060357587291533545,0.131331635834194,580.6229196238922,9.300928058329742,19.23076923076923,4.27071,65.0270922978719,0.1736939483218723,13.315938751381204,0.13061717308512005,0.6917071760987948,0.6600858527247827,0.0,0.05131334419415079,0.05222355107697133,354.8698900002396,7.016702417594013,17.0,0,0,0,13,1329.0,52.5,47.2,0.5760286225402504,0.06404901956439267
|
| 20 |
+
NN_TORCH (tuned + ensemble),44960.17932087947,4.03415755573501,5714.412959426929,1.3298489659738517,0.8184873120659005,0.8128616776400956,0.0,0.07610055505274997,0.12013496922800454,220430.49479235077,97.5953017172201,20.23076923076923,4.65351,15497.21247045199,2.8239229255252414,4608.594420268999,1.2325370779691025,0.9269135314055867,0.8896068156264655,0.0,0.05961664423383828,0.08340398612928321,177697.9133637009,96.53385472639289,21.0,0,0,0,13,1306.3,46.0,56.5,0.552772808586762,0.06851055964209914
|
| 21 |
+
TABPFNV2_GPU (tuned),7396.527001981857,3.794137261464045,3418.770967200307,1.977808999126841,0.7134155719592534,0.7418050587973032,0.46153846153846156,0.06180041784216738,0.11851504520949105,101895.60372403836,193.9605838613745,20.576923076923077,4.17059,3945.7989165067675,0.8012150287628174,4223.8673583405725,0.45159866325593434,1.0,1.0,0.0,0.05688219535982175,0.06558436878663254,99491.49864758716,19.472884837488856,28.0,0,1,1,11,1299.8,52.5,54.5,0.5447227191413238,0.11949963987283921
|
| 22 |
+
REALMLP (default),188.56736958373307,2.8279882822281275,22.387772498457988,3.1534644940370367,0.8482043138660138,0.8308100952567204,0.0,0.07049246793231062,0.12882128240536025,856.0818546821283,166.2876065138886,21.307692307692307,4.68787,113.99487728542752,2.6188460985819497,21.860990319181454,0.8382976743420607,0.985771610248003,0.9237062317944604,0.0,0.056187515565281676,0.10042346984448043,594.293460461532,57.629925208930345,22.0,0,0,0,13,1283.5,46.1,47.1,0.5277280858676208,0.054416123092593686
|
| 23 |
+
XT (tuned + ensemble),1206.5194327423715,3.367576224375994,442.36567464742467,1.069316176291616,0.8375900418733949,0.8513977817862853,0.0,0.10048529388089425,0.120775550104976,8220.916376158188,88.72398178178156,21.53846153846154,5.04794,766.4287914435068,3.576531834072537,158.22496863160976,0.8436571643025992,1.0,0.9970859984141835,0.0,0.04988373521321621,0.12269401261109883,5379.1926370125775,93.77443700336585,25.0,0,0,0,13,1272.5,52.4,59.1,0.5223613595706619,0.07374831493706267
|
| 24 |
+
GBM (default),10.696644908750159,2.245801542559241,3.3219193518156818,0.4939224454467883,0.9087857894621156,0.8834968815958729,0.0,0.08060606825955649,0.11976658053442996,80.53396018410795,58.38494586351267,21.923076923076923,4.4838,7.6057972113291425,0.9335102770063612,2.1107352135741744,0.2745991643955073,0.9712364739383097,0.9121375216694869,0.0,0.04937573951369445,0.10636020418552539,91.35379089849596,24.071571166022103,21.0,0,0,0,13,1263.8,53.0,53.2,0.5134168157423972,0.04684267482014358
|
| 25 |
+
XT (tuned),1206.5194327423715,0.45855456478575357,442.36567464742467,0.18106308268317445,0.8639666647767655,0.8723069971625098,0.0,0.10266445862489976,0.12783943156365074,8220.916376158188,14.733646953552363,22.346153846153847,5.07281,766.4287914435068,0.34996385044521755,158.22496863160976,0.15116311924152026,1.0,0.9903008544022194,0.0,0.050434912392149145,0.12806468799723258,5379.1926370125775,14.85253877204164,24.0,0,0,0,13,1254.9,41.8,52.3,0.5035778175313059,0.05933488091441373
|
| 26 |
+
TABPFNV2_GPU (default),13.930354648573786,0.6212240172247602,5.213536664770012,0.4399683707018391,0.7617874026169423,0.7938464861305419,0.46153846153846156,0.07567956002207855,0.13811994843145634,115.71517682132266,30.565681397453538,23.26923076923077,4.25916,9.373317972819011,0.4424108028411865,2.803336175829957,0.3130195506083406,1.0,1.0,0.0,0.06281203604096552,0.07601826824112161,120.93804022420875,33.21203399192692,28.5,0,0,0,13,1231.2,58.6,60.3,0.4821109123434705,0.08671869218804537
|
| 27 |
+
NN_TORCH (tuned),44960.17932087947,0.2904610134597517,5714.412959426929,0.10578639607158029,0.8688481869538994,0.8668830387716895,0.0,0.0842812846349075,0.1388441315022607,220430.49479235077,7.008617614539204,23.307692307692307,4.7148,15497.21247045199,0.18749599986606175,4608.594420268999,0.09690652350320204,1.0,0.9449347108759663,0.0,0.0730528979706524,0.0987961550603162,177697.9133637009,6.6162587674624795,23.0,0,0,0,13,1230.2,46.0,47.0,0.481216457960644,0.0496801955102473
|
| 28 |
+
XGB (default),12.109628748486186,0.9366908014330091,3.1242101566662273,0.3058622971724495,0.8862480764613536,0.8643492470670666,0.0,0.08752819812522358,0.12572826983269936,67.76669386312491,28.981192639888032,24.115384615384617,4.75458,7.79438853263855,0.5301833947499593,2.2441525977447814,0.24247013095584213,1.0,0.9587276133688395,0.0,0.053268364359151055,0.105372572651016,75.78126190262087,16.70456778360137,24.0,0,0,0,13,1214.6,41.8,46.0,0.462432915921288,0.046556052745046386
|
| 29 |
+
RF (tuned + ensemble),2056.9684221919783,3.432567118171953,500.6828145780351,1.0841887922659657,0.9244962574709313,0.9210959637362763,0.0,0.10851512257257524,0.13041932100317657,10863.776799780928,90.24173062908258,24.46153846153846,5.10626,1088.11842862765,1.444333102968004,515.7302180242054,0.7709478321252661,1.0,0.9973408733427616,0.0,0.06747831829737316,0.13942046203027075,11909.387526812274,91.13733276245972,25.0,0,0,0,13,1202.6,45.8,47.1,0.4543828264758497,0.044566348818597695
|
| 30 |
+
RF (tuned),2056.9684221919783,0.3944415463341607,500.6828145780351,0.1540690468576434,0.9446007082199963,0.9408578430892015,0.0,0.11360740147863871,0.13890562008885568,10863.776799780928,12.055960583687282,26.23076923076923,5.18858,1088.11842862765,0.3136819733513726,515.7302180242054,0.12356183047078627,1.0,1.0,0.0,0.07199386349783587,0.14203697859305436,11909.387526812274,11.406268840053338,28.0,0,0,0,13,1152.7,48.4,57.1,0.41323792486583183,0.040812401020999874
|
| 31 |
+
EBM (tuned + ensemble),26125.740811508127,1.1628193525167612,3543.4601988059676,0.44619286429284205,0.8289294744561572,0.8515101676633261,0.0,0.1367713941762849,0.19454116603903474,102743.72801916403,13.991542249573758,27.0,4.37076,6865.337549757957,0.3269915845659044,1890.6770917738593,0.13287644820933492,1.0,1.0,0.0,0.1248421766855935,0.1374516591403558,100996.51953892264,10.735277156769923,33.0,0,1,0,12,1136.0,45.1,60.4,0.3953488372093023,0.07486975066160587
|
| 32 |
+
XT (default),4.038539225015885,0.28929371426248146,0.7743502790637721,0.08386602222003156,0.9314402600373994,0.9226381137036738,0.0,0.12238733986993501,0.17918453000563647,12.035409694284047,7.5346994725559195,28.115384615384617,5.13889,2.058894846174452,0.22108591927422416,0.46766450701756074,0.055025941487738636,1.0,1.0,0.0,0.08970042626125052,0.15512507020900368,11.279879616649893,6.868103658105229,31.0,0,0,0,13,1100.4,55.5,62.8,0.3694096601073345,0.04000377617175779
|
| 33 |
+
EBM (tuned),26125.740811508127,0.09807351307991222,3543.4601988059676,0.04003457596727012,0.8498896422587312,0.8690004985226352,0.0,0.14218261386610534,0.20871356711851735,102743.72801916403,1.2806753432569877,28.53846153846154,4.42885,6865.337549757957,0.03976681497361925,1890.6770917738593,0.012767925630469206,1.0,1.0,0.0,0.1292889595673019,0.16421526338237233,100996.51953892264,1.0,34.0,0,0,1,12,1091.5,49.5,56.7,0.3595706618962433,0.05876238598299918
|
| 34 |
+
FASTAI (tuned + ensemble),4642.340904501768,8.77000401672135,1248.4159649024482,5.455805855994076,0.9763387226193126,0.966122715762154,0.0,0.12202126425715551,0.19741406156575694,32660.757986061028,336.5557366220283,30.0,5.27232,3620.151651991738,7.070411682128906,540.0550122797715,2.672383567926809,1.0,1.0,0.0,0.1022000155980195,0.1756471698456369,33252.590479353305,324.2617231497696,31.0,0,0,0,13,1040.0,61.4,49.3,0.32558139534883723,0.0357112186773915
|
| 35 |
+
NN_TORCH (default),151.43337847534409,0.22200924249795764,23.930992166336175,0.08705592871966639,0.9827422496757343,0.9678685866022871,0.0,0.1193977421999948,0.19547728530185762,831.2534637345914,6.296769612194,30.23076923076923,4.81722,65.27966655625238,0.14955372280544704,20.47535029226034,0.07966387341594139,1.0,1.0,0.0,0.14050249681884142,0.13614151881375058,546.0088939544379,6.398331846186531,32.0,0,0,0,13,1038.3,57.6,62.3,0.32021466905187834,0.03550445228984282
|
| 36 |
+
EBM (default),61.24195487458481,0.11774356426336827,10.057660454061297,0.07098698960857609,0.8908598695337496,0.8984005515464777,0.0,0.1505943663504528,0.22072991542366915,260.56038663650384,2.782386904835081,30.615384615384617,4.44221,19.539602756500244,0.04366175333658854,6.327684720357259,0.039228283502797535,1.0,1.0,0.0,0.13598656576261503,0.17428198310764084,214.4635432482436,1.7877726532004268,35.0,0,0,0,13,1034.2,43.3,66.2,0.3112701252236136,0.036159887762040425
|
| 37 |
+
RF (default),9.267833071284823,0.31600932585887426,1.1524694810969494,0.08818027662752802,1.0,0.9870278022164788,0.0,0.12896216114203193,0.1901035125951938,27.793203837891944,7.952067403429296,31.346153846153847,5.26146,5.924832847383287,0.26005201869540745,0.5271703851240811,0.062155184511682476,1.0,1.0,0.0,0.08142906388988314,0.17217694118713336,20.351375021697393,6.812325017295935,31.5,0,0,0,13,1000.0,0.0,0.0,0.29427549194991054,0.03259951679594785
|
| 38 |
+
FASTAI (tuned),4642.340904501768,0.9693611326380673,1248.4159649024482,0.5658202849858516,0.9859539042371194,0.9812210227156647,0.0,0.1268703134805104,0.21643571616372462,32660.757986061028,38.043706128121705,31.692307692307693,5.18701,3620.151651991738,1.0039918687608507,540.0550122797715,0.32495714500374384,1.0,1.0,0.0,0.11787324661401322,0.18136473255372101,33252.590479353305,36.96325797937462,33.0,0,0,0,13,991.5,48.2,64.3,0.28622540250447226,0.03287029132617368
|
| 39 |
+
FASTAI (default),18.837261917856004,0.970951892168094,4.540025666114834,0.4814105255967321,1.0,0.9959412543360979,0.0,0.1713566965946914,0.27575692774796806,123.96432879696866,34.056295479841545,34.92307692307692,6.36878,15.734567880630493,1.036571078830295,2.6035035917474465,0.39168673048638547,1.0,1.0,0.0,0.11912950408368406,0.27762932440609267,138.38888737159849,36.35774230804583,36.0,0,0,0,13,858.2,52.8,69.4,0.2110912343470483,0.029119709509087932
|
| 40 |
+
KNN (tuned + ensemble),20.494465350493407,2.240403470422468,2.7608828307729607,0.3822937952790146,1.0,0.9953083923448788,0.07692307692307693,0.3613185363694843,0.6538216817153736,74.30220244876604,25.830539833366643,39.76923076923077,8.1617,12.562016169230143,0.2777775393591987,2.427842858706766,0.14225338857865483,1.0,1.0,0.0,0.41352430110915517,0.7463425706140449,61.12257192545374,15.449077396683121,41.0,0,0,0,13,532.3,77.3,95.3,0.09838998211091235,0.025256773577856426
|
| 41 |
+
LR (tuned + ensemble),260.53517347665934,0.6450919024964683,90.82426667518703,0.24319307436598073,1.0,1.0,0.0,0.35422421997100256,0.6560326250854102,2016.752248654558,10.333316070921164,40.30769230769231,8.15038,155.9093332555559,0.2263851695590549,45.737119844257606,0.10677772758861735,1.0,1.0,0.0,0.3837007856022804,0.7329121008806585,1735.7243863195374,7.455644136363483,40.0,0,0,0,13,488.7,52.5,94.2,0.08586762075134168,0.024850461752159034
|
| 42 |
+
KNN (tuned),20.494465350493407,0.2574708763350788,2.7608828307729607,0.05410989827741383,1.0,0.9988376690148505,0.07692307692307693,0.36756573770309675,0.6864360755861012,74.30220244876604,3.3744578525576268,40.76923076923077,8.25638,12.562016169230143,0.09626038869222005,2.427842858706766,0.028318042556444805,1.0,1.0,0.0,0.42023780750084094,0.7514125894823619,61.12257192545374,2.1032822899149863,42.0,0,0,0,13,441.9,67.3,134.2,0.07513416815742398,0.024635899785160127
|
| 43 |
+
LR (tuned),260.53517347665934,0.13893676680377404,90.82426667518703,0.0633906225067962,1.0,1.0,0.0,0.3558634149624985,0.6630785837896581,2016.752248654558,3.076869056672641,40.92307692307692,8.15927,155.9093332555559,0.05223793453640408,45.737119844257606,0.05009355954825878,1.0,1.0,0.0,0.38692302721983185,0.7430806596590566,1735.7243863195374,2.8910146707817423,41.0,0,0,0,13,420.6,81.6,94.5,0.07155635062611806,0.02449625775032643
|
| 44 |
+
LR (default),4.903454369968838,0.19863318235446245,2.033074367074023,0.07563726553282422,1.0,1.0,0.0,0.3808091655367071,0.7702257899846487,45.803264898726965,4.508173919929611,42.15384615384615,8.22758,5.286295996771918,0.09712121221754286,1.191311693685635,0.0859815087197251,1.0,1.0,0.0,0.38694683448707623,0.8770019722050186,34.79737790723628,4.100500531123858,42.0,0,0,0,13,290.1,86.6,112.6,0.04293381037567084,0.023757512031433232
|
| 45 |
+
KNN (default),2.0401845610039864,0.07292802802517882,0.5185761600539422,0.029646415007926124,1.0,0.999847626563869,0.07692307692307693,0.4076491058824559,0.8492569035691879,1.1215157323318734,1.57971988992164,42.61538461538461,8.55152,0.15191650390625,0.04789047771030002,0.03752343922831045,0.021942545900661376,1.0,1.0,0.0,0.4573857803481276,1.0,1.0,1.5317182357480712,44.0,0,0,0,13,238.6,87.0,145.9,0.03220035778175313,0.023578620171993768
|
data/{imputation_no/splits_all/tasks_multiclass/datasets_medium/tuning-impact-elo.png.zip → full-imputed-reg/time_plot.png.zip}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:da71d8796986e598f595ef583a35349dd78b721b6d2ad86658f6df61f9e4e254
|
| 3 |
+
size 84316
|
data/full-imputed/leaderboard.tex
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\begin{tabular}{llcccccrr}
|
| 2 |
+
\toprule
|
| 3 |
+
\textbf{Model} & \textbf{Elo ($\uparrow$)} & \textbf{Norm.} & \textbf{Avg.} & \textbf{Harm.} & \textbf{\#wins ($\uparrow$)} & \textbf{Improva-} & \textbf{Train time} & \textbf{Predict time} \\
|
| 4 |
+
& & \textbf{score ($\uparrow$)} & \textbf{rank ($\downarrow$)} & \textbf{mean} & & \textbf{bility ($\downarrow$)} & \textbf{per 1K [s]} & \textbf{per 1K [s]} \\
|
| 5 |
+
& & & & \textbf{rank ($\downarrow$)} & & & & \\
|
| 6 |
+
\midrule
|
| 7 |
+
AutoGluon 1.3 (4h) & \textcolor{gold}{\textbf{1590${}_{-28,+24}$}} & \textcolor{gold}{\textbf{0.618}} & \textcolor{gold}{\textbf{8.4}} & \textcolor{gold}{\textbf{3.1}} & \textcolor{silver}{\textbf{8}} & \textcolor{gold}{\textbf{5.8\%}} & 1408.78 & 3.34 \\
|
| 8 |
+
RealMLP (T+E) & \textcolor{silver}{\textbf{1565${}_{-23,+28}$}} & \textcolor{silver}{\textbf{0.537}} & \textcolor{silver}{\textbf{9.1}} & 5.7 & 0 & \textcolor{silver}{\textbf{6.6\%}} & 6564.71 & 10.26 \\
|
| 9 |
+
TabM (T+E) & \textcolor{bronze}{\textbf{1544${}_{-22,+27}$}} & \textcolor{bronze}{\textbf{0.502}} & \textcolor{bronze}{\textbf{9.9}} & 4.9 & 3 & \textcolor{bronze}{\textbf{7.0\%}} & 3285.87 & 1.47 \\
|
| 10 |
+
LightGBM (T+E) & 1526${}_{-24,+24}$ & 0.452 & 10.6 & 6.6 & 1 & 8.6\% & 416.98 & 2.64 \\
|
| 11 |
+
CatBoost (T+E) & 1484${}_{-26,+19}$ & 0.433 & 12.4 & 8.2 & 0 & 7.9\% & 1658.41 & 0.65 \\
|
| 12 |
+
CatBoost (T) & 1470${}_{-23,+18}$ & 0.416 & 13.0 & 7.0 & 1 & 8.1\% & 1658.41 & 0.08 \\
|
| 13 |
+
TabM (T) & 1453${}_{-27,+20}$ & 0.413 & 13.7 & 7.2 & 1 & 8.0\% & 3285.87 & 0.17 \\
|
| 14 |
+
LightGBM (T) & 1448${}_{-27,+23}$ & 0.363 & 14.0 & 11.7 & 0 & 9.3\% & 416.98 & 0.33 \\
|
| 15 |
+
XGBoost (T+E) & 1439${}_{-20,+21}$ & 0.361 & 14.3 & 9.9 & 0 & 9.4\% & 693.49 & 1.69 \\
|
| 16 |
+
ModernNCA (T+E) & 1434${}_{-27,+24}$ & 0.444 & 14.5 & 5.3 & 3 & 8.7\% & 4621.67 & 8.15 \\
|
| 17 |
+
CatBoost (D) & 1428${}_{-20,+27}$ & 0.372 & 14.8 & 7.9 & 1 & 9.3\% & 6.83 & 0.08 \\
|
| 18 |
+
TabPFNv2 (T+E) & 1415${}_{-26,+27}$ & 0.476 & 15.4 & \textcolor{gold}{\textbf{3.1}} & \textcolor{gold}{\textbf{11}} & 8.5\% & 3030.15 & 21.44 \\
|
| 19 |
+
XGBoost (T) & 1405${}_{-23,+22}$ & 0.313 & 15.9 & 13.2 & 0 & 9.7\% & 693.49 & 0.31 \\
|
| 20 |
+
ModernNCA (T) & 1402${}_{-21,+18}$ & 0.307 & 16.0 & 8.9 & 1 & 9.3\% & 4621.67 & 0.47 \\
|
| 21 |
+
TabICL (D) & 1390${}_{-24,+24}$ & 0.381 & 16.6 & \textcolor{bronze}{\textbf{4.5}} & 6 & 9.2\% & 6.63 & 1.48 \\
|
| 22 |
+
TabPFNv2 (T) & 1348${}_{-24,+24}$ & 0.360 & 18.6 & 5.7 & 1 & 10.6\% & 3030.15 & 0.46 \\
|
| 23 |
+
RealMLP (T) & 1348${}_{-21,+20}$ & 0.229 & 18.6 & 15.9 & 0 & 10.1\% & 6564.71 & 0.49 \\
|
| 24 |
+
TabM (D) & 1347${}_{-19,+20}$ & 0.285 & 18.6 & 12.6 & 0 & 10.9\% & 10.49 & 0.13 \\
|
| 25 |
+
TorchMLP (T+E) & 1332${}_{-21,+25}$ & 0.220 & 19.4 & 14.8 & 0 & 10.6\% & 2874.67 & 1.95 \\
|
| 26 |
+
TabPFNv2 (D) & 1321${}_{-23,+21}$ & 0.324 & 20.0 & 5.6 & 4 & 11.6\% & 3.36 & 0.31 \\
|
| 27 |
+
TabDPT (D) & 1300${}_{-28,+25}$ & 0.300 & 21.0 & 4.9 & \textcolor{bronze}{\textbf{7}} & 12.3\% & 22.53 & 8.55 \\
|
| 28 |
+
ModernNCA (D) & 1299${}_{-23,+25}$ & 0.159 & 21.0 & 12.8 & 1 & 12.8\% & 14.87 & 0.31 \\
|
| 29 |
+
EBM (T+E) & 1292${}_{-25,+24}$ & 0.184 & 21.4 & 13.5 & 0 & 14.6\% & 1331.68 & 0.20 \\
|
| 30 |
+
FastaiMLP (T+E) & 1250${}_{-19,+24}$ & 0.158 & 23.5 & 14.5 & 0 & 14.0\% & 593.24 & 4.47 \\
|
| 31 |
+
RealMLP (D) & 1244${}_{-25,+21}$ & 0.104 & 23.7 & 20.3 & 0 & 12.7\% & 21.86 & 0.84 \\
|
| 32 |
+
ExtraTrees (T+E) & 1243${}_{-21,+22}$ & 0.124 & 23.8 & 15.8 & 0 & 14.3\% & 183.02 & 0.76 \\
|
| 33 |
+
EBM (T) & 1236${}_{-21,+18}$ & 0.135 & 24.1 & 17.7 & 0 & 15.3\% & 1331.68 & 0.02 \\
|
| 34 |
+
XGBoost (D) & 1232${}_{-24,+19}$ & 0.115 & 24.4 & 19.8 & 0 & 12.7\% & 1.94 & 0.12 \\
|
| 35 |
+
TorchMLP (T) & 1223${}_{-21,+25}$ & 0.113 & 24.8 & 21.3 & 0 & 12.7\% & 2874.67 & 0.13 \\
|
| 36 |
+
EBM (D) & 1202${}_{-29,+22}$ & 0.134 & 25.7 & 13.5 & 1 & 16.2\% & 4.67 & 0.04 \\
|
| 37 |
+
LightGBM (D) & 1202${}_{-23,+23}$ & 0.088 & 25.7 & 23.0 & 0 & 13.5\% & 1.96 & 0.14 \\
|
| 38 |
+
RandomForest (T+E) & 1201${}_{-24,+21}$ & 0.098 & 25.8 & 15.9 & 0 & 15.1\% & 373.18 & 0.77 \\
|
| 39 |
+
ExtraTrees (T) & 1200${}_{-28,+18}$ & 0.094 & 25.9 & 17.1 & 0 & 15.4\% & 183.02 & 0.09 \\
|
| 40 |
+
FastaiMLP (T) & 1161${}_{-19,+24}$ & 0.073 & 27.7 & 22.6 & 0 & 15.6\% & 593.24 & 0.31 \\
|
| 41 |
+
RandomForest (T) & 1152${}_{-25,+19}$ & 0.072 & 28.1 & 18.0 & 0 & 16.2\% & 373.18 & 0.09 \\
|
| 42 |
+
TorchMLP (D) & 1066${}_{-21,+24}$ & 0.022 & 31.6 & 29.0 & 0 & 17.5\% & 9.99 & 0.13 \\
|
| 43 |
+
FastaiMLP (D) & 1011${}_{-23,+23}$ & 0.023 & 33.7 & 31.0 & 0 & 20.8\% & 2.86 & 0.37 \\
|
| 44 |
+
RandomForest (D) & 1000${}_{-0,+0}$ & 0.009 & 34.0 & 32.4 & 0 & 21.3\% & 0.43 & 0.05 \\
|
| 45 |
+
ExtraTrees (D) & 972${}_{-28,+21}$ & 0.025 & 35.0 & 31.4 & 0 & 23.0\% & 0.25 & 0.05 \\
|
| 46 |
+
Linear (T+E) & 917${}_{-21,+31}$ & 0.031 & 36.6 & 28.3 & 0 & 30.8\% & 47.49 & 0.17 \\
|
| 47 |
+
Linear (T) & 882${}_{-30,+32}$ & 0.020 & 37.5 & 32.8 & 0 & 31.5\% & 47.49 & 0.07 \\
|
| 48 |
+
Linear (D) & 862${}_{-30,+23}$ & 0.014 & 38.1 & 30.5 & 0 & 32.9\% & 1.52 & 0.09 \\
|
| 49 |
+
KNN (T+E) & 685${}_{-32,+27}$ & 0.000 & 41.4 & 41.1 & 0 & 45.3\% & 2.74 & 0.18 \\
|
| 50 |
+
KNN (T) & 608${}_{-48,+32}$ & 0.000 & 42.4 & 42.3 & 0 & 46.9\% & 2.74 & 0.04 \\
|
| 51 |
+
KNN (D) & 459${}_{-45,+42}$ & 0.000 & 43.8 & 43.6 & 0 & 54.1\% & 0.05 & 0.02 \\
|
| 52 |
+
\bottomrule
|
| 53 |
+
\end{tabular}
|
data/full-imputed/tabarena_leaderboard.csv
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
method,time_train_s,time_infer_s,time_train_s_per_1K,time_infer_s_per_1K,normalized-error,normalized-error-task,imputed,champ_delta,loss_rescaled,time_train_s_rescaled,time_infer_s_rescaled,rank,median_metric_error,median_time_train_s,median_time_infer_s,median_time_train_s_per_1K,median_time_infer_s_per_1K,median_normalized-error,median_normalized-error-task,median_imputed,median_champ_delta,median_loss_rescaled,median_time_train_s_rescaled,median_time_infer_s_rescaled,median_rank,rank=1_count,rank=2_count,rank=3_count,rank>3_count,elo,elo+,elo-,winrate,mrr
|
| 2 |
+
AutoGluon 1.3 (4h),8462.98349033711,33.138286938542635,2912.1242917208747,4.391016265244401,0.381932874173557,0.3938004850803849,0.0,0.05822662138626224,0.038656168015376684,43301.56973340033,539.3969074295995,8.411764705882353,0.2055,7367.614226023356,3.9490213659074573,1408.7828331379249,3.337414261487274,0.32575782629688715,0.34354944358388295,0.0,0.022224886416280176,0.016643068102528722,33121.993698706065,185.27028732280235,5.0,8,6,2,35,1589.7,23.3,27.4,0.8315508021390374,0.32434985005444883
|
| 3 |
+
REALMLP (tuned + ensemble),82918.85938235045,50.75538799222518,8669.653795437369,17.385570695148495,0.4634803896199485,0.48980490794993603,0.0,0.0662652507057572,0.04428998923773407,179788.549283492,846.8926595159473,9.147058823529411,0.20859,30826.14291326205,23.329282654656303,6564.713231881598,10.263652729721208,0.4233707478718706,0.4394625063276673,0.0,0.03156540515236528,0.021508501844188344,136595.8709190495,808.3809230744637,7.0,0,5,4,42,1564.6,27.5,23.0,0.8148395721925134,0.17688848740169394
|
| 4 |
+
TABM_GPU (tuned + ensemble),36462.58337058756,8.791583087761158,5017.258422060137,3.1802055454964386,0.49791774396870153,0.5234045251267629,0.0,0.06977046437303486,0.06341802359213981,80230.4785975727,130.9039885664859,9.872549019607844,0.20535,8420.993191123009,2.7141049438052707,3285.8688373170553,1.4723486146222118,0.4651893659350262,0.5081840173827434,0.0,0.03250086419089859,0.027567784172117953,47614.825535817596,111.53030159160512,8.0,3,2,3,43,1543.9,26.8,21.9,0.7983511586452763,0.20599586481497986
|
| 5 |
+
GBM (tuned + ensemble),3088.2834950947295,22.058380506500956,771.2925090199282,4.080656504886727,0.5482943614672702,0.5697587102764388,0.0,0.08557614755706973,0.059109015015710746,11617.562781863631,427.3461655076801,10.627450980392156,0.2112,1667.667911251386,3.7860276963975696,416.9832926671224,2.6387318875879693,0.5661942244497019,0.5831585230842022,0.0,0.04023364809387353,0.02358455413295459,9501.568897853978,118.5632719261967,10.0,1,1,2,47,1526.2,23.7,23.4,0.7811942959001783,0.1520008705225847
|
| 6 |
+
CAT (tuned + ensemble),20021.3498029566,3.148214934334516,4130.291158755297,0.9792413821552454,0.5665168479793786,0.5762538702782276,0.0,0.07932910031410541,0.05277138538144033,58497.64726501732,62.60491239485109,12.372549019607844,0.21079,7127.110804247856,1.3727677133348253,1658.412974283854,0.65278892715772,0.5695869531891277,0.5907800269434179,0.0,0.04606752490069621,0.02774139238223889,22349.13952253535,41.43902270876451,11.0,0,1,4,46,1484.5,18.5,25.4,0.7415329768270945,0.12146805837673025
|
| 7 |
+
CAT (tuned),20021.3498029566,0.45918073721700764,4130.291158755297,0.13269281663977184,0.5837954660770609,0.5897551898062613,0.0,0.08123455741105615,0.05345084183416724,58497.64726501732,8.058537488270943,12.96078431372549,0.21123,7127.110804247856,0.16668947537740073,1658.412974283854,0.08101450844552308,0.5845247966032667,0.6225038615712537,0.0,0.05045951030687079,0.030933776248240515,22349.13952253535,5.582269457200397,12.5,1,3,2,45,1470.5,17.3,22.3,0.7281639928698752,0.1437603439953039
|
| 8 |
+
TABM_GPU (tuned),36462.58337058756,0.9691277276976176,5017.258422060137,0.3543499279245272,0.5874385027995309,0.5895097011198668,0.0,0.08005397326560945,0.07918093169544495,80230.4785975727,13.69951936973594,13.696078431372548,0.21042,8420.993191123009,0.2791590425703261,3285.8688373170553,0.1728818165133111,0.559085035183601,0.6013449948327668,0.0,0.041022605221466724,0.035365730806074164,47614.825535817596,11.564361688735561,14.0,1,3,2,45,1452.9,20.0,26.7,0.7114527629233511,0.1390380052974814
|
| 9 |
+
GBM (tuned),3088.2834950947295,3.280151636356362,771.2925090199282,0.7008989122586311,0.6366067117608026,0.6336828329141213,0.0,0.09282220252278703,0.0695723239257395,11617.562781863631,67.66975356224859,13.950980392156863,0.21181,1667.667911251386,0.5984517203436958,416.9832926671224,0.33384935590955944,0.6296869528283883,0.6590584882044693,0.0,0.05048061255226499,0.03622173132751954,9501.568897853978,17.561755180687065,12.0,0,0,0,51,1447.5,22.7,26.1,0.7056595365418895,0.08527400346153444
|
| 10 |
+
XGB (tuned + ensemble),6066.175009788823,8.000445660682546,1229.0991373608288,3.120951906510457,0.6385613101625683,0.6434959772946812,0.0,0.09352817276204972,0.06895162562612145,14800.692905333448,192.56405868832437,14.27450980392157,0.21458,2256.9276883072325,3.0598979949951173,693.4907982506384,1.6904262577061315,0.671301017368657,0.6581535714975986,0.0,0.05552089944600691,0.03200108485206017,11769.825378159274,82.2877578838671,13.0,0,1,1,49,1438.7,20.3,19.4,0.698306595365419,0.1010413685016667
|
| 11 |
+
MNCA_GPU (tuned + ensemble),50831.51192726024,408.7024568246081,6035.4844365627405,41.810485127597225,0.5559334685448146,0.5505192494459418,0.0,0.08712344899479532,0.06897276604102788,107380.48324313454,2632.7754273052897,14.549019607843137,0.21294,14486.050127214856,13.240725604693095,4621.665633563503,8.148513113458952,0.5384753932635177,0.5315179526728905,0.0,0.035276378418488075,0.031199094919591976,89084.88026764008,537.8274695033359,11.0,3,3,5,40,1433.8,23.6,26.7,0.6920677361853832,0.1903874062097513
|
| 12 |
+
CAT (default),190.03885268302784,0.2709793741147243,87.82759080296049,0.13562630112555335,0.6279909747535407,0.646125708691512,0.0,0.0925312918791838,0.06081652619205146,428.26912869207973,7.186903437353133,14.794117647058824,0.21142,28.268621895048355,0.1854714552561442,6.827020885706225,0.08026752106160412,0.6534673037587888,0.6439696146756235,0.0,0.04582469430261593,0.029179417473348953,113.47556087857672,6.139565341592893,16.0,1,3,1,46,1428.5,26.2,19.6,0.6864973262032086,0.12705337781476866
|
| 13 |
+
TABPFNV2_GPU (tuned + ensemble),9338.42554130284,95.46951768190513,2848.5135701006398,47.682041415407696,0.5239705071709494,0.5769312699511674,0.35294117647058826,0.08515142798212334,0.08426448408310144,62904.17752069347,3721.414760799794,15.372549019607844,0.22709,2098.550690642993,13.798940539360046,3030.145221648074,21.443889733771147,0.5915448073500406,0.6069332103645363,0.0,0.03866296841083827,0.03250100481138207,29840.56658077224,861.272449686595,11.0,11,4,3,33,1414.7,26.3,25.1,0.6733511586452763,0.3218844858197347
|
| 14 |
+
XGB (tuned),6066.175009788823,1.6190793797341305,1229.0991373608288,0.7004875821871327,0.6869435084156271,0.6795624628612148,0.0,0.09696298272522294,0.07331091441041244,14800.692905333448,40.17091923504828,15.892156862745098,0.21499,2256.9276883072325,0.41774741808573407,693.4907982506384,0.3083513292273418,0.7193303230280006,0.7149553857561783,0.0,0.06100086263844462,0.03462012868860662,11769.825378159274,12.136706817415504,15.0,0,0,0,51,1404.9,21.4,22.2,0.6615418894830659,0.07556633120131231
|
| 15 |
+
MNCA_GPU (tuned),50831.51192726024,15.584971993005873,6035.4844365627405,1.7226505575752833,0.692913423977365,0.6430754651403978,0.0,0.09326988355673647,0.07237812189150603,107380.48324313454,104.77227719302421,16.03921568627451,0.21328,14486.050127214856,0.585451708899604,4621.665633563503,0.4747242314576746,0.7553848478357736,0.6366009339265687,0.0,0.06113391902932641,0.0493534926522164,89084.88026764008,26.6476237825924,16.0,1,1,2,47,1402.5,17.6,20.6,0.6581996434937611,0.1120344583371438
|
| 16 |
+
TABICL_GPU (default),82.80334805787777,14.446106202929627,7.4655941033985815,1.6847655412525513,0.6187626573361198,0.6590285685589051,0.29411764705882354,0.09205009921867735,0.09066558702327601,132.83095048510535,173.47404322746496,16.607843137254903,0.21659,20.0619904200236,1.316457470258077,6.625686376434735,1.479660415649414,0.6419318555001297,0.737430199336512,0.0,0.05183434289459943,0.0307061823959099,110.37274820175764,91.25701004379168,14.0,6,4,1,40,1389.8,23.7,23.2,0.6452762923351159,0.22043663312484155
|
| 17 |
+
REALMLP (tuned),82918.85938235045,2.265432894048088,8669.653795437369,0.9268647174900084,0.770575243056979,0.7198426366318216,0.0,0.10098849134105925,0.08466680664165582,179788.549283492,40.77005886388886,18.61764705882353,0.21508,30826.14291326205,1.0006839964124892,6564.713231881598,0.487512478277248,0.866614722551564,0.7557285234401128,0.0,0.06823335132903552,0.05320262249246514,136595.8709190495,36.173930978956705,18.0,0,0,0,51,1347.8,19.9,20.3,0.5995989304812834,0.06290892887580088
|
| 18 |
+
TABPFNV2_GPU (tuned),9338.42554130284,3.508518432739773,2848.5135701006398,1.6633483351042642,0.6402449044416614,0.6630497140643348,0.35294117647058826,0.10613854546664524,0.10151316508024909,62904.17752069347,134.3876978041907,18.61764705882353,0.22751,2098.550690642993,0.5097733656565349,3030.145221648074,0.46198440414964803,0.7603547647708915,0.7104310097848833,0.0,0.07667977096051137,0.04654872982993791,29840.56658077224,22.48627830890164,15.5,1,9,2,39,1348.2,23.9,23.8,0.5995989304812834,0.1748060544077359
|
| 19 |
+
TABM_GPU (default),139.62633961878052,1.0737770921524312,22.4928837749369,0.40818286049864,0.7149663388553331,0.7265875725216725,0.0,0.10904673882873887,0.10206768551470595,289.28104127940037,12.833742622244758,18.61764705882353,0.21188,40.332407061258955,0.18133597903781468,10.492230631952996,0.13221126395693922,0.8197432069948619,0.7908796299405498,0.0,0.05780353607735633,0.03944837820705307,186.77830789084513,10.724711035853641,17.0,0,0,1,50,1346.8,19.5,18.3,0.5995989304812834,0.07920722957248505
|
| 20 |
+
NN_TORCH (tuned + ensemble),29590.123960411,13.183612702147375,3729.842332819238,3.5618312259496654,0.7804812465107793,0.7650139226387963,0.0,0.1061112883342963,0.09038128962619164,97942.50427646744,194.194370742189,19.392156862745097,0.21479,10848.660208092795,3.946354971991645,2874.6743506773596,1.9516254299583915,0.910350140134773,0.8406524459297455,0.0,0.06624137678637454,0.057854463852261596,61441.834728019065,144.9992483814283,20.0,0,0,0,51,1332.3,24.5,20.5,0.5819964349376114,0.06762812359455618
|
| 21 |
+
TABPFNV2_GPU (default),12.045264010803372,0.825882379421741,4.478694030451919,0.4530850283232118,0.6758133693268394,0.7167075967625335,0.35294117647058826,0.11639838128335792,0.11295068368765535,69.53545044274777,29.75030650326298,20.04901960784314,0.22887,9.117408725950453,0.42119165261586505,3.3572004182270923,0.3130195506083406,0.956340758739766,0.8514943913344442,0.0,0.07592598037026033,0.052795487060598015,52.331266670190345,18.512009051191257,21.0,4,1,4,42,1320.6,20.6,22.2,0.5670677361853832,0.1788864671189465
|
| 22 |
+
TABDPT_GPU (default),166.18249968905855,63.11337411850366,27.980557312145997,23.24231264879125,0.6999265055194402,0.699617586999111,0.0,0.12276620509418873,0.09536847721359762,577.6877537613715,1486.1376930964866,20.96078431372549,0.22562,99.10453534126282,28.39870807859633,22.52690614988171,8.550738306685618,0.9903591350487536,0.8691048403402053,0.0,0.05029899916003,0.0433680924463882,528.528670151851,1255.434427440434,22.0,7,0,3,41,1300.5,24.7,27.1,0.5463458110516934,0.2050929674182998
|
| 23 |
+
MNCA_GPU (default),252.05720278889527,8.333707038145958,17.796029105655933,1.1526772129094414,0.840779547661087,0.7959093866791253,0.0,0.12833371899167995,0.09667612599337075,329.3551130182264,62.49957238602975,21.03921568627451,0.21885,36.0034454398685,0.5316168732113309,14.869495839530392,0.30768591310277943,1.0,0.8857694762766525,0.0,0.07424254289688792,0.06351531911154724,236.99495784925895,20.43419277465042,23.0,1,0,0,50,1299.1,24.9,22.8,0.5445632798573975,0.07840885625256006
|
| 24 |
+
EBM (tuned + ensemble),34026.536489860475,1.2927426090946903,5478.959788432886,0.48902813323980865,0.8160130792555895,0.8175846459536137,0.0,0.1459291690476727,0.13123283756498888,45019.152540237825,18.109773959357398,21.431372549019606,0.21615,2925.6548613442314,0.400875727335612,1331.6775166450918,0.19908260374566636,0.958308811651104,0.8761716756909942,0.0,0.08565806627599937,0.05590445639895017,17751.99098903195,11.13922354039944,21.0,0,1,1,49,1292.5,23.9,24.9,0.535650623885918,0.07406174849391879
|
| 25 |
+
FASTAI (tuned + ensemble),6629.648996400055,16.16286987151975,1343.5604508466745,7.704229376998794,0.8424987698640145,0.8369589067092069,0.0,0.13971168994404898,0.11512340310437526,22455.399300542234,425.24771894393024,23.46078431372549,0.21679,3182.895098288854,10.795994228786892,593.237788402893,4.466873745216533,1.0,0.9552259937574975,0.0,0.0932055660765102,0.07243348401502496,19851.125229101002,409.94392325616803,25.0,0,1,0,50,1249.7,24.0,19.0,0.48952762923351156,0.06883106383498735
|
| 26 |
+
REALMLP (default),273.729912211121,2.9575047363123343,25.2860618687397,2.9321723489284044,0.8959152468625471,0.8483293899440195,0.0,0.1265509832451891,0.10892646502099379,570.5207778272487,128.70805989538366,23.745098039215687,0.21516,107.08700556225247,2.6188460985819497,21.860990319181454,0.8382976743420607,1.0,0.8905283644114734,0.0,0.09824845633171009,0.07444845646092337,497.27886689729087,54.5386788723178,24.0,0,0,0,51,1244.4,20.7,24.5,0.483065953654189,0.049206352618688116
|
| 27 |
+
XT (tuned + ensemble),1289.1519403179227,3.0578905248434194,464.9314949446578,1.2901947647379284,0.8763124357874087,0.8533692619097849,0.0,0.14328509610809964,0.11780722719308848,5501.829777288316,78.94715148525705,23.823529411764707,0.21814,763.5855970117781,1.8364481396145291,183.01944048073585,0.761281055543471,1.0,0.9521925032545069,0.0,0.08603990026311015,0.07137952858629182,3537.1622158448404,68.20231667792302,27.0,0,0,1,50,1243.2,21.4,20.4,0.48128342245989303,0.06310725111805937
|
| 28 |
+
EBM (tuned),34026.536489860475,0.16189759790507796,5478.959788432886,0.07139558038617727,0.8649702054759879,0.8501629933938847,0.0,0.15261119112333235,0.14046524715764735,45019.152540237825,2.1906554232861546,24.11764705882353,0.21772,2925.6548613442314,0.0440410852432251,1331.6775166450918,0.022730636596679687,1.0,0.9362089365721089,0.0,0.09714090003058773,0.06554952824985644,17751.99098903195,1.2223545537568268,24.0,0,0,1,50,1236.3,17.4,20.5,0.47459893048128343,0.056429653896796474
|
| 29 |
+
XGB (default),12.860019501050314,0.6666093941607507,3.1825529067488505,0.3000924886961127,0.8848348696110224,0.853007192078055,0.0,0.12712004260212578,0.11901448944644484,40.716829559380564,17.42803351650834,24.441176470588236,0.21667,5.82192047437032,0.3283502260843913,1.9409389396340444,0.12262328807300621,1.0,0.9508124068469325,0.0,0.09769803191981652,0.0669685923578734,34.48133232859512,10.22021081972956,24.0,0,0,0,51,1232.4,18.8,23.5,0.4672459893048128,0.05049212098034601
|
| 30 |
+
NN_TORCH (tuned),29590.123960411,0.7234875786018787,3729.842332819238,0.20874333848987678,0.8872281679035978,0.8461065690351314,0.0,0.1266933814263632,0.11368972667898117,97942.50427646744,10.830632864633353,24.754901960784313,0.21784,10848.660208092795,0.2631075382232666,2874.6743506773596,0.131112832826372,1.0,0.9115838155711167,0.0,0.1030878662833985,0.06896829387646289,61441.834728019065,8.236695976463633,25.0,0,0,0,51,1223.2,25.0,20.4,0.46011586452762926,0.04694203272118342
|
| 31 |
+
EBM (default),104.78526760316363,0.17165232525412033,11.079598604500092,0.09398863718788793,0.8658153943709024,0.8643480238945523,0.0,0.1621049398152807,0.1485076759316338,148.0901517975655,3.2508346897376326,25.745098039215687,0.21677,11.465454594294231,0.05977429548899333,4.6738599788414605,0.03961948198354664,1.0,0.9628721496233147,0.0,0.10271933543623024,0.06419214710978799,75.98904610132907,2.400460311914132,26.0,1,0,2,48,1202.5,21.1,28.4,0.4376114081996435,0.07434503258700696
|
| 32 |
+
GBM (default),8.619418829147072,1.0011564760166576,3.0462908189340183,0.25265600996978405,0.9115791356403461,0.8832381096058513,0.0,0.13512306737563554,0.11629352319961023,44.26353412937288,22.939896191571705,25.745098039215687,0.21706,5.971681065029568,0.2858244842953152,1.9600326879612946,0.14173548842042513,1.0,0.9463131041198098,0.0,0.09851412306889507,0.07460814115278391,32.72231234173676,8.612355874421967,26.0,0,0,0,51,1202.3,22.3,22.7,0.4376114081996435,0.04352354270813194
|
| 33 |
+
RF (tuned + ensemble),2245.014868743487,2.632504310950734,530.9489806737863,1.2198476221584795,0.9024507372146047,0.8782930186177115,0.0,0.15120883991739936,0.12864400480448673,6771.2411119904955,73.51636782881279,25.84313725490196,0.21966,886.9249708387587,1.8479143513573542,373.17861356387994,0.7709478321252661,1.0,0.9768978814786328,0.0,0.0916564450840821,0.08516072052322858,5833.628398157948,63.708677480395814,28.0,0,1,1,49,1200.7,20.1,23.2,0.4353832442067736,0.06295017478288799
|
| 34 |
+
XT (tuned),1289.1519403179227,0.3436224609158917,464.9314949446578,0.1744826726067124,0.9058524786574399,0.8823009390085037,0.0,0.15403365971080407,0.127422275587505,5501.829777288316,9.97674146406182,25.92156862745098,0.21915,763.5855970117781,0.19129647148980033,183.01944048073585,0.09120693679998855,1.0,0.970701256454361,0.0,0.10343347628405763,0.07994728986866971,3537.1622158448404,8.867381424714122,29.0,0,1,0,50,1199.9,17.5,28.0,0.4336007130124777,0.05853966620405146
|
| 35 |
+
FASTAI (tuned),6629.648996400055,1.0291698354002177,1343.5604508466745,0.6091231343301344,0.9268828889794378,0.8920727938696232,0.0,0.1558685523503756,0.1360312984711962,22455.399300542234,33.54113778341792,27.65686274509804,0.2173,3182.895098288854,0.8112125396728516,593.237788402893,0.306391541190021,1.0,0.9746050760858544,0.0,0.0988046136347035,0.08330206169020851,19851.125229101002,31.29559841059079,28.0,0,0,0,51,1160.6,23.5,18.9,0.39416221033868093,0.04418776652877106
|
| 36 |
+
RF (tuned),2245.014868743487,0.2778017885544721,530.9489806737863,0.15585979099514927,0.9281198477241044,0.9030193429154391,0.0,0.1615360365144191,0.13978570251749914,6771.2411119904955,8.469005968793565,28.137254901960784,0.22016,886.9249708387587,0.17402595943874782,373.17861356387994,0.08526202343425164,1.0,0.9971929103870871,0.0,0.10456209496862212,0.09283342230804408,5833.628398157948,7.94881742200239,31.0,0,1,1,49,1151.9,18.9,24.1,0.38324420677361853,0.055631086241924914
|
| 37 |
+
NN_TORCH (default),74.85835825680128,0.5412627521423472,14.695998951842784,0.19921856017345402,0.978335352631338,0.9550533922310487,0.0,0.17458090781576796,0.15954937461607677,327.51821759182326,9.71084645377221,31.637254901960784,0.22759,34.192402362823486,0.22645958264668783,9.990997226772679,0.1258046787872722,1.0,1.0,0.0,0.14050249681884142,0.10372091439545034,204.15320945265722,7.844934898940183,33.0,0,0,0,51,1065.7,23.7,20.8,0.303698752228164,0.03443490177911753
|
| 38 |
+
FASTAI (default),27.993367113578813,1.070063710732138,4.951242935164595,0.5056871108143457,0.9771222767390375,0.9555114040073619,0.0,0.2080437804427664,0.19756225211381712,87.08936574190912,29.523324076097715,33.745098039215684,0.24127,12.973222759034899,0.8480017715030246,2.8561126039251374,0.37317813888351864,1.0,1.0,0.0,0.15801035292114685,0.14150143443329027,77.36570184770021,28.70383139894662,36.0,0,0,0,51,1010.9,22.5,22.1,0.2557932263814617,0.03221137350683143
|
| 39 |
+
RF (default),5.289521401640116,0.18747803105248345,0.8914167974682212,0.07557012377860906,0.9905963640075596,0.9728548321405758,0.0,0.2127887009205986,0.22057611136662575,11.63160057311077,4.814878723410724,34.049019607843135,0.2484,1.2628253036075168,0.08775801128811306,0.43425701731008426,0.05354175385774865,1.0,1.0,0.0,0.15453679020731148,0.13517433236964935,7.010079512208331,3.9076874559468244,35.5,0,0,0,51,1000.0,0.0,0.0,0.24888591800356505,0.03085450482928122
|
| 40 |
+
XT (default),3.067954011524425,0.20851136391458946,0.7599985259503769,0.07668050932017083,0.9748030390364969,0.9607261977937244,0.0,0.22983038868386624,0.2401119926385584,6.922794409042171,5.082769758447109,34.990196078431374,0.24428,1.029017792807685,0.0932659043206109,0.2473449527431567,0.04980480471851431,1.0,1.0,0.0,0.17836788960429084,0.15384123117868195,5.707021421143385,4.456198846093199,38.0,0,0,0,51,972.1,20.7,27.8,0.22749554367201427,0.03187662324031601
|
| 41 |
+
LR (tuned + ensemble),298.0772925112502,1.5473658189794337,106.92655310814473,0.5272909274052285,0.968958377581858,0.9646098555228514,0.0,0.3076836862047438,0.36388884495507595,1326.7185005565484,20.631703511708864,36.568627450980394,0.25172,171.24826147821216,0.28876688745286727,47.49214683366935,0.1676693138737952,1.0,1.0,0.0,0.24584842785173022,0.2585604322609332,1064.131515124883,12.175213508812917,40.0,0,0,1,50,917.3,30.7,20.1,0.19162210338680927,0.03539216425693013
|
| 42 |
+
LR (tuned),298.0772925112502,0.41952294077488855,106.92655310814473,0.14529639602271893,0.9796785843199748,0.970169924696589,0.0,0.31502751681846614,0.3731108004113419,1326.7185005565484,5.927745129039777,37.549019607843135,0.25255,171.24826147821216,0.10993631680806477,47.49214683366935,0.0665447885938415,1.0,1.0,0.0,0.2610498572359117,0.2575122541077485,1064.131515124883,4.067640041721783,41.0,0,0,0,51,881.6,31.6,29.4,0.16934046345811052,0.03046989425942536
|
| 43 |
+
LR (default),6.912347784956555,0.4444732105550163,2.521765696020704,0.1600876370747322,0.9859350644688389,0.9744519582521974,0.0,0.3287432608233925,0.4183743470806094,32.35021650084229,7.018103298699637,38.07843137254902,0.2546,5.298751910527547,0.12218634287516277,1.5162047581506444,0.0887949061495271,1.0,1.0,0.0,0.26947668808304803,0.29385559917332205,22.991652687961256,4.725399415979996,41.5,0,0,1,50,862.4,22.1,29.5,0.1573083778966132,0.03274333914572857
|
| 44 |
+
KNN (tuned + ensemble),129.6893764515588,9.265668427242952,9.839359763162042,0.6763553759282402,1.0,0.9960130371949129,0.11764705882352941,0.45319635453542406,0.6115009863532073,72.94693370250576,64.66285269534394,41.431372549019606,0.34658,10.182021194034153,0.27287014325459796,2.7415773839237785,0.17676389939136214,1.0,1.0,0.0,0.41352430110915517,0.6662116649574654,57.25701094840839,13.90517184260326,43.0,0,0,0,51,685.3,26.5,31.2,0.08110516934046345,0.02430200505969366
|
| 45 |
+
KNN (tuned),129.6893764515588,1.4108907164571591,9.839359763162042,0.11144693589219826,1.0,0.9979197340731149,0.11764705882352941,0.4687472868734289,0.6540729042725081,72.94693370250576,10.182721712640424,42.431372549019606,0.35012,10.182021194034153,0.08784447775946723,2.7415773839237785,0.03624739765555662,1.0,1.0,0.0,0.4456786012073394,0.740394718900499,57.25701094840839,2.2791618782574123,44.0,0,0,0,51,607.8,31.1,47.9,0.05837789661319073,0.023658093377554222
|
| 46 |
+
KNN (default),1.8202055170645122,0.18718713898544476,0.4967972483415847,0.03640307146637206,1.0,0.9999597757876026,0.11764705882352941,0.5414051085605402,0.9163581411737007,1.035103875827835,2.1647566343855695,43.833333333333336,0.40859,0.22567404641045463,0.036888705359564886,0.050692503527237594,0.021942545900661376,1.0,1.0,0.0,0.5109534123207524,1.0,1.0,1.2564234767690339,45.0,0,0,0,51,459.1,41.7,44.9,0.026515151515151516,0.022918450740172708
|
data/imputation_no/splits_all/tasks_all/datasets_all/leaderboard_overview_explorer.html
DELETED
|
@@ -1,1411 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena leaderboard explorer — no imputation | All Tasks | All Datasets</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Chart: a fixed y-axis pane beside a horizontally scrolling plot pane, so
|
| 269 |
-
the axis stays readable however far right the reader scrolls. */
|
| 270 |
-
.lb-chartwrap { position: relative; display: flex; align-items: flex-start; }
|
| 271 |
-
.lb-axis { flex: none; }
|
| 272 |
-
.lb-scroll {
|
| 273 |
-
flex: 1 1 auto; min-width: 0; overflow-x: auto; overflow-y: hidden;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.lb-scroll::-webkit-scrollbar { height: 10px; }
|
| 277 |
-
.lb-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
.rangepick input[type=range] { width: 96px; accent-color: var(--accent); cursor: pointer; }
|
| 282 |
-
.rangeval { font-variant-numeric: tabular-nums; font-weight: 500; min-width: 3.4em; }
|
| 283 |
-
.lb-empty { padding: 40px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 284 |
-
/* Puts the family key on its own line of the legend strip. */
|
| 285 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 286 |
-
/* Family blocks pack side by side rather than stacking: below a full-width
|
| 287 |
-
chart, one row per family leaves the small ones (Other, Baseline) each
|
| 288 |
-
wasting a line. The wide families still claim a row of their own. */
|
| 289 |
-
.chips { margin-top: 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 290 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 291 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 292 |
-
</style>
|
| 293 |
-
</head>
|
| 294 |
-
<body>
|
| 295 |
-
<div class="viewbar">
|
| 296 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 297 |
-
</div>
|
| 298 |
-
<p class="explorer-title" id="title"></p>
|
| 299 |
-
<!-- One control row above everything it scopes (axis, sorting, variants, selection). -->
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick">Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<label class="metricpick">Sort
|
| 305 |
-
<select id="sort-select"></select>
|
| 306 |
-
</label>
|
| 307 |
-
<label class="metricpick rangepick" title="Raise the axis floor to spread out the top of the field">Zoom
|
| 308 |
-
<input type="range" id="ymin-range" aria-label="Y-axis minimum">
|
| 309 |
-
<span class="rangeval" id="ymin-val"></span>
|
| 310 |
-
</label>
|
| 311 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 312 |
-
<div class="btnrow">
|
| 313 |
-
<button class="btn" id="btn-all">All methods</button>
|
| 314 |
-
<button class="btn" id="btn-top">Top 15</button>
|
| 315 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 316 |
-
</div>
|
| 317 |
-
<span class="hint">Click a column or chip to remove a method · hover for exact values</span>
|
| 318 |
-
</div>
|
| 319 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 320 |
-
<span class="hint">Export figure</span>
|
| 321 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 322 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 323 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 324 |
-
</div>
|
| 325 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 326 |
-
<div class="lb-chartwrap" id="chartwrap">
|
| 327 |
-
<svg id="axis" class="lb-axis" role="presentation"></svg>
|
| 328 |
-
<div class="lb-scroll" id="scroller">
|
| 329 |
-
<svg id="chart" role="img" aria-label="Leaderboard overview"></svg>
|
| 330 |
-
</div>
|
| 331 |
-
<div class="tooltip"></div>
|
| 332 |
-
</div>
|
| 333 |
-
<div class="chips" id="chips"></div>
|
| 334 |
-
<details class="datatable">
|
| 335 |
-
<summary>Data table</summary>
|
| 336 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 337 |
-
</details>
|
| 338 |
-
|
| 339 |
-
<script>
|
| 340 |
-
(function () {
|
| 341 |
-
"use strict";
|
| 342 |
-
const CONFIG = {"title": null, "metrics": [{"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": "", "ci": {"lo": "elo_lo", "hi": "elo_hi"}}, {"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "score", "label": "Score", "axisLabel": "Score \u2014 higher is better", "lowerBetter": false, "fromZero": true, "decimals": 3, "suffix": ""}, {"key": "rank", "label": "Average rank", "axisLabel": "Average rank \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 2, "suffix": ""}, {"key": "hrank", "label": "Harmonic rank", "axisLabel": "Harmonic rank \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 2, "suffix": ""}], "rankMetric": "elo"};
|
| 343 |
-
const POINTS = [{"method":"TabFM","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/google-research\/tabfm","reference":false,"elo":1792.0,"imp":4.074,"score":0.889,"rank":6.17,"hrank":1.72,"elo_hi":1907.0,"elo_lo":1682.0,"imputed_pct":0.0,"imputed":false},{"method":"AutoGluon 1.5 (extreme, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":true,"elo":1691.0,"imp":7.979,"score":0.662,"rank":9.39,"hrank":4.03,"elo_hi":1773.0,"elo_lo":1623.0,"imputed_pct":0.0,"imputed":false},{"method":"TabPFN-3","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2605.13986","reference":false,"elo":1665.0,"imp":9.328,"score":0.67,"rank":10.41,"hrank":4.06,"elo_hi":1745.0,"elo_lo":1604.0,"imputed_pct":0.0,"imputed":false},{"method":"TabPFN-2.6","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1620.0,"imp":10.751,"score":0.583,"rank":12.42,"hrank":7.14,"elo_hi":1691.0,"elo_lo":1569.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1595.0,"imp":10.427,"score":0.549,"rank":13.64,"hrank":6.22,"elo_hi":1669.0,"elo_lo":1539.0,"imputed_pct":0.0,"imputed":false},{"method":"TabICLv2","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2602.11139","reference":false,"elo":1594.0,"imp":10.175,"score":0.606,"rank":13.71,"hrank":4.97,"elo_hi":1667.0,"elo_lo":1533.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1554.0,"imp":11.116,"score":0.504,"rank":15.81,"hrank":7.33,"elo_hi":1619.0,"elo_lo":1499.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1524.0,"imp":11.66,"score":0.474,"rank":17.55,"hrank":9.62,"elo_hi":1586.0,"elo_lo":1480.0,"imputed_pct":0.0,"imputed":false},{"method":"AutoGluon 1.4 (best, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":true,"elo":1514.0,"imp":12.789,"score":0.401,"rank":18.2,"hrank":8.44,"elo_hi":1567.0,"elo_lo":1468.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1508.0,"imp":12.881,"score":0.405,"rank":18.55,"hrank":11.52,"elo_hi":1562.0,"elo_lo":1462.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","url":"https:\/\/openreview.net\/pdf?id=Y00pwFyrHR","reference":false,"elo":1459.0,"imp":14.0,"score":0.38,"rank":21.7,"hrank":9.59,"elo_hi":1514.0,"elo_lo":1408.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1458.0,"imp":13.788,"score":0.375,"rank":21.81,"hrank":8.16,"elo_hi":1518.0,"elo_lo":1407.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1450.0,"imp":14.081,"score":0.315,"rank":22.33,"hrank":12.48,"elo_hi":1502.0,"elo_lo":1407.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1433.0,"imp":15.033,"score":0.262,"rank":23.53,"hrank":17.2,"elo_hi":1466.0,"elo_lo":1402.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1426.0,"imp":14.202,"score":0.295,"rank":23.99,"hrank":13.67,"elo_hi":1474.0,"elo_lo":1381.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1422.0,"imp":14.656,"score":0.261,"rank":24.34,"hrank":14.77,"elo_hi":1461.0,"elo_lo":1384.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1408.0,"imp":14.885,"score":0.245,"rank":25.3,"hrank":15.31,"elo_hi":1446.0,"elo_lo":1365.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1404.0,"imp":15.304,"score":0.235,"rank":25.56,"hrank":17.78,"elo_hi":1444.0,"elo_lo":1362.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1403.0,"imp":14.936,"score":0.316,"rank":25.69,"hrank":11.3,"elo_hi":1462.0,"elo_lo":1347.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1394.0,"imp":14.952,"score":0.251,"rank":26.35,"hrank":14.47,"elo_hi":1442.0,"elo_lo":1352.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1389.0,"imp":15.599,"score":0.277,"rank":26.66,"hrank":12.79,"elo_hi":1462.0,"elo_lo":1337.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1386.0,"imp":15.688,"score":0.194,"rank":26.93,"hrank":20.71,"elo_hi":1415.0,"elo_lo":1357.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1378.0,"imp":15.524,"score":0.224,"rank":27.47,"hrank":16.11,"elo_hi":1418.0,"elo_lo":1336.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1375.0,"imp":15.754,"score":0.198,"rank":27.73,"hrank":19.98,"elo_hi":1406.0,"elo_lo":1342.0,"imputed_pct":0.0,"imputed":false},{"method":"LimiX","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2509.03505","reference":false,"elo":1363.0,"imp":15.526,"score":0.299,"rank":28.66,"hrank":9.55,"elo_hi":1441.0,"elo_lo":1304.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1355.0,"imp":16.044,"score":0.189,"rank":29.21,"hrank":16.82,"elo_hi":1392.0,"elo_lo":1318.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSwift","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/LAMDA-Tabular\/TabSwift","reference":false,"elo":1350.0,"imp":16.081,"score":0.251,"rank":29.58,"hrank":17.68,"elo_hi":1408.0,"elo_lo":1298.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1350.0,"imp":16.065,"score":0.16,"rank":29.6,"hrank":22.22,"elo_hi":1379.0,"elo_lo":1318.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Tuned + Ens.","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1348.0,"imp":16.284,"score":0.209,"rank":29.79,"hrank":18.96,"elo_hi":1397.0,"elo_lo":1305.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1333.0,"imp":17.213,"score":0.186,"rank":30.87,"hrank":19.34,"elo_hi":1379.0,"elo_lo":1273.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1325.0,"imp":17.225,"score":0.245,"rank":31.53,"hrank":14.33,"elo_hi":1389.0,"elo_lo":1270.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1308.0,"imp":17.551,"score":0.156,"rank":32.79,"hrank":21.32,"elo_hi":1352.0,"elo_lo":1248.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Tuned","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1300.0,"imp":17.449,"score":0.158,"rank":33.43,"hrank":22.28,"elo_hi":1345.0,"elo_lo":1261.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1298.0,"imp":17.0,"score":0.161,"rank":33.63,"hrank":21.84,"elo_hi":1345.0,"elo_lo":1254.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1295.0,"imp":17.147,"score":0.111,"rank":33.83,"hrank":23.47,"elo_hi":1335.0,"elo_lo":1262.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1285.0,"imp":17.161,"score":0.126,"rank":34.58,"hrank":25.37,"elo_hi":1333.0,"elo_lo":1238.0,"imputed_pct":0.0,"imputed":false},{"method":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2506.10707","reference":false,"elo":1283.0,"imp":18.278,"score":0.194,"rank":34.72,"hrank":14.11,"elo_hi":1340.0,"elo_lo":1228.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1272.0,"imp":18.672,"score":0.116,"rank":35.64,"hrank":25.8,"elo_hi":1312.0,"elo_lo":1232.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Default","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1264.0,"imp":18.657,"score":0.121,"rank":36.23,"hrank":23.23,"elo_hi":1311.0,"elo_lo":1209.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1248.0,"imp":19.194,"score":0.09,"rank":37.44,"hrank":23.68,"elo_hi":1289.0,"elo_lo":1209.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1235.0,"imp":19.314,"score":0.082,"rank":38.43,"hrank":28.17,"elo_hi":1279.0,"elo_lo":1195.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1230.0,"imp":18.569,"score":0.066,"rank":38.85,"hrank":29.23,"elo_hi":1266.0,"elo_lo":1193.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1214.0,"imp":18.792,"score":0.053,"rank":40.04,"hrank":30.76,"elo_hi":1253.0,"elo_lo":1178.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1212.0,"imp":18.877,"score":0.069,"rank":40.24,"hrank":30.96,"elo_hi":1253.0,"elo_lo":1170.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1208.0,"imp":19.777,"score":0.083,"rank":40.47,"hrank":28.16,"elo_hi":1257.0,"elo_lo":1165.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1207.0,"imp":19.677,"score":0.105,"rank":40.58,"hrank":25.38,"elo_hi":1258.0,"elo_lo":1148.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Default","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1204.0,"imp":20.255,"score":0.069,"rank":40.82,"hrank":28.54,"elo_hi":1249.0,"elo_lo":1155.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Default","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1186.0,"imp":19.344,"score":0.038,"rank":42.12,"hrank":36.15,"elo_hi":1220.0,"elo_lo":1157.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1180.0,"imp":20.564,"score":0.074,"rank":42.56,"hrank":26.73,"elo_hi":1225.0,"elo_lo":1128.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1171.0,"imp":20.828,"score":0.06,"rank":43.28,"hrank":29.04,"elo_hi":1225.0,"elo_lo":1124.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1147.0,"imp":21.096,"score":0.048,"rank":45.01,"hrank":31.19,"elo_hi":1199.0,"elo_lo":1088.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1137.0,"imp":21.535,"score":0.041,"rank":45.71,"hrank":28.56,"elo_hi":1187.0,"elo_lo":1093.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":1097.0,"imp":25.584,"score":0.125,"rank":48.47,"hrank":15.95,"elo_hi":1172.0,"elo_lo":1014.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":1096.0,"imp":25.6,"score":0.123,"rank":48.56,"hrank":15.35,"elo_hi":1175.0,"elo_lo":1013.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1094.0,"imp":23.024,"score":0.037,"rank":48.66,"hrank":33.93,"elo_hi":1141.0,"elo_lo":1040.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":1089.0,"imp":26.446,"score":0.024,"rank":49.04,"hrank":38.83,"elo_hi":1133.0,"elo_lo":1044.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1074.0,"imp":22.815,"score":0.011,"rank":49.99,"hrank":39.42,"elo_hi":1108.0,"elo_lo":1032.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Tuned","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":1050.0,"imp":27.802,"score":0.011,"rank":51.52,"hrank":39.96,"elo_hi":1097.0,"elo_lo":1000.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Default","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1043.0,"imp":26.445,"score":0.029,"rank":51.95,"hrank":44.11,"elo_hi":1104.0,"elo_lo":973.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1009.0,"imp":26.176,"score":0.012,"rank":54.0,"hrank":47.38,"elo_hi":1060.0,"elo_lo":943.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1008.0,"imp":25.682,"score":0.009,"rank":54.07,"hrank":39.97,"elo_hi":1065.0,"elo_lo":946.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1000.0,"imp":26.265,"score":0.003,"rank":54.51,"hrank":49.81,"elo_hi":1047.0,"elo_lo":953.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":997.0,"imp":27.822,"score":0.017,"rank":54.67,"hrank":38.92,"elo_hi":1058.0,"elo_lo":921.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":993.0,"imp":30.456,"score":0.077,"rank":54.89,"hrank":24.31,"elo_hi":1082.0,"elo_lo":889.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":965.0,"imp":33.667,"score":0.031,"rank":56.39,"hrank":40.87,"elo_hi":1029.0,"elo_lo":865.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":940.0,"imp":34.211,"score":0.022,"rank":57.67,"hrank":42.64,"elo_hi":1010.0,"elo_lo":835.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Default","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":936.0,"imp":31.748,"score":0.0,"rank":57.84,"hrank":45.44,"elo_hi":979.0,"elo_lo":879.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":890.0,"imp":32.782,"score":0.008,"rank":59.92,"hrank":46.93,"elo_hi":951.0,"elo_lo":790.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":861.0,"imp":36.822,"score":0.014,"rank":61.12,"hrank":47.51,"elo_hi":930.0,"elo_lo":743.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":654.0,"imp":45.987,"score":0.0,"rank":66.89,"hrank":60.42,"elo_hi":732.0,"elo_lo":563.0,"imputed_pct":0.0,"imputed":false}];
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 347 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 348 |
-
// already share a color, and each holds only a handful of methods.
|
| 349 |
-
const FAM_MERGED = "Baseline / Other";
|
| 350 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 351 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 352 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 353 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 354 |
-
|
| 355 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 356 |
-
const FAM_VAR = {
|
| 357 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 358 |
-
"Tree-based": "var(--fam-tree)",
|
| 359 |
-
"Neural Network": "var(--fam-nn)",
|
| 360 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 361 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 362 |
-
};
|
| 363 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 364 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 365 |
-
// that chip carries both symbols.
|
| 366 |
-
const FAM_SYMBOL = {
|
| 367 |
-
"Foundation Model": "🧠⚡",
|
| 368 |
-
"Tree-based": "🌳",
|
| 369 |
-
"Neural Network": "🧠🔁",
|
| 370 |
-
"Reference Pipeline": "📊",
|
| 371 |
-
[FAM_MERGED]: "📏 ❓",
|
| 372 |
-
};
|
| 373 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 374 |
-
const VARIANT_VAR = {
|
| 375 |
-
"Default": "var(--var-default)",
|
| 376 |
-
"Tuned": "var(--var-tuned)",
|
| 377 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 378 |
-
};
|
| 379 |
-
|
| 380 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 381 |
-
function famChipLabel(family, count) {
|
| 382 |
-
const symbol = FAM_SYMBOL[family];
|
| 383 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 384 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 385 |
-
}
|
| 386 |
-
|
| 387 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 388 |
-
const FAM_INK = {
|
| 389 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 390 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 391 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 392 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 393 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 394 |
-
};
|
| 395 |
-
|
| 396 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 397 |
-
function el(name, attrs, parent) {
|
| 398 |
-
const node = document.createElementNS(NS, name);
|
| 399 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 400 |
-
if (parent) parent.appendChild(node);
|
| 401 |
-
return node;
|
| 402 |
-
}
|
| 403 |
-
|
| 404 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 405 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 406 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 407 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 408 |
-
function fmtNum(v, decimals) {
|
| 409 |
-
if (v == null || !isFinite(v)) return "—";
|
| 410 |
-
return v.toFixed(decimals);
|
| 411 |
-
}
|
| 412 |
-
|
| 413 |
-
function fmtMetric(metric, v) {
|
| 414 |
-
if (v == null || !isFinite(v)) return "—";
|
| 415 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 416 |
-
}
|
| 417 |
-
|
| 418 |
-
function fmtTime(v) {
|
| 419 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 420 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 421 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 422 |
-
return fmtNum(v, 3) + " s";
|
| 423 |
-
}
|
| 424 |
-
|
| 425 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 426 |
-
function niceStep(raw) {
|
| 427 |
-
if (!(raw > 0)) return 1;
|
| 428 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 429 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 430 |
-
if (mag * m >= raw) return mag * m;
|
| 431 |
-
}
|
| 432 |
-
return mag * 10;
|
| 433 |
-
}
|
| 434 |
-
|
| 435 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 436 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 437 |
-
function ticks(min, max, target) {
|
| 438 |
-
const step = niceStep((max - min) / target);
|
| 439 |
-
const first = Math.ceil(min / step);
|
| 440 |
-
const out = [];
|
| 441 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 442 |
-
return out.length ? out : [min];
|
| 443 |
-
}
|
| 444 |
-
|
| 445 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 446 |
-
function makeTooltip(box) {
|
| 447 |
-
const node = box.querySelector(".tooltip");
|
| 448 |
-
return {
|
| 449 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 450 |
-
move(ev) {
|
| 451 |
-
const r = box.getBoundingClientRect();
|
| 452 |
-
let tx = ev.clientX - r.left + 14;
|
| 453 |
-
const ty = ev.clientY - r.top + 12;
|
| 454 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 455 |
-
node.style.left = tx + "px";
|
| 456 |
-
node.style.top = ty + "px";
|
| 457 |
-
},
|
| 458 |
-
hide() { node.style.display = "none"; },
|
| 459 |
-
};
|
| 460 |
-
}
|
| 461 |
-
|
| 462 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 463 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 464 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 465 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 466 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 467 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 468 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 469 |
-
function setUpPaperView(afterToggle, options) {
|
| 470 |
-
const opts = options || {};
|
| 471 |
-
const root = document.documentElement;
|
| 472 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 473 |
-
const btn = document.getElementById("btn-paper");
|
| 474 |
-
const embedded = window.parent !== window;
|
| 475 |
-
|
| 476 |
-
function setPaper(on) {
|
| 477 |
-
document.body.classList.toggle("paper", on);
|
| 478 |
-
if (on) {
|
| 479 |
-
hostTheme = root.getAttribute("data-theme");
|
| 480 |
-
root.setAttribute("data-theme", "light");
|
| 481 |
-
} else if (hostTheme) {
|
| 482 |
-
root.setAttribute("data-theme", hostTheme);
|
| 483 |
-
} else {
|
| 484 |
-
root.removeAttribute("data-theme");
|
| 485 |
-
}
|
| 486 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 487 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 488 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 489 |
-
postHeight();
|
| 490 |
-
}
|
| 491 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 492 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 493 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 494 |
-
// shareable single file) this page needs its own.
|
| 495 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 496 |
-
window.addEventListener("message", ev => {
|
| 497 |
-
const d = ev.data;
|
| 498 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 499 |
-
});
|
| 500 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 501 |
-
// key press, so its label would fall out of step with the frame.
|
| 502 |
-
if (!embedded) {
|
| 503 |
-
document.addEventListener("keydown", ev => {
|
| 504 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 505 |
-
});
|
| 506 |
-
}
|
| 507 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 508 |
-
}
|
| 509 |
-
|
| 510 |
-
// --- Figure export ---------------------------------------------------------
|
| 511 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 512 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 513 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 514 |
-
// the legend is HTML rather than part of the SVG.
|
| 515 |
-
|
| 516 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 517 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 518 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 519 |
-
// break the PNG path.
|
| 520 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 521 |
-
// once the node leaves this document.
|
| 522 |
-
function resolveVars(root, resolve) {
|
| 523 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 524 |
-
for (const attr of ["fill", "stroke"]) {
|
| 525 |
-
const value = node.getAttribute(attr);
|
| 526 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 527 |
-
}
|
| 528 |
-
}
|
| 529 |
-
}
|
| 530 |
-
|
| 531 |
-
function legendToSvg(container, resolve) {
|
| 532 |
-
const base = container.getBoundingClientRect();
|
| 533 |
-
const group = document.createElementNS(NS, "g");
|
| 534 |
-
let height = 0;
|
| 535 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 536 |
-
const box = item.getBoundingClientRect();
|
| 537 |
-
if (!box.width) continue;
|
| 538 |
-
height = Math.max(height, box.bottom - base.top);
|
| 539 |
-
let textLeft = box.left - base.left;
|
| 540 |
-
const glyph = item.querySelector("svg");
|
| 541 |
-
if (glyph) {
|
| 542 |
-
const gbox = glyph.getBoundingClientRect();
|
| 543 |
-
const wrap = el("g", {
|
| 544 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 545 |
-
}, group);
|
| 546 |
-
const glyphClone = glyph.cloneNode(true);
|
| 547 |
-
resolveVars(glyphClone, resolve);
|
| 548 |
-
wrap.appendChild(glyphClone);
|
| 549 |
-
textLeft = gbox.right - base.left + 5;
|
| 550 |
-
}
|
| 551 |
-
const label = item.textContent.trim();
|
| 552 |
-
if (!label) continue;
|
| 553 |
-
const colored = item.querySelector("[style*='color']");
|
| 554 |
-
const text = el("text", {
|
| 555 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 556 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 557 |
-
}, group);
|
| 558 |
-
text.textContent = label;
|
| 559 |
-
}
|
| 560 |
-
return { group, height: Math.ceil(height) };
|
| 561 |
-
}
|
| 562 |
-
|
| 563 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 564 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 565 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 566 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 567 |
-
const resolve = value => String(value).replace(
|
| 568 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 569 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 570 |
-
|
| 571 |
-
let chartW = 0, chartH = 0;
|
| 572 |
-
for (const part of parts) {
|
| 573 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 574 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 575 |
-
}
|
| 576 |
-
|
| 577 |
-
const out = document.createElementNS(NS, "svg");
|
| 578 |
-
out.setAttribute("xmlns", NS);
|
| 579 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 580 |
-
let top = pad;
|
| 581 |
-
const later = []; // built after the width is known
|
| 582 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 583 |
-
if (legend && legend.height) {
|
| 584 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 585 |
-
later.push(() => out.appendChild(legend.group));
|
| 586 |
-
top += legend.height + 8;
|
| 587 |
-
}
|
| 588 |
-
|
| 589 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 590 |
-
const height = top + chartH + pad;
|
| 591 |
-
out.setAttribute("width", Math.ceil(width));
|
| 592 |
-
out.setAttribute("height", Math.ceil(height));
|
| 593 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 594 |
-
for (const build of later) build();
|
| 595 |
-
|
| 596 |
-
for (const part of parts) {
|
| 597 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 598 |
-
const clone = part.svg.cloneNode(true);
|
| 599 |
-
resolveVars(clone, resolve);
|
| 600 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 601 |
-
}
|
| 602 |
-
return out;
|
| 603 |
-
}
|
| 604 |
-
|
| 605 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 606 |
-
function slugify(text) {
|
| 607 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 608 |
-
}
|
| 609 |
-
|
| 610 |
-
function downloadUrl(url, filename) {
|
| 611 |
-
const a = document.createElement("a");
|
| 612 |
-
a.href = url;
|
| 613 |
-
a.download = filename;
|
| 614 |
-
document.body.appendChild(a);
|
| 615 |
-
a.click();
|
| 616 |
-
a.remove();
|
| 617 |
-
}
|
| 618 |
-
|
| 619 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 620 |
-
function rasterize(svg, scale, done, fail) {
|
| 621 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 622 |
-
const img = new Image();
|
| 623 |
-
img.onload = () => {
|
| 624 |
-
const canvas = document.createElement("canvas");
|
| 625 |
-
canvas.width = Math.round(width * scale);
|
| 626 |
-
canvas.height = Math.round(height * scale);
|
| 627 |
-
const ctx = canvas.getContext("2d");
|
| 628 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 629 |
-
ctx.drawImage(img, 0, 0);
|
| 630 |
-
done(canvas, width, height);
|
| 631 |
-
};
|
| 632 |
-
img.onerror = fail;
|
| 633 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 634 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 635 |
-
}
|
| 636 |
-
|
| 637 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 638 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 639 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 640 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 641 |
-
// and the pixels land at 96*scale dpi.
|
| 642 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 643 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 644 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 645 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 646 |
-
rgb[j] = pixels[i];
|
| 647 |
-
rgb[j + 1] = pixels[i + 1];
|
| 648 |
-
rgb[j + 2] = pixels[i + 2];
|
| 649 |
-
}
|
| 650 |
-
const deflated = new Uint8Array(await new Response(
|
| 651 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 652 |
-
|
| 653 |
-
const encoder = new TextEncoder();
|
| 654 |
-
const chunks = [];
|
| 655 |
-
const offsets = [];
|
| 656 |
-
let cursor = 0;
|
| 657 |
-
const put = data => {
|
| 658 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 659 |
-
chunks.push(bytes);
|
| 660 |
-
cursor += bytes.length;
|
| 661 |
-
};
|
| 662 |
-
const object = (id, body, stream) => {
|
| 663 |
-
offsets[id] = cursor;
|
| 664 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 665 |
-
if (stream) {
|
| 666 |
-
put("stream\n");
|
| 667 |
-
put(stream);
|
| 668 |
-
put("\nendstream\n");
|
| 669 |
-
}
|
| 670 |
-
put("endobj\n");
|
| 671 |
-
};
|
| 672 |
-
|
| 673 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 674 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 675 |
-
put("%PDF-1.4\n");
|
| 676 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 677 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 678 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 679 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 680 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 681 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 682 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 683 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 684 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 685 |
-
|
| 686 |
-
const xref = cursor;
|
| 687 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 688 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 689 |
-
put(table);
|
| 690 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 691 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 692 |
-
}
|
| 693 |
-
|
| 694 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 695 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 696 |
-
function setUpExport(getParts, basename) {
|
| 697 |
-
const buttons = {
|
| 698 |
-
svg: document.getElementById("btn-svg"),
|
| 699 |
-
png: document.getElementById("btn-png"),
|
| 700 |
-
pdf: document.getElementById("btn-pdf"),
|
| 701 |
-
};
|
| 702 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 703 |
-
|
| 704 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 705 |
-
function complain(format) {
|
| 706 |
-
const button = buttons[format];
|
| 707 |
-
if (!button) return;
|
| 708 |
-
const label = button.textContent;
|
| 709 |
-
button.textContent = "failed";
|
| 710 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 711 |
-
}
|
| 712 |
-
|
| 713 |
-
function run(format) {
|
| 714 |
-
const svg = figure();
|
| 715 |
-
const name = basename();
|
| 716 |
-
if (format === "svg") {
|
| 717 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 718 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 719 |
-
return;
|
| 720 |
-
}
|
| 721 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 722 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 723 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 724 |
-
if (format === "png") {
|
| 725 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 726 |
-
} else {
|
| 727 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 728 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 729 |
-
.catch(() => complain("pdf"));
|
| 730 |
-
}
|
| 731 |
-
}, () => complain(format));
|
| 732 |
-
}
|
| 733 |
-
|
| 734 |
-
for (const format of Object.keys(buttons)) {
|
| 735 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 736 |
-
}
|
| 737 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 738 |
-
window.addEventListener("message", ev => {
|
| 739 |
-
const d = ev.data;
|
| 740 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 741 |
-
});
|
| 742 |
-
}
|
| 743 |
-
|
| 744 |
-
// When embedded, report the content height so the host page can size the
|
| 745 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 746 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 747 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 748 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 749 |
-
// stops re-posting once the height settles.
|
| 750 |
-
let lastPostedHeight = 0;
|
| 751 |
-
function postHeight() {
|
| 752 |
-
if (window.parent === window) return;
|
| 753 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 754 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 755 |
-
lastPostedHeight = height;
|
| 756 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 757 |
-
}
|
| 758 |
-
|
| 759 |
-
|
| 760 |
-
// ---------- geometry ----------
|
| 761 |
-
const AXIS_W = 72; // width of the sticky y-axis pane
|
| 762 |
-
const PLOT_H = 320; // height of the plot area itself
|
| 763 |
-
const TOP = 14; // headroom above the tallest bar
|
| 764 |
-
const LABEL_TOP = 18; // axis line -> first label row
|
| 765 |
-
const LABEL_ROW = 19; // vertical offset of the staggered second row
|
| 766 |
-
const LABEL_SIZE = 14; // method names; the slot below scales with it
|
| 767 |
-
const TICK_SIZE = 12.5;
|
| 768 |
-
// Method names are set horizontally (rotated ones are markedly harder to
|
| 769 |
-
// read), staggered over two rows exactly like the static figure — so a slot
|
| 770 |
-
// has to be wide enough for half a name. Past ~24 methods the chart scrolls
|
| 771 |
-
// rather than squeezing every column into the viewport.
|
| 772 |
-
// No upper bound on the slot: with few methods selected a capped slot left
|
| 773 |
-
// the columns huddled on the left with dead space beside them, so the slots
|
| 774 |
-
// simply share out whatever width there is.
|
| 775 |
-
const MIN_SLOT = 66;
|
| 776 |
-
const BAR_FRAC = 0.88; // share of the slot the widest bar takes
|
| 777 |
-
const MAX_BAR = 70; // ...but never wider than this, however few columns
|
| 778 |
-
|
| 779 |
-
// Variant -> (color token, width relative to the widest bar). The bars are
|
| 780 |
-
// concentric, so the nesting itself encodes the tuning progression.
|
| 781 |
-
const VARIANT_STYLE = {
|
| 782 |
-
"Tuned + Ens.": { color: "var(--var-tunedens)", rel: 1 },
|
| 783 |
-
"Tuned": { color: "var(--var-tuned)", rel: 0.8 },
|
| 784 |
-
"Default": { color: "var(--var-default)", rel: 0.6 },
|
| 785 |
-
};
|
| 786 |
-
const VARIANT_ORDER = ["Default", "Tuned", "Tuned + Ens."];
|
| 787 |
-
// Dash patterns cycle so several reference lines stay distinguishable.
|
| 788 |
-
const REF_DASHES = ["8 5", "2 4", "12 4 3 4"];
|
| 789 |
-
|
| 790 |
-
const titleEl = document.getElementById("title");
|
| 791 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 792 |
-
|
| 793 |
-
const axisSvg = document.getElementById("axis");
|
| 794 |
-
const svg = document.getElementById("chart");
|
| 795 |
-
const scroller = document.getElementById("scroller");
|
| 796 |
-
const wrap = document.getElementById("chartwrap");
|
| 797 |
-
const yminRange = document.getElementById("ymin-range");
|
| 798 |
-
const yminVal = document.getElementById("ymin-val");
|
| 799 |
-
const tip = makeTooltip(wrap);
|
| 800 |
-
|
| 801 |
-
// ---------- data ----------
|
| 802 |
-
const METRICS = CONFIG.metrics;
|
| 803 |
-
const metricByKey = {};
|
| 804 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 805 |
-
|
| 806 |
-
// One entry per method (its variants grouped); reference pipelines are kept
|
| 807 |
-
// apart — they are drawn as threshold lines, not as columns.
|
| 808 |
-
const byMethod = new Map();
|
| 809 |
-
const refs = [];
|
| 810 |
-
for (const p of POINTS) {
|
| 811 |
-
if (p.reference) { refs.push(p); continue; }
|
| 812 |
-
let entry = byMethod.get(p.method);
|
| 813 |
-
if (!entry) {
|
| 814 |
-
entry = { method: p.method, family: p.family, url: p.url, points: [] };
|
| 815 |
-
byMethod.set(p.method, entry);
|
| 816 |
-
}
|
| 817 |
-
entry.points.push(p);
|
| 818 |
-
}
|
| 819 |
-
for (const e of byMethod.values()) {
|
| 820 |
-
e.points.sort((a, b) => VARIANT_ORDER.indexOf(a.variant) - VARIANT_ORDER.indexOf(b.variant));
|
| 821 |
-
e.imputed = e.points.some(p => p.imputed);
|
| 822 |
-
e.imputed_pct = Math.max(...e.points.map(p => p.imputed_pct || 0));
|
| 823 |
-
}
|
| 824 |
-
|
| 825 |
-
const state = {
|
| 826 |
-
metric: METRICS[0].key,
|
| 827 |
-
sort: "best",
|
| 828 |
-
yMin: null, // null = the automatic axis floor; a number = zoomed in
|
| 829 |
-
|
| 830 |
-
methods: new Set(byMethod.keys()),
|
| 831 |
-
refs: new Set(refs.map(r => r.method)),
|
| 832 |
-
variants: new Set(VARIANT_ORDER),
|
| 833 |
-
};
|
| 834 |
-
|
| 835 |
-
function metric() { return metricByKey[state.metric]; }
|
| 836 |
-
|
| 837 |
-
// A method's best value under `m`, ignoring variants the reader switched off.
|
| 838 |
-
function bestOf(entry, m) {
|
| 839 |
-
const vals = entry.points
|
| 840 |
-
.filter(p => state.variants.has(p.variant) && p[m.key] != null)
|
| 841 |
-
.map(p => p[m.key]);
|
| 842 |
-
if (!vals.length) return null;
|
| 843 |
-
return m.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 844 |
-
}
|
| 845 |
-
|
| 846 |
-
function sortedMethods(entries, m) {
|
| 847 |
-
const arr = [...entries];
|
| 848 |
-
const cmp = {
|
| 849 |
-
best: (a, b) => rankVal(a, m) - rankVal(b, m),
|
| 850 |
-
worst: (a, b) => rankVal(b, m) - rankVal(a, m),
|
| 851 |
-
name: (a, b) => a.method.localeCompare(b.method),
|
| 852 |
-
family: (a, b) =>
|
| 853 |
-
FAM_ORDER.indexOf(a.family) - FAM_ORDER.indexOf(b.family) || rankVal(a, m) - rankVal(b, m),
|
| 854 |
-
}[state.sort];
|
| 855 |
-
return arr.sort(cmp);
|
| 856 |
-
}
|
| 857 |
-
// Sort key that puts "better" first for either metric direction, with
|
| 858 |
-
// value-less methods last.
|
| 859 |
-
function rankVal(entry, m) {
|
| 860 |
-
const v = bestOf(entry, m);
|
| 861 |
-
if (v == null) return Infinity;
|
| 862 |
-
return m.lowerBetter ? v : -v;
|
| 863 |
-
}
|
| 864 |
-
|
| 865 |
-
function visibleEntries() {
|
| 866 |
-
const m = metric();
|
| 867 |
-
return sortedMethods([...byMethod.values()].filter(e => state.methods.has(e.method) && bestOf(e, m) != null), m);
|
| 868 |
-
}
|
| 869 |
-
function visibleRefs() {
|
| 870 |
-
return refs.filter(r => state.refs.has(r.method) && r[state.metric] != null);
|
| 871 |
-
}
|
| 872 |
-
|
| 873 |
-
// Rendered width of each label, measured in the live document (font metrics
|
| 874 |
-
// are not knowable up front): it decides whether the names fit on one row or
|
| 875 |
-
// need the two-row stagger, and which ones have to be shortened.
|
| 876 |
-
function measureLabels(names) {
|
| 877 |
-
const probe = el("g", { visibility: "hidden" }, svg);
|
| 878 |
-
const widths = names.map(name => {
|
| 879 |
-
const t = el("text", { "font-size": LABEL_SIZE }, probe);
|
| 880 |
-
t.textContent = name;
|
| 881 |
-
return t.getComputedTextLength();
|
| 882 |
-
});
|
| 883 |
-
probe.remove();
|
| 884 |
-
return widths;
|
| 885 |
-
}
|
| 886 |
-
|
| 887 |
-
// Trim a name to `budget` px, ending in an ellipsis. The full name stays one
|
| 888 |
-
// hover (and one data-table row) away.
|
| 889 |
-
function fitLabel(node, name, width, budget) {
|
| 890 |
-
if (width <= budget) return;
|
| 891 |
-
let text = name;
|
| 892 |
-
while (text.length > 1 && node.getComputedTextLength() > budget) {
|
| 893 |
-
text = text.slice(0, -1);
|
| 894 |
-
node.textContent = text + "…";
|
| 895 |
-
}
|
| 896 |
-
}
|
| 897 |
-
|
| 898 |
-
// ---------- chart ----------
|
| 899 |
-
function render() {
|
| 900 |
-
const m = metric();
|
| 901 |
-
const entries = visibleEntries();
|
| 902 |
-
const shownRefs = visibleRefs();
|
| 903 |
-
svg.textContent = "";
|
| 904 |
-
axisSvg.textContent = "";
|
| 905 |
-
axisSvg.setAttribute("width", AXIS_W);
|
| 906 |
-
|
| 907 |
-
const avail = Math.max(240, scroller.clientWidth - 2);
|
| 908 |
-
if (!entries.length) {
|
| 909 |
-
axisSvg.setAttribute("height", 120);
|
| 910 |
-
svg.setAttribute("width", avail);
|
| 911 |
-
svg.setAttribute("height", 120);
|
| 912 |
-
const t = el("text", { x: avail / 2, y: 60, "text-anchor": "middle", "font-size": 13, fill: "var(--muted)" }, svg);
|
| 913 |
-
t.textContent = "No methods selected — use “All methods” to bring them back.";
|
| 914 |
-
buildLegend(m, shownRefs);
|
| 915 |
-
postHeight();
|
| 916 |
-
return;
|
| 917 |
-
}
|
| 918 |
-
|
| 919 |
-
const slot = Math.max(MIN_SLOT, avail / entries.length);
|
| 920 |
-
const barUnit = Math.min(MAX_BAR, slot * BAR_FRAC);
|
| 921 |
-
const plotW = Math.max(avail, slot * entries.length);
|
| 922 |
-
// Names go on one row when they fit side by side, otherwise on two
|
| 923 |
-
// staggered rows (each label then has two slots of room).
|
| 924 |
-
const labels = entries.map(e => e.method + (e.imputed ? " ‡" : ""));
|
| 925 |
-
const labelWidths = measureLabels(labels);
|
| 926 |
-
const widest = Math.max(...labelWidths);
|
| 927 |
-
const labelRows = widest <= slot - 6 ? 1 : 2;
|
| 928 |
-
const H = TOP + PLOT_H + LABEL_TOP + (labelRows - 1) * LABEL_ROW + 10;
|
| 929 |
-
svg.setAttribute("width", plotW);
|
| 930 |
-
svg.setAttribute("height", H);
|
| 931 |
-
axisSvg.setAttribute("height", H);
|
| 932 |
-
|
| 933 |
-
// -- y domain: from zero where the metric has one, else a floor below the
|
| 934 |
-
// shortest bar (Elo has no meaningful zero, and starting at zero would
|
| 935 |
-
// squash every difference into the top fifth of the chart). The floor
|
| 936 |
-
// ignores the CI whiskers so one wide interval cannot deflate the scale.
|
| 937 |
-
const barVals = [];
|
| 938 |
-
const allVals = [];
|
| 939 |
-
for (const e of entries) {
|
| 940 |
-
for (const p of e.points) {
|
| 941 |
-
if (!state.variants.has(p.variant) || p[m.key] == null) continue;
|
| 942 |
-
barVals.push(p[m.key]);
|
| 943 |
-
allVals.push(p[m.key]);
|
| 944 |
-
if (m.ci && p[m.ci.hi] != null) allVals.push(p[m.ci.hi]);
|
| 945 |
-
}
|
| 946 |
-
}
|
| 947 |
-
for (const r of shownRefs) { barVals.push(r[state.metric]); allVals.push(r[state.metric]); }
|
| 948 |
-
const barMin = Math.min(...barVals), barMax = Math.max(...allVals);
|
| 949 |
-
const span = barMax - barMin || Math.abs(barMax) || 1;
|
| 950 |
-
let autoY0, y1;
|
| 951 |
-
if (m.fromZero) {
|
| 952 |
-
autoY0 = 0;
|
| 953 |
-
y1 = barMax * 1.06 || 1;
|
| 954 |
-
} else {
|
| 955 |
-
// Snap the floor down to a tick multiple so the axis reads in round
|
| 956 |
-
// numbers, and keep it just below the shortest bar: every bar stays
|
| 957 |
-
// visible (the static figure clips the ones below its fixed floor).
|
| 958 |
-
const step = niceStep(span / 6);
|
| 959 |
-
autoY0 = Math.floor((barMin - span * 0.05) / step) * step;
|
| 960 |
-
y1 = barMax + span * 0.04;
|
| 961 |
-
}
|
| 962 |
-
// The zoom slider raises the floor from there toward the top of the field,
|
| 963 |
-
// magnifying the differences between the leaders. Its bounds follow the
|
| 964 |
-
// metric's own scale, so they are refreshed on every render; the bars and
|
| 965 |
-
// whiskers that drop below the new floor are clipped away (see plot-clip).
|
| 966 |
-
const zoomMax = autoY0 + (y1 - autoY0) * 0.9;
|
| 967 |
-
yminRange.min = autoY0;
|
| 968 |
-
yminRange.max = zoomMax;
|
| 969 |
-
yminRange.step = (zoomMax - autoY0) / 200 || 1;
|
| 970 |
-
if (state.yMin != null) state.yMin = Math.min(state.yMin, zoomMax);
|
| 971 |
-
if (state.yMin != null && state.yMin <= autoY0) state.yMin = null;
|
| 972 |
-
const y0 = state.yMin == null ? autoY0 : state.yMin;
|
| 973 |
-
yminRange.value = y0;
|
| 974 |
-
yminVal.textContent = state.yMin == null ? "auto" : fmtNum(y0, m.decimals);
|
| 975 |
-
const Y = v => TOP + (1 - (v - y0) / (y1 - y0)) * PLOT_H;
|
| 976 |
-
const baseY = Y(y0);
|
| 977 |
-
|
| 978 |
-
// -- grid (solid hairlines) in the plot pane, tick labels in the axis pane
|
| 979 |
-
const tickVals = ticks(y0, y1, 6);
|
| 980 |
-
const grid = el("g", {}, svg);
|
| 981 |
-
const tickLabels = [];
|
| 982 |
-
for (const tv of tickVals) {
|
| 983 |
-
const gy = Y(tv);
|
| 984 |
-
el("line", { x1: 0, y1: gy, x2: plotW, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 985 |
-
const t = el("text", {
|
| 986 |
-
x: AXIS_W - 10, y: gy + 4, "text-anchor": "end", "font-size": TICK_SIZE, fill: "var(--muted)",
|
| 987 |
-
}, axisSvg);
|
| 988 |
-
t.textContent = fmtNum(tv, m.decimals);
|
| 989 |
-
tickLabels.push({ y: gy, node: t });
|
| 990 |
-
}
|
| 991 |
-
el("line", { x1: 0, y1: baseY, x2: plotW, y2: baseY, stroke: "var(--muted)", "stroke-width": 1 }, grid);
|
| 992 |
-
el("line", { x1: AXIS_W - 1, y1: TOP, x2: AXIS_W - 1, y2: baseY, stroke: "var(--muted)", "stroke-width": 1 }, axisSvg);
|
| 993 |
-
el("text", {
|
| 994 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": LABEL_SIZE, "font-weight": 650,
|
| 995 |
-
fill: "var(--ink)", transform: `translate(15 ${TOP + PLOT_H / 2}) rotate(-90)`,
|
| 996 |
-
}, axisSvg).textContent = m.axisLabel;
|
| 997 |
-
|
| 998 |
-
// -- hover band behind the marks (highlights the whole column group)
|
| 999 |
-
const band = el("rect", {
|
| 1000 |
-
x: 0, y: TOP, width: slot, height: PLOT_H + 6, fill: "var(--ink)", opacity: 0, "pointer-events": "none",
|
| 1001 |
-
}, svg);
|
| 1002 |
-
|
| 1003 |
-
const defs = el("defs", {}, svg);
|
| 1004 |
-
// -- imputed hatch, reused by every partially imputed bar. Crossed diagonals,
|
| 1005 |
-
// matching the "x" hatch matplotlib draws in the static figure; the
|
| 1006 |
-
// diagonals meet the tile corners exactly, so the grid tiles seamlessly.
|
| 1007 |
-
const pat = el("pattern", {
|
| 1008 |
-
id: "imp-hatch", width: 8, height: 8, patternUnits: "userSpaceOnUse",
|
| 1009 |
-
}, defs);
|
| 1010 |
-
el("path", {
|
| 1011 |
-
d: "M0,0 L8,8 M8,0 L0,8", stroke: "var(--paper)", "stroke-width": 1.5,
|
| 1012 |
-
opacity: 0.85, fill: "none",
|
| 1013 |
-
}, pat);
|
| 1014 |
-
|
| 1015 |
-
// -- Everything data-bearing is clipped to the plot area. The axis floor is
|
| 1016 |
-
// set from the bar values (a couple of very wide intervals would
|
| 1017 |
-
// otherwise deflate the whole scale), so a long lower CI whisker can
|
| 1018 |
-
// reach past it and run into the method names below. Clip it there; the
|
| 1019 |
-
// exact interval stays in the tooltip and the data table.
|
| 1020 |
-
const clip = el("clipPath", { id: "plot-clip" }, defs);
|
| 1021 |
-
el("rect", { x: 0, y: 0, width: plotW, height: baseY }, clip);
|
| 1022 |
-
|
| 1023 |
-
// -- bars: one concentric group per method
|
| 1024 |
-
const barsG = el("g", { "clip-path": "url(#plot-clip)" }, svg);
|
| 1025 |
-
entries.forEach((entry, i) => {
|
| 1026 |
-
const cx = i * slot + slot / 2;
|
| 1027 |
-
// Widest bar first, narrowest last: the bars are concentric, so painting
|
| 1028 |
-
// them by width guarantees each one stays visible. Ordering by height
|
| 1029 |
-
// instead loses a variant outright whenever a narrower bar is the taller
|
| 1030 |
-
// of the two (TabSTAR's tuned bar sat 1 Elo above tuned + ensembled, and
|
| 1031 |
-
// the wider bar covered it completely).
|
| 1032 |
-
const relOf = p => (VARIANT_STYLE[p.variant] || VARIANT_STYLE["Default"]).rel;
|
| 1033 |
-
const drawn = entry.points
|
| 1034 |
-
.filter(p => state.variants.has(p.variant) && p[m.key] != null)
|
| 1035 |
-
.slice()
|
| 1036 |
-
.sort((a, b) => relOf(b) - relOf(a));
|
| 1037 |
-
for (const p of drawn) {
|
| 1038 |
-
const style = VARIANT_STYLE[p.variant] || VARIANT_STYLE["Default"];
|
| 1039 |
-
const w = barUnit * style.rel;
|
| 1040 |
-
const top = Y(p[m.key]);
|
| 1041 |
-
const rect = {
|
| 1042 |
-
x: cx - w / 2, y: Math.min(top, baseY), width: w, height: Math.max(1, Math.abs(baseY - top)),
|
| 1043 |
-
};
|
| 1044 |
-
// 2px surface ring, not a border: it is what keeps a nested bar legible
|
| 1045 |
-
// against the wider bar it sits inside.
|
| 1046 |
-
el("rect", { ...rect, fill: style.color, stroke: "var(--paper)", "stroke-width": 1.5, rx: 2 }, barsG);
|
| 1047 |
-
if (p.imputed) el("rect", { ...rect, fill: "url(#imp-hatch)", rx: 2 }, barsG);
|
| 1048 |
-
if (m.ci && p[m.ci.lo] != null) {
|
| 1049 |
-
const cap = Math.max(2.5, w * 0.34);
|
| 1050 |
-
const whisk = el("g", {
|
| 1051 |
-
stroke: `color-mix(in srgb, ${style.color} 55%, var(--ink))`, "stroke-width": 1.4, opacity: 0.9,
|
| 1052 |
-
}, barsG);
|
| 1053 |
-
el("line", { x1: cx, y1: Y(p[m.ci.lo]), x2: cx, y2: Y(p[m.ci.hi]) }, whisk);
|
| 1054 |
-
el("line", { x1: cx - cap, y1: Y(p[m.ci.hi]), x2: cx + cap, y2: Y(p[m.ci.hi]) }, whisk);
|
| 1055 |
-
el("line", { x1: cx - cap, y1: Y(p[m.ci.lo]), x2: cx + cap, y2: Y(p[m.ci.lo]) }, whisk);
|
| 1056 |
-
}
|
| 1057 |
-
}
|
| 1058 |
-
});
|
| 1059 |
-
|
| 1060 |
-
// -- x axis: the method name, colored by model family (the legend below
|
| 1061 |
-
// names the colors).
|
| 1062 |
-
const xg = el("g", {}, svg);
|
| 1063 |
-
// Hairlines share one group that is painted before every name, so a name
|
| 1064 |
-
// nudged sideways at the edge (see below) passes over a neighbouring
|
| 1065 |
-
// column's hairline instead of being crossed out by it.
|
| 1066 |
-
const xLines = el("g", {}, xg);
|
| 1067 |
-
const xLabels = el("g", {}, xg);
|
| 1068 |
-
entries.forEach((entry, i) => {
|
| 1069 |
-
const cx = i * slot + slot / 2;
|
| 1070 |
-
const row = labelRows === 1 ? 0 : i % 2;
|
| 1071 |
-
const y = baseY + LABEL_TOP + row * LABEL_ROW;
|
| 1072 |
-
// A hairline drops the staggered row back to its own column.
|
| 1073 |
-
if (row) {
|
| 1074 |
-
el("line", {
|
| 1075 |
-
x1: cx, y1: baseY + 3, x2: cx, y2: y - 10,
|
| 1076 |
-
stroke: "var(--line)", "stroke-width": 1,
|
| 1077 |
-
}, xLines);
|
| 1078 |
-
}
|
| 1079 |
-
const t = el("text", {
|
| 1080 |
-
x: cx, y, "font-size": LABEL_SIZE, "text-anchor": "middle", "font-weight": 650,
|
| 1081 |
-
fill: FAM_INK[entry.family] || "var(--ink)",
|
| 1082 |
-
// A halo in the surface color keeps the glyphs legible where a nudged
|
| 1083 |
-
// name crosses a hairline, rather than the line running through them.
|
| 1084 |
-
"paint-order": "stroke", stroke: "var(--paper)", "stroke-width": 3,
|
| 1085 |
-
}, xLabels);
|
| 1086 |
-
t.textContent = labels[i];
|
| 1087 |
-
fitLabel(t, labels[i], labelWidths[i], slot * labelRows - 8);
|
| 1088 |
-
// The outermost columns sit only half a slot from the edge, so a name
|
| 1089 |
-
// wider than one slot would reach past the SVG viewport and be cut off
|
| 1090 |
-
// there (a name may occupy two slots when the rows are staggered). Nudge
|
| 1091 |
-
// it inwards by just enough to stay whole; every other label keeps its
|
| 1092 |
-
// column centre, and the bar below still marks the column.
|
| 1093 |
-
const half = t.getComputedTextLength() / 2;
|
| 1094 |
-
t.setAttribute("x", Math.max(half + 1, Math.min(cx, plotW - half - 1)));
|
| 1095 |
-
});
|
| 1096 |
-
|
| 1097 |
-
// -- reference pipelines as threshold lines. Their names live in the legend
|
| 1098 |
-
// (matched by dash pattern) rather than on the line, where they would
|
| 1099 |
-
// cover the tallest bars at every scroll position.
|
| 1100 |
-
const refG = el("g", {}, svg);
|
| 1101 |
-
const tagYs = [];
|
| 1102 |
-
shownRefs.forEach((r, i) => {
|
| 1103 |
-
const ry = Y(r[state.metric]);
|
| 1104 |
-
if (ry < TOP || ry > baseY) return;
|
| 1105 |
-
el("line", {
|
| 1106 |
-
x1: 0, y1: ry, x2: plotW, y2: ry, stroke: "var(--fam-reference)", "stroke-width": 1.8,
|
| 1107 |
-
"stroke-dasharray": REF_DASHES[i % REF_DASHES.length], opacity: 0.95,
|
| 1108 |
-
}, refG);
|
| 1109 |
-
// Sticky value tag in the axis pane, so the threshold stays readable at
|
| 1110 |
-
// any scroll position. Two nearby thresholds would print on top of each
|
| 1111 |
-
// other, so nudge each tag clear of the ones already placed; a tag wins
|
| 1112 |
-
// over a tick label it would sit on.
|
| 1113 |
-
let ty = ry;
|
| 1114 |
-
while (tagYs.some(y => Math.abs(y - ty) < 12)) ty += 12;
|
| 1115 |
-
tagYs.push(ty);
|
| 1116 |
-
for (const t of tickLabels) {
|
| 1117 |
-
if (Math.abs(t.y - ty) < 10) t.node.remove();
|
| 1118 |
-
}
|
| 1119 |
-
el("text", {
|
| 1120 |
-
x: AXIS_W - 10, y: ty + 4, "text-anchor": "end", "font-size": 11, "font-weight": 650,
|
| 1121 |
-
fill: "var(--fam-reference)",
|
| 1122 |
-
}, axisSvg).textContent = fmtMetric(m, r[state.metric]);
|
| 1123 |
-
});
|
| 1124 |
-
buildLegend(m, shownRefs);
|
| 1125 |
-
|
| 1126 |
-
// -- hit targets: one full-height column per method (>= 34px wide)
|
| 1127 |
-
const hits = el("g", {}, svg);
|
| 1128 |
-
entries.forEach((entry, i) => {
|
| 1129 |
-
const h = el("rect", {
|
| 1130 |
-
x: i * slot, y: TOP, width: slot, height: PLOT_H + 6, fill: "transparent", cursor: "pointer",
|
| 1131 |
-
}, hits);
|
| 1132 |
-
h.addEventListener("mouseenter", ev => {
|
| 1133 |
-
band.setAttribute("x", i * slot);
|
| 1134 |
-
band.setAttribute("opacity", 0.06);
|
| 1135 |
-
showTip(entry, ev);
|
| 1136 |
-
});
|
| 1137 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1138 |
-
h.addEventListener("mouseleave", () => { band.setAttribute("opacity", 0); tip.hide(); });
|
| 1139 |
-
h.addEventListener("click", () => toggleMethod(entry.method));
|
| 1140 |
-
});
|
| 1141 |
-
|
| 1142 |
-
postHeight();
|
| 1143 |
-
}
|
| 1144 |
-
|
| 1145 |
-
function showTip(entry, ev) {
|
| 1146 |
-
const m = metric();
|
| 1147 |
-
let html = `<div class="t-name">${entry.method}</div><div>${entry.family}</div>`;
|
| 1148 |
-
for (const p of entry.points) {
|
| 1149 |
-
if (!state.variants.has(p.variant) || p[m.key] == null) continue;
|
| 1150 |
-
const ci = m.ci && p[m.ci.lo] != null
|
| 1151 |
-
? ` <span class="t-var">(${fmtNum(p[m.ci.lo], m.decimals)}–${fmtNum(p[m.ci.hi], m.decimals)})</span>`
|
| 1152 |
-
: "";
|
| 1153 |
-
html += `<div><span class="t-var">${p.variant}:</span> <b>${fmtMetric(m, p[m.key])}</b>${ci}</div>`;
|
| 1154 |
-
}
|
| 1155 |
-
if (entry.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(entry.imputed_pct, 0)}% of datasets</div>`;
|
| 1156 |
-
tip.show(html, ev);
|
| 1157 |
-
}
|
| 1158 |
-
|
| 1159 |
-
// ---------- chips ----------
|
| 1160 |
-
const chipsBox = document.getElementById("chips");
|
| 1161 |
-
const chipByMethod = new Map();
|
| 1162 |
-
const famChips = new Map();
|
| 1163 |
-
|
| 1164 |
-
function familyMembers(fam) {
|
| 1165 |
-
const out = [...byMethod.values()].filter(e => e.family === fam).map(e => e.method);
|
| 1166 |
-
for (const r of refs) if (r.family === fam) out.push(r.method);
|
| 1167 |
-
return out;
|
| 1168 |
-
}
|
| 1169 |
-
function isOn(name) { return state.methods.has(name) || state.refs.has(name); }
|
| 1170 |
-
|
| 1171 |
-
function buildChips() {
|
| 1172 |
-
const rankMetric = metricByKey[CONFIG.rankMetric] || METRICS[0];
|
| 1173 |
-
const head = document.createElement("div");
|
| 1174 |
-
head.className = "chips-head";
|
| 1175 |
-
head.textContent = "Methods shown — click to remove, click a family to toggle the whole group";
|
| 1176 |
-
chipsBox.appendChild(head);
|
| 1177 |
-
for (const fam of FAM_ORDER) {
|
| 1178 |
-
const members = familyMembers(fam);
|
| 1179 |
-
if (!members.length) continue;
|
| 1180 |
-
members.sort((a, b) => chipRank(a, rankMetric) - chipRank(b, rankMetric));
|
| 1181 |
-
const row = document.createElement("div");
|
| 1182 |
-
row.className = "chiprow";
|
| 1183 |
-
const famBtn = document.createElement("button");
|
| 1184 |
-
famBtn.className = "famchip";
|
| 1185 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1186 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1187 |
-
famBtn.title = `Toggle all ${members.length} ${fam} methods`;
|
| 1188 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1189 |
-
row.appendChild(famBtn);
|
| 1190 |
-
famChips.set(fam, famBtn);
|
| 1191 |
-
const set = document.createElement("div");
|
| 1192 |
-
set.className = "chipset";
|
| 1193 |
-
for (const name of members) {
|
| 1194 |
-
const entry = byMethod.get(name);
|
| 1195 |
-
const b = document.createElement("button");
|
| 1196 |
-
b.className = "chip";
|
| 1197 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1198 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1199 |
-
b.appendChild(Object.assign(document.createElement("span"), { textContent: name }));
|
| 1200 |
-
if (entry && entry.imputed) {
|
| 1201 |
-
const mark = document.createElement("span");
|
| 1202 |
-
mark.className = "imp-mark";
|
| 1203 |
-
mark.textContent = "‡";
|
| 1204 |
-
b.appendChild(mark);
|
| 1205 |
-
}
|
| 1206 |
-
b.title = name + (entry && entry.imputed ? " — partially imputed" : "");
|
| 1207 |
-
b.addEventListener("click", () => toggleMethod(name));
|
| 1208 |
-
set.appendChild(b);
|
| 1209 |
-
chipByMethod.set(name, b);
|
| 1210 |
-
}
|
| 1211 |
-
row.appendChild(set);
|
| 1212 |
-
chipsBox.appendChild(row);
|
| 1213 |
-
}
|
| 1214 |
-
}
|
| 1215 |
-
function chipRank(name, m) {
|
| 1216 |
-
const entry = byMethod.get(name);
|
| 1217 |
-
if (entry) return rankVal(entry, m);
|
| 1218 |
-
const r = refs.find(x => x.method === name);
|
| 1219 |
-
const v = r ? r[m.key] : null;
|
| 1220 |
-
return v == null ? Infinity : (m.lowerBetter ? v : -v);
|
| 1221 |
-
}
|
| 1222 |
-
function syncChips() {
|
| 1223 |
-
for (const [name, b] of chipByMethod) b.setAttribute("aria-pressed", String(isOn(name)));
|
| 1224 |
-
for (const [fam, b] of famChips) b.setAttribute("aria-pressed", String(familyMembers(fam).every(isOn)));
|
| 1225 |
-
}
|
| 1226 |
-
|
| 1227 |
-
function toggleMethod(name) {
|
| 1228 |
-
const set = byMethod.has(name) ? state.methods : state.refs;
|
| 1229 |
-
if (set.has(name)) set.delete(name); else set.add(name);
|
| 1230 |
-
syncChips();
|
| 1231 |
-
render();
|
| 1232 |
-
}
|
| 1233 |
-
function toggleFamily(fam) {
|
| 1234 |
-
const members = familyMembers(fam);
|
| 1235 |
-
const allOn = members.every(isOn);
|
| 1236 |
-
for (const name of members) {
|
| 1237 |
-
const set = byMethod.has(name) ? state.methods : state.refs;
|
| 1238 |
-
if (allOn) set.delete(name); else set.add(name);
|
| 1239 |
-
}
|
| 1240 |
-
syncChips();
|
| 1241 |
-
render();
|
| 1242 |
-
}
|
| 1243 |
-
function setMethods(names) {
|
| 1244 |
-
state.methods = new Set(names);
|
| 1245 |
-
syncChips();
|
| 1246 |
-
render();
|
| 1247 |
-
}
|
| 1248 |
-
|
| 1249 |
-
document.getElementById("btn-all").addEventListener("click", () => {
|
| 1250 |
-
state.refs = new Set(refs.map(r => r.method));
|
| 1251 |
-
setMethods(byMethod.keys());
|
| 1252 |
-
});
|
| 1253 |
-
document.getElementById("btn-none").addEventListener("click", () => {
|
| 1254 |
-
state.refs = new Set();
|
| 1255 |
-
setMethods([]);
|
| 1256 |
-
});
|
| 1257 |
-
document.getElementById("btn-top").addEventListener("click", () => {
|
| 1258 |
-
const m = metric();
|
| 1259 |
-
// Rank explicitly rather than reusing the display sort: which 15 methods are
|
| 1260 |
-
// kept must not depend on which end of the axis the best ones are drawn at
|
| 1261 |
-
// (sorting "best on the right" would otherwise select the 15 worst).
|
| 1262 |
-
const top = [...byMethod.values()]
|
| 1263 |
-
.sort((a, b) => rankVal(a, m) - rankVal(b, m))
|
| 1264 |
-
.slice(0, 15)
|
| 1265 |
-
.map(e => e.method);
|
| 1266 |
-
state.refs = new Set(refs.map(r => r.method));
|
| 1267 |
-
setMethods(top);
|
| 1268 |
-
});
|
| 1269 |
-
|
| 1270 |
-
// ---------- selectors ----------
|
| 1271 |
-
yminRange.addEventListener("input", ev => {
|
| 1272 |
-
state.yMin = Number(ev.target.value);
|
| 1273 |
-
render();
|
| 1274 |
-
});
|
| 1275 |
-
|
| 1276 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1277 |
-
for (const m of METRICS) {
|
| 1278 |
-
metricSelect.appendChild(Object.assign(document.createElement("option"), { value: m.key, textContent: m.label }));
|
| 1279 |
-
}
|
| 1280 |
-
metricSelect.addEventListener("change", ev => {
|
| 1281 |
-
state.metric = ev.target.value;
|
| 1282 |
-
state.yMin = null; // the previous floor means nothing on a new scale
|
| 1283 |
-
buildTable();
|
| 1284 |
-
render();
|
| 1285 |
-
});
|
| 1286 |
-
|
| 1287 |
-
const sortSelect = document.getElementById("sort-select");
|
| 1288 |
-
for (const [value, label] of [
|
| 1289 |
-
["best", "Best on the left"], ["worst", "Best on the right"],
|
| 1290 |
-
["family", "Model family"], ["name", "A–Z"],
|
| 1291 |
-
]) {
|
| 1292 |
-
sortSelect.appendChild(Object.assign(document.createElement("option"), { value, textContent: label }));
|
| 1293 |
-
}
|
| 1294 |
-
sortSelect.value = state.sort;
|
| 1295 |
-
sortSelect.addEventListener("change", ev => { state.sort = ev.target.value; render(); });
|
| 1296 |
-
|
| 1297 |
-
// Variant toggles: buttons rather than chips, since they filter the series
|
| 1298 |
-
// rather than the rows. "Default" gets no button at all — every method has a
|
| 1299 |
-
// default result, so it is the baseline of the chart rather than an option
|
| 1300 |
-
// (switching it off would leave the default-only methods with no bar). Only
|
| 1301 |
-
// the extras layered on top, tuning and ensembling, are toggleable; the legend
|
| 1302 |
-
// still carries Default's color.
|
| 1303 |
-
const ALWAYS_SHOWN = "Default";
|
| 1304 |
-
const variantBtns = document.getElementById("variant-btns");
|
| 1305 |
-
const variantBtnByKey = new Map();
|
| 1306 |
-
for (const v of VARIANT_ORDER) {
|
| 1307 |
-
if (v === ALWAYS_SHOWN || !POINTS.some(p => p.variant === v)) continue;
|
| 1308 |
-
const b = document.createElement("button");
|
| 1309 |
-
b.className = "btn";
|
| 1310 |
-
b.textContent = v === "Tuned + Ens." ? "Tuned + Ensembled" : v;
|
| 1311 |
-
b.style.setProperty("--fam", VARIANT_STYLE[v].color);
|
| 1312 |
-
b.title = `Show or hide the ${b.textContent.toLowerCase()} bars`;
|
| 1313 |
-
b.addEventListener("click", () => {
|
| 1314 |
-
if (state.variants.has(v)) state.variants.delete(v);
|
| 1315 |
-
else state.variants.add(v);
|
| 1316 |
-
syncVariantBtns();
|
| 1317 |
-
render();
|
| 1318 |
-
});
|
| 1319 |
-
variantBtns.appendChild(b);
|
| 1320 |
-
variantBtnByKey.set(v, b);
|
| 1321 |
-
}
|
| 1322 |
-
function syncVariantBtns() {
|
| 1323 |
-
for (const [v, b] of variantBtnByKey) {
|
| 1324 |
-
const on = state.variants.has(v);
|
| 1325 |
-
b.setAttribute("aria-pressed", String(on));
|
| 1326 |
-
b.style.opacity = on ? "1" : "0.45";
|
| 1327 |
-
b.style.borderColor = on ? VARIANT_STYLE[v].color : "var(--line)";
|
| 1328 |
-
}
|
| 1329 |
-
}
|
| 1330 |
-
|
| 1331 |
-
// ---------- legend ----------
|
| 1332 |
-
// Rebuilt on every render: it names the reference lines (each by its dash
|
| 1333 |
-
// pattern and current value), which change with the metric and the selection.
|
| 1334 |
-
function buildLegend(m, shownRefs) {
|
| 1335 |
-
const parts = [];
|
| 1336 |
-
for (const v of VARIANT_ORDER) {
|
| 1337 |
-
if (!POINTS.some(p => p.variant === v)) continue;
|
| 1338 |
-
const label = v === "Tuned + Ens." ? "Tuned + Ensembled" : v;
|
| 1339 |
-
const off = state.variants.has(v) ? "" : ' style="opacity:0.4"';
|
| 1340 |
-
parts.push(
|
| 1341 |
-
`<span class="item"${off}><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1342 |
-
`<rect x="1" y="1" width="10" height="10" rx="2" fill="${VARIANT_STYLE[v].color}"/></svg> ${label}</span>`);
|
| 1343 |
-
}
|
| 1344 |
-
if (m.ci) {
|
| 1345 |
-
parts.push('<span class="item"><svg width="12" height="14" viewBox="0 0 12 14">' +
|
| 1346 |
-
'<path d="M6,2 V12 M2,2 H10 M2,12 H10" stroke="var(--muted)" stroke-width="1.4" fill="none"/></svg> 95% CI</span>');
|
| 1347 |
-
}
|
| 1348 |
-
shownRefs.forEach((r, i) => {
|
| 1349 |
-
parts.push(`<span class="item"><svg width="26" height="8" viewBox="0 0 26 8">` +
|
| 1350 |
-
`<line x1="0" y1="4" x2="26" y2="4" stroke="var(--fam-reference)" stroke-width="1.8" ` +
|
| 1351 |
-
`stroke-dasharray="${REF_DASHES[i % REF_DASHES.length]}"/></svg> ${r.method} · ${fmtMetric(m, r[state.metric])}</span>`);
|
| 1352 |
-
});
|
| 1353 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1354 |
-
parts.push('<span class="item"><svg width="14" height="14" viewBox="0 0 14 14">' +
|
| 1355 |
-
'<rect x="1" y="1" width="12" height="12" rx="2" fill="var(--pt-muted)"/>' +
|
| 1356 |
-
'<path d="M1,1 L7,7 M7,1 L1,7 M7,7 L13,13 M13,7 L7,13 M1,7 L7,13 M7,7 L13,1" ' +
|
| 1357 |
-
'stroke="var(--paper)" stroke-width="1.5" fill="none"/>' +
|
| 1358 |
-
"</svg> ‡ partially imputed</span>");
|
| 1359 |
-
}
|
| 1360 |
-
// Model family, named rather than merely pointed at: without the colors
|
| 1361 |
-
// spelled out, the swatch under each column decodes to nothing.
|
| 1362 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => !p.reference && p.family === f));
|
| 1363 |
-
if (families.length > 1) {
|
| 1364 |
-
parts.push('<span class="legendbreak"></span><span class="item">Family:</span>');
|
| 1365 |
-
for (const fam of families) {
|
| 1366 |
-
parts.push(`<span class="item"><svg width="16" height="9" viewBox="0 0 16 9">` +
|
| 1367 |
-
`<rect x="0" y="1" width="16" height="7" rx="2" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1368 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`);
|
| 1369 |
-
}
|
| 1370 |
-
}
|
| 1371 |
-
document.getElementById("legendstrip").innerHTML = parts.join("");
|
| 1372 |
-
}
|
| 1373 |
-
|
| 1374 |
-
// ---------- data table (the WCAG-clean twin of the chart) ----------
|
| 1375 |
-
function buildTable() {
|
| 1376 |
-
const m = metric();
|
| 1377 |
-
const rows = [...POINTS].filter(p => p[m.key] != null).sort((a, b) =>
|
| 1378 |
-
m.lowerBetter ? a[m.key] - b[m.key] : b[m.key] - a[m.key]);
|
| 1379 |
-
let html = "<table><thead><tr><th>Method</th><th>Variant</th><th>Family</th>";
|
| 1380 |
-
for (const x of METRICS) html += `<th>${x.label}</th>`;
|
| 1381 |
-
html += "<th>Imputed</th></tr></thead><tbody>";
|
| 1382 |
-
for (const p of rows) {
|
| 1383 |
-
html += `<tr><td>${p.method}</td><td>${p.variant || "—"}</td><td>${p.family}</td>`;
|
| 1384 |
-
for (const x of METRICS) html += `<td>${fmtMetric(x, p[x.key])}</td>`;
|
| 1385 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1386 |
-
}
|
| 1387 |
-
document.getElementById("tblwrap").innerHTML = html + "</tbody></table>";
|
| 1388 |
-
}
|
| 1389 |
-
|
| 1390 |
-
// ---------- paper view ----------
|
| 1391 |
-
setUpPaperView(render);
|
| 1392 |
-
// The y-axis lives in its own pane, so it is offset back into place.
|
| 1393 |
-
setUpExport(() => [{ svg: axisSvg, dx: 0 }, { svg: svg, dx: AXIS_W }], () => slugify(document.title));
|
| 1394 |
-
|
| 1395 |
-
// ---------- boot ----------
|
| 1396 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1397 |
-
let resizeTimer = null;
|
| 1398 |
-
window.addEventListener("resize", () => {
|
| 1399 |
-
clearTimeout(resizeTimer);
|
| 1400 |
-
resizeTimer = setTimeout(render, 120);
|
| 1401 |
-
});
|
| 1402 |
-
|
| 1403 |
-
buildChips();
|
| 1404 |
-
buildTable();
|
| 1405 |
-
syncChips();
|
| 1406 |
-
syncVariantBtns();
|
| 1407 |
-
render(); // also builds the legend (it depends on the metric + selection)
|
| 1408 |
-
})();
|
| 1409 |
-
</script>
|
| 1410 |
-
</body>
|
| 1411 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/leaderboard_table.html
DELETED
|
@@ -1,1162 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena leaderboard table — no imputation | All Tasks | All Datasets</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* --- The table ------------------------------------------------------------
|
| 269 |
-
A scroll box with a sticky header, so the column names stay put through 80
|
| 270 |
-
rows. Numbers are tabular so digits line up down a column. */
|
| 271 |
-
.lbt-scroll {
|
| 272 |
-
overflow: auto; max-height: 720px; margin-top: 4px;
|
| 273 |
-
border: 1px solid var(--line); border-radius: 10px;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.lbt-scroll::-webkit-scrollbar { width: 11px; height: 11px; }
|
| 277 |
-
.lbt-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
table.lbt { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
|
| 282 |
-
table.lbt th, table.lbt td { padding: 5px 9px; text-align: center; border: 1px solid var(--line); }
|
| 283 |
-
table.lbt thead th {
|
| 284 |
-
position: sticky; top: 0; z-index: 3; background: var(--card); font-size: 12px;
|
| 285 |
-
font-weight: 650; white-space: nowrap; cursor: pointer; user-select: none;
|
| 286 |
-
box-shadow: inset 0 -1px 0 var(--line);
|
| 287 |
-
}
|
| 288 |
-
/* The header is both the sort control and the definition, so it gets the
|
| 289 |
-
pointer of the former and the dotted underline of the latter. */
|
| 290 |
-
table.lbt thead th .lbl { text-decoration: underline; text-decoration-style: dotted;
|
| 291 |
-
text-decoration-color: var(--muted); text-underline-offset: 3px; }
|
| 292 |
-
table.lbt thead th:hover { color: var(--accent); }
|
| 293 |
-
table.lbt thead th::after { content: "\2195"; font-size: 0.72em; opacity: 0.3; margin-left: 5px; }
|
| 294 |
-
table.lbt thead th[aria-sort="ascending"]::after { content: "\25B2"; opacity: 0.85; }
|
| 295 |
-
table.lbt thead th[aria-sort="descending"]::after { content: "\25BC"; opacity: 0.85; }
|
| 296 |
-
table.lbt td.name { text-align: left; white-space: nowrap; }
|
| 297 |
-
table.lbt td.pos { color: var(--muted); font-variant-numeric: tabular-nums; }
|
| 298 |
-
table.lbt td.type { white-space: nowrap; width: 1%; }
|
| 299 |
-
table.lbt td.num { font-weight: 600; }
|
| 300 |
-
table.lbt td.na { color: var(--pt-muted); }
|
| 301 |
-
table.lbt tbody tr:hover td { filter: brightness(1.12); }
|
| 302 |
-
.ci { opacity: 0.5; font-weight: 400; font-size: 0.82em; }
|
| 303 |
-
.pill { padding: 1px 7px; border-radius: 999px; font-size: 0.95em; white-space: nowrap; }
|
| 304 |
-
.verified { font-size: 0.85em; }
|
| 305 |
-
.link-icon { font-size: 0.78em; opacity: 0.65; margin-left: 2px; }
|
| 306 |
-
/* Grey rather than a dimmed inherit: dimming leaves the tag tinted with the
|
| 307 |
-
family colour, which the model name already carries, and made this table
|
| 308 |
-
disagree with the cross-subset table on the app page. */
|
| 309 |
-
.variant-tag { color: var(--muted); font-weight: 400; font-size: 0.9em; }
|
| 310 |
-
td.name .imp-mark { color: var(--muted); font-weight: 700; margin-left: 3px; }
|
| 311 |
-
td.name a { text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }
|
| 312 |
-
td.name a:hover { text-decoration-style: solid; }
|
| 313 |
-
|
| 314 |
-
.lbt-search {
|
| 315 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 316 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 317 |
-
padding: 6px 9px; width: 12em;
|
| 318 |
-
}
|
| 319 |
-
.lbt-cap { font-size: 12.5px; color: var(--muted); margin: 7px 0 0; }
|
| 320 |
-
.lbt-empty { padding: 34px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 321 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 322 |
-
/* The model selector sits above the table it filters. Families pack side by
|
| 323 |
-
side rather than stacking: one row each would leave the small ones (Baseline,
|
| 324 |
-
Other) wasting a line. */
|
| 325 |
-
.chips { margin: 2px 0 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 326 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 327 |
-
|
| 328 |
-
/* The data export, in the same green the website's figure-export controls use,
|
| 329 |
-
so "this downloads something" reads the same across the site. */
|
| 330 |
-
.btn.export {
|
| 331 |
-
color: #063; background: #7ee0b8; border-color: #7ee0b8; font-weight: 700;
|
| 332 |
-
}
|
| 333 |
-
.btn.export:hover { background: #a6efcd; border-color: #a6efcd; }
|
| 334 |
-
/* Paper view keeps the table: here the table *is* the figure. */
|
| 335 |
-
body.paper .lbt-scroll { max-height: none; }
|
| 336 |
-
</style>
|
| 337 |
-
</head>
|
| 338 |
-
<body>
|
| 339 |
-
<div class="viewbar">
|
| 340 |
-
<button class="btn" id="btn-paper" title="White background, table only — for slides and papers">Paper view</button>
|
| 341 |
-
</div>
|
| 342 |
-
<p class="explorer-title" id="title"></p>
|
| 343 |
-
<div class="controls">
|
| 344 |
-
<span class="grouplabel">Variants</span>
|
| 345 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 346 |
-
<button class="btn" id="btn-imputed" title="Models whose score is partly imputed, marked ‡"></button>
|
| 347 |
-
<input class="lbt-search" id="search" type="search" placeholder="Search model or family" aria-label="Search">
|
| 348 |
-
<span class="grouplabel">Columns</span>
|
| 349 |
-
<div class="btnrow" id="col-btns"></div>
|
| 350 |
-
<button class="btn export" id="btn-csv" title="Download the rows and columns shown, in the current sort order">Download CSV</button>
|
| 351 |
-
</div>
|
| 352 |
-
<!-- The shared paper-view helper reveals this bar; a table has no figure to
|
| 353 |
-
export as SVG/PNG/PDF, and its CSV button belongs beside the filters that
|
| 354 |
-
shape the export, so it stays empty here. -->
|
| 355 |
-
<div class="exportbar" id="exportbar" hidden></div>
|
| 356 |
-
<!-- The model selector belongs above the table it filters. It doubles as the
|
| 357 |
-
family key, which is why there is no separate legend strip. -->
|
| 358 |
-
<div class="chips" id="chips"></div>
|
| 359 |
-
<div class="lbt-scroll" id="tblwrap"></div>
|
| 360 |
-
<p class="lbt-cap" id="caption"></p>
|
| 361 |
-
|
| 362 |
-
<script>
|
| 363 |
-
(function () {
|
| 364 |
-
"use strict";
|
| 365 |
-
const CONFIG = {"title": null, "columns": [{"key": "position", "label": "#", "always": true, "hint": "Position in this subset's published ranking."}, {"key": "family", "label": "Type", "always": true, "hint": "Model family \u2014 see the key above the table."}, {"key": "model", "label": "Model", "always": true, "hint": "The model, its tuning variant in brackets, \u2714\ufe0f when the implementation was verified, and \u2021 when some results are imputed."}, {"key": "elo", "label": "Elo", "decimals": 0, "heatmap": true, "hint": "Pairwise win-rate rating; a 400-point gap is about a 91% win rate. Higher is better."}, {"key": "score", "label": "Score", "decimals": 3, "heatmap": true, "hint": "Error rescaled per dataset to 1 (best) \u2026 0 (median), then averaged. Higher is better."}, {"key": "rank", "label": "Rank", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "Mean rank across datasets. Lower is better."}, {"key": "hrank", "label": "Harmonic rank", "short": "H. rank", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "Harmonic mean of per-dataset ranks; rewards being excellent somewhere. Lower is better."}, {"key": "imp", "label": "Improvability (%)", "short": "Improv.", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "How much lower the best model's error is than this one's, per dataset. Lower is better."}, {"key": "train_time", "label": "Train time (s/1K)", "short": "Train s", "decimals": 2, "lowerBetter": true, "heatmap": true, "logScale": true, "hint": "Median seconds to fit per 1000 rows. Lower is better; shaded on a log scale."}, {"key": "predict_time", "label": "Predict time (s/1K)", "short": "Predict s", "decimals": 3, "lowerBetter": true, "heatmap": true, "logScale": true, "hint": "Median seconds to predict per 1000 rows. Lower is better; shaded on a log scale."}, {"key": "imputed_pct", "label": "Imputed (%)", "short": "Imputed", "decimals": 1, "lowerBetter": true, "heatmap": true, "hint": "Share of datasets whose score was imputed because the model could not run on them."}, {"key": "hardware", "label": "Hardware", "text": true, "hint": "The hardware the reported runtimes were measured on."}], "rankKey": "elo", "variants": ["Default", "Tuned", "Tuned + Ens."]};
|
| 366 |
-
const POINTS = [{"position":0,"method":"TabFM","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/google-research\/tabfm","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1792.0,"score":0.889,"rank":6.17,"hrank":1.72,"imp":4.074,"train_time":38.81,"predict_time":6.985,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+115\/-110","imputed":false},{"position":1,"method":"AutoGluon 1.5 (extreme, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83d\udcca","verified":true,"elo":1691.0,"score":0.662,"rank":9.39,"hrank":4.03,"imp":7.979,"train_time":289.07,"predict_time":4.031,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+82\/-68","imputed":false},{"position":2,"method":"TabPFN-3","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2605.13986","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1665.0,"score":0.67,"rank":10.41,"hrank":4.06,"imp":9.328,"train_time":3.66,"predict_time":0.399,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+80\/-61","imputed":false},{"position":3,"method":"TabPFN-2.6","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1620.0,"score":0.583,"rank":12.42,"hrank":7.14,"imp":10.751,"train_time":5.48,"predict_time":0.555,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+71\/-51","imputed":false},{"position":4,"method":"RealTabPFN-2.5","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1595.0,"score":0.549,"rank":13.64,"hrank":6.22,"imp":10.427,"train_time":2040.22,"predict_time":8.908,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+74\/-56","imputed":false},{"position":5,"method":"TabICLv2","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2602.11139","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1594.0,"score":0.606,"rank":13.71,"hrank":4.97,"imp":10.175,"train_time":2.05,"predict_time":0.151,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+73\/-61","imputed":false},{"position":6,"method":"RealTabPFN-2.5","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1554.0,"score":0.504,"rank":15.81,"hrank":7.33,"imp":11.116,"train_time":2040.22,"predict_time":1.218,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+65\/-55","imputed":false},{"position":7,"method":"RealTabPFN-2.5","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1524.0,"score":0.474,"rank":17.55,"hrank":9.62,"imp":11.66,"train_time":5.81,"predict_time":0.645,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+62\/-44","imputed":false},{"position":8,"method":"AutoGluon 1.4 (best, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83d\udcca","verified":true,"elo":1514.0,"score":0.401,"rank":18.2,"hrank":8.44,"imp":12.789,"train_time":1735.72,"predict_time":2.558,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+53\/-46","imputed":false},{"position":9,"method":"RealMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1508.0,"score":0.405,"rank":18.55,"hrank":11.52,"imp":12.881,"train_time":2950.72,"predict_time":11.975,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+54\/-46","imputed":false},{"position":10,"method":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","url":"https:\/\/openreview.net\/pdf?id=Y00pwFyrHR","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1459.0,"score":0.38,"rank":21.7,"hrank":9.59,"imp":14.0,"train_time":2.07,"predict_time":0.182,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+55\/-51","imputed":false},{"position":11,"method":"TabDPT","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1458.0,"score":0.375,"rank":21.81,"hrank":8.16,"imp":13.788,"train_time":4910.38,"predict_time":286.537,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+60\/-51","imputed":false},{"position":12,"method":"TabM","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1450.0,"score":0.315,"rank":22.33,"hrank":12.48,"imp":14.081,"train_time":2450.13,"predict_time":2.247,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+52\/-43","imputed":false},{"position":13,"method":"LightGBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1433.0,"score":0.262,"rank":23.53,"hrank":17.2,"imp":15.033,"train_time":417.05,"predict_time":2.639,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+33\/-31","imputed":false},{"position":14,"method":"RealMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1426.0,"score":0.295,"rank":23.99,"hrank":13.67,"imp":14.202,"train_time":2950.72,"predict_time":0.663,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+48\/-45","imputed":false},{"position":15,"method":"CatBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1422.0,"score":0.261,"rank":24.34,"hrank":14.77,"imp":14.656,"train_time":1346.21,"predict_time":0.344,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+39\/-38","imputed":false},{"position":16,"method":"CatBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1408.0,"score":0.245,"rank":25.3,"hrank":15.31,"imp":14.885,"train_time":1346.21,"predict_time":0.038,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+38\/-43","imputed":false},{"position":17,"method":"iLTM","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1404.0,"score":0.235,"rank":25.56,"hrank":17.78,"imp":15.304,"train_time":12685.08,"predict_time":464.37,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+40\/-42","imputed":false},{"position":18,"method":"TabDPT","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1403.0,"score":0.316,"rank":25.69,"hrank":11.3,"imp":14.936,"train_time":4910.38,"predict_time":39.96,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+59\/-56","imputed":false},{"position":19,"method":"TabM","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1394.0,"score":0.251,"rank":26.35,"hrank":14.47,"imp":14.952,"train_time":2450.13,"predict_time":0.251,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+48\/-42","imputed":false},{"position":20,"method":"ModernNCA","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1389.0,"score":0.277,"rank":26.66,"hrank":12.79,"imp":15.599,"train_time":4621.67,"predict_time":8.138,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+73\/-52","imputed":false},{"position":21,"method":"LightGBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1386.0,"score":0.194,"rank":26.93,"hrank":20.71,"imp":15.688,"train_time":417.05,"predict_time":0.334,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+29\/-29","imputed":false},{"position":22,"method":"CatBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1378.0,"score":0.224,"rank":27.47,"hrank":16.11,"imp":15.524,"train_time":5.88,"predict_time":0.025,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+40\/-42","imputed":false},{"position":23,"method":"XGBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1375.0,"score":0.198,"rank":27.73,"hrank":19.98,"imp":15.754,"train_time":693.49,"predict_time":1.689,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+31\/-33","imputed":false},{"position":24,"method":"LimiX","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2509.03505","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1363.0,"score":0.299,"rank":28.66,"hrank":9.55,"imp":15.526,"train_time":26.46,"predict_time":6.242,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+78\/-59","imputed":false},{"position":25,"method":"ModernNCA","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1355.0,"score":0.189,"rank":29.21,"hrank":16.82,"imp":16.044,"train_time":4621.67,"predict_time":0.475,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+37\/-37","imputed":false},{"position":26,"method":"TabSwift","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/LAMDA-Tabular\/TabSwift","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1350.0,"score":0.251,"rank":29.58,"hrank":17.68,"imp":16.081,"train_time":1.18,"predict_time":0.072,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+58\/-52","imputed":false},{"position":27,"method":"XGBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1350.0,"score":0.16,"rank":29.6,"hrank":22.22,"imp":16.065,"train_time":693.49,"predict_time":0.308,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+29\/-32","imputed":false},{"position":28,"method":"xRFM","variant":"Tuned + Ens.","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1348.0,"score":0.209,"rank":29.79,"hrank":18.96,"imp":16.284,"train_time":846.89,"predict_time":2.549,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+49\/-43","imputed":false},{"position":29,"method":"ChimeraBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1333.0,"score":0.186,"rank":30.87,"hrank":19.34,"imp":17.213,"train_time":427.39,"predict_time":0.404,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+46\/-60","imputed":false},{"position":30,"method":"TabDPT","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1325.0,"score":0.245,"rank":31.53,"hrank":14.33,"imp":17.225,"train_time":47.65,"predict_time":43.738,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+64\/-55","imputed":false},{"position":31,"method":"ChimeraBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1308.0,"score":0.156,"rank":32.79,"hrank":21.32,"imp":17.551,"train_time":427.39,"predict_time":0.034,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+44\/-60","imputed":false},{"position":32,"method":"xRFM","variant":"Tuned","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1300.0,"score":0.158,"rank":33.43,"hrank":22.28,"imp":17.449,"train_time":846.89,"predict_time":0.13,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+45\/-39","imputed":false},{"position":33,"method":"TabM","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1298.0,"score":0.161,"rank":33.63,"hrank":21.84,"imp":17.0,"train_time":7.49,"predict_time":0.244,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+47\/-44","imputed":false},{"position":34,"method":"iLTM","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1295.0,"score":0.111,"rank":33.83,"hrank":23.47,"imp":17.147,"train_time":12685.08,"predict_time":62.13,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+40\/-33","imputed":false},{"position":35,"method":"TorchMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1285.0,"score":0.126,"rank":34.58,"hrank":25.37,"imp":17.161,"train_time":2875.52,"predict_time":1.952,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+48\/-47","imputed":false},{"position":36,"method":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2506.10707","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1283.0,"score":0.194,"rank":34.72,"hrank":14.11,"imp":18.278,"train_time":14.11,"predict_time":2.075,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+57\/-55","imputed":false},{"position":37,"method":"EBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1272.0,"score":0.116,"rank":35.64,"hrank":25.8,"imp":18.672,"train_time":1711.25,"predict_time":0.141,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+40\/-40","imputed":false},{"position":38,"method":"ChimeraBoost","variant":"Default","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1264.0,"score":0.121,"rank":36.23,"hrank":23.23,"imp":18.657,"train_time":1.99,"predict_time":0.033,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+47\/-55","imputed":false},{"position":39,"method":"ModernNCA","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1248.0,"score":0.09,"rank":37.44,"hrank":23.68,"imp":19.194,"train_time":14.87,"predict_time":0.307,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+41\/-39","imputed":false},{"position":40,"method":"EBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1235.0,"score":0.082,"rank":38.43,"hrank":28.17,"imp":19.314,"train_time":1711.25,"predict_time":0.015,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+44\/-40","imputed":false},{"position":41,"method":"RealMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1230.0,"score":0.066,"rank":38.85,"hrank":29.23,"imp":18.569,"train_time":10.06,"predict_time":1.689,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+36\/-37","imputed":false},{"position":42,"method":"XGBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1214.0,"score":0.053,"rank":40.04,"hrank":30.76,"imp":18.792,"train_time":1.94,"predict_time":0.123,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+39\/-36","imputed":false},{"position":43,"method":"TorchMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1212.0,"score":0.069,"rank":40.24,"hrank":30.96,"imp":18.877,"train_time":2875.52,"predict_time":0.131,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+41\/-42","imputed":false},{"position":44,"method":"ExtraTrees","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1208.0,"score":0.083,"rank":40.47,"hrank":28.16,"imp":19.777,"train_time":263.04,"predict_time":0.766,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+49\/-43","imputed":false},{"position":45,"method":"FastaiMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1207.0,"score":0.105,"rank":40.58,"hrank":25.38,"imp":19.677,"train_time":593.24,"predict_time":4.467,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+51\/-59","imputed":false},{"position":46,"method":"EBM","variant":"Default","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1204.0,"score":0.069,"rank":40.82,"hrank":28.54,"imp":20.255,"train_time":6.67,"predict_time":0.014,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+45\/-49","imputed":false},{"position":47,"method":"LightGBM","variant":"Default","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1186.0,"score":0.038,"rank":42.12,"hrank":36.15,"imp":19.344,"train_time":1.96,"predict_time":0.142,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+34\/-29","imputed":false},{"position":48,"method":"ExtraTrees","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1180.0,"score":0.074,"rank":42.56,"hrank":26.73,"imp":20.564,"train_time":263.04,"predict_time":0.071,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+45\/-52","imputed":false},{"position":49,"method":"RandomForest","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1171.0,"score":0.06,"rank":43.28,"hrank":29.04,"imp":20.828,"train_time":373.24,"predict_time":0.771,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+54\/-47","imputed":false},{"position":50,"method":"FastaiMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1147.0,"score":0.048,"rank":45.01,"hrank":31.19,"imp":21.096,"train_time":593.24,"predict_time":0.306,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+52\/-59","imputed":false},{"position":51,"method":"RandomForest","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1137.0,"score":0.041,"rank":45.71,"hrank":28.56,"imp":21.535,"train_time":373.24,"predict_time":0.085,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+50\/-44","imputed":false},{"position":52,"method":"TabSTAR","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1097.0,"score":0.125,"rank":48.47,"hrank":15.95,"imp":25.584,"train_time":28729.74,"predict_time":4.268,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+75\/-83","imputed":false},{"position":53,"method":"TabSTAR","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1096.0,"score":0.123,"rank":48.56,"hrank":15.35,"imp":25.6,"train_time":28729.74,"predict_time":18.811,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+79\/-83","imputed":false},{"position":54,"method":"iLTM","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1094.0,"score":0.037,"rank":48.66,"hrank":33.93,"imp":23.024,"train_time":296.64,"predict_time":68.173,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+47\/-54","imputed":false},{"position":55,"method":"PerpetualBooster","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":1089.0,"score":0.024,"rank":49.04,"hrank":38.83,"imp":26.446,"train_time":185.31,"predict_time":0.6,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+44\/-45","imputed":false},{"position":56,"method":"TorchMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1074.0,"score":0.011,"rank":49.99,"hrank":39.42,"imp":22.815,"train_time":9.99,"predict_time":0.126,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+34\/-42","imputed":false},{"position":57,"method":"PerpetualBooster","variant":"Tuned","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":1050.0,"score":0.011,"rank":51.52,"hrank":39.96,"imp":27.802,"train_time":185.31,"predict_time":0.258,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+47\/-50","imputed":false},{"position":58,"method":"xRFM","variant":"Default","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1043.0,"score":0.029,"rank":51.95,"hrank":44.11,"imp":26.445,"train_time":3.23,"predict_time":0.919,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+61\/-70","imputed":false},{"position":59,"method":"ExtraTrees","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1009.0,"score":0.012,"rank":54.0,"hrank":47.38,"imp":26.176,"train_time":1.87,"predict_time":0.283,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+51\/-66","imputed":false},{"position":60,"method":"FastaiMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1008.0,"score":0.009,"rank":54.07,"hrank":39.97,"imp":25.682,"train_time":2.86,"predict_time":0.373,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+57\/-62","imputed":false},{"position":61,"method":"RandomForest","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1000.0,"score":0.003,"rank":54.51,"hrank":49.81,"imp":26.265,"train_time":0.43,"predict_time":0.054,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+47\/-47","imputed":false},{"position":62,"method":"KNN","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":997.0,"score":0.017,"rank":54.67,"hrank":38.92,"imp":27.822,"train_time":129.08,"predict_time":1.801,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+61\/-76","imputed":false},{"position":63,"method":"TabSTAR","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":993.0,"score":0.077,"rank":54.89,"hrank":24.31,"imp":30.456,"train_time":384.75,"predict_time":5.348,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+89\/-104","imputed":false},{"position":64,"method":"Linear","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":965.0,"score":0.031,"rank":56.39,"hrank":40.87,"imp":33.667,"train_time":237.63,"predict_time":0.424,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+64\/-100","imputed":false},{"position":65,"method":"Linear","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":940.0,"score":0.022,"rank":57.67,"hrank":42.64,"imp":34.211,"train_time":237.63,"predict_time":0.085,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+70\/-105","imputed":false},{"position":66,"method":"PerpetualBooster","variant":"Default","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":936.0,"score":0.0,"rank":57.84,"hrank":45.44,"imp":31.748,"train_time":27.32,"predict_time":0.029,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+43\/-57","imputed":false},{"position":67,"method":"KNN","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":890.0,"score":0.008,"rank":59.92,"hrank":46.93,"imp":32.782,"train_time":129.08,"predict_time":0.18,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+61\/-100","imputed":false},{"position":68,"method":"Linear","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":861.0,"score":0.014,"rank":61.12,"hrank":47.51,"imp":36.822,"train_time":1.19,"predict_time":0.12,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+69\/-118","imputed":false},{"position":69,"method":"KNN","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":654.0,"score":0.0,"rank":66.89,"hrank":60.42,"imp":45.987,"train_time":0.19,"predict_time":0.036,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+78\/-91","imputed":false}];
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 370 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 371 |
-
// already share a color, and each holds only a handful of methods.
|
| 372 |
-
const FAM_MERGED = "Baseline / Other";
|
| 373 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 374 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 375 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 376 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 377 |
-
|
| 378 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 379 |
-
const FAM_VAR = {
|
| 380 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 381 |
-
"Tree-based": "var(--fam-tree)",
|
| 382 |
-
"Neural Network": "var(--fam-nn)",
|
| 383 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 384 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 385 |
-
};
|
| 386 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 387 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 388 |
-
// that chip carries both symbols.
|
| 389 |
-
const FAM_SYMBOL = {
|
| 390 |
-
"Foundation Model": "🧠⚡",
|
| 391 |
-
"Tree-based": "🌳",
|
| 392 |
-
"Neural Network": "🧠🔁",
|
| 393 |
-
"Reference Pipeline": "📊",
|
| 394 |
-
[FAM_MERGED]: "📏 ❓",
|
| 395 |
-
};
|
| 396 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 397 |
-
const VARIANT_VAR = {
|
| 398 |
-
"Default": "var(--var-default)",
|
| 399 |
-
"Tuned": "var(--var-tuned)",
|
| 400 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 401 |
-
};
|
| 402 |
-
|
| 403 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 404 |
-
function famChipLabel(family, count) {
|
| 405 |
-
const symbol = FAM_SYMBOL[family];
|
| 406 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 407 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 408 |
-
}
|
| 409 |
-
|
| 410 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 411 |
-
const FAM_INK = {
|
| 412 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 413 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 414 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 415 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 416 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 417 |
-
};
|
| 418 |
-
|
| 419 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 420 |
-
function el(name, attrs, parent) {
|
| 421 |
-
const node = document.createElementNS(NS, name);
|
| 422 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 423 |
-
if (parent) parent.appendChild(node);
|
| 424 |
-
return node;
|
| 425 |
-
}
|
| 426 |
-
|
| 427 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 428 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 429 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 430 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 431 |
-
function fmtNum(v, decimals) {
|
| 432 |
-
if (v == null || !isFinite(v)) return "—";
|
| 433 |
-
return v.toFixed(decimals);
|
| 434 |
-
}
|
| 435 |
-
|
| 436 |
-
function fmtMetric(metric, v) {
|
| 437 |
-
if (v == null || !isFinite(v)) return "—";
|
| 438 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 439 |
-
}
|
| 440 |
-
|
| 441 |
-
function fmtTime(v) {
|
| 442 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 443 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 444 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 445 |
-
return fmtNum(v, 3) + " s";
|
| 446 |
-
}
|
| 447 |
-
|
| 448 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 449 |
-
function niceStep(raw) {
|
| 450 |
-
if (!(raw > 0)) return 1;
|
| 451 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 452 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 453 |
-
if (mag * m >= raw) return mag * m;
|
| 454 |
-
}
|
| 455 |
-
return mag * 10;
|
| 456 |
-
}
|
| 457 |
-
|
| 458 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 459 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 460 |
-
function ticks(min, max, target) {
|
| 461 |
-
const step = niceStep((max - min) / target);
|
| 462 |
-
const first = Math.ceil(min / step);
|
| 463 |
-
const out = [];
|
| 464 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 465 |
-
return out.length ? out : [min];
|
| 466 |
-
}
|
| 467 |
-
|
| 468 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 469 |
-
function makeTooltip(box) {
|
| 470 |
-
const node = box.querySelector(".tooltip");
|
| 471 |
-
return {
|
| 472 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 473 |
-
move(ev) {
|
| 474 |
-
const r = box.getBoundingClientRect();
|
| 475 |
-
let tx = ev.clientX - r.left + 14;
|
| 476 |
-
const ty = ev.clientY - r.top + 12;
|
| 477 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 478 |
-
node.style.left = tx + "px";
|
| 479 |
-
node.style.top = ty + "px";
|
| 480 |
-
},
|
| 481 |
-
hide() { node.style.display = "none"; },
|
| 482 |
-
};
|
| 483 |
-
}
|
| 484 |
-
|
| 485 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 486 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 487 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 488 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 489 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 490 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 491 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 492 |
-
function setUpPaperView(afterToggle, options) {
|
| 493 |
-
const opts = options || {};
|
| 494 |
-
const root = document.documentElement;
|
| 495 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 496 |
-
const btn = document.getElementById("btn-paper");
|
| 497 |
-
const embedded = window.parent !== window;
|
| 498 |
-
|
| 499 |
-
function setPaper(on) {
|
| 500 |
-
document.body.classList.toggle("paper", on);
|
| 501 |
-
if (on) {
|
| 502 |
-
hostTheme = root.getAttribute("data-theme");
|
| 503 |
-
root.setAttribute("data-theme", "light");
|
| 504 |
-
} else if (hostTheme) {
|
| 505 |
-
root.setAttribute("data-theme", hostTheme);
|
| 506 |
-
} else {
|
| 507 |
-
root.removeAttribute("data-theme");
|
| 508 |
-
}
|
| 509 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 510 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 511 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 512 |
-
postHeight();
|
| 513 |
-
}
|
| 514 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 515 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 516 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 517 |
-
// shareable single file) this page needs its own.
|
| 518 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 519 |
-
window.addEventListener("message", ev => {
|
| 520 |
-
const d = ev.data;
|
| 521 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 522 |
-
});
|
| 523 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 524 |
-
// key press, so its label would fall out of step with the frame.
|
| 525 |
-
if (!embedded) {
|
| 526 |
-
document.addEventListener("keydown", ev => {
|
| 527 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 528 |
-
});
|
| 529 |
-
}
|
| 530 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 531 |
-
}
|
| 532 |
-
|
| 533 |
-
// --- Figure export ---------------------------------------------------------
|
| 534 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 535 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 536 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 537 |
-
// the legend is HTML rather than part of the SVG.
|
| 538 |
-
|
| 539 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 540 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 541 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 542 |
-
// break the PNG path.
|
| 543 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 544 |
-
// once the node leaves this document.
|
| 545 |
-
function resolveVars(root, resolve) {
|
| 546 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 547 |
-
for (const attr of ["fill", "stroke"]) {
|
| 548 |
-
const value = node.getAttribute(attr);
|
| 549 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 550 |
-
}
|
| 551 |
-
}
|
| 552 |
-
}
|
| 553 |
-
|
| 554 |
-
function legendToSvg(container, resolve) {
|
| 555 |
-
const base = container.getBoundingClientRect();
|
| 556 |
-
const group = document.createElementNS(NS, "g");
|
| 557 |
-
let height = 0;
|
| 558 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 559 |
-
const box = item.getBoundingClientRect();
|
| 560 |
-
if (!box.width) continue;
|
| 561 |
-
height = Math.max(height, box.bottom - base.top);
|
| 562 |
-
let textLeft = box.left - base.left;
|
| 563 |
-
const glyph = item.querySelector("svg");
|
| 564 |
-
if (glyph) {
|
| 565 |
-
const gbox = glyph.getBoundingClientRect();
|
| 566 |
-
const wrap = el("g", {
|
| 567 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 568 |
-
}, group);
|
| 569 |
-
const glyphClone = glyph.cloneNode(true);
|
| 570 |
-
resolveVars(glyphClone, resolve);
|
| 571 |
-
wrap.appendChild(glyphClone);
|
| 572 |
-
textLeft = gbox.right - base.left + 5;
|
| 573 |
-
}
|
| 574 |
-
const label = item.textContent.trim();
|
| 575 |
-
if (!label) continue;
|
| 576 |
-
const colored = item.querySelector("[style*='color']");
|
| 577 |
-
const text = el("text", {
|
| 578 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 579 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 580 |
-
}, group);
|
| 581 |
-
text.textContent = label;
|
| 582 |
-
}
|
| 583 |
-
return { group, height: Math.ceil(height) };
|
| 584 |
-
}
|
| 585 |
-
|
| 586 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 587 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 588 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 589 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 590 |
-
const resolve = value => String(value).replace(
|
| 591 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 592 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 593 |
-
|
| 594 |
-
let chartW = 0, chartH = 0;
|
| 595 |
-
for (const part of parts) {
|
| 596 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 597 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 598 |
-
}
|
| 599 |
-
|
| 600 |
-
const out = document.createElementNS(NS, "svg");
|
| 601 |
-
out.setAttribute("xmlns", NS);
|
| 602 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 603 |
-
let top = pad;
|
| 604 |
-
const later = []; // built after the width is known
|
| 605 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 606 |
-
if (legend && legend.height) {
|
| 607 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 608 |
-
later.push(() => out.appendChild(legend.group));
|
| 609 |
-
top += legend.height + 8;
|
| 610 |
-
}
|
| 611 |
-
|
| 612 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 613 |
-
const height = top + chartH + pad;
|
| 614 |
-
out.setAttribute("width", Math.ceil(width));
|
| 615 |
-
out.setAttribute("height", Math.ceil(height));
|
| 616 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 617 |
-
for (const build of later) build();
|
| 618 |
-
|
| 619 |
-
for (const part of parts) {
|
| 620 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 621 |
-
const clone = part.svg.cloneNode(true);
|
| 622 |
-
resolveVars(clone, resolve);
|
| 623 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 624 |
-
}
|
| 625 |
-
return out;
|
| 626 |
-
}
|
| 627 |
-
|
| 628 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 629 |
-
function slugify(text) {
|
| 630 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 631 |
-
}
|
| 632 |
-
|
| 633 |
-
function downloadUrl(url, filename) {
|
| 634 |
-
const a = document.createElement("a");
|
| 635 |
-
a.href = url;
|
| 636 |
-
a.download = filename;
|
| 637 |
-
document.body.appendChild(a);
|
| 638 |
-
a.click();
|
| 639 |
-
a.remove();
|
| 640 |
-
}
|
| 641 |
-
|
| 642 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 643 |
-
function rasterize(svg, scale, done, fail) {
|
| 644 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 645 |
-
const img = new Image();
|
| 646 |
-
img.onload = () => {
|
| 647 |
-
const canvas = document.createElement("canvas");
|
| 648 |
-
canvas.width = Math.round(width * scale);
|
| 649 |
-
canvas.height = Math.round(height * scale);
|
| 650 |
-
const ctx = canvas.getContext("2d");
|
| 651 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 652 |
-
ctx.drawImage(img, 0, 0);
|
| 653 |
-
done(canvas, width, height);
|
| 654 |
-
};
|
| 655 |
-
img.onerror = fail;
|
| 656 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 657 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 658 |
-
}
|
| 659 |
-
|
| 660 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 661 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 662 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 663 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 664 |
-
// and the pixels land at 96*scale dpi.
|
| 665 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 666 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 667 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 668 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 669 |
-
rgb[j] = pixels[i];
|
| 670 |
-
rgb[j + 1] = pixels[i + 1];
|
| 671 |
-
rgb[j + 2] = pixels[i + 2];
|
| 672 |
-
}
|
| 673 |
-
const deflated = new Uint8Array(await new Response(
|
| 674 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 675 |
-
|
| 676 |
-
const encoder = new TextEncoder();
|
| 677 |
-
const chunks = [];
|
| 678 |
-
const offsets = [];
|
| 679 |
-
let cursor = 0;
|
| 680 |
-
const put = data => {
|
| 681 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 682 |
-
chunks.push(bytes);
|
| 683 |
-
cursor += bytes.length;
|
| 684 |
-
};
|
| 685 |
-
const object = (id, body, stream) => {
|
| 686 |
-
offsets[id] = cursor;
|
| 687 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 688 |
-
if (stream) {
|
| 689 |
-
put("stream\n");
|
| 690 |
-
put(stream);
|
| 691 |
-
put("\nendstream\n");
|
| 692 |
-
}
|
| 693 |
-
put("endobj\n");
|
| 694 |
-
};
|
| 695 |
-
|
| 696 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 697 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 698 |
-
put("%PDF-1.4\n");
|
| 699 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 700 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 701 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 702 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 703 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 704 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 705 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 706 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 707 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 708 |
-
|
| 709 |
-
const xref = cursor;
|
| 710 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 711 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 712 |
-
put(table);
|
| 713 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 714 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 715 |
-
}
|
| 716 |
-
|
| 717 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 718 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 719 |
-
function setUpExport(getParts, basename) {
|
| 720 |
-
const buttons = {
|
| 721 |
-
svg: document.getElementById("btn-svg"),
|
| 722 |
-
png: document.getElementById("btn-png"),
|
| 723 |
-
pdf: document.getElementById("btn-pdf"),
|
| 724 |
-
};
|
| 725 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 726 |
-
|
| 727 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 728 |
-
function complain(format) {
|
| 729 |
-
const button = buttons[format];
|
| 730 |
-
if (!button) return;
|
| 731 |
-
const label = button.textContent;
|
| 732 |
-
button.textContent = "failed";
|
| 733 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 734 |
-
}
|
| 735 |
-
|
| 736 |
-
function run(format) {
|
| 737 |
-
const svg = figure();
|
| 738 |
-
const name = basename();
|
| 739 |
-
if (format === "svg") {
|
| 740 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 741 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 742 |
-
return;
|
| 743 |
-
}
|
| 744 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 745 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 746 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 747 |
-
if (format === "png") {
|
| 748 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 749 |
-
} else {
|
| 750 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 751 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 752 |
-
.catch(() => complain("pdf"));
|
| 753 |
-
}
|
| 754 |
-
}, () => complain(format));
|
| 755 |
-
}
|
| 756 |
-
|
| 757 |
-
for (const format of Object.keys(buttons)) {
|
| 758 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 759 |
-
}
|
| 760 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 761 |
-
window.addEventListener("message", ev => {
|
| 762 |
-
const d = ev.data;
|
| 763 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 764 |
-
});
|
| 765 |
-
}
|
| 766 |
-
|
| 767 |
-
// When embedded, report the content height so the host page can size the
|
| 768 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 769 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 770 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 771 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 772 |
-
// stops re-posting once the height settles.
|
| 773 |
-
let lastPostedHeight = 0;
|
| 774 |
-
function postHeight() {
|
| 775 |
-
if (window.parent === window) return;
|
| 776 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 777 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 778 |
-
lastPostedHeight = height;
|
| 779 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 780 |
-
}
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
const COLUMNS = CONFIG.columns;
|
| 784 |
-
const RANK_KEY = CONFIG.rankKey;
|
| 785 |
-
const colByKey = new Map(COLUMNS.map(c => [c.key, c]));
|
| 786 |
-
const VARIANTS = CONFIG.variants.filter(v => POINTS.some(p => p.variant === v));
|
| 787 |
-
|
| 788 |
-
// How a variant is written out. The short "Tuned + Ens." form is the internal key
|
| 789 |
-
// (the charts' colour and marker tables are keyed by it), but nothing on the page
|
| 790 |
-
// should show the abbreviation: the row tag uses the spelling the data and the
|
| 791 |
-
// app's cross-subset table use, and the toggle spells it out in full.
|
| 792 |
-
const VARIANT_TEXT = {
|
| 793 |
-
"Default": "default",
|
| 794 |
-
"Tuned": "tuned",
|
| 795 |
-
"Tuned + Ens.": "tuned + ensembled",
|
| 796 |
-
};
|
| 797 |
-
const VARIANT_BTN = { "Tuned + Ens.": "Tuned + Ensembled" };
|
| 798 |
-
const variantText = v => VARIANT_TEXT[v] || v;
|
| 799 |
-
const HAS_IMPUTED = POINTS.some(p => p.imputed);
|
| 800 |
-
|
| 801 |
-
const state = {
|
| 802 |
-
methods: new Set(POINTS.map(p => p.method)),
|
| 803 |
-
variants: new Set(VARIANTS),
|
| 804 |
-
columns: new Set(COLUMNS.filter(c => c.on !== false).map(c => c.key)),
|
| 805 |
-
imputed: true,
|
| 806 |
-
search: "",
|
| 807 |
-
sortKey: null,
|
| 808 |
-
sortAsc: false,
|
| 809 |
-
};
|
| 810 |
-
|
| 811 |
-
const tblwrap = document.getElementById("tblwrap");
|
| 812 |
-
const chipsBox = document.getElementById("chips");
|
| 813 |
-
const famChips = new Map();
|
| 814 |
-
const chipByMethod = new Map();
|
| 815 |
-
|
| 816 |
-
// ---------- heat shading ----------
|
| 817 |
-
// Green (best) through olive to red (worst), matching the website's
|
| 818 |
-
// cross-subset overview so a reader moving between them reads one scale.
|
| 819 |
-
const RAMP = [[0, [28, 120, 62]], [0.5, [138, 122, 36]], [1, [160, 58, 58]]];
|
| 820 |
-
function heatColor(frac) {
|
| 821 |
-
const f = Math.max(0, Math.min(1, frac));
|
| 822 |
-
for (let i = 0; i < RAMP.length - 1; i++) {
|
| 823 |
-
const [f0, c0] = RAMP[i], [f1, c1] = RAMP[i + 1];
|
| 824 |
-
if (f <= f1) {
|
| 825 |
-
const t = f1 === f0 ? 0 : (f - f0) / (f1 - f0);
|
| 826 |
-
const mix = c0.map((v, j) => Math.round(v + t * (c1[j] - v)));
|
| 827 |
-
return "rgb(" + mix.join(",") + ")";
|
| 828 |
-
}
|
| 829 |
-
}
|
| 830 |
-
return "rgb(" + RAMP[RAMP.length - 1][1].join(",") + ")";
|
| 831 |
-
}
|
| 832 |
-
// Runtimes span orders of magnitude; shading them linearly paints every model
|
| 833 |
-
// the same green and only the slowest one red, so those normalize in log space.
|
| 834 |
-
function scaleOf(col, v) { return col.logScale ? Math.log10(v) : v; }
|
| 835 |
-
function bounds(rows, col) {
|
| 836 |
-
const values = [];
|
| 837 |
-
for (const p of rows) {
|
| 838 |
-
const v = p[col.key];
|
| 839 |
-
if (v == null || !isFinite(v)) continue;
|
| 840 |
-
if (col.logScale && !(v > 0)) continue;
|
| 841 |
-
values.push(scaleOf(col, v));
|
| 842 |
-
}
|
| 843 |
-
if (values.length < 2) return null;
|
| 844 |
-
const lo = Math.min(...values), hi = Math.max(...values);
|
| 845 |
-
return hi > lo ? [lo, hi] : null;
|
| 846 |
-
}
|
| 847 |
-
|
| 848 |
-
// ---------- cells ----------
|
| 849 |
-
function nameCell(p) {
|
| 850 |
-
const ink = FAM_INK[p.family] || "var(--muted)";
|
| 851 |
-
let inner = escapeHtml(p.method);
|
| 852 |
-
if (p.variant) inner += ' <span class="variant-tag">(' + escapeHtml(variantText(p.variant)) + ")</span>";
|
| 853 |
-
if (p.verified) inner += ' <span class="verified" title="Verified implementation">✔️</span>';
|
| 854 |
-
if (p.imputed) {
|
| 855 |
-
const pct = isFinite(p.imputed_pct) ? fmtNum(p.imputed_pct, 0) + "% " : "";
|
| 856 |
-
inner += ' <span class="imp-mark" title="' + pct + 'imputed">‡</span>';
|
| 857 |
-
}
|
| 858 |
-
const body = p.url
|
| 859 |
-
? '<a href="' + escapeHtml(p.url) + '" target="_blank" rel="noopener" style="color:' + ink +
|
| 860 |
-
';font-weight:600;">' + inner + '<span class="link-icon">↗</span></a>'
|
| 861 |
-
: '<span style="color:' + ink + ';font-weight:600;">' + inner + "</span>";
|
| 862 |
-
return '<td class="name" data-export="' + escapeHtml(plainName(p)) + '">' + body + "</td>";
|
| 863 |
-
}
|
| 864 |
-
function plainName(p) {
|
| 865 |
-
return p.method + (p.variant ? " (" + p.variant + ")" : "");
|
| 866 |
-
}
|
| 867 |
-
function escapeHtml(text) {
|
| 868 |
-
return String(text == null ? "" : text).replace(/[&<>"']/g, c =>
|
| 869 |
-
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
| 870 |
-
}
|
| 871 |
-
|
| 872 |
-
// ---------- rows ----------
|
| 873 |
-
function visibleRows() {
|
| 874 |
-
const term = state.search.trim().toLowerCase();
|
| 875 |
-
return POINTS.filter(p => {
|
| 876 |
-
if (!state.methods.has(p.method)) return false;
|
| 877 |
-
if (p.variant && !state.variants.has(p.variant)) return false;
|
| 878 |
-
if (!state.imputed && p.imputed) return false;
|
| 879 |
-
if (term && !(p.method + " " + (p.variant || "") + " " + p.family).toLowerCase().includes(term)) return false;
|
| 880 |
-
return true;
|
| 881 |
-
});
|
| 882 |
-
}
|
| 883 |
-
function sortRows(rows) {
|
| 884 |
-
const out = rows.slice();
|
| 885 |
-
if (!state.sortKey) return out.sort((a, b) => a.position - b.position);
|
| 886 |
-
const col = colByKey.get(state.sortKey);
|
| 887 |
-
const sign = state.sortAsc ? 1 : -1;
|
| 888 |
-
const keyOf = p => {
|
| 889 |
-
const v = p[state.sortKey];
|
| 890 |
-
if (col && col.text) return String(v == null ? "" : v).toLowerCase();
|
| 891 |
-
return v == null || !isFinite(v) ? null : v;
|
| 892 |
-
};
|
| 893 |
-
return out.sort((a, b) => {
|
| 894 |
-
const ka = keyOf(a), kb = keyOf(b);
|
| 895 |
-
if (ka === null || kb === null) return ka === kb ? 0 : ka === null ? 1 : -1;
|
| 896 |
-
return ka < kb ? -sign : ka > kb ? sign : 0;
|
| 897 |
-
});
|
| 898 |
-
}
|
| 899 |
-
|
| 900 |
-
function activeColumns() {
|
| 901 |
-
return COLUMNS.filter(c => c.always || state.columns.has(c.key));
|
| 902 |
-
}
|
| 903 |
-
|
| 904 |
-
function render() {
|
| 905 |
-
const rows = sortRows(visibleRows());
|
| 906 |
-
const cols = activeColumns();
|
| 907 |
-
if (!rows.length) {
|
| 908 |
-
tblwrap.innerHTML = '<p class="lbt-empty">Nothing selected — turn a family or variant back on.</p>';
|
| 909 |
-
document.getElementById("caption").textContent = "";
|
| 910 |
-
postHeight();
|
| 911 |
-
return;
|
| 912 |
-
}
|
| 913 |
-
// No medals here: this table is the full ranking, so the position column
|
| 914 |
-
// already says who is where. They belong to the cross-subset overview.
|
| 915 |
-
const heat = new Map();
|
| 916 |
-
for (const col of cols) if (col.heatmap) heat.set(col.key, bounds(rows, col));
|
| 917 |
-
|
| 918 |
-
let html = '<table class="lbt"><thead><tr>';
|
| 919 |
-
for (const col of cols) {
|
| 920 |
-
const sorted = state.sortKey === col.key
|
| 921 |
-
? ' aria-sort="' + (state.sortAsc ? "ascending" : "descending") + '"' : "";
|
| 922 |
-
html += "<th" + sorted + ' data-key="' + col.key + '" title="' + escapeHtml(col.hint || col.label) +
|
| 923 |
-
'"><span class="lbl">' + escapeHtml(col.label) + "</span>" +
|
| 924 |
-
(col.key === "elo" ? ' <span class="ci">(95% CI)</span>' : "") + "</th>";
|
| 925 |
-
}
|
| 926 |
-
html += "</tr></thead><tbody>";
|
| 927 |
-
for (const p of rows) {
|
| 928 |
-
html += "<tr>";
|
| 929 |
-
for (const col of cols) {
|
| 930 |
-
if (col.key === "position") {
|
| 931 |
-
html += '<td class="pos num" data-sort="' + p.position + '">' + p.position + "</td>";
|
| 932 |
-
} else if (col.key === "family") {
|
| 933 |
-
const mark = FAM_VAR[p.family] || "var(--fam-baseline)";
|
| 934 |
-
html += '<td class="type" data-sort="' + escapeHtml(p.family) + '" data-export="' + escapeHtml(p.family) +
|
| 935 |
-
'"><span class="pill" style="background:color-mix(in srgb, ' + mark +
|
| 936 |
-
' 13%, transparent);color:' + (FAM_INK[p.family] || "var(--muted)") +
|
| 937 |
-
";border:1px solid color-mix(in srgb, " + mark + ' 40%, transparent);">' +
|
| 938 |
-
escapeHtml(p.family_symbol || "") + "</span></td>";
|
| 939 |
-
} else if (col.key === "model") {
|
| 940 |
-
html += nameCell(p);
|
| 941 |
-
} else {
|
| 942 |
-
html += valueCell(p, col, heat.get(col.key));
|
| 943 |
-
}
|
| 944 |
-
}
|
| 945 |
-
html += "</tr>";
|
| 946 |
-
}
|
| 947 |
-
tblwrap.innerHTML = html + "</tbody></table>";
|
| 948 |
-
for (const th of tblwrap.querySelectorAll("th")) {
|
| 949 |
-
th.addEventListener("click", () => sortBy(th.dataset.key));
|
| 950 |
-
}
|
| 951 |
-
document.getElementById("caption").textContent =
|
| 952 |
-
rows.length + (rows.length === 1 ? " row" : " rows") +
|
| 953 |
-
" · click a column header to sort, hover one for what it means" +
|
| 954 |
-
(heat.size ? " · green is better, red is worse, per column" : "") +
|
| 955 |
-
(HAS_IMPUTED ? " · ‡ marks a partly imputed score" : "");
|
| 956 |
-
postHeight();
|
| 957 |
-
}
|
| 958 |
-
|
| 959 |
-
function valueCell(p, col, span) {
|
| 960 |
-
const v = p[col.key];
|
| 961 |
-
if (v == null || (typeof v === "number" && !isFinite(v))) return '<td class="na">–</td>';
|
| 962 |
-
if (col.text) {
|
| 963 |
-
return '<td data-sort="' + escapeHtml(v) + '" data-export="' + escapeHtml(v) + '">' + escapeHtml(v) + "</td>";
|
| 964 |
-
}
|
| 965 |
-
let style = "";
|
| 966 |
-
if (span) {
|
| 967 |
-
let frac = (scaleOf(col, v) - span[0]) / (span[1] - span[0]);
|
| 968 |
-
if (!col.lowerBetter) frac = 1 - frac;
|
| 969 |
-
style = ' style="background:' + heatColor(frac) + ';color:#f7f7f7;"';
|
| 970 |
-
}
|
| 971 |
-
let text = fmtNum(v, col.decimals) + (col.suffix || "");
|
| 972 |
-
let ci = "";
|
| 973 |
-
if (col.key === "elo" && p.elo_ci) {
|
| 974 |
-
ci = ' <span class="ci">(' + escapeHtml(p.elo_ci) + ")</span>";
|
| 975 |
-
}
|
| 976 |
-
return '<td class="num" data-sort="' + v + '"' + (ci ? ' data-ci="' + escapeHtml(p.elo_ci) + '"' : "") +
|
| 977 |
-
style + ">" + text + ci + "</td>";
|
| 978 |
-
}
|
| 979 |
-
|
| 980 |
-
function sortBy(key) {
|
| 981 |
-
if (!key) return;
|
| 982 |
-
if (state.sortKey === key) state.sortAsc = !state.sortAsc;
|
| 983 |
-
else { state.sortKey = key; state.sortAsc = !!(colByKey.get(key) || {}).lowerBetter; }
|
| 984 |
-
render();
|
| 985 |
-
}
|
| 986 |
-
|
| 987 |
-
// ---------- chips (families and their methods) ----------
|
| 988 |
-
function familyMembers(fam) {
|
| 989 |
-
return [...new Set(POINTS.filter(p => p.family === fam).map(p => p.method))];
|
| 990 |
-
}
|
| 991 |
-
function methodRank(name) {
|
| 992 |
-
const col = colByKey.get(RANK_KEY);
|
| 993 |
-
const values = POINTS.filter(p => p.method === name && isFinite(p[RANK_KEY])).map(p => p[RANK_KEY]);
|
| 994 |
-
if (!values.length) return Infinity;
|
| 995 |
-
return col.lowerBetter ? Math.min(...values) : -Math.max(...values);
|
| 996 |
-
}
|
| 997 |
-
function buildChips() {
|
| 998 |
-
const head = document.createElement("div");
|
| 999 |
-
head.className = "chips-head";
|
| 1000 |
-
head.textContent = "Models shown — click to remove, click a family to toggle the whole group";
|
| 1001 |
-
chipsBox.appendChild(head);
|
| 1002 |
-
for (const fam of FAM_ORDER) {
|
| 1003 |
-
const members = familyMembers(fam);
|
| 1004 |
-
if (!members.length) continue;
|
| 1005 |
-
members.sort((a, b) => methodRank(a) - methodRank(b));
|
| 1006 |
-
const row = document.createElement("div");
|
| 1007 |
-
row.className = "chiprow";
|
| 1008 |
-
const famBtn = document.createElement("button");
|
| 1009 |
-
famBtn.className = "famchip";
|
| 1010 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1011 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1012 |
-
famBtn.title = "Toggle all " + members.length + " " + fam + " models";
|
| 1013 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1014 |
-
row.appendChild(famBtn);
|
| 1015 |
-
famChips.set(fam, famBtn);
|
| 1016 |
-
const set = document.createElement("div");
|
| 1017 |
-
set.className = "chipset";
|
| 1018 |
-
for (const name of members) {
|
| 1019 |
-
const imputed = POINTS.some(p => p.method === name && p.imputed);
|
| 1020 |
-
const b = document.createElement("button");
|
| 1021 |
-
b.className = "chip";
|
| 1022 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1023 |
-
b.innerHTML = '<span class="dot"></span><span>' + escapeHtml(name) + "</span>" +
|
| 1024 |
-
(imputed ? '<span class="imp-mark">‡</span>' : "");
|
| 1025 |
-
b.title = name + (imputed ? " — partially imputed" : "");
|
| 1026 |
-
b.addEventListener("click", () => toggleMethod(name));
|
| 1027 |
-
set.appendChild(b);
|
| 1028 |
-
chipByMethod.set(name, b);
|
| 1029 |
-
}
|
| 1030 |
-
row.appendChild(set);
|
| 1031 |
-
chipsBox.appendChild(row);
|
| 1032 |
-
}
|
| 1033 |
-
}
|
| 1034 |
-
function syncChips() {
|
| 1035 |
-
for (const [name, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.methods.has(name)));
|
| 1036 |
-
for (const [fam, b] of famChips) {
|
| 1037 |
-
b.setAttribute("aria-pressed", String(familyMembers(fam).every(m => state.methods.has(m))));
|
| 1038 |
-
}
|
| 1039 |
-
}
|
| 1040 |
-
function toggleMethod(name) {
|
| 1041 |
-
if (state.methods.has(name)) state.methods.delete(name); else state.methods.add(name);
|
| 1042 |
-
syncChips();
|
| 1043 |
-
render();
|
| 1044 |
-
}
|
| 1045 |
-
function toggleFamily(fam) {
|
| 1046 |
-
const members = familyMembers(fam);
|
| 1047 |
-
const allOn = members.every(m => state.methods.has(m));
|
| 1048 |
-
for (const m of members) { if (allOn) state.methods.delete(m); else state.methods.add(m); }
|
| 1049 |
-
syncChips();
|
| 1050 |
-
render();
|
| 1051 |
-
}
|
| 1052 |
-
|
| 1053 |
-
// ---------- variant / imputed / column toggles ----------
|
| 1054 |
-
const variantBtns = new Map();
|
| 1055 |
-
function buildVariantBtns() {
|
| 1056 |
-
const box = document.getElementById("variant-btns");
|
| 1057 |
-
for (const v of VARIANTS) {
|
| 1058 |
-
const b = document.createElement("button");
|
| 1059 |
-
b.className = "btn toggle";
|
| 1060 |
-
b.innerHTML = '<span class="swatch"></span>' + escapeHtml(VARIANT_BTN[v] || v);
|
| 1061 |
-
b.style.setProperty("--fam", VARIANT_VAR[v] || "var(--accent)");
|
| 1062 |
-
b.title = "Show or hide the " + variantText(v) + " results";
|
| 1063 |
-
b.addEventListener("click", () => {
|
| 1064 |
-
if (state.variants.has(v)) state.variants.delete(v); else state.variants.add(v);
|
| 1065 |
-
syncVariantBtns();
|
| 1066 |
-
render();
|
| 1067 |
-
});
|
| 1068 |
-
box.appendChild(b);
|
| 1069 |
-
variantBtns.set(v, b);
|
| 1070 |
-
}
|
| 1071 |
-
}
|
| 1072 |
-
function syncVariantBtns() {
|
| 1073 |
-
for (const [v, b] of variantBtns) b.setAttribute("aria-pressed", String(state.variants.has(v)));
|
| 1074 |
-
const imp = document.getElementById("btn-imputed");
|
| 1075 |
-
imp.hidden = !HAS_IMPUTED;
|
| 1076 |
-
imp.className = "btn toggle";
|
| 1077 |
-
imp.innerHTML = '<span class="swatch"></span>‡ Imputed';
|
| 1078 |
-
imp.setAttribute("aria-pressed", String(state.imputed));
|
| 1079 |
-
imp.style.setProperty("--fam", "var(--muted)");
|
| 1080 |
-
}
|
| 1081 |
-
function buildColumnBtns() {
|
| 1082 |
-
const box = document.getElementById("col-btns");
|
| 1083 |
-
for (const col of COLUMNS) {
|
| 1084 |
-
if (col.always) continue;
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "btn toggle";
|
| 1087 |
-
b.textContent = col.short || col.label;
|
| 1088 |
-
b.title = "Show or hide " + col.label;
|
| 1089 |
-
b.style.setProperty("--fam", "var(--accent)");
|
| 1090 |
-
b.addEventListener("click", () => {
|
| 1091 |
-
if (state.columns.has(col.key)) state.columns.delete(col.key); else state.columns.add(col.key);
|
| 1092 |
-
b.setAttribute("aria-pressed", String(state.columns.has(col.key)));
|
| 1093 |
-
render();
|
| 1094 |
-
});
|
| 1095 |
-
b.setAttribute("aria-pressed", String(state.columns.has(col.key)));
|
| 1096 |
-
box.appendChild(b);
|
| 1097 |
-
}
|
| 1098 |
-
}
|
| 1099 |
-
|
| 1100 |
-
// ---------- CSV ----------
|
| 1101 |
-
// Exports what the reader is looking at: the rows the filters left, the
|
| 1102 |
-
// columns they picked, in the order they sorted.
|
| 1103 |
-
function downloadCsv() {
|
| 1104 |
-
const cols = activeColumns();
|
| 1105 |
-
const rows = sortRows(visibleRows());
|
| 1106 |
-
const quote = v => '"' + String(v == null ? "" : v).replace(/"/g, '""') + '"';
|
| 1107 |
-
const head = [];
|
| 1108 |
-
for (const col of cols) {
|
| 1109 |
-
head.push(col.label);
|
| 1110 |
-
if (col.key === "elo" && rows.some(p => p.elo_ci)) head.push("Elo 95% CI");
|
| 1111 |
-
}
|
| 1112 |
-
const lines = [head.map(quote).join(",")];
|
| 1113 |
-
for (const p of rows) {
|
| 1114 |
-
const values = [];
|
| 1115 |
-
for (const col of cols) {
|
| 1116 |
-
if (col.key === "model") values.push(plainName(p));
|
| 1117 |
-
else values.push(p[col.key]);
|
| 1118 |
-
if (col.key === "elo" && rows.some(q => q.elo_ci)) values.push(p.elo_ci || "");
|
| 1119 |
-
}
|
| 1120 |
-
lines.push(values.map(quote).join(","));
|
| 1121 |
-
}
|
| 1122 |
-
const blob = new Blob([lines.join("\n") + "\n"], { type: "text/csv;charset=utf-8" });
|
| 1123 |
-
const url = URL.createObjectURL(blob);
|
| 1124 |
-
downloadUrl(url, slugify(CONFIG.title || document.title || "leaderboard") + ".csv");
|
| 1125 |
-
URL.revokeObjectURL(url);
|
| 1126 |
-
}
|
| 1127 |
-
|
| 1128 |
-
// ---------- boot ----------
|
| 1129 |
-
if (CONFIG.title) document.getElementById("title").textContent = CONFIG.title;
|
| 1130 |
-
document.getElementById("search").addEventListener("input", ev => {
|
| 1131 |
-
state.search = ev.target.value;
|
| 1132 |
-
render();
|
| 1133 |
-
});
|
| 1134 |
-
document.getElementById("btn-imputed").addEventListener("click", () => {
|
| 1135 |
-
state.imputed = !state.imputed;
|
| 1136 |
-
syncVariantBtns();
|
| 1137 |
-
render();
|
| 1138 |
-
});
|
| 1139 |
-
document.getElementById("btn-csv").addEventListener("click", downloadCsv);
|
| 1140 |
-
// Embedded, the host page puts its own CSV button in the panel header (next to
|
| 1141 |
-
// the title) and asks for the download over postMessage, the same way it drives
|
| 1142 |
-
// the figure exports. Standalone, this page needs its own button.
|
| 1143 |
-
if (window.parent !== window) {
|
| 1144 |
-
document.getElementById("btn-csv").hidden = true;
|
| 1145 |
-
window.addEventListener("message", ev => {
|
| 1146 |
-
if (ev.data && ev.data.type === "tabarena-leaderboard-csv") downloadCsv();
|
| 1147 |
-
});
|
| 1148 |
-
}
|
| 1149 |
-
// Opens with the controls: the filters are the point of this page, not chrome
|
| 1150 |
-
// around a figure.
|
| 1151 |
-
setUpPaperView(render, { openInPaper: false });
|
| 1152 |
-
buildVariantBtns();
|
| 1153 |
-
buildColumnBtns();
|
| 1154 |
-
buildChips();
|
| 1155 |
-
syncChips();
|
| 1156 |
-
syncVariantBtns();
|
| 1157 |
-
render();
|
| 1158 |
-
window.addEventListener("resize", postHeight);
|
| 1159 |
-
})();
|
| 1160 |
-
</script>
|
| 1161 |
-
</body>
|
| 1162 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/n_datasets_51
DELETED
|
File without changes
|
data/imputation_no/splits_all/tasks_all/datasets_all/pareto_front_explorer.html
DELETED
|
@@ -1,1230 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena Pareto explorer</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Two-column layout: controls + chips in a side panel, chart beside it.
|
| 269 |
-
``chips-right`` mirrors the columns. Wraps to stacked when narrow. */
|
| 270 |
-
.explorer-grid { display: flex; gap: 18px; align-items: flex-start; }
|
| 271 |
-
.explorer-grid.chips-right { flex-direction: row-reverse; }
|
| 272 |
-
.sidebox { flex: 0 0 330px; min-width: 250px; display: flex; flex-direction: column; gap: 10px; }
|
| 273 |
-
.mainbox { flex: 1 1 auto; min-width: 0; }
|
| 274 |
-
@media (max-width: 860px) {
|
| 275 |
-
.explorer-grid { flex-wrap: wrap; }
|
| 276 |
-
.sidebox { flex: 1 1 100%; }
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 280 |
-
.chartbox { position: relative; }
|
| 281 |
-
/* The chart is sized in device pixels by render() rather than scaled from a
|
| 282 |
-
viewBox: scaling stretched the type along with the plot, and a viewBox tall
|
| 283 |
-
enough to read made the whole panel own the screen. */
|
| 284 |
-
.chartbox svg { display: block; }
|
| 285 |
-
/* Chips scroll within the column so the panel height follows the chart. */
|
| 286 |
-
.sidebox .chips { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent; }
|
| 287 |
-
.sidebox .chips::-webkit-scrollbar { width: 9px; }
|
| 288 |
-
.sidebox .chips::-webkit-scrollbar-thumb {
|
| 289 |
-
background: var(--pt-muted); border-radius: 8px; border: 3px solid transparent; background-clip: content-box;
|
| 290 |
-
}
|
| 291 |
-
</style>
|
| 292 |
-
</head>
|
| 293 |
-
<body>
|
| 294 |
-
<div class="viewbar">
|
| 295 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 296 |
-
</div>
|
| 297 |
-
<p class="explorer-title" id="title"></p>
|
| 298 |
-
<div class="explorer-grid" id="grid">
|
| 299 |
-
<div class="sidebox">
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick" id="metricpick" hidden>Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<div class="btnrow">
|
| 305 |
-
<button class="btn" id="btn-front">Pareto front</button>
|
| 306 |
-
<button class="btn" id="btn-all">All</button>
|
| 307 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 308 |
-
</div>
|
| 309 |
-
<span class="hint">Click methods or family buttons to highlight · hover points for details</span>
|
| 310 |
-
</div>
|
| 311 |
-
<div class="chips" id="chips"></div>
|
| 312 |
-
</div>
|
| 313 |
-
<div class="mainbox">
|
| 314 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 315 |
-
<span class="hint">Export figure</span>
|
| 316 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 317 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 318 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 319 |
-
</div>
|
| 320 |
-
<!-- Legend above the chart so readers decode the marks before the data. -->
|
| 321 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 322 |
-
<div class="chartbox" id="chartbox">
|
| 323 |
-
<svg id="chart" role="img" aria-label="Pareto front explorer"></svg>
|
| 324 |
-
<div class="tooltip"></div>
|
| 325 |
-
</div>
|
| 326 |
-
</div>
|
| 327 |
-
</div>
|
| 328 |
-
<details class="datatable">
|
| 329 |
-
<summary>Data table</summary>
|
| 330 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 331 |
-
</details>
|
| 332 |
-
|
| 333 |
-
<script>
|
| 334 |
-
(function () {
|
| 335 |
-
"use strict";
|
| 336 |
-
const CONFIG = {"mode": "scatter", "title": null, "metrics": [{"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": ""}], "xAxes": [{"key": "x_infer", "label": "Inference time", "axisLabel": "Inference time per 1K samples (s), median \u2014 log scale", "short": "Inference (s/1K, median)"}], "chipsSide": "left"};
|
| 337 |
-
const POINTS = [{"method":"CatBoost","family":"Tree-based","x_infer":0.0248961767,"imp":15.5244408181,"elo":1378.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"CatBoost","family":"Tree-based","x_infer":0.0380928654,"imp":14.8850630485,"elo":1408.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"CatBoost","family":"Tree-based","x_infer":0.3442282032,"imp":14.655679873,"elo":1421.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.0325848325,"imp":18.6570877535,"elo":1263.9,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.0336512776,"imp":17.5510939543,"elo":1308.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.4040760969,"imp":17.2125514645,"elo":1333.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"EBM","family":"Tree-based","x_infer":0.0143528648,"imp":20.2553633192,"elo":1203.8,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"EBM","family":"Tree-based","x_infer":0.0150308987,"imp":19.3136682806,"elo":1235.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"EBM","family":"Tree-based","x_infer":0.1412900124,"imp":18.6722157117,"elo":1271.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.2834081321,"imp":26.1764963285,"elo":1009.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.0712129939,"imp":20.5638085151,"elo":1180.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.7662402325,"imp":19.7773891991,"elo":1208.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"FastaiMLP","family":"Neural Network","x_infer":0.3731781389,"imp":25.6818545229,"elo":1007.8,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"FastaiMLP","family":"Neural Network","x_infer":0.3063915412,"imp":21.0963185218,"elo":1146.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"FastaiMLP","family":"Neural Network","x_infer":4.4666950703,"imp":19.6768711642,"elo":1207.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"LightGBM","family":"Tree-based","x_infer":0.1416787942,"imp":19.3442915921,"elo":1186.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"LightGBM","family":"Tree-based","x_infer":0.3337603531,"imp":15.6876116943,"elo":1385.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"LightGBM","family":"Tree-based","x_infer":2.638673831,"imp":15.0334967342,"elo":1432.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"LimiX","family":"Foundation Model","x_infer":6.2423742585,"imp":15.5263025459,"elo":1362.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ModernNCA","family":"Neural Network","x_infer":0.3073466784,"imp":19.1942294206,"elo":1248.1,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ModernNCA","family":"Neural Network","x_infer":0.4747242315,"imp":16.0439590519,"elo":1355.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ModernNCA","family":"Neural Network","x_infer":8.1379168675,"imp":15.5985458077,"elo":1389.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.0285805066,"imp":31.7480551938,"elo":936.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.2581384468,"imp":27.801643493,"elo":1050.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.5997539679,"imp":26.4456425257,"elo":1088.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RandomForest","family":"Tree-based","x_infer":0.0535405758,"imp":26.2650042304,"elo":1000.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RandomForest","family":"Tree-based","x_infer":0.0852279186,"imp":21.5350457807,"elo":1137.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RandomForest","family":"Tree-based","x_infer":0.7709478321,"imp":20.8284764332,"elo":1170.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RealMLP","family":"Neural Network","x_infer":1.6887954948,"imp":18.5692266729,"elo":1229.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RealMLP","family":"Neural Network","x_infer":0.663132055,"imp":14.2021817976,"elo":1426.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RealMLP","family":"Neural Network","x_infer":11.9749853765,"imp":12.8814924929,"elo":1507.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":0.6449695981,"imp":11.6604512027,"elo":1524.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":1.2178786994,"imp":11.1161483399,"elo":1554.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":8.9076602204,"imp":10.4265657302,"elo":1594.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"SAP-RPT-OSS","family":"Foundation Model","x_infer":2.0745579697,"imp":18.2783205087,"elo":1283.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabDPT","family":"Foundation Model","x_infer":43.7378122226,"imp":17.2252827702,"elo":1324.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabDPT","family":"Foundation Model","x_infer":39.9597364603,"imp":14.9360532408,"elo":1402.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabDPT","family":"Foundation Model","x_infer":286.5373788357,"imp":13.7879250832,"elo":1457.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabDPT-Turbo","family":"Foundation Model","x_infer":0.1824194029,"imp":13.9998432493,"elo":1459.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabFM","family":"Foundation Model","x_infer":6.9854290718,"imp":4.0744823648,"elo":1791.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabICLv2","family":"Foundation Model","x_infer":0.1505492146,"imp":10.1751538315,"elo":1593.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabM","family":"Neural Network","x_infer":0.2435252328,"imp":17.0001433318,"elo":1297.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabM","family":"Neural Network","x_infer":0.2512939462,"imp":14.951713351,"elo":1393.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabM","family":"Neural Network","x_infer":2.2468658586,"imp":14.0806210836,"elo":1450.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabPFN-2.6","family":"Foundation Model","x_infer":0.5548034626,"imp":10.7505455244,"elo":1619.8,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabPFN-3","family":"Foundation Model","x_infer":0.3988194969,"imp":9.3282966338,"elo":1665.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabSTAR","family":"Foundation Model","x_infer":5.3480868421,"imp":30.4556099407,"elo":993.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabSTAR","family":"Foundation Model","x_infer":4.2680534632,"imp":25.584307557,"elo":1097.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabSTAR","family":"Foundation Model","x_infer":18.8114333153,"imp":25.6000754281,"elo":1096.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabSwift","family":"Foundation Model","x_infer":0.0719683769,"imp":16.0807432886,"elo":1350.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TorchMLP","family":"Neural Network","x_infer":0.1258046788,"imp":22.8151308708,"elo":1074.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TorchMLP","family":"Neural Network","x_infer":0.1311128328,"imp":18.876878914,"elo":1211.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TorchMLP","family":"Neural Network","x_infer":1.95162543,"imp":17.1611523587,"elo":1285.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"XGBoost","family":"Tree-based","x_infer":0.1226232881,"imp":18.7922233221,"elo":1214.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"XGBoost","family":"Tree-based","x_infer":0.3080760155,"imp":16.0650443256,"elo":1350.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"XGBoost","family":"Tree-based","x_infer":1.689445163,"imp":15.7538195428,"elo":1375.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"iLTM","family":"Foundation Model","x_infer":68.173296937,"imp":23.0236433289,"elo":1094.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"iLTM","family":"Foundation Model","x_infer":62.1299021172,"imp":17.1472473791,"elo":1295.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"iLTM","family":"Foundation Model","x_infer":464.3696034625,"imp":15.3035551324,"elo":1404.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"xRFM","family":"Other","x_infer":0.9186215876,"imp":26.4448633944,"elo":1043.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"xRFM","family":"Other","x_infer":0.1302743502,"imp":17.4492208687,"elo":1300.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"xRFM","family":"Other","x_infer":2.5492595349,"imp":16.2842179754,"elo":1347.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."}];
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 341 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 342 |
-
// already share a color, and each holds only a handful of methods.
|
| 343 |
-
const FAM_MERGED = "Baseline / Other";
|
| 344 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 345 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 346 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 347 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 348 |
-
|
| 349 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 350 |
-
const FAM_VAR = {
|
| 351 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 352 |
-
"Tree-based": "var(--fam-tree)",
|
| 353 |
-
"Neural Network": "var(--fam-nn)",
|
| 354 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 355 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 356 |
-
};
|
| 357 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 358 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 359 |
-
// that chip carries both symbols.
|
| 360 |
-
const FAM_SYMBOL = {
|
| 361 |
-
"Foundation Model": "🧠⚡",
|
| 362 |
-
"Tree-based": "🌳",
|
| 363 |
-
"Neural Network": "🧠🔁",
|
| 364 |
-
"Reference Pipeline": "📊",
|
| 365 |
-
[FAM_MERGED]: "📏 ❓",
|
| 366 |
-
};
|
| 367 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 368 |
-
const VARIANT_VAR = {
|
| 369 |
-
"Default": "var(--var-default)",
|
| 370 |
-
"Tuned": "var(--var-tuned)",
|
| 371 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 372 |
-
};
|
| 373 |
-
|
| 374 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 375 |
-
function famChipLabel(family, count) {
|
| 376 |
-
const symbol = FAM_SYMBOL[family];
|
| 377 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 378 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 379 |
-
}
|
| 380 |
-
|
| 381 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 382 |
-
const FAM_INK = {
|
| 383 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 384 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 385 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 386 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 387 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 388 |
-
};
|
| 389 |
-
|
| 390 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 391 |
-
function el(name, attrs, parent) {
|
| 392 |
-
const node = document.createElementNS(NS, name);
|
| 393 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 394 |
-
if (parent) parent.appendChild(node);
|
| 395 |
-
return node;
|
| 396 |
-
}
|
| 397 |
-
|
| 398 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 399 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 400 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 401 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 402 |
-
function fmtNum(v, decimals) {
|
| 403 |
-
if (v == null || !isFinite(v)) return "—";
|
| 404 |
-
return v.toFixed(decimals);
|
| 405 |
-
}
|
| 406 |
-
|
| 407 |
-
function fmtMetric(metric, v) {
|
| 408 |
-
if (v == null || !isFinite(v)) return "—";
|
| 409 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 410 |
-
}
|
| 411 |
-
|
| 412 |
-
function fmtTime(v) {
|
| 413 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 414 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 415 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 416 |
-
return fmtNum(v, 3) + " s";
|
| 417 |
-
}
|
| 418 |
-
|
| 419 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 420 |
-
function niceStep(raw) {
|
| 421 |
-
if (!(raw > 0)) return 1;
|
| 422 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 423 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 424 |
-
if (mag * m >= raw) return mag * m;
|
| 425 |
-
}
|
| 426 |
-
return mag * 10;
|
| 427 |
-
}
|
| 428 |
-
|
| 429 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 430 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 431 |
-
function ticks(min, max, target) {
|
| 432 |
-
const step = niceStep((max - min) / target);
|
| 433 |
-
const first = Math.ceil(min / step);
|
| 434 |
-
const out = [];
|
| 435 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 436 |
-
return out.length ? out : [min];
|
| 437 |
-
}
|
| 438 |
-
|
| 439 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 440 |
-
function makeTooltip(box) {
|
| 441 |
-
const node = box.querySelector(".tooltip");
|
| 442 |
-
return {
|
| 443 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 444 |
-
move(ev) {
|
| 445 |
-
const r = box.getBoundingClientRect();
|
| 446 |
-
let tx = ev.clientX - r.left + 14;
|
| 447 |
-
const ty = ev.clientY - r.top + 12;
|
| 448 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 449 |
-
node.style.left = tx + "px";
|
| 450 |
-
node.style.top = ty + "px";
|
| 451 |
-
},
|
| 452 |
-
hide() { node.style.display = "none"; },
|
| 453 |
-
};
|
| 454 |
-
}
|
| 455 |
-
|
| 456 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 457 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 458 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 459 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 460 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 461 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 462 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 463 |
-
function setUpPaperView(afterToggle, options) {
|
| 464 |
-
const opts = options || {};
|
| 465 |
-
const root = document.documentElement;
|
| 466 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 467 |
-
const btn = document.getElementById("btn-paper");
|
| 468 |
-
const embedded = window.parent !== window;
|
| 469 |
-
|
| 470 |
-
function setPaper(on) {
|
| 471 |
-
document.body.classList.toggle("paper", on);
|
| 472 |
-
if (on) {
|
| 473 |
-
hostTheme = root.getAttribute("data-theme");
|
| 474 |
-
root.setAttribute("data-theme", "light");
|
| 475 |
-
} else if (hostTheme) {
|
| 476 |
-
root.setAttribute("data-theme", hostTheme);
|
| 477 |
-
} else {
|
| 478 |
-
root.removeAttribute("data-theme");
|
| 479 |
-
}
|
| 480 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 481 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 482 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 483 |
-
postHeight();
|
| 484 |
-
}
|
| 485 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 486 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 487 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 488 |
-
// shareable single file) this page needs its own.
|
| 489 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 490 |
-
window.addEventListener("message", ev => {
|
| 491 |
-
const d = ev.data;
|
| 492 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 493 |
-
});
|
| 494 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 495 |
-
// key press, so its label would fall out of step with the frame.
|
| 496 |
-
if (!embedded) {
|
| 497 |
-
document.addEventListener("keydown", ev => {
|
| 498 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 499 |
-
});
|
| 500 |
-
}
|
| 501 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 502 |
-
}
|
| 503 |
-
|
| 504 |
-
// --- Figure export ---------------------------------------------------------
|
| 505 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 506 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 507 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 508 |
-
// the legend is HTML rather than part of the SVG.
|
| 509 |
-
|
| 510 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 511 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 512 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 513 |
-
// break the PNG path.
|
| 514 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 515 |
-
// once the node leaves this document.
|
| 516 |
-
function resolveVars(root, resolve) {
|
| 517 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 518 |
-
for (const attr of ["fill", "stroke"]) {
|
| 519 |
-
const value = node.getAttribute(attr);
|
| 520 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 521 |
-
}
|
| 522 |
-
}
|
| 523 |
-
}
|
| 524 |
-
|
| 525 |
-
function legendToSvg(container, resolve) {
|
| 526 |
-
const base = container.getBoundingClientRect();
|
| 527 |
-
const group = document.createElementNS(NS, "g");
|
| 528 |
-
let height = 0;
|
| 529 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 530 |
-
const box = item.getBoundingClientRect();
|
| 531 |
-
if (!box.width) continue;
|
| 532 |
-
height = Math.max(height, box.bottom - base.top);
|
| 533 |
-
let textLeft = box.left - base.left;
|
| 534 |
-
const glyph = item.querySelector("svg");
|
| 535 |
-
if (glyph) {
|
| 536 |
-
const gbox = glyph.getBoundingClientRect();
|
| 537 |
-
const wrap = el("g", {
|
| 538 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 539 |
-
}, group);
|
| 540 |
-
const glyphClone = glyph.cloneNode(true);
|
| 541 |
-
resolveVars(glyphClone, resolve);
|
| 542 |
-
wrap.appendChild(glyphClone);
|
| 543 |
-
textLeft = gbox.right - base.left + 5;
|
| 544 |
-
}
|
| 545 |
-
const label = item.textContent.trim();
|
| 546 |
-
if (!label) continue;
|
| 547 |
-
const colored = item.querySelector("[style*='color']");
|
| 548 |
-
const text = el("text", {
|
| 549 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 550 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 551 |
-
}, group);
|
| 552 |
-
text.textContent = label;
|
| 553 |
-
}
|
| 554 |
-
return { group, height: Math.ceil(height) };
|
| 555 |
-
}
|
| 556 |
-
|
| 557 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 558 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 559 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 560 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 561 |
-
const resolve = value => String(value).replace(
|
| 562 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 563 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 564 |
-
|
| 565 |
-
let chartW = 0, chartH = 0;
|
| 566 |
-
for (const part of parts) {
|
| 567 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 568 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 569 |
-
}
|
| 570 |
-
|
| 571 |
-
const out = document.createElementNS(NS, "svg");
|
| 572 |
-
out.setAttribute("xmlns", NS);
|
| 573 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 574 |
-
let top = pad;
|
| 575 |
-
const later = []; // built after the width is known
|
| 576 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 577 |
-
if (legend && legend.height) {
|
| 578 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 579 |
-
later.push(() => out.appendChild(legend.group));
|
| 580 |
-
top += legend.height + 8;
|
| 581 |
-
}
|
| 582 |
-
|
| 583 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 584 |
-
const height = top + chartH + pad;
|
| 585 |
-
out.setAttribute("width", Math.ceil(width));
|
| 586 |
-
out.setAttribute("height", Math.ceil(height));
|
| 587 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 588 |
-
for (const build of later) build();
|
| 589 |
-
|
| 590 |
-
for (const part of parts) {
|
| 591 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 592 |
-
const clone = part.svg.cloneNode(true);
|
| 593 |
-
resolveVars(clone, resolve);
|
| 594 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 595 |
-
}
|
| 596 |
-
return out;
|
| 597 |
-
}
|
| 598 |
-
|
| 599 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 600 |
-
function slugify(text) {
|
| 601 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 602 |
-
}
|
| 603 |
-
|
| 604 |
-
function downloadUrl(url, filename) {
|
| 605 |
-
const a = document.createElement("a");
|
| 606 |
-
a.href = url;
|
| 607 |
-
a.download = filename;
|
| 608 |
-
document.body.appendChild(a);
|
| 609 |
-
a.click();
|
| 610 |
-
a.remove();
|
| 611 |
-
}
|
| 612 |
-
|
| 613 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 614 |
-
function rasterize(svg, scale, done, fail) {
|
| 615 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 616 |
-
const img = new Image();
|
| 617 |
-
img.onload = () => {
|
| 618 |
-
const canvas = document.createElement("canvas");
|
| 619 |
-
canvas.width = Math.round(width * scale);
|
| 620 |
-
canvas.height = Math.round(height * scale);
|
| 621 |
-
const ctx = canvas.getContext("2d");
|
| 622 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 623 |
-
ctx.drawImage(img, 0, 0);
|
| 624 |
-
done(canvas, width, height);
|
| 625 |
-
};
|
| 626 |
-
img.onerror = fail;
|
| 627 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 628 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 629 |
-
}
|
| 630 |
-
|
| 631 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 632 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 633 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 634 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 635 |
-
// and the pixels land at 96*scale dpi.
|
| 636 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 637 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 638 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 639 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 640 |
-
rgb[j] = pixels[i];
|
| 641 |
-
rgb[j + 1] = pixels[i + 1];
|
| 642 |
-
rgb[j + 2] = pixels[i + 2];
|
| 643 |
-
}
|
| 644 |
-
const deflated = new Uint8Array(await new Response(
|
| 645 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 646 |
-
|
| 647 |
-
const encoder = new TextEncoder();
|
| 648 |
-
const chunks = [];
|
| 649 |
-
const offsets = [];
|
| 650 |
-
let cursor = 0;
|
| 651 |
-
const put = data => {
|
| 652 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 653 |
-
chunks.push(bytes);
|
| 654 |
-
cursor += bytes.length;
|
| 655 |
-
};
|
| 656 |
-
const object = (id, body, stream) => {
|
| 657 |
-
offsets[id] = cursor;
|
| 658 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 659 |
-
if (stream) {
|
| 660 |
-
put("stream\n");
|
| 661 |
-
put(stream);
|
| 662 |
-
put("\nendstream\n");
|
| 663 |
-
}
|
| 664 |
-
put("endobj\n");
|
| 665 |
-
};
|
| 666 |
-
|
| 667 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 668 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 669 |
-
put("%PDF-1.4\n");
|
| 670 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 671 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 672 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 673 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 674 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 675 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 676 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 677 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 678 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 679 |
-
|
| 680 |
-
const xref = cursor;
|
| 681 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 682 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 683 |
-
put(table);
|
| 684 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 685 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 686 |
-
}
|
| 687 |
-
|
| 688 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 689 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 690 |
-
function setUpExport(getParts, basename) {
|
| 691 |
-
const buttons = {
|
| 692 |
-
svg: document.getElementById("btn-svg"),
|
| 693 |
-
png: document.getElementById("btn-png"),
|
| 694 |
-
pdf: document.getElementById("btn-pdf"),
|
| 695 |
-
};
|
| 696 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 697 |
-
|
| 698 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 699 |
-
function complain(format) {
|
| 700 |
-
const button = buttons[format];
|
| 701 |
-
if (!button) return;
|
| 702 |
-
const label = button.textContent;
|
| 703 |
-
button.textContent = "failed";
|
| 704 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 705 |
-
}
|
| 706 |
-
|
| 707 |
-
function run(format) {
|
| 708 |
-
const svg = figure();
|
| 709 |
-
const name = basename();
|
| 710 |
-
if (format === "svg") {
|
| 711 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 712 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 713 |
-
return;
|
| 714 |
-
}
|
| 715 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 716 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 717 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 718 |
-
if (format === "png") {
|
| 719 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 720 |
-
} else {
|
| 721 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 722 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 723 |
-
.catch(() => complain("pdf"));
|
| 724 |
-
}
|
| 725 |
-
}, () => complain(format));
|
| 726 |
-
}
|
| 727 |
-
|
| 728 |
-
for (const format of Object.keys(buttons)) {
|
| 729 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 730 |
-
}
|
| 731 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 732 |
-
window.addEventListener("message", ev => {
|
| 733 |
-
const d = ev.data;
|
| 734 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 735 |
-
});
|
| 736 |
-
}
|
| 737 |
-
|
| 738 |
-
// When embedded, report the content height so the host page can size the
|
| 739 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 740 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 741 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 742 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 743 |
-
// stops re-posting once the height settles.
|
| 744 |
-
let lastPostedHeight = 0;
|
| 745 |
-
function postHeight() {
|
| 746 |
-
if (window.parent === window) return;
|
| 747 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 748 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 749 |
-
lastPostedHeight = height;
|
| 750 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 751 |
-
}
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
const TRAJECTORY = CONFIG.mode === "trajectory";
|
| 755 |
-
|
| 756 |
-
const titleEl = document.getElementById("title");
|
| 757 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 758 |
-
|
| 759 |
-
// Column order: chips/controls left of the chart, or mirrored.
|
| 760 |
-
document.getElementById("grid").classList.add(CONFIG.chipsSide === "right" ? "chips-right" : "chips-left");
|
| 761 |
-
|
| 762 |
-
const svg = document.getElementById("chart");
|
| 763 |
-
const box = document.getElementById("chartbox");
|
| 764 |
-
const chipsBox = document.getElementById("chips");
|
| 765 |
-
const controlsBox = document.querySelector(".controls");
|
| 766 |
-
const tip = makeTooltip(box);
|
| 767 |
-
|
| 768 |
-
// Marker glyph per variant at (cx, cy); trajectories use circles everywhere.
|
| 769 |
-
function drawMark(parent, cx, cy, variant, color, size, opacity, dataM, whiteStroke) {
|
| 770 |
-
const common = { opacity: opacity, "data-m": dataM };
|
| 771 |
-
let node;
|
| 772 |
-
if (TRAJECTORY || variant === "Default" || !variant) {
|
| 773 |
-
node = el("circle", { ...common, cx, cy, r: size, fill: color }, parent);
|
| 774 |
-
} else if (variant === "Tuned") {
|
| 775 |
-
const s = size * 1.75;
|
| 776 |
-
node = el("rect", { ...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1.5, fill: color }, parent);
|
| 777 |
-
} else if (variant === "Tuned + Ens.") {
|
| 778 |
-
const d = size * 0.95;
|
| 779 |
-
node = el("path", {
|
| 780 |
-
...common,
|
| 781 |
-
d: `M${cx - d},${cy - d} L${cx + d},${cy + d} M${cx - d},${cy + d} L${cx + d},${cy - d}`,
|
| 782 |
-
stroke: color, "stroke-width": size * 0.62, fill: "none", "stroke-linecap": "round",
|
| 783 |
-
}, parent);
|
| 784 |
-
} else {
|
| 785 |
-
// Any other variant (e.g. "Baseline", holdout types): diamond.
|
| 786 |
-
const s = size * 1.45;
|
| 787 |
-
node = el("rect", {
|
| 788 |
-
...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1,
|
| 789 |
-
fill: color, transform: `rotate(45 ${cx} ${cy})`,
|
| 790 |
-
}, parent);
|
| 791 |
-
}
|
| 792 |
-
if (whiteStroke && variant !== "Tuned + Ens.") {
|
| 793 |
-
node.setAttribute("stroke", "var(--card)");
|
| 794 |
-
node.setAttribute("stroke-width", "1");
|
| 795 |
-
}
|
| 796 |
-
return node;
|
| 797 |
-
}
|
| 798 |
-
|
| 799 |
-
function drawImputedRing(parent, cx, cy, size, color, opacity, dataM) {
|
| 800 |
-
el("circle", {
|
| 801 |
-
cx, cy, r: size + 4.5, fill: "none", stroke: color, "stroke-width": 1.4,
|
| 802 |
-
"stroke-dasharray": "3 2.5", opacity: opacity, "data-m": dataM,
|
| 803 |
-
}, parent);
|
| 804 |
-
}
|
| 805 |
-
|
| 806 |
-
// Fat green arrow pointing into the optimal corner (mirrors the static
|
| 807 |
-
// figures' "Optimal" arrow so both read the same way).
|
| 808 |
-
function drawOptimalArrow(parent, lowerBetter, M, W, H) {
|
| 809 |
-
const cornerY = lowerBetter ? H - M.b - 12 : M.t + 12;
|
| 810 |
-
const tailY = lowerBetter ? H - M.b - 64 : M.t + 64;
|
| 811 |
-
const cx = M.l + 12, tx = M.l + 64;
|
| 812 |
-
const dx = cx - tx, dy = cornerY - tailY;
|
| 813 |
-
const len = Math.hypot(dx, dy);
|
| 814 |
-
const ux = dx / len, uy = dy / len;
|
| 815 |
-
const headLen = 16;
|
| 816 |
-
const bx = cx - ux * headLen, by = cornerY - uy * headLen; // head base center
|
| 817 |
-
// line stops at the head base
|
| 818 |
-
el("line", {
|
| 819 |
-
x1: tx, y1: tailY, x2: bx, y2: by,
|
| 820 |
-
stroke: "var(--optimal)", "stroke-width": 13, "stroke-linecap": "round", opacity: 0.92,
|
| 821 |
-
}, parent);
|
| 822 |
-
const px = -uy, py = ux; // perpendicular
|
| 823 |
-
el("polygon", {
|
| 824 |
-
points: `${cx},${cornerY} ${bx + px * 11},${by + py * 11} ${bx - px * 11},${by - py * 11}`,
|
| 825 |
-
fill: "var(--optimal)", opacity: 0.92,
|
| 826 |
-
}, parent);
|
| 827 |
-
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
| 828 |
-
if (angle > 90 || angle < -90) angle += 180;
|
| 829 |
-
const mx = (tx + bx) / 2, my = (tailY + by) / 2;
|
| 830 |
-
const t = el("text", {
|
| 831 |
-
x: mx, y: my, "text-anchor": "middle", "dominant-baseline": "middle",
|
| 832 |
-
"font-size": 10.5, "font-weight": 700, fill: "#ffffff",
|
| 833 |
-
transform: `rotate(${angle} ${mx} ${my})`,
|
| 834 |
-
}, parent);
|
| 835 |
-
t.textContent = "Optimal";
|
| 836 |
-
}
|
| 837 |
-
|
| 838 |
-
// ---------- data ----------
|
| 839 |
-
const byMethod = new Map();
|
| 840 |
-
for (const p of POINTS) {
|
| 841 |
-
if (!byMethod.has(p.method)) byMethod.set(p.method, []);
|
| 842 |
-
byMethod.get(p.method).push(p); // insertion order = builder's point order
|
| 843 |
-
}
|
| 844 |
-
|
| 845 |
-
const METRICS = CONFIG.metrics;
|
| 846 |
-
let metricKey = METRICS[0].key;
|
| 847 |
-
const metricByKey = {};
|
| 848 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 849 |
-
|
| 850 |
-
// Single time axis per explorer (the scatter ships inference time, the
|
| 851 |
-
// trajectories train time).
|
| 852 |
-
const X_AXIS = CONFIG.xAxes[0];
|
| 853 |
-
const xKey = X_AXIS.key;
|
| 854 |
-
|
| 855 |
-
function mval(p, metric) { return p[metric.key]; }
|
| 856 |
-
|
| 857 |
-
function computeFront(metric) {
|
| 858 |
-
const xk = xKey;
|
| 859 |
-
const pts = [...POINTS].sort((a, b) =>
|
| 860 |
-
a[xk] - b[xk] || (metric.lowerBetter ? mval(a, metric) - mval(b, metric) : mval(b, metric) - mval(a, metric)));
|
| 861 |
-
const verts = [];
|
| 862 |
-
const methods = new Set();
|
| 863 |
-
let best = null;
|
| 864 |
-
for (const p of pts) {
|
| 865 |
-
const v = mval(p, metric);
|
| 866 |
-
if (best === null || (metric.lowerBetter ? v < best : v > best)) {
|
| 867 |
-
if (best !== null) verts.push([p[xk], best]);
|
| 868 |
-
verts.push([p[xk], v]);
|
| 869 |
-
best = v;
|
| 870 |
-
methods.add(p.method);
|
| 871 |
-
}
|
| 872 |
-
}
|
| 873 |
-
return { verts, methods };
|
| 874 |
-
}
|
| 875 |
-
|
| 876 |
-
const state = { active: new Set(computeFront(metricByKey[metricKey]).methods) };
|
| 877 |
-
|
| 878 |
-
// ---------- chart ----------
|
| 879 |
-
// A flat, fixed-height plot: two of these panels then fit on one screen.
|
| 880 |
-
const CHART_H = 400;
|
| 881 |
-
const M = { l: 62, r: 18, t: 14, b: 52 };
|
| 882 |
-
|
| 883 |
-
function render() {
|
| 884 |
-
const metric = metricByKey[metricKey];
|
| 885 |
-
svg.textContent = "";
|
| 886 |
-
const W = Math.max(360, Math.round(box.clientWidth));
|
| 887 |
-
const H = CHART_H;
|
| 888 |
-
svg.setAttribute("width", W);
|
| 889 |
-
svg.setAttribute("height", H);
|
| 890 |
-
// Keep the chip list from outgrowing the chart beside it.
|
| 891 |
-
chipsBox.style.maxHeight = Math.max(170, H - controlsBox.offsetHeight + 20) + "px";
|
| 892 |
-
|
| 893 |
-
// x scale (log)
|
| 894 |
-
const xsAll = POINTS.map(p => p[xKey]);
|
| 895 |
-
const xmin = Math.min(...xsAll) * 0.65, xmax = Math.max(...xsAll) * 1.6;
|
| 896 |
-
const lx0 = Math.log10(xmin), lx1 = Math.log10(xmax);
|
| 897 |
-
const X = v => M.l + (Math.log10(v) - lx0) / (lx1 - lx0) * (W - M.l - M.r);
|
| 898 |
-
|
| 899 |
-
const vals = POINTS.map(p => mval(p, metric));
|
| 900 |
-
let y0, y1;
|
| 901 |
-
if (metric.fromZero) {
|
| 902 |
-
y0 = 0; y1 = Math.max(...vals) * 1.07;
|
| 903 |
-
} else {
|
| 904 |
-
const pad = (Math.max(...vals) - Math.min(...vals)) * 0.07;
|
| 905 |
-
y0 = Math.min(...vals) - pad; y1 = Math.max(...vals) + pad;
|
| 906 |
-
}
|
| 907 |
-
const Y = v => M.t + (1 - (v - y0) / (y1 - y0)) * (H - M.t - M.b);
|
| 908 |
-
|
| 909 |
-
// grid + axes
|
| 910 |
-
const grid = el("g", {}, svg);
|
| 911 |
-
for (let e = Math.ceil(lx0); Math.pow(10, e) < xmax; e++) {
|
| 912 |
-
const gx = X(Math.pow(10, e));
|
| 913 |
-
el("line", { x1: gx, y1: M.t, x2: gx, y2: H - M.b, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 914 |
-
const lbl = fmtNum(Math.pow(10, e), e >= 0 ? 0 : -e);
|
| 915 |
-
el("text", { x: gx, y: H - M.b + 20, "text-anchor": "middle", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 916 |
-
.textContent = lbl;
|
| 917 |
-
}
|
| 918 |
-
for (const yv of ticks(y0, y1, 6)) {
|
| 919 |
-
const gy = Y(yv);
|
| 920 |
-
el("line", { x1: M.l, y1: gy, x2: W - M.r, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 921 |
-
el("text", { x: M.l - 8, y: gy + 4, "text-anchor": "end", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 922 |
-
.textContent = fmtNum(yv, Number.isInteger(yv) ? 0 : metric.decimals);
|
| 923 |
-
}
|
| 924 |
-
el("rect", { x: M.l, y: M.t, width: W - M.l - M.r, height: H - M.t - M.b, fill: "none", stroke: "var(--line)" }, grid);
|
| 925 |
-
el("text", {
|
| 926 |
-
x: (M.l + W - M.r) / 2, y: H - 10, "text-anchor": "middle", "font-size": 14,
|
| 927 |
-
"font-weight": 650, fill: "var(--ink)",
|
| 928 |
-
}, grid).textContent = X_AXIS.axisLabel;
|
| 929 |
-
el("text", {
|
| 930 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": 14, "font-weight": 650, fill: "var(--ink)",
|
| 931 |
-
transform: `translate(16 ${(M.t + H - M.b) / 2}) rotate(-90)`,
|
| 932 |
-
}, grid).textContent = metric.axisLabel;
|
| 933 |
-
|
| 934 |
-
drawOptimalArrow(grid, metric.lowerBetter, M, W, H);
|
| 935 |
-
|
| 936 |
-
// pareto front (always shown)
|
| 937 |
-
const front = computeFront(metric);
|
| 938 |
-
const fv = front.verts;
|
| 939 |
-
if (fv.length) {
|
| 940 |
-
let d = `M${X(fv[0][0])},${metric.lowerBetter ? M.t : H - M.b}`;
|
| 941 |
-
for (const [fx, fy] of fv) d += ` L${X(fx)},${Y(fy)}`;
|
| 942 |
-
d += ` L${W - M.r},${Y(fv[fv.length - 1][1])}`;
|
| 943 |
-
el("path", { d, fill: "none", stroke: "var(--ink)", "stroke-width": 1.6, "stroke-dasharray": "7 5", opacity: 0.85 }, svg);
|
| 944 |
-
}
|
| 945 |
-
|
| 946 |
-
const isOn = m => state.active.has(m);
|
| 947 |
-
|
| 948 |
-
// connectors: variant links (scatter) / the trajectory itself
|
| 949 |
-
const conn = el("g", {}, svg);
|
| 950 |
-
for (const [method, pts] of byMethod) {
|
| 951 |
-
if (pts.length < 2) continue;
|
| 952 |
-
const on = isOn(method);
|
| 953 |
-
if (!TRAJECTORY && !on) continue; // scatter: connectors only for active methods
|
| 954 |
-
const dd = pts.map((p, i) => `${i ? "L" : "M"}${X(p[xKey])},${Y(mval(p, metric))}`).join(" ");
|
| 955 |
-
el("path", {
|
| 956 |
-
d: dd, fill: "none",
|
| 957 |
-
stroke: on ? FAM_VAR[pts[0].family] : "var(--pt-muted)",
|
| 958 |
-
"stroke-width": on ? (TRAJECTORY ? 2 : 1.4) : 1,
|
| 959 |
-
opacity: on ? 0.6 : 0.35,
|
| 960 |
-
"data-m": method,
|
| 961 |
-
}, conn);
|
| 962 |
-
}
|
| 963 |
-
|
| 964 |
-
// points: inactive first, active on top
|
| 965 |
-
const ptsOff = el("g", {}, svg);
|
| 966 |
-
const ptsOn = el("g", {}, svg);
|
| 967 |
-
for (const [method, pts] of byMethod) {
|
| 968 |
-
const on = isOn(method);
|
| 969 |
-
for (const p of pts) {
|
| 970 |
-
const color = on ? FAM_VAR[p.family] : "var(--pt-muted)";
|
| 971 |
-
const size = (on ? 7 : 5) * (TRAJECTORY ? 0.8 : 1);
|
| 972 |
-
const op = on ? 0.95 : 0.5;
|
| 973 |
-
drawMark(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), p.variant, color, size, op, p.method, on);
|
| 974 |
-
// Imputation ring: every affected point in scatter mode; only the
|
| 975 |
-
// trajectory's end point in trajectory mode (a ring on all ~8 line
|
| 976 |
-
// points would read as beads, and the chip's ‡ already flags the line).
|
| 977 |
-
if (p.imputed && (!TRAJECTORY || p === pts[pts.length - 1])) {
|
| 978 |
-
drawImputedRing(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), size, color, op, p.method);
|
| 979 |
-
}
|
| 980 |
-
}
|
| 981 |
-
}
|
| 982 |
-
|
| 983 |
-
// labels for active methods at their best point, greedy de-overlap
|
| 984 |
-
const labels = [];
|
| 985 |
-
for (const [method, pts] of byMethod) {
|
| 986 |
-
if (!isOn(method)) continue;
|
| 987 |
-
const best = pts.reduce((a, b) =>
|
| 988 |
-
(metric.lowerBetter ? mval(a, metric) < mval(b, metric) : mval(a, metric) > mval(b, metric)) ? a : b);
|
| 989 |
-
labels.push({ method, family: best.family, x: X(best[xKey]) + 10, y: Y(mval(best, metric)) - 10 });
|
| 990 |
-
}
|
| 991 |
-
labels.sort((a, b) => a.y - b.y);
|
| 992 |
-
for (let i = 1; i < labels.length; i++) {
|
| 993 |
-
for (let j = 0; j < i; j++) {
|
| 994 |
-
if (Math.abs(labels[i].x - labels[j].x) < 110 && Math.abs(labels[i].y - labels[j].y) < 15) {
|
| 995 |
-
labels[i].y = labels[j].y + 15;
|
| 996 |
-
}
|
| 997 |
-
}
|
| 998 |
-
}
|
| 999 |
-
const lg = el("g", {}, svg);
|
| 1000 |
-
for (const l of labels) {
|
| 1001 |
-
const t = el("text", {
|
| 1002 |
-
x: Math.min(l.x, W - M.r - 8), y: Math.max(l.y, M.t + 12), "font-size": 13, "font-weight": 700,
|
| 1003 |
-
fill: FAM_VAR[l.family], "paint-order": "stroke", stroke: "var(--card)", "stroke-width": 3.5,
|
| 1004 |
-
"text-anchor": l.x > W - 120 ? "end" : "start",
|
| 1005 |
-
}, lg);
|
| 1006 |
-
t.textContent = l.method;
|
| 1007 |
-
}
|
| 1008 |
-
|
| 1009 |
-
// invisible hit targets on top (bigger than marks)
|
| 1010 |
-
const hits = el("g", {}, svg);
|
| 1011 |
-
for (const p of POINTS) {
|
| 1012 |
-
const h = el("circle", { cx: X(p[xKey]), cy: Y(mval(p, metric)), r: 12, fill: "transparent", cursor: "pointer" }, hits);
|
| 1013 |
-
h.addEventListener("mouseenter", ev => showTip(p, ev));
|
| 1014 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1015 |
-
h.addEventListener("mouseleave", () => hideTip(p.method));
|
| 1016 |
-
h.addEventListener("click", () => toggle(p.method));
|
| 1017 |
-
}
|
| 1018 |
-
}
|
| 1019 |
-
|
| 1020 |
-
// Temporary hover emphasis without a re-render (a re-render would replace
|
| 1021 |
-
// the hit node under the cursor mid-hover).
|
| 1022 |
-
function emphasize(method, on) {
|
| 1023 |
-
svg.querySelectorAll(`[data-m="${CSS.escape(method)}"]`).forEach(n => {
|
| 1024 |
-
if (on) {
|
| 1025 |
-
if (!n.dataset.save) n.dataset.save = n.getAttribute("opacity") || "1";
|
| 1026 |
-
n.setAttribute("opacity", "0.95");
|
| 1027 |
-
} else if (n.dataset.save) {
|
| 1028 |
-
n.setAttribute("opacity", n.dataset.save);
|
| 1029 |
-
delete n.dataset.save;
|
| 1030 |
-
}
|
| 1031 |
-
});
|
| 1032 |
-
}
|
| 1033 |
-
|
| 1034 |
-
function showTip(p, ev) {
|
| 1035 |
-
emphasize(p.method, true);
|
| 1036 |
-
const sub = TRAJECTORY ? (p.n_configs != null ? `${p.n_configs} configs` : "") : (p.variant || "");
|
| 1037 |
-
let html = `<div class="t-name">${p.method}` + (sub ? ` <span class="t-var">(${sub})</span>` : "") + "</div>" +
|
| 1038 |
-
`<div>${p.family}</div>`;
|
| 1039 |
-
for (const m of METRICS) {
|
| 1040 |
-
html += `<div>${m.label}: <b>${fmtMetric(m, mval(p, m))}</b></div>`;
|
| 1041 |
-
}
|
| 1042 |
-
html += `<div>${X_AXIS.short}: <b>${fmtTime(p[xKey])}</b></div>`;
|
| 1043 |
-
if (p.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(p.imputed_pct, 0)}% of datasets</div>`;
|
| 1044 |
-
tip.show(html, ev);
|
| 1045 |
-
}
|
| 1046 |
-
function hideTip(method) {
|
| 1047 |
-
emphasize(method, false);
|
| 1048 |
-
tip.hide();
|
| 1049 |
-
}
|
| 1050 |
-
|
| 1051 |
-
// ---------- chips ----------
|
| 1052 |
-
const chipByMethod = new Map();
|
| 1053 |
-
const famChips = new Map();
|
| 1054 |
-
function familyMethods(fam) {
|
| 1055 |
-
return [...byMethod.keys()].filter(m => byMethod.get(m)[0].family === fam);
|
| 1056 |
-
}
|
| 1057 |
-
// Chips are listed by leaderboard rank — best Elo first when Elo is
|
| 1058 |
-
// configured, otherwise best value of the primary metric.
|
| 1059 |
-
const RANK_METRIC = metricByKey["elo"] || metricByKey[METRICS[0].key];
|
| 1060 |
-
function bestVal(method) {
|
| 1061 |
-
const vals = byMethod.get(method).map(p => mval(p, RANK_METRIC));
|
| 1062 |
-
return RANK_METRIC.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 1063 |
-
}
|
| 1064 |
-
function rankSorted(methods) {
|
| 1065 |
-
return [...methods].sort((a, b) =>
|
| 1066 |
-
RANK_METRIC.lowerBetter ? bestVal(a) - bestVal(b) : bestVal(b) - bestVal(a));
|
| 1067 |
-
}
|
| 1068 |
-
function buildChips() {
|
| 1069 |
-
for (const fam of FAM_ORDER) {
|
| 1070 |
-
const methods = rankSorted(familyMethods(fam));
|
| 1071 |
-
if (!methods.length) continue;
|
| 1072 |
-
const row = document.createElement("div");
|
| 1073 |
-
row.className = "chiprow";
|
| 1074 |
-
const famBtn = document.createElement("button");
|
| 1075 |
-
famBtn.className = "famchip";
|
| 1076 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1077 |
-
famBtn.innerHTML = famChipLabel(fam, methods.length);
|
| 1078 |
-
famBtn.title = `Toggle all ${methods.length} ${fam} methods`;
|
| 1079 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1080 |
-
row.appendChild(famBtn);
|
| 1081 |
-
famChips.set(fam, famBtn);
|
| 1082 |
-
const set = document.createElement("div");
|
| 1083 |
-
set.className = "chipset";
|
| 1084 |
-
for (const m of methods) {
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "chip";
|
| 1087 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1088 |
-
const imputed = byMethod.get(m).some(p => p.imputed);
|
| 1089 |
-
const label = document.createElement("span");
|
| 1090 |
-
label.textContent = m;
|
| 1091 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1092 |
-
b.appendChild(label);
|
| 1093 |
-
if (imputed) {
|
| 1094 |
-
const mark = document.createElement("span");
|
| 1095 |
-
mark.className = "imp-mark";
|
| 1096 |
-
mark.textContent = "‡";
|
| 1097 |
-
b.appendChild(mark);
|
| 1098 |
-
}
|
| 1099 |
-
b.title = m + (imputed ? " — partially imputed" : "");
|
| 1100 |
-
b.addEventListener("click", () => toggle(m));
|
| 1101 |
-
set.appendChild(b);
|
| 1102 |
-
chipByMethod.set(m, b);
|
| 1103 |
-
}
|
| 1104 |
-
row.appendChild(set);
|
| 1105 |
-
chipsBox.appendChild(row);
|
| 1106 |
-
}
|
| 1107 |
-
}
|
| 1108 |
-
function syncChips() {
|
| 1109 |
-
for (const [m, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.active.has(m)));
|
| 1110 |
-
for (const [fam, b] of famChips) {
|
| 1111 |
-
b.setAttribute("aria-pressed", String(familyMethods(fam).every(m => state.active.has(m))));
|
| 1112 |
-
}
|
| 1113 |
-
}
|
| 1114 |
-
function toggle(m) {
|
| 1115 |
-
if (state.active.has(m)) state.active.delete(m); else state.active.add(m);
|
| 1116 |
-
syncChips();
|
| 1117 |
-
render();
|
| 1118 |
-
}
|
| 1119 |
-
function toggleFamily(fam) {
|
| 1120 |
-
const methods = familyMethods(fam);
|
| 1121 |
-
const allOn = methods.every(m => state.active.has(m));
|
| 1122 |
-
for (const m of methods) {
|
| 1123 |
-
if (allOn) state.active.delete(m); else state.active.add(m);
|
| 1124 |
-
}
|
| 1125 |
-
syncChips();
|
| 1126 |
-
render();
|
| 1127 |
-
}
|
| 1128 |
-
function setActive(methods) {
|
| 1129 |
-
state.active = new Set(methods);
|
| 1130 |
-
syncChips();
|
| 1131 |
-
render();
|
| 1132 |
-
}
|
| 1133 |
-
document.getElementById("btn-front").addEventListener("click",
|
| 1134 |
-
() => setActive(computeFront(metricByKey[metricKey]).methods));
|
| 1135 |
-
document.getElementById("btn-all").addEventListener("click", () => setActive([...byMethod.keys()]));
|
| 1136 |
-
document.getElementById("btn-none").addEventListener("click", () => setActive([]));
|
| 1137 |
-
|
| 1138 |
-
// metric selector (hidden when only one metric is configured)
|
| 1139 |
-
const metricPick = document.getElementById("metricpick");
|
| 1140 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1141 |
-
if (METRICS.length > 1) {
|
| 1142 |
-
metricPick.hidden = false;
|
| 1143 |
-
for (const m of METRICS) {
|
| 1144 |
-
const opt = document.createElement("option");
|
| 1145 |
-
opt.value = m.key;
|
| 1146 |
-
opt.textContent = m.label;
|
| 1147 |
-
metricSelect.appendChild(opt);
|
| 1148 |
-
}
|
| 1149 |
-
metricSelect.addEventListener("change", ev => {
|
| 1150 |
-
metricKey = ev.target.value;
|
| 1151 |
-
render();
|
| 1152 |
-
});
|
| 1153 |
-
}
|
| 1154 |
-
|
| 1155 |
-
// ---------- legend strip ----------
|
| 1156 |
-
function buildLegend() {
|
| 1157 |
-
const box2 = document.getElementById("legendstrip");
|
| 1158 |
-
let html = "";
|
| 1159 |
-
if (!TRAJECTORY) {
|
| 1160 |
-
html +=
|
| 1161 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><circle cx="7" cy="7" r="5" fill="var(--muted)"/></svg> Default</span>' +
|
| 1162 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" rx="1.5" fill="var(--muted)"/></svg> Tuned</span>' +
|
| 1163 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><path d="M3,3 L11,11 M3,11 L11,3" stroke="var(--muted)" stroke-width="2.6" stroke-linecap="round"/></svg> Tuned + Ensembled</span>';
|
| 1164 |
-
} else {
|
| 1165 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--muted)" stroke-width="2"/><circle cx="6" cy="4" r="2.6" fill="var(--muted)"/><circle cx="16" cy="4" r="2.6" fill="var(--muted)"/></svg> Tuning trajectory (more configs → more time)</span>';
|
| 1166 |
-
}
|
| 1167 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--ink)" stroke-width="1.6" stroke-dasharray="6 4"/></svg> Pareto front (always shown)</span>';
|
| 1168 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1169 |
-
html += '<span class="item"><svg width="18" height="18" viewBox="0 0 18 18"><circle cx="9" cy="9" r="4" fill="var(--muted)"/><circle cx="9" cy="9" r="7.5" fill="none" stroke="var(--muted)" stroke-width="1.3" stroke-dasharray="3 2.5"/></svg> ‡ partially imputed</span>';
|
| 1170 |
-
}
|
| 1171 |
-
// Model family, named: highlighted points are colored by family, and in paper
|
| 1172 |
-
// view the chip list that would otherwise decode them is hidden.
|
| 1173 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => p.family === f));
|
| 1174 |
-
if (families.length > 1) {
|
| 1175 |
-
html += '<span class="legendbreak"></span><span class="item">Family:</span>';
|
| 1176 |
-
for (const fam of families) {
|
| 1177 |
-
html += `<span class="item"><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1178 |
-
`<circle cx="6" cy="6" r="5" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1179 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`;
|
| 1180 |
-
}
|
| 1181 |
-
}
|
| 1182 |
-
box2.innerHTML = html;
|
| 1183 |
-
}
|
| 1184 |
-
|
| 1185 |
-
// ---------- paper view ----------
|
| 1186 |
-
setUpPaperView(render);
|
| 1187 |
-
setUpExport(() => [{ svg: svg, dx: 0 }], () => slugify(document.title));
|
| 1188 |
-
|
| 1189 |
-
// ---------- data table ----------
|
| 1190 |
-
function buildTable() {
|
| 1191 |
-
const m0 = metricByKey[METRICS[0].key];
|
| 1192 |
-
const rows = [...POINTS].sort((a, b) =>
|
| 1193 |
-
m0.lowerBetter ? mval(a, m0) - mval(b, m0) : mval(b, m0) - mval(a, m0));
|
| 1194 |
-
let html = "<table><thead><tr><th>Method</th>";
|
| 1195 |
-
html += TRAJECTORY ? "<th>Configs</th>" : "<th>Variant</th>";
|
| 1196 |
-
html += "<th>Family</th>";
|
| 1197 |
-
for (const m of METRICS) html += `<th>${m.label}</th>`;
|
| 1198 |
-
html += `<th>${X_AXIS.short}</th><th>Imputed</th></tr></thead><tbody>`;
|
| 1199 |
-
for (const p of rows) {
|
| 1200 |
-
html += `<tr><td>${p.method}</td><td>${TRAJECTORY ? (p.n_configs != null ? p.n_configs : "—") : p.variant}</td><td>${p.family}</td>`;
|
| 1201 |
-
for (const m of METRICS) html += `<td>${fmtMetric(m, mval(p, m))}</td>`;
|
| 1202 |
-
html += `<td>${fmtNum(p[xKey], 3)}</td>`;
|
| 1203 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1204 |
-
}
|
| 1205 |
-
html += "</tbody></table>";
|
| 1206 |
-
document.getElementById("tblwrap").innerHTML = html;
|
| 1207 |
-
}
|
| 1208 |
-
|
| 1209 |
-
const _renderInner = render;
|
| 1210 |
-
render = function () {
|
| 1211 |
-
_renderInner();
|
| 1212 |
-
postHeight();
|
| 1213 |
-
};
|
| 1214 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1215 |
-
let resizeTimer = null;
|
| 1216 |
-
window.addEventListener("resize", () => {
|
| 1217 |
-
clearTimeout(resizeTimer);
|
| 1218 |
-
resizeTimer = setTimeout(render, 120);
|
| 1219 |
-
});
|
| 1220 |
-
window.addEventListener("load", postHeight);
|
| 1221 |
-
|
| 1222 |
-
buildChips();
|
| 1223 |
-
buildLegend();
|
| 1224 |
-
buildTable();
|
| 1225 |
-
syncChips();
|
| 1226 |
-
render();
|
| 1227 |
-
})();
|
| 1228 |
-
</script>
|
| 1229 |
-
</body>
|
| 1230 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/pareto_front_improvability_vs_time_infer.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:2d4ed0a9b275cd8602f4dbb38201fd6cc8918d6896ec8e750f4a8cb6d2d2196d
|
| 3 |
-
size 264726
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/pareto_front_points.csv
DELETED
|
@@ -1,63 +0,0 @@
|
|
| 1 |
-
method,variant,family,x_infer,x_train,imp,elo,imputed,imputed_pct
|
| 2 |
-
TabFM,Default,Foundation Model,6.985429071794801,38.805908867807105,4.074482364796911,1791.7,False,0.0
|
| 3 |
-
TabPFN-3,Default,Foundation Model,0.3988194969093643,3.6584650300170622,9.32829663379356,1665.3,False,0.0
|
| 4 |
-
TabPFN-2.6,Default,Foundation Model,0.5548034626013535,5.482579877802832,10.750545524440877,1619.8,False,0.0
|
| 5 |
-
RealTabPFN-2.5,Tuned + Ens.,Foundation Model,8.907660220396073,2040.2228420972824,10.4265657302182,1594.9,False,0.0
|
| 6 |
-
TabICLv2,Default,Foundation Model,0.15054921462491172,2.0524528171730156,10.175153831453988,1593.7,False,0.0
|
| 7 |
-
RealTabPFN-2.5,Tuned,Foundation Model,1.217878699427239,2040.2228420972824,11.11614833993503,1554.3,False,0.0
|
| 8 |
-
RealTabPFN-2.5,Default,Foundation Model,0.644969598113518,5.809798529870024,11.66045120270563,1524.4,False,0.0
|
| 9 |
-
RealMLP,Tuned + Ens.,Neural Network,11.974985376498216,2950.724447694827,12.881492492932924,1507.9,False,0.0
|
| 10 |
-
TabDPT-Turbo,Default,Foundation Model,0.18241940288749647,2.06768405148355,13.999843249302529,1459.4,False,0.0
|
| 11 |
-
TabDPT,Tuned + Ens.,Foundation Model,286.53737883567806,4910.377306237253,13.787925083199838,1457.8,False,0.0
|
| 12 |
-
TabM,Tuned + Ens.,Neural Network,2.246865858634313,2450.1270774379373,14.080621083598398,1450.2,False,0.0
|
| 13 |
-
LightGBM,Tuned + Ens.,Tree-based,2.638673830958025,417.0474735648702,15.033496734155674,1432.9,False,0.0
|
| 14 |
-
RealMLP,Tuned,Neural Network,0.663132054971364,2950.724447694827,14.202181797556316,1426.4,False,0.0
|
| 15 |
-
CatBoost,Tuned + Ens.,Tree-based,0.3442282032056243,1346.210691180287,14.655679872953623,1421.5,False,0.0
|
| 16 |
-
CatBoost,Tuned,Tree-based,0.03809286543601384,1346.210691180287,14.885063048465241,1408.1,False,0.0
|
| 17 |
-
iLTM,Tuned + Ens.,Foundation Model,464.3696034625343,12685.081550183375,15.303555132389759,1404.5,False,0.0
|
| 18 |
-
TabDPT,Tuned,Foundation Model,39.95973646029047,4910.377306237253,14.936053240835797,1402.6,False,0.0
|
| 19 |
-
TabM,Tuned,Neural Network,0.25129394622912726,2450.1270774379373,14.951713350982976,1393.6,False,0.0
|
| 20 |
-
ModernNCA,Tuned + Ens.,Neural Network,8.137916867537678,4621.665633563503,15.598545807661889,1389.4,False,0.0
|
| 21 |
-
LightGBM,Tuned,Tree-based,0.3337603531487198,417.0474735648702,15.687611694327014,1385.7,False,0.0
|
| 22 |
-
CatBoost,Default,Tree-based,0.02489617665608724,5.876676442022475,15.524440818146829,1378.5,False,0.0
|
| 23 |
-
XGBoost,Tuned + Ens.,Tree-based,1.6894451629541256,693.4907982506384,15.753819542791774,1375.0,False,0.0
|
| 24 |
-
LimiX,Default,Foundation Model,6.2423742585450634,26.459751268166386,15.526302545921503,1362.6,False,0.0
|
| 25 |
-
ModernNCA,Tuned,Neural Network,0.4747242314576746,4621.665633563503,16.043959051908736,1355.2,False,0.0
|
| 26 |
-
TabSwift,Default,Foundation Model,0.07196837694453946,1.1753394519011986,16.080743288565568,1350.4,False,0.0
|
| 27 |
-
XGBoost,Tuned,Tree-based,0.3080760155405317,693.4907982506384,16.065044325649545,1350.1,False,0.0
|
| 28 |
-
xRFM,Tuned + Ens.,Other,2.549259534903935,846.8860702336882,16.284217975386294,1347.6,False,0.0
|
| 29 |
-
ChimeraBoost,Tuned + Ens.,Tree-based,0.4040760969279745,427.39175038402846,17.212551464527458,1333.4,False,0.0
|
| 30 |
-
TabDPT,Default,Foundation Model,43.737812222627376,47.64668788909912,17.225282770201353,1324.7,False,0.0
|
| 31 |
-
ChimeraBoost,Tuned,Tree-based,0.033651277628640924,427.39175038402846,17.551093954280812,1308.4,False,0.0
|
| 32 |
-
xRFM,Tuned,Other,0.13027435019228545,846.8860702336882,17.449220868675354,1300.2,False,0.0
|
| 33 |
-
TabM,Default,Neural Network,0.2435252328360982,7.486463968520102,17.00014333184639,1297.6,False,0.0
|
| 34 |
-
iLTM,Tuned,Foundation Model,62.129902117180094,12685.081550183375,17.147247379128842,1295.0,False,0.0
|
| 35 |
-
TorchMLP,Tuned + Ens.,Neural Network,1.9516254299583915,2875.520340774675,17.161152358690444,1285.2,False,0.0
|
| 36 |
-
SAP-RPT-OSS,Default,Foundation Model,2.0745579697490073,14.11326684554418,18.278320508713314,1283.4,False,0.0
|
| 37 |
-
EBM,Tuned + Ens.,Tree-based,0.14129001235465857,1711.2458519871225,18.672215711732292,1271.5,False,0.0
|
| 38 |
-
ChimeraBoost,Default,Tree-based,0.032584832539708695,1.9886321895080843,18.657087753455368,1263.9,False,0.0
|
| 39 |
-
ModernNCA,Default,Neural Network,0.3073466783584545,14.869686344646652,19.19422942055122,1248.1,False,0.0
|
| 40 |
-
EBM,Tuned,Tree-based,0.015030898720760692,1711.2458519871225,19.313668280627464,1235.3,False,0.0
|
| 41 |
-
RealMLP,Default,Neural Network,1.688795494836301,10.05564923800873,18.569226672945717,1229.7,False,0.0
|
| 42 |
-
XGBoost,Default,Tree-based,0.12262328807300621,1.9409389396340444,18.792223322104178,1214.2,False,0.0
|
| 43 |
-
TorchMLP,Tuned,Neural Network,0.131112832826372,2875.520340774675,18.87687891401735,1211.5,False,0.0
|
| 44 |
-
ExtraTrees,Tuned + Ens.,Tree-based,0.7662402324832739,263.0379305178949,19.777389199117614,1208.5,False,0.0
|
| 45 |
-
FastaiMLP,Tuned + Ens.,Neural Network,4.466695070266724,593.237788402893,19.676871164178753,1207.0,False,0.0
|
| 46 |
-
EBM,Default,Tree-based,0.014352864847965238,6.673146850898109,20.25536331915339,1203.8,False,0.0
|
| 47 |
-
LightGBM,Default,Tree-based,0.14167879422505697,1.9600326879612946,19.344291592086606,1186.4,False,0.0
|
| 48 |
-
ExtraTrees,Tuned,Tree-based,0.07121299392949774,263.0379305178949,20.563808515074136,1180.5,False,0.0
|
| 49 |
-
RandomForest,Tuned + Ens.,Tree-based,0.7709478321252661,373.23710550957964,20.828476433186648,1170.8,False,0.0
|
| 50 |
-
FastaiMLP,Tuned,Neural Network,0.306391541190021,593.237788402893,21.096318521849227,1146.9,False,0.0
|
| 51 |
-
RandomForest,Tuned,Tree-based,0.08522791862487794,373.23710550957964,21.53504578065053,1137.1,False,0.0
|
| 52 |
-
TabSTAR,Tuned,Foundation Model,4.26805346323971,28729.737365569254,25.584307557024438,1097.3,False,0.0
|
| 53 |
-
TabSTAR,Tuned + Ens.,Foundation Model,18.8114333152771,28729.737365569254,25.600075428140812,1096.0,False,0.0
|
| 54 |
-
iLTM,Default,Foundation Model,68.17329693701195,296.63929176158115,23.023643328901947,1094.5,False,0.0
|
| 55 |
-
PerpetualBooster,Tuned + Ens.,Tree-based,0.5997539679209392,185.306705652078,26.44564252568807,1088.7,False,0.0
|
| 56 |
-
TorchMLP,Default,Neural Network,0.1258046787872722,9.99256321379882,22.815130870764776,1074.3,False,0.0
|
| 57 |
-
PerpetualBooster,Tuned,Tree-based,0.2581384468078613,185.306705652078,27.8016434929848,1050.3,False,0.0
|
| 58 |
-
xRFM,Default,Other,0.9186215875564591,3.2328671519382346,26.44486339439917,1043.4,False,0.0
|
| 59 |
-
ExtraTrees,Default,Tree-based,0.28340813208977944,1.8719729433204921,26.176496328475334,1009.0,False,0.0
|
| 60 |
-
FastaiMLP,Default,Neural Network,0.37317813888351864,2.856149195889622,25.681854522852465,1007.8,False,0.0
|
| 61 |
-
RandomForest,Default,Tree-based,0.05354057584727896,0.43432508267329906,26.26500423038912,1000.0,False,0.0
|
| 62 |
-
TabSTAR,Default,Foundation Model,5.348086842145453,384.74563018139656,30.455609940739038,993.3,False,0.0
|
| 63 |
-
PerpetualBooster,Default,Tree-based,0.028580506642659504,27.322832322961396,31.748055193831643,936.2,False,0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/pareto_n_configs_imp.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:036d780a68a23a2cff1d510eff9811401d88a26d7c4bad96d0ef045517bfa96a
|
| 3 |
-
size 293312
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/tuning-impact-elo.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:2a267fd19bf63d233f1b8548b957a1c2486976a3da3ecf03e3879cf153f323cc
|
| 3 |
-
size 105318
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/tuning_trajectories.csv
DELETED
|
@@ -1,163 +0,0 @@
|
|
| 1 |
-
method,family,x_train,x_infer,imp,elo,n_configs,imputed,imputed_pct
|
| 2 |
-
CatBoost,Tree-based,5.876676442022475,0.02489617665608724,15.545773630432649,1392.9,1.0,False,0.0
|
| 3 |
-
CatBoost,Tree-based,11.667825125586923,0.06336535482356946,15.118241955137155,1413.1,2.0,False,0.0
|
| 4 |
-
CatBoost,Tree-based,31.910651762403862,0.11771650741480857,14.848578649025981,1430.8,5.0,False,0.0
|
| 5 |
-
CatBoost,Tree-based,62.57212517570079,0.1714353465164701,14.747756855813183,1435.8,10.0,False,0.0
|
| 6 |
-
CatBoost,Tree-based,155.90493556689327,0.22162205257045137,14.640617769474321,1441.2,25.0,False,0.0
|
| 7 |
-
CatBoost,Tree-based,317.34591689097914,0.2666794694644051,14.63114463814291,1441.7,50.0,False,0.0
|
| 8 |
-
CatBoost,Tree-based,662.4830210733933,0.31052760007315267,14.647846561269168,1440.2,100.0,False,0.0
|
| 9 |
-
CatBoost,Tree-based,998.8498259224127,0.340735055101516,14.667356369432946,1438.8,150.0,False,0.0
|
| 10 |
-
CatBoost,Tree-based,1346.210691180287,0.344857002822471,14.674240095020256,1437.7,201.0,False,0.0
|
| 11 |
-
ChimeraBoost,Tree-based,1.9886321895080843,0.032584832539708695,18.678063113906685,1273.2,1.0,False,0.0
|
| 12 |
-
ChimeraBoost,Tree-based,4.43838502030943,0.06094444009053425,18.336632808534546,1294.1,2.0,False,0.0
|
| 13 |
-
ChimeraBoost,Tree-based,10.070184857413143,0.1129020180967119,18.11679730595953,1307.5,5.0,False,0.0
|
| 14 |
-
ChimeraBoost,Tree-based,20.473417816445547,0.17710346910688612,17.925973974729047,1318.0,10.0,False,0.0
|
| 15 |
-
ChimeraBoost,Tree-based,52.71737575557528,0.24549033666046208,17.653702793765603,1330.8,25.0,False,0.0
|
| 16 |
-
ChimeraBoost,Tree-based,106.3941874905326,0.2926890222079797,17.502292085061757,1338.7,50.0,False,0.0
|
| 17 |
-
ChimeraBoost,Tree-based,212.82074782052993,0.3120254129614995,17.33931475498968,1346.0,100.0,False,0.0
|
| 18 |
-
ChimeraBoost,Tree-based,318.99571798382766,0.3237207715925697,17.270003424423187,1348.8,150.0,False,0.0
|
| 19 |
-
ChimeraBoost,Tree-based,427.39175038402846,0.4040760969279745,17.232645726102113,1351.7,201.0,False,0.0
|
| 20 |
-
EBM,Tree-based,6.673146850898109,0.014352864847965238,20.275933791848207,1208.2,1.0,False,0.0
|
| 21 |
-
EBM,Tree-based,16.576534345676816,0.030424724199585355,19.878683743638497,1222.7,2.0,False,0.0
|
| 22 |
-
EBM,Tree-based,47.738558903301914,0.052842477784541445,19.453429661489196,1243.5,5.0,False,0.0
|
| 23 |
-
EBM,Tree-based,89.41107246991604,0.0702878348384009,19.272670456493394,1252.8,10.0,False,0.0
|
| 24 |
-
EBM,Tree-based,218.44812470797967,0.09747169882795435,19.043819281561163,1263.4,25.0,False,0.0
|
| 25 |
-
EBM,Tree-based,440.25457359654257,0.11411218718429054,18.902341183605127,1271.7,50.0,False,0.0
|
| 26 |
-
EBM,Tree-based,856.7647171052814,0.12772155113709277,18.78039180099042,1278.4,100.0,False,0.0
|
| 27 |
-
EBM,Tree-based,1266.0910927829382,0.13762164045367722,18.736984316643394,1281.9,150.0,False,0.0
|
| 28 |
-
EBM,Tree-based,1711.2458519871225,0.1384442291079833,18.69454550084852,1284.9,201.0,False,0.0
|
| 29 |
-
ExtraTrees,Tree-based,1.8719729433204921,0.28340813208977944,26.19484841286617,1009.7,1.0,False,0.0
|
| 30 |
-
ExtraTrees,Tree-based,3.1259596547771116,0.299267558256785,24.34885423133725,1053.5,2.0,False,0.0
|
| 31 |
-
ExtraTrees,Tree-based,6.772191225672007,0.3233863551370985,21.682680228814046,1124.8,5.0,False,0.0
|
| 32 |
-
ExtraTrees,Tree-based,13.288092341970305,0.39167570468287294,20.760558802976053,1165.9,10.0,False,0.0
|
| 33 |
-
ExtraTrees,Tree-based,32.8419339595057,0.4883309222469785,20.10698573925726,1197.4,25.0,False,0.0
|
| 34 |
-
ExtraTrees,Tree-based,65.49386348647792,0.56779316986261,19.944577260601946,1207.8,50.0,False,0.0
|
| 35 |
-
ExtraTrees,Tree-based,130.83697151858863,0.6638268741052196,19.834039933936086,1214.7,100.0,False,0.0
|
| 36 |
-
ExtraTrees,Tree-based,196.22448049705483,0.7241674769499868,19.791012646492206,1218.9,150.0,False,0.0
|
| 37 |
-
ExtraTrees,Tree-based,263.0379305178949,0.7662402324832739,19.798451388325567,1219.9,201.0,False,0.0
|
| 38 |
-
FastaiMLP,Neural Network,2.856149195889622,0.37317813888351864,25.701345794106835,1012.4,1.0,False,0.0
|
| 39 |
-
FastaiMLP,Neural Network,5.5343795003616165,0.6641420918672822,24.502014126684376,1049.9,2.0,False,0.0
|
| 40 |
-
FastaiMLP,Neural Network,14.55103442753632,1.1863927783450354,22.653470439457397,1116.6,5.0,False,0.0
|
| 41 |
-
FastaiMLP,Neural Network,29.7233431539627,1.7323440480232237,21.746441627597715,1149.9,10.0,False,0.0
|
| 42 |
-
FastaiMLP,Neural Network,72.5444980812019,2.392081415581216,20.845819728470904,1180.3,25.0,False,0.0
|
| 43 |
-
FastaiMLP,Neural Network,145.75437119097205,3.1392189600815126,20.39162631932187,1196.9,50.0,False,0.0
|
| 44 |
-
FastaiMLP,Neural Network,293.94750082788664,3.8048101374308265,20.04889167045696,1207.2,100.0,False,0.0
|
| 45 |
-
FastaiMLP,Neural Network,441.8525399102105,4.207369513432185,19.826636643046832,1215.4,150.0,False,0.0
|
| 46 |
-
FastaiMLP,Neural Network,593.237788402893,4.45581943154335,19.693526906883832,1220.6,201.0,False,0.0
|
| 47 |
-
LightGBM,Tree-based,1.9600326879612946,0.14167879422505697,19.36479217453779,1188.7,1.0,False,0.0
|
| 48 |
-
LightGBM,Tree-based,4.146536889124949,0.6924533471949544,17.853666842868513,1267.1,2.0,False,0.0
|
| 49 |
-
LightGBM,Tree-based,10.390743356824784,0.9306682768676963,16.68551387028264,1346.2,5.0,False,0.0
|
| 50 |
-
LightGBM,Tree-based,20.270167537261766,1.197546153728451,16.08404982178837,1386.9,10.0,False,0.0
|
| 51 |
-
LightGBM,Tree-based,51.48744833401502,1.50753196069901,15.52809643468747,1421.6,25.0,False,0.0
|
| 52 |
-
LightGBM,Tree-based,103.68557420134589,1.674099392656769,15.31584330152404,1437.2,50.0,False,0.0
|
| 53 |
-
LightGBM,Tree-based,207.54351147839122,2.0960239899208046,15.155215757412046,1447.7,100.0,False,0.0
|
| 54 |
-
LightGBM,Tree-based,310.2926532568141,2.2957707359829054,15.093355735444023,1451.2,150.0,False,0.0
|
| 55 |
-
LightGBM,Tree-based,417.0474735648702,2.638673830958025,15.056180468340754,1453.8,201.0,False,0.0
|
| 56 |
-
LimiX,Foundation Model,26.459751268166386,6.2423742585450634,15.4843630348554,1381.2,1.0,False,0.0
|
| 57 |
-
ModernNCA,Neural Network,14.869686344646652,0.3073466783584545,19.214634854684004,1258.8,1.0,False,0.0
|
| 58 |
-
ModernNCA,Neural Network,40.51716877036181,0.8515440487861633,17.923544469309995,1296.1,2.0,False,0.0
|
| 59 |
-
ModernNCA,Neural Network,111.44983108853623,1.746831801986318,16.005200974400687,1381.4,5.0,False,0.0
|
| 60 |
-
ModernNCA,Neural Network,224.92944042496907,2.5416509890556336,15.514065161520602,1406.1,10.0,False,0.0
|
| 61 |
-
ModernNCA,Neural Network,554.8880523029388,4.032296481132508,15.005455193102883,1431.4,25.0,False,0.0
|
| 62 |
-
ModernNCA,Neural Network,1145.4516650488413,5.448522539138794,15.052960698398241,1428.7,50.0,False,0.0
|
| 63 |
-
ModernNCA,Neural Network,2295.4928354707367,6.931406373977661,15.312154787900578,1419.9,100.0,False,0.0
|
| 64 |
-
ModernNCA,Neural Network,3433.7924746693766,7.728596683131394,15.511417949160927,1411.9,150.0,False,0.0
|
| 65 |
-
ModernNCA,Neural Network,4621.665633563503,8.137916867537678,15.625323263302192,1406.7,201.0,False,0.0
|
| 66 |
-
PerpetualBooster,Tree-based,27.322832322961396,0.028580506642659504,32.25100598233364,936.7,1.0,False,0.0
|
| 67 |
-
PerpetualBooster,Tree-based,60.33046553317705,0.23376323541005453,30.003028571926745,1001.6,2.0,False,0.0
|
| 68 |
-
PerpetualBooster,Tree-based,157.39589541510517,0.5732905745506287,26.632005416466946,1088.2,5.0,False,0.0
|
| 69 |
-
PerpetualBooster,Tree-based,185.306705652078,0.5997539679209392,26.460216259374146,1095.6,6.0,False,0.0
|
| 70 |
-
RandomForest,Tree-based,0.43432508267329906,0.05354057584727896,26.293240248827328,999.4,1.0,False,0.0
|
| 71 |
-
RandomForest,Tree-based,2.300696812702446,0.11877280473082547,23.63129314546007,1058.9,2.0,False,0.0
|
| 72 |
-
RandomForest,Tree-based,7.869405165361387,0.23579108802464072,22.294500271065914,1101.7,5.0,False,0.0
|
| 73 |
-
RandomForest,Tree-based,17.24737248948874,0.34062966640910297,21.59813362204917,1131.3,10.0,False,0.0
|
| 74 |
-
RandomForest,Tree-based,45.0373615696637,0.5043278961482858,21.108236480738782,1162.1,25.0,False,0.0
|
| 75 |
-
RandomForest,Tree-based,91.39172333285852,0.5878338983942606,20.976376645285406,1170.7,50.0,False,0.0
|
| 76 |
-
RandomForest,Tree-based,184.69967416087664,0.6965050641895468,20.889389653111095,1176.8,100.0,False,0.0
|
| 77 |
-
RandomForest,Tree-based,277.8099565315396,0.7595438384705165,20.8512167325917,1179.4,150.0,False,0.0
|
| 78 |
-
RandomForest,Tree-based,373.23710550957964,0.7784693873625508,20.846353319166443,1181.1,201.0,False,0.0
|
| 79 |
-
RealMLP,Neural Network,10.05564923800873,1.688795494836301,18.590239453484394,1235.3,1.0,False,0.0
|
| 80 |
-
RealMLP,Neural Network,24.67055944083978,2.4593014940325313,16.23691942847831,1345.9,2.0,False,0.0
|
| 81 |
-
RealMLP,Neural Network,69.64352733395047,3.7162198129739616,14.560737750122787,1438.2,5.0,False,0.0
|
| 82 |
-
RealMLP,Neural Network,141.15299775889818,5.676482463380541,13.942792911633916,1472.7,10.0,False,0.0
|
| 83 |
-
RealMLP,Neural Network,364.60114695980747,7.847718735760291,13.467173212944909,1502.2,25.0,False,0.0
|
| 84 |
-
RealMLP,Neural Network,736.9754853515838,9.767676536105808,13.247150637288602,1515.4,50.0,False,0.0
|
| 85 |
-
RealMLP,Neural Network,1469.265397304651,11.259146773020426,13.064776423132237,1524.1,100.0,False,0.0
|
| 86 |
-
RealMLP,Neural Network,2197.532004168663,12.053178920512211,12.972203262678384,1529.9,150.0,False,0.0
|
| 87 |
-
RealMLP,Neural Network,2950.724447694827,12.377824840296128,12.904667349438354,1532.8,201.0,False,0.0
|
| 88 |
-
RealTabPFN-2.5,Foundation Model,5.809798529870024,0.644969598113518,11.683982092880285,1538.3,1.0,False,0.0
|
| 89 |
-
RealTabPFN-2.5,Foundation Model,16.695089235760015,1.4031929555826625,11.614346808353798,1544.7,2.0,False,0.0
|
| 90 |
-
RealTabPFN-2.5,Foundation Model,45.81806103711327,2.874227223348986,11.2924871479828,1561.1,5.0,False,0.0
|
| 91 |
-
RealTabPFN-2.5,Foundation Model,96.05664533202847,4.09552534439249,11.111189934935469,1578.5,10.0,False,0.0
|
| 92 |
-
RealTabPFN-2.5,Foundation Model,245.14109091684222,5.753407464362681,10.868476470961895,1599.1,25.0,False,0.0
|
| 93 |
-
RealTabPFN-2.5,Foundation Model,498.5667116885384,6.850076117335025,10.686824052693943,1608.6,50.0,False,0.0
|
| 94 |
-
RealTabPFN-2.5,Foundation Model,1015.1487598759433,7.792073605314185,10.568015672278301,1613.1,100.0,False,0.0
|
| 95 |
-
RealTabPFN-2.5,Foundation Model,1526.7130408425285,8.999759905935408,10.507654206859593,1614.3,150.0,False,0.0
|
| 96 |
-
RealTabPFN-2.5,Foundation Model,2040.2228420972824,9.030681926100565,10.455540657911111,1613.3,201.0,False,0.0
|
| 97 |
-
SAP-RPT-OSS,Foundation Model,14.11326684554418,2.0745579697490073,18.2986171533795,1297.7,1.0,False,0.0
|
| 98 |
-
TabDPT,Foundation Model,47.64668788909912,43.737812222627376,17.244714242411675,1337.6,1.0,False,0.0
|
| 99 |
-
TabDPT,Foundation Model,70.40721927502358,57.29898182743639,16.427375964657816,1364.1,2.0,False,0.0
|
| 100 |
-
TabDPT,Foundation Model,132.97854094385033,81.7804361753873,15.612978495749699,1399.5,5.0,False,0.0
|
| 101 |
-
TabDPT,Foundation Model,243.77644681542583,113.41332740687801,15.25847431382481,1415.5,10.0,False,0.0
|
| 102 |
-
TabDPT,Foundation Model,599.14526392591,170.40307060248648,14.58792821121514,1442.4,25.0,False,0.0
|
| 103 |
-
TabDPT,Foundation Model,1224.6320092924832,211.92435767541818,14.246562277368833,1456.9,50.0,False,0.0
|
| 104 |
-
TabDPT,Foundation Model,2440.704045474264,252.46699651351815,14.025515152987841,1467.0,100.0,False,0.0
|
| 105 |
-
TabDPT,Foundation Model,3652.693914186981,264.8770310030767,13.88361683040771,1472.2,150.0,False,0.0
|
| 106 |
-
TabDPT,Foundation Model,4910.377306237253,289.5741517328534,13.812001220438422,1474.3,201.0,False,0.0
|
| 107 |
-
TabDPT-Turbo,Foundation Model,2.06768405148355,0.18241940288749647,14.0203361291699,1472.3,1.0,False,0.0
|
| 108 |
-
TabFM,Foundation Model,38.805908867807105,6.985429071794801,4.0944582802657035,1807.7,1.0,False,0.0
|
| 109 |
-
TabICLv2,Foundation Model,2.0524528171730156,0.15054921462491172,10.19897564153584,1611.8,1.0,False,0.0
|
| 110 |
-
TabM,Neural Network,7.486463968520102,0.2435252328360982,17.02187952020658,1307.7,1.0,False,0.0
|
| 111 |
-
TabM,Neural Network,16.686302531690117,0.4863020309973096,16.495752283556467,1334.9,2.0,False,0.0
|
| 112 |
-
TabM,Neural Network,56.596063695315806,0.890570759276549,15.85723403452073,1370.8,5.0,False,0.0
|
| 113 |
-
TabM,Neural Network,118.7995551510581,0.9696677240363341,15.285453852205777,1405.2,10.0,False,0.0
|
| 114 |
-
TabM,Neural Network,301.71685986726413,1.2874446083056301,14.793023765894237,1431.2,25.0,False,0.0
|
| 115 |
-
TabM,Neural Network,606.7957589349577,1.5958040707920327,14.504939209135886,1447.7,50.0,False,0.0
|
| 116 |
-
TabM,Neural Network,1211.551032832957,1.9425270855949641,14.301458534985233,1459.4,100.0,False,0.0
|
| 117 |
-
TabM,Neural Network,1826.0696865509133,2.1383865310957564,14.157021352875951,1465.8,150.0,False,0.0
|
| 118 |
-
TabM,Neural Network,2450.1270774379373,2.236152469066152,14.101948299098552,1471.1,201.0,False,0.0
|
| 119 |
-
TabPFN-2.6,Foundation Model,5.482579877802832,0.5548034626013535,10.773892289839509,1643.6,1.0,False,0.0
|
| 120 |
-
TabPFN-3,Foundation Model,3.6584650300170622,0.3988194969093643,9.350273566614813,1683.7,1.0,False,0.0
|
| 121 |
-
TabSTAR,Foundation Model,384.74563018139656,5.348086842145453,30.47412388440593,997.8,1.0,False,0.0
|
| 122 |
-
TabSTAR,Foundation Model,579.5314694237709,6.864771890640259,30.347038882975998,1006.6,2.0,False,0.0
|
| 123 |
-
TabSTAR,Foundation Model,986.9188087141514,7.884261027648034,30.080943935841937,1014.9,5.0,False,0.0
|
| 124 |
-
TabSTAR,Foundation Model,1626.205745840524,9.437109846485178,29.421057045559767,1032.7,10.0,False,0.0
|
| 125 |
-
TabSTAR,Foundation Model,3523.6508469471287,12.411686028639474,28.225052033106863,1055.9,25.0,False,0.0
|
| 126 |
-
TabSTAR,Foundation Model,7090.437342984086,14.581168526013691,27.026195240095387,1076.7,50.0,False,0.0
|
| 127 |
-
TabSTAR,Foundation Model,14236.603036992845,17.05862640937169,26.355370232204596,1092.3,100.0,False,0.0
|
| 128 |
-
TabSTAR,Foundation Model,21385.328840252965,18.39983408008061,25.942905489351652,1103.1,150.0,False,0.0
|
| 129 |
-
TabSTAR,Foundation Model,28729.737365569254,18.8114333152771,25.62018492142047,1114.2,201.0,False,0.0
|
| 130 |
-
TabSwift,Foundation Model,1.1753394519011986,0.07196837694453946,16.10208326307144,1367.0,1.0,False,0.0
|
| 131 |
-
TorchMLP,Neural Network,9.99256321379882,0.1258046787872722,22.82955610374213,1082.6,1.0,False,0.0
|
| 132 |
-
TorchMLP,Neural Network,23.39767303078301,0.25026397500859937,21.109494917973674,1136.9,2.0,False,0.0
|
| 133 |
-
TorchMLP,Neural Network,67.83522273002498,0.5082028825487114,19.58502204023533,1188.5,5.0,False,0.0
|
| 134 |
-
TorchMLP,Neural Network,150.5961763502482,0.7461273476481438,18.859173580368292,1222.0,10.0,False,0.0
|
| 135 |
-
TorchMLP,Neural Network,358.89142527924406,1.1062947766294757,18.17773359177303,1252.0,25.0,False,0.0
|
| 136 |
-
TorchMLP,Neural Network,711.8242682675321,1.3608592505593902,17.762854174437347,1273.5,50.0,False,0.0
|
| 137 |
-
TorchMLP,Neural Network,1402.3570975877033,1.5999240551180054,17.468497616393975,1287.5,100.0,False,0.0
|
| 138 |
-
TorchMLP,Neural Network,2125.061118692563,1.7712720948858605,17.31173997878631,1296.2,150.0,False,0.0
|
| 139 |
-
TorchMLP,Neural Network,2875.520340774675,1.9516254299583915,17.17786611550823,1302.7,201.0,False,0.0
|
| 140 |
-
XGBoost,Tree-based,1.9409389396340444,0.12262328807300621,18.812692339626054,1218.2,1.0,False,0.0
|
| 141 |
-
XGBoost,Tree-based,5.773697624577766,0.549105895360311,17.165162871678664,1301.3,2.0,False,0.0
|
| 142 |
-
XGBoost,Tree-based,17.165802076190833,0.9903293256488429,16.632507902802494,1337.3,5.0,False,0.0
|
| 143 |
-
XGBoost,Tree-based,34.081364319342484,1.180882272831562,16.31489777339226,1358.0,10.0,False,0.0
|
| 144 |
-
XGBoost,Tree-based,86.41550386463979,1.5144136771170538,16.068815450472144,1372.9,25.0,False,0.0
|
| 145 |
-
XGBoost,Tree-based,172.69993584479832,1.6869916704181176,15.96558821702624,1379.4,50.0,False,0.0
|
| 146 |
-
XGBoost,Tree-based,344.2808053206447,1.7329947109908745,15.883217938316573,1385.7,100.0,False,0.0
|
| 147 |
-
XGBoost,Tree-based,515.1408947247787,1.8097831769800434,15.823927924282033,1389.9,150.0,False,0.0
|
| 148 |
-
XGBoost,Tree-based,693.4907982506384,1.7397156137573087,15.775712987807076,1394.4,201.0,False,0.0
|
| 149 |
-
iLTM,Foundation Model,296.63929176158115,68.17329693701195,23.043017100027516,1103.5,1.0,False,0.0
|
| 150 |
-
iLTM,Foundation Model,761.0284006743531,133.58534546802647,20.349313351022555,1173.0,2.0,False,0.0
|
| 151 |
-
iLTM,Foundation Model,2323.5909795410653,253.2846359590774,18.812213351704102,1278.0,5.0,False,0.0
|
| 152 |
-
iLTM,Foundation Model,4948.456215600054,348.32007675170894,17.541943153993884,1341.2,10.0,False,0.0
|
| 153 |
-
iLTM,Foundation Model,12120.256080215093,469.70642335709636,15.35397948820616,1419.4,25.0,False,0.0
|
| 154 |
-
iLTM,Foundation Model,12685.081550183375,463.2685781743115,15.32495866465839,1423.0,26.0,False,0.0
|
| 155 |
-
xRFM,Other,3.2328671519382346,0.9186215875564591,26.46345800176384,1050.2,1.0,False,0.0
|
| 156 |
-
xRFM,Other,7.775795304879809,0.871141043689068,23.22748715206326,1112.9,2.0,False,0.0
|
| 157 |
-
xRFM,Other,20.620430421907656,1.133551260828972,19.273412112959537,1230.3,5.0,False,0.0
|
| 158 |
-
xRFM,Other,41.99625808068535,1.4441868364810944,17.524789542834434,1312.0,10.0,False,0.0
|
| 159 |
-
xRFM,Other,105.70497940399669,1.8072467962280723,16.693771119799536,1350.7,25.0,False,0.0
|
| 160 |
-
xRFM,Other,210.31944482616692,2.1086840459278653,16.424264842001456,1362.8,50.0,False,0.0
|
| 161 |
-
xRFM,Other,422.08708123786937,2.3155613238258024,16.321595045395437,1365.4,100.0,False,0.0
|
| 162 |
-
xRFM,Other,631.9086612835005,2.533833287124123,16.300273763804636,1366.1,150.0,False,0.0
|
| 163 |
-
xRFM,Other,846.8860702336882,2.566047516252313,16.296898496190295,1365.5,201.0,False,0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/tuning_trajectories_explorer.html
DELETED
|
@@ -1,1230 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena tuning trajectories</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Two-column layout: controls + chips in a side panel, chart beside it.
|
| 269 |
-
``chips-right`` mirrors the columns. Wraps to stacked when narrow. */
|
| 270 |
-
.explorer-grid { display: flex; gap: 18px; align-items: flex-start; }
|
| 271 |
-
.explorer-grid.chips-right { flex-direction: row-reverse; }
|
| 272 |
-
.sidebox { flex: 0 0 330px; min-width: 250px; display: flex; flex-direction: column; gap: 10px; }
|
| 273 |
-
.mainbox { flex: 1 1 auto; min-width: 0; }
|
| 274 |
-
@media (max-width: 860px) {
|
| 275 |
-
.explorer-grid { flex-wrap: wrap; }
|
| 276 |
-
.sidebox { flex: 1 1 100%; }
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 280 |
-
.chartbox { position: relative; }
|
| 281 |
-
/* The chart is sized in device pixels by render() rather than scaled from a
|
| 282 |
-
viewBox: scaling stretched the type along with the plot, and a viewBox tall
|
| 283 |
-
enough to read made the whole panel own the screen. */
|
| 284 |
-
.chartbox svg { display: block; }
|
| 285 |
-
/* Chips scroll within the column so the panel height follows the chart. */
|
| 286 |
-
.sidebox .chips { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent; }
|
| 287 |
-
.sidebox .chips::-webkit-scrollbar { width: 9px; }
|
| 288 |
-
.sidebox .chips::-webkit-scrollbar-thumb {
|
| 289 |
-
background: var(--pt-muted); border-radius: 8px; border: 3px solid transparent; background-clip: content-box;
|
| 290 |
-
}
|
| 291 |
-
</style>
|
| 292 |
-
</head>
|
| 293 |
-
<body>
|
| 294 |
-
<div class="viewbar">
|
| 295 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 296 |
-
</div>
|
| 297 |
-
<p class="explorer-title" id="title"></p>
|
| 298 |
-
<div class="explorer-grid" id="grid">
|
| 299 |
-
<div class="sidebox">
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick" id="metricpick" hidden>Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<div class="btnrow">
|
| 305 |
-
<button class="btn" id="btn-front">Pareto front</button>
|
| 306 |
-
<button class="btn" id="btn-all">All</button>
|
| 307 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 308 |
-
</div>
|
| 309 |
-
<span class="hint">Click methods or family buttons to highlight · hover points for details</span>
|
| 310 |
-
</div>
|
| 311 |
-
<div class="chips" id="chips"></div>
|
| 312 |
-
</div>
|
| 313 |
-
<div class="mainbox">
|
| 314 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 315 |
-
<span class="hint">Export figure</span>
|
| 316 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 317 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 318 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 319 |
-
</div>
|
| 320 |
-
<!-- Legend above the chart so readers decode the marks before the data. -->
|
| 321 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 322 |
-
<div class="chartbox" id="chartbox">
|
| 323 |
-
<svg id="chart" role="img" aria-label="Pareto front explorer"></svg>
|
| 324 |
-
<div class="tooltip"></div>
|
| 325 |
-
</div>
|
| 326 |
-
</div>
|
| 327 |
-
</div>
|
| 328 |
-
<details class="datatable">
|
| 329 |
-
<summary>Data table</summary>
|
| 330 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 331 |
-
</details>
|
| 332 |
-
|
| 333 |
-
<script>
|
| 334 |
-
(function () {
|
| 335 |
-
"use strict";
|
| 336 |
-
const CONFIG = {"mode": "trajectory", "title": null, "metrics": [{"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": ""}], "xAxes": [{"key": "x_train", "label": "Train time", "axisLabel": "Train time per 1K samples (s), median \u2014 log scale", "short": "Train (s/1K, median)"}], "chipsSide": "right"};
|
| 337 |
-
const POINTS = [{"method":"CatBoost","family":"Tree-based","x_train":5.876676442,"imp":15.5457736304,"elo":1392.9,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"CatBoost","family":"Tree-based","x_train":11.6678251256,"imp":15.1182419551,"elo":1413.1,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"CatBoost","family":"Tree-based","x_train":31.9106517624,"imp":14.848578649,"elo":1430.8,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"CatBoost","family":"Tree-based","x_train":62.5721251757,"imp":14.7477568558,"elo":1435.8,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"CatBoost","family":"Tree-based","x_train":155.9049355669,"imp":14.6406177695,"elo":1441.2,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"CatBoost","family":"Tree-based","x_train":317.345916891,"imp":14.6311446381,"elo":1441.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"CatBoost","family":"Tree-based","x_train":662.4830210734,"imp":14.6478465613,"elo":1440.2,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"CatBoost","family":"Tree-based","x_train":998.8498259224,"imp":14.6673563694,"elo":1438.8,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"CatBoost","family":"Tree-based","x_train":1346.2106911803,"imp":14.674240095,"elo":1437.7,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":1.9886321895,"imp":18.6780631139,"elo":1273.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":4.4383850203,"imp":18.3366328085,"elo":1294.1,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":10.0701848574,"imp":18.116797306,"elo":1307.5,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":20.4734178164,"imp":17.9259739747,"elo":1318.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":52.7173757556,"imp":17.6537027938,"elo":1330.8,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":106.3941874905,"imp":17.5022920851,"elo":1338.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":212.8207478205,"imp":17.339314755,"elo":1346.0,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":318.9957179838,"imp":17.2700034244,"elo":1348.8,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":427.391750384,"imp":17.2326457261,"elo":1351.7,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"EBM","family":"Tree-based","x_train":6.6731468509,"imp":20.2759337918,"elo":1208.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"EBM","family":"Tree-based","x_train":16.5765343457,"imp":19.8786837436,"elo":1222.7,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"EBM","family":"Tree-based","x_train":47.7385589033,"imp":19.4534296615,"elo":1243.5,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"EBM","family":"Tree-based","x_train":89.4110724699,"imp":19.2726704565,"elo":1252.8,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"EBM","family":"Tree-based","x_train":218.448124708,"imp":19.0438192816,"elo":1263.4,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"EBM","family":"Tree-based","x_train":440.2545735965,"imp":18.9023411836,"elo":1271.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"EBM","family":"Tree-based","x_train":856.7647171053,"imp":18.780391801,"elo":1278.4,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"EBM","family":"Tree-based","x_train":1266.0910927829,"imp":18.7369843166,"elo":1281.9,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"EBM","family":"Tree-based","x_train":1711.2458519871,"imp":18.6945455008,"elo":1284.9,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"ExtraTrees","family":"Tree-based","x_train":1.8719729433,"imp":26.1948484129,"elo":1009.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ExtraTrees","family":"Tree-based","x_train":3.1259596548,"imp":24.3488542313,"elo":1053.5,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"ExtraTrees","family":"Tree-based","x_train":6.7721912257,"imp":21.6826802288,"elo":1124.8,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"ExtraTrees","family":"Tree-based","x_train":13.288092342,"imp":20.760558803,"elo":1165.9,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"ExtraTrees","family":"Tree-based","x_train":32.8419339595,"imp":20.1069857393,"elo":1197.4,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"ExtraTrees","family":"Tree-based","x_train":65.4938634865,"imp":19.9445772606,"elo":1207.8,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"ExtraTrees","family":"Tree-based","x_train":130.8369715186,"imp":19.8340399339,"elo":1214.7,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"ExtraTrees","family":"Tree-based","x_train":196.2244804971,"imp":19.7910126465,"elo":1218.9,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"ExtraTrees","family":"Tree-based","x_train":263.0379305179,"imp":19.7984513883,"elo":1219.9,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"FastaiMLP","family":"Neural Network","x_train":2.8561491959,"imp":25.7013457941,"elo":1012.4,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"FastaiMLP","family":"Neural Network","x_train":5.5343795004,"imp":24.5020141267,"elo":1049.9,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"FastaiMLP","family":"Neural Network","x_train":14.5510344275,"imp":22.6534704395,"elo":1116.6,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"FastaiMLP","family":"Neural Network","x_train":29.723343154,"imp":21.7464416276,"elo":1149.9,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"FastaiMLP","family":"Neural Network","x_train":72.5444980812,"imp":20.8458197285,"elo":1180.3,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"FastaiMLP","family":"Neural Network","x_train":145.754371191,"imp":20.3916263193,"elo":1196.9,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"FastaiMLP","family":"Neural Network","x_train":293.9475008279,"imp":20.0488916705,"elo":1207.2,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"FastaiMLP","family":"Neural Network","x_train":441.8525399102,"imp":19.826636643,"elo":1215.4,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"FastaiMLP","family":"Neural Network","x_train":593.2377884029,"imp":19.6935269069,"elo":1220.6,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"LightGBM","family":"Tree-based","x_train":1.960032688,"imp":19.3647921745,"elo":1188.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"LightGBM","family":"Tree-based","x_train":4.1465368891,"imp":17.8536668429,"elo":1267.1,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"LightGBM","family":"Tree-based","x_train":10.3907433568,"imp":16.6855138703,"elo":1346.2,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"LightGBM","family":"Tree-based","x_train":20.2701675373,"imp":16.0840498218,"elo":1386.9,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"LightGBM","family":"Tree-based","x_train":51.487448334,"imp":15.5280964347,"elo":1421.6,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"LightGBM","family":"Tree-based","x_train":103.6855742013,"imp":15.3158433015,"elo":1437.2,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"LightGBM","family":"Tree-based","x_train":207.5435114784,"imp":15.1552157574,"elo":1447.7,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"LightGBM","family":"Tree-based","x_train":310.2926532568,"imp":15.0933557354,"elo":1451.2,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"LightGBM","family":"Tree-based","x_train":417.0474735649,"imp":15.0561804683,"elo":1453.8,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"LimiX","family":"Foundation Model","x_train":26.4597512682,"imp":15.4843630349,"elo":1381.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ModernNCA","family":"Neural Network","x_train":14.8696863446,"imp":19.2146348547,"elo":1258.8,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ModernNCA","family":"Neural Network","x_train":40.5171687704,"imp":17.9235444693,"elo":1296.1,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"ModernNCA","family":"Neural Network","x_train":111.4498310885,"imp":16.0052009744,"elo":1381.4,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"ModernNCA","family":"Neural Network","x_train":224.929440425,"imp":15.5140651615,"elo":1406.1,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"ModernNCA","family":"Neural Network","x_train":554.8880523029,"imp":15.0054551931,"elo":1431.4,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"ModernNCA","family":"Neural Network","x_train":1145.4516650488,"imp":15.0529606984,"elo":1428.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"ModernNCA","family":"Neural Network","x_train":2295.4928354707,"imp":15.3121547879,"elo":1419.9,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"ModernNCA","family":"Neural Network","x_train":3433.7924746694,"imp":15.5114179492,"elo":1411.9,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"ModernNCA","family":"Neural Network","x_train":4621.6656335635,"imp":15.6253232633,"elo":1406.7,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":27.322832323,"imp":32.2510059823,"elo":936.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":60.3304655332,"imp":30.0030285719,"elo":1001.6,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":157.3958954151,"imp":26.6320054165,"elo":1088.2,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":185.3067056521,"imp":26.4602162594,"elo":1095.6,"imputed":false,"imputed_pct":0.0,"n_configs":6.0},{"method":"RandomForest","family":"Tree-based","x_train":0.4343250827,"imp":26.2932402488,"elo":999.4,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"RandomForest","family":"Tree-based","x_train":2.3006968127,"imp":23.6312931455,"elo":1058.9,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"RandomForest","family":"Tree-based","x_train":7.8694051654,"imp":22.2945002711,"elo":1101.7,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"RandomForest","family":"Tree-based","x_train":17.2473724895,"imp":21.598133622,"elo":1131.3,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"RandomForest","family":"Tree-based","x_train":45.0373615697,"imp":21.1082364807,"elo":1162.1,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"RandomForest","family":"Tree-based","x_train":91.3917233329,"imp":20.9763766453,"elo":1170.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"RandomForest","family":"Tree-based","x_train":184.6996741609,"imp":20.8893896531,"elo":1176.8,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"RandomForest","family":"Tree-based","x_train":277.8099565315,"imp":20.8512167326,"elo":1179.4,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"RandomForest","family":"Tree-based","x_train":373.2371055096,"imp":20.8463533192,"elo":1181.1,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"RealMLP","family":"Neural Network","x_train":10.055649238,"imp":18.5902394535,"elo":1235.3,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"RealMLP","family":"Neural Network","x_train":24.6705594408,"imp":16.2369194285,"elo":1345.9,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"RealMLP","family":"Neural Network","x_train":69.643527334,"imp":14.5607377501,"elo":1438.2,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"RealMLP","family":"Neural Network","x_train":141.1529977589,"imp":13.9427929116,"elo":1472.7,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"RealMLP","family":"Neural Network","x_train":364.6011469598,"imp":13.4671732129,"elo":1502.2,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"RealMLP","family":"Neural Network","x_train":736.9754853516,"imp":13.2471506373,"elo":1515.4,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"RealMLP","family":"Neural Network","x_train":1469.2653973047,"imp":13.0647764231,"elo":1524.1,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"RealMLP","family":"Neural Network","x_train":2197.5320041687,"imp":12.9722032627,"elo":1529.9,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"RealMLP","family":"Neural Network","x_train":2950.7244476948,"imp":12.9046673494,"elo":1532.8,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":5.8097985299,"imp":11.6839820929,"elo":1538.3,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":16.6950892358,"imp":11.6143468084,"elo":1544.7,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":45.8180610371,"imp":11.292487148,"elo":1561.1,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":96.056645332,"imp":11.1111899349,"elo":1578.5,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":245.1410909168,"imp":10.868476471,"elo":1599.1,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":498.5667116885,"imp":10.6868240527,"elo":1608.6,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":1015.1487598759,"imp":10.5680156723,"elo":1613.1,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":1526.7130408425,"imp":10.5076542069,"elo":1614.3,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":2040.2228420973,"imp":10.4555406579,"elo":1613.3,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"SAP-RPT-OSS","family":"Foundation Model","x_train":14.1132668455,"imp":18.2986171534,"elo":1297.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabDPT","family":"Foundation Model","x_train":47.6466878891,"imp":17.2447142424,"elo":1337.6,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabDPT","family":"Foundation Model","x_train":70.407219275,"imp":16.4273759647,"elo":1364.1,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TabDPT","family":"Foundation Model","x_train":132.9785409439,"imp":15.6129784957,"elo":1399.5,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TabDPT","family":"Foundation Model","x_train":243.7764468154,"imp":15.2584743138,"elo":1415.5,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TabDPT","family":"Foundation Model","x_train":599.1452639259,"imp":14.5879282112,"elo":1442.4,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TabDPT","family":"Foundation Model","x_train":1224.6320092925,"imp":14.2465622774,"elo":1456.9,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TabDPT","family":"Foundation Model","x_train":2440.7040454743,"imp":14.025515153,"elo":1467.0,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TabDPT","family":"Foundation Model","x_train":3652.693914187,"imp":13.8836168304,"elo":1472.2,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TabDPT","family":"Foundation Model","x_train":4910.3773062373,"imp":13.8120012204,"elo":1474.3,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"TabDPT-Turbo","family":"Foundation Model","x_train":2.0676840515,"imp":14.0203361292,"elo":1472.3,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabFM","family":"Foundation Model","x_train":38.8059088678,"imp":4.0944582803,"elo":1807.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabICLv2","family":"Foundation Model","x_train":2.0524528172,"imp":10.1989756415,"elo":1611.8,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabM","family":"Neural Network","x_train":7.4864639685,"imp":17.0218795202,"elo":1307.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabM","family":"Neural Network","x_train":16.6863025317,"imp":16.4957522836,"elo":1334.9,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TabM","family":"Neural Network","x_train":56.5960636953,"imp":15.8572340345,"elo":1370.8,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TabM","family":"Neural Network","x_train":118.7995551511,"imp":15.2854538522,"elo":1405.2,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TabM","family":"Neural Network","x_train":301.7168598673,"imp":14.7930237659,"elo":1431.2,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TabM","family":"Neural Network","x_train":606.795758935,"imp":14.5049392091,"elo":1447.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TabM","family":"Neural Network","x_train":1211.551032833,"imp":14.301458535,"elo":1459.4,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TabM","family":"Neural Network","x_train":1826.0696865509,"imp":14.1570213529,"elo":1465.8,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TabM","family":"Neural Network","x_train":2450.1270774379,"imp":14.1019482991,"elo":1471.1,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"TabPFN-2.6","family":"Foundation Model","x_train":5.4825798778,"imp":10.7738922898,"elo":1643.6,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabPFN-3","family":"Foundation Model","x_train":3.65846503,"imp":9.3502735666,"elo":1683.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabSTAR","family":"Foundation Model","x_train":384.7456301814,"imp":30.4741238844,"elo":997.8,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabSTAR","family":"Foundation Model","x_train":579.5314694238,"imp":30.347038883,"elo":1006.6,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TabSTAR","family":"Foundation Model","x_train":986.9188087142,"imp":30.0809439358,"elo":1014.9,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TabSTAR","family":"Foundation Model","x_train":1626.2057458405,"imp":29.4210570456,"elo":1032.7,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TabSTAR","family":"Foundation Model","x_train":3523.6508469471,"imp":28.2250520331,"elo":1055.9,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TabSTAR","family":"Foundation Model","x_train":7090.4373429841,"imp":27.0261952401,"elo":1076.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TabSTAR","family":"Foundation Model","x_train":14236.6030369928,"imp":26.3553702322,"elo":1092.3,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TabSTAR","family":"Foundation Model","x_train":21385.328840253,"imp":25.9429054894,"elo":1103.1,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TabSTAR","family":"Foundation Model","x_train":28729.7373655693,"imp":25.6201849214,"elo":1114.2,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"TabSwift","family":"Foundation Model","x_train":1.1753394519,"imp":16.1020832631,"elo":1367.0,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TorchMLP","family":"Neural Network","x_train":9.9925632138,"imp":22.8295561037,"elo":1082.6,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TorchMLP","family":"Neural Network","x_train":23.3976730308,"imp":21.109494918,"elo":1136.9,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TorchMLP","family":"Neural Network","x_train":67.83522273,"imp":19.5850220402,"elo":1188.5,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TorchMLP","family":"Neural Network","x_train":150.5961763502,"imp":18.8591735804,"elo":1222.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TorchMLP","family":"Neural Network","x_train":358.8914252792,"imp":18.1777335918,"elo":1252.0,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TorchMLP","family":"Neural Network","x_train":711.8242682675,"imp":17.7628541744,"elo":1273.5,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TorchMLP","family":"Neural Network","x_train":1402.3570975877,"imp":17.4684976164,"elo":1287.5,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TorchMLP","family":"Neural Network","x_train":2125.0611186926,"imp":17.3117399788,"elo":1296.2,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TorchMLP","family":"Neural Network","x_train":2875.5203407747,"imp":17.1778661155,"elo":1302.7,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"XGBoost","family":"Tree-based","x_train":1.9409389396,"imp":18.8126923396,"elo":1218.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"XGBoost","family":"Tree-based","x_train":5.7736976246,"imp":17.1651628717,"elo":1301.3,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"XGBoost","family":"Tree-based","x_train":17.1658020762,"imp":16.6325079028,"elo":1337.3,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"XGBoost","family":"Tree-based","x_train":34.0813643193,"imp":16.3148977734,"elo":1358.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"XGBoost","family":"Tree-based","x_train":86.4155038646,"imp":16.0688154505,"elo":1372.9,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"XGBoost","family":"Tree-based","x_train":172.6999358448,"imp":15.965588217,"elo":1379.4,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"XGBoost","family":"Tree-based","x_train":344.2808053206,"imp":15.8832179383,"elo":1385.7,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"XGBoost","family":"Tree-based","x_train":515.1408947248,"imp":15.8239279243,"elo":1389.9,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"XGBoost","family":"Tree-based","x_train":693.4907982506,"imp":15.7757129878,"elo":1394.4,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"iLTM","family":"Foundation Model","x_train":296.6392917616,"imp":23.0430171,"elo":1103.5,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"iLTM","family":"Foundation Model","x_train":761.0284006744,"imp":20.349313351,"elo":1173.0,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"iLTM","family":"Foundation Model","x_train":2323.5909795411,"imp":18.8122133517,"elo":1278.0,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"iLTM","family":"Foundation Model","x_train":4948.4562156001,"imp":17.541943154,"elo":1341.2,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"iLTM","family":"Foundation Model","x_train":12120.2560802151,"imp":15.3539794882,"elo":1419.4,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"iLTM","family":"Foundation Model","x_train":12685.0815501834,"imp":15.3249586647,"elo":1423.0,"imputed":false,"imputed_pct":0.0,"n_configs":26.0},{"method":"xRFM","family":"Other","x_train":3.2328671519,"imp":26.4634580018,"elo":1050.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"xRFM","family":"Other","x_train":7.7757953049,"imp":23.2274871521,"elo":1112.9,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"xRFM","family":"Other","x_train":20.6204304219,"imp":19.273412113,"elo":1230.3,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"xRFM","family":"Other","x_train":41.9962580807,"imp":17.5247895428,"elo":1312.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"xRFM","family":"Other","x_train":105.704979404,"imp":16.6937711198,"elo":1350.7,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"xRFM","family":"Other","x_train":210.3194448262,"imp":16.424264842,"elo":1362.8,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"xRFM","family":"Other","x_train":422.0870812379,"imp":16.3215950454,"elo":1365.4,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"xRFM","family":"Other","x_train":631.9086612835,"imp":16.3002737638,"elo":1366.1,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"xRFM","family":"Other","x_train":846.8860702337,"imp":16.2968984962,"elo":1365.5,"imputed":false,"imputed_pct":0.0,"n_configs":201.0}];
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 341 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 342 |
-
// already share a color, and each holds only a handful of methods.
|
| 343 |
-
const FAM_MERGED = "Baseline / Other";
|
| 344 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 345 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 346 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 347 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 348 |
-
|
| 349 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 350 |
-
const FAM_VAR = {
|
| 351 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 352 |
-
"Tree-based": "var(--fam-tree)",
|
| 353 |
-
"Neural Network": "var(--fam-nn)",
|
| 354 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 355 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 356 |
-
};
|
| 357 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 358 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 359 |
-
// that chip carries both symbols.
|
| 360 |
-
const FAM_SYMBOL = {
|
| 361 |
-
"Foundation Model": "🧠⚡",
|
| 362 |
-
"Tree-based": "🌳",
|
| 363 |
-
"Neural Network": "🧠🔁",
|
| 364 |
-
"Reference Pipeline": "📊",
|
| 365 |
-
[FAM_MERGED]: "📏 ❓",
|
| 366 |
-
};
|
| 367 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 368 |
-
const VARIANT_VAR = {
|
| 369 |
-
"Default": "var(--var-default)",
|
| 370 |
-
"Tuned": "var(--var-tuned)",
|
| 371 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 372 |
-
};
|
| 373 |
-
|
| 374 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 375 |
-
function famChipLabel(family, count) {
|
| 376 |
-
const symbol = FAM_SYMBOL[family];
|
| 377 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 378 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 379 |
-
}
|
| 380 |
-
|
| 381 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 382 |
-
const FAM_INK = {
|
| 383 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 384 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 385 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 386 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 387 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 388 |
-
};
|
| 389 |
-
|
| 390 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 391 |
-
function el(name, attrs, parent) {
|
| 392 |
-
const node = document.createElementNS(NS, name);
|
| 393 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 394 |
-
if (parent) parent.appendChild(node);
|
| 395 |
-
return node;
|
| 396 |
-
}
|
| 397 |
-
|
| 398 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 399 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 400 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 401 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 402 |
-
function fmtNum(v, decimals) {
|
| 403 |
-
if (v == null || !isFinite(v)) return "—";
|
| 404 |
-
return v.toFixed(decimals);
|
| 405 |
-
}
|
| 406 |
-
|
| 407 |
-
function fmtMetric(metric, v) {
|
| 408 |
-
if (v == null || !isFinite(v)) return "—";
|
| 409 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 410 |
-
}
|
| 411 |
-
|
| 412 |
-
function fmtTime(v) {
|
| 413 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 414 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 415 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 416 |
-
return fmtNum(v, 3) + " s";
|
| 417 |
-
}
|
| 418 |
-
|
| 419 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 420 |
-
function niceStep(raw) {
|
| 421 |
-
if (!(raw > 0)) return 1;
|
| 422 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 423 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 424 |
-
if (mag * m >= raw) return mag * m;
|
| 425 |
-
}
|
| 426 |
-
return mag * 10;
|
| 427 |
-
}
|
| 428 |
-
|
| 429 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 430 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 431 |
-
function ticks(min, max, target) {
|
| 432 |
-
const step = niceStep((max - min) / target);
|
| 433 |
-
const first = Math.ceil(min / step);
|
| 434 |
-
const out = [];
|
| 435 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 436 |
-
return out.length ? out : [min];
|
| 437 |
-
}
|
| 438 |
-
|
| 439 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 440 |
-
function makeTooltip(box) {
|
| 441 |
-
const node = box.querySelector(".tooltip");
|
| 442 |
-
return {
|
| 443 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 444 |
-
move(ev) {
|
| 445 |
-
const r = box.getBoundingClientRect();
|
| 446 |
-
let tx = ev.clientX - r.left + 14;
|
| 447 |
-
const ty = ev.clientY - r.top + 12;
|
| 448 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 449 |
-
node.style.left = tx + "px";
|
| 450 |
-
node.style.top = ty + "px";
|
| 451 |
-
},
|
| 452 |
-
hide() { node.style.display = "none"; },
|
| 453 |
-
};
|
| 454 |
-
}
|
| 455 |
-
|
| 456 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 457 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 458 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 459 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 460 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 461 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 462 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 463 |
-
function setUpPaperView(afterToggle, options) {
|
| 464 |
-
const opts = options || {};
|
| 465 |
-
const root = document.documentElement;
|
| 466 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 467 |
-
const btn = document.getElementById("btn-paper");
|
| 468 |
-
const embedded = window.parent !== window;
|
| 469 |
-
|
| 470 |
-
function setPaper(on) {
|
| 471 |
-
document.body.classList.toggle("paper", on);
|
| 472 |
-
if (on) {
|
| 473 |
-
hostTheme = root.getAttribute("data-theme");
|
| 474 |
-
root.setAttribute("data-theme", "light");
|
| 475 |
-
} else if (hostTheme) {
|
| 476 |
-
root.setAttribute("data-theme", hostTheme);
|
| 477 |
-
} else {
|
| 478 |
-
root.removeAttribute("data-theme");
|
| 479 |
-
}
|
| 480 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 481 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 482 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 483 |
-
postHeight();
|
| 484 |
-
}
|
| 485 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 486 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 487 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 488 |
-
// shareable single file) this page needs its own.
|
| 489 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 490 |
-
window.addEventListener("message", ev => {
|
| 491 |
-
const d = ev.data;
|
| 492 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 493 |
-
});
|
| 494 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 495 |
-
// key press, so its label would fall out of step with the frame.
|
| 496 |
-
if (!embedded) {
|
| 497 |
-
document.addEventListener("keydown", ev => {
|
| 498 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 499 |
-
});
|
| 500 |
-
}
|
| 501 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 502 |
-
}
|
| 503 |
-
|
| 504 |
-
// --- Figure export ---------------------------------------------------------
|
| 505 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 506 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 507 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 508 |
-
// the legend is HTML rather than part of the SVG.
|
| 509 |
-
|
| 510 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 511 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 512 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 513 |
-
// break the PNG path.
|
| 514 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 515 |
-
// once the node leaves this document.
|
| 516 |
-
function resolveVars(root, resolve) {
|
| 517 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 518 |
-
for (const attr of ["fill", "stroke"]) {
|
| 519 |
-
const value = node.getAttribute(attr);
|
| 520 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 521 |
-
}
|
| 522 |
-
}
|
| 523 |
-
}
|
| 524 |
-
|
| 525 |
-
function legendToSvg(container, resolve) {
|
| 526 |
-
const base = container.getBoundingClientRect();
|
| 527 |
-
const group = document.createElementNS(NS, "g");
|
| 528 |
-
let height = 0;
|
| 529 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 530 |
-
const box = item.getBoundingClientRect();
|
| 531 |
-
if (!box.width) continue;
|
| 532 |
-
height = Math.max(height, box.bottom - base.top);
|
| 533 |
-
let textLeft = box.left - base.left;
|
| 534 |
-
const glyph = item.querySelector("svg");
|
| 535 |
-
if (glyph) {
|
| 536 |
-
const gbox = glyph.getBoundingClientRect();
|
| 537 |
-
const wrap = el("g", {
|
| 538 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 539 |
-
}, group);
|
| 540 |
-
const glyphClone = glyph.cloneNode(true);
|
| 541 |
-
resolveVars(glyphClone, resolve);
|
| 542 |
-
wrap.appendChild(glyphClone);
|
| 543 |
-
textLeft = gbox.right - base.left + 5;
|
| 544 |
-
}
|
| 545 |
-
const label = item.textContent.trim();
|
| 546 |
-
if (!label) continue;
|
| 547 |
-
const colored = item.querySelector("[style*='color']");
|
| 548 |
-
const text = el("text", {
|
| 549 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 550 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 551 |
-
}, group);
|
| 552 |
-
text.textContent = label;
|
| 553 |
-
}
|
| 554 |
-
return { group, height: Math.ceil(height) };
|
| 555 |
-
}
|
| 556 |
-
|
| 557 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 558 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 559 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 560 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 561 |
-
const resolve = value => String(value).replace(
|
| 562 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 563 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 564 |
-
|
| 565 |
-
let chartW = 0, chartH = 0;
|
| 566 |
-
for (const part of parts) {
|
| 567 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 568 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 569 |
-
}
|
| 570 |
-
|
| 571 |
-
const out = document.createElementNS(NS, "svg");
|
| 572 |
-
out.setAttribute("xmlns", NS);
|
| 573 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 574 |
-
let top = pad;
|
| 575 |
-
const later = []; // built after the width is known
|
| 576 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 577 |
-
if (legend && legend.height) {
|
| 578 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 579 |
-
later.push(() => out.appendChild(legend.group));
|
| 580 |
-
top += legend.height + 8;
|
| 581 |
-
}
|
| 582 |
-
|
| 583 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 584 |
-
const height = top + chartH + pad;
|
| 585 |
-
out.setAttribute("width", Math.ceil(width));
|
| 586 |
-
out.setAttribute("height", Math.ceil(height));
|
| 587 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 588 |
-
for (const build of later) build();
|
| 589 |
-
|
| 590 |
-
for (const part of parts) {
|
| 591 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 592 |
-
const clone = part.svg.cloneNode(true);
|
| 593 |
-
resolveVars(clone, resolve);
|
| 594 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 595 |
-
}
|
| 596 |
-
return out;
|
| 597 |
-
}
|
| 598 |
-
|
| 599 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 600 |
-
function slugify(text) {
|
| 601 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 602 |
-
}
|
| 603 |
-
|
| 604 |
-
function downloadUrl(url, filename) {
|
| 605 |
-
const a = document.createElement("a");
|
| 606 |
-
a.href = url;
|
| 607 |
-
a.download = filename;
|
| 608 |
-
document.body.appendChild(a);
|
| 609 |
-
a.click();
|
| 610 |
-
a.remove();
|
| 611 |
-
}
|
| 612 |
-
|
| 613 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 614 |
-
function rasterize(svg, scale, done, fail) {
|
| 615 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 616 |
-
const img = new Image();
|
| 617 |
-
img.onload = () => {
|
| 618 |
-
const canvas = document.createElement("canvas");
|
| 619 |
-
canvas.width = Math.round(width * scale);
|
| 620 |
-
canvas.height = Math.round(height * scale);
|
| 621 |
-
const ctx = canvas.getContext("2d");
|
| 622 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 623 |
-
ctx.drawImage(img, 0, 0);
|
| 624 |
-
done(canvas, width, height);
|
| 625 |
-
};
|
| 626 |
-
img.onerror = fail;
|
| 627 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 628 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 629 |
-
}
|
| 630 |
-
|
| 631 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 632 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 633 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 634 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 635 |
-
// and the pixels land at 96*scale dpi.
|
| 636 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 637 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 638 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 639 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 640 |
-
rgb[j] = pixels[i];
|
| 641 |
-
rgb[j + 1] = pixels[i + 1];
|
| 642 |
-
rgb[j + 2] = pixels[i + 2];
|
| 643 |
-
}
|
| 644 |
-
const deflated = new Uint8Array(await new Response(
|
| 645 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 646 |
-
|
| 647 |
-
const encoder = new TextEncoder();
|
| 648 |
-
const chunks = [];
|
| 649 |
-
const offsets = [];
|
| 650 |
-
let cursor = 0;
|
| 651 |
-
const put = data => {
|
| 652 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 653 |
-
chunks.push(bytes);
|
| 654 |
-
cursor += bytes.length;
|
| 655 |
-
};
|
| 656 |
-
const object = (id, body, stream) => {
|
| 657 |
-
offsets[id] = cursor;
|
| 658 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 659 |
-
if (stream) {
|
| 660 |
-
put("stream\n");
|
| 661 |
-
put(stream);
|
| 662 |
-
put("\nendstream\n");
|
| 663 |
-
}
|
| 664 |
-
put("endobj\n");
|
| 665 |
-
};
|
| 666 |
-
|
| 667 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 668 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 669 |
-
put("%PDF-1.4\n");
|
| 670 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 671 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 672 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 673 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 674 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 675 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 676 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 677 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 678 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 679 |
-
|
| 680 |
-
const xref = cursor;
|
| 681 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 682 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 683 |
-
put(table);
|
| 684 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 685 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 686 |
-
}
|
| 687 |
-
|
| 688 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 689 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 690 |
-
function setUpExport(getParts, basename) {
|
| 691 |
-
const buttons = {
|
| 692 |
-
svg: document.getElementById("btn-svg"),
|
| 693 |
-
png: document.getElementById("btn-png"),
|
| 694 |
-
pdf: document.getElementById("btn-pdf"),
|
| 695 |
-
};
|
| 696 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 697 |
-
|
| 698 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 699 |
-
function complain(format) {
|
| 700 |
-
const button = buttons[format];
|
| 701 |
-
if (!button) return;
|
| 702 |
-
const label = button.textContent;
|
| 703 |
-
button.textContent = "failed";
|
| 704 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 705 |
-
}
|
| 706 |
-
|
| 707 |
-
function run(format) {
|
| 708 |
-
const svg = figure();
|
| 709 |
-
const name = basename();
|
| 710 |
-
if (format === "svg") {
|
| 711 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 712 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 713 |
-
return;
|
| 714 |
-
}
|
| 715 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 716 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 717 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 718 |
-
if (format === "png") {
|
| 719 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 720 |
-
} else {
|
| 721 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 722 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 723 |
-
.catch(() => complain("pdf"));
|
| 724 |
-
}
|
| 725 |
-
}, () => complain(format));
|
| 726 |
-
}
|
| 727 |
-
|
| 728 |
-
for (const format of Object.keys(buttons)) {
|
| 729 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 730 |
-
}
|
| 731 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 732 |
-
window.addEventListener("message", ev => {
|
| 733 |
-
const d = ev.data;
|
| 734 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 735 |
-
});
|
| 736 |
-
}
|
| 737 |
-
|
| 738 |
-
// When embedded, report the content height so the host page can size the
|
| 739 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 740 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 741 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 742 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 743 |
-
// stops re-posting once the height settles.
|
| 744 |
-
let lastPostedHeight = 0;
|
| 745 |
-
function postHeight() {
|
| 746 |
-
if (window.parent === window) return;
|
| 747 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 748 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 749 |
-
lastPostedHeight = height;
|
| 750 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 751 |
-
}
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
const TRAJECTORY = CONFIG.mode === "trajectory";
|
| 755 |
-
|
| 756 |
-
const titleEl = document.getElementById("title");
|
| 757 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 758 |
-
|
| 759 |
-
// Column order: chips/controls left of the chart, or mirrored.
|
| 760 |
-
document.getElementById("grid").classList.add(CONFIG.chipsSide === "right" ? "chips-right" : "chips-left");
|
| 761 |
-
|
| 762 |
-
const svg = document.getElementById("chart");
|
| 763 |
-
const box = document.getElementById("chartbox");
|
| 764 |
-
const chipsBox = document.getElementById("chips");
|
| 765 |
-
const controlsBox = document.querySelector(".controls");
|
| 766 |
-
const tip = makeTooltip(box);
|
| 767 |
-
|
| 768 |
-
// Marker glyph per variant at (cx, cy); trajectories use circles everywhere.
|
| 769 |
-
function drawMark(parent, cx, cy, variant, color, size, opacity, dataM, whiteStroke) {
|
| 770 |
-
const common = { opacity: opacity, "data-m": dataM };
|
| 771 |
-
let node;
|
| 772 |
-
if (TRAJECTORY || variant === "Default" || !variant) {
|
| 773 |
-
node = el("circle", { ...common, cx, cy, r: size, fill: color }, parent);
|
| 774 |
-
} else if (variant === "Tuned") {
|
| 775 |
-
const s = size * 1.75;
|
| 776 |
-
node = el("rect", { ...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1.5, fill: color }, parent);
|
| 777 |
-
} else if (variant === "Tuned + Ens.") {
|
| 778 |
-
const d = size * 0.95;
|
| 779 |
-
node = el("path", {
|
| 780 |
-
...common,
|
| 781 |
-
d: `M${cx - d},${cy - d} L${cx + d},${cy + d} M${cx - d},${cy + d} L${cx + d},${cy - d}`,
|
| 782 |
-
stroke: color, "stroke-width": size * 0.62, fill: "none", "stroke-linecap": "round",
|
| 783 |
-
}, parent);
|
| 784 |
-
} else {
|
| 785 |
-
// Any other variant (e.g. "Baseline", holdout types): diamond.
|
| 786 |
-
const s = size * 1.45;
|
| 787 |
-
node = el("rect", {
|
| 788 |
-
...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1,
|
| 789 |
-
fill: color, transform: `rotate(45 ${cx} ${cy})`,
|
| 790 |
-
}, parent);
|
| 791 |
-
}
|
| 792 |
-
if (whiteStroke && variant !== "Tuned + Ens.") {
|
| 793 |
-
node.setAttribute("stroke", "var(--card)");
|
| 794 |
-
node.setAttribute("stroke-width", "1");
|
| 795 |
-
}
|
| 796 |
-
return node;
|
| 797 |
-
}
|
| 798 |
-
|
| 799 |
-
function drawImputedRing(parent, cx, cy, size, color, opacity, dataM) {
|
| 800 |
-
el("circle", {
|
| 801 |
-
cx, cy, r: size + 4.5, fill: "none", stroke: color, "stroke-width": 1.4,
|
| 802 |
-
"stroke-dasharray": "3 2.5", opacity: opacity, "data-m": dataM,
|
| 803 |
-
}, parent);
|
| 804 |
-
}
|
| 805 |
-
|
| 806 |
-
// Fat green arrow pointing into the optimal corner (mirrors the static
|
| 807 |
-
// figures' "Optimal" arrow so both read the same way).
|
| 808 |
-
function drawOptimalArrow(parent, lowerBetter, M, W, H) {
|
| 809 |
-
const cornerY = lowerBetter ? H - M.b - 12 : M.t + 12;
|
| 810 |
-
const tailY = lowerBetter ? H - M.b - 64 : M.t + 64;
|
| 811 |
-
const cx = M.l + 12, tx = M.l + 64;
|
| 812 |
-
const dx = cx - tx, dy = cornerY - tailY;
|
| 813 |
-
const len = Math.hypot(dx, dy);
|
| 814 |
-
const ux = dx / len, uy = dy / len;
|
| 815 |
-
const headLen = 16;
|
| 816 |
-
const bx = cx - ux * headLen, by = cornerY - uy * headLen; // head base center
|
| 817 |
-
// line stops at the head base
|
| 818 |
-
el("line", {
|
| 819 |
-
x1: tx, y1: tailY, x2: bx, y2: by,
|
| 820 |
-
stroke: "var(--optimal)", "stroke-width": 13, "stroke-linecap": "round", opacity: 0.92,
|
| 821 |
-
}, parent);
|
| 822 |
-
const px = -uy, py = ux; // perpendicular
|
| 823 |
-
el("polygon", {
|
| 824 |
-
points: `${cx},${cornerY} ${bx + px * 11},${by + py * 11} ${bx - px * 11},${by - py * 11}`,
|
| 825 |
-
fill: "var(--optimal)", opacity: 0.92,
|
| 826 |
-
}, parent);
|
| 827 |
-
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
| 828 |
-
if (angle > 90 || angle < -90) angle += 180;
|
| 829 |
-
const mx = (tx + bx) / 2, my = (tailY + by) / 2;
|
| 830 |
-
const t = el("text", {
|
| 831 |
-
x: mx, y: my, "text-anchor": "middle", "dominant-baseline": "middle",
|
| 832 |
-
"font-size": 10.5, "font-weight": 700, fill: "#ffffff",
|
| 833 |
-
transform: `rotate(${angle} ${mx} ${my})`,
|
| 834 |
-
}, parent);
|
| 835 |
-
t.textContent = "Optimal";
|
| 836 |
-
}
|
| 837 |
-
|
| 838 |
-
// ---------- data ----------
|
| 839 |
-
const byMethod = new Map();
|
| 840 |
-
for (const p of POINTS) {
|
| 841 |
-
if (!byMethod.has(p.method)) byMethod.set(p.method, []);
|
| 842 |
-
byMethod.get(p.method).push(p); // insertion order = builder's point order
|
| 843 |
-
}
|
| 844 |
-
|
| 845 |
-
const METRICS = CONFIG.metrics;
|
| 846 |
-
let metricKey = METRICS[0].key;
|
| 847 |
-
const metricByKey = {};
|
| 848 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 849 |
-
|
| 850 |
-
// Single time axis per explorer (the scatter ships inference time, the
|
| 851 |
-
// trajectories train time).
|
| 852 |
-
const X_AXIS = CONFIG.xAxes[0];
|
| 853 |
-
const xKey = X_AXIS.key;
|
| 854 |
-
|
| 855 |
-
function mval(p, metric) { return p[metric.key]; }
|
| 856 |
-
|
| 857 |
-
function computeFront(metric) {
|
| 858 |
-
const xk = xKey;
|
| 859 |
-
const pts = [...POINTS].sort((a, b) =>
|
| 860 |
-
a[xk] - b[xk] || (metric.lowerBetter ? mval(a, metric) - mval(b, metric) : mval(b, metric) - mval(a, metric)));
|
| 861 |
-
const verts = [];
|
| 862 |
-
const methods = new Set();
|
| 863 |
-
let best = null;
|
| 864 |
-
for (const p of pts) {
|
| 865 |
-
const v = mval(p, metric);
|
| 866 |
-
if (best === null || (metric.lowerBetter ? v < best : v > best)) {
|
| 867 |
-
if (best !== null) verts.push([p[xk], best]);
|
| 868 |
-
verts.push([p[xk], v]);
|
| 869 |
-
best = v;
|
| 870 |
-
methods.add(p.method);
|
| 871 |
-
}
|
| 872 |
-
}
|
| 873 |
-
return { verts, methods };
|
| 874 |
-
}
|
| 875 |
-
|
| 876 |
-
const state = { active: new Set(computeFront(metricByKey[metricKey]).methods) };
|
| 877 |
-
|
| 878 |
-
// ---------- chart ----------
|
| 879 |
-
// A flat, fixed-height plot: two of these panels then fit on one screen.
|
| 880 |
-
const CHART_H = 400;
|
| 881 |
-
const M = { l: 62, r: 18, t: 14, b: 52 };
|
| 882 |
-
|
| 883 |
-
function render() {
|
| 884 |
-
const metric = metricByKey[metricKey];
|
| 885 |
-
svg.textContent = "";
|
| 886 |
-
const W = Math.max(360, Math.round(box.clientWidth));
|
| 887 |
-
const H = CHART_H;
|
| 888 |
-
svg.setAttribute("width", W);
|
| 889 |
-
svg.setAttribute("height", H);
|
| 890 |
-
// Keep the chip list from outgrowing the chart beside it.
|
| 891 |
-
chipsBox.style.maxHeight = Math.max(170, H - controlsBox.offsetHeight + 20) + "px";
|
| 892 |
-
|
| 893 |
-
// x scale (log)
|
| 894 |
-
const xsAll = POINTS.map(p => p[xKey]);
|
| 895 |
-
const xmin = Math.min(...xsAll) * 0.65, xmax = Math.max(...xsAll) * 1.6;
|
| 896 |
-
const lx0 = Math.log10(xmin), lx1 = Math.log10(xmax);
|
| 897 |
-
const X = v => M.l + (Math.log10(v) - lx0) / (lx1 - lx0) * (W - M.l - M.r);
|
| 898 |
-
|
| 899 |
-
const vals = POINTS.map(p => mval(p, metric));
|
| 900 |
-
let y0, y1;
|
| 901 |
-
if (metric.fromZero) {
|
| 902 |
-
y0 = 0; y1 = Math.max(...vals) * 1.07;
|
| 903 |
-
} else {
|
| 904 |
-
const pad = (Math.max(...vals) - Math.min(...vals)) * 0.07;
|
| 905 |
-
y0 = Math.min(...vals) - pad; y1 = Math.max(...vals) + pad;
|
| 906 |
-
}
|
| 907 |
-
const Y = v => M.t + (1 - (v - y0) / (y1 - y0)) * (H - M.t - M.b);
|
| 908 |
-
|
| 909 |
-
// grid + axes
|
| 910 |
-
const grid = el("g", {}, svg);
|
| 911 |
-
for (let e = Math.ceil(lx0); Math.pow(10, e) < xmax; e++) {
|
| 912 |
-
const gx = X(Math.pow(10, e));
|
| 913 |
-
el("line", { x1: gx, y1: M.t, x2: gx, y2: H - M.b, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 914 |
-
const lbl = fmtNum(Math.pow(10, e), e >= 0 ? 0 : -e);
|
| 915 |
-
el("text", { x: gx, y: H - M.b + 20, "text-anchor": "middle", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 916 |
-
.textContent = lbl;
|
| 917 |
-
}
|
| 918 |
-
for (const yv of ticks(y0, y1, 6)) {
|
| 919 |
-
const gy = Y(yv);
|
| 920 |
-
el("line", { x1: M.l, y1: gy, x2: W - M.r, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 921 |
-
el("text", { x: M.l - 8, y: gy + 4, "text-anchor": "end", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 922 |
-
.textContent = fmtNum(yv, Number.isInteger(yv) ? 0 : metric.decimals);
|
| 923 |
-
}
|
| 924 |
-
el("rect", { x: M.l, y: M.t, width: W - M.l - M.r, height: H - M.t - M.b, fill: "none", stroke: "var(--line)" }, grid);
|
| 925 |
-
el("text", {
|
| 926 |
-
x: (M.l + W - M.r) / 2, y: H - 10, "text-anchor": "middle", "font-size": 14,
|
| 927 |
-
"font-weight": 650, fill: "var(--ink)",
|
| 928 |
-
}, grid).textContent = X_AXIS.axisLabel;
|
| 929 |
-
el("text", {
|
| 930 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": 14, "font-weight": 650, fill: "var(--ink)",
|
| 931 |
-
transform: `translate(16 ${(M.t + H - M.b) / 2}) rotate(-90)`,
|
| 932 |
-
}, grid).textContent = metric.axisLabel;
|
| 933 |
-
|
| 934 |
-
drawOptimalArrow(grid, metric.lowerBetter, M, W, H);
|
| 935 |
-
|
| 936 |
-
// pareto front (always shown)
|
| 937 |
-
const front = computeFront(metric);
|
| 938 |
-
const fv = front.verts;
|
| 939 |
-
if (fv.length) {
|
| 940 |
-
let d = `M${X(fv[0][0])},${metric.lowerBetter ? M.t : H - M.b}`;
|
| 941 |
-
for (const [fx, fy] of fv) d += ` L${X(fx)},${Y(fy)}`;
|
| 942 |
-
d += ` L${W - M.r},${Y(fv[fv.length - 1][1])}`;
|
| 943 |
-
el("path", { d, fill: "none", stroke: "var(--ink)", "stroke-width": 1.6, "stroke-dasharray": "7 5", opacity: 0.85 }, svg);
|
| 944 |
-
}
|
| 945 |
-
|
| 946 |
-
const isOn = m => state.active.has(m);
|
| 947 |
-
|
| 948 |
-
// connectors: variant links (scatter) / the trajectory itself
|
| 949 |
-
const conn = el("g", {}, svg);
|
| 950 |
-
for (const [method, pts] of byMethod) {
|
| 951 |
-
if (pts.length < 2) continue;
|
| 952 |
-
const on = isOn(method);
|
| 953 |
-
if (!TRAJECTORY && !on) continue; // scatter: connectors only for active methods
|
| 954 |
-
const dd = pts.map((p, i) => `${i ? "L" : "M"}${X(p[xKey])},${Y(mval(p, metric))}`).join(" ");
|
| 955 |
-
el("path", {
|
| 956 |
-
d: dd, fill: "none",
|
| 957 |
-
stroke: on ? FAM_VAR[pts[0].family] : "var(--pt-muted)",
|
| 958 |
-
"stroke-width": on ? (TRAJECTORY ? 2 : 1.4) : 1,
|
| 959 |
-
opacity: on ? 0.6 : 0.35,
|
| 960 |
-
"data-m": method,
|
| 961 |
-
}, conn);
|
| 962 |
-
}
|
| 963 |
-
|
| 964 |
-
// points: inactive first, active on top
|
| 965 |
-
const ptsOff = el("g", {}, svg);
|
| 966 |
-
const ptsOn = el("g", {}, svg);
|
| 967 |
-
for (const [method, pts] of byMethod) {
|
| 968 |
-
const on = isOn(method);
|
| 969 |
-
for (const p of pts) {
|
| 970 |
-
const color = on ? FAM_VAR[p.family] : "var(--pt-muted)";
|
| 971 |
-
const size = (on ? 7 : 5) * (TRAJECTORY ? 0.8 : 1);
|
| 972 |
-
const op = on ? 0.95 : 0.5;
|
| 973 |
-
drawMark(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), p.variant, color, size, op, p.method, on);
|
| 974 |
-
// Imputation ring: every affected point in scatter mode; only the
|
| 975 |
-
// trajectory's end point in trajectory mode (a ring on all ~8 line
|
| 976 |
-
// points would read as beads, and the chip's ‡ already flags the line).
|
| 977 |
-
if (p.imputed && (!TRAJECTORY || p === pts[pts.length - 1])) {
|
| 978 |
-
drawImputedRing(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), size, color, op, p.method);
|
| 979 |
-
}
|
| 980 |
-
}
|
| 981 |
-
}
|
| 982 |
-
|
| 983 |
-
// labels for active methods at their best point, greedy de-overlap
|
| 984 |
-
const labels = [];
|
| 985 |
-
for (const [method, pts] of byMethod) {
|
| 986 |
-
if (!isOn(method)) continue;
|
| 987 |
-
const best = pts.reduce((a, b) =>
|
| 988 |
-
(metric.lowerBetter ? mval(a, metric) < mval(b, metric) : mval(a, metric) > mval(b, metric)) ? a : b);
|
| 989 |
-
labels.push({ method, family: best.family, x: X(best[xKey]) + 10, y: Y(mval(best, metric)) - 10 });
|
| 990 |
-
}
|
| 991 |
-
labels.sort((a, b) => a.y - b.y);
|
| 992 |
-
for (let i = 1; i < labels.length; i++) {
|
| 993 |
-
for (let j = 0; j < i; j++) {
|
| 994 |
-
if (Math.abs(labels[i].x - labels[j].x) < 110 && Math.abs(labels[i].y - labels[j].y) < 15) {
|
| 995 |
-
labels[i].y = labels[j].y + 15;
|
| 996 |
-
}
|
| 997 |
-
}
|
| 998 |
-
}
|
| 999 |
-
const lg = el("g", {}, svg);
|
| 1000 |
-
for (const l of labels) {
|
| 1001 |
-
const t = el("text", {
|
| 1002 |
-
x: Math.min(l.x, W - M.r - 8), y: Math.max(l.y, M.t + 12), "font-size": 13, "font-weight": 700,
|
| 1003 |
-
fill: FAM_VAR[l.family], "paint-order": "stroke", stroke: "var(--card)", "stroke-width": 3.5,
|
| 1004 |
-
"text-anchor": l.x > W - 120 ? "end" : "start",
|
| 1005 |
-
}, lg);
|
| 1006 |
-
t.textContent = l.method;
|
| 1007 |
-
}
|
| 1008 |
-
|
| 1009 |
-
// invisible hit targets on top (bigger than marks)
|
| 1010 |
-
const hits = el("g", {}, svg);
|
| 1011 |
-
for (const p of POINTS) {
|
| 1012 |
-
const h = el("circle", { cx: X(p[xKey]), cy: Y(mval(p, metric)), r: 12, fill: "transparent", cursor: "pointer" }, hits);
|
| 1013 |
-
h.addEventListener("mouseenter", ev => showTip(p, ev));
|
| 1014 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1015 |
-
h.addEventListener("mouseleave", () => hideTip(p.method));
|
| 1016 |
-
h.addEventListener("click", () => toggle(p.method));
|
| 1017 |
-
}
|
| 1018 |
-
}
|
| 1019 |
-
|
| 1020 |
-
// Temporary hover emphasis without a re-render (a re-render would replace
|
| 1021 |
-
// the hit node under the cursor mid-hover).
|
| 1022 |
-
function emphasize(method, on) {
|
| 1023 |
-
svg.querySelectorAll(`[data-m="${CSS.escape(method)}"]`).forEach(n => {
|
| 1024 |
-
if (on) {
|
| 1025 |
-
if (!n.dataset.save) n.dataset.save = n.getAttribute("opacity") || "1";
|
| 1026 |
-
n.setAttribute("opacity", "0.95");
|
| 1027 |
-
} else if (n.dataset.save) {
|
| 1028 |
-
n.setAttribute("opacity", n.dataset.save);
|
| 1029 |
-
delete n.dataset.save;
|
| 1030 |
-
}
|
| 1031 |
-
});
|
| 1032 |
-
}
|
| 1033 |
-
|
| 1034 |
-
function showTip(p, ev) {
|
| 1035 |
-
emphasize(p.method, true);
|
| 1036 |
-
const sub = TRAJECTORY ? (p.n_configs != null ? `${p.n_configs} configs` : "") : (p.variant || "");
|
| 1037 |
-
let html = `<div class="t-name">${p.method}` + (sub ? ` <span class="t-var">(${sub})</span>` : "") + "</div>" +
|
| 1038 |
-
`<div>${p.family}</div>`;
|
| 1039 |
-
for (const m of METRICS) {
|
| 1040 |
-
html += `<div>${m.label}: <b>${fmtMetric(m, mval(p, m))}</b></div>`;
|
| 1041 |
-
}
|
| 1042 |
-
html += `<div>${X_AXIS.short}: <b>${fmtTime(p[xKey])}</b></div>`;
|
| 1043 |
-
if (p.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(p.imputed_pct, 0)}% of datasets</div>`;
|
| 1044 |
-
tip.show(html, ev);
|
| 1045 |
-
}
|
| 1046 |
-
function hideTip(method) {
|
| 1047 |
-
emphasize(method, false);
|
| 1048 |
-
tip.hide();
|
| 1049 |
-
}
|
| 1050 |
-
|
| 1051 |
-
// ---------- chips ----------
|
| 1052 |
-
const chipByMethod = new Map();
|
| 1053 |
-
const famChips = new Map();
|
| 1054 |
-
function familyMethods(fam) {
|
| 1055 |
-
return [...byMethod.keys()].filter(m => byMethod.get(m)[0].family === fam);
|
| 1056 |
-
}
|
| 1057 |
-
// Chips are listed by leaderboard rank — best Elo first when Elo is
|
| 1058 |
-
// configured, otherwise best value of the primary metric.
|
| 1059 |
-
const RANK_METRIC = metricByKey["elo"] || metricByKey[METRICS[0].key];
|
| 1060 |
-
function bestVal(method) {
|
| 1061 |
-
const vals = byMethod.get(method).map(p => mval(p, RANK_METRIC));
|
| 1062 |
-
return RANK_METRIC.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 1063 |
-
}
|
| 1064 |
-
function rankSorted(methods) {
|
| 1065 |
-
return [...methods].sort((a, b) =>
|
| 1066 |
-
RANK_METRIC.lowerBetter ? bestVal(a) - bestVal(b) : bestVal(b) - bestVal(a));
|
| 1067 |
-
}
|
| 1068 |
-
function buildChips() {
|
| 1069 |
-
for (const fam of FAM_ORDER) {
|
| 1070 |
-
const methods = rankSorted(familyMethods(fam));
|
| 1071 |
-
if (!methods.length) continue;
|
| 1072 |
-
const row = document.createElement("div");
|
| 1073 |
-
row.className = "chiprow";
|
| 1074 |
-
const famBtn = document.createElement("button");
|
| 1075 |
-
famBtn.className = "famchip";
|
| 1076 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1077 |
-
famBtn.innerHTML = famChipLabel(fam, methods.length);
|
| 1078 |
-
famBtn.title = `Toggle all ${methods.length} ${fam} methods`;
|
| 1079 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1080 |
-
row.appendChild(famBtn);
|
| 1081 |
-
famChips.set(fam, famBtn);
|
| 1082 |
-
const set = document.createElement("div");
|
| 1083 |
-
set.className = "chipset";
|
| 1084 |
-
for (const m of methods) {
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "chip";
|
| 1087 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1088 |
-
const imputed = byMethod.get(m).some(p => p.imputed);
|
| 1089 |
-
const label = document.createElement("span");
|
| 1090 |
-
label.textContent = m;
|
| 1091 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1092 |
-
b.appendChild(label);
|
| 1093 |
-
if (imputed) {
|
| 1094 |
-
const mark = document.createElement("span");
|
| 1095 |
-
mark.className = "imp-mark";
|
| 1096 |
-
mark.textContent = "‡";
|
| 1097 |
-
b.appendChild(mark);
|
| 1098 |
-
}
|
| 1099 |
-
b.title = m + (imputed ? " — partially imputed" : "");
|
| 1100 |
-
b.addEventListener("click", () => toggle(m));
|
| 1101 |
-
set.appendChild(b);
|
| 1102 |
-
chipByMethod.set(m, b);
|
| 1103 |
-
}
|
| 1104 |
-
row.appendChild(set);
|
| 1105 |
-
chipsBox.appendChild(row);
|
| 1106 |
-
}
|
| 1107 |
-
}
|
| 1108 |
-
function syncChips() {
|
| 1109 |
-
for (const [m, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.active.has(m)));
|
| 1110 |
-
for (const [fam, b] of famChips) {
|
| 1111 |
-
b.setAttribute("aria-pressed", String(familyMethods(fam).every(m => state.active.has(m))));
|
| 1112 |
-
}
|
| 1113 |
-
}
|
| 1114 |
-
function toggle(m) {
|
| 1115 |
-
if (state.active.has(m)) state.active.delete(m); else state.active.add(m);
|
| 1116 |
-
syncChips();
|
| 1117 |
-
render();
|
| 1118 |
-
}
|
| 1119 |
-
function toggleFamily(fam) {
|
| 1120 |
-
const methods = familyMethods(fam);
|
| 1121 |
-
const allOn = methods.every(m => state.active.has(m));
|
| 1122 |
-
for (const m of methods) {
|
| 1123 |
-
if (allOn) state.active.delete(m); else state.active.add(m);
|
| 1124 |
-
}
|
| 1125 |
-
syncChips();
|
| 1126 |
-
render();
|
| 1127 |
-
}
|
| 1128 |
-
function setActive(methods) {
|
| 1129 |
-
state.active = new Set(methods);
|
| 1130 |
-
syncChips();
|
| 1131 |
-
render();
|
| 1132 |
-
}
|
| 1133 |
-
document.getElementById("btn-front").addEventListener("click",
|
| 1134 |
-
() => setActive(computeFront(metricByKey[metricKey]).methods));
|
| 1135 |
-
document.getElementById("btn-all").addEventListener("click", () => setActive([...byMethod.keys()]));
|
| 1136 |
-
document.getElementById("btn-none").addEventListener("click", () => setActive([]));
|
| 1137 |
-
|
| 1138 |
-
// metric selector (hidden when only one metric is configured)
|
| 1139 |
-
const metricPick = document.getElementById("metricpick");
|
| 1140 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1141 |
-
if (METRICS.length > 1) {
|
| 1142 |
-
metricPick.hidden = false;
|
| 1143 |
-
for (const m of METRICS) {
|
| 1144 |
-
const opt = document.createElement("option");
|
| 1145 |
-
opt.value = m.key;
|
| 1146 |
-
opt.textContent = m.label;
|
| 1147 |
-
metricSelect.appendChild(opt);
|
| 1148 |
-
}
|
| 1149 |
-
metricSelect.addEventListener("change", ev => {
|
| 1150 |
-
metricKey = ev.target.value;
|
| 1151 |
-
render();
|
| 1152 |
-
});
|
| 1153 |
-
}
|
| 1154 |
-
|
| 1155 |
-
// ---------- legend strip ----------
|
| 1156 |
-
function buildLegend() {
|
| 1157 |
-
const box2 = document.getElementById("legendstrip");
|
| 1158 |
-
let html = "";
|
| 1159 |
-
if (!TRAJECTORY) {
|
| 1160 |
-
html +=
|
| 1161 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><circle cx="7" cy="7" r="5" fill="var(--muted)"/></svg> Default</span>' +
|
| 1162 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" rx="1.5" fill="var(--muted)"/></svg> Tuned</span>' +
|
| 1163 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><path d="M3,3 L11,11 M3,11 L11,3" stroke="var(--muted)" stroke-width="2.6" stroke-linecap="round"/></svg> Tuned + Ensembled</span>';
|
| 1164 |
-
} else {
|
| 1165 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--muted)" stroke-width="2"/><circle cx="6" cy="4" r="2.6" fill="var(--muted)"/><circle cx="16" cy="4" r="2.6" fill="var(--muted)"/></svg> Tuning trajectory (more configs → more time)</span>';
|
| 1166 |
-
}
|
| 1167 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--ink)" stroke-width="1.6" stroke-dasharray="6 4"/></svg> Pareto front (always shown)</span>';
|
| 1168 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1169 |
-
html += '<span class="item"><svg width="18" height="18" viewBox="0 0 18 18"><circle cx="9" cy="9" r="4" fill="var(--muted)"/><circle cx="9" cy="9" r="7.5" fill="none" stroke="var(--muted)" stroke-width="1.3" stroke-dasharray="3 2.5"/></svg> ‡ partially imputed</span>';
|
| 1170 |
-
}
|
| 1171 |
-
// Model family, named: highlighted points are colored by family, and in paper
|
| 1172 |
-
// view the chip list that would otherwise decode them is hidden.
|
| 1173 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => p.family === f));
|
| 1174 |
-
if (families.length > 1) {
|
| 1175 |
-
html += '<span class="legendbreak"></span><span class="item">Family:</span>';
|
| 1176 |
-
for (const fam of families) {
|
| 1177 |
-
html += `<span class="item"><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1178 |
-
`<circle cx="6" cy="6" r="5" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1179 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`;
|
| 1180 |
-
}
|
| 1181 |
-
}
|
| 1182 |
-
box2.innerHTML = html;
|
| 1183 |
-
}
|
| 1184 |
-
|
| 1185 |
-
// ---------- paper view ----------
|
| 1186 |
-
setUpPaperView(render);
|
| 1187 |
-
setUpExport(() => [{ svg: svg, dx: 0 }], () => slugify(document.title));
|
| 1188 |
-
|
| 1189 |
-
// ---------- data table ----------
|
| 1190 |
-
function buildTable() {
|
| 1191 |
-
const m0 = metricByKey[METRICS[0].key];
|
| 1192 |
-
const rows = [...POINTS].sort((a, b) =>
|
| 1193 |
-
m0.lowerBetter ? mval(a, m0) - mval(b, m0) : mval(b, m0) - mval(a, m0));
|
| 1194 |
-
let html = "<table><thead><tr><th>Method</th>";
|
| 1195 |
-
html += TRAJECTORY ? "<th>Configs</th>" : "<th>Variant</th>";
|
| 1196 |
-
html += "<th>Family</th>";
|
| 1197 |
-
for (const m of METRICS) html += `<th>${m.label}</th>`;
|
| 1198 |
-
html += `<th>${X_AXIS.short}</th><th>Imputed</th></tr></thead><tbody>`;
|
| 1199 |
-
for (const p of rows) {
|
| 1200 |
-
html += `<tr><td>${p.method}</td><td>${TRAJECTORY ? (p.n_configs != null ? p.n_configs : "—") : p.variant}</td><td>${p.family}</td>`;
|
| 1201 |
-
for (const m of METRICS) html += `<td>${fmtMetric(m, mval(p, m))}</td>`;
|
| 1202 |
-
html += `<td>${fmtNum(p[xKey], 3)}</td>`;
|
| 1203 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1204 |
-
}
|
| 1205 |
-
html += "</tbody></table>";
|
| 1206 |
-
document.getElementById("tblwrap").innerHTML = html;
|
| 1207 |
-
}
|
| 1208 |
-
|
| 1209 |
-
const _renderInner = render;
|
| 1210 |
-
render = function () {
|
| 1211 |
-
_renderInner();
|
| 1212 |
-
postHeight();
|
| 1213 |
-
};
|
| 1214 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1215 |
-
let resizeTimer = null;
|
| 1216 |
-
window.addEventListener("resize", () => {
|
| 1217 |
-
clearTimeout(resizeTimer);
|
| 1218 |
-
resizeTimer = setTimeout(render, 120);
|
| 1219 |
-
});
|
| 1220 |
-
window.addEventListener("load", postHeight);
|
| 1221 |
-
|
| 1222 |
-
buildChips();
|
| 1223 |
-
buildLegend();
|
| 1224 |
-
buildTable();
|
| 1225 |
-
syncChips();
|
| 1226 |
-
render();
|
| 1227 |
-
})();
|
| 1228 |
-
</script>
|
| 1229 |
-
</body>
|
| 1230 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/website_leaderboard.csv
DELETED
|
@@ -1,71 +0,0 @@
|
|
| 1 |
-
#,Type,TypeName,Model,Elo [⬆️],Elo 95% CI,Score [⬆️],Rank [⬇️],Harmonic Rank [⬇️],Improvability (%) [⬇️],Median Train Time (s/1K) [⬇️],Median Predict Time (s/1K) [⬇️],Verified,Imputed (%) [⬇️],Imputed,Hardware
|
| 2 |
-
0,🧠⚡,Foundation Model,[TabFM (default)](https://github.com/google-research/tabfm),1792.0,+115/-110,0.889,6.17,1.72,4.074,38.81,6.985,✔️,0.0,False,GPU
|
| 3 |
-
1,📊,Reference Pipeline,"[AutoGluon 1.5 (extreme, 4h)](https://arxiv.org/abs/2003.06505)",1691.0,+82/-68,0.662,9.39,4.03,7.979,289.07,4.031,✔️,0.0,False,GPU
|
| 4 |
-
2,🧠⚡,Foundation Model,[TabPFN-3 (default)](https://arxiv.org/abs/2605.13986),1665.0,+80/-61,0.67,10.41,4.06,9.328,3.66,0.399,✔️,0.0,False,GPU
|
| 5 |
-
3,🧠⚡,Foundation Model,[TabPFN-2.6 (default)](https://arxiv.org/abs/2511.08667),1620.0,+71/-51,0.583,12.42,7.14,10.751,5.48,0.555,✔️,0.0,False,GPU
|
| 6 |
-
4,🧠⚡,Foundation Model,[RealTabPFN-2.5 (tuned + ensembled)](https://arxiv.org/abs/2511.08667),1595.0,+74/-56,0.549,13.64,6.22,10.427,2040.22,8.908,✔️,0.0,False,GPU
|
| 7 |
-
5,🧠⚡,Foundation Model,[TabICLv2 (default)](https://arxiv.org/abs/2602.11139),1594.0,+73/-61,0.606,13.71,4.97,10.175,2.05,0.151,✔️,0.0,False,GPU
|
| 8 |
-
6,🧠⚡,Foundation Model,[RealTabPFN-2.5 (tuned)](https://arxiv.org/abs/2511.08667),1554.0,+65/-55,0.504,15.81,7.33,11.116,2040.22,1.218,✔️,0.0,False,GPU
|
| 9 |
-
7,🧠⚡,Foundation Model,[RealTabPFN-2.5 (default)](https://arxiv.org/abs/2511.08667),1524.0,+62/-44,0.474,17.55,9.62,11.66,5.81,0.645,✔️,0.0,False,GPU
|
| 10 |
-
8,📊,Reference Pipeline,"[AutoGluon 1.4 (best, 4h)](https://arxiv.org/abs/2003.06505)",1514.0,+53/-46,0.401,18.2,8.44,12.789,1735.72,2.558,✔️,0.0,False,CPU
|
| 11 |
-
9,🧠🔁,Neural Network,[RealMLP (tuned + ensembled)](https://arxiv.org/abs/2407.04491),1508.0,+54/-46,0.405,18.55,11.52,12.881,2950.72,11.975,✔️,0.0,False,GPU
|
| 12 |
-
10,🧠⚡,Foundation Model,[TabDPT-Turbo (default)](https://openreview.net/pdf?id=Y00pwFyrHR),1459.0,+55/-51,0.38,21.7,9.59,14.0,2.07,0.182,➖,0.0,False,GPU
|
| 13 |
-
11,🧠⚡,Foundation Model,[TabDPT (tuned + ensembled)](https://arxiv.org/abs/2410.18164),1458.0,+60/-51,0.375,21.81,8.16,13.788,4910.38,286.537,✔️,0.0,False,GPU
|
| 14 |
-
12,🧠🔁,Neural Network,[TabM (tuned + ensembled)](https://arxiv.org/abs/2410.24210),1450.0,+52/-43,0.315,22.33,12.48,14.081,2450.13,2.247,✔️,0.0,False,GPU
|
| 15 |
-
13,🌳,Tree-based,[LightGBM (tuned + ensembled)](https://papers.nips.cc/paper_files/paper/2017/hash/6449f44a102fde848669bdd9eb6b76fa-Abstract.html),1433.0,+33/-31,0.262,23.53,17.2,15.033,417.05,2.639,✔️,0.0,False,CPU
|
| 16 |
-
14,🧠🔁,Neural Network,[RealMLP (tuned)](https://arxiv.org/abs/2407.04491),1426.0,+48/-45,0.295,23.99,13.67,14.202,2950.72,0.663,✔️,0.0,False,GPU
|
| 17 |
-
15,🌳,Tree-based,[CatBoost (tuned + ensembled)](https://arxiv.org/abs/1706.09516),1422.0,+39/-38,0.261,24.34,14.77,14.656,1346.21,0.344,✔️,0.0,False,CPU
|
| 18 |
-
16,🌳,Tree-based,[CatBoost (tuned)](https://arxiv.org/abs/1706.09516),1408.0,+38/-43,0.245,25.3,15.31,14.885,1346.21,0.038,✔️,0.0,False,CPU
|
| 19 |
-
17,🧠⚡,Foundation Model,[iLTM (tuned + ensembled)](https://arxiv.org/abs/2511.15941),1404.0,+40/-42,0.235,25.56,17.78,15.304,12685.08,464.37,✔️,0.0,False,GPU
|
| 20 |
-
18,🧠⚡,Foundation Model,[TabDPT (tuned)](https://arxiv.org/abs/2410.18164),1403.0,+59/-56,0.316,25.69,11.3,14.936,4910.38,39.96,✔️,0.0,False,GPU
|
| 21 |
-
19,🧠🔁,Neural Network,[TabM (tuned)](https://arxiv.org/abs/2410.24210),1394.0,+48/-42,0.251,26.35,14.47,14.952,2450.13,0.251,✔️,0.0,False,GPU
|
| 22 |
-
20,🧠🔁,Neural Network,[ModernNCA (tuned + ensembled)](https://arxiv.org/abs/2407.03257),1389.0,+73/-52,0.277,26.66,12.79,15.599,4621.67,8.138,✔️,0.0,False,GPU
|
| 23 |
-
21,🌳,Tree-based,[LightGBM (tuned)](https://papers.nips.cc/paper_files/paper/2017/hash/6449f44a102fde848669bdd9eb6b76fa-Abstract.html),1386.0,+29/-29,0.194,26.93,20.71,15.688,417.05,0.334,✔️,0.0,False,CPU
|
| 24 |
-
22,🌳,Tree-based,[CatBoost (default)](https://arxiv.org/abs/1706.09516),1378.0,+40/-42,0.224,27.47,16.11,15.524,5.88,0.025,✔️,0.0,False,CPU
|
| 25 |
-
23,🌳,Tree-based,[XGBoost (tuned + ensembled)](https://arxiv.org/abs/1603.02754),1375.0,+31/-33,0.198,27.73,19.98,15.754,693.49,1.689,✔️,0.0,False,CPU
|
| 26 |
-
24,🧠⚡,Foundation Model,[LimiX (default)](https://arxiv.org/abs/2509.03505),1363.0,+78/-59,0.299,28.66,9.55,15.526,26.46,6.242,➖,0.0,False,GPU
|
| 27 |
-
25,🧠🔁,Neural Network,[ModernNCA (tuned)](https://arxiv.org/abs/2407.03257),1355.0,+37/-37,0.189,29.21,16.82,16.044,4621.67,0.475,✔️,0.0,False,GPU
|
| 28 |
-
26,🧠⚡,Foundation Model,[TabSwift (default)](https://github.com/LAMDA-Tabular/TabSwift),1350.0,+58/-52,0.251,29.58,17.68,16.081,1.18,0.072,➖,0.0,False,GPU
|
| 29 |
-
27,🌳,Tree-based,[XGBoost (tuned)](https://arxiv.org/abs/1603.02754),1350.0,+29/-32,0.16,29.6,22.22,16.065,693.49,0.308,✔️,0.0,False,CPU
|
| 30 |
-
28,❓,Other,[xRFM (tuned + ensembled)](https://arxiv.org/abs/2508.10053),1348.0,+49/-43,0.209,29.79,18.96,16.284,846.89,2.549,✔️,0.0,False,GPU
|
| 31 |
-
29,🌳,Tree-based,[ChimeraBoost (tuned + ensembled)](https://github.com/bbstats/chimeraboost),1333.0,+46/-60,0.186,30.87,19.34,17.213,427.39,0.404,✔���,0.0,False,CPU
|
| 32 |
-
30,🧠⚡,Foundation Model,[TabDPT (default)](https://arxiv.org/abs/2410.18164),1325.0,+64/-55,0.245,31.53,14.33,17.225,47.65,43.738,✔️,0.0,False,GPU
|
| 33 |
-
31,🌳,Tree-based,[ChimeraBoost (tuned)](https://github.com/bbstats/chimeraboost),1308.0,+44/-60,0.156,32.79,21.32,17.551,427.39,0.034,✔️,0.0,False,CPU
|
| 34 |
-
32,❓,Other,[xRFM (tuned)](https://arxiv.org/abs/2508.10053),1300.0,+45/-39,0.158,33.43,22.28,17.449,846.89,0.13,✔️,0.0,False,GPU
|
| 35 |
-
33,🧠🔁,Neural Network,[TabM (default)](https://arxiv.org/abs/2410.24210),1298.0,+47/-44,0.161,33.63,21.84,17.0,7.49,0.244,✔️,0.0,False,GPU
|
| 36 |
-
34,🧠⚡,Foundation Model,[iLTM (tuned)](https://arxiv.org/abs/2511.15941),1295.0,+40/-33,0.111,33.83,23.47,17.147,12685.08,62.13,✔️,0.0,False,GPU
|
| 37 |
-
35,🧠🔁,Neural Network,[TorchMLP (tuned + ensembled)](https://arxiv.org/abs/2003.06505),1285.0,+48/-47,0.126,34.58,25.37,17.161,2875.52,1.952,✔️,0.0,False,CPU
|
| 38 |
-
36,🧠⚡,Foundation Model,[SAP-RPT-OSS (default)](https://arxiv.org/abs/2506.10707),1283.0,+57/-55,0.194,34.72,14.11,18.278,14.11,2.075,➖,0.0,False,GPU
|
| 39 |
-
37,🌳,Tree-based,[EBM (tuned + ensembled)](https://www.cs.cornell.edu/~yinlou/papers/lou-kdd13.pdf),1272.0,+40/-40,0.116,35.64,25.8,18.672,1711.25,0.141,✔️,0.0,False,CPU
|
| 40 |
-
38,🌳,Tree-based,[ChimeraBoost (default)](https://github.com/bbstats/chimeraboost),1264.0,+47/-55,0.121,36.23,23.23,18.657,1.99,0.033,✔️,0.0,False,CPU
|
| 41 |
-
39,🧠🔁,Neural Network,[ModernNCA (default)](https://arxiv.org/abs/2407.03257),1248.0,+41/-39,0.09,37.44,23.68,19.194,14.87,0.307,✔️,0.0,False,GPU
|
| 42 |
-
40,🌳,Tree-based,[EBM (tuned)](https://www.cs.cornell.edu/~yinlou/papers/lou-kdd13.pdf),1235.0,+44/-40,0.082,38.43,28.17,19.314,1711.25,0.015,✔️,0.0,False,CPU
|
| 43 |
-
41,🧠🔁,Neural Network,[RealMLP (default)](https://arxiv.org/abs/2407.04491),1230.0,+36/-37,0.066,38.85,29.23,18.569,10.06,1.689,✔️,0.0,False,GPU
|
| 44 |
-
42,🌳,Tree-based,[XGBoost (default)](https://arxiv.org/abs/1603.02754),1214.0,+39/-36,0.053,40.04,30.76,18.792,1.94,0.123,✔️,0.0,False,CPU
|
| 45 |
-
43,🧠🔁,Neural Network,[TorchMLP (tuned)](https://arxiv.org/abs/2003.06505),1212.0,+41/-42,0.069,40.24,30.96,18.877,2875.52,0.131,✔️,0.0,False,CPU
|
| 46 |
-
44,🌳,Tree-based,[ExtraTrees (tuned + ensembled)](https://link.springer.com/article/10.1007/s10994-006-6226-1),1208.0,+49/-43,0.083,40.47,28.16,19.777,263.04,0.766,✔️,0.0,False,CPU
|
| 47 |
-
45,🧠🔁,Neural Network,[FastaiMLP (tuned + ensembled)](https://arxiv.org/abs/2003.06505),1207.0,+51/-59,0.105,40.58,25.38,19.677,593.24,4.467,✔️,0.0,False,CPU
|
| 48 |
-
46,🌳,Tree-based,[EBM (default)](https://www.cs.cornell.edu/~yinlou/papers/lou-kdd13.pdf),1204.0,+45/-49,0.069,40.82,28.54,20.255,6.67,0.014,✔️,0.0,False,CPU
|
| 49 |
-
47,🌳,Tree-based,[LightGBM (default)](https://papers.nips.cc/paper_files/paper/2017/hash/6449f44a102fde848669bdd9eb6b76fa-Abstract.html),1186.0,+34/-29,0.038,42.12,36.15,19.344,1.96,0.142,✔️,0.0,False,CPU
|
| 50 |
-
48,🌳,Tree-based,[ExtraTrees (tuned)](https://link.springer.com/article/10.1007/s10994-006-6226-1),1180.0,+45/-52,0.074,42.56,26.73,20.564,263.04,0.071,✔️,0.0,False,CPU
|
| 51 |
-
49,🌳,Tree-based,[RandomForest (tuned + ensembled)](https://link.springer.com/article/10.1023/A:1010933404324),1171.0,+54/-47,0.06,43.28,29.04,20.828,373.24,0.771,✔️,0.0,False,CPU
|
| 52 |
-
50,🧠🔁,Neural Network,[FastaiMLP (tuned)](https://arxiv.org/abs/2003.06505),1147.0,+52/-59,0.048,45.01,31.19,21.096,593.24,0.306,✔️,0.0,False,CPU
|
| 53 |
-
51,🌳,Tree-based,[RandomForest (tuned)](https://link.springer.com/article/10.1023/A:1010933404324),1137.0,+50/-44,0.041,45.71,28.56,21.535,373.24,0.085,✔️,0.0,False,CPU
|
| 54 |
-
52,🧠⚡,Foundation Model,[TabSTAR (tuned)](https://arxiv.org/abs/2505.18125),1097.0,+75/-83,0.125,48.47,15.95,25.584,28729.74,4.268,✔️,0.0,False,GPU
|
| 55 |
-
53,🧠⚡,Foundation Model,[TabSTAR (tuned + ensembled)](https://arxiv.org/abs/2505.18125),1096.0,+79/-83,0.123,48.56,15.35,25.6,28729.74,18.811,✔️,0.0,False,GPU
|
| 56 |
-
54,🧠⚡,Foundation Model,[iLTM (default)](https://arxiv.org/abs/2511.15941),1094.0,+47/-54,0.037,48.66,33.93,23.024,296.64,68.173,✔️,0.0,False,GPU
|
| 57 |
-
55,🌳,Tree-based,[PerpetualBooster (tuned + ensembled)](https://perpetual-ml.com/),1089.0,+44/-45,0.024,49.04,38.83,26.446,185.31,0.6,✔️,0.0,False,CPU
|
| 58 |
-
56,🧠🔁,Neural Network,[TorchMLP (default)](https://arxiv.org/abs/2003.06505),1074.0,+34/-42,0.011,49.99,39.42,22.815,9.99,0.126,✔️,0.0,False,CPU
|
| 59 |
-
57,🌳,Tree-based,[PerpetualBooster (tuned)](https://perpetual-ml.com/),1050.0,+47/-50,0.011,51.52,39.96,27.802,185.31,0.258,✔️,0.0,False,CPU
|
| 60 |
-
58,❓,Other,[xRFM (default)](https://arxiv.org/abs/2508.10053),1043.0,+61/-70,0.029,51.95,44.11,26.445,3.23,0.919,✔️,0.0,False,GPU
|
| 61 |
-
59,🌳,Tree-based,[ExtraTrees (default)](https://link.springer.com/article/10.1007/s10994-006-6226-1),1009.0,+51/-66,0.012,54.0,47.38,26.176,1.87,0.283,✔️,0.0,False,CPU
|
| 62 |
-
60,🧠🔁,Neural Network,[FastaiMLP (default)](https://arxiv.org/abs/2003.06505),1008.0,+57/-62,0.009,54.07,39.97,25.682,2.86,0.373,✔️,0.0,False,CPU
|
| 63 |
-
61,🌳,Tree-based,[RandomForest (default)](https://link.springer.com/article/10.1023/A:1010933404324),1000.0,+47/-47,0.003,54.51,49.81,26.265,0.43,0.054,✔️,0.0,False,CPU
|
| 64 |
-
62,📏,Baseline,[KNN (tuned + ensembled)](https://scikit-learn.org/stable/modules/neighbors.html),997.0,+61/-76,0.017,54.67,38.92,27.822,129.08,1.801,✔️,0.0,False,CPU
|
| 65 |
-
63,🧠⚡,Foundation Model,[TabSTAR (default)](https://arxiv.org/abs/2505.18125),993.0,+89/-104,0.077,54.89,24.31,30.456,384.75,5.348,✔️,0.0,False,GPU
|
| 66 |
-
64,📏,Baseline,[Linear (tuned + ensembled)](https://scikit-learn.org/stable/modules/linear_model.html),965.0,+64/-100,0.031,56.39,40.87,33.667,237.63,0.424,✔️,0.0,False,CPU
|
| 67 |
-
65,📏,Baseline,[Linear (tuned)](https://scikit-learn.org/stable/modules/linear_model.html),940.0,+70/-105,0.022,57.67,42.64,34.211,237.63,0.085,✔️,0.0,False,CPU
|
| 68 |
-
66,🌳,Tree-based,[PerpetualBooster (default)](https://perpetual-ml.com/),936.0,+43/-57,0.0,57.84,45.44,31.748,27.32,0.029,✔️,0.0,False,CPU
|
| 69 |
-
67,📏,Baseline,[KNN (tuned)](https://scikit-learn.org/stable/modules/neighbors.html),890.0,+61/-100,0.008,59.92,46.93,32.782,129.08,0.18,✔️,0.0,False,CPU
|
| 70 |
-
68,📏,Baseline,[Linear (default)](https://scikit-learn.org/stable/modules/linear_model.html),861.0,+69/-118,0.014,61.12,47.51,36.822,1.19,0.12,✔️,0.0,False,CPU
|
| 71 |
-
69,📏,Baseline,[KNN (default)](https://scikit-learn.org/stable/modules/neighbors.html),654.0,+78/-91,0.0,66.89,60.42,45.987,0.19,0.036,✔️,0.0,False,CPU
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/winrate_explorer.html
DELETED
|
@@ -1,1169 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>Arena win-rate matrix</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* The matrix scrolls in both directions: 40+ models will not fit a page either
|
| 269 |
-
way, and shrinking the cells to fit makes the numbers unreadable. `margin:
|
| 270 |
-
auto` centres it once the selection is small enough to fit — and collapses
|
| 271 |
-
to zero when it overflows, which `justify-content: center` would not. */
|
| 272 |
-
.wr-scroll {
|
| 273 |
-
overflow: auto; max-width: 100%;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.wr-scroll::-webkit-scrollbar { width: 11px; height: 11px; }
|
| 277 |
-
.wr-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
#chart { display: block; margin-inline: auto; }
|
| 282 |
-
.wr-empty { padding: 40px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 283 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 284 |
-
.chips { margin: 2px 0 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 285 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 286 |
-
</style>
|
| 287 |
-
</head>
|
| 288 |
-
<body>
|
| 289 |
-
<div class="viewbar">
|
| 290 |
-
<button class="btn" id="btn-paper" title="White background, matrix only — for slides and papers">Paper view</button>
|
| 291 |
-
</div>
|
| 292 |
-
<p class="explorer-title" id="title"></p>
|
| 293 |
-
<div class="controls">
|
| 294 |
-
<button class="btn toggle" id="btn-best"
|
| 295 |
-
title="Keep only each model's best-performing variant, one row and column per model — as the static figure does">One per model</button>
|
| 296 |
-
<span class="grouplabel">Variants</span>
|
| 297 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 298 |
-
<label class="metricpick">Order
|
| 299 |
-
<select id="order-select">
|
| 300 |
-
<option value="published">As published</option>
|
| 301 |
-
<option value="winrate">Mean win rate</option>
|
| 302 |
-
<option value="name">Name</option>
|
| 303 |
-
</select>
|
| 304 |
-
</label>
|
| 305 |
-
<label class="metricpick">Size
|
| 306 |
-
<select id="zoom-select" title="Fit scales the whole matrix into the panel; the percentages draw it at reading size and scroll">
|
| 307 |
-
<option value="fit">Fit panel</option>
|
| 308 |
-
<option value="0.6">60%</option>
|
| 309 |
-
<option value="0.8">80%</option>
|
| 310 |
-
<option value="1">100%</option>
|
| 311 |
-
</select>
|
| 312 |
-
</label>
|
| 313 |
-
<span class="hint">Click a row or column label to remove that model</span>
|
| 314 |
-
</div>
|
| 315 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 316 |
-
<span class="hint">Export figure</span>
|
| 317 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">Download SVG</button>
|
| 318 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">Download PDF</button>
|
| 319 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">Download PNG</button>
|
| 320 |
-
</div>
|
| 321 |
-
<div class="chips" id="chips"></div>
|
| 322 |
-
<div class="wr-scroll" id="wrap">
|
| 323 |
-
<svg id="chart" role="img" aria-label="Pairwise win-rate matrix"></svg>
|
| 324 |
-
</div>
|
| 325 |
-
<div class="tooltip"></div>
|
| 326 |
-
|
| 327 |
-
<script>
|
| 328 |
-
(function () {
|
| 329 |
-
"use strict";
|
| 330 |
-
const CONFIG = {"title": null, "methods": ["TabFM (default)", "TabPFN-3 (default)", "TabPFN-2.6 (default)", "TabICLv2 (default)", "RealTabPFN-2.5 (T+E)", "RealMLP (T+E)", "TabDPT-Turbo (default)", "TabDPT (T+E)", "TabM (T+E)", "LightGBM (T+E)", "CatBoost (T+E)", "iLTM (T+E)", "ModernNCA (T+E)", "LimiX (default)", "XGBoost (T+E)", "TabSwift (default)", "xRFM (T+E)", "ChimeraBoost (T+E)", "SAP-RPT-OSS (default)", "TorchMLP (T+E)", "EBM (T+E)", "ExtraTrees (T+E)", "FastaiMLP (T+E)", "RandomForest (T+E)", "TabSTAR (T+E)", "PerpetualBooster (T+E)", "KNN (T+E)", "Linear (T+E)"], "matrix": [[NaN, 0.7877995371818542, 0.832461953163147, 0.8446625471115112, 0.8332244157791138, 0.8671024441719055, 0.9039215445518494, 0.8777777552604675, 0.9117648005485535, 0.9076253771781921, 0.9030501246452332, 0.90152508020401, 0.911328911781311, 0.9027233719825745, 0.9257081747055054, 0.899564266204834, 0.9193899631500244, 0.9211329817771912, 0.9093682765960693, 0.946405291557312, 0.9333334565162659, 0.9507625102996826, 0.9226579666137695, 0.9607843160629272, 0.9008715152740479, 0.9897603988647461, 0.9607843160629272, 0.9747276902198792], [0.21220043301582336, NaN, 0.6313725709915161, 0.5980392098426819, 0.6503269076347351, 0.7633987069129944, 0.8095861673355103, 0.7507625818252563, 0.8098039627075195, 0.8141611814498901, 0.817211389541626, 0.840522825717926, 0.8544661402702332, 0.7888888120651245, 0.8476034998893738, 0.9067538976669312, 0.8559913635253906, 0.8660130500793457, 0.8488017916679382, 0.9095861315727234, 0.872984766960144, 0.9424837231636047, 0.9046840071678162, 0.9368192553520203, 0.9028322696685791, 0.9474945068359375, 0.9496732354164124, 0.9533769488334656], [0.1675381362438202, 0.3686274588108063, NaN, 0.4673202335834503, 0.4984748661518097, 0.7224401831626892, 0.6877995133399963, 0.688235342502594, 0.7675382494926453, 0.7921568751335144, 0.80305016040802, 0.813507616519928, 0.8211329579353333, 0.7742919325828552, 0.8326797485351562, 0.8226578831672668, 0.8357298374176025, 0.8614379167556763, 0.8477123975753784, 0.8941175937652588, 0.8880175352096558, 0.9265795946121216, 0.886274516582489, 0.9328976273536682, 0.8921568393707275, 0.9627451300621033, 0.9542483687400818, 0.9525054693222046], [0.15533769130706787, 0.4019608199596405, 0.5326797366142273, NaN, 0.5496732592582703, 0.6989107131958008, 0.7287582159042358, 0.736710250377655, 0.7566449642181396, 0.7668846249580383, 0.7697169184684753, 0.7821350693702698, 0.789760410785675, 0.7700434923171997, 0.7860567569732666, 0.8444445133209229, 0.7936820387840271, 0.7938998341560364, 0.8159041404724121, 0.8474946022033691, 0.8276689052581787, 0.8920480608940125, 0.8697168827056885, 0.8991285562515259, 0.8808279037475586, 0.930065393447876, 0.9529411196708679, 0.9564269781112671], [0.16677561402320862, 0.34967318177223206, 0.5015250444412231, 0.4503267705440521, NaN, 0.6901960968971252, 0.6529412269592285, 0.6607843041419983, 0.7368191480636597, 0.7690632343292236, 0.7671024799346924, 0.7611110806465149, 0.7455337643623352, 0.7605664134025574, 0.8139433860778809, 0.8045751452445984, 0.8111111521720886, 0.806427001953125, 0.8238562941551208, 0.8773420453071594, 0.864052414894104, 0.8827887177467346, 0.8763617873191833, 0.9089323878288269, 0.886274516582489, 0.9679738283157349, 0.9322439432144165, 0.9346405267715454], [0.13289760053157806, 0.236601322889328, 0.27755990624427795, 0.3010893762111664, 0.30980387330055237, NaN, 0.5185185074806213, 0.5011982917785645, 0.5873637795448303, 0.6832243800163269, 0.6779956221580505, 0.7211328148841858, 0.6420479416847229, 0.6246187686920166, 0.7673202753067017, 0.6348583698272705, 0.7873638272285461, 0.7009803056716919, 0.7440088391304016, 0.8043574094772339, 0.802178680896759, 0.8533769249916077, 0.897276759147644, 0.8949890732765198, 0.8551198244094849, 0.9485838413238525, 0.9296296238899231, 0.943572998046875], [0.09607843309640884, 0.1904139369726181, 0.3122004270553589, 0.27124181389808655, 0.34705883264541626, 0.4814814031124115, NaN, 0.49716776609420776, 0.5273420214653015, 0.5732026100158691, 0.6126362085342407, 0.6322440505027771, 0.583442211151123, 0.6368191242218018, 0.6366013288497925, 0.722113311290741, 0.6642701625823975, 0.6688452959060669, 0.6799564957618713, 0.7461873292922974, 0.6816993355751038, 0.8277778029441833, 0.800000011920929, 0.845969557762146, 0.8178650140762329, 0.889760434627533, 0.9220044016838074, 0.8710241317749023], [0.12222223728895187, 0.24923749268054962, 0.31176474690437317, 0.26328974962234497, 0.3392156958580017, 0.49880173802375793, 0.502832293510437, NaN, 0.5465141534805298, 0.5873638391494751, 0.586928129196167, 0.6372548937797546, 0.5880174040794373, 0.5922658443450928, 0.6138344407081604, 0.6667755246162415, 0.6900871396064758, 0.6533769369125366, 0.6984749436378479, 0.7306101322174072, 0.7038127183914185, 0.8111111521720886, 0.7825707793235779, 0.8453159928321838, 0.8008715510368347, 0.9117648005485535, 0.9208061099052429, 0.8586056232452393], [0.0882352963089943, 0.19019603729248047, 0.2324618697166443, 0.2433551400899887, 0.26318079233169556, 0.4126361310482025, 0.4726580083370209, 0.4534858167171478, NaN, 0.5718954801559448, 0.5877995491027832, 0.5844226479530334, 0.5686275362968445, 0.5265794396400452, 0.6440086960792542, 0.6037037372589111, 0.6080610752105713, 0.6732025742530823, 0.6956428289413452, 0.7422658801078796, 0.7629631161689758, 0.7758169770240784, 0.8163398504257202, 0.7871459722518921, 0.8529411554336548, 0.8919390439987183, 0.9067538976669312, 0.9376905560493469], [0.09237473458051682, 0.18583877384662628, 0.2078431397676468, 0.23311546444892883, 0.23093684017658234, 0.3167755901813507, 0.42679741978645325, 0.4126362204551697, 0.42810454964637756, NaN, 0.5143791437149048, 0.525381326675415, 0.5034857988357544, 0.4766884744167328, 0.7058824896812439, 0.5838780403137207, 0.5912854671478271, 0.6857298016548157, 0.6505447030067444, 0.6858387589454651, 0.7537038326263428, 0.7979304194450378, 0.766884446144104, 0.8446623086929321, 0.8398692607879639, 0.9313726425170898, 0.9183006286621094, 0.9305011630058289], [0.09694989770650864, 0.1827886551618576, 0.19694988429546356, 0.2302832007408142, 0.23289760947227478, 0.3220043480396271, 0.38736382126808167, 0.4130719006061554, 0.4122004806995392, 0.4856208860874176, NaN, 0.5322440266609192, 0.5337690114974976, 0.48104575276374817, 0.6332244277000427, 0.5793028473854065, 0.5962962508201599, 0.6686274409294128, 0.6758170127868652, 0.6973856091499329, 0.729411780834198, 0.7967320084571838, 0.7627449631690979, 0.8492375612258911, 0.8387799263000488, 0.9074073433876038, 0.9143790602684021, 0.9172112941741943], [0.09847494214773178, 0.1594771146774292, 0.18649239838123322, 0.21786490082740784, 0.23888882994651794, 0.27886706590652466, 0.3677560091018677, 0.36274513602256775, 0.41557735204696655, 0.47461873292922974, 0.4677559435367584, NaN, 0.4877995252609253, 0.45762529969215393, 0.5728757977485657, 0.545969545841217, 0.5859478116035461, 0.5999999642372131, 0.6542484164237976, 0.7239652276039124, 0.6869280934333801, 0.783115565776825, 0.8023965954780579, 0.8392158150672913, 0.809259295463562, 0.876470685005188, 0.9041393995285034, 0.8884533047676086], [0.08867102116346359, 0.14553378522396088, 0.1788671314716339, 0.21023967862129211, 0.2544662356376648, 0.35795214772224426, 0.4165577292442322, 0.41198259592056274, 0.4313725233078003, 0.496514230966568, 0.46623098850250244, 0.5122004747390747, NaN, 0.5206971764564514, 0.574292004108429, 0.5703703761100769, 0.569934606552124, 0.5884531140327454, 0.6220043897628784, 0.6592592597007751, 0.6727669835090637, 0.7470586895942688, 0.7244008183479309, 0.775381326675415, 0.7694989442825317, 0.8492375016212463, 0.8700435757637024, 0.837690532207489], [0.09727669507265091, 0.21111111342906952, 0.22570808231830597, 0.22995641827583313, 0.23943357169628143, 0.375381201505661, 0.3631807863712311, 0.4077341556549072, 0.47342050075531006, 0.5233115553855896, 0.5189542770385742, 0.5423746705055237, 0.4793028235435486, NaN, 0.554684042930603, 0.5067538619041443, 0.5180827975273132, 0.6217865347862244, 0.6102396845817566, 0.6187363266944885, 0.674727737903595, 0.6623092889785767, 0.6911765336990356, 0.6956426501274109, 0.7529411911964417, 0.7442266345024109, 0.8154684901237488, 0.8671024441719055], [0.07429194450378418, 0.15239651501178741, 0.16732025146484375, 0.21394334733486176, 0.18605665862560272, 0.23267973959445953, 0.3633987307548523, 0.386165589094162, 0.35599133372306824, 0.29411762952804565, 0.36677560210227966, 0.4271242022514343, 0.42570802569389343, 0.4453159272670746, NaN, 0.5084967017173767, 0.549128532409668, 0.5625271797180176, 0.6069716811180115, 0.6589323878288269, 0.683442234992981, 0.755337655544281, 0.7252722978591919, 0.8282135725021362, 0.8185186386108398, 0.8570805788040161, 0.8982569575309753, 0.914161205291748], [0.10043573379516602, 0.09324619919061661, 0.17734204232692719, 0.15555556118488312, 0.19542483985424042, 0.3651416301727295, 0.2778867185115814, 0.33322441577911377, 0.39629629254341125, 0.4161219596862793, 0.4206971228122711, 0.45403045415878296, 0.4296295940876007, 0.4932461977005005, 0.4915032386779785, NaN, 0.5167755484580994, 0.5145969986915588, 0.6108932495117188, 0.614814817905426, 0.6034857630729675, 0.6795207858085632, 0.7614378929138184, 0.6956426501274109, 0.812853991985321, 0.8383443355560303, 0.8732026219367981, 0.8507625460624695], [0.08061002194881439, 0.14400872588157654, 0.16427013278007507, 0.20631809532642365, 0.18888889253139496, 0.21263618767261505, 0.33572983741760254, 0.30991286039352417, 0.3919389247894287, 0.4087145924568176, 0.4037036895751953, 0.41405224800109863, 0.4300653338432312, 0.48191726207733154, 0.4508714973926544, 0.48322442173957825, NaN, 0.5030500888824463, 0.5579520463943481, 0.587145984172821, 0.6163398623466492, 0.7108932733535767, 0.69248366355896, 0.7629628777503967, 0.7592591643333435, 0.8089324831962585, 0.9225490093231201, 0.9095860123634338], [0.078867107629776, 0.1339869201183319, 0.13856208324432373, 0.20610018074512482, 0.193572998046875, 0.29901957511901855, 0.33115464448928833, 0.34662309288978577, 0.32679736614227295, 0.31427016854286194, 0.33137258887290955, 0.4000000059604645, 0.41154685616493225, 0.378213495016098, 0.43747276067733765, 0.48540303111076355, 0.4969498813152313, NaN, 0.5867102146148682, 0.5897603631019592, 0.6431373357772827, 0.6633987426757812, 0.6562091708183289, 0.727450966835022, 0.801307201385498, 0.8145970106124878, 0.8328975439071655, 0.8795207142829895], [0.09063181281089783, 0.15119825303554535, 0.1522875726222992, 0.18409587442874908, 0.1761437952518463, 0.2559913098812103, 0.32004356384277344, 0.3015250861644745, 0.3043573200702667, 0.349455326795578, 0.32418304681777954, 0.34575164318084717, 0.3779956102371216, 0.389760285615921, 0.39302828907966614, 0.38910675048828125, 0.44204798340797424, 0.41328975558280945, NaN, 0.5030500888824463, 0.5071895718574524, 0.5803921818733215, 0.6381263732910156, 0.5990196466445923, 0.6921569108963013, 0.7361655831336975, 0.8058823943138123, 0.8745097517967224], [0.05359477549791336, 0.09041394293308258, 0.10588236153125763, 0.15250545740127563, 0.12265795469284058, 0.19564269483089447, 0.25381267070770264, 0.26938995718955994, 0.2577342092990875, 0.31416118144989014, 0.30261439085006714, 0.2760348320007324, 0.34074074029922485, 0.3812636435031891, 0.34106752276420593, 0.3851851522922516, 0.41285398602485657, 0.41023963689804077, 0.4969499111175537, NaN, 0.5, 0.6605664491653442, 0.6821351647377014, 0.7006535530090332, 0.7874729037284851, 0.7250545024871826, 0.841394305229187, 0.8798475861549377], [0.06666666269302368, 0.12701524794101715, 0.11198257654905319, 0.17233113944530487, 0.13594771921634674, 0.19782133400440216, 0.31830066442489624, 0.29618731141090393, 0.2370370477437973, 0.24629630148410797, 0.2705882489681244, 0.3130718469619751, 0.32723310589790344, 0.3252723217010498, 0.31655776500701904, 0.3965142071247101, 0.38366013765335083, 0.35686275362968445, 0.49281045794487, 0.5, NaN, 0.6171023845672607, 0.5759259462356567, 0.6315903663635254, 0.7851852178573608, 0.7061002254486084, 0.8313726782798767, 0.9047930240631104], [0.04923747479915619, 0.057516347616910934, 0.07342047989368439, 0.10795208811759949, 0.11721134185791016, 0.14662308990955353, 0.17222221195697784, 0.18888890743255615, 0.22418296337127686, 0.2020697295665741, 0.20326797664165497, 0.2168845385313034, 0.25294119119644165, 0.33769068121910095, 0.2446623295545578, 0.32047930359840393, 0.2891067862510681, 0.33660128712654114, 0.41960784792900085, 0.33943355083465576, 0.38289758563041687, NaN, 0.49389976263046265, 0.6332244277000427, 0.6583877801895142, 0.644444465637207, 0.8858387470245361, 0.7785401940345764], [0.07734205573797226, 0.09531590342521667, 0.11372550576925278, 0.13028322160243988, 0.1236383393406868, 0.10272331535816193, 0.20000001788139343, 0.21742920577526093, 0.1836601346731186, 0.23311546444892883, 0.23725493252277374, 0.19760346412658691, 0.27559909224510193, 0.30882349610328674, 0.27472764253616333, 0.23856207728385925, 0.30751633644104004, 0.34379082918167114, 0.361873596906662, 0.31786492466926575, 0.42407405376434326, 0.5061002373695374, NaN, 0.5604574680328369, 0.6694989204406738, 0.6150326728820801, 0.7636166214942932, 0.8605664372444153], [0.03921568766236305, 0.0631808266043663, 0.06710240244865417, 0.10087146610021591, 0.09106754511594772, 0.10501088201999664, 0.15403051674365997, 0.15468411147594452, 0.21285401284694672, 0.15533769130706787, 0.15076254308223724, 0.1607843041419983, 0.22461874783039093, 0.3043573200702667, 0.17178650200366974, 0.30435726046562195, 0.2370370626449585, 0.27254900336265564, 0.4009803831577301, 0.299346387386322, 0.36840957403182983, 0.36677560210227966, 0.4395425021648407, NaN, 0.6549019813537598, 0.613725483417511, 0.8453158736228943, 0.7675381302833557], [0.09912854433059692, 0.09716776013374329, 0.10784313827753067, 0.1191721186041832, 0.11372549086809158, 0.14488017559051514, 0.18213507533073425, 0.19912856817245483, 0.14705882966518402, 0.16013072431087494, 0.16122004389762878, 0.19074073433876038, 0.23050105571746826, 0.24705885350704193, 0.1814814805984497, 0.18714596331119537, 0.24074076116085052, 0.19869278371334076, 0.3078431189060211, 0.21252721548080444, 0.21481479704380035, 0.34161216020584106, 0.33050107955932617, 0.3450980484485626, NaN, 0.5320261716842651, 0.628322422504425, 0.6775598526000977], [0.010239651426672935, 0.05250544473528862, 0.037254903465509415, 0.06993463635444641, 0.03202614188194275, 0.051416121423244476, 0.11023964732885361, 0.08823530375957489, 0.10806101560592651, 0.06862745434045792, 0.09259260445833206, 0.12352942675352097, 0.15076249837875366, 0.2557734549045563, 0.1429194062948227, 0.16165576875209808, 0.19106753170490265, 0.1854030191898346, 0.2638344168663025, 0.27494552731513977, 0.2938997745513916, 0.35555556416511536, 0.3849673271179199, 0.38627445697784424, 0.46797382831573486, NaN, 0.6161219477653503, 0.6856208443641663], [0.03921568766236305, 0.05032680183649063, 0.04575163871049881, 0.0470588244497776, 0.06775599718093872, 0.07037036865949631, 0.07799564301967621, 0.07919389754533768, 0.09324619174003601, 0.08169934153556824, 0.0856209248304367, 0.0958605632185936, 0.1299564391374588, 0.1845315843820572, 0.10174292325973511, 0.1267973929643631, 0.07745098322629929, 0.1671023815870285, 0.19411763548851013, 0.158605694770813, 0.16862745583057404, 0.11416123062372208, 0.23638343811035156, 0.15468408167362213, 0.37167757749557495, 0.38387802243232727, NaN, 0.6224400997161865], [0.02527233213186264, 0.046623099595308304, 0.0474945567548275, 0.043572988361120224, 0.06535948812961578, 0.056427016854286194, 0.1289760321378708, 0.14139433205127716, 0.06230936944484711, 0.06949891895055771, 0.08278867602348328, 0.1115468442440033, 0.16230936348438263, 0.13289758563041687, 0.08583878725767136, 0.1492374688386917, 0.09041394293308258, 0.12047931551933289, 0.125490203499794, 0.12015251070261002, 0.09520696848630905, 0.22145968675613403, 0.13943354785442352, 0.2324618697166443, 0.32244011759757996, 0.31437912583351135, 0.37755993008613586, NaN]], "variants": ["Default", "Tuned", "Tuned + Ens."]};
|
| 331 |
-
const POINTS = [{"method":"TabFM (default)","model":"TabFM","variant":"Default","family":"Foundation Model","mean":0.9074155181},{"method":"TabPFN-3 (default)","model":"TabPFN-3","variant":"Default","family":"Foundation Model","mean":0.8142903458},{"method":"TabPFN-2.6 (default)","model":"TabPFN-2.6","variant":"Default","family":"Foundation Model","mean":0.7726619994},{"method":"TabICLv2 (default)","model":"TabICLv2","variant":"Default","family":"Foundation Model","mean":0.7603526612},{"method":"RealTabPFN-2.5 (T+E)","model":"RealTabPFN-2.5 (T+E)","variant":"","family":"Foundation Model","mean":0.7482570929},{"method":"RealMLP (T+E)","model":"RealMLP (T+E)","variant":"","family":"Neural Network","mean":0.6584321829},{"method":"TabDPT-Turbo (default)","model":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","mean":0.6124223501},{"method":"TabDPT (T+E)","model":"TabDPT (T+E)","variant":"","family":"Foundation Model","mean":0.6116194838},{"method":"TabM (T+E)","model":"TabM (T+E)","variant":"","family":"Neural Network","mean":0.5886670039},{"method":"LightGBM (T+E)","model":"LightGBM (T+E)","variant":"","family":"Tree-based","mean":0.5644719052},{"method":"CatBoost (T+E)","model":"CatBoost (T+E)","variant":"","family":"Tree-based","mean":0.558286926},{"method":"iLTM (T+E)","model":"iLTM (T+E)","variant":"","family":"Foundation Model","mean":0.5365529174},{"method":"ModernNCA (T+E)","model":"ModernNCA (T+E)","variant":"","family":"Neural Network","mean":0.5304325126},{"method":"LimiX (default)","model":"LimiX","variant":"Default","family":"Foundation Model","mean":0.5192971878},{"method":"XGBoost (T+E)","model":"XGBoost (T+E)","variant":"","family":"Tree-based","mean":0.49843056},{"method":"TabSwift (default)","model":"TabSwift","variant":"Default","family":"Foundation Model","mean":0.4878560445},{"method":"xRFM (T+E)","model":"xRFM (T+E)","variant":"","family":"Other","mean":0.4791858218},{"method":"ChimeraBoost (T+E)","model":"ChimeraBoost (T+E)","variant":"","family":"Tree-based","mean":0.4631445193},{"method":"SAP-RPT-OSS (default)","model":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","mean":0.4184216956},{"method":"TorchMLP (T+E)","model":"TorchMLP (T+E)","variant":"","family":"Neural Network","mean":0.4051803513},{"method":"EBM (T+E)","model":"EBM (T+E)","variant":"","family":"Tree-based","mean":0.3942306182},{"method":"ExtraTrees (T+E)","model":"ExtraTrees (T+E)","variant":"","family":"Tree-based","mean":0.325082707},{"method":"FastaiMLP (T+E)","model":"FastaiMLP (T+E)","variant":"","family":"Neural Network","mean":0.3237109618},{"method":"RandomForest (T+E)","model":"RandomForest (T+E)","variant":"","family":"Tree-based","mean":0.2861534742},{"method":"TabSTAR (T+E)","model":"TabSTAR (T+E)","variant":"","family":"Foundation Model","mean":0.2443798877},{"method":"PerpetualBooster (T+E)","model":"PerpetualBooster (T+E)","variant":"","family":"Tree-based","mean":0.2096828785},{"method":"KNN (T+E)","model":"KNN (T+E)","variant":"","family":"Baseline","mean":0.1491204749},{"method":"Linear (T+E)","model":"Linear (T+E)","variant":"","family":"Baseline","mean":0.1322601511}];
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 335 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 336 |
-
// already share a color, and each holds only a handful of methods.
|
| 337 |
-
const FAM_MERGED = "Baseline / Other";
|
| 338 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 339 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 340 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 341 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 342 |
-
|
| 343 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 344 |
-
const FAM_VAR = {
|
| 345 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 346 |
-
"Tree-based": "var(--fam-tree)",
|
| 347 |
-
"Neural Network": "var(--fam-nn)",
|
| 348 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 349 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 350 |
-
};
|
| 351 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 352 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 353 |
-
// that chip carries both symbols.
|
| 354 |
-
const FAM_SYMBOL = {
|
| 355 |
-
"Foundation Model": "🧠⚡",
|
| 356 |
-
"Tree-based": "🌳",
|
| 357 |
-
"Neural Network": "🧠🔁",
|
| 358 |
-
"Reference Pipeline": "📊",
|
| 359 |
-
[FAM_MERGED]: "📏 ❓",
|
| 360 |
-
};
|
| 361 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 362 |
-
const VARIANT_VAR = {
|
| 363 |
-
"Default": "var(--var-default)",
|
| 364 |
-
"Tuned": "var(--var-tuned)",
|
| 365 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 366 |
-
};
|
| 367 |
-
|
| 368 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 369 |
-
function famChipLabel(family, count) {
|
| 370 |
-
const symbol = FAM_SYMBOL[family];
|
| 371 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 372 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 373 |
-
}
|
| 374 |
-
|
| 375 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 376 |
-
const FAM_INK = {
|
| 377 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 378 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 379 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 380 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 381 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 382 |
-
};
|
| 383 |
-
|
| 384 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 385 |
-
function el(name, attrs, parent) {
|
| 386 |
-
const node = document.createElementNS(NS, name);
|
| 387 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 388 |
-
if (parent) parent.appendChild(node);
|
| 389 |
-
return node;
|
| 390 |
-
}
|
| 391 |
-
|
| 392 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 393 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 394 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 395 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 396 |
-
function fmtNum(v, decimals) {
|
| 397 |
-
if (v == null || !isFinite(v)) return "—";
|
| 398 |
-
return v.toFixed(decimals);
|
| 399 |
-
}
|
| 400 |
-
|
| 401 |
-
function fmtMetric(metric, v) {
|
| 402 |
-
if (v == null || !isFinite(v)) return "—";
|
| 403 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 404 |
-
}
|
| 405 |
-
|
| 406 |
-
function fmtTime(v) {
|
| 407 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 408 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 409 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 410 |
-
return fmtNum(v, 3) + " s";
|
| 411 |
-
}
|
| 412 |
-
|
| 413 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 414 |
-
function niceStep(raw) {
|
| 415 |
-
if (!(raw > 0)) return 1;
|
| 416 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 417 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 418 |
-
if (mag * m >= raw) return mag * m;
|
| 419 |
-
}
|
| 420 |
-
return mag * 10;
|
| 421 |
-
}
|
| 422 |
-
|
| 423 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 424 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 425 |
-
function ticks(min, max, target) {
|
| 426 |
-
const step = niceStep((max - min) / target);
|
| 427 |
-
const first = Math.ceil(min / step);
|
| 428 |
-
const out = [];
|
| 429 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 430 |
-
return out.length ? out : [min];
|
| 431 |
-
}
|
| 432 |
-
|
| 433 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 434 |
-
function makeTooltip(box) {
|
| 435 |
-
const node = box.querySelector(".tooltip");
|
| 436 |
-
return {
|
| 437 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 438 |
-
move(ev) {
|
| 439 |
-
const r = box.getBoundingClientRect();
|
| 440 |
-
let tx = ev.clientX - r.left + 14;
|
| 441 |
-
const ty = ev.clientY - r.top + 12;
|
| 442 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 443 |
-
node.style.left = tx + "px";
|
| 444 |
-
node.style.top = ty + "px";
|
| 445 |
-
},
|
| 446 |
-
hide() { node.style.display = "none"; },
|
| 447 |
-
};
|
| 448 |
-
}
|
| 449 |
-
|
| 450 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 451 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 452 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 453 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 454 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 455 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 456 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 457 |
-
function setUpPaperView(afterToggle, options) {
|
| 458 |
-
const opts = options || {};
|
| 459 |
-
const root = document.documentElement;
|
| 460 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 461 |
-
const btn = document.getElementById("btn-paper");
|
| 462 |
-
const embedded = window.parent !== window;
|
| 463 |
-
|
| 464 |
-
function setPaper(on) {
|
| 465 |
-
document.body.classList.toggle("paper", on);
|
| 466 |
-
if (on) {
|
| 467 |
-
hostTheme = root.getAttribute("data-theme");
|
| 468 |
-
root.setAttribute("data-theme", "light");
|
| 469 |
-
} else if (hostTheme) {
|
| 470 |
-
root.setAttribute("data-theme", hostTheme);
|
| 471 |
-
} else {
|
| 472 |
-
root.removeAttribute("data-theme");
|
| 473 |
-
}
|
| 474 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 475 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 476 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 477 |
-
postHeight();
|
| 478 |
-
}
|
| 479 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 480 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 481 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 482 |
-
// shareable single file) this page needs its own.
|
| 483 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 484 |
-
window.addEventListener("message", ev => {
|
| 485 |
-
const d = ev.data;
|
| 486 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 487 |
-
});
|
| 488 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 489 |
-
// key press, so its label would fall out of step with the frame.
|
| 490 |
-
if (!embedded) {
|
| 491 |
-
document.addEventListener("keydown", ev => {
|
| 492 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 493 |
-
});
|
| 494 |
-
}
|
| 495 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 496 |
-
}
|
| 497 |
-
|
| 498 |
-
// --- Figure export ---------------------------------------------------------
|
| 499 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 500 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 501 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 502 |
-
// the legend is HTML rather than part of the SVG.
|
| 503 |
-
|
| 504 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 505 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 506 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 507 |
-
// break the PNG path.
|
| 508 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 509 |
-
// once the node leaves this document.
|
| 510 |
-
function resolveVars(root, resolve) {
|
| 511 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 512 |
-
for (const attr of ["fill", "stroke"]) {
|
| 513 |
-
const value = node.getAttribute(attr);
|
| 514 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 515 |
-
}
|
| 516 |
-
}
|
| 517 |
-
}
|
| 518 |
-
|
| 519 |
-
function legendToSvg(container, resolve) {
|
| 520 |
-
const base = container.getBoundingClientRect();
|
| 521 |
-
const group = document.createElementNS(NS, "g");
|
| 522 |
-
let height = 0;
|
| 523 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 524 |
-
const box = item.getBoundingClientRect();
|
| 525 |
-
if (!box.width) continue;
|
| 526 |
-
height = Math.max(height, box.bottom - base.top);
|
| 527 |
-
let textLeft = box.left - base.left;
|
| 528 |
-
const glyph = item.querySelector("svg");
|
| 529 |
-
if (glyph) {
|
| 530 |
-
const gbox = glyph.getBoundingClientRect();
|
| 531 |
-
const wrap = el("g", {
|
| 532 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 533 |
-
}, group);
|
| 534 |
-
const glyphClone = glyph.cloneNode(true);
|
| 535 |
-
resolveVars(glyphClone, resolve);
|
| 536 |
-
wrap.appendChild(glyphClone);
|
| 537 |
-
textLeft = gbox.right - base.left + 5;
|
| 538 |
-
}
|
| 539 |
-
const label = item.textContent.trim();
|
| 540 |
-
if (!label) continue;
|
| 541 |
-
const colored = item.querySelector("[style*='color']");
|
| 542 |
-
const text = el("text", {
|
| 543 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 544 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 545 |
-
}, group);
|
| 546 |
-
text.textContent = label;
|
| 547 |
-
}
|
| 548 |
-
return { group, height: Math.ceil(height) };
|
| 549 |
-
}
|
| 550 |
-
|
| 551 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 552 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 553 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 554 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 555 |
-
const resolve = value => String(value).replace(
|
| 556 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 557 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 558 |
-
|
| 559 |
-
let chartW = 0, chartH = 0;
|
| 560 |
-
for (const part of parts) {
|
| 561 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 562 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 563 |
-
}
|
| 564 |
-
|
| 565 |
-
const out = document.createElementNS(NS, "svg");
|
| 566 |
-
out.setAttribute("xmlns", NS);
|
| 567 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 568 |
-
let top = pad;
|
| 569 |
-
const later = []; // built after the width is known
|
| 570 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 571 |
-
if (legend && legend.height) {
|
| 572 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 573 |
-
later.push(() => out.appendChild(legend.group));
|
| 574 |
-
top += legend.height + 8;
|
| 575 |
-
}
|
| 576 |
-
|
| 577 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 578 |
-
const height = top + chartH + pad;
|
| 579 |
-
out.setAttribute("width", Math.ceil(width));
|
| 580 |
-
out.setAttribute("height", Math.ceil(height));
|
| 581 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 582 |
-
for (const build of later) build();
|
| 583 |
-
|
| 584 |
-
for (const part of parts) {
|
| 585 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 586 |
-
const clone = part.svg.cloneNode(true);
|
| 587 |
-
resolveVars(clone, resolve);
|
| 588 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 589 |
-
}
|
| 590 |
-
return out;
|
| 591 |
-
}
|
| 592 |
-
|
| 593 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 594 |
-
function slugify(text) {
|
| 595 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 596 |
-
}
|
| 597 |
-
|
| 598 |
-
function downloadUrl(url, filename) {
|
| 599 |
-
const a = document.createElement("a");
|
| 600 |
-
a.href = url;
|
| 601 |
-
a.download = filename;
|
| 602 |
-
document.body.appendChild(a);
|
| 603 |
-
a.click();
|
| 604 |
-
a.remove();
|
| 605 |
-
}
|
| 606 |
-
|
| 607 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 608 |
-
function rasterize(svg, scale, done, fail) {
|
| 609 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 610 |
-
const img = new Image();
|
| 611 |
-
img.onload = () => {
|
| 612 |
-
const canvas = document.createElement("canvas");
|
| 613 |
-
canvas.width = Math.round(width * scale);
|
| 614 |
-
canvas.height = Math.round(height * scale);
|
| 615 |
-
const ctx = canvas.getContext("2d");
|
| 616 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 617 |
-
ctx.drawImage(img, 0, 0);
|
| 618 |
-
done(canvas, width, height);
|
| 619 |
-
};
|
| 620 |
-
img.onerror = fail;
|
| 621 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 622 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 623 |
-
}
|
| 624 |
-
|
| 625 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 626 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 627 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 628 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 629 |
-
// and the pixels land at 96*scale dpi.
|
| 630 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 631 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 632 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 633 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 634 |
-
rgb[j] = pixels[i];
|
| 635 |
-
rgb[j + 1] = pixels[i + 1];
|
| 636 |
-
rgb[j + 2] = pixels[i + 2];
|
| 637 |
-
}
|
| 638 |
-
const deflated = new Uint8Array(await new Response(
|
| 639 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 640 |
-
|
| 641 |
-
const encoder = new TextEncoder();
|
| 642 |
-
const chunks = [];
|
| 643 |
-
const offsets = [];
|
| 644 |
-
let cursor = 0;
|
| 645 |
-
const put = data => {
|
| 646 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 647 |
-
chunks.push(bytes);
|
| 648 |
-
cursor += bytes.length;
|
| 649 |
-
};
|
| 650 |
-
const object = (id, body, stream) => {
|
| 651 |
-
offsets[id] = cursor;
|
| 652 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 653 |
-
if (stream) {
|
| 654 |
-
put("stream\n");
|
| 655 |
-
put(stream);
|
| 656 |
-
put("\nendstream\n");
|
| 657 |
-
}
|
| 658 |
-
put("endobj\n");
|
| 659 |
-
};
|
| 660 |
-
|
| 661 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 662 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 663 |
-
put("%PDF-1.4\n");
|
| 664 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 665 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 666 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 667 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 668 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 669 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 670 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 671 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 672 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 673 |
-
|
| 674 |
-
const xref = cursor;
|
| 675 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 676 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 677 |
-
put(table);
|
| 678 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 679 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 680 |
-
}
|
| 681 |
-
|
| 682 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 683 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 684 |
-
function setUpExport(getParts, basename) {
|
| 685 |
-
const buttons = {
|
| 686 |
-
svg: document.getElementById("btn-svg"),
|
| 687 |
-
png: document.getElementById("btn-png"),
|
| 688 |
-
pdf: document.getElementById("btn-pdf"),
|
| 689 |
-
};
|
| 690 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 691 |
-
|
| 692 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 693 |
-
function complain(format) {
|
| 694 |
-
const button = buttons[format];
|
| 695 |
-
if (!button) return;
|
| 696 |
-
const label = button.textContent;
|
| 697 |
-
button.textContent = "failed";
|
| 698 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 699 |
-
}
|
| 700 |
-
|
| 701 |
-
function run(format) {
|
| 702 |
-
const svg = figure();
|
| 703 |
-
const name = basename();
|
| 704 |
-
if (format === "svg") {
|
| 705 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 706 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 707 |
-
return;
|
| 708 |
-
}
|
| 709 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 710 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 711 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 712 |
-
if (format === "png") {
|
| 713 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 714 |
-
} else {
|
| 715 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 716 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 717 |
-
.catch(() => complain("pdf"));
|
| 718 |
-
}
|
| 719 |
-
}, () => complain(format));
|
| 720 |
-
}
|
| 721 |
-
|
| 722 |
-
for (const format of Object.keys(buttons)) {
|
| 723 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 724 |
-
}
|
| 725 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 726 |
-
window.addEventListener("message", ev => {
|
| 727 |
-
const d = ev.data;
|
| 728 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 729 |
-
});
|
| 730 |
-
}
|
| 731 |
-
|
| 732 |
-
// When embedded, report the content height so the host page can size the
|
| 733 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 734 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 735 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 736 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 737 |
-
// stops re-posting once the height settles.
|
| 738 |
-
let lastPostedHeight = 0;
|
| 739 |
-
function postHeight() {
|
| 740 |
-
if (window.parent === window) return;
|
| 741 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 742 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 743 |
-
lastPostedHeight = height;
|
| 744 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 745 |
-
}
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
// POINTS is one record per matrix label (its model, variant, family and mean
|
| 749 |
-
// win rate); the matrix itself is CONFIG.matrix, row-major over CONFIG.methods.
|
| 750 |
-
const METHODS = CONFIG.methods;
|
| 751 |
-
const MATRIX = CONFIG.matrix;
|
| 752 |
-
const rowOf = new Map(METHODS.map((m, i) => [m, i]));
|
| 753 |
-
const info = new Map(POINTS.map(p => [p.method, p]));
|
| 754 |
-
const MODELS = [...new Set(POINTS.map(p => p.model))];
|
| 755 |
-
const VARIANTS = CONFIG.variants.filter(v => POINTS.some(p => p.variant === v));
|
| 756 |
-
const VARIANT_BTN = { "Tuned + Ens.": "Tuned + Ensembled" };
|
| 757 |
-
|
| 758 |
-
// Reference pipelines are AutoML systems rather than models, so a first read of
|
| 759 |
-
// the matrix should be model against model; they are one chip click away. Falls
|
| 760 |
-
// back to everything if that would leave nothing to compare.
|
| 761 |
-
const OFF_BY_DEFAULT = new Set(["Reference Pipeline"]);
|
| 762 |
-
const familyOf = new Map(POINTS.map(p => [p.model, p.family]));
|
| 763 |
-
const DEFAULT_MODELS = MODELS.filter(m => !OFF_BY_DEFAULT.has(familyOf.get(m)));
|
| 764 |
-
|
| 765 |
-
const state = {
|
| 766 |
-
models: new Set(DEFAULT_MODELS.length > 1 ? DEFAULT_MODELS : MODELS),
|
| 767 |
-
variants: new Set(VARIANTS),
|
| 768 |
-
// One entry per model by default, as the static figure shows it: 80 rows of
|
| 769 |
-
// model-variant pairs is a wall, and the comparison people want first is
|
| 770 |
-
// between models.
|
| 771 |
-
best: true,
|
| 772 |
-
order: "published",
|
| 773 |
-
// Default to fitting the panel: at reading size the matrix is taller than a
|
| 774 |
-
// screen, and the shape of the heatmap is what most readers want first.
|
| 775 |
-
zoom: "fit",
|
| 776 |
-
};
|
| 777 |
-
// Ceiling on the fitted height. Fitting is normally width-driven; this only bites
|
| 778 |
-
// on very tall selections, and it is set where the labels are still readable
|
| 779 |
-
// rather than at half a screen, which would shrink 30 rows to 8px type.
|
| 780 |
-
const FIT_H = 1040;
|
| 781 |
-
// Nominal (drawn) size of the last render; the display size is a CSS scale of it.
|
| 782 |
-
let nomW = 0, nomH = 0;
|
| 783 |
-
const svg = document.getElementById("chart");
|
| 784 |
-
const wrap = document.getElementById("wrap");
|
| 785 |
-
const tooltip = document.querySelector(".tooltip");
|
| 786 |
-
const chipsBox = document.getElementById("chips");
|
| 787 |
-
const famChips = new Map();
|
| 788 |
-
const chipByModel = new Map();
|
| 789 |
-
|
| 790 |
-
// Sized against the static figure rather than the other explorers: that one uses
|
| 791 |
-
// 16pt tick labels and 18pt axis labels on generously sized cells, and it stayed
|
| 792 |
-
// the easier of the two to read. Weight still matches the explorers' 650, so a
|
| 793 |
-
// model name looks like the same name everywhere.
|
| 794 |
-
const LABEL_SIZE = 16, LABEL_WEIGHT = 650, CAPTION_SIZE = 18, CELL = 42, VALUE_SIZE = 15;
|
| 795 |
-
// The colour key is a vertical bar to the right of the matrix, as on the static
|
| 796 |
-
// figure. It sits beside the rows rather than above them, so it is in view
|
| 797 |
-
// wherever the reader is in a tall matrix.
|
| 798 |
-
const BAR_W = 30, BAR_GAP = 32, TICK_SIZE = 15;
|
| 799 |
-
const SCALE_CAPTION = "win rate of the row over the column";
|
| 800 |
-
const SCALE_CAPTION_SHORT = "win rate";
|
| 801 |
-
|
| 802 |
-
// Purple (the column wins) through white to green (the row wins), the same
|
| 803 |
-
// diverging reading as the static figure's PRGn colormap.
|
| 804 |
-
const LOSE = [118, 42, 131], MID = [247, 247, 247], WIN = [27, 120, 55];
|
| 805 |
-
function cellColor(rate) {
|
| 806 |
-
if (rate == null || !isFinite(rate)) return "#8884";
|
| 807 |
-
const t = Math.max(0, Math.min(1, rate));
|
| 808 |
-
const [a, b, u] = t < 0.5 ? [LOSE, MID, t / 0.5] : [MID, WIN, (t - 0.5) / 0.5];
|
| 809 |
-
return "rgb(" + a.map((v, i) => Math.round(v + u * (b[i] - v))).join(",") + ")";
|
| 810 |
-
}
|
| 811 |
-
|
| 812 |
-
// Measured where possible: the labels are model names of wildly different
|
| 813 |
-
// lengths, and the margins have to clear the longest one exactly or a rotated
|
| 814 |
-
// column label runs into the caption above it. `getComputedTextLength` returns 0
|
| 815 |
-
// when the frame has not been laid out yet (it is lazily loaded, and may still be
|
| 816 |
-
// off-screen on the first paint), which would collapse both margins and push
|
| 817 |
-
// every label outside the viewBox — invisible until something forced a redraw.
|
| 818 |
-
// So fall back to an estimate, and redraw once the fonts have settled.
|
| 819 |
-
function textWidth(text, size, weight) {
|
| 820 |
-
const probe = el("text", {
|
| 821 |
-
"font-size": size || LABEL_SIZE, "font-weight": weight || LABEL_WEIGHT,
|
| 822 |
-
}, svg);
|
| 823 |
-
probe.textContent = text;
|
| 824 |
-
let width = 0;
|
| 825 |
-
try { width = probe.getComputedTextLength(); } catch (e) { width = 0; }
|
| 826 |
-
probe.remove();
|
| 827 |
-
return width > 0 ? width : text.length * (size || LABEL_SIZE) * 0.58;
|
| 828 |
-
}
|
| 829 |
-
|
| 830 |
-
// Labels always carry their variant tag — "(default)" / "(tuned + ensembled)" —
|
| 831 |
-
// including in one-per-model mode, where the tag is precisely what says which
|
| 832 |
-
// variant survived the filter. The static figure labels them the same way.
|
| 833 |
-
function labelText(label) {
|
| 834 |
-
return label;
|
| 835 |
-
}
|
| 836 |
-
|
| 837 |
-
function shown() {
|
| 838 |
-
let list = METHODS.filter(label => {
|
| 839 |
-
const p = info.get(label);
|
| 840 |
-
if (!p || !state.models.has(p.model)) return false;
|
| 841 |
-
return !p.variant || state.variants.has(p.variant);
|
| 842 |
-
});
|
| 843 |
-
if (state.best) {
|
| 844 |
-
// Best *among the variants still selected*, so the variant toggles keep
|
| 845 |
-
// meaning something in this mode.
|
| 846 |
-
const pick = new Map();
|
| 847 |
-
for (const label of list) {
|
| 848 |
-
const p = info.get(label);
|
| 849 |
-
const held = pick.get(p.model);
|
| 850 |
-
if (!held || (info.get(held).mean || 0) < (p.mean || 0)) pick.set(p.model, label);
|
| 851 |
-
}
|
| 852 |
-
list = list.filter(label => pick.get(info.get(label).model) === label);
|
| 853 |
-
}
|
| 854 |
-
if (state.order === "winrate") {
|
| 855 |
-
list.sort((a, b) => (info.get(b).mean || 0) - (info.get(a).mean || 0));
|
| 856 |
-
} else if (state.order === "name") {
|
| 857 |
-
list.sort((a, b) => labelText(a).localeCompare(labelText(b)));
|
| 858 |
-
}
|
| 859 |
-
return list;
|
| 860 |
-
}
|
| 861 |
-
|
| 862 |
-
function render() {
|
| 863 |
-
const list = shown();
|
| 864 |
-
svg.innerHTML = "";
|
| 865 |
-
if (list.length < 2) {
|
| 866 |
-
svg.setAttribute("width", 0);
|
| 867 |
-
svg.setAttribute("height", 0);
|
| 868 |
-
// Also drop the display scale, or the empty chart keeps the last figure's box.
|
| 869 |
-
svg.style.width = svg.style.height = "";
|
| 870 |
-
nomW = nomH = 0;
|
| 871 |
-
wrap.querySelector(".wr-empty") ||
|
| 872 |
-
wrap.insertAdjacentHTML("beforeend",
|
| 873 |
-
'<p class="wr-empty">Select at least two models to compare.</p>');
|
| 874 |
-
postHeight();
|
| 875 |
-
return;
|
| 876 |
-
}
|
| 877 |
-
const empty = wrap.querySelector(".wr-empty");
|
| 878 |
-
if (empty) empty.remove();
|
| 879 |
-
|
| 880 |
-
const widths = list.map(label => textWidth(labelText(label)));
|
| 881 |
-
const longest = Math.max(...widths);
|
| 882 |
-
// A label rotated -60° rises 0.866 of its length; the captions sit in the
|
| 883 |
-
// corner box rather than above the columns, where long names would cross them.
|
| 884 |
-
// Floor the header so the two corner captions always have room, even when
|
| 885 |
-
// every selected name is short.
|
| 886 |
-
const headerH = Math.max(Math.ceil(longest * 0.866) + 14, 2 * CAPTION_SIZE + 26);
|
| 887 |
-
const labelW = Math.ceil(longest) + 16;
|
| 888 |
-
const n = list.length;
|
| 889 |
-
// A -60° label anchored at (x, y) reaches (x + 0.5L, y - 0.866L): it grows up
|
| 890 |
-
// *and right*. headerH covers the rise; this covers the run, or the rightmost
|
| 891 |
-
// column's name is clipped by half its length.
|
| 892 |
-
const overhang = Math.ceil(longest * 0.5);
|
| 893 |
-
const matrixRight = labelW + n * CELL;
|
| 894 |
-
// The key occupies the band to the right of the matrix; the label overhang is
|
| 895 |
-
// above the matrix, so the two never collide and the wider of the two wins.
|
| 896 |
-
const tickW = Math.ceil(textWidth("100%", TICK_SIZE, 700));
|
| 897 |
-
const barX = matrixRight + BAR_GAP;
|
| 898 |
-
const keyRight = barX + BAR_W + 12 + tickW + 10 + CAPTION_SIZE;
|
| 899 |
-
const width = Math.max(matrixRight + overhang + 12, keyRight + 10);
|
| 900 |
-
const height = headerH + n * CELL + 12;
|
| 901 |
-
svg.setAttribute("width", width);
|
| 902 |
-
svg.setAttribute("height", height);
|
| 903 |
-
svg.setAttribute("viewBox", "0 0 " + width + " " + height);
|
| 904 |
-
|
| 905 |
-
// Captions, stacked in the corner box and bold, as on the static figure.
|
| 906 |
-
const capB = el("text", {
|
| 907 |
-
x: 4, y: headerH - 34, "font-size": CAPTION_SIZE, "font-weight": 700, fill: "var(--ink)",
|
| 908 |
-
}, svg);
|
| 909 |
-
capB.textContent = "Model B: loser →";
|
| 910 |
-
const capA = el("text", {
|
| 911 |
-
x: 4, y: headerH - 14, "font-size": CAPTION_SIZE, "font-weight": 700, fill: "var(--ink)",
|
| 912 |
-
}, svg);
|
| 913 |
-
capA.textContent = "Model A: winner ↓";
|
| 914 |
-
|
| 915 |
-
list.forEach((label, j) => {
|
| 916 |
-
const x = labelW + j * CELL + CELL / 2 + 4;
|
| 917 |
-
const text = el("text", {
|
| 918 |
-
x: x, y: headerH - 8, "font-size": LABEL_SIZE, "font-weight": LABEL_WEIGHT,
|
| 919 |
-
"text-anchor": "start", fill: FAM_INK[info.get(label).family] || "var(--ink)",
|
| 920 |
-
transform: "rotate(-60 " + x + " " + (headerH - 8) + ")", cursor: "pointer",
|
| 921 |
-
}, svg);
|
| 922 |
-
text.textContent = labelText(label);
|
| 923 |
-
text.addEventListener("click", () => toggleModel(info.get(label).model));
|
| 924 |
-
});
|
| 925 |
-
|
| 926 |
-
list.forEach((rowLabel, i) => {
|
| 927 |
-
const y = headerH + i * CELL;
|
| 928 |
-
const text = el("text", {
|
| 929 |
-
x: labelW - 12, y: y + CELL / 2 + 6, "font-size": LABEL_SIZE, "font-weight": LABEL_WEIGHT,
|
| 930 |
-
"text-anchor": "end", fill: FAM_INK[info.get(rowLabel).family] || "var(--ink)",
|
| 931 |
-
cursor: "pointer",
|
| 932 |
-
}, svg);
|
| 933 |
-
text.textContent = labelText(rowLabel);
|
| 934 |
-
text.addEventListener("click", () => toggleModel(info.get(rowLabel).model));
|
| 935 |
-
|
| 936 |
-
list.forEach((colLabel, j) => {
|
| 937 |
-
const rate = valueAt(rowLabel, colLabel);
|
| 938 |
-
const x = labelW + j * CELL;
|
| 939 |
-
const same = rowLabel === colLabel;
|
| 940 |
-
const rect = el("rect", {
|
| 941 |
-
x: x, y: y, width: CELL - 1, height: CELL - 1, rx: 2,
|
| 942 |
-
fill: same ? "#8883" : cellColor(rate),
|
| 943 |
-
}, svg);
|
| 944 |
-
if (same) return;
|
| 945 |
-
const value = el("text", {
|
| 946 |
-
x: x + (CELL - 1) / 2, y: y + CELL / 2 + 5.5, "font-size": VALUE_SIZE,
|
| 947 |
-
"font-weight": 600, "text-anchor": "middle",
|
| 948 |
-
fill: Math.abs(rate - 0.5) > 0.3 ? "#ffffff" : "#14161a", "pointer-events": "none",
|
| 949 |
-
}, svg);
|
| 950 |
-
value.textContent = rate == null || !isFinite(rate) ? "" : Math.round(rate * 100);
|
| 951 |
-
rect.addEventListener("mousemove", ev => showTip(ev, rowLabel, colLabel, rate));
|
| 952 |
-
rect.addEventListener("mouseleave", () => { tooltip.style.display = "none"; });
|
| 953 |
-
});
|
| 954 |
-
});
|
| 955 |
-
|
| 956 |
-
drawScale(barX, headerH, n * CELL - 2, tickW);
|
| 957 |
-
nomW = width;
|
| 958 |
-
nomH = height;
|
| 959 |
-
applyZoom();
|
| 960 |
-
}
|
| 961 |
-
|
| 962 |
-
// Scale the figure for display only: the width/height *attributes* stay nominal,
|
| 963 |
-
// so the export helpers keep building full-size figures, and the CSS box drives
|
| 964 |
-
// what the page shows (the viewBox does the scaling, so it stays vector-sharp).
|
| 965 |
-
function applyZoom() {
|
| 966 |
-
if (!nomW || !nomH) return;
|
| 967 |
-
let scale = Number(state.zoom);
|
| 968 |
-
if (!(scale > 0)) {
|
| 969 |
-
const availW = Math.max(240, (wrap.clientWidth || nomW) - 4);
|
| 970 |
-
scale = Math.min(1, availW / nomW, FIT_H / nomH);
|
| 971 |
-
}
|
| 972 |
-
svg.style.width = Math.round(nomW * scale) + "px";
|
| 973 |
-
svg.style.height = Math.round(nomH * scale) + "px";
|
| 974 |
-
postHeight();
|
| 975 |
-
}
|
| 976 |
-
|
| 977 |
-
// The colour key, drawn into the figure so it is there in paper view and in an
|
| 978 |
-
// exported SVG/PNG/PDF, not only beside the live chart.
|
| 979 |
-
function drawScale(x, y, barH, tickW) {
|
| 980 |
-
const id = "wr-ramp";
|
| 981 |
-
const grad = el("linearGradient", { id: id, x1: "0", x2: "0", y1: "0", y2: "1" },
|
| 982 |
-
el("defs", {}, svg));
|
| 983 |
-
// Top of the bar is the row winning outright, the bottom is the column winning.
|
| 984 |
-
for (const [offset, rate] of [[0, 1], [0.5, 0.5], [1, 0]]) {
|
| 985 |
-
el("stop", { offset: offset, "stop-color": cellColor(rate) }, grad);
|
| 986 |
-
}
|
| 987 |
-
el("rect", {
|
| 988 |
-
x: x, y: y, width: BAR_W, height: barH, rx: 7,
|
| 989 |
-
fill: "url(#" + id + ")", stroke: "var(--muted)", "stroke-width": 1,
|
| 990 |
-
}, svg);
|
| 991 |
-
for (const [frac, label] of [[0, "100%"], [0.5, "50%"], [1, "0%"]]) {
|
| 992 |
-
const ty = y + frac * barH;
|
| 993 |
-
el("line", {
|
| 994 |
-
x1: x + BAR_W, y1: ty, x2: x + BAR_W + 6, y2: ty,
|
| 995 |
-
stroke: "var(--muted)", "stroke-width": 1.5,
|
| 996 |
-
}, svg);
|
| 997 |
-
const tick = el("text", {
|
| 998 |
-
x: x + BAR_W + 11, y: ty + TICK_SIZE * 0.36, "font-size": TICK_SIZE,
|
| 999 |
-
"font-weight": 700, "text-anchor": "start", fill: "var(--ink)",
|
| 1000 |
-
}, svg);
|
| 1001 |
-
tick.textContent = label;
|
| 1002 |
-
}
|
| 1003 |
-
// The label reads down the bar. It shortens rather than growing past the bar
|
| 1004 |
-
// when only a couple of models are selected: anything above the bar would run
|
| 1005 |
-
// into the rightmost column's rotated name.
|
| 1006 |
-
const size = CAPTION_SIZE - 2;
|
| 1007 |
-
const cx = x + BAR_W + 11 + tickW + 10 + size * 0.5;
|
| 1008 |
-
const cy = y + barH / 2;
|
| 1009 |
-
const caption = el("text", {
|
| 1010 |
-
x: cx, y: cy, "font-size": size, "font-weight": 700,
|
| 1011 |
-
"text-anchor": "middle", fill: "var(--ink)",
|
| 1012 |
-
transform: "rotate(90 " + cx + " " + cy + ")",
|
| 1013 |
-
}, svg);
|
| 1014 |
-
caption.textContent =
|
| 1015 |
-
textWidth(SCALE_CAPTION, size, 700) <= barH ? SCALE_CAPTION : SCALE_CAPTION_SHORT;
|
| 1016 |
-
}
|
| 1017 |
-
|
| 1018 |
-
function valueAt(rowLabel, colLabel) {
|
| 1019 |
-
const i = rowOf.get(rowLabel), j = rowOf.get(colLabel);
|
| 1020 |
-
if (i == null || j == null) return null;
|
| 1021 |
-
const row = MATRIX[i];
|
| 1022 |
-
return row ? row[j] : null;
|
| 1023 |
-
}
|
| 1024 |
-
|
| 1025 |
-
function showTip(ev, rowLabel, colLabel, rate) {
|
| 1026 |
-
tooltip.style.display = "block";
|
| 1027 |
-
tooltip.innerHTML =
|
| 1028 |
-
'<div class="t-name">' + rowLabel + " vs " + colLabel + "</div>" +
|
| 1029 |
-
"<div>" + rowLabel + " wins " + fmtNum(rate * 100, 1) + "% of tasks</div>" +
|
| 1030 |
-
'<div class="t-var">' + colLabel + " wins " + fmtNum((1 - rate) * 100, 1) + "%</div>";
|
| 1031 |
-
const box = document.body.getBoundingClientRect();
|
| 1032 |
-
tooltip.style.left = (ev.clientX - box.left + 14) + "px";
|
| 1033 |
-
tooltip.style.top = (ev.clientY - box.top + 12) + "px";
|
| 1034 |
-
}
|
| 1035 |
-
|
| 1036 |
-
// ---------- model chips, by family ----------
|
| 1037 |
-
function familyModels(fam) {
|
| 1038 |
-
return [...new Set(POINTS.filter(p => p.family === fam).map(p => p.model))];
|
| 1039 |
-
}
|
| 1040 |
-
function meanOfModel(model) {
|
| 1041 |
-
const values = POINTS.filter(p => p.model === model && isFinite(p.mean)).map(p => p.mean);
|
| 1042 |
-
return values.length ? Math.max(...values) : 0;
|
| 1043 |
-
}
|
| 1044 |
-
function buildChips() {
|
| 1045 |
-
const head = document.createElement("div");
|
| 1046 |
-
head.className = "chips-head";
|
| 1047 |
-
head.textContent = "Models compared — click to remove, click a family to toggle the whole group";
|
| 1048 |
-
chipsBox.appendChild(head);
|
| 1049 |
-
for (const fam of FAM_ORDER) {
|
| 1050 |
-
const members = familyModels(fam);
|
| 1051 |
-
if (!members.length) continue;
|
| 1052 |
-
members.sort((a, b) => meanOfModel(b) - meanOfModel(a));
|
| 1053 |
-
const row = document.createElement("div");
|
| 1054 |
-
row.className = "chiprow";
|
| 1055 |
-
const famBtn = document.createElement("button");
|
| 1056 |
-
famBtn.className = "famchip";
|
| 1057 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1058 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1059 |
-
famBtn.title = "Toggle all " + members.length + " " + fam + " models";
|
| 1060 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1061 |
-
row.appendChild(famBtn);
|
| 1062 |
-
famChips.set(fam, famBtn);
|
| 1063 |
-
const set = document.createElement("div");
|
| 1064 |
-
set.className = "chipset";
|
| 1065 |
-
for (const model of members) {
|
| 1066 |
-
const b = document.createElement("button");
|
| 1067 |
-
b.className = "chip";
|
| 1068 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1069 |
-
b.innerHTML = '<span class="dot"></span><span></span>';
|
| 1070 |
-
b.lastChild.textContent = model;
|
| 1071 |
-
b.title = model + " — best mean win rate " + fmtNum(meanOfModel(model) * 100, 1) + "%";
|
| 1072 |
-
b.addEventListener("click", () => toggleModel(model));
|
| 1073 |
-
set.appendChild(b);
|
| 1074 |
-
chipByModel.set(model, b);
|
| 1075 |
-
}
|
| 1076 |
-
row.appendChild(set);
|
| 1077 |
-
chipsBox.appendChild(row);
|
| 1078 |
-
}
|
| 1079 |
-
}
|
| 1080 |
-
function syncChips() {
|
| 1081 |
-
for (const [model, b] of chipByModel) b.setAttribute("aria-pressed", String(state.models.has(model)));
|
| 1082 |
-
for (const [fam, b] of famChips) {
|
| 1083 |
-
b.setAttribute("aria-pressed", String(familyModels(fam).every(m => state.models.has(m))));
|
| 1084 |
-
}
|
| 1085 |
-
}
|
| 1086 |
-
function toggleModel(model) {
|
| 1087 |
-
if (state.models.has(model)) state.models.delete(model); else state.models.add(model);
|
| 1088 |
-
syncChips();
|
| 1089 |
-
render();
|
| 1090 |
-
}
|
| 1091 |
-
function toggleFamily(fam) {
|
| 1092 |
-
const members = familyModels(fam);
|
| 1093 |
-
const allOn = members.every(m => state.models.has(m));
|
| 1094 |
-
for (const m of members) { if (allOn) state.models.delete(m); else state.models.add(m); }
|
| 1095 |
-
syncChips();
|
| 1096 |
-
render();
|
| 1097 |
-
}
|
| 1098 |
-
|
| 1099 |
-
// ---------- variant toggles ----------
|
| 1100 |
-
const variantBtns = new Map();
|
| 1101 |
-
function buildVariantBtns() {
|
| 1102 |
-
const box = document.getElementById("variant-btns");
|
| 1103 |
-
for (const v of VARIANTS) {
|
| 1104 |
-
const b = document.createElement("button");
|
| 1105 |
-
b.className = "btn toggle";
|
| 1106 |
-
b.innerHTML = '<span class="swatch"></span>';
|
| 1107 |
-
// Spelled out: the matrix labels carry the long form the data uses, so the
|
| 1108 |
-
// toggle should not be the only place showing the abbreviated key.
|
| 1109 |
-
b.appendChild(document.createTextNode(VARIANT_BTN[v] || v));
|
| 1110 |
-
b.style.setProperty("--fam", VARIANT_VAR[v] || "var(--accent)");
|
| 1111 |
-
b.title = "Show or hide the " + (VARIANT_BTN[v] || v).toLowerCase() + " results";
|
| 1112 |
-
b.addEventListener("click", () => {
|
| 1113 |
-
if (state.variants.has(v)) state.variants.delete(v); else state.variants.add(v);
|
| 1114 |
-
syncVariantBtns();
|
| 1115 |
-
render();
|
| 1116 |
-
});
|
| 1117 |
-
box.appendChild(b);
|
| 1118 |
-
variantBtns.set(v, b);
|
| 1119 |
-
}
|
| 1120 |
-
}
|
| 1121 |
-
function syncVariantBtns() {
|
| 1122 |
-
for (const [v, b] of variantBtns) b.setAttribute("aria-pressed", String(state.variants.has(v)));
|
| 1123 |
-
}
|
| 1124 |
-
|
| 1125 |
-
// ---------- boot ----------
|
| 1126 |
-
if (CONFIG.title) document.getElementById("title").textContent = CONFIG.title;
|
| 1127 |
-
document.getElementById("zoom-select").addEventListener("change", ev => {
|
| 1128 |
-
state.zoom = ev.target.value;
|
| 1129 |
-
applyZoom();
|
| 1130 |
-
});
|
| 1131 |
-
window.addEventListener("resize", applyZoom);
|
| 1132 |
-
// Embedded in a lazily shown panel, the first render can measure a zero-width
|
| 1133 |
-
// panel; re-fit once it has a width. Width changes only, so the height applyZoom
|
| 1134 |
-
// itself produces cannot feed back into another fit.
|
| 1135 |
-
if (window.ResizeObserver) {
|
| 1136 |
-
let lastWidth = 0;
|
| 1137 |
-
new ResizeObserver(() => {
|
| 1138 |
-
const w = wrap.clientWidth;
|
| 1139 |
-
if (Math.abs(w - lastWidth) < 2) return;
|
| 1140 |
-
lastWidth = w;
|
| 1141 |
-
applyZoom();
|
| 1142 |
-
}).observe(wrap);
|
| 1143 |
-
}
|
| 1144 |
-
document.getElementById("order-select").addEventListener("change", ev => {
|
| 1145 |
-
state.order = ev.target.value;
|
| 1146 |
-
render();
|
| 1147 |
-
});
|
| 1148 |
-
const bestBtn = document.getElementById("btn-best");
|
| 1149 |
-
bestBtn.style.setProperty("--fam", "var(--accent)");
|
| 1150 |
-
bestBtn.addEventListener("click", () => {
|
| 1151 |
-
state.best = !state.best;
|
| 1152 |
-
bestBtn.setAttribute("aria-pressed", String(state.best));
|
| 1153 |
-
render();
|
| 1154 |
-
});
|
| 1155 |
-
bestBtn.setAttribute("aria-pressed", String(state.best));
|
| 1156 |
-
setUpPaperView(render);
|
| 1157 |
-
setUpExport(() => [{ svg: svg, dx: 0 }], () => slugify(CONFIG.title || document.title));
|
| 1158 |
-
buildVariantBtns();
|
| 1159 |
-
buildChips();
|
| 1160 |
-
syncChips();
|
| 1161 |
-
syncVariantBtns();
|
| 1162 |
-
render();
|
| 1163 |
-
// The first render may have had to estimate label widths (see textWidth); redraw
|
| 1164 |
-
// with real measurements as soon as the fonts are in.
|
| 1165 |
-
if (document.fonts && document.fonts.ready) document.fonts.ready.then(render);
|
| 1166 |
-
})();
|
| 1167 |
-
</script>
|
| 1168 |
-
</body>
|
| 1169 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/winrate_matrix.csv
DELETED
|
@@ -1,29 +0,0 @@
|
|
| 1 |
-
,TabFM (default),TabPFN-3 (default),TabPFN-2.6 (default),TabICLv2 (default),RealTabPFN-2.5 (T+E),RealMLP (T+E),TabDPT-Turbo (default),TabDPT (T+E),TabM (T+E),LightGBM (T+E),CatBoost (T+E),iLTM (T+E),ModernNCA (T+E),LimiX (default),XGBoost (T+E),TabSwift (default),xRFM (T+E),ChimeraBoost (T+E),SAP-RPT-OSS (default),TorchMLP (T+E),EBM (T+E),ExtraTrees (T+E),FastaiMLP (T+E),RandomForest (T+E),TabSTAR (T+E),PerpetualBooster (T+E),KNN (T+E),Linear (T+E)
|
| 2 |
-
TabFM (default),,0.78779954,0.83246195,0.84466255,0.8332244,0.86710244,0.90392154,0.87777776,0.9117648,0.9076254,0.9030501,0.9015251,0.9113289,0.9027234,0.9257082,0.89956427,0.91938996,0.921133,0.9093683,0.9464053,0.93333346,0.9507625,0.92265797,0.9607843,0.9008715,0.9897604,0.9607843,0.9747277
|
| 3 |
-
TabPFN-3 (default),0.21220043,,0.6313726,0.5980392,0.6503269,0.7633987,0.80958617,0.7507626,0.80980396,0.8141612,0.8172114,0.8405228,0.85446614,0.7888888,0.8476035,0.9067539,0.85599136,0.86601305,0.8488018,0.90958613,0.87298477,0.9424837,0.904684,0.93681926,0.90283227,0.9474945,0.94967324,0.95337695
|
| 4 |
-
TabPFN-2.6 (default),0.16753814,0.36862746,,0.46732023,0.49847487,0.7224402,0.6877995,0.68823534,0.76753825,0.7921569,0.80305016,0.8135076,0.82113296,0.77429193,0.83267975,0.8226579,0.83572984,0.8614379,0.8477124,0.8941176,0.88801754,0.9265796,0.8862745,0.9328976,0.89215684,0.96274513,0.95424837,0.95250547
|
| 5 |
-
TabICLv2 (default),0.15533769,0.40196082,0.53267974,,0.54967326,0.6989107,0.7287582,0.73671025,0.75664496,0.7668846,0.7697169,0.78213507,0.7897604,0.7700435,0.78605676,0.8444445,0.79368204,0.79389983,0.81590414,0.8474946,0.8276689,0.89204806,0.8697169,0.89912856,0.8808279,0.9300654,0.9529411,0.956427
|
| 6 |
-
RealTabPFN-2.5 (T+E),0.16677561,0.34967318,0.50152504,0.45032677,,0.6901961,0.6529412,0.6607843,0.73681915,0.76906323,0.7671025,0.7611111,0.74553376,0.7605664,0.8139434,0.80457515,0.81111115,0.806427,0.8238563,0.87734205,0.8640524,0.8827887,0.8763618,0.9089324,0.8862745,0.9679738,0.93224394,0.9346405
|
| 7 |
-
RealMLP (T+E),0.1328976,0.23660132,0.2775599,0.30108938,0.30980387,,0.5185185,0.5011983,0.5873638,0.6832244,0.6779956,0.7211328,0.64204794,0.62461877,0.7673203,0.63485837,0.7873638,0.7009803,0.74400884,0.8043574,0.8021787,0.8533769,0.89727676,0.8949891,0.8551198,0.94858384,0.9296296,0.943573
|
| 8 |
-
TabDPT-Turbo (default),0.09607843,0.19041394,0.31220043,0.2712418,0.34705883,0.4814814,,0.49716777,0.527342,0.5732026,0.6126362,0.63224405,0.5834422,0.6368191,0.6366013,0.7221133,0.66427016,0.6688453,0.6799565,0.7461873,0.68169934,0.8277778,0.8,0.84596956,0.817865,0.88976043,0.9220044,0.87102413
|
| 9 |
-
TabDPT (T+E),0.12222224,0.2492375,0.31176475,0.26328975,0.3392157,0.49880174,0.5028323,,0.54651415,0.58736384,0.5869281,0.6372549,0.5880174,0.59226584,0.61383444,0.6667755,0.69008714,0.65337694,0.69847494,0.73061013,0.7038127,0.81111115,0.7825708,0.845316,0.80087155,0.9117648,0.9208061,0.8586056
|
| 10 |
-
TabM (T+E),0.0882353,0.19019604,0.23246187,0.24335514,0.2631808,0.41263613,0.472658,0.45348582,,0.5718955,0.58779955,0.58442265,0.56862754,0.52657944,0.6440087,0.60370374,0.6080611,0.6732026,0.6956428,0.7422659,0.7629631,0.775817,0.81633985,0.787146,0.85294116,0.89193904,0.9067539,0.93769056
|
| 11 |
-
LightGBM (T+E),0.092374735,0.18583877,0.20784314,0.23311546,0.23093684,0.3167756,0.42679742,0.41263622,0.42810455,,0.51437914,0.5253813,0.5034858,0.47668847,0.7058825,0.58387804,0.59128547,0.6857298,0.6505447,0.68583876,0.75370383,0.7979304,0.76688445,0.8446623,0.83986926,0.93137264,0.9183006,0.93050116
|
| 12 |
-
CatBoost (T+E),0.0969499,0.18278866,0.19694988,0.2302832,0.23289761,0.32200435,0.38736382,0.4130719,0.41220048,0.4856209,,0.532244,0.533769,0.48104575,0.6332244,0.57930285,0.59629625,0.66862744,0.675817,0.6973856,0.7294118,0.796732,0.76274496,0.84923756,0.8387799,0.90740734,0.91437906,0.9172113
|
| 13 |
-
iLTM (T+E),0.09847494,0.15947711,0.1864924,0.2178649,0.23888883,0.27886707,0.367756,0.36274514,0.41557735,0.47461873,0.46775594,,0.48779953,0.4576253,0.5728758,0.54596955,0.5859478,0.59999996,0.6542484,0.7239652,0.6869281,0.78311557,0.8023966,0.8392158,0.8092593,0.8764707,0.9041394,0.8884533
|
| 14 |
-
ModernNCA (T+E),0.08867102,0.14553379,0.17886713,0.21023968,0.25446624,0.35795215,0.41655773,0.4119826,0.43137252,0.49651423,0.466231,0.5122005,,0.5206972,0.574292,0.5703704,0.5699346,0.5884531,0.6220044,0.65925926,0.672767,0.7470587,0.7244008,0.7753813,0.76949894,0.8492375,0.8700436,0.83769053
|
| 15 |
-
LimiX (default),0.097276695,0.21111111,0.22570808,0.22995642,0.23943357,0.3753812,0.3631808,0.40773416,0.4734205,0.52331156,0.5189543,0.5423747,0.47930282,,0.55468404,0.50675386,0.5180828,0.62178653,0.6102397,0.6187363,0.67472774,0.6623093,0.69117653,0.69564265,0.7529412,0.74422663,0.8154685,0.86710244
|
| 16 |
-
XGBoost (T+E),0.074291945,0.15239652,0.16732025,0.21394335,0.18605666,0.23267974,0.36339873,0.3861656,0.35599133,0.29411763,0.3667756,0.4271242,0.42570803,0.44531593,,0.5084967,0.54912853,0.5625272,0.6069717,0.6589324,0.68344223,0.75533766,0.7252723,0.8282136,0.81851864,0.8570806,0.89825696,0.9141612
|
| 17 |
-
TabSwift (default),0.100435734,0.0932462,0.17734204,0.15555556,0.19542484,0.36514163,0.27788672,0.33322442,0.3962963,0.41612196,0.42069712,0.45403045,0.4296296,0.4932462,0.49150324,,0.51677555,0.514597,0.61089325,0.6148148,0.60348576,0.6795208,0.7614379,0.69564265,0.812854,0.83834434,0.8732026,0.85076255
|
| 18 |
-
xRFM (T+E),0.08061002,0.14400873,0.16427013,0.2063181,0.18888889,0.21263619,0.33572984,0.30991286,0.39193892,0.4087146,0.4037037,0.41405225,0.43006533,0.48191726,0.4508715,0.48322442,,0.5030501,0.55795205,0.587146,0.61633986,0.7108933,0.69248366,0.7629629,0.75925916,0.8089325,0.922549,0.909586
|
| 19 |
-
ChimeraBoost (T+E),0.07886711,0.13398692,0.13856208,0.20610018,0.193573,0.29901958,0.33115464,0.3466231,0.32679737,0.31427017,0.3313726,0.4,0.41154686,0.3782135,0.43747276,0.48540303,0.49694988,,0.5867102,0.58976036,0.64313734,0.66339874,0.6562092,0.72745097,0.8013072,0.814597,0.83289754,0.8795207
|
| 20 |
-
SAP-RPT-OSS (default),0.09063181,0.15119825,0.15228757,0.18409587,0.1761438,0.2559913,0.32004356,0.3015251,0.30435732,0.34945533,0.32418305,0.34575164,0.3779956,0.3897603,0.3930283,0.38910675,0.44204798,0.41328976,,0.5030501,0.5071896,0.5803922,0.6381264,0.59901965,0.6921569,0.7361656,0.8058824,0.87450975
|
| 21 |
-
TorchMLP (T+E),0.053594775,0.09041394,0.10588236,0.15250546,0.122657955,0.1956427,0.25381267,0.26938996,0.2577342,0.31416118,0.3026144,0.27603483,0.34074074,0.38126364,0.34106752,0.38518515,0.412854,0.41023964,0.4969499,,0.5,0.66056645,0.68213516,0.70065355,0.7874729,0.7250545,0.8413943,0.8798476
|
| 22 |
-
EBM (T+E),0.06666666,0.12701525,0.11198258,0.17233114,0.13594772,0.19782133,0.31830066,0.2961873,0.23703705,0.2462963,0.27058825,0.31307185,0.3272331,0.32527232,0.31655777,0.3965142,0.38366014,0.35686275,0.49281046,0.5,,0.6171024,0.57592595,0.63159037,0.7851852,0.7061002,0.8313727,0.904793
|
| 23 |
-
ExtraTrees (T+E),0.049237475,0.057516348,0.07342048,0.10795209,0.11721134,0.14662309,0.17222221,0.1888889,0.22418296,0.20206973,0.20326798,0.21688454,0.2529412,0.33769068,0.24466233,0.3204793,0.2891068,0.3366013,0.41960785,0.33943355,0.3828976,,0.49389976,0.6332244,0.6583878,0.64444447,0.88583875,0.7785402
|
| 24 |
-
FastaiMLP (T+E),0.077342056,0.0953159,0.113725506,0.13028322,0.12363834,0.102723315,0.20000002,0.2174292,0.18366013,0.23311546,0.23725493,0.19760346,0.2755991,0.3088235,0.27472764,0.23856208,0.30751634,0.34379083,0.3618736,0.31786492,0.42407405,0.50610024,,0.56045747,0.6694989,0.6150327,0.7636166,0.86056644
|
| 25 |
-
RandomForest (T+E),0.039215688,0.06318083,0.0671024,0.100871466,0.091067545,0.10501088,0.15403052,0.15468411,0.21285401,0.15533769,0.15076254,0.1607843,0.22461875,0.30435732,0.1717865,0.30435726,0.23703706,0.272549,0.40098038,0.2993464,0.36840957,0.3667756,0.4395425,,0.654902,0.6137255,0.8453159,0.76753813
|
| 26 |
-
TabSTAR (T+E),0.099128544,0.09716776,0.10784314,0.11917212,0.11372549,0.14488018,0.18213508,0.19912857,0.14705883,0.16013072,0.16122004,0.19074073,0.23050106,0.24705885,0.18148148,0.18714596,0.24074076,0.19869278,0.30784312,0.21252722,0.2148148,0.34161216,0.33050108,0.34509805,,0.5320262,0.6283224,0.67755985
|
| 27 |
-
PerpetualBooster (T+E),0.010239651,0.052505445,0.037254903,0.06993464,0.032026142,0.05141612,0.11023965,0.088235304,0.108061016,0.068627454,0.092592604,0.12352943,0.1507625,0.25577345,0.1429194,0.16165577,0.19106753,0.18540302,0.26383442,0.27494553,0.29389977,0.35555556,0.38496733,0.38627446,0.46797383,,0.61612195,0.68562084
|
| 28 |
-
KNN (T+E),0.039215688,0.0503268,0.04575164,0.047058824,0.067756,0.07037037,0.07799564,0.0791939,0.09324619,0.08169934,0.085620925,0.09586056,0.12995644,0.18453158,0.10174292,0.1267974,0.07745098,0.16710238,0.19411764,0.1586057,0.16862746,0.11416123,0.23638344,0.15468408,0.37167758,0.38387802,,0.6224401
|
| 29 |
-
Linear (T+E),0.025272332,0.0466231,0.047494557,0.04357299,0.06535949,0.056427017,0.12897603,0.14139433,0.06230937,0.06949892,0.082788676,0.111546844,0.16230936,0.13289759,0.08583879,0.14923747,0.09041394,0.120479316,0.1254902,0.12015251,0.09520697,0.22145969,0.13943355,0.23246187,0.32244012,0.31437913,0.37755993,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_all/winrate_matrix.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:ffcfbb5fff8f010ee7a55f2db2cdf1f98513fa37d75457cbeaa2755b113cc4b5
|
| 3 |
-
size 684630
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/leaderboard_overview_explorer.html
DELETED
|
@@ -1,1411 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena leaderboard explorer — no imputation | All Tasks | Medium</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Chart: a fixed y-axis pane beside a horizontally scrolling plot pane, so
|
| 269 |
-
the axis stays readable however far right the reader scrolls. */
|
| 270 |
-
.lb-chartwrap { position: relative; display: flex; align-items: flex-start; }
|
| 271 |
-
.lb-axis { flex: none; }
|
| 272 |
-
.lb-scroll {
|
| 273 |
-
flex: 1 1 auto; min-width: 0; overflow-x: auto; overflow-y: hidden;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.lb-scroll::-webkit-scrollbar { height: 10px; }
|
| 277 |
-
.lb-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
.rangepick input[type=range] { width: 96px; accent-color: var(--accent); cursor: pointer; }
|
| 282 |
-
.rangeval { font-variant-numeric: tabular-nums; font-weight: 500; min-width: 3.4em; }
|
| 283 |
-
.lb-empty { padding: 40px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 284 |
-
/* Puts the family key on its own line of the legend strip. */
|
| 285 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 286 |
-
/* Family blocks pack side by side rather than stacking: below a full-width
|
| 287 |
-
chart, one row per family leaves the small ones (Other, Baseline) each
|
| 288 |
-
wasting a line. The wide families still claim a row of their own. */
|
| 289 |
-
.chips { margin-top: 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 290 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 291 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 292 |
-
</style>
|
| 293 |
-
</head>
|
| 294 |
-
<body>
|
| 295 |
-
<div class="viewbar">
|
| 296 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 297 |
-
</div>
|
| 298 |
-
<p class="explorer-title" id="title"></p>
|
| 299 |
-
<!-- One control row above everything it scopes (axis, sorting, variants, selection). -->
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick">Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<label class="metricpick">Sort
|
| 305 |
-
<select id="sort-select"></select>
|
| 306 |
-
</label>
|
| 307 |
-
<label class="metricpick rangepick" title="Raise the axis floor to spread out the top of the field">Zoom
|
| 308 |
-
<input type="range" id="ymin-range" aria-label="Y-axis minimum">
|
| 309 |
-
<span class="rangeval" id="ymin-val"></span>
|
| 310 |
-
</label>
|
| 311 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 312 |
-
<div class="btnrow">
|
| 313 |
-
<button class="btn" id="btn-all">All methods</button>
|
| 314 |
-
<button class="btn" id="btn-top">Top 15</button>
|
| 315 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 316 |
-
</div>
|
| 317 |
-
<span class="hint">Click a column or chip to remove a method · hover for exact values</span>
|
| 318 |
-
</div>
|
| 319 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 320 |
-
<span class="hint">Export figure</span>
|
| 321 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 322 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 323 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 324 |
-
</div>
|
| 325 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 326 |
-
<div class="lb-chartwrap" id="chartwrap">
|
| 327 |
-
<svg id="axis" class="lb-axis" role="presentation"></svg>
|
| 328 |
-
<div class="lb-scroll" id="scroller">
|
| 329 |
-
<svg id="chart" role="img" aria-label="Leaderboard overview"></svg>
|
| 330 |
-
</div>
|
| 331 |
-
<div class="tooltip"></div>
|
| 332 |
-
</div>
|
| 333 |
-
<div class="chips" id="chips"></div>
|
| 334 |
-
<details class="datatable">
|
| 335 |
-
<summary>Data table</summary>
|
| 336 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 337 |
-
</details>
|
| 338 |
-
|
| 339 |
-
<script>
|
| 340 |
-
(function () {
|
| 341 |
-
"use strict";
|
| 342 |
-
const CONFIG = {"title": null, "metrics": [{"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": "", "ci": {"lo": "elo_lo", "hi": "elo_hi"}}, {"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "score", "label": "Score", "axisLabel": "Score \u2014 higher is better", "lowerBetter": false, "fromZero": true, "decimals": 3, "suffix": ""}, {"key": "rank", "label": "Average rank", "axisLabel": "Average rank \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 2, "suffix": ""}, {"key": "hrank", "label": "Harmonic rank", "axisLabel": "Harmonic rank \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 2, "suffix": ""}], "rankMetric": "elo"};
|
| 343 |
-
const POINTS = [{"method":"TabFM","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/google-research\/tabfm","reference":false,"elo":1986.0,"imp":2.683,"score":0.867,"rank":4.41,"hrank":1.69,"elo_hi":2292.0,"elo_lo":1841.0,"imputed_pct":0.0,"imputed":false},{"method":"AutoGluon 1.5 (extreme, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":true,"elo":1899.0,"imp":4.858,"score":0.71,"rank":6.33,"hrank":2.98,"elo_hi":1984.0,"elo_lo":1850.0,"imputed_pct":0.0,"imputed":false},{"method":"TabPFN-3","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2605.13986","reference":false,"elo":1794.0,"imp":5.878,"score":0.659,"rank":9.55,"hrank":3.26,"elo_hi":2008.0,"elo_lo":1659.0,"imputed_pct":0.0,"imputed":false},{"method":"AutoGluon 1.4 (best, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":true,"elo":1775.0,"imp":6.048,"score":0.579,"rank":10.23,"hrank":4.46,"elo_hi":1858.0,"elo_lo":1724.0,"imputed_pct":0.0,"imputed":false},{"method":"TabPFN-2.6","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1722.0,"imp":7.846,"score":0.504,"rank":12.39,"hrank":8.78,"elo_hi":1852.0,"elo_lo":1647.0,"imputed_pct":0.0,"imputed":false},{"method":"TabICLv2","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2602.11139","reference":false,"elo":1697.0,"imp":6.851,"score":0.541,"rank":13.53,"hrank":4.41,"elo_hi":1883.0,"elo_lo":1587.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1646.0,"imp":8.576,"score":0.446,"rank":16.07,"hrank":8.48,"elo_hi":1788.0,"elo_lo":1542.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1625.0,"imp":8.917,"score":0.412,"rank":17.17,"hrank":11.86,"elo_hi":1717.0,"elo_lo":1533.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1615.0,"imp":9.07,"score":0.397,"rank":17.73,"hrank":12.25,"elo_hi":1719.0,"elo_lo":1510.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1611.0,"imp":8.932,"score":0.379,"rank":17.97,"hrank":9.32,"elo_hi":1696.0,"elo_lo":1548.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1600.0,"imp":9.218,"score":0.403,"rank":18.55,"hrank":10.47,"elo_hi":1726.0,"elo_lo":1501.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1596.0,"imp":9.14,"score":0.372,"rank":18.8,"hrank":9.43,"elo_hi":1694.0,"elo_lo":1530.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1589.0,"imp":10.466,"score":0.327,"rank":19.19,"hrank":13.5,"elo_hi":1657.0,"elo_lo":1538.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1576.0,"imp":9.095,"score":0.378,"rank":19.95,"hrank":9.61,"elo_hi":1679.0,"elo_lo":1475.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1558.0,"imp":10.221,"score":0.322,"rank":20.99,"hrank":15.67,"elo_hi":1628.0,"elo_lo":1506.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1548.0,"imp":10.546,"score":0.295,"rank":21.61,"hrank":14.86,"elo_hi":1629.0,"elo_lo":1493.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1544.0,"imp":10.254,"score":0.292,"rank":21.87,"hrank":13.14,"elo_hi":1690.0,"elo_lo":1457.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1533.0,"imp":10.104,"score":0.301,"rank":22.52,"hrank":14.08,"elo_hi":1638.0,"elo_lo":1444.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1530.0,"imp":10.077,"score":0.324,"rank":22.69,"hrank":14.72,"elo_hi":1666.0,"elo_lo":1451.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","url":"https:\/\/openreview.net\/pdf?id=Y00pwFyrHR","reference":false,"elo":1526.0,"imp":10.809,"score":0.355,"rank":22.94,"hrank":10.98,"elo_hi":1682.0,"elo_lo":1387.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1522.0,"imp":10.287,"score":0.319,"rank":23.22,"hrank":6.34,"elo_hi":1656.0,"elo_lo":1403.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1517.0,"imp":11.684,"score":0.314,"rank":23.53,"hrank":13.31,"elo_hi":1633.0,"elo_lo":1396.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1506.0,"imp":11.603,"score":0.216,"rank":24.2,"hrank":18.44,"elo_hi":1582.0,"elo_lo":1452.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1501.0,"imp":11.102,"score":0.234,"rank":24.53,"hrank":20.07,"elo_hi":1565.0,"elo_lo":1446.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1481.0,"imp":11.089,"score":0.234,"rank":25.86,"hrank":15.63,"elo_hi":1611.0,"elo_lo":1405.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1472.0,"imp":11.215,"score":0.217,"rank":26.42,"hrank":20.56,"elo_hi":1564.0,"elo_lo":1391.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1470.0,"imp":12.146,"score":0.266,"rank":26.58,"hrank":15.47,"elo_hi":1576.0,"elo_lo":1355.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Tuned + Ens.","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1423.0,"imp":12.482,"score":0.224,"rank":29.66,"hrank":21.18,"elo_hi":1529.0,"elo_lo":1309.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1423.0,"imp":12.112,"score":0.155,"rank":29.69,"hrank":18.8,"elo_hi":1520.0,"elo_lo":1360.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Default","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1418.0,"imp":13.176,"score":0.203,"rank":30.0,"hrank":19.33,"elo_hi":1530.0,"elo_lo":1299.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1404.0,"imp":12.662,"score":0.221,"rank":30.97,"hrank":12.53,"elo_hi":1527.0,"elo_lo":1286.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1377.0,"imp":12.45,"score":0.128,"rank":32.79,"hrank":26.34,"elo_hi":1448.0,"elo_lo":1316.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Tuned","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1373.0,"imp":13.982,"score":0.159,"rank":33.01,"hrank":27.27,"elo_hi":1465.0,"elo_lo":1272.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1372.0,"imp":12.907,"score":0.137,"rank":33.13,"hrank":21.73,"elo_hi":1461.0,"elo_lo":1269.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSwift","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/LAMDA-Tabular\/TabSwift","reference":false,"elo":1344.0,"imp":13.337,"score":0.157,"rank":34.99,"hrank":24.16,"elo_hi":1462.0,"elo_lo":1242.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1332.0,"imp":15.311,"score":0.174,"rank":35.84,"hrank":16.46,"elo_hi":1451.0,"elo_lo":1198.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1326.0,"imp":13.982,"score":0.096,"rank":36.23,"hrank":29.85,"elo_hi":1436.0,"elo_lo":1238.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1326.0,"imp":15.595,"score":0.134,"rank":36.24,"hrank":27.26,"elo_hi":1439.0,"elo_lo":1198.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1298.0,"imp":14.33,"score":0.073,"rank":38.1,"hrank":33.85,"elo_hi":1370.0,"elo_lo":1219.0,"imputed_pct":0.0,"imputed":false},{"method":"LimiX","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2509.03505","reference":false,"elo":1279.0,"imp":16.418,"score":0.17,"rank":39.33,"hrank":9.92,"elo_hi":1419.0,"elo_lo":1119.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1272.0,"imp":14.114,"score":0.049,"rank":39.78,"hrank":35.01,"elo_hi":1342.0,"elo_lo":1197.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1272.0,"imp":15.091,"score":0.034,"rank":39.84,"hrank":36.58,"elo_hi":1345.0,"elo_lo":1204.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1265.0,"imp":16.441,"score":0.089,"rank":40.24,"hrank":32.83,"elo_hi":1369.0,"elo_lo":1132.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Default","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1258.0,"imp":14.82,"score":0.028,"rank":40.73,"hrank":38.32,"elo_hi":1309.0,"elo_lo":1194.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1244.0,"imp":15.1,"score":0.03,"rank":41.64,"hrank":35.97,"elo_hi":1329.0,"elo_lo":1159.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Default","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1221.0,"imp":17.87,"score":0.057,"rank":43.14,"hrank":37.72,"elo_hi":1309.0,"elo_lo":1085.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1217.0,"imp":15.304,"score":0.022,"rank":43.4,"hrank":40.85,"elo_hi":1296.0,"elo_lo":1128.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1214.0,"imp":15.744,"score":0.031,"rank":43.54,"hrank":37.85,"elo_hi":1300.0,"elo_lo":1130.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1201.0,"imp":17.192,"score":0.06,"rank":44.39,"hrank":36.49,"elo_hi":1311.0,"elo_lo":1063.0,"imputed_pct":0.0,"imputed":false},{"method":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2506.10707","reference":false,"elo":1201.0,"imp":16.933,"score":0.028,"rank":44.41,"hrank":39.08,"elo_hi":1283.0,"elo_lo":1106.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1179.0,"imp":18.488,"score":0.033,"rank":45.73,"hrank":41.33,"elo_hi":1263.0,"elo_lo":1068.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1174.0,"imp":16.303,"score":0.008,"rank":46.07,"hrank":43.76,"elo_hi":1244.0,"elo_lo":1091.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1126.0,"imp":18.145,"score":0.001,"rank":48.9,"hrank":47.16,"elo_hi":1185.0,"elo_lo":1054.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":1110.0,"imp":21.633,"score":0.019,"rank":49.83,"hrank":43.02,"elo_hi":1211.0,"elo_lo":985.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1101.0,"imp":19.294,"score":0.015,"rank":50.32,"hrank":45.23,"elo_hi":1192.0,"elo_lo":996.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Tuned","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":1060.0,"imp":22.747,"score":0.004,"rank":52.57,"hrank":48.1,"elo_hi":1152.0,"elo_lo":944.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Default","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1046.0,"imp":25.98,"score":0.018,"rank":53.27,"hrank":47.13,"elo_hi":1193.0,"elo_lo":862.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1031.0,"imp":22.864,"score":0.018,"rank":54.04,"hrank":48.76,"elo_hi":1167.0,"elo_lo":860.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1000.0,"imp":21.197,"score":0.0,"rank":55.55,"hrank":54.46,"elo_hi":1051.0,"elo_lo":908.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":989.0,"imp":24.353,"score":0.005,"rank":56.06,"hrank":49.75,"elo_hi":1083.0,"elo_lo":861.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":988.0,"imp":25.807,"score":0.0,"rank":56.13,"hrank":54.65,"elo_hi":1044.0,"elo_lo":898.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":987.0,"imp":25.781,"score":0.0,"rank":56.18,"hrank":54.79,"elo_hi":1048.0,"elo_lo":901.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":976.0,"imp":22.789,"score":0.0,"rank":56.64,"hrank":54.71,"elo_hi":1070.0,"elo_lo":855.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":935.0,"imp":32.872,"score":0.004,"rank":58.45,"hrank":53.87,"elo_hi":1088.0,"elo_lo":709.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Default","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":901.0,"imp":29.424,"score":0.0,"rank":59.81,"hrank":57.82,"elo_hi":1007.0,"elo_lo":748.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":892.0,"imp":33.73,"score":0.002,"rank":60.16,"hrank":56.48,"elo_hi":1046.0,"elo_lo":647.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":848.0,"imp":30.685,"score":0.0,"rank":61.7,"hrank":61.11,"elo_hi":898.0,"elo_lo":760.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":814.0,"imp":29.973,"score":0.0,"rank":62.78,"hrank":62.5,"elo_hi":867.0,"elo_lo":708.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":797.0,"imp":35.794,"score":0.0,"rank":63.27,"hrank":61.49,"elo_hi":934.0,"elo_lo":553.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":593.0,"imp":43.501,"score":0.0,"rank":67.65,"hrank":67.52,"elo_hi":676.0,"elo_lo":447.0,"imputed_pct":0.0,"imputed":false}];
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 347 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 348 |
-
// already share a color, and each holds only a handful of methods.
|
| 349 |
-
const FAM_MERGED = "Baseline / Other";
|
| 350 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 351 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 352 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 353 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 354 |
-
|
| 355 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 356 |
-
const FAM_VAR = {
|
| 357 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 358 |
-
"Tree-based": "var(--fam-tree)",
|
| 359 |
-
"Neural Network": "var(--fam-nn)",
|
| 360 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 361 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 362 |
-
};
|
| 363 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 364 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 365 |
-
// that chip carries both symbols.
|
| 366 |
-
const FAM_SYMBOL = {
|
| 367 |
-
"Foundation Model": "🧠⚡",
|
| 368 |
-
"Tree-based": "🌳",
|
| 369 |
-
"Neural Network": "🧠🔁",
|
| 370 |
-
"Reference Pipeline": "📊",
|
| 371 |
-
[FAM_MERGED]: "📏 ❓",
|
| 372 |
-
};
|
| 373 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 374 |
-
const VARIANT_VAR = {
|
| 375 |
-
"Default": "var(--var-default)",
|
| 376 |
-
"Tuned": "var(--var-tuned)",
|
| 377 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 378 |
-
};
|
| 379 |
-
|
| 380 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 381 |
-
function famChipLabel(family, count) {
|
| 382 |
-
const symbol = FAM_SYMBOL[family];
|
| 383 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 384 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 385 |
-
}
|
| 386 |
-
|
| 387 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 388 |
-
const FAM_INK = {
|
| 389 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 390 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 391 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 392 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 393 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 394 |
-
};
|
| 395 |
-
|
| 396 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 397 |
-
function el(name, attrs, parent) {
|
| 398 |
-
const node = document.createElementNS(NS, name);
|
| 399 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 400 |
-
if (parent) parent.appendChild(node);
|
| 401 |
-
return node;
|
| 402 |
-
}
|
| 403 |
-
|
| 404 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 405 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 406 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 407 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 408 |
-
function fmtNum(v, decimals) {
|
| 409 |
-
if (v == null || !isFinite(v)) return "—";
|
| 410 |
-
return v.toFixed(decimals);
|
| 411 |
-
}
|
| 412 |
-
|
| 413 |
-
function fmtMetric(metric, v) {
|
| 414 |
-
if (v == null || !isFinite(v)) return "—";
|
| 415 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 416 |
-
}
|
| 417 |
-
|
| 418 |
-
function fmtTime(v) {
|
| 419 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 420 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 421 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 422 |
-
return fmtNum(v, 3) + " s";
|
| 423 |
-
}
|
| 424 |
-
|
| 425 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 426 |
-
function niceStep(raw) {
|
| 427 |
-
if (!(raw > 0)) return 1;
|
| 428 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 429 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 430 |
-
if (mag * m >= raw) return mag * m;
|
| 431 |
-
}
|
| 432 |
-
return mag * 10;
|
| 433 |
-
}
|
| 434 |
-
|
| 435 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 436 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 437 |
-
function ticks(min, max, target) {
|
| 438 |
-
const step = niceStep((max - min) / target);
|
| 439 |
-
const first = Math.ceil(min / step);
|
| 440 |
-
const out = [];
|
| 441 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 442 |
-
return out.length ? out : [min];
|
| 443 |
-
}
|
| 444 |
-
|
| 445 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 446 |
-
function makeTooltip(box) {
|
| 447 |
-
const node = box.querySelector(".tooltip");
|
| 448 |
-
return {
|
| 449 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 450 |
-
move(ev) {
|
| 451 |
-
const r = box.getBoundingClientRect();
|
| 452 |
-
let tx = ev.clientX - r.left + 14;
|
| 453 |
-
const ty = ev.clientY - r.top + 12;
|
| 454 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 455 |
-
node.style.left = tx + "px";
|
| 456 |
-
node.style.top = ty + "px";
|
| 457 |
-
},
|
| 458 |
-
hide() { node.style.display = "none"; },
|
| 459 |
-
};
|
| 460 |
-
}
|
| 461 |
-
|
| 462 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 463 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 464 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 465 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 466 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 467 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 468 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 469 |
-
function setUpPaperView(afterToggle, options) {
|
| 470 |
-
const opts = options || {};
|
| 471 |
-
const root = document.documentElement;
|
| 472 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 473 |
-
const btn = document.getElementById("btn-paper");
|
| 474 |
-
const embedded = window.parent !== window;
|
| 475 |
-
|
| 476 |
-
function setPaper(on) {
|
| 477 |
-
document.body.classList.toggle("paper", on);
|
| 478 |
-
if (on) {
|
| 479 |
-
hostTheme = root.getAttribute("data-theme");
|
| 480 |
-
root.setAttribute("data-theme", "light");
|
| 481 |
-
} else if (hostTheme) {
|
| 482 |
-
root.setAttribute("data-theme", hostTheme);
|
| 483 |
-
} else {
|
| 484 |
-
root.removeAttribute("data-theme");
|
| 485 |
-
}
|
| 486 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 487 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 488 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 489 |
-
postHeight();
|
| 490 |
-
}
|
| 491 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 492 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 493 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 494 |
-
// shareable single file) this page needs its own.
|
| 495 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 496 |
-
window.addEventListener("message", ev => {
|
| 497 |
-
const d = ev.data;
|
| 498 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 499 |
-
});
|
| 500 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 501 |
-
// key press, so its label would fall out of step with the frame.
|
| 502 |
-
if (!embedded) {
|
| 503 |
-
document.addEventListener("keydown", ev => {
|
| 504 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 505 |
-
});
|
| 506 |
-
}
|
| 507 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 508 |
-
}
|
| 509 |
-
|
| 510 |
-
// --- Figure export ---------------------------------------------------------
|
| 511 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 512 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 513 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 514 |
-
// the legend is HTML rather than part of the SVG.
|
| 515 |
-
|
| 516 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 517 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 518 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 519 |
-
// break the PNG path.
|
| 520 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 521 |
-
// once the node leaves this document.
|
| 522 |
-
function resolveVars(root, resolve) {
|
| 523 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 524 |
-
for (const attr of ["fill", "stroke"]) {
|
| 525 |
-
const value = node.getAttribute(attr);
|
| 526 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 527 |
-
}
|
| 528 |
-
}
|
| 529 |
-
}
|
| 530 |
-
|
| 531 |
-
function legendToSvg(container, resolve) {
|
| 532 |
-
const base = container.getBoundingClientRect();
|
| 533 |
-
const group = document.createElementNS(NS, "g");
|
| 534 |
-
let height = 0;
|
| 535 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 536 |
-
const box = item.getBoundingClientRect();
|
| 537 |
-
if (!box.width) continue;
|
| 538 |
-
height = Math.max(height, box.bottom - base.top);
|
| 539 |
-
let textLeft = box.left - base.left;
|
| 540 |
-
const glyph = item.querySelector("svg");
|
| 541 |
-
if (glyph) {
|
| 542 |
-
const gbox = glyph.getBoundingClientRect();
|
| 543 |
-
const wrap = el("g", {
|
| 544 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 545 |
-
}, group);
|
| 546 |
-
const glyphClone = glyph.cloneNode(true);
|
| 547 |
-
resolveVars(glyphClone, resolve);
|
| 548 |
-
wrap.appendChild(glyphClone);
|
| 549 |
-
textLeft = gbox.right - base.left + 5;
|
| 550 |
-
}
|
| 551 |
-
const label = item.textContent.trim();
|
| 552 |
-
if (!label) continue;
|
| 553 |
-
const colored = item.querySelector("[style*='color']");
|
| 554 |
-
const text = el("text", {
|
| 555 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 556 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 557 |
-
}, group);
|
| 558 |
-
text.textContent = label;
|
| 559 |
-
}
|
| 560 |
-
return { group, height: Math.ceil(height) };
|
| 561 |
-
}
|
| 562 |
-
|
| 563 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 564 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 565 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 566 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 567 |
-
const resolve = value => String(value).replace(
|
| 568 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 569 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 570 |
-
|
| 571 |
-
let chartW = 0, chartH = 0;
|
| 572 |
-
for (const part of parts) {
|
| 573 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 574 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 575 |
-
}
|
| 576 |
-
|
| 577 |
-
const out = document.createElementNS(NS, "svg");
|
| 578 |
-
out.setAttribute("xmlns", NS);
|
| 579 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 580 |
-
let top = pad;
|
| 581 |
-
const later = []; // built after the width is known
|
| 582 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 583 |
-
if (legend && legend.height) {
|
| 584 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 585 |
-
later.push(() => out.appendChild(legend.group));
|
| 586 |
-
top += legend.height + 8;
|
| 587 |
-
}
|
| 588 |
-
|
| 589 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 590 |
-
const height = top + chartH + pad;
|
| 591 |
-
out.setAttribute("width", Math.ceil(width));
|
| 592 |
-
out.setAttribute("height", Math.ceil(height));
|
| 593 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 594 |
-
for (const build of later) build();
|
| 595 |
-
|
| 596 |
-
for (const part of parts) {
|
| 597 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 598 |
-
const clone = part.svg.cloneNode(true);
|
| 599 |
-
resolveVars(clone, resolve);
|
| 600 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 601 |
-
}
|
| 602 |
-
return out;
|
| 603 |
-
}
|
| 604 |
-
|
| 605 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 606 |
-
function slugify(text) {
|
| 607 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 608 |
-
}
|
| 609 |
-
|
| 610 |
-
function downloadUrl(url, filename) {
|
| 611 |
-
const a = document.createElement("a");
|
| 612 |
-
a.href = url;
|
| 613 |
-
a.download = filename;
|
| 614 |
-
document.body.appendChild(a);
|
| 615 |
-
a.click();
|
| 616 |
-
a.remove();
|
| 617 |
-
}
|
| 618 |
-
|
| 619 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 620 |
-
function rasterize(svg, scale, done, fail) {
|
| 621 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 622 |
-
const img = new Image();
|
| 623 |
-
img.onload = () => {
|
| 624 |
-
const canvas = document.createElement("canvas");
|
| 625 |
-
canvas.width = Math.round(width * scale);
|
| 626 |
-
canvas.height = Math.round(height * scale);
|
| 627 |
-
const ctx = canvas.getContext("2d");
|
| 628 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 629 |
-
ctx.drawImage(img, 0, 0);
|
| 630 |
-
done(canvas, width, height);
|
| 631 |
-
};
|
| 632 |
-
img.onerror = fail;
|
| 633 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 634 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 635 |
-
}
|
| 636 |
-
|
| 637 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 638 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 639 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 640 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 641 |
-
// and the pixels land at 96*scale dpi.
|
| 642 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 643 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 644 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 645 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 646 |
-
rgb[j] = pixels[i];
|
| 647 |
-
rgb[j + 1] = pixels[i + 1];
|
| 648 |
-
rgb[j + 2] = pixels[i + 2];
|
| 649 |
-
}
|
| 650 |
-
const deflated = new Uint8Array(await new Response(
|
| 651 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 652 |
-
|
| 653 |
-
const encoder = new TextEncoder();
|
| 654 |
-
const chunks = [];
|
| 655 |
-
const offsets = [];
|
| 656 |
-
let cursor = 0;
|
| 657 |
-
const put = data => {
|
| 658 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 659 |
-
chunks.push(bytes);
|
| 660 |
-
cursor += bytes.length;
|
| 661 |
-
};
|
| 662 |
-
const object = (id, body, stream) => {
|
| 663 |
-
offsets[id] = cursor;
|
| 664 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 665 |
-
if (stream) {
|
| 666 |
-
put("stream\n");
|
| 667 |
-
put(stream);
|
| 668 |
-
put("\nendstream\n");
|
| 669 |
-
}
|
| 670 |
-
put("endobj\n");
|
| 671 |
-
};
|
| 672 |
-
|
| 673 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 674 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 675 |
-
put("%PDF-1.4\n");
|
| 676 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 677 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 678 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 679 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 680 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 681 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 682 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 683 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 684 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 685 |
-
|
| 686 |
-
const xref = cursor;
|
| 687 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 688 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 689 |
-
put(table);
|
| 690 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 691 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 692 |
-
}
|
| 693 |
-
|
| 694 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 695 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 696 |
-
function setUpExport(getParts, basename) {
|
| 697 |
-
const buttons = {
|
| 698 |
-
svg: document.getElementById("btn-svg"),
|
| 699 |
-
png: document.getElementById("btn-png"),
|
| 700 |
-
pdf: document.getElementById("btn-pdf"),
|
| 701 |
-
};
|
| 702 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 703 |
-
|
| 704 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 705 |
-
function complain(format) {
|
| 706 |
-
const button = buttons[format];
|
| 707 |
-
if (!button) return;
|
| 708 |
-
const label = button.textContent;
|
| 709 |
-
button.textContent = "failed";
|
| 710 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 711 |
-
}
|
| 712 |
-
|
| 713 |
-
function run(format) {
|
| 714 |
-
const svg = figure();
|
| 715 |
-
const name = basename();
|
| 716 |
-
if (format === "svg") {
|
| 717 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 718 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 719 |
-
return;
|
| 720 |
-
}
|
| 721 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 722 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 723 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 724 |
-
if (format === "png") {
|
| 725 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 726 |
-
} else {
|
| 727 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 728 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 729 |
-
.catch(() => complain("pdf"));
|
| 730 |
-
}
|
| 731 |
-
}, () => complain(format));
|
| 732 |
-
}
|
| 733 |
-
|
| 734 |
-
for (const format of Object.keys(buttons)) {
|
| 735 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 736 |
-
}
|
| 737 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 738 |
-
window.addEventListener("message", ev => {
|
| 739 |
-
const d = ev.data;
|
| 740 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 741 |
-
});
|
| 742 |
-
}
|
| 743 |
-
|
| 744 |
-
// When embedded, report the content height so the host page can size the
|
| 745 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 746 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 747 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 748 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 749 |
-
// stops re-posting once the height settles.
|
| 750 |
-
let lastPostedHeight = 0;
|
| 751 |
-
function postHeight() {
|
| 752 |
-
if (window.parent === window) return;
|
| 753 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 754 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 755 |
-
lastPostedHeight = height;
|
| 756 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 757 |
-
}
|
| 758 |
-
|
| 759 |
-
|
| 760 |
-
// ---------- geometry ----------
|
| 761 |
-
const AXIS_W = 72; // width of the sticky y-axis pane
|
| 762 |
-
const PLOT_H = 320; // height of the plot area itself
|
| 763 |
-
const TOP = 14; // headroom above the tallest bar
|
| 764 |
-
const LABEL_TOP = 18; // axis line -> first label row
|
| 765 |
-
const LABEL_ROW = 19; // vertical offset of the staggered second row
|
| 766 |
-
const LABEL_SIZE = 14; // method names; the slot below scales with it
|
| 767 |
-
const TICK_SIZE = 12.5;
|
| 768 |
-
// Method names are set horizontally (rotated ones are markedly harder to
|
| 769 |
-
// read), staggered over two rows exactly like the static figure — so a slot
|
| 770 |
-
// has to be wide enough for half a name. Past ~24 methods the chart scrolls
|
| 771 |
-
// rather than squeezing every column into the viewport.
|
| 772 |
-
// No upper bound on the slot: with few methods selected a capped slot left
|
| 773 |
-
// the columns huddled on the left with dead space beside them, so the slots
|
| 774 |
-
// simply share out whatever width there is.
|
| 775 |
-
const MIN_SLOT = 66;
|
| 776 |
-
const BAR_FRAC = 0.88; // share of the slot the widest bar takes
|
| 777 |
-
const MAX_BAR = 70; // ...but never wider than this, however few columns
|
| 778 |
-
|
| 779 |
-
// Variant -> (color token, width relative to the widest bar). The bars are
|
| 780 |
-
// concentric, so the nesting itself encodes the tuning progression.
|
| 781 |
-
const VARIANT_STYLE = {
|
| 782 |
-
"Tuned + Ens.": { color: "var(--var-tunedens)", rel: 1 },
|
| 783 |
-
"Tuned": { color: "var(--var-tuned)", rel: 0.8 },
|
| 784 |
-
"Default": { color: "var(--var-default)", rel: 0.6 },
|
| 785 |
-
};
|
| 786 |
-
const VARIANT_ORDER = ["Default", "Tuned", "Tuned + Ens."];
|
| 787 |
-
// Dash patterns cycle so several reference lines stay distinguishable.
|
| 788 |
-
const REF_DASHES = ["8 5", "2 4", "12 4 3 4"];
|
| 789 |
-
|
| 790 |
-
const titleEl = document.getElementById("title");
|
| 791 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 792 |
-
|
| 793 |
-
const axisSvg = document.getElementById("axis");
|
| 794 |
-
const svg = document.getElementById("chart");
|
| 795 |
-
const scroller = document.getElementById("scroller");
|
| 796 |
-
const wrap = document.getElementById("chartwrap");
|
| 797 |
-
const yminRange = document.getElementById("ymin-range");
|
| 798 |
-
const yminVal = document.getElementById("ymin-val");
|
| 799 |
-
const tip = makeTooltip(wrap);
|
| 800 |
-
|
| 801 |
-
// ---------- data ----------
|
| 802 |
-
const METRICS = CONFIG.metrics;
|
| 803 |
-
const metricByKey = {};
|
| 804 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 805 |
-
|
| 806 |
-
// One entry per method (its variants grouped); reference pipelines are kept
|
| 807 |
-
// apart — they are drawn as threshold lines, not as columns.
|
| 808 |
-
const byMethod = new Map();
|
| 809 |
-
const refs = [];
|
| 810 |
-
for (const p of POINTS) {
|
| 811 |
-
if (p.reference) { refs.push(p); continue; }
|
| 812 |
-
let entry = byMethod.get(p.method);
|
| 813 |
-
if (!entry) {
|
| 814 |
-
entry = { method: p.method, family: p.family, url: p.url, points: [] };
|
| 815 |
-
byMethod.set(p.method, entry);
|
| 816 |
-
}
|
| 817 |
-
entry.points.push(p);
|
| 818 |
-
}
|
| 819 |
-
for (const e of byMethod.values()) {
|
| 820 |
-
e.points.sort((a, b) => VARIANT_ORDER.indexOf(a.variant) - VARIANT_ORDER.indexOf(b.variant));
|
| 821 |
-
e.imputed = e.points.some(p => p.imputed);
|
| 822 |
-
e.imputed_pct = Math.max(...e.points.map(p => p.imputed_pct || 0));
|
| 823 |
-
}
|
| 824 |
-
|
| 825 |
-
const state = {
|
| 826 |
-
metric: METRICS[0].key,
|
| 827 |
-
sort: "best",
|
| 828 |
-
yMin: null, // null = the automatic axis floor; a number = zoomed in
|
| 829 |
-
|
| 830 |
-
methods: new Set(byMethod.keys()),
|
| 831 |
-
refs: new Set(refs.map(r => r.method)),
|
| 832 |
-
variants: new Set(VARIANT_ORDER),
|
| 833 |
-
};
|
| 834 |
-
|
| 835 |
-
function metric() { return metricByKey[state.metric]; }
|
| 836 |
-
|
| 837 |
-
// A method's best value under `m`, ignoring variants the reader switched off.
|
| 838 |
-
function bestOf(entry, m) {
|
| 839 |
-
const vals = entry.points
|
| 840 |
-
.filter(p => state.variants.has(p.variant) && p[m.key] != null)
|
| 841 |
-
.map(p => p[m.key]);
|
| 842 |
-
if (!vals.length) return null;
|
| 843 |
-
return m.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 844 |
-
}
|
| 845 |
-
|
| 846 |
-
function sortedMethods(entries, m) {
|
| 847 |
-
const arr = [...entries];
|
| 848 |
-
const cmp = {
|
| 849 |
-
best: (a, b) => rankVal(a, m) - rankVal(b, m),
|
| 850 |
-
worst: (a, b) => rankVal(b, m) - rankVal(a, m),
|
| 851 |
-
name: (a, b) => a.method.localeCompare(b.method),
|
| 852 |
-
family: (a, b) =>
|
| 853 |
-
FAM_ORDER.indexOf(a.family) - FAM_ORDER.indexOf(b.family) || rankVal(a, m) - rankVal(b, m),
|
| 854 |
-
}[state.sort];
|
| 855 |
-
return arr.sort(cmp);
|
| 856 |
-
}
|
| 857 |
-
// Sort key that puts "better" first for either metric direction, with
|
| 858 |
-
// value-less methods last.
|
| 859 |
-
function rankVal(entry, m) {
|
| 860 |
-
const v = bestOf(entry, m);
|
| 861 |
-
if (v == null) return Infinity;
|
| 862 |
-
return m.lowerBetter ? v : -v;
|
| 863 |
-
}
|
| 864 |
-
|
| 865 |
-
function visibleEntries() {
|
| 866 |
-
const m = metric();
|
| 867 |
-
return sortedMethods([...byMethod.values()].filter(e => state.methods.has(e.method) && bestOf(e, m) != null), m);
|
| 868 |
-
}
|
| 869 |
-
function visibleRefs() {
|
| 870 |
-
return refs.filter(r => state.refs.has(r.method) && r[state.metric] != null);
|
| 871 |
-
}
|
| 872 |
-
|
| 873 |
-
// Rendered width of each label, measured in the live document (font metrics
|
| 874 |
-
// are not knowable up front): it decides whether the names fit on one row or
|
| 875 |
-
// need the two-row stagger, and which ones have to be shortened.
|
| 876 |
-
function measureLabels(names) {
|
| 877 |
-
const probe = el("g", { visibility: "hidden" }, svg);
|
| 878 |
-
const widths = names.map(name => {
|
| 879 |
-
const t = el("text", { "font-size": LABEL_SIZE }, probe);
|
| 880 |
-
t.textContent = name;
|
| 881 |
-
return t.getComputedTextLength();
|
| 882 |
-
});
|
| 883 |
-
probe.remove();
|
| 884 |
-
return widths;
|
| 885 |
-
}
|
| 886 |
-
|
| 887 |
-
// Trim a name to `budget` px, ending in an ellipsis. The full name stays one
|
| 888 |
-
// hover (and one data-table row) away.
|
| 889 |
-
function fitLabel(node, name, width, budget) {
|
| 890 |
-
if (width <= budget) return;
|
| 891 |
-
let text = name;
|
| 892 |
-
while (text.length > 1 && node.getComputedTextLength() > budget) {
|
| 893 |
-
text = text.slice(0, -1);
|
| 894 |
-
node.textContent = text + "…";
|
| 895 |
-
}
|
| 896 |
-
}
|
| 897 |
-
|
| 898 |
-
// ---------- chart ----------
|
| 899 |
-
function render() {
|
| 900 |
-
const m = metric();
|
| 901 |
-
const entries = visibleEntries();
|
| 902 |
-
const shownRefs = visibleRefs();
|
| 903 |
-
svg.textContent = "";
|
| 904 |
-
axisSvg.textContent = "";
|
| 905 |
-
axisSvg.setAttribute("width", AXIS_W);
|
| 906 |
-
|
| 907 |
-
const avail = Math.max(240, scroller.clientWidth - 2);
|
| 908 |
-
if (!entries.length) {
|
| 909 |
-
axisSvg.setAttribute("height", 120);
|
| 910 |
-
svg.setAttribute("width", avail);
|
| 911 |
-
svg.setAttribute("height", 120);
|
| 912 |
-
const t = el("text", { x: avail / 2, y: 60, "text-anchor": "middle", "font-size": 13, fill: "var(--muted)" }, svg);
|
| 913 |
-
t.textContent = "No methods selected — use “All methods” to bring them back.";
|
| 914 |
-
buildLegend(m, shownRefs);
|
| 915 |
-
postHeight();
|
| 916 |
-
return;
|
| 917 |
-
}
|
| 918 |
-
|
| 919 |
-
const slot = Math.max(MIN_SLOT, avail / entries.length);
|
| 920 |
-
const barUnit = Math.min(MAX_BAR, slot * BAR_FRAC);
|
| 921 |
-
const plotW = Math.max(avail, slot * entries.length);
|
| 922 |
-
// Names go on one row when they fit side by side, otherwise on two
|
| 923 |
-
// staggered rows (each label then has two slots of room).
|
| 924 |
-
const labels = entries.map(e => e.method + (e.imputed ? " ‡" : ""));
|
| 925 |
-
const labelWidths = measureLabels(labels);
|
| 926 |
-
const widest = Math.max(...labelWidths);
|
| 927 |
-
const labelRows = widest <= slot - 6 ? 1 : 2;
|
| 928 |
-
const H = TOP + PLOT_H + LABEL_TOP + (labelRows - 1) * LABEL_ROW + 10;
|
| 929 |
-
svg.setAttribute("width", plotW);
|
| 930 |
-
svg.setAttribute("height", H);
|
| 931 |
-
axisSvg.setAttribute("height", H);
|
| 932 |
-
|
| 933 |
-
// -- y domain: from zero where the metric has one, else a floor below the
|
| 934 |
-
// shortest bar (Elo has no meaningful zero, and starting at zero would
|
| 935 |
-
// squash every difference into the top fifth of the chart). The floor
|
| 936 |
-
// ignores the CI whiskers so one wide interval cannot deflate the scale.
|
| 937 |
-
const barVals = [];
|
| 938 |
-
const allVals = [];
|
| 939 |
-
for (const e of entries) {
|
| 940 |
-
for (const p of e.points) {
|
| 941 |
-
if (!state.variants.has(p.variant) || p[m.key] == null) continue;
|
| 942 |
-
barVals.push(p[m.key]);
|
| 943 |
-
allVals.push(p[m.key]);
|
| 944 |
-
if (m.ci && p[m.ci.hi] != null) allVals.push(p[m.ci.hi]);
|
| 945 |
-
}
|
| 946 |
-
}
|
| 947 |
-
for (const r of shownRefs) { barVals.push(r[state.metric]); allVals.push(r[state.metric]); }
|
| 948 |
-
const barMin = Math.min(...barVals), barMax = Math.max(...allVals);
|
| 949 |
-
const span = barMax - barMin || Math.abs(barMax) || 1;
|
| 950 |
-
let autoY0, y1;
|
| 951 |
-
if (m.fromZero) {
|
| 952 |
-
autoY0 = 0;
|
| 953 |
-
y1 = barMax * 1.06 || 1;
|
| 954 |
-
} else {
|
| 955 |
-
// Snap the floor down to a tick multiple so the axis reads in round
|
| 956 |
-
// numbers, and keep it just below the shortest bar: every bar stays
|
| 957 |
-
// visible (the static figure clips the ones below its fixed floor).
|
| 958 |
-
const step = niceStep(span / 6);
|
| 959 |
-
autoY0 = Math.floor((barMin - span * 0.05) / step) * step;
|
| 960 |
-
y1 = barMax + span * 0.04;
|
| 961 |
-
}
|
| 962 |
-
// The zoom slider raises the floor from there toward the top of the field,
|
| 963 |
-
// magnifying the differences between the leaders. Its bounds follow the
|
| 964 |
-
// metric's own scale, so they are refreshed on every render; the bars and
|
| 965 |
-
// whiskers that drop below the new floor are clipped away (see plot-clip).
|
| 966 |
-
const zoomMax = autoY0 + (y1 - autoY0) * 0.9;
|
| 967 |
-
yminRange.min = autoY0;
|
| 968 |
-
yminRange.max = zoomMax;
|
| 969 |
-
yminRange.step = (zoomMax - autoY0) / 200 || 1;
|
| 970 |
-
if (state.yMin != null) state.yMin = Math.min(state.yMin, zoomMax);
|
| 971 |
-
if (state.yMin != null && state.yMin <= autoY0) state.yMin = null;
|
| 972 |
-
const y0 = state.yMin == null ? autoY0 : state.yMin;
|
| 973 |
-
yminRange.value = y0;
|
| 974 |
-
yminVal.textContent = state.yMin == null ? "auto" : fmtNum(y0, m.decimals);
|
| 975 |
-
const Y = v => TOP + (1 - (v - y0) / (y1 - y0)) * PLOT_H;
|
| 976 |
-
const baseY = Y(y0);
|
| 977 |
-
|
| 978 |
-
// -- grid (solid hairlines) in the plot pane, tick labels in the axis pane
|
| 979 |
-
const tickVals = ticks(y0, y1, 6);
|
| 980 |
-
const grid = el("g", {}, svg);
|
| 981 |
-
const tickLabels = [];
|
| 982 |
-
for (const tv of tickVals) {
|
| 983 |
-
const gy = Y(tv);
|
| 984 |
-
el("line", { x1: 0, y1: gy, x2: plotW, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 985 |
-
const t = el("text", {
|
| 986 |
-
x: AXIS_W - 10, y: gy + 4, "text-anchor": "end", "font-size": TICK_SIZE, fill: "var(--muted)",
|
| 987 |
-
}, axisSvg);
|
| 988 |
-
t.textContent = fmtNum(tv, m.decimals);
|
| 989 |
-
tickLabels.push({ y: gy, node: t });
|
| 990 |
-
}
|
| 991 |
-
el("line", { x1: 0, y1: baseY, x2: plotW, y2: baseY, stroke: "var(--muted)", "stroke-width": 1 }, grid);
|
| 992 |
-
el("line", { x1: AXIS_W - 1, y1: TOP, x2: AXIS_W - 1, y2: baseY, stroke: "var(--muted)", "stroke-width": 1 }, axisSvg);
|
| 993 |
-
el("text", {
|
| 994 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": LABEL_SIZE, "font-weight": 650,
|
| 995 |
-
fill: "var(--ink)", transform: `translate(15 ${TOP + PLOT_H / 2}) rotate(-90)`,
|
| 996 |
-
}, axisSvg).textContent = m.axisLabel;
|
| 997 |
-
|
| 998 |
-
// -- hover band behind the marks (highlights the whole column group)
|
| 999 |
-
const band = el("rect", {
|
| 1000 |
-
x: 0, y: TOP, width: slot, height: PLOT_H + 6, fill: "var(--ink)", opacity: 0, "pointer-events": "none",
|
| 1001 |
-
}, svg);
|
| 1002 |
-
|
| 1003 |
-
const defs = el("defs", {}, svg);
|
| 1004 |
-
// -- imputed hatch, reused by every partially imputed bar. Crossed diagonals,
|
| 1005 |
-
// matching the "x" hatch matplotlib draws in the static figure; the
|
| 1006 |
-
// diagonals meet the tile corners exactly, so the grid tiles seamlessly.
|
| 1007 |
-
const pat = el("pattern", {
|
| 1008 |
-
id: "imp-hatch", width: 8, height: 8, patternUnits: "userSpaceOnUse",
|
| 1009 |
-
}, defs);
|
| 1010 |
-
el("path", {
|
| 1011 |
-
d: "M0,0 L8,8 M8,0 L0,8", stroke: "var(--paper)", "stroke-width": 1.5,
|
| 1012 |
-
opacity: 0.85, fill: "none",
|
| 1013 |
-
}, pat);
|
| 1014 |
-
|
| 1015 |
-
// -- Everything data-bearing is clipped to the plot area. The axis floor is
|
| 1016 |
-
// set from the bar values (a couple of very wide intervals would
|
| 1017 |
-
// otherwise deflate the whole scale), so a long lower CI whisker can
|
| 1018 |
-
// reach past it and run into the method names below. Clip it there; the
|
| 1019 |
-
// exact interval stays in the tooltip and the data table.
|
| 1020 |
-
const clip = el("clipPath", { id: "plot-clip" }, defs);
|
| 1021 |
-
el("rect", { x: 0, y: 0, width: plotW, height: baseY }, clip);
|
| 1022 |
-
|
| 1023 |
-
// -- bars: one concentric group per method
|
| 1024 |
-
const barsG = el("g", { "clip-path": "url(#plot-clip)" }, svg);
|
| 1025 |
-
entries.forEach((entry, i) => {
|
| 1026 |
-
const cx = i * slot + slot / 2;
|
| 1027 |
-
// Widest bar first, narrowest last: the bars are concentric, so painting
|
| 1028 |
-
// them by width guarantees each one stays visible. Ordering by height
|
| 1029 |
-
// instead loses a variant outright whenever a narrower bar is the taller
|
| 1030 |
-
// of the two (TabSTAR's tuned bar sat 1 Elo above tuned + ensembled, and
|
| 1031 |
-
// the wider bar covered it completely).
|
| 1032 |
-
const relOf = p => (VARIANT_STYLE[p.variant] || VARIANT_STYLE["Default"]).rel;
|
| 1033 |
-
const drawn = entry.points
|
| 1034 |
-
.filter(p => state.variants.has(p.variant) && p[m.key] != null)
|
| 1035 |
-
.slice()
|
| 1036 |
-
.sort((a, b) => relOf(b) - relOf(a));
|
| 1037 |
-
for (const p of drawn) {
|
| 1038 |
-
const style = VARIANT_STYLE[p.variant] || VARIANT_STYLE["Default"];
|
| 1039 |
-
const w = barUnit * style.rel;
|
| 1040 |
-
const top = Y(p[m.key]);
|
| 1041 |
-
const rect = {
|
| 1042 |
-
x: cx - w / 2, y: Math.min(top, baseY), width: w, height: Math.max(1, Math.abs(baseY - top)),
|
| 1043 |
-
};
|
| 1044 |
-
// 2px surface ring, not a border: it is what keeps a nested bar legible
|
| 1045 |
-
// against the wider bar it sits inside.
|
| 1046 |
-
el("rect", { ...rect, fill: style.color, stroke: "var(--paper)", "stroke-width": 1.5, rx: 2 }, barsG);
|
| 1047 |
-
if (p.imputed) el("rect", { ...rect, fill: "url(#imp-hatch)", rx: 2 }, barsG);
|
| 1048 |
-
if (m.ci && p[m.ci.lo] != null) {
|
| 1049 |
-
const cap = Math.max(2.5, w * 0.34);
|
| 1050 |
-
const whisk = el("g", {
|
| 1051 |
-
stroke: `color-mix(in srgb, ${style.color} 55%, var(--ink))`, "stroke-width": 1.4, opacity: 0.9,
|
| 1052 |
-
}, barsG);
|
| 1053 |
-
el("line", { x1: cx, y1: Y(p[m.ci.lo]), x2: cx, y2: Y(p[m.ci.hi]) }, whisk);
|
| 1054 |
-
el("line", { x1: cx - cap, y1: Y(p[m.ci.hi]), x2: cx + cap, y2: Y(p[m.ci.hi]) }, whisk);
|
| 1055 |
-
el("line", { x1: cx - cap, y1: Y(p[m.ci.lo]), x2: cx + cap, y2: Y(p[m.ci.lo]) }, whisk);
|
| 1056 |
-
}
|
| 1057 |
-
}
|
| 1058 |
-
});
|
| 1059 |
-
|
| 1060 |
-
// -- x axis: the method name, colored by model family (the legend below
|
| 1061 |
-
// names the colors).
|
| 1062 |
-
const xg = el("g", {}, svg);
|
| 1063 |
-
// Hairlines share one group that is painted before every name, so a name
|
| 1064 |
-
// nudged sideways at the edge (see below) passes over a neighbouring
|
| 1065 |
-
// column's hairline instead of being crossed out by it.
|
| 1066 |
-
const xLines = el("g", {}, xg);
|
| 1067 |
-
const xLabels = el("g", {}, xg);
|
| 1068 |
-
entries.forEach((entry, i) => {
|
| 1069 |
-
const cx = i * slot + slot / 2;
|
| 1070 |
-
const row = labelRows === 1 ? 0 : i % 2;
|
| 1071 |
-
const y = baseY + LABEL_TOP + row * LABEL_ROW;
|
| 1072 |
-
// A hairline drops the staggered row back to its own column.
|
| 1073 |
-
if (row) {
|
| 1074 |
-
el("line", {
|
| 1075 |
-
x1: cx, y1: baseY + 3, x2: cx, y2: y - 10,
|
| 1076 |
-
stroke: "var(--line)", "stroke-width": 1,
|
| 1077 |
-
}, xLines);
|
| 1078 |
-
}
|
| 1079 |
-
const t = el("text", {
|
| 1080 |
-
x: cx, y, "font-size": LABEL_SIZE, "text-anchor": "middle", "font-weight": 650,
|
| 1081 |
-
fill: FAM_INK[entry.family] || "var(--ink)",
|
| 1082 |
-
// A halo in the surface color keeps the glyphs legible where a nudged
|
| 1083 |
-
// name crosses a hairline, rather than the line running through them.
|
| 1084 |
-
"paint-order": "stroke", stroke: "var(--paper)", "stroke-width": 3,
|
| 1085 |
-
}, xLabels);
|
| 1086 |
-
t.textContent = labels[i];
|
| 1087 |
-
fitLabel(t, labels[i], labelWidths[i], slot * labelRows - 8);
|
| 1088 |
-
// The outermost columns sit only half a slot from the edge, so a name
|
| 1089 |
-
// wider than one slot would reach past the SVG viewport and be cut off
|
| 1090 |
-
// there (a name may occupy two slots when the rows are staggered). Nudge
|
| 1091 |
-
// it inwards by just enough to stay whole; every other label keeps its
|
| 1092 |
-
// column centre, and the bar below still marks the column.
|
| 1093 |
-
const half = t.getComputedTextLength() / 2;
|
| 1094 |
-
t.setAttribute("x", Math.max(half + 1, Math.min(cx, plotW - half - 1)));
|
| 1095 |
-
});
|
| 1096 |
-
|
| 1097 |
-
// -- reference pipelines as threshold lines. Their names live in the legend
|
| 1098 |
-
// (matched by dash pattern) rather than on the line, where they would
|
| 1099 |
-
// cover the tallest bars at every scroll position.
|
| 1100 |
-
const refG = el("g", {}, svg);
|
| 1101 |
-
const tagYs = [];
|
| 1102 |
-
shownRefs.forEach((r, i) => {
|
| 1103 |
-
const ry = Y(r[state.metric]);
|
| 1104 |
-
if (ry < TOP || ry > baseY) return;
|
| 1105 |
-
el("line", {
|
| 1106 |
-
x1: 0, y1: ry, x2: plotW, y2: ry, stroke: "var(--fam-reference)", "stroke-width": 1.8,
|
| 1107 |
-
"stroke-dasharray": REF_DASHES[i % REF_DASHES.length], opacity: 0.95,
|
| 1108 |
-
}, refG);
|
| 1109 |
-
// Sticky value tag in the axis pane, so the threshold stays readable at
|
| 1110 |
-
// any scroll position. Two nearby thresholds would print on top of each
|
| 1111 |
-
// other, so nudge each tag clear of the ones already placed; a tag wins
|
| 1112 |
-
// over a tick label it would sit on.
|
| 1113 |
-
let ty = ry;
|
| 1114 |
-
while (tagYs.some(y => Math.abs(y - ty) < 12)) ty += 12;
|
| 1115 |
-
tagYs.push(ty);
|
| 1116 |
-
for (const t of tickLabels) {
|
| 1117 |
-
if (Math.abs(t.y - ty) < 10) t.node.remove();
|
| 1118 |
-
}
|
| 1119 |
-
el("text", {
|
| 1120 |
-
x: AXIS_W - 10, y: ty + 4, "text-anchor": "end", "font-size": 11, "font-weight": 650,
|
| 1121 |
-
fill: "var(--fam-reference)",
|
| 1122 |
-
}, axisSvg).textContent = fmtMetric(m, r[state.metric]);
|
| 1123 |
-
});
|
| 1124 |
-
buildLegend(m, shownRefs);
|
| 1125 |
-
|
| 1126 |
-
// -- hit targets: one full-height column per method (>= 34px wide)
|
| 1127 |
-
const hits = el("g", {}, svg);
|
| 1128 |
-
entries.forEach((entry, i) => {
|
| 1129 |
-
const h = el("rect", {
|
| 1130 |
-
x: i * slot, y: TOP, width: slot, height: PLOT_H + 6, fill: "transparent", cursor: "pointer",
|
| 1131 |
-
}, hits);
|
| 1132 |
-
h.addEventListener("mouseenter", ev => {
|
| 1133 |
-
band.setAttribute("x", i * slot);
|
| 1134 |
-
band.setAttribute("opacity", 0.06);
|
| 1135 |
-
showTip(entry, ev);
|
| 1136 |
-
});
|
| 1137 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1138 |
-
h.addEventListener("mouseleave", () => { band.setAttribute("opacity", 0); tip.hide(); });
|
| 1139 |
-
h.addEventListener("click", () => toggleMethod(entry.method));
|
| 1140 |
-
});
|
| 1141 |
-
|
| 1142 |
-
postHeight();
|
| 1143 |
-
}
|
| 1144 |
-
|
| 1145 |
-
function showTip(entry, ev) {
|
| 1146 |
-
const m = metric();
|
| 1147 |
-
let html = `<div class="t-name">${entry.method}</div><div>${entry.family}</div>`;
|
| 1148 |
-
for (const p of entry.points) {
|
| 1149 |
-
if (!state.variants.has(p.variant) || p[m.key] == null) continue;
|
| 1150 |
-
const ci = m.ci && p[m.ci.lo] != null
|
| 1151 |
-
? ` <span class="t-var">(${fmtNum(p[m.ci.lo], m.decimals)}–${fmtNum(p[m.ci.hi], m.decimals)})</span>`
|
| 1152 |
-
: "";
|
| 1153 |
-
html += `<div><span class="t-var">${p.variant}:</span> <b>${fmtMetric(m, p[m.key])}</b>${ci}</div>`;
|
| 1154 |
-
}
|
| 1155 |
-
if (entry.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(entry.imputed_pct, 0)}% of datasets</div>`;
|
| 1156 |
-
tip.show(html, ev);
|
| 1157 |
-
}
|
| 1158 |
-
|
| 1159 |
-
// ---------- chips ----------
|
| 1160 |
-
const chipsBox = document.getElementById("chips");
|
| 1161 |
-
const chipByMethod = new Map();
|
| 1162 |
-
const famChips = new Map();
|
| 1163 |
-
|
| 1164 |
-
function familyMembers(fam) {
|
| 1165 |
-
const out = [...byMethod.values()].filter(e => e.family === fam).map(e => e.method);
|
| 1166 |
-
for (const r of refs) if (r.family === fam) out.push(r.method);
|
| 1167 |
-
return out;
|
| 1168 |
-
}
|
| 1169 |
-
function isOn(name) { return state.methods.has(name) || state.refs.has(name); }
|
| 1170 |
-
|
| 1171 |
-
function buildChips() {
|
| 1172 |
-
const rankMetric = metricByKey[CONFIG.rankMetric] || METRICS[0];
|
| 1173 |
-
const head = document.createElement("div");
|
| 1174 |
-
head.className = "chips-head";
|
| 1175 |
-
head.textContent = "Methods shown — click to remove, click a family to toggle the whole group";
|
| 1176 |
-
chipsBox.appendChild(head);
|
| 1177 |
-
for (const fam of FAM_ORDER) {
|
| 1178 |
-
const members = familyMembers(fam);
|
| 1179 |
-
if (!members.length) continue;
|
| 1180 |
-
members.sort((a, b) => chipRank(a, rankMetric) - chipRank(b, rankMetric));
|
| 1181 |
-
const row = document.createElement("div");
|
| 1182 |
-
row.className = "chiprow";
|
| 1183 |
-
const famBtn = document.createElement("button");
|
| 1184 |
-
famBtn.className = "famchip";
|
| 1185 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1186 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1187 |
-
famBtn.title = `Toggle all ${members.length} ${fam} methods`;
|
| 1188 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1189 |
-
row.appendChild(famBtn);
|
| 1190 |
-
famChips.set(fam, famBtn);
|
| 1191 |
-
const set = document.createElement("div");
|
| 1192 |
-
set.className = "chipset";
|
| 1193 |
-
for (const name of members) {
|
| 1194 |
-
const entry = byMethod.get(name);
|
| 1195 |
-
const b = document.createElement("button");
|
| 1196 |
-
b.className = "chip";
|
| 1197 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1198 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1199 |
-
b.appendChild(Object.assign(document.createElement("span"), { textContent: name }));
|
| 1200 |
-
if (entry && entry.imputed) {
|
| 1201 |
-
const mark = document.createElement("span");
|
| 1202 |
-
mark.className = "imp-mark";
|
| 1203 |
-
mark.textContent = "‡";
|
| 1204 |
-
b.appendChild(mark);
|
| 1205 |
-
}
|
| 1206 |
-
b.title = name + (entry && entry.imputed ? " — partially imputed" : "");
|
| 1207 |
-
b.addEventListener("click", () => toggleMethod(name));
|
| 1208 |
-
set.appendChild(b);
|
| 1209 |
-
chipByMethod.set(name, b);
|
| 1210 |
-
}
|
| 1211 |
-
row.appendChild(set);
|
| 1212 |
-
chipsBox.appendChild(row);
|
| 1213 |
-
}
|
| 1214 |
-
}
|
| 1215 |
-
function chipRank(name, m) {
|
| 1216 |
-
const entry = byMethod.get(name);
|
| 1217 |
-
if (entry) return rankVal(entry, m);
|
| 1218 |
-
const r = refs.find(x => x.method === name);
|
| 1219 |
-
const v = r ? r[m.key] : null;
|
| 1220 |
-
return v == null ? Infinity : (m.lowerBetter ? v : -v);
|
| 1221 |
-
}
|
| 1222 |
-
function syncChips() {
|
| 1223 |
-
for (const [name, b] of chipByMethod) b.setAttribute("aria-pressed", String(isOn(name)));
|
| 1224 |
-
for (const [fam, b] of famChips) b.setAttribute("aria-pressed", String(familyMembers(fam).every(isOn)));
|
| 1225 |
-
}
|
| 1226 |
-
|
| 1227 |
-
function toggleMethod(name) {
|
| 1228 |
-
const set = byMethod.has(name) ? state.methods : state.refs;
|
| 1229 |
-
if (set.has(name)) set.delete(name); else set.add(name);
|
| 1230 |
-
syncChips();
|
| 1231 |
-
render();
|
| 1232 |
-
}
|
| 1233 |
-
function toggleFamily(fam) {
|
| 1234 |
-
const members = familyMembers(fam);
|
| 1235 |
-
const allOn = members.every(isOn);
|
| 1236 |
-
for (const name of members) {
|
| 1237 |
-
const set = byMethod.has(name) ? state.methods : state.refs;
|
| 1238 |
-
if (allOn) set.delete(name); else set.add(name);
|
| 1239 |
-
}
|
| 1240 |
-
syncChips();
|
| 1241 |
-
render();
|
| 1242 |
-
}
|
| 1243 |
-
function setMethods(names) {
|
| 1244 |
-
state.methods = new Set(names);
|
| 1245 |
-
syncChips();
|
| 1246 |
-
render();
|
| 1247 |
-
}
|
| 1248 |
-
|
| 1249 |
-
document.getElementById("btn-all").addEventListener("click", () => {
|
| 1250 |
-
state.refs = new Set(refs.map(r => r.method));
|
| 1251 |
-
setMethods(byMethod.keys());
|
| 1252 |
-
});
|
| 1253 |
-
document.getElementById("btn-none").addEventListener("click", () => {
|
| 1254 |
-
state.refs = new Set();
|
| 1255 |
-
setMethods([]);
|
| 1256 |
-
});
|
| 1257 |
-
document.getElementById("btn-top").addEventListener("click", () => {
|
| 1258 |
-
const m = metric();
|
| 1259 |
-
// Rank explicitly rather than reusing the display sort: which 15 methods are
|
| 1260 |
-
// kept must not depend on which end of the axis the best ones are drawn at
|
| 1261 |
-
// (sorting "best on the right" would otherwise select the 15 worst).
|
| 1262 |
-
const top = [...byMethod.values()]
|
| 1263 |
-
.sort((a, b) => rankVal(a, m) - rankVal(b, m))
|
| 1264 |
-
.slice(0, 15)
|
| 1265 |
-
.map(e => e.method);
|
| 1266 |
-
state.refs = new Set(refs.map(r => r.method));
|
| 1267 |
-
setMethods(top);
|
| 1268 |
-
});
|
| 1269 |
-
|
| 1270 |
-
// ---------- selectors ----------
|
| 1271 |
-
yminRange.addEventListener("input", ev => {
|
| 1272 |
-
state.yMin = Number(ev.target.value);
|
| 1273 |
-
render();
|
| 1274 |
-
});
|
| 1275 |
-
|
| 1276 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1277 |
-
for (const m of METRICS) {
|
| 1278 |
-
metricSelect.appendChild(Object.assign(document.createElement("option"), { value: m.key, textContent: m.label }));
|
| 1279 |
-
}
|
| 1280 |
-
metricSelect.addEventListener("change", ev => {
|
| 1281 |
-
state.metric = ev.target.value;
|
| 1282 |
-
state.yMin = null; // the previous floor means nothing on a new scale
|
| 1283 |
-
buildTable();
|
| 1284 |
-
render();
|
| 1285 |
-
});
|
| 1286 |
-
|
| 1287 |
-
const sortSelect = document.getElementById("sort-select");
|
| 1288 |
-
for (const [value, label] of [
|
| 1289 |
-
["best", "Best on the left"], ["worst", "Best on the right"],
|
| 1290 |
-
["family", "Model family"], ["name", "A–Z"],
|
| 1291 |
-
]) {
|
| 1292 |
-
sortSelect.appendChild(Object.assign(document.createElement("option"), { value, textContent: label }));
|
| 1293 |
-
}
|
| 1294 |
-
sortSelect.value = state.sort;
|
| 1295 |
-
sortSelect.addEventListener("change", ev => { state.sort = ev.target.value; render(); });
|
| 1296 |
-
|
| 1297 |
-
// Variant toggles: buttons rather than chips, since they filter the series
|
| 1298 |
-
// rather than the rows. "Default" gets no button at all — every method has a
|
| 1299 |
-
// default result, so it is the baseline of the chart rather than an option
|
| 1300 |
-
// (switching it off would leave the default-only methods with no bar). Only
|
| 1301 |
-
// the extras layered on top, tuning and ensembling, are toggleable; the legend
|
| 1302 |
-
// still carries Default's color.
|
| 1303 |
-
const ALWAYS_SHOWN = "Default";
|
| 1304 |
-
const variantBtns = document.getElementById("variant-btns");
|
| 1305 |
-
const variantBtnByKey = new Map();
|
| 1306 |
-
for (const v of VARIANT_ORDER) {
|
| 1307 |
-
if (v === ALWAYS_SHOWN || !POINTS.some(p => p.variant === v)) continue;
|
| 1308 |
-
const b = document.createElement("button");
|
| 1309 |
-
b.className = "btn";
|
| 1310 |
-
b.textContent = v === "Tuned + Ens." ? "Tuned + Ensembled" : v;
|
| 1311 |
-
b.style.setProperty("--fam", VARIANT_STYLE[v].color);
|
| 1312 |
-
b.title = `Show or hide the ${b.textContent.toLowerCase()} bars`;
|
| 1313 |
-
b.addEventListener("click", () => {
|
| 1314 |
-
if (state.variants.has(v)) state.variants.delete(v);
|
| 1315 |
-
else state.variants.add(v);
|
| 1316 |
-
syncVariantBtns();
|
| 1317 |
-
render();
|
| 1318 |
-
});
|
| 1319 |
-
variantBtns.appendChild(b);
|
| 1320 |
-
variantBtnByKey.set(v, b);
|
| 1321 |
-
}
|
| 1322 |
-
function syncVariantBtns() {
|
| 1323 |
-
for (const [v, b] of variantBtnByKey) {
|
| 1324 |
-
const on = state.variants.has(v);
|
| 1325 |
-
b.setAttribute("aria-pressed", String(on));
|
| 1326 |
-
b.style.opacity = on ? "1" : "0.45";
|
| 1327 |
-
b.style.borderColor = on ? VARIANT_STYLE[v].color : "var(--line)";
|
| 1328 |
-
}
|
| 1329 |
-
}
|
| 1330 |
-
|
| 1331 |
-
// ---------- legend ----------
|
| 1332 |
-
// Rebuilt on every render: it names the reference lines (each by its dash
|
| 1333 |
-
// pattern and current value), which change with the metric and the selection.
|
| 1334 |
-
function buildLegend(m, shownRefs) {
|
| 1335 |
-
const parts = [];
|
| 1336 |
-
for (const v of VARIANT_ORDER) {
|
| 1337 |
-
if (!POINTS.some(p => p.variant === v)) continue;
|
| 1338 |
-
const label = v === "Tuned + Ens." ? "Tuned + Ensembled" : v;
|
| 1339 |
-
const off = state.variants.has(v) ? "" : ' style="opacity:0.4"';
|
| 1340 |
-
parts.push(
|
| 1341 |
-
`<span class="item"${off}><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1342 |
-
`<rect x="1" y="1" width="10" height="10" rx="2" fill="${VARIANT_STYLE[v].color}"/></svg> ${label}</span>`);
|
| 1343 |
-
}
|
| 1344 |
-
if (m.ci) {
|
| 1345 |
-
parts.push('<span class="item"><svg width="12" height="14" viewBox="0 0 12 14">' +
|
| 1346 |
-
'<path d="M6,2 V12 M2,2 H10 M2,12 H10" stroke="var(--muted)" stroke-width="1.4" fill="none"/></svg> 95% CI</span>');
|
| 1347 |
-
}
|
| 1348 |
-
shownRefs.forEach((r, i) => {
|
| 1349 |
-
parts.push(`<span class="item"><svg width="26" height="8" viewBox="0 0 26 8">` +
|
| 1350 |
-
`<line x1="0" y1="4" x2="26" y2="4" stroke="var(--fam-reference)" stroke-width="1.8" ` +
|
| 1351 |
-
`stroke-dasharray="${REF_DASHES[i % REF_DASHES.length]}"/></svg> ${r.method} · ${fmtMetric(m, r[state.metric])}</span>`);
|
| 1352 |
-
});
|
| 1353 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1354 |
-
parts.push('<span class="item"><svg width="14" height="14" viewBox="0 0 14 14">' +
|
| 1355 |
-
'<rect x="1" y="1" width="12" height="12" rx="2" fill="var(--pt-muted)"/>' +
|
| 1356 |
-
'<path d="M1,1 L7,7 M7,1 L1,7 M7,7 L13,13 M13,7 L7,13 M1,7 L7,13 M7,7 L13,1" ' +
|
| 1357 |
-
'stroke="var(--paper)" stroke-width="1.5" fill="none"/>' +
|
| 1358 |
-
"</svg> ‡ partially imputed</span>");
|
| 1359 |
-
}
|
| 1360 |
-
// Model family, named rather than merely pointed at: without the colors
|
| 1361 |
-
// spelled out, the swatch under each column decodes to nothing.
|
| 1362 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => !p.reference && p.family === f));
|
| 1363 |
-
if (families.length > 1) {
|
| 1364 |
-
parts.push('<span class="legendbreak"></span><span class="item">Family:</span>');
|
| 1365 |
-
for (const fam of families) {
|
| 1366 |
-
parts.push(`<span class="item"><svg width="16" height="9" viewBox="0 0 16 9">` +
|
| 1367 |
-
`<rect x="0" y="1" width="16" height="7" rx="2" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1368 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`);
|
| 1369 |
-
}
|
| 1370 |
-
}
|
| 1371 |
-
document.getElementById("legendstrip").innerHTML = parts.join("");
|
| 1372 |
-
}
|
| 1373 |
-
|
| 1374 |
-
// ---------- data table (the WCAG-clean twin of the chart) ----------
|
| 1375 |
-
function buildTable() {
|
| 1376 |
-
const m = metric();
|
| 1377 |
-
const rows = [...POINTS].filter(p => p[m.key] != null).sort((a, b) =>
|
| 1378 |
-
m.lowerBetter ? a[m.key] - b[m.key] : b[m.key] - a[m.key]);
|
| 1379 |
-
let html = "<table><thead><tr><th>Method</th><th>Variant</th><th>Family</th>";
|
| 1380 |
-
for (const x of METRICS) html += `<th>${x.label}</th>`;
|
| 1381 |
-
html += "<th>Imputed</th></tr></thead><tbody>";
|
| 1382 |
-
for (const p of rows) {
|
| 1383 |
-
html += `<tr><td>${p.method}</td><td>${p.variant || "—"}</td><td>${p.family}</td>`;
|
| 1384 |
-
for (const x of METRICS) html += `<td>${fmtMetric(x, p[x.key])}</td>`;
|
| 1385 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1386 |
-
}
|
| 1387 |
-
document.getElementById("tblwrap").innerHTML = html + "</tbody></table>";
|
| 1388 |
-
}
|
| 1389 |
-
|
| 1390 |
-
// ---------- paper view ----------
|
| 1391 |
-
setUpPaperView(render);
|
| 1392 |
-
// The y-axis lives in its own pane, so it is offset back into place.
|
| 1393 |
-
setUpExport(() => [{ svg: axisSvg, dx: 0 }, { svg: svg, dx: AXIS_W }], () => slugify(document.title));
|
| 1394 |
-
|
| 1395 |
-
// ---------- boot ----------
|
| 1396 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1397 |
-
let resizeTimer = null;
|
| 1398 |
-
window.addEventListener("resize", () => {
|
| 1399 |
-
clearTimeout(resizeTimer);
|
| 1400 |
-
resizeTimer = setTimeout(render, 120);
|
| 1401 |
-
});
|
| 1402 |
-
|
| 1403 |
-
buildChips();
|
| 1404 |
-
buildTable();
|
| 1405 |
-
syncChips();
|
| 1406 |
-
syncVariantBtns();
|
| 1407 |
-
render(); // also builds the legend (it depends on the metric + selection)
|
| 1408 |
-
})();
|
| 1409 |
-
</script>
|
| 1410 |
-
</body>
|
| 1411 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/leaderboard_table.html
DELETED
|
@@ -1,1162 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena leaderboard table — no imputation | All Tasks | Medium</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* --- The table ------------------------------------------------------------
|
| 269 |
-
A scroll box with a sticky header, so the column names stay put through 80
|
| 270 |
-
rows. Numbers are tabular so digits line up down a column. */
|
| 271 |
-
.lbt-scroll {
|
| 272 |
-
overflow: auto; max-height: 720px; margin-top: 4px;
|
| 273 |
-
border: 1px solid var(--line); border-radius: 10px;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.lbt-scroll::-webkit-scrollbar { width: 11px; height: 11px; }
|
| 277 |
-
.lbt-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
table.lbt { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
|
| 282 |
-
table.lbt th, table.lbt td { padding: 5px 9px; text-align: center; border: 1px solid var(--line); }
|
| 283 |
-
table.lbt thead th {
|
| 284 |
-
position: sticky; top: 0; z-index: 3; background: var(--card); font-size: 12px;
|
| 285 |
-
font-weight: 650; white-space: nowrap; cursor: pointer; user-select: none;
|
| 286 |
-
box-shadow: inset 0 -1px 0 var(--line);
|
| 287 |
-
}
|
| 288 |
-
/* The header is both the sort control and the definition, so it gets the
|
| 289 |
-
pointer of the former and the dotted underline of the latter. */
|
| 290 |
-
table.lbt thead th .lbl { text-decoration: underline; text-decoration-style: dotted;
|
| 291 |
-
text-decoration-color: var(--muted); text-underline-offset: 3px; }
|
| 292 |
-
table.lbt thead th:hover { color: var(--accent); }
|
| 293 |
-
table.lbt thead th::after { content: "\2195"; font-size: 0.72em; opacity: 0.3; margin-left: 5px; }
|
| 294 |
-
table.lbt thead th[aria-sort="ascending"]::after { content: "\25B2"; opacity: 0.85; }
|
| 295 |
-
table.lbt thead th[aria-sort="descending"]::after { content: "\25BC"; opacity: 0.85; }
|
| 296 |
-
table.lbt td.name { text-align: left; white-space: nowrap; }
|
| 297 |
-
table.lbt td.pos { color: var(--muted); font-variant-numeric: tabular-nums; }
|
| 298 |
-
table.lbt td.type { white-space: nowrap; width: 1%; }
|
| 299 |
-
table.lbt td.num { font-weight: 600; }
|
| 300 |
-
table.lbt td.na { color: var(--pt-muted); }
|
| 301 |
-
table.lbt tbody tr:hover td { filter: brightness(1.12); }
|
| 302 |
-
.ci { opacity: 0.5; font-weight: 400; font-size: 0.82em; }
|
| 303 |
-
.pill { padding: 1px 7px; border-radius: 999px; font-size: 0.95em; white-space: nowrap; }
|
| 304 |
-
.verified { font-size: 0.85em; }
|
| 305 |
-
.link-icon { font-size: 0.78em; opacity: 0.65; margin-left: 2px; }
|
| 306 |
-
/* Grey rather than a dimmed inherit: dimming leaves the tag tinted with the
|
| 307 |
-
family colour, which the model name already carries, and made this table
|
| 308 |
-
disagree with the cross-subset table on the app page. */
|
| 309 |
-
.variant-tag { color: var(--muted); font-weight: 400; font-size: 0.9em; }
|
| 310 |
-
td.name .imp-mark { color: var(--muted); font-weight: 700; margin-left: 3px; }
|
| 311 |
-
td.name a { text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }
|
| 312 |
-
td.name a:hover { text-decoration-style: solid; }
|
| 313 |
-
|
| 314 |
-
.lbt-search {
|
| 315 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 316 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 317 |
-
padding: 6px 9px; width: 12em;
|
| 318 |
-
}
|
| 319 |
-
.lbt-cap { font-size: 12.5px; color: var(--muted); margin: 7px 0 0; }
|
| 320 |
-
.lbt-empty { padding: 34px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 321 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 322 |
-
/* The model selector sits above the table it filters. Families pack side by
|
| 323 |
-
side rather than stacking: one row each would leave the small ones (Baseline,
|
| 324 |
-
Other) wasting a line. */
|
| 325 |
-
.chips { margin: 2px 0 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 326 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 327 |
-
|
| 328 |
-
/* The data export, in the same green the website's figure-export controls use,
|
| 329 |
-
so "this downloads something" reads the same across the site. */
|
| 330 |
-
.btn.export {
|
| 331 |
-
color: #063; background: #7ee0b8; border-color: #7ee0b8; font-weight: 700;
|
| 332 |
-
}
|
| 333 |
-
.btn.export:hover { background: #a6efcd; border-color: #a6efcd; }
|
| 334 |
-
/* Paper view keeps the table: here the table *is* the figure. */
|
| 335 |
-
body.paper .lbt-scroll { max-height: none; }
|
| 336 |
-
</style>
|
| 337 |
-
</head>
|
| 338 |
-
<body>
|
| 339 |
-
<div class="viewbar">
|
| 340 |
-
<button class="btn" id="btn-paper" title="White background, table only — for slides and papers">Paper view</button>
|
| 341 |
-
</div>
|
| 342 |
-
<p class="explorer-title" id="title"></p>
|
| 343 |
-
<div class="controls">
|
| 344 |
-
<span class="grouplabel">Variants</span>
|
| 345 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 346 |
-
<button class="btn" id="btn-imputed" title="Models whose score is partly imputed, marked ‡"></button>
|
| 347 |
-
<input class="lbt-search" id="search" type="search" placeholder="Search model or family" aria-label="Search">
|
| 348 |
-
<span class="grouplabel">Columns</span>
|
| 349 |
-
<div class="btnrow" id="col-btns"></div>
|
| 350 |
-
<button class="btn export" id="btn-csv" title="Download the rows and columns shown, in the current sort order">Download CSV</button>
|
| 351 |
-
</div>
|
| 352 |
-
<!-- The shared paper-view helper reveals this bar; a table has no figure to
|
| 353 |
-
export as SVG/PNG/PDF, and its CSV button belongs beside the filters that
|
| 354 |
-
shape the export, so it stays empty here. -->
|
| 355 |
-
<div class="exportbar" id="exportbar" hidden></div>
|
| 356 |
-
<!-- The model selector belongs above the table it filters. It doubles as the
|
| 357 |
-
family key, which is why there is no separate legend strip. -->
|
| 358 |
-
<div class="chips" id="chips"></div>
|
| 359 |
-
<div class="lbt-scroll" id="tblwrap"></div>
|
| 360 |
-
<p class="lbt-cap" id="caption"></p>
|
| 361 |
-
|
| 362 |
-
<script>
|
| 363 |
-
(function () {
|
| 364 |
-
"use strict";
|
| 365 |
-
const CONFIG = {"title": null, "columns": [{"key": "position", "label": "#", "always": true, "hint": "Position in this subset's published ranking."}, {"key": "family", "label": "Type", "always": true, "hint": "Model family \u2014 see the key above the table."}, {"key": "model", "label": "Model", "always": true, "hint": "The model, its tuning variant in brackets, \u2714\ufe0f when the implementation was verified, and \u2021 when some results are imputed."}, {"key": "elo", "label": "Elo", "decimals": 0, "heatmap": true, "hint": "Pairwise win-rate rating; a 400-point gap is about a 91% win rate. Higher is better."}, {"key": "score", "label": "Score", "decimals": 3, "heatmap": true, "hint": "Error rescaled per dataset to 1 (best) \u2026 0 (median), then averaged. Higher is better."}, {"key": "rank", "label": "Rank", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "Mean rank across datasets. Lower is better."}, {"key": "hrank", "label": "Harmonic rank", "short": "H. rank", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "Harmonic mean of per-dataset ranks; rewards being excellent somewhere. Lower is better."}, {"key": "imp", "label": "Improvability (%)", "short": "Improv.", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "How much lower the best model's error is than this one's, per dataset. Lower is better."}, {"key": "train_time", "label": "Train time (s/1K)", "short": "Train s", "decimals": 2, "lowerBetter": true, "heatmap": true, "logScale": true, "hint": "Median seconds to fit per 1000 rows. Lower is better; shaded on a log scale."}, {"key": "predict_time", "label": "Predict time (s/1K)", "short": "Predict s", "decimals": 3, "lowerBetter": true, "heatmap": true, "logScale": true, "hint": "Median seconds to predict per 1000 rows. Lower is better; shaded on a log scale."}, {"key": "imputed_pct", "label": "Imputed (%)", "short": "Imputed", "decimals": 1, "lowerBetter": true, "heatmap": true, "hint": "Share of datasets whose score was imputed because the model could not run on them."}, {"key": "hardware", "label": "Hardware", "text": true, "hint": "The hardware the reported runtimes were measured on."}], "rankKey": "elo", "variants": ["Default", "Tuned", "Tuned + Ens."]};
|
| 366 |
-
const POINTS = [{"position":0,"method":"TabFM","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/google-research\/tabfm","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1986.0,"score":0.867,"rank":4.41,"hrank":1.69,"imp":2.683,"train_time":27.29,"predict_time":13.119,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+306\/-145","imputed":false},{"position":1,"method":"AutoGluon 1.5 (extreme, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83d\udcca","verified":true,"elo":1899.0,"score":0.71,"rank":6.33,"hrank":2.98,"imp":4.858,"train_time":191.18,"predict_time":2.207,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+85\/-49","imputed":false},{"position":2,"method":"TabPFN-3","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2605.13986","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1794.0,"score":0.659,"rank":9.55,"hrank":3.26,"imp":5.878,"train_time":1.01,"predict_time":0.215,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+214\/-135","imputed":false},{"position":3,"method":"AutoGluon 1.4 (best, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83d\udcca","verified":true,"elo":1775.0,"score":0.579,"rank":10.23,"hrank":4.46,"imp":6.048,"train_time":432.36,"predict_time":4.085,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+83\/-51","imputed":false},{"position":4,"method":"TabPFN-2.6","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1722.0,"score":0.504,"rank":12.39,"hrank":8.78,"imp":7.846,"train_time":2.76,"predict_time":0.701,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+130\/-75","imputed":false},{"position":5,"method":"TabICLv2","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2602.11139","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1697.0,"score":0.541,"rank":13.53,"hrank":4.41,"imp":6.851,"train_time":0.6,"predict_time":0.119,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+186\/-110","imputed":false},{"position":6,"method":"RealTabPFN-2.5","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1646.0,"score":0.446,"rank":16.07,"hrank":8.48,"imp":8.576,"train_time":735.58,"predict_time":11.736,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+142\/-104","imputed":false},{"position":7,"method":"RealMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1625.0,"score":0.412,"rank":17.17,"hrank":11.86,"imp":8.917,"train_time":1719.82,"predict_time":1.675,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+92\/-92","imputed":false},{"position":8,"method":"ModernNCA","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1615.0,"score":0.397,"rank":17.73,"hrank":12.25,"imp":9.07,"train_time":2526.31,"predict_time":6.013,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+104\/-105","imputed":false},{"position":9,"method":"CatBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1611.0,"score":0.379,"rank":17.97,"hrank":9.32,"imp":8.932,"train_time":489.93,"predict_time":0.249,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+85\/-63","imputed":false},{"position":10,"method":"RealTabPFN-2.5","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1600.0,"score":0.403,"rank":18.55,"hrank":10.47,"imp":9.218,"train_time":735.58,"predict_time":1.386,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+126\/-99","imputed":false},{"position":11,"method":"CatBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1596.0,"score":0.372,"rank":18.8,"hrank":9.43,"imp":9.14,"train_time":489.93,"predict_time":0.02,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+98\/-66","imputed":false},{"position":12,"method":"LightGBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1589.0,"score":0.327,"rank":19.19,"hrank":13.5,"imp":10.466,"train_time":131.56,"predict_time":2.639,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+68\/-51","imputed":false},{"position":13,"method":"CatBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1576.0,"score":0.378,"rank":19.95,"hrank":9.61,"imp":9.095,"train_time":2.47,"predict_time":0.01,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+103\/-101","imputed":false},{"position":14,"method":"iLTM","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1558.0,"score":0.322,"rank":20.99,"hrank":15.67,"imp":10.221,"train_time":2067.95,"predict_time":65.195,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+70\/-52","imputed":false},{"position":15,"method":"XGBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1548.0,"score":0.295,"rank":21.61,"hrank":14.86,"imp":10.546,"train_time":282.13,"predict_time":0.563,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+81\/-55","imputed":false},{"position":16,"method":"TabM","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1544.0,"score":0.292,"rank":21.87,"hrank":13.14,"imp":10.254,"train_time":1236.88,"predict_time":0.579,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+146\/-87","imputed":false},{"position":17,"method":"RealMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1533.0,"score":0.301,"rank":22.52,"hrank":14.08,"imp":10.104,"train_time":1719.82,"predict_time":0.081,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+105\/-89","imputed":false},{"position":18,"method":"RealTabPFN-2.5","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1530.0,"score":0.324,"rank":22.69,"hrank":14.72,"imp":10.077,"train_time":1.88,"predict_time":0.645,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+136\/-79","imputed":false},{"position":19,"method":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","url":"https:\/\/openreview.net\/pdf?id=Y00pwFyrHR","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1526.0,"score":0.355,"rank":22.94,"hrank":10.98,"imp":10.809,"train_time":0.75,"predict_time":0.18,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+156\/-139","imputed":false},{"position":20,"method":"TabDPT","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1522.0,"score":0.319,"rank":23.22,"hrank":6.34,"imp":10.287,"train_time":4786.6,"predict_time":444.544,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+134\/-119","imputed":false},{"position":21,"method":"ChimeraBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1517.0,"score":0.314,"rank":23.53,"hrank":13.31,"imp":11.684,"train_time":95.92,"predict_time":0.297,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+116\/-121","imputed":false},{"position":22,"method":"LightGBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1506.0,"score":0.216,"rank":24.2,"hrank":18.44,"imp":11.603,"train_time":131.56,"predict_time":0.132,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+76\/-54","imputed":false},{"position":23,"method":"XGBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1501.0,"score":0.234,"rank":24.53,"hrank":20.07,"imp":11.102,"train_time":282.13,"predict_time":0.066,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+64\/-55","imputed":false},{"position":24,"method":"TabM","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1481.0,"score":0.234,"rank":25.86,"hrank":15.63,"imp":11.089,"train_time":1236.88,"predict_time":0.054,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+130\/-76","imputed":false},{"position":25,"method":"ModernNCA","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1472.0,"score":0.217,"rank":26.42,"hrank":20.56,"imp":11.215,"train_time":2526.31,"predict_time":0.349,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+92\/-81","imputed":false},{"position":26,"method":"ChimeraBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1470.0,"score":0.266,"rank":26.58,"hrank":15.47,"imp":12.146,"train_time":95.92,"predict_time":0.027,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+106\/-115","imputed":false},{"position":27,"method":"xRFM","variant":"Tuned + Ens.","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1423.0,"score":0.224,"rank":29.66,"hrank":21.18,"imp":12.482,"train_time":566.74,"predict_time":0.951,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+106\/-114","imputed":false},{"position":28,"method":"iLTM","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1423.0,"score":0.155,"rank":29.69,"hrank":18.8,"imp":12.112,"train_time":2067.95,"predict_time":10.881,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+97\/-63","imputed":false},{"position":29,"method":"ChimeraBoost","variant":"Default","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1418.0,"score":0.203,"rank":30.0,"hrank":19.33,"imp":13.176,"train_time":0.48,"predict_time":0.023,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+112\/-119","imputed":false},{"position":30,"method":"TabDPT","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1404.0,"score":0.221,"rank":30.97,"hrank":12.53,"imp":12.662,"train_time":4786.6,"predict_time":42.641,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+123\/-118","imputed":false},{"position":31,"method":"TorchMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1377.0,"score":0.128,"rank":32.79,"hrank":26.34,"imp":12.45,"train_time":1770.56,"predict_time":1.069,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+71\/-61","imputed":false},{"position":32,"method":"xRFM","variant":"Tuned","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1373.0,"score":0.159,"rank":33.01,"hrank":27.27,"imp":13.982,"train_time":566.74,"predict_time":0.06,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+92\/-101","imputed":false},{"position":33,"method":"XGBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1372.0,"score":0.137,"rank":33.13,"hrank":21.73,"imp":12.907,"train_time":0.49,"predict_time":0.053,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+89\/-103","imputed":false},{"position":34,"method":"TabSwift","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/LAMDA-Tabular\/TabSwift","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1344.0,"score":0.157,"rank":34.99,"hrank":24.16,"imp":13.337,"train_time":0.51,"predict_time":0.127,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+118\/-102","imputed":false},{"position":35,"method":"TabDPT","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1332.0,"score":0.174,"rank":35.84,"hrank":16.46,"imp":15.311,"train_time":46.62,"predict_time":43.738,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+119\/-134","imputed":false},{"position":36,"method":"TabM","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1326.0,"score":0.096,"rank":36.23,"hrank":29.85,"imp":13.982,"train_time":2.13,"predict_time":0.047,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+110\/-88","imputed":false},{"position":37,"method":"EBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1326.0,"score":0.134,"rank":36.24,"hrank":27.26,"imp":15.595,"train_time":695.61,"predict_time":0.085,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+113\/-128","imputed":false},{"position":38,"method":"ModernNCA","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1298.0,"score":0.073,"rank":38.1,"hrank":33.85,"imp":14.33,"train_time":8.06,"predict_time":0.25,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+72\/-79","imputed":false},{"position":39,"method":"LimiX","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2509.03505","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1279.0,"score":0.17,"rank":39.33,"hrank":9.92,"imp":16.418,"train_time":6.55,"predict_time":5.409,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+140\/-160","imputed":false},{"position":40,"method":"TorchMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1272.0,"score":0.049,"rank":39.78,"hrank":35.01,"imp":14.114,"train_time":1770.56,"predict_time":0.051,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+70\/-75","imputed":false},{"position":41,"method":"RealMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1272.0,"score":0.034,"rank":39.84,"hrank":36.58,"imp":15.091,"train_time":6.75,"predict_time":0.235,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+73\/-68","imputed":false},{"position":42,"method":"EBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1265.0,"score":0.089,"rank":40.24,"hrank":32.83,"imp":16.441,"train_time":695.61,"predict_time":0.006,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+104\/-133","imputed":false},{"position":43,"method":"LightGBM","variant":"Default","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1258.0,"score":0.028,"rank":40.73,"hrank":38.32,"imp":14.82,"train_time":0.29,"predict_time":0.045,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+51\/-64","imputed":false},{"position":44,"method":"RandomForest","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1244.0,"score":0.03,"rank":41.64,"hrank":35.97,"imp":15.1,"train_time":66.0,"predict_time":0.341,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+85\/-85","imputed":false},{"position":45,"method":"EBM","variant":"Default","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1221.0,"score":0.057,"rank":43.14,"hrank":37.72,"imp":17.87,"train_time":2.18,"predict_time":0.005,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+88\/-136","imputed":false},{"position":46,"method":"ExtraTrees","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1217.0,"score":0.022,"rank":43.4,"hrank":40.85,"imp":15.304,"train_time":49.61,"predict_time":0.199,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+79\/-89","imputed":false},{"position":47,"method":"RandomForest","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1214.0,"score":0.031,"rank":43.54,"hrank":37.85,"imp":15.744,"train_time":66.0,"predict_time":0.024,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+86\/-84","imputed":false},{"position":48,"method":"FastaiMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1201.0,"score":0.06,"rank":44.39,"hrank":36.49,"imp":17.192,"train_time":351.94,"predict_time":1.658,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+110\/-138","imputed":false},{"position":49,"method":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2506.10707","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1201.0,"score":0.028,"rank":44.41,"hrank":39.08,"imp":16.933,"train_time":11.44,"predict_time":10.416,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+82\/-95","imputed":false},{"position":50,"method":"iLTM","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1179.0,"score":0.033,"rank":45.73,"hrank":41.33,"imp":18.488,"train_time":88.27,"predict_time":9.62,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+84\/-111","imputed":false},{"position":51,"method":"ExtraTrees","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1174.0,"score":0.008,"rank":46.07,"hrank":43.76,"imp":16.303,"train_time":49.61,"predict_time":0.015,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+70\/-83","imputed":false},{"position":52,"method":"TorchMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1126.0,"score":0.001,"rank":48.9,"hrank":47.16,"imp":18.145,"train_time":2.18,"predict_time":0.039,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+59\/-72","imputed":false},{"position":53,"method":"PerpetualBooster","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":1110.0,"score":0.019,"rank":49.83,"hrank":43.02,"imp":21.633,"train_time":20.26,"predict_time":0.515,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+101\/-125","imputed":false},{"position":54,"method":"FastaiMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1101.0,"score":0.015,"rank":50.32,"hrank":45.23,"imp":19.294,"train_time":351.94,"predict_time":0.114,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+91\/-105","imputed":false},{"position":55,"method":"PerpetualBooster","variant":"Tuned","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":1060.0,"score":0.004,"rank":52.57,"hrank":48.1,"imp":22.747,"train_time":20.26,"predict_time":0.2,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+92\/-116","imputed":false},{"position":56,"method":"xRFM","variant":"Default","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1046.0,"score":0.018,"rank":53.27,"hrank":47.13,"imp":25.98,"train_time":2.49,"predict_time":0.145,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+147\/-184","imputed":false},{"position":57,"method":"FastaiMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1031.0,"score":0.018,"rank":54.04,"hrank":48.76,"imp":22.864,"train_time":1.51,"predict_time":0.111,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+136\/-171","imputed":false},{"position":58,"method":"RandomForest","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1000.0,"score":0.0,"rank":55.55,"hrank":54.46,"imp":21.197,"train_time":0.2,"predict_time":0.021,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+51\/-92","imputed":false},{"position":59,"method":"KNN","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":989.0,"score":0.005,"rank":56.06,"hrank":49.75,"imp":24.353,"train_time":150.3,"predict_time":10.071,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+94\/-128","imputed":false},{"position":60,"method":"TabSTAR","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":988.0,"score":0.0,"rank":56.13,"hrank":54.65,"imp":25.807,"train_time":3381.77,"predict_time":1.724,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+56\/-90","imputed":false},{"position":61,"method":"TabSTAR","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":987.0,"score":0.0,"rank":56.18,"hrank":54.79,"imp":25.781,"train_time":3381.77,"predict_time":5.283,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+61\/-86","imputed":false},{"position":62,"method":"ExtraTrees","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":976.0,"score":0.0,"rank":56.64,"hrank":54.71,"imp":22.789,"train_time":0.48,"predict_time":0.073,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+94\/-121","imputed":false},{"position":63,"method":"Linear","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":935.0,"score":0.004,"rank":58.45,"hrank":53.87,"imp":32.872,"train_time":43.64,"predict_time":0.081,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+153\/-226","imputed":false},{"position":64,"method":"PerpetualBooster","variant":"Default","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":901.0,"score":0.0,"rank":59.81,"hrank":57.82,"imp":29.424,"train_time":1.5,"predict_time":0.015,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+106\/-153","imputed":false},{"position":65,"method":"Linear","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":892.0,"score":0.002,"rank":60.16,"hrank":56.48,"imp":33.73,"train_time":43.64,"predict_time":0.018,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+154\/-245","imputed":false},{"position":66,"method":"TabSTAR","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":848.0,"score":0.0,"rank":61.7,"hrank":61.11,"imp":30.685,"train_time":110.78,"predict_time":1.964,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+50\/-88","imputed":false},{"position":67,"method":"KNN","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":814.0,"score":0.0,"rank":62.78,"hrank":62.5,"imp":29.973,"train_time":150.3,"predict_time":0.482,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+53\/-106","imputed":false},{"position":68,"method":"Linear","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":797.0,"score":0.0,"rank":63.27,"hrank":61.49,"imp":35.794,"train_time":0.19,"predict_time":0.019,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+137\/-244","imputed":false},{"position":69,"method":"KNN","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":593.0,"score":0.0,"rank":67.65,"hrank":67.52,"imp":43.501,"train_time":0.1,"predict_time":0.072,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+83\/-146","imputed":false}];
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 370 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 371 |
-
// already share a color, and each holds only a handful of methods.
|
| 372 |
-
const FAM_MERGED = "Baseline / Other";
|
| 373 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 374 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 375 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 376 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 377 |
-
|
| 378 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 379 |
-
const FAM_VAR = {
|
| 380 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 381 |
-
"Tree-based": "var(--fam-tree)",
|
| 382 |
-
"Neural Network": "var(--fam-nn)",
|
| 383 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 384 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 385 |
-
};
|
| 386 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 387 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 388 |
-
// that chip carries both symbols.
|
| 389 |
-
const FAM_SYMBOL = {
|
| 390 |
-
"Foundation Model": "🧠⚡",
|
| 391 |
-
"Tree-based": "🌳",
|
| 392 |
-
"Neural Network": "🧠🔁",
|
| 393 |
-
"Reference Pipeline": "📊",
|
| 394 |
-
[FAM_MERGED]: "📏 ❓",
|
| 395 |
-
};
|
| 396 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 397 |
-
const VARIANT_VAR = {
|
| 398 |
-
"Default": "var(--var-default)",
|
| 399 |
-
"Tuned": "var(--var-tuned)",
|
| 400 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 401 |
-
};
|
| 402 |
-
|
| 403 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 404 |
-
function famChipLabel(family, count) {
|
| 405 |
-
const symbol = FAM_SYMBOL[family];
|
| 406 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 407 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 408 |
-
}
|
| 409 |
-
|
| 410 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 411 |
-
const FAM_INK = {
|
| 412 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 413 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 414 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 415 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 416 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 417 |
-
};
|
| 418 |
-
|
| 419 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 420 |
-
function el(name, attrs, parent) {
|
| 421 |
-
const node = document.createElementNS(NS, name);
|
| 422 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 423 |
-
if (parent) parent.appendChild(node);
|
| 424 |
-
return node;
|
| 425 |
-
}
|
| 426 |
-
|
| 427 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 428 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 429 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 430 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 431 |
-
function fmtNum(v, decimals) {
|
| 432 |
-
if (v == null || !isFinite(v)) return "—";
|
| 433 |
-
return v.toFixed(decimals);
|
| 434 |
-
}
|
| 435 |
-
|
| 436 |
-
function fmtMetric(metric, v) {
|
| 437 |
-
if (v == null || !isFinite(v)) return "—";
|
| 438 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 439 |
-
}
|
| 440 |
-
|
| 441 |
-
function fmtTime(v) {
|
| 442 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 443 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 444 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 445 |
-
return fmtNum(v, 3) + " s";
|
| 446 |
-
}
|
| 447 |
-
|
| 448 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 449 |
-
function niceStep(raw) {
|
| 450 |
-
if (!(raw > 0)) return 1;
|
| 451 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 452 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 453 |
-
if (mag * m >= raw) return mag * m;
|
| 454 |
-
}
|
| 455 |
-
return mag * 10;
|
| 456 |
-
}
|
| 457 |
-
|
| 458 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 459 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 460 |
-
function ticks(min, max, target) {
|
| 461 |
-
const step = niceStep((max - min) / target);
|
| 462 |
-
const first = Math.ceil(min / step);
|
| 463 |
-
const out = [];
|
| 464 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 465 |
-
return out.length ? out : [min];
|
| 466 |
-
}
|
| 467 |
-
|
| 468 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 469 |
-
function makeTooltip(box) {
|
| 470 |
-
const node = box.querySelector(".tooltip");
|
| 471 |
-
return {
|
| 472 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 473 |
-
move(ev) {
|
| 474 |
-
const r = box.getBoundingClientRect();
|
| 475 |
-
let tx = ev.clientX - r.left + 14;
|
| 476 |
-
const ty = ev.clientY - r.top + 12;
|
| 477 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 478 |
-
node.style.left = tx + "px";
|
| 479 |
-
node.style.top = ty + "px";
|
| 480 |
-
},
|
| 481 |
-
hide() { node.style.display = "none"; },
|
| 482 |
-
};
|
| 483 |
-
}
|
| 484 |
-
|
| 485 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 486 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 487 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 488 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 489 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 490 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 491 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 492 |
-
function setUpPaperView(afterToggle, options) {
|
| 493 |
-
const opts = options || {};
|
| 494 |
-
const root = document.documentElement;
|
| 495 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 496 |
-
const btn = document.getElementById("btn-paper");
|
| 497 |
-
const embedded = window.parent !== window;
|
| 498 |
-
|
| 499 |
-
function setPaper(on) {
|
| 500 |
-
document.body.classList.toggle("paper", on);
|
| 501 |
-
if (on) {
|
| 502 |
-
hostTheme = root.getAttribute("data-theme");
|
| 503 |
-
root.setAttribute("data-theme", "light");
|
| 504 |
-
} else if (hostTheme) {
|
| 505 |
-
root.setAttribute("data-theme", hostTheme);
|
| 506 |
-
} else {
|
| 507 |
-
root.removeAttribute("data-theme");
|
| 508 |
-
}
|
| 509 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 510 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 511 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 512 |
-
postHeight();
|
| 513 |
-
}
|
| 514 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 515 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 516 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 517 |
-
// shareable single file) this page needs its own.
|
| 518 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 519 |
-
window.addEventListener("message", ev => {
|
| 520 |
-
const d = ev.data;
|
| 521 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 522 |
-
});
|
| 523 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 524 |
-
// key press, so its label would fall out of step with the frame.
|
| 525 |
-
if (!embedded) {
|
| 526 |
-
document.addEventListener("keydown", ev => {
|
| 527 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 528 |
-
});
|
| 529 |
-
}
|
| 530 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 531 |
-
}
|
| 532 |
-
|
| 533 |
-
// --- Figure export ---------------------------------------------------------
|
| 534 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 535 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 536 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 537 |
-
// the legend is HTML rather than part of the SVG.
|
| 538 |
-
|
| 539 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 540 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 541 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 542 |
-
// break the PNG path.
|
| 543 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 544 |
-
// once the node leaves this document.
|
| 545 |
-
function resolveVars(root, resolve) {
|
| 546 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 547 |
-
for (const attr of ["fill", "stroke"]) {
|
| 548 |
-
const value = node.getAttribute(attr);
|
| 549 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 550 |
-
}
|
| 551 |
-
}
|
| 552 |
-
}
|
| 553 |
-
|
| 554 |
-
function legendToSvg(container, resolve) {
|
| 555 |
-
const base = container.getBoundingClientRect();
|
| 556 |
-
const group = document.createElementNS(NS, "g");
|
| 557 |
-
let height = 0;
|
| 558 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 559 |
-
const box = item.getBoundingClientRect();
|
| 560 |
-
if (!box.width) continue;
|
| 561 |
-
height = Math.max(height, box.bottom - base.top);
|
| 562 |
-
let textLeft = box.left - base.left;
|
| 563 |
-
const glyph = item.querySelector("svg");
|
| 564 |
-
if (glyph) {
|
| 565 |
-
const gbox = glyph.getBoundingClientRect();
|
| 566 |
-
const wrap = el("g", {
|
| 567 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 568 |
-
}, group);
|
| 569 |
-
const glyphClone = glyph.cloneNode(true);
|
| 570 |
-
resolveVars(glyphClone, resolve);
|
| 571 |
-
wrap.appendChild(glyphClone);
|
| 572 |
-
textLeft = gbox.right - base.left + 5;
|
| 573 |
-
}
|
| 574 |
-
const label = item.textContent.trim();
|
| 575 |
-
if (!label) continue;
|
| 576 |
-
const colored = item.querySelector("[style*='color']");
|
| 577 |
-
const text = el("text", {
|
| 578 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 579 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 580 |
-
}, group);
|
| 581 |
-
text.textContent = label;
|
| 582 |
-
}
|
| 583 |
-
return { group, height: Math.ceil(height) };
|
| 584 |
-
}
|
| 585 |
-
|
| 586 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 587 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 588 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 589 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 590 |
-
const resolve = value => String(value).replace(
|
| 591 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 592 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 593 |
-
|
| 594 |
-
let chartW = 0, chartH = 0;
|
| 595 |
-
for (const part of parts) {
|
| 596 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 597 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 598 |
-
}
|
| 599 |
-
|
| 600 |
-
const out = document.createElementNS(NS, "svg");
|
| 601 |
-
out.setAttribute("xmlns", NS);
|
| 602 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 603 |
-
let top = pad;
|
| 604 |
-
const later = []; // built after the width is known
|
| 605 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 606 |
-
if (legend && legend.height) {
|
| 607 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 608 |
-
later.push(() => out.appendChild(legend.group));
|
| 609 |
-
top += legend.height + 8;
|
| 610 |
-
}
|
| 611 |
-
|
| 612 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 613 |
-
const height = top + chartH + pad;
|
| 614 |
-
out.setAttribute("width", Math.ceil(width));
|
| 615 |
-
out.setAttribute("height", Math.ceil(height));
|
| 616 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 617 |
-
for (const build of later) build();
|
| 618 |
-
|
| 619 |
-
for (const part of parts) {
|
| 620 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 621 |
-
const clone = part.svg.cloneNode(true);
|
| 622 |
-
resolveVars(clone, resolve);
|
| 623 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 624 |
-
}
|
| 625 |
-
return out;
|
| 626 |
-
}
|
| 627 |
-
|
| 628 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 629 |
-
function slugify(text) {
|
| 630 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 631 |
-
}
|
| 632 |
-
|
| 633 |
-
function downloadUrl(url, filename) {
|
| 634 |
-
const a = document.createElement("a");
|
| 635 |
-
a.href = url;
|
| 636 |
-
a.download = filename;
|
| 637 |
-
document.body.appendChild(a);
|
| 638 |
-
a.click();
|
| 639 |
-
a.remove();
|
| 640 |
-
}
|
| 641 |
-
|
| 642 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 643 |
-
function rasterize(svg, scale, done, fail) {
|
| 644 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 645 |
-
const img = new Image();
|
| 646 |
-
img.onload = () => {
|
| 647 |
-
const canvas = document.createElement("canvas");
|
| 648 |
-
canvas.width = Math.round(width * scale);
|
| 649 |
-
canvas.height = Math.round(height * scale);
|
| 650 |
-
const ctx = canvas.getContext("2d");
|
| 651 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 652 |
-
ctx.drawImage(img, 0, 0);
|
| 653 |
-
done(canvas, width, height);
|
| 654 |
-
};
|
| 655 |
-
img.onerror = fail;
|
| 656 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 657 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 658 |
-
}
|
| 659 |
-
|
| 660 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 661 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 662 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 663 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 664 |
-
// and the pixels land at 96*scale dpi.
|
| 665 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 666 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 667 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 668 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 669 |
-
rgb[j] = pixels[i];
|
| 670 |
-
rgb[j + 1] = pixels[i + 1];
|
| 671 |
-
rgb[j + 2] = pixels[i + 2];
|
| 672 |
-
}
|
| 673 |
-
const deflated = new Uint8Array(await new Response(
|
| 674 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 675 |
-
|
| 676 |
-
const encoder = new TextEncoder();
|
| 677 |
-
const chunks = [];
|
| 678 |
-
const offsets = [];
|
| 679 |
-
let cursor = 0;
|
| 680 |
-
const put = data => {
|
| 681 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 682 |
-
chunks.push(bytes);
|
| 683 |
-
cursor += bytes.length;
|
| 684 |
-
};
|
| 685 |
-
const object = (id, body, stream) => {
|
| 686 |
-
offsets[id] = cursor;
|
| 687 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 688 |
-
if (stream) {
|
| 689 |
-
put("stream\n");
|
| 690 |
-
put(stream);
|
| 691 |
-
put("\nendstream\n");
|
| 692 |
-
}
|
| 693 |
-
put("endobj\n");
|
| 694 |
-
};
|
| 695 |
-
|
| 696 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 697 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 698 |
-
put("%PDF-1.4\n");
|
| 699 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 700 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 701 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 702 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 703 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 704 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 705 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 706 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 707 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 708 |
-
|
| 709 |
-
const xref = cursor;
|
| 710 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 711 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 712 |
-
put(table);
|
| 713 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 714 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 715 |
-
}
|
| 716 |
-
|
| 717 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 718 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 719 |
-
function setUpExport(getParts, basename) {
|
| 720 |
-
const buttons = {
|
| 721 |
-
svg: document.getElementById("btn-svg"),
|
| 722 |
-
png: document.getElementById("btn-png"),
|
| 723 |
-
pdf: document.getElementById("btn-pdf"),
|
| 724 |
-
};
|
| 725 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 726 |
-
|
| 727 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 728 |
-
function complain(format) {
|
| 729 |
-
const button = buttons[format];
|
| 730 |
-
if (!button) return;
|
| 731 |
-
const label = button.textContent;
|
| 732 |
-
button.textContent = "failed";
|
| 733 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 734 |
-
}
|
| 735 |
-
|
| 736 |
-
function run(format) {
|
| 737 |
-
const svg = figure();
|
| 738 |
-
const name = basename();
|
| 739 |
-
if (format === "svg") {
|
| 740 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 741 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 742 |
-
return;
|
| 743 |
-
}
|
| 744 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 745 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 746 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 747 |
-
if (format === "png") {
|
| 748 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 749 |
-
} else {
|
| 750 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 751 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 752 |
-
.catch(() => complain("pdf"));
|
| 753 |
-
}
|
| 754 |
-
}, () => complain(format));
|
| 755 |
-
}
|
| 756 |
-
|
| 757 |
-
for (const format of Object.keys(buttons)) {
|
| 758 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 759 |
-
}
|
| 760 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 761 |
-
window.addEventListener("message", ev => {
|
| 762 |
-
const d = ev.data;
|
| 763 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 764 |
-
});
|
| 765 |
-
}
|
| 766 |
-
|
| 767 |
-
// When embedded, report the content height so the host page can size the
|
| 768 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 769 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 770 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 771 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 772 |
-
// stops re-posting once the height settles.
|
| 773 |
-
let lastPostedHeight = 0;
|
| 774 |
-
function postHeight() {
|
| 775 |
-
if (window.parent === window) return;
|
| 776 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 777 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 778 |
-
lastPostedHeight = height;
|
| 779 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 780 |
-
}
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
const COLUMNS = CONFIG.columns;
|
| 784 |
-
const RANK_KEY = CONFIG.rankKey;
|
| 785 |
-
const colByKey = new Map(COLUMNS.map(c => [c.key, c]));
|
| 786 |
-
const VARIANTS = CONFIG.variants.filter(v => POINTS.some(p => p.variant === v));
|
| 787 |
-
|
| 788 |
-
// How a variant is written out. The short "Tuned + Ens." form is the internal key
|
| 789 |
-
// (the charts' colour and marker tables are keyed by it), but nothing on the page
|
| 790 |
-
// should show the abbreviation: the row tag uses the spelling the data and the
|
| 791 |
-
// app's cross-subset table use, and the toggle spells it out in full.
|
| 792 |
-
const VARIANT_TEXT = {
|
| 793 |
-
"Default": "default",
|
| 794 |
-
"Tuned": "tuned",
|
| 795 |
-
"Tuned + Ens.": "tuned + ensembled",
|
| 796 |
-
};
|
| 797 |
-
const VARIANT_BTN = { "Tuned + Ens.": "Tuned + Ensembled" };
|
| 798 |
-
const variantText = v => VARIANT_TEXT[v] || v;
|
| 799 |
-
const HAS_IMPUTED = POINTS.some(p => p.imputed);
|
| 800 |
-
|
| 801 |
-
const state = {
|
| 802 |
-
methods: new Set(POINTS.map(p => p.method)),
|
| 803 |
-
variants: new Set(VARIANTS),
|
| 804 |
-
columns: new Set(COLUMNS.filter(c => c.on !== false).map(c => c.key)),
|
| 805 |
-
imputed: true,
|
| 806 |
-
search: "",
|
| 807 |
-
sortKey: null,
|
| 808 |
-
sortAsc: false,
|
| 809 |
-
};
|
| 810 |
-
|
| 811 |
-
const tblwrap = document.getElementById("tblwrap");
|
| 812 |
-
const chipsBox = document.getElementById("chips");
|
| 813 |
-
const famChips = new Map();
|
| 814 |
-
const chipByMethod = new Map();
|
| 815 |
-
|
| 816 |
-
// ---------- heat shading ----------
|
| 817 |
-
// Green (best) through olive to red (worst), matching the website's
|
| 818 |
-
// cross-subset overview so a reader moving between them reads one scale.
|
| 819 |
-
const RAMP = [[0, [28, 120, 62]], [0.5, [138, 122, 36]], [1, [160, 58, 58]]];
|
| 820 |
-
function heatColor(frac) {
|
| 821 |
-
const f = Math.max(0, Math.min(1, frac));
|
| 822 |
-
for (let i = 0; i < RAMP.length - 1; i++) {
|
| 823 |
-
const [f0, c0] = RAMP[i], [f1, c1] = RAMP[i + 1];
|
| 824 |
-
if (f <= f1) {
|
| 825 |
-
const t = f1 === f0 ? 0 : (f - f0) / (f1 - f0);
|
| 826 |
-
const mix = c0.map((v, j) => Math.round(v + t * (c1[j] - v)));
|
| 827 |
-
return "rgb(" + mix.join(",") + ")";
|
| 828 |
-
}
|
| 829 |
-
}
|
| 830 |
-
return "rgb(" + RAMP[RAMP.length - 1][1].join(",") + ")";
|
| 831 |
-
}
|
| 832 |
-
// Runtimes span orders of magnitude; shading them linearly paints every model
|
| 833 |
-
// the same green and only the slowest one red, so those normalize in log space.
|
| 834 |
-
function scaleOf(col, v) { return col.logScale ? Math.log10(v) : v; }
|
| 835 |
-
function bounds(rows, col) {
|
| 836 |
-
const values = [];
|
| 837 |
-
for (const p of rows) {
|
| 838 |
-
const v = p[col.key];
|
| 839 |
-
if (v == null || !isFinite(v)) continue;
|
| 840 |
-
if (col.logScale && !(v > 0)) continue;
|
| 841 |
-
values.push(scaleOf(col, v));
|
| 842 |
-
}
|
| 843 |
-
if (values.length < 2) return null;
|
| 844 |
-
const lo = Math.min(...values), hi = Math.max(...values);
|
| 845 |
-
return hi > lo ? [lo, hi] : null;
|
| 846 |
-
}
|
| 847 |
-
|
| 848 |
-
// ---------- cells ----------
|
| 849 |
-
function nameCell(p) {
|
| 850 |
-
const ink = FAM_INK[p.family] || "var(--muted)";
|
| 851 |
-
let inner = escapeHtml(p.method);
|
| 852 |
-
if (p.variant) inner += ' <span class="variant-tag">(' + escapeHtml(variantText(p.variant)) + ")</span>";
|
| 853 |
-
if (p.verified) inner += ' <span class="verified" title="Verified implementation">✔️</span>';
|
| 854 |
-
if (p.imputed) {
|
| 855 |
-
const pct = isFinite(p.imputed_pct) ? fmtNum(p.imputed_pct, 0) + "% " : "";
|
| 856 |
-
inner += ' <span class="imp-mark" title="' + pct + 'imputed">‡</span>';
|
| 857 |
-
}
|
| 858 |
-
const body = p.url
|
| 859 |
-
? '<a href="' + escapeHtml(p.url) + '" target="_blank" rel="noopener" style="color:' + ink +
|
| 860 |
-
';font-weight:600;">' + inner + '<span class="link-icon">↗</span></a>'
|
| 861 |
-
: '<span style="color:' + ink + ';font-weight:600;">' + inner + "</span>";
|
| 862 |
-
return '<td class="name" data-export="' + escapeHtml(plainName(p)) + '">' + body + "</td>";
|
| 863 |
-
}
|
| 864 |
-
function plainName(p) {
|
| 865 |
-
return p.method + (p.variant ? " (" + p.variant + ")" : "");
|
| 866 |
-
}
|
| 867 |
-
function escapeHtml(text) {
|
| 868 |
-
return String(text == null ? "" : text).replace(/[&<>"']/g, c =>
|
| 869 |
-
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
| 870 |
-
}
|
| 871 |
-
|
| 872 |
-
// ---------- rows ----------
|
| 873 |
-
function visibleRows() {
|
| 874 |
-
const term = state.search.trim().toLowerCase();
|
| 875 |
-
return POINTS.filter(p => {
|
| 876 |
-
if (!state.methods.has(p.method)) return false;
|
| 877 |
-
if (p.variant && !state.variants.has(p.variant)) return false;
|
| 878 |
-
if (!state.imputed && p.imputed) return false;
|
| 879 |
-
if (term && !(p.method + " " + (p.variant || "") + " " + p.family).toLowerCase().includes(term)) return false;
|
| 880 |
-
return true;
|
| 881 |
-
});
|
| 882 |
-
}
|
| 883 |
-
function sortRows(rows) {
|
| 884 |
-
const out = rows.slice();
|
| 885 |
-
if (!state.sortKey) return out.sort((a, b) => a.position - b.position);
|
| 886 |
-
const col = colByKey.get(state.sortKey);
|
| 887 |
-
const sign = state.sortAsc ? 1 : -1;
|
| 888 |
-
const keyOf = p => {
|
| 889 |
-
const v = p[state.sortKey];
|
| 890 |
-
if (col && col.text) return String(v == null ? "" : v).toLowerCase();
|
| 891 |
-
return v == null || !isFinite(v) ? null : v;
|
| 892 |
-
};
|
| 893 |
-
return out.sort((a, b) => {
|
| 894 |
-
const ka = keyOf(a), kb = keyOf(b);
|
| 895 |
-
if (ka === null || kb === null) return ka === kb ? 0 : ka === null ? 1 : -1;
|
| 896 |
-
return ka < kb ? -sign : ka > kb ? sign : 0;
|
| 897 |
-
});
|
| 898 |
-
}
|
| 899 |
-
|
| 900 |
-
function activeColumns() {
|
| 901 |
-
return COLUMNS.filter(c => c.always || state.columns.has(c.key));
|
| 902 |
-
}
|
| 903 |
-
|
| 904 |
-
function render() {
|
| 905 |
-
const rows = sortRows(visibleRows());
|
| 906 |
-
const cols = activeColumns();
|
| 907 |
-
if (!rows.length) {
|
| 908 |
-
tblwrap.innerHTML = '<p class="lbt-empty">Nothing selected — turn a family or variant back on.</p>';
|
| 909 |
-
document.getElementById("caption").textContent = "";
|
| 910 |
-
postHeight();
|
| 911 |
-
return;
|
| 912 |
-
}
|
| 913 |
-
// No medals here: this table is the full ranking, so the position column
|
| 914 |
-
// already says who is where. They belong to the cross-subset overview.
|
| 915 |
-
const heat = new Map();
|
| 916 |
-
for (const col of cols) if (col.heatmap) heat.set(col.key, bounds(rows, col));
|
| 917 |
-
|
| 918 |
-
let html = '<table class="lbt"><thead><tr>';
|
| 919 |
-
for (const col of cols) {
|
| 920 |
-
const sorted = state.sortKey === col.key
|
| 921 |
-
? ' aria-sort="' + (state.sortAsc ? "ascending" : "descending") + '"' : "";
|
| 922 |
-
html += "<th" + sorted + ' data-key="' + col.key + '" title="' + escapeHtml(col.hint || col.label) +
|
| 923 |
-
'"><span class="lbl">' + escapeHtml(col.label) + "</span>" +
|
| 924 |
-
(col.key === "elo" ? ' <span class="ci">(95% CI)</span>' : "") + "</th>";
|
| 925 |
-
}
|
| 926 |
-
html += "</tr></thead><tbody>";
|
| 927 |
-
for (const p of rows) {
|
| 928 |
-
html += "<tr>";
|
| 929 |
-
for (const col of cols) {
|
| 930 |
-
if (col.key === "position") {
|
| 931 |
-
html += '<td class="pos num" data-sort="' + p.position + '">' + p.position + "</td>";
|
| 932 |
-
} else if (col.key === "family") {
|
| 933 |
-
const mark = FAM_VAR[p.family] || "var(--fam-baseline)";
|
| 934 |
-
html += '<td class="type" data-sort="' + escapeHtml(p.family) + '" data-export="' + escapeHtml(p.family) +
|
| 935 |
-
'"><span class="pill" style="background:color-mix(in srgb, ' + mark +
|
| 936 |
-
' 13%, transparent);color:' + (FAM_INK[p.family] || "var(--muted)") +
|
| 937 |
-
";border:1px solid color-mix(in srgb, " + mark + ' 40%, transparent);">' +
|
| 938 |
-
escapeHtml(p.family_symbol || "") + "</span></td>";
|
| 939 |
-
} else if (col.key === "model") {
|
| 940 |
-
html += nameCell(p);
|
| 941 |
-
} else {
|
| 942 |
-
html += valueCell(p, col, heat.get(col.key));
|
| 943 |
-
}
|
| 944 |
-
}
|
| 945 |
-
html += "</tr>";
|
| 946 |
-
}
|
| 947 |
-
tblwrap.innerHTML = html + "</tbody></table>";
|
| 948 |
-
for (const th of tblwrap.querySelectorAll("th")) {
|
| 949 |
-
th.addEventListener("click", () => sortBy(th.dataset.key));
|
| 950 |
-
}
|
| 951 |
-
document.getElementById("caption").textContent =
|
| 952 |
-
rows.length + (rows.length === 1 ? " row" : " rows") +
|
| 953 |
-
" · click a column header to sort, hover one for what it means" +
|
| 954 |
-
(heat.size ? " · green is better, red is worse, per column" : "") +
|
| 955 |
-
(HAS_IMPUTED ? " · ‡ marks a partly imputed score" : "");
|
| 956 |
-
postHeight();
|
| 957 |
-
}
|
| 958 |
-
|
| 959 |
-
function valueCell(p, col, span) {
|
| 960 |
-
const v = p[col.key];
|
| 961 |
-
if (v == null || (typeof v === "number" && !isFinite(v))) return '<td class="na">–</td>';
|
| 962 |
-
if (col.text) {
|
| 963 |
-
return '<td data-sort="' + escapeHtml(v) + '" data-export="' + escapeHtml(v) + '">' + escapeHtml(v) + "</td>";
|
| 964 |
-
}
|
| 965 |
-
let style = "";
|
| 966 |
-
if (span) {
|
| 967 |
-
let frac = (scaleOf(col, v) - span[0]) / (span[1] - span[0]);
|
| 968 |
-
if (!col.lowerBetter) frac = 1 - frac;
|
| 969 |
-
style = ' style="background:' + heatColor(frac) + ';color:#f7f7f7;"';
|
| 970 |
-
}
|
| 971 |
-
let text = fmtNum(v, col.decimals) + (col.suffix || "");
|
| 972 |
-
let ci = "";
|
| 973 |
-
if (col.key === "elo" && p.elo_ci) {
|
| 974 |
-
ci = ' <span class="ci">(' + escapeHtml(p.elo_ci) + ")</span>";
|
| 975 |
-
}
|
| 976 |
-
return '<td class="num" data-sort="' + v + '"' + (ci ? ' data-ci="' + escapeHtml(p.elo_ci) + '"' : "") +
|
| 977 |
-
style + ">" + text + ci + "</td>";
|
| 978 |
-
}
|
| 979 |
-
|
| 980 |
-
function sortBy(key) {
|
| 981 |
-
if (!key) return;
|
| 982 |
-
if (state.sortKey === key) state.sortAsc = !state.sortAsc;
|
| 983 |
-
else { state.sortKey = key; state.sortAsc = !!(colByKey.get(key) || {}).lowerBetter; }
|
| 984 |
-
render();
|
| 985 |
-
}
|
| 986 |
-
|
| 987 |
-
// ---------- chips (families and their methods) ----------
|
| 988 |
-
function familyMembers(fam) {
|
| 989 |
-
return [...new Set(POINTS.filter(p => p.family === fam).map(p => p.method))];
|
| 990 |
-
}
|
| 991 |
-
function methodRank(name) {
|
| 992 |
-
const col = colByKey.get(RANK_KEY);
|
| 993 |
-
const values = POINTS.filter(p => p.method === name && isFinite(p[RANK_KEY])).map(p => p[RANK_KEY]);
|
| 994 |
-
if (!values.length) return Infinity;
|
| 995 |
-
return col.lowerBetter ? Math.min(...values) : -Math.max(...values);
|
| 996 |
-
}
|
| 997 |
-
function buildChips() {
|
| 998 |
-
const head = document.createElement("div");
|
| 999 |
-
head.className = "chips-head";
|
| 1000 |
-
head.textContent = "Models shown — click to remove, click a family to toggle the whole group";
|
| 1001 |
-
chipsBox.appendChild(head);
|
| 1002 |
-
for (const fam of FAM_ORDER) {
|
| 1003 |
-
const members = familyMembers(fam);
|
| 1004 |
-
if (!members.length) continue;
|
| 1005 |
-
members.sort((a, b) => methodRank(a) - methodRank(b));
|
| 1006 |
-
const row = document.createElement("div");
|
| 1007 |
-
row.className = "chiprow";
|
| 1008 |
-
const famBtn = document.createElement("button");
|
| 1009 |
-
famBtn.className = "famchip";
|
| 1010 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1011 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1012 |
-
famBtn.title = "Toggle all " + members.length + " " + fam + " models";
|
| 1013 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1014 |
-
row.appendChild(famBtn);
|
| 1015 |
-
famChips.set(fam, famBtn);
|
| 1016 |
-
const set = document.createElement("div");
|
| 1017 |
-
set.className = "chipset";
|
| 1018 |
-
for (const name of members) {
|
| 1019 |
-
const imputed = POINTS.some(p => p.method === name && p.imputed);
|
| 1020 |
-
const b = document.createElement("button");
|
| 1021 |
-
b.className = "chip";
|
| 1022 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1023 |
-
b.innerHTML = '<span class="dot"></span><span>' + escapeHtml(name) + "</span>" +
|
| 1024 |
-
(imputed ? '<span class="imp-mark">‡</span>' : "");
|
| 1025 |
-
b.title = name + (imputed ? " — partially imputed" : "");
|
| 1026 |
-
b.addEventListener("click", () => toggleMethod(name));
|
| 1027 |
-
set.appendChild(b);
|
| 1028 |
-
chipByMethod.set(name, b);
|
| 1029 |
-
}
|
| 1030 |
-
row.appendChild(set);
|
| 1031 |
-
chipsBox.appendChild(row);
|
| 1032 |
-
}
|
| 1033 |
-
}
|
| 1034 |
-
function syncChips() {
|
| 1035 |
-
for (const [name, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.methods.has(name)));
|
| 1036 |
-
for (const [fam, b] of famChips) {
|
| 1037 |
-
b.setAttribute("aria-pressed", String(familyMembers(fam).every(m => state.methods.has(m))));
|
| 1038 |
-
}
|
| 1039 |
-
}
|
| 1040 |
-
function toggleMethod(name) {
|
| 1041 |
-
if (state.methods.has(name)) state.methods.delete(name); else state.methods.add(name);
|
| 1042 |
-
syncChips();
|
| 1043 |
-
render();
|
| 1044 |
-
}
|
| 1045 |
-
function toggleFamily(fam) {
|
| 1046 |
-
const members = familyMembers(fam);
|
| 1047 |
-
const allOn = members.every(m => state.methods.has(m));
|
| 1048 |
-
for (const m of members) { if (allOn) state.methods.delete(m); else state.methods.add(m); }
|
| 1049 |
-
syncChips();
|
| 1050 |
-
render();
|
| 1051 |
-
}
|
| 1052 |
-
|
| 1053 |
-
// ---------- variant / imputed / column toggles ----------
|
| 1054 |
-
const variantBtns = new Map();
|
| 1055 |
-
function buildVariantBtns() {
|
| 1056 |
-
const box = document.getElementById("variant-btns");
|
| 1057 |
-
for (const v of VARIANTS) {
|
| 1058 |
-
const b = document.createElement("button");
|
| 1059 |
-
b.className = "btn toggle";
|
| 1060 |
-
b.innerHTML = '<span class="swatch"></span>' + escapeHtml(VARIANT_BTN[v] || v);
|
| 1061 |
-
b.style.setProperty("--fam", VARIANT_VAR[v] || "var(--accent)");
|
| 1062 |
-
b.title = "Show or hide the " + variantText(v) + " results";
|
| 1063 |
-
b.addEventListener("click", () => {
|
| 1064 |
-
if (state.variants.has(v)) state.variants.delete(v); else state.variants.add(v);
|
| 1065 |
-
syncVariantBtns();
|
| 1066 |
-
render();
|
| 1067 |
-
});
|
| 1068 |
-
box.appendChild(b);
|
| 1069 |
-
variantBtns.set(v, b);
|
| 1070 |
-
}
|
| 1071 |
-
}
|
| 1072 |
-
function syncVariantBtns() {
|
| 1073 |
-
for (const [v, b] of variantBtns) b.setAttribute("aria-pressed", String(state.variants.has(v)));
|
| 1074 |
-
const imp = document.getElementById("btn-imputed");
|
| 1075 |
-
imp.hidden = !HAS_IMPUTED;
|
| 1076 |
-
imp.className = "btn toggle";
|
| 1077 |
-
imp.innerHTML = '<span class="swatch"></span>‡ Imputed';
|
| 1078 |
-
imp.setAttribute("aria-pressed", String(state.imputed));
|
| 1079 |
-
imp.style.setProperty("--fam", "var(--muted)");
|
| 1080 |
-
}
|
| 1081 |
-
function buildColumnBtns() {
|
| 1082 |
-
const box = document.getElementById("col-btns");
|
| 1083 |
-
for (const col of COLUMNS) {
|
| 1084 |
-
if (col.always) continue;
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "btn toggle";
|
| 1087 |
-
b.textContent = col.short || col.label;
|
| 1088 |
-
b.title = "Show or hide " + col.label;
|
| 1089 |
-
b.style.setProperty("--fam", "var(--accent)");
|
| 1090 |
-
b.addEventListener("click", () => {
|
| 1091 |
-
if (state.columns.has(col.key)) state.columns.delete(col.key); else state.columns.add(col.key);
|
| 1092 |
-
b.setAttribute("aria-pressed", String(state.columns.has(col.key)));
|
| 1093 |
-
render();
|
| 1094 |
-
});
|
| 1095 |
-
b.setAttribute("aria-pressed", String(state.columns.has(col.key)));
|
| 1096 |
-
box.appendChild(b);
|
| 1097 |
-
}
|
| 1098 |
-
}
|
| 1099 |
-
|
| 1100 |
-
// ---------- CSV ----------
|
| 1101 |
-
// Exports what the reader is looking at: the rows the filters left, the
|
| 1102 |
-
// columns they picked, in the order they sorted.
|
| 1103 |
-
function downloadCsv() {
|
| 1104 |
-
const cols = activeColumns();
|
| 1105 |
-
const rows = sortRows(visibleRows());
|
| 1106 |
-
const quote = v => '"' + String(v == null ? "" : v).replace(/"/g, '""') + '"';
|
| 1107 |
-
const head = [];
|
| 1108 |
-
for (const col of cols) {
|
| 1109 |
-
head.push(col.label);
|
| 1110 |
-
if (col.key === "elo" && rows.some(p => p.elo_ci)) head.push("Elo 95% CI");
|
| 1111 |
-
}
|
| 1112 |
-
const lines = [head.map(quote).join(",")];
|
| 1113 |
-
for (const p of rows) {
|
| 1114 |
-
const values = [];
|
| 1115 |
-
for (const col of cols) {
|
| 1116 |
-
if (col.key === "model") values.push(plainName(p));
|
| 1117 |
-
else values.push(p[col.key]);
|
| 1118 |
-
if (col.key === "elo" && rows.some(q => q.elo_ci)) values.push(p.elo_ci || "");
|
| 1119 |
-
}
|
| 1120 |
-
lines.push(values.map(quote).join(","));
|
| 1121 |
-
}
|
| 1122 |
-
const blob = new Blob([lines.join("\n") + "\n"], { type: "text/csv;charset=utf-8" });
|
| 1123 |
-
const url = URL.createObjectURL(blob);
|
| 1124 |
-
downloadUrl(url, slugify(CONFIG.title || document.title || "leaderboard") + ".csv");
|
| 1125 |
-
URL.revokeObjectURL(url);
|
| 1126 |
-
}
|
| 1127 |
-
|
| 1128 |
-
// ---------- boot ----------
|
| 1129 |
-
if (CONFIG.title) document.getElementById("title").textContent = CONFIG.title;
|
| 1130 |
-
document.getElementById("search").addEventListener("input", ev => {
|
| 1131 |
-
state.search = ev.target.value;
|
| 1132 |
-
render();
|
| 1133 |
-
});
|
| 1134 |
-
document.getElementById("btn-imputed").addEventListener("click", () => {
|
| 1135 |
-
state.imputed = !state.imputed;
|
| 1136 |
-
syncVariantBtns();
|
| 1137 |
-
render();
|
| 1138 |
-
});
|
| 1139 |
-
document.getElementById("btn-csv").addEventListener("click", downloadCsv);
|
| 1140 |
-
// Embedded, the host page puts its own CSV button in the panel header (next to
|
| 1141 |
-
// the title) and asks for the download over postMessage, the same way it drives
|
| 1142 |
-
// the figure exports. Standalone, this page needs its own button.
|
| 1143 |
-
if (window.parent !== window) {
|
| 1144 |
-
document.getElementById("btn-csv").hidden = true;
|
| 1145 |
-
window.addEventListener("message", ev => {
|
| 1146 |
-
if (ev.data && ev.data.type === "tabarena-leaderboard-csv") downloadCsv();
|
| 1147 |
-
});
|
| 1148 |
-
}
|
| 1149 |
-
// Opens with the controls: the filters are the point of this page, not chrome
|
| 1150 |
-
// around a figure.
|
| 1151 |
-
setUpPaperView(render, { openInPaper: false });
|
| 1152 |
-
buildVariantBtns();
|
| 1153 |
-
buildColumnBtns();
|
| 1154 |
-
buildChips();
|
| 1155 |
-
syncChips();
|
| 1156 |
-
syncVariantBtns();
|
| 1157 |
-
render();
|
| 1158 |
-
window.addEventListener("resize", postHeight);
|
| 1159 |
-
})();
|
| 1160 |
-
</script>
|
| 1161 |
-
</body>
|
| 1162 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/n_datasets_15
DELETED
|
File without changes
|
data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_front_explorer.html
DELETED
|
@@ -1,1230 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena Pareto explorer</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Two-column layout: controls + chips in a side panel, chart beside it.
|
| 269 |
-
``chips-right`` mirrors the columns. Wraps to stacked when narrow. */
|
| 270 |
-
.explorer-grid { display: flex; gap: 18px; align-items: flex-start; }
|
| 271 |
-
.explorer-grid.chips-right { flex-direction: row-reverse; }
|
| 272 |
-
.sidebox { flex: 0 0 330px; min-width: 250px; display: flex; flex-direction: column; gap: 10px; }
|
| 273 |
-
.mainbox { flex: 1 1 auto; min-width: 0; }
|
| 274 |
-
@media (max-width: 860px) {
|
| 275 |
-
.explorer-grid { flex-wrap: wrap; }
|
| 276 |
-
.sidebox { flex: 1 1 100%; }
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 280 |
-
.chartbox { position: relative; }
|
| 281 |
-
/* The chart is sized in device pixels by render() rather than scaled from a
|
| 282 |
-
viewBox: scaling stretched the type along with the plot, and a viewBox tall
|
| 283 |
-
enough to read made the whole panel own the screen. */
|
| 284 |
-
.chartbox svg { display: block; }
|
| 285 |
-
/* Chips scroll within the column so the panel height follows the chart. */
|
| 286 |
-
.sidebox .chips { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent; }
|
| 287 |
-
.sidebox .chips::-webkit-scrollbar { width: 9px; }
|
| 288 |
-
.sidebox .chips::-webkit-scrollbar-thumb {
|
| 289 |
-
background: var(--pt-muted); border-radius: 8px; border: 3px solid transparent; background-clip: content-box;
|
| 290 |
-
}
|
| 291 |
-
</style>
|
| 292 |
-
</head>
|
| 293 |
-
<body>
|
| 294 |
-
<div class="viewbar">
|
| 295 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 296 |
-
</div>
|
| 297 |
-
<p class="explorer-title" id="title"></p>
|
| 298 |
-
<div class="explorer-grid" id="grid">
|
| 299 |
-
<div class="sidebox">
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick" id="metricpick" hidden>Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<div class="btnrow">
|
| 305 |
-
<button class="btn" id="btn-front">Pareto front</button>
|
| 306 |
-
<button class="btn" id="btn-all">All</button>
|
| 307 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 308 |
-
</div>
|
| 309 |
-
<span class="hint">Click methods or family buttons to highlight · hover points for details</span>
|
| 310 |
-
</div>
|
| 311 |
-
<div class="chips" id="chips"></div>
|
| 312 |
-
</div>
|
| 313 |
-
<div class="mainbox">
|
| 314 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 315 |
-
<span class="hint">Export figure</span>
|
| 316 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 317 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 318 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 319 |
-
</div>
|
| 320 |
-
<!-- Legend above the chart so readers decode the marks before the data. -->
|
| 321 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 322 |
-
<div class="chartbox" id="chartbox">
|
| 323 |
-
<svg id="chart" role="img" aria-label="Pareto front explorer"></svg>
|
| 324 |
-
<div class="tooltip"></div>
|
| 325 |
-
</div>
|
| 326 |
-
</div>
|
| 327 |
-
</div>
|
| 328 |
-
<details class="datatable">
|
| 329 |
-
<summary>Data table</summary>
|
| 330 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 331 |
-
</details>
|
| 332 |
-
|
| 333 |
-
<script>
|
| 334 |
-
(function () {
|
| 335 |
-
"use strict";
|
| 336 |
-
const CONFIG = {"mode": "scatter", "title": null, "metrics": [{"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": ""}], "xAxes": [{"key": "x_infer", "label": "Inference time", "axisLabel": "Inference time per 1K samples (s), median \u2014 log scale", "short": "Inference (s/1K, median)"}], "chipsSide": "left"};
|
| 337 |
-
const POINTS = [{"method":"CatBoost","family":"Tree-based","x_infer":0.0102827644,"imp":9.0952095474,"elo":1575.9,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"CatBoost","family":"Tree-based","x_infer":0.0196975147,"imp":9.1399516875,"elo":1595.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"CatBoost","family":"Tree-based","x_infer":0.2485703935,"imp":8.9317687118,"elo":1610.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.0225370945,"imp":13.175735213,"elo":1418.1,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.0265970701,"imp":12.1456953066,"elo":1469.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.2967122121,"imp":11.6842157983,"elo":1517.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"EBM","family":"Tree-based","x_infer":0.0054230738,"imp":17.8697973966,"elo":1220.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"EBM","family":"Tree-based","x_infer":0.0061458745,"imp":16.4411619269,"elo":1265.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"EBM","family":"Tree-based","x_infer":0.0851920607,"imp":15.5948171656,"elo":1325.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.0733045085,"imp":22.7894839202,"elo":976.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.0153132761,"imp":16.3030865094,"elo":1173.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.1990111469,"imp":15.3042054388,"elo":1216.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"FastaiMLP","family":"Neural Network","x_infer":0.1111866275,"imp":22.8643090483,"elo":1031.1,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"FastaiMLP","family":"Neural Network","x_infer":0.1141755222,"imp":19.2937753734,"elo":1101.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"FastaiMLP","family":"Neural Network","x_infer":1.6581625315,"imp":17.1916474397,"elo":1200.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"LightGBM","family":"Tree-based","x_infer":0.0447579838,"imp":14.819832856,"elo":1258.1,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"LightGBM","family":"Tree-based","x_infer":0.1322357268,"imp":11.6033224024,"elo":1506.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"LightGBM","family":"Tree-based","x_infer":2.638673831,"imp":10.4658385154,"elo":1588.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"LimiX","family":"Foundation Model","x_infer":5.4085730775,"imp":16.4177044552,"elo":1279.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ModernNCA","family":"Neural Network","x_infer":0.2496013467,"imp":14.3302915146,"elo":1297.8,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ModernNCA","family":"Neural Network","x_infer":0.3490410688,"imp":11.2147479695,"elo":1472.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ModernNCA","family":"Neural Network","x_infer":6.0133340655,"imp":9.0700293864,"elo":1614.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.0149545776,"imp":29.4235354386,"elo":900.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.1995710638,"imp":22.7471582873,"elo":1059.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.5149235805,"imp":21.6330567052,"elo":1109.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RandomForest","family":"Tree-based","x_infer":0.020899149,"imp":21.1973502954,"elo":1000.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RandomForest","family":"Tree-based","x_infer":0.0243850814,"imp":15.7438782463,"elo":1214.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RandomForest","family":"Tree-based","x_infer":0.3407391303,"imp":15.0995978866,"elo":1244.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RealMLP","family":"Neural Network","x_infer":0.234981848,"imp":15.0910499881,"elo":1271.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RealMLP","family":"Neural Network","x_infer":0.0807033173,"imp":10.103937795,"elo":1533.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RealMLP","family":"Neural Network","x_infer":1.6746674551,"imp":8.9170097602,"elo":1625.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":0.6449695981,"imp":10.077321119,"elo":1530.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":1.3859818406,"imp":9.2178209823,"elo":1600.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":11.7359861516,"imp":8.5761380952,"elo":1645.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"SAP-RPT-OSS","family":"Foundation Model","x_infer":10.4162023366,"imp":16.9330805211,"elo":1200.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabDPT","family":"Foundation Model","x_infer":43.7378122226,"imp":15.3106058247,"elo":1331.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabDPT","family":"Foundation Model","x_infer":42.6414441586,"imp":12.6616447819,"elo":1403.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabDPT","family":"Foundation Model","x_infer":444.5439481393,"imp":10.2874153003,"elo":1522.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabDPT-Turbo","family":"Foundation Model","x_infer":0.1795394575,"imp":10.8085465808,"elo":1526.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabFM","family":"Foundation Model","x_infer":13.1188916889,"imp":2.6827874305,"elo":1985.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabICLv2","family":"Foundation Model","x_infer":0.1186281919,"imp":6.8505424386,"elo":1697.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabM","family":"Neural Network","x_infer":0.0470610966,"imp":13.9816848431,"elo":1325.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabM","family":"Neural Network","x_infer":0.0538978015,"imp":11.0894895039,"elo":1480.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabM","family":"Neural Network","x_infer":0.5790353938,"imp":10.2538835957,"elo":1543.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabPFN-2.6","family":"Foundation Model","x_infer":0.7008750147,"imp":7.8460750331,"elo":1722.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabPFN-3","family":"Foundation Model","x_infer":0.2147265792,"imp":5.8782765424,"elo":1793.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabSTAR","family":"Foundation Model","x_infer":1.9637818715,"imp":30.6853633341,"elo":847.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabSTAR","family":"Foundation Model","x_infer":1.723789106,"imp":25.807196939,"elo":987.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabSTAR","family":"Foundation Model","x_infer":5.282666633,"imp":25.7806935994,"elo":986.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabSwift","family":"Foundation Model","x_infer":0.1271670825,"imp":13.3366678662,"elo":1344.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TorchMLP","family":"Neural Network","x_infer":0.0388490278,"imp":18.1452782924,"elo":1126.1,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TorchMLP","family":"Neural Network","x_infer":0.050592863,"imp":14.1135657835,"elo":1272.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TorchMLP","family":"Neural Network","x_infer":1.0691781292,"imp":12.4495254577,"elo":1376.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"XGBoost","family":"Tree-based","x_infer":0.0534163689,"imp":12.9074172378,"elo":1371.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"XGBoost","family":"Tree-based","x_infer":0.0664942176,"imp":11.1023313966,"elo":1501.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"XGBoost","family":"Tree-based","x_infer":0.5626253891,"imp":10.5460036421,"elo":1548.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"iLTM","family":"Foundation Model","x_infer":9.6204056883,"imp":18.4877413347,"elo":1179.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"iLTM","family":"Foundation Model","x_infer":10.8813375711,"imp":12.1121479202,"elo":1422.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"iLTM","family":"Foundation Model","x_infer":65.1951531214,"imp":10.2205385819,"elo":1558.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"xRFM","family":"Other","x_infer":0.1448756257,"imp":25.9796305322,"elo":1046.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"xRFM","family":"Other","x_infer":0.0599221336,"imp":13.9821871779,"elo":1373.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"xRFM","family":"Other","x_infer":0.9511369135,"imp":12.4822741841,"elo":1423.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."}];
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 341 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 342 |
-
// already share a color, and each holds only a handful of methods.
|
| 343 |
-
const FAM_MERGED = "Baseline / Other";
|
| 344 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 345 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 346 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 347 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 348 |
-
|
| 349 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 350 |
-
const FAM_VAR = {
|
| 351 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 352 |
-
"Tree-based": "var(--fam-tree)",
|
| 353 |
-
"Neural Network": "var(--fam-nn)",
|
| 354 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 355 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 356 |
-
};
|
| 357 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 358 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 359 |
-
// that chip carries both symbols.
|
| 360 |
-
const FAM_SYMBOL = {
|
| 361 |
-
"Foundation Model": "🧠⚡",
|
| 362 |
-
"Tree-based": "🌳",
|
| 363 |
-
"Neural Network": "🧠🔁",
|
| 364 |
-
"Reference Pipeline": "📊",
|
| 365 |
-
[FAM_MERGED]: "📏 ❓",
|
| 366 |
-
};
|
| 367 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 368 |
-
const VARIANT_VAR = {
|
| 369 |
-
"Default": "var(--var-default)",
|
| 370 |
-
"Tuned": "var(--var-tuned)",
|
| 371 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 372 |
-
};
|
| 373 |
-
|
| 374 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 375 |
-
function famChipLabel(family, count) {
|
| 376 |
-
const symbol = FAM_SYMBOL[family];
|
| 377 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 378 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 379 |
-
}
|
| 380 |
-
|
| 381 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 382 |
-
const FAM_INK = {
|
| 383 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 384 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 385 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 386 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 387 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 388 |
-
};
|
| 389 |
-
|
| 390 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 391 |
-
function el(name, attrs, parent) {
|
| 392 |
-
const node = document.createElementNS(NS, name);
|
| 393 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 394 |
-
if (parent) parent.appendChild(node);
|
| 395 |
-
return node;
|
| 396 |
-
}
|
| 397 |
-
|
| 398 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 399 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 400 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 401 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 402 |
-
function fmtNum(v, decimals) {
|
| 403 |
-
if (v == null || !isFinite(v)) return "—";
|
| 404 |
-
return v.toFixed(decimals);
|
| 405 |
-
}
|
| 406 |
-
|
| 407 |
-
function fmtMetric(metric, v) {
|
| 408 |
-
if (v == null || !isFinite(v)) return "—";
|
| 409 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 410 |
-
}
|
| 411 |
-
|
| 412 |
-
function fmtTime(v) {
|
| 413 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 414 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 415 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 416 |
-
return fmtNum(v, 3) + " s";
|
| 417 |
-
}
|
| 418 |
-
|
| 419 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 420 |
-
function niceStep(raw) {
|
| 421 |
-
if (!(raw > 0)) return 1;
|
| 422 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 423 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 424 |
-
if (mag * m >= raw) return mag * m;
|
| 425 |
-
}
|
| 426 |
-
return mag * 10;
|
| 427 |
-
}
|
| 428 |
-
|
| 429 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 430 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 431 |
-
function ticks(min, max, target) {
|
| 432 |
-
const step = niceStep((max - min) / target);
|
| 433 |
-
const first = Math.ceil(min / step);
|
| 434 |
-
const out = [];
|
| 435 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 436 |
-
return out.length ? out : [min];
|
| 437 |
-
}
|
| 438 |
-
|
| 439 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 440 |
-
function makeTooltip(box) {
|
| 441 |
-
const node = box.querySelector(".tooltip");
|
| 442 |
-
return {
|
| 443 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 444 |
-
move(ev) {
|
| 445 |
-
const r = box.getBoundingClientRect();
|
| 446 |
-
let tx = ev.clientX - r.left + 14;
|
| 447 |
-
const ty = ev.clientY - r.top + 12;
|
| 448 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 449 |
-
node.style.left = tx + "px";
|
| 450 |
-
node.style.top = ty + "px";
|
| 451 |
-
},
|
| 452 |
-
hide() { node.style.display = "none"; },
|
| 453 |
-
};
|
| 454 |
-
}
|
| 455 |
-
|
| 456 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 457 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 458 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 459 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 460 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 461 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 462 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 463 |
-
function setUpPaperView(afterToggle, options) {
|
| 464 |
-
const opts = options || {};
|
| 465 |
-
const root = document.documentElement;
|
| 466 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 467 |
-
const btn = document.getElementById("btn-paper");
|
| 468 |
-
const embedded = window.parent !== window;
|
| 469 |
-
|
| 470 |
-
function setPaper(on) {
|
| 471 |
-
document.body.classList.toggle("paper", on);
|
| 472 |
-
if (on) {
|
| 473 |
-
hostTheme = root.getAttribute("data-theme");
|
| 474 |
-
root.setAttribute("data-theme", "light");
|
| 475 |
-
} else if (hostTheme) {
|
| 476 |
-
root.setAttribute("data-theme", hostTheme);
|
| 477 |
-
} else {
|
| 478 |
-
root.removeAttribute("data-theme");
|
| 479 |
-
}
|
| 480 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 481 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 482 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 483 |
-
postHeight();
|
| 484 |
-
}
|
| 485 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 486 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 487 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 488 |
-
// shareable single file) this page needs its own.
|
| 489 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 490 |
-
window.addEventListener("message", ev => {
|
| 491 |
-
const d = ev.data;
|
| 492 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 493 |
-
});
|
| 494 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 495 |
-
// key press, so its label would fall out of step with the frame.
|
| 496 |
-
if (!embedded) {
|
| 497 |
-
document.addEventListener("keydown", ev => {
|
| 498 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 499 |
-
});
|
| 500 |
-
}
|
| 501 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 502 |
-
}
|
| 503 |
-
|
| 504 |
-
// --- Figure export ---------------------------------------------------------
|
| 505 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 506 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 507 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 508 |
-
// the legend is HTML rather than part of the SVG.
|
| 509 |
-
|
| 510 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 511 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 512 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 513 |
-
// break the PNG path.
|
| 514 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 515 |
-
// once the node leaves this document.
|
| 516 |
-
function resolveVars(root, resolve) {
|
| 517 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 518 |
-
for (const attr of ["fill", "stroke"]) {
|
| 519 |
-
const value = node.getAttribute(attr);
|
| 520 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 521 |
-
}
|
| 522 |
-
}
|
| 523 |
-
}
|
| 524 |
-
|
| 525 |
-
function legendToSvg(container, resolve) {
|
| 526 |
-
const base = container.getBoundingClientRect();
|
| 527 |
-
const group = document.createElementNS(NS, "g");
|
| 528 |
-
let height = 0;
|
| 529 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 530 |
-
const box = item.getBoundingClientRect();
|
| 531 |
-
if (!box.width) continue;
|
| 532 |
-
height = Math.max(height, box.bottom - base.top);
|
| 533 |
-
let textLeft = box.left - base.left;
|
| 534 |
-
const glyph = item.querySelector("svg");
|
| 535 |
-
if (glyph) {
|
| 536 |
-
const gbox = glyph.getBoundingClientRect();
|
| 537 |
-
const wrap = el("g", {
|
| 538 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 539 |
-
}, group);
|
| 540 |
-
const glyphClone = glyph.cloneNode(true);
|
| 541 |
-
resolveVars(glyphClone, resolve);
|
| 542 |
-
wrap.appendChild(glyphClone);
|
| 543 |
-
textLeft = gbox.right - base.left + 5;
|
| 544 |
-
}
|
| 545 |
-
const label = item.textContent.trim();
|
| 546 |
-
if (!label) continue;
|
| 547 |
-
const colored = item.querySelector("[style*='color']");
|
| 548 |
-
const text = el("text", {
|
| 549 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 550 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 551 |
-
}, group);
|
| 552 |
-
text.textContent = label;
|
| 553 |
-
}
|
| 554 |
-
return { group, height: Math.ceil(height) };
|
| 555 |
-
}
|
| 556 |
-
|
| 557 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 558 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 559 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 560 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 561 |
-
const resolve = value => String(value).replace(
|
| 562 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 563 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 564 |
-
|
| 565 |
-
let chartW = 0, chartH = 0;
|
| 566 |
-
for (const part of parts) {
|
| 567 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 568 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 569 |
-
}
|
| 570 |
-
|
| 571 |
-
const out = document.createElementNS(NS, "svg");
|
| 572 |
-
out.setAttribute("xmlns", NS);
|
| 573 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 574 |
-
let top = pad;
|
| 575 |
-
const later = []; // built after the width is known
|
| 576 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 577 |
-
if (legend && legend.height) {
|
| 578 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 579 |
-
later.push(() => out.appendChild(legend.group));
|
| 580 |
-
top += legend.height + 8;
|
| 581 |
-
}
|
| 582 |
-
|
| 583 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 584 |
-
const height = top + chartH + pad;
|
| 585 |
-
out.setAttribute("width", Math.ceil(width));
|
| 586 |
-
out.setAttribute("height", Math.ceil(height));
|
| 587 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 588 |
-
for (const build of later) build();
|
| 589 |
-
|
| 590 |
-
for (const part of parts) {
|
| 591 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 592 |
-
const clone = part.svg.cloneNode(true);
|
| 593 |
-
resolveVars(clone, resolve);
|
| 594 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 595 |
-
}
|
| 596 |
-
return out;
|
| 597 |
-
}
|
| 598 |
-
|
| 599 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 600 |
-
function slugify(text) {
|
| 601 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 602 |
-
}
|
| 603 |
-
|
| 604 |
-
function downloadUrl(url, filename) {
|
| 605 |
-
const a = document.createElement("a");
|
| 606 |
-
a.href = url;
|
| 607 |
-
a.download = filename;
|
| 608 |
-
document.body.appendChild(a);
|
| 609 |
-
a.click();
|
| 610 |
-
a.remove();
|
| 611 |
-
}
|
| 612 |
-
|
| 613 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 614 |
-
function rasterize(svg, scale, done, fail) {
|
| 615 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 616 |
-
const img = new Image();
|
| 617 |
-
img.onload = () => {
|
| 618 |
-
const canvas = document.createElement("canvas");
|
| 619 |
-
canvas.width = Math.round(width * scale);
|
| 620 |
-
canvas.height = Math.round(height * scale);
|
| 621 |
-
const ctx = canvas.getContext("2d");
|
| 622 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 623 |
-
ctx.drawImage(img, 0, 0);
|
| 624 |
-
done(canvas, width, height);
|
| 625 |
-
};
|
| 626 |
-
img.onerror = fail;
|
| 627 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 628 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 629 |
-
}
|
| 630 |
-
|
| 631 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 632 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 633 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 634 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 635 |
-
// and the pixels land at 96*scale dpi.
|
| 636 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 637 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 638 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 639 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 640 |
-
rgb[j] = pixels[i];
|
| 641 |
-
rgb[j + 1] = pixels[i + 1];
|
| 642 |
-
rgb[j + 2] = pixels[i + 2];
|
| 643 |
-
}
|
| 644 |
-
const deflated = new Uint8Array(await new Response(
|
| 645 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 646 |
-
|
| 647 |
-
const encoder = new TextEncoder();
|
| 648 |
-
const chunks = [];
|
| 649 |
-
const offsets = [];
|
| 650 |
-
let cursor = 0;
|
| 651 |
-
const put = data => {
|
| 652 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 653 |
-
chunks.push(bytes);
|
| 654 |
-
cursor += bytes.length;
|
| 655 |
-
};
|
| 656 |
-
const object = (id, body, stream) => {
|
| 657 |
-
offsets[id] = cursor;
|
| 658 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 659 |
-
if (stream) {
|
| 660 |
-
put("stream\n");
|
| 661 |
-
put(stream);
|
| 662 |
-
put("\nendstream\n");
|
| 663 |
-
}
|
| 664 |
-
put("endobj\n");
|
| 665 |
-
};
|
| 666 |
-
|
| 667 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 668 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 669 |
-
put("%PDF-1.4\n");
|
| 670 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 671 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 672 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 673 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 674 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 675 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 676 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 677 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 678 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 679 |
-
|
| 680 |
-
const xref = cursor;
|
| 681 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 682 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 683 |
-
put(table);
|
| 684 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 685 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 686 |
-
}
|
| 687 |
-
|
| 688 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 689 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 690 |
-
function setUpExport(getParts, basename) {
|
| 691 |
-
const buttons = {
|
| 692 |
-
svg: document.getElementById("btn-svg"),
|
| 693 |
-
png: document.getElementById("btn-png"),
|
| 694 |
-
pdf: document.getElementById("btn-pdf"),
|
| 695 |
-
};
|
| 696 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 697 |
-
|
| 698 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 699 |
-
function complain(format) {
|
| 700 |
-
const button = buttons[format];
|
| 701 |
-
if (!button) return;
|
| 702 |
-
const label = button.textContent;
|
| 703 |
-
button.textContent = "failed";
|
| 704 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 705 |
-
}
|
| 706 |
-
|
| 707 |
-
function run(format) {
|
| 708 |
-
const svg = figure();
|
| 709 |
-
const name = basename();
|
| 710 |
-
if (format === "svg") {
|
| 711 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 712 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 713 |
-
return;
|
| 714 |
-
}
|
| 715 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 716 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 717 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 718 |
-
if (format === "png") {
|
| 719 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 720 |
-
} else {
|
| 721 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 722 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 723 |
-
.catch(() => complain("pdf"));
|
| 724 |
-
}
|
| 725 |
-
}, () => complain(format));
|
| 726 |
-
}
|
| 727 |
-
|
| 728 |
-
for (const format of Object.keys(buttons)) {
|
| 729 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 730 |
-
}
|
| 731 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 732 |
-
window.addEventListener("message", ev => {
|
| 733 |
-
const d = ev.data;
|
| 734 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 735 |
-
});
|
| 736 |
-
}
|
| 737 |
-
|
| 738 |
-
// When embedded, report the content height so the host page can size the
|
| 739 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 740 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 741 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 742 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 743 |
-
// stops re-posting once the height settles.
|
| 744 |
-
let lastPostedHeight = 0;
|
| 745 |
-
function postHeight() {
|
| 746 |
-
if (window.parent === window) return;
|
| 747 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 748 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 749 |
-
lastPostedHeight = height;
|
| 750 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 751 |
-
}
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
const TRAJECTORY = CONFIG.mode === "trajectory";
|
| 755 |
-
|
| 756 |
-
const titleEl = document.getElementById("title");
|
| 757 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 758 |
-
|
| 759 |
-
// Column order: chips/controls left of the chart, or mirrored.
|
| 760 |
-
document.getElementById("grid").classList.add(CONFIG.chipsSide === "right" ? "chips-right" : "chips-left");
|
| 761 |
-
|
| 762 |
-
const svg = document.getElementById("chart");
|
| 763 |
-
const box = document.getElementById("chartbox");
|
| 764 |
-
const chipsBox = document.getElementById("chips");
|
| 765 |
-
const controlsBox = document.querySelector(".controls");
|
| 766 |
-
const tip = makeTooltip(box);
|
| 767 |
-
|
| 768 |
-
// Marker glyph per variant at (cx, cy); trajectories use circles everywhere.
|
| 769 |
-
function drawMark(parent, cx, cy, variant, color, size, opacity, dataM, whiteStroke) {
|
| 770 |
-
const common = { opacity: opacity, "data-m": dataM };
|
| 771 |
-
let node;
|
| 772 |
-
if (TRAJECTORY || variant === "Default" || !variant) {
|
| 773 |
-
node = el("circle", { ...common, cx, cy, r: size, fill: color }, parent);
|
| 774 |
-
} else if (variant === "Tuned") {
|
| 775 |
-
const s = size * 1.75;
|
| 776 |
-
node = el("rect", { ...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1.5, fill: color }, parent);
|
| 777 |
-
} else if (variant === "Tuned + Ens.") {
|
| 778 |
-
const d = size * 0.95;
|
| 779 |
-
node = el("path", {
|
| 780 |
-
...common,
|
| 781 |
-
d: `M${cx - d},${cy - d} L${cx + d},${cy + d} M${cx - d},${cy + d} L${cx + d},${cy - d}`,
|
| 782 |
-
stroke: color, "stroke-width": size * 0.62, fill: "none", "stroke-linecap": "round",
|
| 783 |
-
}, parent);
|
| 784 |
-
} else {
|
| 785 |
-
// Any other variant (e.g. "Baseline", holdout types): diamond.
|
| 786 |
-
const s = size * 1.45;
|
| 787 |
-
node = el("rect", {
|
| 788 |
-
...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1,
|
| 789 |
-
fill: color, transform: `rotate(45 ${cx} ${cy})`,
|
| 790 |
-
}, parent);
|
| 791 |
-
}
|
| 792 |
-
if (whiteStroke && variant !== "Tuned + Ens.") {
|
| 793 |
-
node.setAttribute("stroke", "var(--card)");
|
| 794 |
-
node.setAttribute("stroke-width", "1");
|
| 795 |
-
}
|
| 796 |
-
return node;
|
| 797 |
-
}
|
| 798 |
-
|
| 799 |
-
function drawImputedRing(parent, cx, cy, size, color, opacity, dataM) {
|
| 800 |
-
el("circle", {
|
| 801 |
-
cx, cy, r: size + 4.5, fill: "none", stroke: color, "stroke-width": 1.4,
|
| 802 |
-
"stroke-dasharray": "3 2.5", opacity: opacity, "data-m": dataM,
|
| 803 |
-
}, parent);
|
| 804 |
-
}
|
| 805 |
-
|
| 806 |
-
// Fat green arrow pointing into the optimal corner (mirrors the static
|
| 807 |
-
// figures' "Optimal" arrow so both read the same way).
|
| 808 |
-
function drawOptimalArrow(parent, lowerBetter, M, W, H) {
|
| 809 |
-
const cornerY = lowerBetter ? H - M.b - 12 : M.t + 12;
|
| 810 |
-
const tailY = lowerBetter ? H - M.b - 64 : M.t + 64;
|
| 811 |
-
const cx = M.l + 12, tx = M.l + 64;
|
| 812 |
-
const dx = cx - tx, dy = cornerY - tailY;
|
| 813 |
-
const len = Math.hypot(dx, dy);
|
| 814 |
-
const ux = dx / len, uy = dy / len;
|
| 815 |
-
const headLen = 16;
|
| 816 |
-
const bx = cx - ux * headLen, by = cornerY - uy * headLen; // head base center
|
| 817 |
-
// line stops at the head base
|
| 818 |
-
el("line", {
|
| 819 |
-
x1: tx, y1: tailY, x2: bx, y2: by,
|
| 820 |
-
stroke: "var(--optimal)", "stroke-width": 13, "stroke-linecap": "round", opacity: 0.92,
|
| 821 |
-
}, parent);
|
| 822 |
-
const px = -uy, py = ux; // perpendicular
|
| 823 |
-
el("polygon", {
|
| 824 |
-
points: `${cx},${cornerY} ${bx + px * 11},${by + py * 11} ${bx - px * 11},${by - py * 11}`,
|
| 825 |
-
fill: "var(--optimal)", opacity: 0.92,
|
| 826 |
-
}, parent);
|
| 827 |
-
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
| 828 |
-
if (angle > 90 || angle < -90) angle += 180;
|
| 829 |
-
const mx = (tx + bx) / 2, my = (tailY + by) / 2;
|
| 830 |
-
const t = el("text", {
|
| 831 |
-
x: mx, y: my, "text-anchor": "middle", "dominant-baseline": "middle",
|
| 832 |
-
"font-size": 10.5, "font-weight": 700, fill: "#ffffff",
|
| 833 |
-
transform: `rotate(${angle} ${mx} ${my})`,
|
| 834 |
-
}, parent);
|
| 835 |
-
t.textContent = "Optimal";
|
| 836 |
-
}
|
| 837 |
-
|
| 838 |
-
// ---------- data ----------
|
| 839 |
-
const byMethod = new Map();
|
| 840 |
-
for (const p of POINTS) {
|
| 841 |
-
if (!byMethod.has(p.method)) byMethod.set(p.method, []);
|
| 842 |
-
byMethod.get(p.method).push(p); // insertion order = builder's point order
|
| 843 |
-
}
|
| 844 |
-
|
| 845 |
-
const METRICS = CONFIG.metrics;
|
| 846 |
-
let metricKey = METRICS[0].key;
|
| 847 |
-
const metricByKey = {};
|
| 848 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 849 |
-
|
| 850 |
-
// Single time axis per explorer (the scatter ships inference time, the
|
| 851 |
-
// trajectories train time).
|
| 852 |
-
const X_AXIS = CONFIG.xAxes[0];
|
| 853 |
-
const xKey = X_AXIS.key;
|
| 854 |
-
|
| 855 |
-
function mval(p, metric) { return p[metric.key]; }
|
| 856 |
-
|
| 857 |
-
function computeFront(metric) {
|
| 858 |
-
const xk = xKey;
|
| 859 |
-
const pts = [...POINTS].sort((a, b) =>
|
| 860 |
-
a[xk] - b[xk] || (metric.lowerBetter ? mval(a, metric) - mval(b, metric) : mval(b, metric) - mval(a, metric)));
|
| 861 |
-
const verts = [];
|
| 862 |
-
const methods = new Set();
|
| 863 |
-
let best = null;
|
| 864 |
-
for (const p of pts) {
|
| 865 |
-
const v = mval(p, metric);
|
| 866 |
-
if (best === null || (metric.lowerBetter ? v < best : v > best)) {
|
| 867 |
-
if (best !== null) verts.push([p[xk], best]);
|
| 868 |
-
verts.push([p[xk], v]);
|
| 869 |
-
best = v;
|
| 870 |
-
methods.add(p.method);
|
| 871 |
-
}
|
| 872 |
-
}
|
| 873 |
-
return { verts, methods };
|
| 874 |
-
}
|
| 875 |
-
|
| 876 |
-
const state = { active: new Set(computeFront(metricByKey[metricKey]).methods) };
|
| 877 |
-
|
| 878 |
-
// ---------- chart ----------
|
| 879 |
-
// A flat, fixed-height plot: two of these panels then fit on one screen.
|
| 880 |
-
const CHART_H = 400;
|
| 881 |
-
const M = { l: 62, r: 18, t: 14, b: 52 };
|
| 882 |
-
|
| 883 |
-
function render() {
|
| 884 |
-
const metric = metricByKey[metricKey];
|
| 885 |
-
svg.textContent = "";
|
| 886 |
-
const W = Math.max(360, Math.round(box.clientWidth));
|
| 887 |
-
const H = CHART_H;
|
| 888 |
-
svg.setAttribute("width", W);
|
| 889 |
-
svg.setAttribute("height", H);
|
| 890 |
-
// Keep the chip list from outgrowing the chart beside it.
|
| 891 |
-
chipsBox.style.maxHeight = Math.max(170, H - controlsBox.offsetHeight + 20) + "px";
|
| 892 |
-
|
| 893 |
-
// x scale (log)
|
| 894 |
-
const xsAll = POINTS.map(p => p[xKey]);
|
| 895 |
-
const xmin = Math.min(...xsAll) * 0.65, xmax = Math.max(...xsAll) * 1.6;
|
| 896 |
-
const lx0 = Math.log10(xmin), lx1 = Math.log10(xmax);
|
| 897 |
-
const X = v => M.l + (Math.log10(v) - lx0) / (lx1 - lx0) * (W - M.l - M.r);
|
| 898 |
-
|
| 899 |
-
const vals = POINTS.map(p => mval(p, metric));
|
| 900 |
-
let y0, y1;
|
| 901 |
-
if (metric.fromZero) {
|
| 902 |
-
y0 = 0; y1 = Math.max(...vals) * 1.07;
|
| 903 |
-
} else {
|
| 904 |
-
const pad = (Math.max(...vals) - Math.min(...vals)) * 0.07;
|
| 905 |
-
y0 = Math.min(...vals) - pad; y1 = Math.max(...vals) + pad;
|
| 906 |
-
}
|
| 907 |
-
const Y = v => M.t + (1 - (v - y0) / (y1 - y0)) * (H - M.t - M.b);
|
| 908 |
-
|
| 909 |
-
// grid + axes
|
| 910 |
-
const grid = el("g", {}, svg);
|
| 911 |
-
for (let e = Math.ceil(lx0); Math.pow(10, e) < xmax; e++) {
|
| 912 |
-
const gx = X(Math.pow(10, e));
|
| 913 |
-
el("line", { x1: gx, y1: M.t, x2: gx, y2: H - M.b, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 914 |
-
const lbl = fmtNum(Math.pow(10, e), e >= 0 ? 0 : -e);
|
| 915 |
-
el("text", { x: gx, y: H - M.b + 20, "text-anchor": "middle", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 916 |
-
.textContent = lbl;
|
| 917 |
-
}
|
| 918 |
-
for (const yv of ticks(y0, y1, 6)) {
|
| 919 |
-
const gy = Y(yv);
|
| 920 |
-
el("line", { x1: M.l, y1: gy, x2: W - M.r, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 921 |
-
el("text", { x: M.l - 8, y: gy + 4, "text-anchor": "end", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 922 |
-
.textContent = fmtNum(yv, Number.isInteger(yv) ? 0 : metric.decimals);
|
| 923 |
-
}
|
| 924 |
-
el("rect", { x: M.l, y: M.t, width: W - M.l - M.r, height: H - M.t - M.b, fill: "none", stroke: "var(--line)" }, grid);
|
| 925 |
-
el("text", {
|
| 926 |
-
x: (M.l + W - M.r) / 2, y: H - 10, "text-anchor": "middle", "font-size": 14,
|
| 927 |
-
"font-weight": 650, fill: "var(--ink)",
|
| 928 |
-
}, grid).textContent = X_AXIS.axisLabel;
|
| 929 |
-
el("text", {
|
| 930 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": 14, "font-weight": 650, fill: "var(--ink)",
|
| 931 |
-
transform: `translate(16 ${(M.t + H - M.b) / 2}) rotate(-90)`,
|
| 932 |
-
}, grid).textContent = metric.axisLabel;
|
| 933 |
-
|
| 934 |
-
drawOptimalArrow(grid, metric.lowerBetter, M, W, H);
|
| 935 |
-
|
| 936 |
-
// pareto front (always shown)
|
| 937 |
-
const front = computeFront(metric);
|
| 938 |
-
const fv = front.verts;
|
| 939 |
-
if (fv.length) {
|
| 940 |
-
let d = `M${X(fv[0][0])},${metric.lowerBetter ? M.t : H - M.b}`;
|
| 941 |
-
for (const [fx, fy] of fv) d += ` L${X(fx)},${Y(fy)}`;
|
| 942 |
-
d += ` L${W - M.r},${Y(fv[fv.length - 1][1])}`;
|
| 943 |
-
el("path", { d, fill: "none", stroke: "var(--ink)", "stroke-width": 1.6, "stroke-dasharray": "7 5", opacity: 0.85 }, svg);
|
| 944 |
-
}
|
| 945 |
-
|
| 946 |
-
const isOn = m => state.active.has(m);
|
| 947 |
-
|
| 948 |
-
// connectors: variant links (scatter) / the trajectory itself
|
| 949 |
-
const conn = el("g", {}, svg);
|
| 950 |
-
for (const [method, pts] of byMethod) {
|
| 951 |
-
if (pts.length < 2) continue;
|
| 952 |
-
const on = isOn(method);
|
| 953 |
-
if (!TRAJECTORY && !on) continue; // scatter: connectors only for active methods
|
| 954 |
-
const dd = pts.map((p, i) => `${i ? "L" : "M"}${X(p[xKey])},${Y(mval(p, metric))}`).join(" ");
|
| 955 |
-
el("path", {
|
| 956 |
-
d: dd, fill: "none",
|
| 957 |
-
stroke: on ? FAM_VAR[pts[0].family] : "var(--pt-muted)",
|
| 958 |
-
"stroke-width": on ? (TRAJECTORY ? 2 : 1.4) : 1,
|
| 959 |
-
opacity: on ? 0.6 : 0.35,
|
| 960 |
-
"data-m": method,
|
| 961 |
-
}, conn);
|
| 962 |
-
}
|
| 963 |
-
|
| 964 |
-
// points: inactive first, active on top
|
| 965 |
-
const ptsOff = el("g", {}, svg);
|
| 966 |
-
const ptsOn = el("g", {}, svg);
|
| 967 |
-
for (const [method, pts] of byMethod) {
|
| 968 |
-
const on = isOn(method);
|
| 969 |
-
for (const p of pts) {
|
| 970 |
-
const color = on ? FAM_VAR[p.family] : "var(--pt-muted)";
|
| 971 |
-
const size = (on ? 7 : 5) * (TRAJECTORY ? 0.8 : 1);
|
| 972 |
-
const op = on ? 0.95 : 0.5;
|
| 973 |
-
drawMark(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), p.variant, color, size, op, p.method, on);
|
| 974 |
-
// Imputation ring: every affected point in scatter mode; only the
|
| 975 |
-
// trajectory's end point in trajectory mode (a ring on all ~8 line
|
| 976 |
-
// points would read as beads, and the chip's ‡ already flags the line).
|
| 977 |
-
if (p.imputed && (!TRAJECTORY || p === pts[pts.length - 1])) {
|
| 978 |
-
drawImputedRing(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), size, color, op, p.method);
|
| 979 |
-
}
|
| 980 |
-
}
|
| 981 |
-
}
|
| 982 |
-
|
| 983 |
-
// labels for active methods at their best point, greedy de-overlap
|
| 984 |
-
const labels = [];
|
| 985 |
-
for (const [method, pts] of byMethod) {
|
| 986 |
-
if (!isOn(method)) continue;
|
| 987 |
-
const best = pts.reduce((a, b) =>
|
| 988 |
-
(metric.lowerBetter ? mval(a, metric) < mval(b, metric) : mval(a, metric) > mval(b, metric)) ? a : b);
|
| 989 |
-
labels.push({ method, family: best.family, x: X(best[xKey]) + 10, y: Y(mval(best, metric)) - 10 });
|
| 990 |
-
}
|
| 991 |
-
labels.sort((a, b) => a.y - b.y);
|
| 992 |
-
for (let i = 1; i < labels.length; i++) {
|
| 993 |
-
for (let j = 0; j < i; j++) {
|
| 994 |
-
if (Math.abs(labels[i].x - labels[j].x) < 110 && Math.abs(labels[i].y - labels[j].y) < 15) {
|
| 995 |
-
labels[i].y = labels[j].y + 15;
|
| 996 |
-
}
|
| 997 |
-
}
|
| 998 |
-
}
|
| 999 |
-
const lg = el("g", {}, svg);
|
| 1000 |
-
for (const l of labels) {
|
| 1001 |
-
const t = el("text", {
|
| 1002 |
-
x: Math.min(l.x, W - M.r - 8), y: Math.max(l.y, M.t + 12), "font-size": 13, "font-weight": 700,
|
| 1003 |
-
fill: FAM_VAR[l.family], "paint-order": "stroke", stroke: "var(--card)", "stroke-width": 3.5,
|
| 1004 |
-
"text-anchor": l.x > W - 120 ? "end" : "start",
|
| 1005 |
-
}, lg);
|
| 1006 |
-
t.textContent = l.method;
|
| 1007 |
-
}
|
| 1008 |
-
|
| 1009 |
-
// invisible hit targets on top (bigger than marks)
|
| 1010 |
-
const hits = el("g", {}, svg);
|
| 1011 |
-
for (const p of POINTS) {
|
| 1012 |
-
const h = el("circle", { cx: X(p[xKey]), cy: Y(mval(p, metric)), r: 12, fill: "transparent", cursor: "pointer" }, hits);
|
| 1013 |
-
h.addEventListener("mouseenter", ev => showTip(p, ev));
|
| 1014 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1015 |
-
h.addEventListener("mouseleave", () => hideTip(p.method));
|
| 1016 |
-
h.addEventListener("click", () => toggle(p.method));
|
| 1017 |
-
}
|
| 1018 |
-
}
|
| 1019 |
-
|
| 1020 |
-
// Temporary hover emphasis without a re-render (a re-render would replace
|
| 1021 |
-
// the hit node under the cursor mid-hover).
|
| 1022 |
-
function emphasize(method, on) {
|
| 1023 |
-
svg.querySelectorAll(`[data-m="${CSS.escape(method)}"]`).forEach(n => {
|
| 1024 |
-
if (on) {
|
| 1025 |
-
if (!n.dataset.save) n.dataset.save = n.getAttribute("opacity") || "1";
|
| 1026 |
-
n.setAttribute("opacity", "0.95");
|
| 1027 |
-
} else if (n.dataset.save) {
|
| 1028 |
-
n.setAttribute("opacity", n.dataset.save);
|
| 1029 |
-
delete n.dataset.save;
|
| 1030 |
-
}
|
| 1031 |
-
});
|
| 1032 |
-
}
|
| 1033 |
-
|
| 1034 |
-
function showTip(p, ev) {
|
| 1035 |
-
emphasize(p.method, true);
|
| 1036 |
-
const sub = TRAJECTORY ? (p.n_configs != null ? `${p.n_configs} configs` : "") : (p.variant || "");
|
| 1037 |
-
let html = `<div class="t-name">${p.method}` + (sub ? ` <span class="t-var">(${sub})</span>` : "") + "</div>" +
|
| 1038 |
-
`<div>${p.family}</div>`;
|
| 1039 |
-
for (const m of METRICS) {
|
| 1040 |
-
html += `<div>${m.label}: <b>${fmtMetric(m, mval(p, m))}</b></div>`;
|
| 1041 |
-
}
|
| 1042 |
-
html += `<div>${X_AXIS.short}: <b>${fmtTime(p[xKey])}</b></div>`;
|
| 1043 |
-
if (p.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(p.imputed_pct, 0)}% of datasets</div>`;
|
| 1044 |
-
tip.show(html, ev);
|
| 1045 |
-
}
|
| 1046 |
-
function hideTip(method) {
|
| 1047 |
-
emphasize(method, false);
|
| 1048 |
-
tip.hide();
|
| 1049 |
-
}
|
| 1050 |
-
|
| 1051 |
-
// ---------- chips ----------
|
| 1052 |
-
const chipByMethod = new Map();
|
| 1053 |
-
const famChips = new Map();
|
| 1054 |
-
function familyMethods(fam) {
|
| 1055 |
-
return [...byMethod.keys()].filter(m => byMethod.get(m)[0].family === fam);
|
| 1056 |
-
}
|
| 1057 |
-
// Chips are listed by leaderboard rank — best Elo first when Elo is
|
| 1058 |
-
// configured, otherwise best value of the primary metric.
|
| 1059 |
-
const RANK_METRIC = metricByKey["elo"] || metricByKey[METRICS[0].key];
|
| 1060 |
-
function bestVal(method) {
|
| 1061 |
-
const vals = byMethod.get(method).map(p => mval(p, RANK_METRIC));
|
| 1062 |
-
return RANK_METRIC.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 1063 |
-
}
|
| 1064 |
-
function rankSorted(methods) {
|
| 1065 |
-
return [...methods].sort((a, b) =>
|
| 1066 |
-
RANK_METRIC.lowerBetter ? bestVal(a) - bestVal(b) : bestVal(b) - bestVal(a));
|
| 1067 |
-
}
|
| 1068 |
-
function buildChips() {
|
| 1069 |
-
for (const fam of FAM_ORDER) {
|
| 1070 |
-
const methods = rankSorted(familyMethods(fam));
|
| 1071 |
-
if (!methods.length) continue;
|
| 1072 |
-
const row = document.createElement("div");
|
| 1073 |
-
row.className = "chiprow";
|
| 1074 |
-
const famBtn = document.createElement("button");
|
| 1075 |
-
famBtn.className = "famchip";
|
| 1076 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1077 |
-
famBtn.innerHTML = famChipLabel(fam, methods.length);
|
| 1078 |
-
famBtn.title = `Toggle all ${methods.length} ${fam} methods`;
|
| 1079 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1080 |
-
row.appendChild(famBtn);
|
| 1081 |
-
famChips.set(fam, famBtn);
|
| 1082 |
-
const set = document.createElement("div");
|
| 1083 |
-
set.className = "chipset";
|
| 1084 |
-
for (const m of methods) {
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "chip";
|
| 1087 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1088 |
-
const imputed = byMethod.get(m).some(p => p.imputed);
|
| 1089 |
-
const label = document.createElement("span");
|
| 1090 |
-
label.textContent = m;
|
| 1091 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1092 |
-
b.appendChild(label);
|
| 1093 |
-
if (imputed) {
|
| 1094 |
-
const mark = document.createElement("span");
|
| 1095 |
-
mark.className = "imp-mark";
|
| 1096 |
-
mark.textContent = "‡";
|
| 1097 |
-
b.appendChild(mark);
|
| 1098 |
-
}
|
| 1099 |
-
b.title = m + (imputed ? " — partially imputed" : "");
|
| 1100 |
-
b.addEventListener("click", () => toggle(m));
|
| 1101 |
-
set.appendChild(b);
|
| 1102 |
-
chipByMethod.set(m, b);
|
| 1103 |
-
}
|
| 1104 |
-
row.appendChild(set);
|
| 1105 |
-
chipsBox.appendChild(row);
|
| 1106 |
-
}
|
| 1107 |
-
}
|
| 1108 |
-
function syncChips() {
|
| 1109 |
-
for (const [m, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.active.has(m)));
|
| 1110 |
-
for (const [fam, b] of famChips) {
|
| 1111 |
-
b.setAttribute("aria-pressed", String(familyMethods(fam).every(m => state.active.has(m))));
|
| 1112 |
-
}
|
| 1113 |
-
}
|
| 1114 |
-
function toggle(m) {
|
| 1115 |
-
if (state.active.has(m)) state.active.delete(m); else state.active.add(m);
|
| 1116 |
-
syncChips();
|
| 1117 |
-
render();
|
| 1118 |
-
}
|
| 1119 |
-
function toggleFamily(fam) {
|
| 1120 |
-
const methods = familyMethods(fam);
|
| 1121 |
-
const allOn = methods.every(m => state.active.has(m));
|
| 1122 |
-
for (const m of methods) {
|
| 1123 |
-
if (allOn) state.active.delete(m); else state.active.add(m);
|
| 1124 |
-
}
|
| 1125 |
-
syncChips();
|
| 1126 |
-
render();
|
| 1127 |
-
}
|
| 1128 |
-
function setActive(methods) {
|
| 1129 |
-
state.active = new Set(methods);
|
| 1130 |
-
syncChips();
|
| 1131 |
-
render();
|
| 1132 |
-
}
|
| 1133 |
-
document.getElementById("btn-front").addEventListener("click",
|
| 1134 |
-
() => setActive(computeFront(metricByKey[metricKey]).methods));
|
| 1135 |
-
document.getElementById("btn-all").addEventListener("click", () => setActive([...byMethod.keys()]));
|
| 1136 |
-
document.getElementById("btn-none").addEventListener("click", () => setActive([]));
|
| 1137 |
-
|
| 1138 |
-
// metric selector (hidden when only one metric is configured)
|
| 1139 |
-
const metricPick = document.getElementById("metricpick");
|
| 1140 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1141 |
-
if (METRICS.length > 1) {
|
| 1142 |
-
metricPick.hidden = false;
|
| 1143 |
-
for (const m of METRICS) {
|
| 1144 |
-
const opt = document.createElement("option");
|
| 1145 |
-
opt.value = m.key;
|
| 1146 |
-
opt.textContent = m.label;
|
| 1147 |
-
metricSelect.appendChild(opt);
|
| 1148 |
-
}
|
| 1149 |
-
metricSelect.addEventListener("change", ev => {
|
| 1150 |
-
metricKey = ev.target.value;
|
| 1151 |
-
render();
|
| 1152 |
-
});
|
| 1153 |
-
}
|
| 1154 |
-
|
| 1155 |
-
// ---------- legend strip ----------
|
| 1156 |
-
function buildLegend() {
|
| 1157 |
-
const box2 = document.getElementById("legendstrip");
|
| 1158 |
-
let html = "";
|
| 1159 |
-
if (!TRAJECTORY) {
|
| 1160 |
-
html +=
|
| 1161 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><circle cx="7" cy="7" r="5" fill="var(--muted)"/></svg> Default</span>' +
|
| 1162 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" rx="1.5" fill="var(--muted)"/></svg> Tuned</span>' +
|
| 1163 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><path d="M3,3 L11,11 M3,11 L11,3" stroke="var(--muted)" stroke-width="2.6" stroke-linecap="round"/></svg> Tuned + Ensembled</span>';
|
| 1164 |
-
} else {
|
| 1165 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--muted)" stroke-width="2"/><circle cx="6" cy="4" r="2.6" fill="var(--muted)"/><circle cx="16" cy="4" r="2.6" fill="var(--muted)"/></svg> Tuning trajectory (more configs → more time)</span>';
|
| 1166 |
-
}
|
| 1167 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--ink)" stroke-width="1.6" stroke-dasharray="6 4"/></svg> Pareto front (always shown)</span>';
|
| 1168 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1169 |
-
html += '<span class="item"><svg width="18" height="18" viewBox="0 0 18 18"><circle cx="9" cy="9" r="4" fill="var(--muted)"/><circle cx="9" cy="9" r="7.5" fill="none" stroke="var(--muted)" stroke-width="1.3" stroke-dasharray="3 2.5"/></svg> ‡ partially imputed</span>';
|
| 1170 |
-
}
|
| 1171 |
-
// Model family, named: highlighted points are colored by family, and in paper
|
| 1172 |
-
// view the chip list that would otherwise decode them is hidden.
|
| 1173 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => p.family === f));
|
| 1174 |
-
if (families.length > 1) {
|
| 1175 |
-
html += '<span class="legendbreak"></span><span class="item">Family:</span>';
|
| 1176 |
-
for (const fam of families) {
|
| 1177 |
-
html += `<span class="item"><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1178 |
-
`<circle cx="6" cy="6" r="5" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1179 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`;
|
| 1180 |
-
}
|
| 1181 |
-
}
|
| 1182 |
-
box2.innerHTML = html;
|
| 1183 |
-
}
|
| 1184 |
-
|
| 1185 |
-
// ---------- paper view ----------
|
| 1186 |
-
setUpPaperView(render);
|
| 1187 |
-
setUpExport(() => [{ svg: svg, dx: 0 }], () => slugify(document.title));
|
| 1188 |
-
|
| 1189 |
-
// ---------- data table ----------
|
| 1190 |
-
function buildTable() {
|
| 1191 |
-
const m0 = metricByKey[METRICS[0].key];
|
| 1192 |
-
const rows = [...POINTS].sort((a, b) =>
|
| 1193 |
-
m0.lowerBetter ? mval(a, m0) - mval(b, m0) : mval(b, m0) - mval(a, m0));
|
| 1194 |
-
let html = "<table><thead><tr><th>Method</th>";
|
| 1195 |
-
html += TRAJECTORY ? "<th>Configs</th>" : "<th>Variant</th>";
|
| 1196 |
-
html += "<th>Family</th>";
|
| 1197 |
-
for (const m of METRICS) html += `<th>${m.label}</th>`;
|
| 1198 |
-
html += `<th>${X_AXIS.short}</th><th>Imputed</th></tr></thead><tbody>`;
|
| 1199 |
-
for (const p of rows) {
|
| 1200 |
-
html += `<tr><td>${p.method}</td><td>${TRAJECTORY ? (p.n_configs != null ? p.n_configs : "—") : p.variant}</td><td>${p.family}</td>`;
|
| 1201 |
-
for (const m of METRICS) html += `<td>${fmtMetric(m, mval(p, m))}</td>`;
|
| 1202 |
-
html += `<td>${fmtNum(p[xKey], 3)}</td>`;
|
| 1203 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1204 |
-
}
|
| 1205 |
-
html += "</tbody></table>";
|
| 1206 |
-
document.getElementById("tblwrap").innerHTML = html;
|
| 1207 |
-
}
|
| 1208 |
-
|
| 1209 |
-
const _renderInner = render;
|
| 1210 |
-
render = function () {
|
| 1211 |
-
_renderInner();
|
| 1212 |
-
postHeight();
|
| 1213 |
-
};
|
| 1214 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1215 |
-
let resizeTimer = null;
|
| 1216 |
-
window.addEventListener("resize", () => {
|
| 1217 |
-
clearTimeout(resizeTimer);
|
| 1218 |
-
resizeTimer = setTimeout(render, 120);
|
| 1219 |
-
});
|
| 1220 |
-
window.addEventListener("load", postHeight);
|
| 1221 |
-
|
| 1222 |
-
buildChips();
|
| 1223 |
-
buildLegend();
|
| 1224 |
-
buildTable();
|
| 1225 |
-
syncChips();
|
| 1226 |
-
render();
|
| 1227 |
-
})();
|
| 1228 |
-
</script>
|
| 1229 |
-
</body>
|
| 1230 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_front_improvability_vs_time_infer.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:66175fc84a0e3c329e8475d6213f76ff63a8225c786eee15d60e809db5b02424
|
| 3 |
-
size 275007
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_front_points.csv
DELETED
|
@@ -1,63 +0,0 @@
|
|
| 1 |
-
method,variant,family,x_infer,x_train,imp,elo,imputed,imputed_pct
|
| 2 |
-
TabFM,Default,Foundation Model,13.118891688893655,27.288414010629126,2.682787430454827,1985.6,False,0.0
|
| 3 |
-
TabPFN-3,Default,Foundation Model,0.21472657924676145,1.0099025842179519,5.8782765424085754,1793.5,False,0.0
|
| 4 |
-
TabPFN-2.6,Default,Foundation Model,0.700875014724915,2.7558592936727737,7.846075033073932,1722.4,False,0.0
|
| 5 |
-
TabICLv2,Default,Foundation Model,0.118628191947937,0.6015671441553114,6.850542438637394,1697.2,False,0.0
|
| 6 |
-
RealTabPFN-2.5,Tuned + Ens.,Foundation Model,11.735986151605083,735.5848736648751,8.576138095171979,1645.8,False,0.0
|
| 7 |
-
RealMLP,Tuned + Ens.,Neural Network,1.6746674551212202,1719.820290101634,8.917009760191236,1625.1,False,0.0
|
| 8 |
-
ModernNCA,Tuned + Ens.,Neural Network,6.0133340654646315,2526.306680600179,9.070029386372564,1614.9,False,0.0
|
| 9 |
-
CatBoost,Tuned + Ens.,Tree-based,0.24857039354928848,489.92741010372185,8.931768711834955,1610.6,False,0.0
|
| 10 |
-
RealTabPFN-2.5,Tuned,Foundation Model,1.3859818405575224,735.5848736648751,9.217820982256466,1600.2,False,0.0
|
| 11 |
-
CatBoost,Tuned,Tree-based,0.01969751471208236,489.92741010372185,9.139951687547399,1595.7,False,0.0
|
| 12 |
-
LightGBM,Tuned + Ens.,Tree-based,2.638673830958025,131.56200707040514,10.465838515368032,1588.9,False,0.0
|
| 13 |
-
CatBoost,Default,Tree-based,0.010282764438985344,2.469413828723084,9.095209547420893,1575.9,False,0.0
|
| 14 |
-
iLTM,Tuned + Ens.,Foundation Model,65.19515312136267,2067.952899612129,10.22053858185718,1558.4,False,0.0
|
| 15 |
-
XGBoost,Tuned + Ens.,Tree-based,0.5626253890991211,282.1320041804491,10.54600364212248,1548.1,False,0.0
|
| 16 |
-
TabM,Tuned + Ens.,Neural Network,0.5790353938445546,1236.8778796591432,10.253883595670708,1543.9,False,0.0
|
| 17 |
-
RealMLP,Tuned,Neural Network,0.08070331733080324,1719.820290101634,10.10393779502221,1533.3,False,0.0
|
| 18 |
-
RealTabPFN-2.5,Default,Foundation Model,0.644969598113518,1.8760518371058228,10.077321118993932,1530.5,False,0.0
|
| 19 |
-
TabDPT-Turbo,Default,Foundation Model,0.1795394574862431,0.7535798581633265,10.808546580815626,1526.5,False,0.0
|
| 20 |
-
TabDPT,Tuned + Ens.,Foundation Model,444.5439481393411,4786.598933193933,10.287415300269947,1522.0,False,0.0
|
| 21 |
-
ChimeraBoost,Tuned + Ens.,Tree-based,0.2967122120719018,95.91691558887598,11.684215798303551,1517.0,False,0.0
|
| 22 |
-
LightGBM,Tuned,Tree-based,0.13223572676641904,131.56200707040514,11.603322402427677,1506.5,False,0.0
|
| 23 |
-
XGBoost,Tuned,Tree-based,0.06649421763475445,282.1320041804491,11.102331396641715,1501.2,False,0.0
|
| 24 |
-
TabM,Tuned,Neural Network,0.053897801486310716,1236.8778796591432,11.089489503934743,1480.7,False,0.0
|
| 25 |
-
ModernNCA,Tuned,Neural Network,0.3490410688188341,2526.306680600179,11.214747969543462,1472.1,False,0.0
|
| 26 |
-
ChimeraBoost,Tuned,Tree-based,0.026597070066552417,95.91691558887598,12.145695306561958,1469.6,False,0.0
|
| 27 |
-
xRFM,Tuned + Ens.,Other,0.9511369134522893,566.736982568635,12.482274184135383,1423.2,False,0.0
|
| 28 |
-
iLTM,Tuned,Foundation Model,10.881337571144105,2067.952899612129,12.112147920197751,1422.7,False,0.0
|
| 29 |
-
ChimeraBoost,Default,Tree-based,0.02253709445919907,0.47897883160115473,13.175735213047773,1418.1,False,0.0
|
| 30 |
-
TabDPT,Tuned,Foundation Model,42.64144415855408,4786.598933193933,12.661644781930676,1403.6,False,0.0
|
| 31 |
-
TorchMLP,Tuned + Ens.,Neural Network,1.0691781291613058,1770.5620854905956,12.449525457707859,1376.8,False,0.0
|
| 32 |
-
xRFM,Tuned,Other,0.05992213358760137,566.736982568635,13.982187177893387,1373.4,False,0.0
|
| 33 |
-
XGBoost,Default,Tree-based,0.053416368885586527,0.4869354633908524,12.907417237764236,1371.6,False,0.0
|
| 34 |
-
TabSwift,Default,Foundation Model,0.12716708249348388,0.5069992698737326,13.3366678662291,1344.2,False,0.0
|
| 35 |
-
TabDPT,Default,Foundation Model,43.737812222627376,46.6209023206833,15.31060582466251,1331.5,False,0.0
|
| 36 |
-
TabM,Default,Neural Network,0.047061096558805166,2.1306936635677576,13.981684843143066,1325.7,False,0.0
|
| 37 |
-
EBM,Tuned + Ens.,Tree-based,0.08519206070345582,695.6092947224777,15.59481716563213,1325.5,False,0.0
|
| 38 |
-
ModernNCA,Default,Neural Network,0.24960134666003478,8.063770877226162,14.330291514556546,1297.8,False,0.0
|
| 39 |
-
LimiX,Default,Foundation Model,5.408573077515913,6.553292592842144,16.417704455233075,1279.3,False,0.0
|
| 40 |
-
TorchMLP,Tuned,Neural Network,0.05059286303330543,1770.5620854905956,14.11356578349425,1272.5,False,0.0
|
| 41 |
-
RealMLP,Default,Neural Network,0.23498184801373212,6.7532462416847245,15.091049988060348,1271.6,False,0.0
|
| 42 |
-
EBM,Tuned,Tree-based,0.006145874472476498,695.6092947224777,16.441161926872642,1265.4,False,0.0
|
| 43 |
-
LightGBM,Default,Tree-based,0.04475798376061936,0.2873206973075867,14.819832856038637,1258.1,False,0.0
|
| 44 |
-
RandomForest,Tuned + Ens.,Tree-based,0.34073913033041453,65.99906390887335,15.099597886629788,1244.0,False,0.0
|
| 45 |
-
EBM,Default,Tree-based,0.005423073797379131,2.1751921610874043,17.869797396618495,1220.7,False,0.0
|
| 46 |
-
ExtraTrees,Tuned + Ens.,Tree-based,0.1990111468528113,49.61278913069225,15.304205438801747,1216.6,False,0.0
|
| 47 |
-
RandomForest,Tuned,Tree-based,0.024385081397162542,65.99906390887335,15.743878246297873,1214.3,False,0.0
|
| 48 |
-
FastaiMLP,Tuned + Ens.,Neural Network,1.6581625314855013,351.94124054616117,17.191647439682967,1200.9,False,0.0
|
| 49 |
-
SAP-RPT-OSS,Default,Foundation Model,10.416202336590205,11.438056903606038,16.93308052112088,1200.6,False,0.0
|
| 50 |
-
iLTM,Default,Foundation Model,9.620405688285826,88.27017877459726,18.48774133469958,1179.4,False,0.0
|
| 51 |
-
ExtraTrees,Tuned,Tree-based,0.01531327607338889,49.61278913069225,16.303086509449745,1173.8,False,0.0
|
| 52 |
-
TorchMLP,Default,Neural Network,0.03884902778397399,2.1848199639320423,18.14527829243004,1126.1,False,0.0
|
| 53 |
-
PerpetualBooster,Tuned + Ens.,Tree-based,0.5149235804875691,20.261904767465836,21.63305670520802,1109.8,False,0.0
|
| 54 |
-
FastaiMLP,Tuned,Neural Network,0.11417552222870819,351.94124054616117,19.293775373383966,1101.1,False,0.0
|
| 55 |
-
PerpetualBooster,Tuned,Tree-based,0.1995710637834337,20.261904767465836,22.7471582872999,1059.6,False,0.0
|
| 56 |
-
xRFM,Default,Other,0.1448756257440684,2.4940806965258653,25.979630532218167,1046.2,False,0.0
|
| 57 |
-
FastaiMLP,Default,Neural Network,0.11118662754860731,1.5145310856529652,22.86430904829306,1031.1,False,0.0
|
| 58 |
-
RandomForest,Default,Tree-based,0.020899149004195042,0.19915272527270847,21.197350295416424,1000.0,False,0.0
|
| 59 |
-
TabSTAR,Tuned,Foundation Model,1.7237891060437345,3381.771216219202,25.807196939028948,987.6,False,0.0
|
| 60 |
-
TabSTAR,Tuned + Ens.,Foundation Model,5.282666632972537,3381.771216219202,25.780693599443993,986.6,False,0.0
|
| 61 |
-
ExtraTrees,Default,Tree-based,0.07330450852711995,0.48425838390986126,22.789483920160308,976.4,False,0.0
|
| 62 |
-
PerpetualBooster,Default,Tree-based,0.0149545775519477,1.498562971264291,29.423535438616728,900.7,False,0.0
|
| 63 |
-
TabSTAR,Default,Foundation Model,1.9637818715369053,110.78162664148357,30.685363334130848,847.7,False,0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/pareto_n_configs_imp.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:a06f1ddd5fb23e76494005fb7b89c5b14707991a6d372c5659393437790f6f4e
|
| 3 |
-
size 329290
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/tuning-impact-elo.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:7185f3fddd76776304b7ce81d0589553ffcc5e7699704ffd92f3612034a0f893
|
| 3 |
-
size 106865
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/tuning_trajectories.csv
DELETED
|
@@ -1,163 +0,0 @@
|
|
| 1 |
-
method,family,x_train,x_infer,imp,elo,n_configs,imputed,imputed_pct
|
| 2 |
-
CatBoost,Tree-based,2.469413828723084,0.010282764438985344,9.108385412408444,1592.4,1.0,False,0.0
|
| 3 |
-
CatBoost,Tree-based,4.4162445684880955,0.04068073453140345,9.115993897741033,1597.2,2.0,False,0.0
|
| 4 |
-
CatBoost,Tree-based,12.876612222369168,0.06886368438989382,9.077949577458742,1614.6,5.0,False,0.0
|
| 5 |
-
CatBoost,Tree-based,24.258974220991107,0.09260063686411787,9.058859454142612,1619.0,10.0,False,0.0
|
| 6 |
-
CatBoost,Tree-based,62.05166363782045,0.14800972629415846,8.94676664463184,1630.9,25.0,False,0.0
|
| 7 |
-
CatBoost,Tree-based,122.58001743340024,0.17889789170675716,8.907062350602835,1636.2,50.0,False,0.0
|
| 8 |
-
CatBoost,Tree-based,242.64107636346372,0.21238325680356107,8.92346583669855,1635.5,100.0,False,0.0
|
| 9 |
-
CatBoost,Tree-based,361.12835802610556,0.22857363602101013,8.93120303627158,1634.4,150.0,False,0.0
|
| 10 |
-
CatBoost,Tree-based,489.92741010372185,0.25701532770653723,8.939773822979856,1632.8,201.0,False,0.0
|
| 11 |
-
ChimeraBoost,Tree-based,0.47897883160115473,0.02253709445919907,13.189454574606707,1436.0,1.0,False,0.0
|
| 12 |
-
ChimeraBoost,Tree-based,0.9589536975181837,0.04707955012195989,12.780468930510342,1466.1,2.0,False,0.0
|
| 13 |
-
ChimeraBoost,Tree-based,2.3562175890436245,0.09651491905580373,12.474418307166582,1487.0,5.0,False,0.0
|
| 14 |
-
ChimeraBoost,Tree-based,4.7221268742289215,0.14469563000700886,12.239180925343982,1504.5,10.0,False,0.0
|
| 15 |
-
ChimeraBoost,Tree-based,11.925520358640576,0.20166683840835442,12.049733976311524,1519.9,25.0,False,0.0
|
| 16 |
-
ChimeraBoost,Tree-based,23.876897602770455,0.24104859679665822,11.913101781047567,1529.1,50.0,False,0.0
|
| 17 |
-
ChimeraBoost,Tree-based,47.75183320297697,0.2647783876343018,11.775566699064154,1538.0,100.0,False,0.0
|
| 18 |
-
ChimeraBoost,Tree-based,71.58606156368943,0.28902400667036765,11.715015921705005,1542.4,150.0,False,0.0
|
| 19 |
-
ChimeraBoost,Tree-based,95.91691558887598,0.30641840856334224,11.695769572500863,1545.6,201.0,False,0.0
|
| 20 |
-
EBM,Tree-based,2.1751921610874043,0.005423073797379131,17.880342849641814,1226.6,1.0,False,0.0
|
| 21 |
-
EBM,Tree-based,6.66369259252883,0.01166082767964927,17.194191521115066,1252.7,2.0,False,0.0
|
| 22 |
-
EBM,Tree-based,17.233925805413904,0.022699023320909735,16.611687689639407,1279.2,5.0,False,0.0
|
| 23 |
-
EBM,Tree-based,34.57775587659134,0.03331359493060592,16.356047022321825,1292.6,10.0,False,0.0
|
| 24 |
-
EBM,Tree-based,87.92451656340509,0.049757168812449036,16.052139850599062,1310.8,25.0,False,0.0
|
| 25 |
-
EBM,Tree-based,174.9652611713922,0.05930088518555479,15.899420591867939,1322.1,50.0,False,0.0
|
| 26 |
-
EBM,Tree-based,345.06715788569375,0.0709126161428919,15.738671469168668,1333.5,100.0,False,0.0
|
| 27 |
-
EBM,Tree-based,520.7521321905026,0.0763826625184994,15.682540075474053,1338.6,150.0,False,0.0
|
| 28 |
-
EBM,Tree-based,695.6092947224777,0.08519206070345582,15.601358072339396,1345.5,201.0,False,0.0
|
| 29 |
-
ExtraTrees,Tree-based,0.48425838390986126,0.07330450852711995,22.79988950966345,973.5,1.0,False,0.0
|
| 30 |
-
ExtraTrees,Tree-based,0.8466137520036096,0.07522212407038217,20.659729306554848,1029.8,2.0,False,0.0
|
| 31 |
-
ExtraTrees,Tree-based,1.692317521137873,0.0926460135839083,17.462172250613623,1121.5,5.0,False,0.0
|
| 32 |
-
ExtraTrees,Tree-based,2.929179805844217,0.10109344429242911,16.311064736513742,1167.0,10.0,False,0.0
|
| 33 |
-
ExtraTrees,Tree-based,6.61473647238103,0.10828184879460544,15.560182328594163,1201.4,25.0,False,0.0
|
| 34 |
-
ExtraTrees,Tree-based,12.710816754735825,0.14385828902585665,15.392998219548856,1213.9,50.0,False,0.0
|
| 35 |
-
ExtraTrees,Tree-based,24.941682372165904,0.16087820180002574,15.26699302280187,1223.4,100.0,False,0.0
|
| 36 |
-
ExtraTrees,Tree-based,37.13843182260326,0.18771563305900177,15.265549059518888,1226.1,150.0,False,0.0
|
| 37 |
-
ExtraTrees,Tree-based,49.61278913069225,0.1990111468528113,15.316095966675125,1228.5,201.0,False,0.0
|
| 38 |
-
FastaiMLP,Neural Network,1.5145310856529652,0.11118662754860731,22.873841530144425,1039.3,1.0,False,0.0
|
| 39 |
-
FastaiMLP,Neural Network,3.1588915156956174,0.22199569005113567,21.853790659634655,1065.8,2.0,False,0.0
|
| 40 |
-
FastaiMLP,Neural Network,8.59563123829451,0.4051013545327364,20.52389504257173,1113.9,5.0,False,0.0
|
| 41 |
-
FastaiMLP,Neural Network,17.78186248206276,0.6441505685161579,19.750939156228988,1138.1,10.0,False,0.0
|
| 42 |
-
FastaiMLP,Neural Network,42.53008857176902,0.9551913220836626,18.79520904183076,1166.3,25.0,False,0.0
|
| 43 |
-
FastaiMLP,Neural Network,85.67628226317562,1.2793194595040644,18.216855293020117,1183.4,50.0,False,0.0
|
| 44 |
-
FastaiMLP,Neural Network,173.7598987199963,1.5591641511917327,17.729624605224796,1197.3,100.0,False,0.0
|
| 45 |
-
FastaiMLP,Neural Network,261.7851807624679,1.6900218906632645,17.401845831784602,1210.6,150.0,False,0.0
|
| 46 |
-
FastaiMLP,Neural Network,351.94124054616117,1.658906059585989,17.197757082763808,1219.8,201.0,False,0.0
|
| 47 |
-
LightGBM,Tree-based,0.2873206973075867,0.04475798376061936,14.831406830988078,1265.3,1.0,False,0.0
|
| 48 |
-
LightGBM,Tree-based,0.931650224659178,0.423415924843989,14.227285012543916,1316.7,2.0,False,0.0
|
| 49 |
-
LightGBM,Tree-based,2.728670285380442,0.7433885464019945,13.077108942307165,1416.7,5.0,False,0.0
|
| 50 |
-
LightGBM,Tree-based,6.1477936875711485,0.9410923145319288,12.216587804790636,1486.0,10.0,False,0.0
|
| 51 |
-
LightGBM,Tree-based,16.52097248547071,1.3202136892725407,11.206256977787026,1552.1,25.0,False,0.0
|
| 52 |
-
LightGBM,Tree-based,32.67977659086273,1.4195738396100834,10.77603904990665,1588.5,50.0,False,0.0
|
| 53 |
-
LightGBM,Tree-based,65.3538276872704,2.0760086735335515,10.583483894061576,1603.7,100.0,False,0.0
|
| 54 |
-
LightGBM,Tree-based,98.42128335857386,2.2773590031797486,10.522416903623661,1608.7,150.0,False,0.0
|
| 55 |
-
LightGBM,Tree-based,131.56200707040514,2.638673830958025,10.484769236100053,1615.4,201.0,False,0.0
|
| 56 |
-
LimiX,Foundation Model,6.553292592842144,5.408573077515913,16.14157585284815,1298.5,1.0,False,0.0
|
| 57 |
-
ModernNCA,Neural Network,8.063770877226162,0.24960134666003478,14.341711205023394,1311.4,1.0,False,0.0
|
| 58 |
-
ModernNCA,Neural Network,21.753839521403215,0.5785744608262396,12.878270477194889,1383.0,2.0,False,0.0
|
| 59 |
-
ModernNCA,Neural Network,60.91776288315985,1.29474806549814,11.027959170982662,1499.2,5.0,False,0.0
|
| 60 |
-
ModernNCA,Neural Network,121.85928580479494,2.1427076773113676,10.344152870747507,1546.2,10.0,False,0.0
|
| 61 |
-
ModernNCA,Neural Network,292.3137710755714,2.7736882795804276,9.611889968072926,1599.2,25.0,False,0.0
|
| 62 |
-
ModernNCA,Neural Network,629.890040030536,3.9630762476559322,9.307735484335712,1621.1,50.0,False,0.0
|
| 63 |
-
ModernNCA,Neural Network,1243.5591974675485,5.167921375609095,9.181770303214156,1633.7,100.0,False,0.0
|
| 64 |
-
ModernNCA,Neural Network,1862.5519447854,5.876817380350334,9.122250703177043,1637.8,150.0,False,0.0
|
| 65 |
-
ModernNCA,Neural Network,2526.306680600179,6.104160729998767,9.09173861372904,1640.3,201.0,False,0.0
|
| 66 |
-
PerpetualBooster,Tree-based,1.498562971264291,0.0149545775519477,29.689070512344767,914.4,1.0,False,0.0
|
| 67 |
-
PerpetualBooster,Tree-based,6.4317773956676225,0.14601458387603072,27.150126117960287,995.4,2.0,False,0.0
|
| 68 |
-
PerpetualBooster,Tree-based,16.949305660221782,0.444796272511348,21.76117480747134,1110.0,5.0,False,0.0
|
| 69 |
-
PerpetualBooster,Tree-based,20.261904767465836,0.5149235804875691,21.637241667958527,1119.5,6.0,False,0.0
|
| 70 |
-
RandomForest,Tree-based,0.19915272527270847,0.020899149004195042,21.213144829853707,999.5,1.0,False,0.0
|
| 71 |
-
RandomForest,Tree-based,0.5021873110599798,0.045901973979854016,17.69477084542158,1106.7,2.0,False,0.0
|
| 72 |
-
RandomForest,Tree-based,1.489455051236279,0.11282485912166518,16.252525288491515,1176.5,5.0,False,0.0
|
| 73 |
-
RandomForest,Tree-based,3.130777319214283,0.13673928726731627,15.703690077118287,1208.8,10.0,False,0.0
|
| 74 |
-
RandomForest,Tree-based,8.02025679639823,0.20254017138230673,15.340406965354184,1234.5,25.0,False,0.0
|
| 75 |
-
RandomForest,Tree-based,16.237787158411987,0.2523558649222056,15.214174130159272,1245.0,50.0,False,0.0
|
| 76 |
-
RandomForest,Tree-based,32.671093442836856,0.2972209594249725,15.126789502908613,1254.8,100.0,False,0.0
|
| 77 |
-
RandomForest,Tree-based,49.171965802832155,0.33106692790985104,15.085348041401572,1259.4,150.0,False,0.0
|
| 78 |
-
RandomForest,Tree-based,65.99906390887335,0.34148336141365077,15.111140652140218,1262.7,201.0,False,0.0
|
| 79 |
-
RealMLP,Neural Network,6.7532462416847245,0.23498184801373212,15.100567151344697,1281.1,1.0,False,0.0
|
| 80 |
-
RealMLP,Neural Network,15.527578690794181,0.3080259999395399,12.907226004650202,1413.1,2.0,False,0.0
|
| 81 |
-
RealMLP,Neural Network,39.124153040818086,0.5106934438586126,11.363558126850805,1512.9,5.0,False,0.0
|
| 82 |
-
RealMLP,Neural Network,82.74224081710975,0.759436157944363,10.5674293142504,1553.2,10.0,False,0.0
|
| 83 |
-
RealMLP,Neural Network,213.27613858935567,0.9843404045345187,9.848178322594768,1599.1,25.0,False,0.0
|
| 84 |
-
RealMLP,Neural Network,427.90915376015505,1.1860326968189097,9.529736811839793,1614.8,50.0,False,0.0
|
| 85 |
-
RealMLP,Neural Network,848.9386425085199,1.4580786339418361,9.160122719593092,1634.3,100.0,False,0.0
|
| 86 |
-
RealMLP,Neural Network,1278.8937139162222,1.5889939536507325,9.003642529752812,1645.3,150.0,False,0.0
|
| 87 |
-
RealMLP,Neural Network,1719.820290101634,1.6682080327694422,8.92878682894443,1654.4,201.0,False,0.0
|
| 88 |
-
RealTabPFN-2.5,Foundation Model,1.8760518371058228,0.644969598113518,10.091872578679544,1542.8,1.0,False,0.0
|
| 89 |
-
RealTabPFN-2.5,Foundation Model,5.127864715472546,1.4937099645347298,10.018663162993988,1552.4,2.0,False,0.0
|
| 90 |
-
RealTabPFN-2.5,Foundation Model,16.206992788783356,3.2513268046584503,9.848206787771563,1566.8,5.0,False,0.0
|
| 91 |
-
RealTabPFN-2.5,Foundation Model,34.25360422679489,4.991835645809406,9.701576186330296,1583.0,10.0,False,0.0
|
| 92 |
-
RealTabPFN-2.5,Foundation Model,88.96282194243713,6.462092531240927,9.358425943462754,1623.9,25.0,False,0.0
|
| 93 |
-
RealTabPFN-2.5,Foundation Model,181.39522434540766,9.411482770309476,9.00034093600866,1645.7,50.0,False,0.0
|
| 94 |
-
RealTabPFN-2.5,Foundation Model,363.91723618262904,11.623618059298572,8.777908024057808,1656.9,100.0,False,0.0
|
| 95 |
-
RealTabPFN-2.5,Foundation Model,547.7650992279482,11.995516969136737,8.657656126655123,1660.4,150.0,False,0.0
|
| 96 |
-
RealTabPFN-2.5,Foundation Model,735.5848736648751,11.735986151605083,8.585639428162168,1660.9,201.0,False,0.0
|
| 97 |
-
SAP-RPT-OSS,Foundation Model,11.438056903606038,10.416202336590205,16.941314181065422,1215.7,1.0,False,0.0
|
| 98 |
-
TabDPT,Foundation Model,46.6209023206833,43.737812222627376,15.320041044124682,1343.2,1.0,False,0.0
|
| 99 |
-
TabDPT,Foundation Model,70.03488466291391,60.76345722760032,14.195649530423754,1371.8,2.0,False,0.0
|
| 100 |
-
TabDPT,Foundation Model,129.29601127069574,97.7966669956843,13.094383264418624,1413.9,5.0,False,0.0
|
| 101 |
-
TabDPT,Foundation Model,230.72939494613806,126.13170818355633,12.678445777759691,1431.4,10.0,False,0.0
|
| 102 |
-
TabDPT,Foundation Model,589.0616829285759,211.8920837189545,11.724325816257148,1477.2,25.0,False,0.0
|
| 103 |
-
TabDPT,Foundation Model,1187.757830840611,283.78344604791266,11.191253011736734,1502.7,50.0,False,0.0
|
| 104 |
-
TabDPT,Foundation Model,2376.2279314343073,356.1524517375418,10.813507343563613,1519.8,100.0,False,0.0
|
| 105 |
-
TabDPT,Foundation Model,3574.191913268326,402.5853130690112,10.483151139306383,1533.6,150.0,False,0.0
|
| 106 |
-
TabDPT,Foundation Model,4786.598933193933,433.01544407663886,10.296860814024953,1538.9,201.0,False,0.0
|
| 107 |
-
TabDPT-Turbo,Foundation Model,0.7535798581633265,0.1795394574862431,10.819902208137352,1540.5,1.0,False,0.0
|
| 108 |
-
TabFM,Foundation Model,27.288414010629126,13.118891688893655,2.6842884758658836,1990.2,1.0,False,0.0
|
| 109 |
-
TabICLv2,Foundation Model,0.6015671441553114,0.118628191947937,6.865956109703099,1713.3,1.0,False,0.0
|
| 110 |
-
TabM,Neural Network,2.1306936635677576,0.047061096558805166,13.99396716730505,1336.4,1.0,False,0.0
|
| 111 |
-
TabM,Neural Network,6.720132302065123,0.10166420156235179,13.138602472702448,1384.2,2.0,False,0.0
|
| 112 |
-
TabM,Neural Network,26.071931655972485,0.19658337075272886,12.076710839994865,1440.9,5.0,False,0.0
|
| 113 |
-
TabM,Neural Network,56.6403905325952,0.2690374607115522,11.465419545965009,1482.1,10.0,False,0.0
|
| 114 |
-
TabM,Neural Network,151.63250845437173,0.34533908128738405,10.915087566605157,1514.9,25.0,False,0.0
|
| 115 |
-
TabM,Neural Network,305.405015900313,0.46416595419440415,10.634788115506625,1536.6,50.0,False,0.0
|
| 116 |
-
TabM,Neural Network,598.1660502680137,0.5371776271588682,10.40920433362231,1551.8,100.0,False,0.0
|
| 117 |
-
TabM,Neural Network,909.6246432442554,0.5567799536795643,10.320563967083489,1559.9,150.0,False,0.0
|
| 118 |
-
TabM,Neural Network,1236.8778796591432,0.5682121276236716,10.262306941439089,1568.2,201.0,False,0.0
|
| 119 |
-
TabPFN-2.6,Foundation Model,2.7558592936727737,0.700875014724915,7.860528976942049,1746.6,1.0,False,0.0
|
| 120 |
-
TabPFN-3,Foundation Model,1.0099025842179519,0.21472657924676145,5.883486403593643,1798.7,1.0,False,0.0
|
| 121 |
-
TabSTAR,Foundation Model,110.78162664148357,1.9637818715369053,30.69176142205053,842.3,1.0,False,0.0
|
| 122 |
-
TabSTAR,Foundation Model,125.57112346948114,1.933477852272125,30.6098027549634,858.0,2.0,False,0.0
|
| 123 |
-
TabSTAR,Foundation Model,166.49912766533103,2.140647516193624,30.457152233542967,864.2,5.0,False,0.0
|
| 124 |
-
TabSTAR,Foundation Model,216.82609728692088,2.4886555762895703,30.017913515556792,881.7,10.0,False,0.0
|
| 125 |
-
TabSTAR,Foundation Model,435.6268489691195,2.9679019309527157,29.053271930943918,906.8,25.0,False,0.0
|
| 126 |
-
TabSTAR,Foundation Model,841.7488888840559,3.4310027254645297,27.865416610529476,933.8,50.0,False,0.0
|
| 127 |
-
TabSTAR,Foundation Model,1663.686576013856,4.443681021054585,27.08082788380544,956.7,100.0,False,0.0
|
| 128 |
-
TabSTAR,Foundation Model,2487.204912475645,4.943553034388052,26.384678054770276,981.0,150.0,False,0.0
|
| 129 |
-
TabSTAR,Foundation Model,3381.771216219202,5.282666632972537,25.788716656340082,1007.2,201.0,False,0.0
|
| 130 |
-
TabSwift,Foundation Model,0.5069992698737326,0.12716708249348388,13.350681903466016,1362.2,1.0,False,0.0
|
| 131 |
-
TorchMLP,Neural Network,2.1848199639320423,0.03884902778397399,18.153580763501207,1135.4,1.0,False,0.0
|
| 132 |
-
TorchMLP,Neural Network,9.222603334986646,0.09146565885667123,16.913855088278495,1182.8,2.0,False,0.0
|
| 133 |
-
TorchMLP,Neural Network,41.23639970605849,0.2165503089261113,15.542102939673713,1240.3,5.0,False,0.0
|
| 134 |
-
TorchMLP,Neural Network,91.32376520040506,0.35785402203318467,14.726269057806753,1284.5,10.0,False,0.0
|
| 135 |
-
TorchMLP,Neural Network,218.54732020220172,0.5218944892827895,13.843543448675543,1325.1,25.0,False,0.0
|
| 136 |
-
TorchMLP,Neural Network,447.05075486815855,0.7429074477444512,13.331475602418127,1355.0,50.0,False,0.0
|
| 137 |
-
TorchMLP,Neural Network,866.7256429369004,0.9478582393719392,12.928400950565655,1377.2,100.0,False,0.0
|
| 138 |
-
TorchMLP,Neural Network,1331.6601195386634,1.0346365316168704,12.685478783982992,1390.2,150.0,False,0.0
|
| 139 |
-
TorchMLP,Neural Network,1770.5620854905956,1.0691781291613058,12.462997864617684,1401.4,201.0,False,0.0
|
| 140 |
-
XGBoost,Tree-based,0.4869354633908524,0.053416368885586527,12.920703471704298,1387.7,1.0,False,0.0
|
| 141 |
-
XGBoost,Tree-based,2.4341782987194773,0.17931842124252992,11.917596563649761,1466.8,2.0,False,0.0
|
| 142 |
-
XGBoost,Tree-based,7.3419221790132845,0.2826887094137962,11.365912227698736,1515.0,5.0,False,0.0
|
| 143 |
-
XGBoost,Tree-based,13.425391893256847,0.29683045128481406,11.001231426277393,1536.9,10.0,False,0.0
|
| 144 |
-
XGBoost,Tree-based,35.1370362217863,0.40283655412991837,10.749441963853915,1552.3,25.0,False,0.0
|
| 145 |
-
XGBoost,Tree-based,69.83880191326698,0.4362798233826955,10.644994504895712,1560.2,50.0,False,0.0
|
| 146 |
-
XGBoost,Tree-based,138.68430728332427,0.4803960764408111,10.57795589179427,1567.5,100.0,False,0.0
|
| 147 |
-
XGBoost,Tree-based,209.60031705983081,0.5237722573280333,10.566097258404868,1571.0,150.0,False,0.0
|
| 148 |
-
XGBoost,Tree-based,282.1320041804491,0.5608426218032837,10.56061766714314,1574.8,201.0,False,0.0
|
| 149 |
-
iLTM,Foundation Model,88.27017877459726,9.620405688285826,18.49837810390806,1192.9,1.0,False,0.0
|
| 150 |
-
iLTM,Foundation Model,168.23671986991735,18.955818040688833,16.389045401402022,1247.3,2.0,False,0.0
|
| 151 |
-
iLTM,Foundation Model,410.88335194101177,33.21024323942741,16.218624325209394,1345.3,5.0,False,0.0
|
| 152 |
-
iLTM,Foundation Model,805.521975186799,46.92423318461996,13.559497444839424,1442.5,10.0,False,0.0
|
| 153 |
-
iLTM,Foundation Model,1992.2815124103738,66.5740410026117,10.270428232288518,1578.8,25.0,False,0.0
|
| 154 |
-
iLTM,Foundation Model,2067.952899612129,65.19515312136267,10.233826926607986,1584.4,26.0,False,0.0
|
| 155 |
-
xRFM,Other,2.4940806965258653,0.1448756257440684,25.98755778666362,1051.9,1.0,False,0.0
|
| 156 |
-
xRFM,Other,5.313335044139122,0.19036624122472157,21.3468517178997,1127.7,2.0,False,0.0
|
| 157 |
-
xRFM,Other,13.802098162260378,0.2632687113094409,16.135396193164826,1255.0,5.0,False,0.0
|
| 158 |
-
xRFM,Other,28.327072009638513,0.38188561104171487,13.900279138547264,1372.9,10.0,False,0.0
|
| 159 |
-
xRFM,Other,70.60474405079418,0.5413359982156494,12.97431812352308,1424.6,25.0,False,0.0
|
| 160 |
-
xRFM,Other,140.54533237320845,0.6886364122629532,12.624894430651533,1441.4,50.0,False,0.0
|
| 161 |
-
xRFM,Other,281.12441629309126,0.8346908134535932,12.489108203595404,1446.3,100.0,False,0.0
|
| 162 |
-
xRFM,Other,422.35324605180153,0.899204071689565,12.448018897829023,1447.6,150.0,False,0.0
|
| 163 |
-
xRFM,Other,566.736982568635,0.9679699004975301,12.462818714897264,1446.1,201.0,False,0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/tuning_trajectories_explorer.html
DELETED
|
@@ -1,1230 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena tuning trajectories</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Two-column layout: controls + chips in a side panel, chart beside it.
|
| 269 |
-
``chips-right`` mirrors the columns. Wraps to stacked when narrow. */
|
| 270 |
-
.explorer-grid { display: flex; gap: 18px; align-items: flex-start; }
|
| 271 |
-
.explorer-grid.chips-right { flex-direction: row-reverse; }
|
| 272 |
-
.sidebox { flex: 0 0 330px; min-width: 250px; display: flex; flex-direction: column; gap: 10px; }
|
| 273 |
-
.mainbox { flex: 1 1 auto; min-width: 0; }
|
| 274 |
-
@media (max-width: 860px) {
|
| 275 |
-
.explorer-grid { flex-wrap: wrap; }
|
| 276 |
-
.sidebox { flex: 1 1 100%; }
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 280 |
-
.chartbox { position: relative; }
|
| 281 |
-
/* The chart is sized in device pixels by render() rather than scaled from a
|
| 282 |
-
viewBox: scaling stretched the type along with the plot, and a viewBox tall
|
| 283 |
-
enough to read made the whole panel own the screen. */
|
| 284 |
-
.chartbox svg { display: block; }
|
| 285 |
-
/* Chips scroll within the column so the panel height follows the chart. */
|
| 286 |
-
.sidebox .chips { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent; }
|
| 287 |
-
.sidebox .chips::-webkit-scrollbar { width: 9px; }
|
| 288 |
-
.sidebox .chips::-webkit-scrollbar-thumb {
|
| 289 |
-
background: var(--pt-muted); border-radius: 8px; border: 3px solid transparent; background-clip: content-box;
|
| 290 |
-
}
|
| 291 |
-
</style>
|
| 292 |
-
</head>
|
| 293 |
-
<body>
|
| 294 |
-
<div class="viewbar">
|
| 295 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 296 |
-
</div>
|
| 297 |
-
<p class="explorer-title" id="title"></p>
|
| 298 |
-
<div class="explorer-grid" id="grid">
|
| 299 |
-
<div class="sidebox">
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick" id="metricpick" hidden>Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<div class="btnrow">
|
| 305 |
-
<button class="btn" id="btn-front">Pareto front</button>
|
| 306 |
-
<button class="btn" id="btn-all">All</button>
|
| 307 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 308 |
-
</div>
|
| 309 |
-
<span class="hint">Click methods or family buttons to highlight · hover points for details</span>
|
| 310 |
-
</div>
|
| 311 |
-
<div class="chips" id="chips"></div>
|
| 312 |
-
</div>
|
| 313 |
-
<div class="mainbox">
|
| 314 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 315 |
-
<span class="hint">Export figure</span>
|
| 316 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 317 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 318 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 319 |
-
</div>
|
| 320 |
-
<!-- Legend above the chart so readers decode the marks before the data. -->
|
| 321 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 322 |
-
<div class="chartbox" id="chartbox">
|
| 323 |
-
<svg id="chart" role="img" aria-label="Pareto front explorer"></svg>
|
| 324 |
-
<div class="tooltip"></div>
|
| 325 |
-
</div>
|
| 326 |
-
</div>
|
| 327 |
-
</div>
|
| 328 |
-
<details class="datatable">
|
| 329 |
-
<summary>Data table</summary>
|
| 330 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 331 |
-
</details>
|
| 332 |
-
|
| 333 |
-
<script>
|
| 334 |
-
(function () {
|
| 335 |
-
"use strict";
|
| 336 |
-
const CONFIG = {"mode": "trajectory", "title": null, "metrics": [{"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": ""}], "xAxes": [{"key": "x_train", "label": "Train time", "axisLabel": "Train time per 1K samples (s), median \u2014 log scale", "short": "Train (s/1K, median)"}], "chipsSide": "right"};
|
| 337 |
-
const POINTS = [{"method":"CatBoost","family":"Tree-based","x_train":2.4694138287,"imp":9.1083854124,"elo":1592.4,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"CatBoost","family":"Tree-based","x_train":4.4162445685,"imp":9.1159938977,"elo":1597.2,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"CatBoost","family":"Tree-based","x_train":12.8766122224,"imp":9.0779495775,"elo":1614.6,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"CatBoost","family":"Tree-based","x_train":24.258974221,"imp":9.0588594541,"elo":1619.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"CatBoost","family":"Tree-based","x_train":62.0516636378,"imp":8.9467666446,"elo":1630.9,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"CatBoost","family":"Tree-based","x_train":122.5800174334,"imp":8.9070623506,"elo":1636.2,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"CatBoost","family":"Tree-based","x_train":242.6410763635,"imp":8.9234658367,"elo":1635.5,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"CatBoost","family":"Tree-based","x_train":361.1283580261,"imp":8.9312030363,"elo":1634.4,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"CatBoost","family":"Tree-based","x_train":489.9274101037,"imp":8.939773823,"elo":1632.8,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":0.4789788316,"imp":13.1894545746,"elo":1436.0,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":0.9589536975,"imp":12.7804689305,"elo":1466.1,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":2.356217589,"imp":12.4744183072,"elo":1487.0,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":4.7221268742,"imp":12.2391809253,"elo":1504.5,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":11.9255203586,"imp":12.0497339763,"elo":1519.9,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":23.8768976028,"imp":11.913101781,"elo":1529.1,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":47.751833203,"imp":11.7755666991,"elo":1538.0,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":71.5860615637,"imp":11.7150159217,"elo":1542.4,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"ChimeraBoost","family":"Tree-based","x_train":95.9169155889,"imp":11.6957695725,"elo":1545.6,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"EBM","family":"Tree-based","x_train":2.1751921611,"imp":17.8803428496,"elo":1226.6,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"EBM","family":"Tree-based","x_train":6.6636925925,"imp":17.1941915211,"elo":1252.7,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"EBM","family":"Tree-based","x_train":17.2339258054,"imp":16.6116876896,"elo":1279.2,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"EBM","family":"Tree-based","x_train":34.5777558766,"imp":16.3560470223,"elo":1292.6,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"EBM","family":"Tree-based","x_train":87.9245165634,"imp":16.0521398506,"elo":1310.8,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"EBM","family":"Tree-based","x_train":174.9652611714,"imp":15.8994205919,"elo":1322.1,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"EBM","family":"Tree-based","x_train":345.0671578857,"imp":15.7386714692,"elo":1333.5,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"EBM","family":"Tree-based","x_train":520.7521321905,"imp":15.6825400755,"elo":1338.6,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"EBM","family":"Tree-based","x_train":695.6092947225,"imp":15.6013580723,"elo":1345.5,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"ExtraTrees","family":"Tree-based","x_train":0.4842583839,"imp":22.7998895097,"elo":973.5,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ExtraTrees","family":"Tree-based","x_train":0.846613752,"imp":20.6597293066,"elo":1029.8,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"ExtraTrees","family":"Tree-based","x_train":1.6923175211,"imp":17.4621722506,"elo":1121.5,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"ExtraTrees","family":"Tree-based","x_train":2.9291798058,"imp":16.3110647365,"elo":1167.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"ExtraTrees","family":"Tree-based","x_train":6.6147364724,"imp":15.5601823286,"elo":1201.4,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"ExtraTrees","family":"Tree-based","x_train":12.7108167547,"imp":15.3929982195,"elo":1213.9,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"ExtraTrees","family":"Tree-based","x_train":24.9416823722,"imp":15.2669930228,"elo":1223.4,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"ExtraTrees","family":"Tree-based","x_train":37.1384318226,"imp":15.2655490595,"elo":1226.1,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"ExtraTrees","family":"Tree-based","x_train":49.6127891307,"imp":15.3160959667,"elo":1228.5,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"FastaiMLP","family":"Neural Network","x_train":1.5145310857,"imp":22.8738415301,"elo":1039.3,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"FastaiMLP","family":"Neural Network","x_train":3.1588915157,"imp":21.8537906596,"elo":1065.8,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"FastaiMLP","family":"Neural Network","x_train":8.5956312383,"imp":20.5238950426,"elo":1113.9,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"FastaiMLP","family":"Neural Network","x_train":17.7818624821,"imp":19.7509391562,"elo":1138.1,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"FastaiMLP","family":"Neural Network","x_train":42.5300885718,"imp":18.7952090418,"elo":1166.3,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"FastaiMLP","family":"Neural Network","x_train":85.6762822632,"imp":18.216855293,"elo":1183.4,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"FastaiMLP","family":"Neural Network","x_train":173.75989872,"imp":17.7296246052,"elo":1197.3,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"FastaiMLP","family":"Neural Network","x_train":261.7851807625,"imp":17.4018458318,"elo":1210.6,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"FastaiMLP","family":"Neural Network","x_train":351.9412405462,"imp":17.1977570828,"elo":1219.8,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"LightGBM","family":"Tree-based","x_train":0.2873206973,"imp":14.831406831,"elo":1265.3,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"LightGBM","family":"Tree-based","x_train":0.9316502247,"imp":14.2272850125,"elo":1316.7,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"LightGBM","family":"Tree-based","x_train":2.7286702854,"imp":13.0771089423,"elo":1416.7,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"LightGBM","family":"Tree-based","x_train":6.1477936876,"imp":12.2165878048,"elo":1486.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"LightGBM","family":"Tree-based","x_train":16.5209724855,"imp":11.2062569778,"elo":1552.1,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"LightGBM","family":"Tree-based","x_train":32.6797765909,"imp":10.7760390499,"elo":1588.5,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"LightGBM","family":"Tree-based","x_train":65.3538276873,"imp":10.5834838941,"elo":1603.7,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"LightGBM","family":"Tree-based","x_train":98.4212833586,"imp":10.5224169036,"elo":1608.7,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"LightGBM","family":"Tree-based","x_train":131.5620070704,"imp":10.4847692361,"elo":1615.4,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"LimiX","family":"Foundation Model","x_train":6.5532925928,"imp":16.1415758528,"elo":1298.5,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ModernNCA","family":"Neural Network","x_train":8.0637708772,"imp":14.341711205,"elo":1311.4,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"ModernNCA","family":"Neural Network","x_train":21.7538395214,"imp":12.8782704772,"elo":1383.0,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"ModernNCA","family":"Neural Network","x_train":60.9177628832,"imp":11.027959171,"elo":1499.2,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"ModernNCA","family":"Neural Network","x_train":121.8592858048,"imp":10.3441528707,"elo":1546.2,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"ModernNCA","family":"Neural Network","x_train":292.3137710756,"imp":9.6118899681,"elo":1599.2,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"ModernNCA","family":"Neural Network","x_train":629.8900400305,"imp":9.3077354843,"elo":1621.1,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"ModernNCA","family":"Neural Network","x_train":1243.5591974675,"imp":9.1817703032,"elo":1633.7,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"ModernNCA","family":"Neural Network","x_train":1862.5519447854,"imp":9.1222507032,"elo":1637.8,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"ModernNCA","family":"Neural Network","x_train":2526.3066806002,"imp":9.0917386137,"elo":1640.3,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":1.4985629713,"imp":29.6890705123,"elo":914.4,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":6.4317773957,"imp":27.150126118,"elo":995.4,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":16.9493056602,"imp":21.7611748075,"elo":1110.0,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"PerpetualBooster","family":"Tree-based","x_train":20.2619047675,"imp":21.637241668,"elo":1119.5,"imputed":false,"imputed_pct":0.0,"n_configs":6.0},{"method":"RandomForest","family":"Tree-based","x_train":0.1991527253,"imp":21.2131448299,"elo":999.5,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"RandomForest","family":"Tree-based","x_train":0.5021873111,"imp":17.6947708454,"elo":1106.7,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"RandomForest","family":"Tree-based","x_train":1.4894550512,"imp":16.2525252885,"elo":1176.5,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"RandomForest","family":"Tree-based","x_train":3.1307773192,"imp":15.7036900771,"elo":1208.8,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"RandomForest","family":"Tree-based","x_train":8.0202567964,"imp":15.3404069654,"elo":1234.5,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"RandomForest","family":"Tree-based","x_train":16.2377871584,"imp":15.2141741302,"elo":1245.0,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"RandomForest","family":"Tree-based","x_train":32.6710934428,"imp":15.1267895029,"elo":1254.8,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"RandomForest","family":"Tree-based","x_train":49.1719658028,"imp":15.0853480414,"elo":1259.4,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"RandomForest","family":"Tree-based","x_train":65.9990639089,"imp":15.1111406521,"elo":1262.7,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"RealMLP","family":"Neural Network","x_train":6.7532462417,"imp":15.1005671513,"elo":1281.1,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"RealMLP","family":"Neural Network","x_train":15.5275786908,"imp":12.9072260047,"elo":1413.1,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"RealMLP","family":"Neural Network","x_train":39.1241530408,"imp":11.3635581269,"elo":1512.9,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"RealMLP","family":"Neural Network","x_train":82.7422408171,"imp":10.5674293143,"elo":1553.2,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"RealMLP","family":"Neural Network","x_train":213.2761385894,"imp":9.8481783226,"elo":1599.1,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"RealMLP","family":"Neural Network","x_train":427.9091537602,"imp":9.5297368118,"elo":1614.8,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"RealMLP","family":"Neural Network","x_train":848.9386425085,"imp":9.1601227196,"elo":1634.3,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"RealMLP","family":"Neural Network","x_train":1278.8937139162,"imp":9.0036425298,"elo":1645.3,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"RealMLP","family":"Neural Network","x_train":1719.8202901016,"imp":8.9287868289,"elo":1654.4,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":1.8760518371,"imp":10.0918725787,"elo":1542.8,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":5.1278647155,"imp":10.018663163,"elo":1552.4,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":16.2069927888,"imp":9.8482067878,"elo":1566.8,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":34.2536042268,"imp":9.7015761863,"elo":1583.0,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":88.9628219424,"imp":9.3584259435,"elo":1623.9,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":181.3952243454,"imp":9.000340936,"elo":1645.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":363.9172361826,"imp":8.7779080241,"elo":1656.9,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":547.7650992279,"imp":8.6576561267,"elo":1660.4,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_train":735.5848736649,"imp":8.5856394282,"elo":1660.9,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"SAP-RPT-OSS","family":"Foundation Model","x_train":11.4380569036,"imp":16.9413141811,"elo":1215.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabDPT","family":"Foundation Model","x_train":46.6209023207,"imp":15.3200410441,"elo":1343.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabDPT","family":"Foundation Model","x_train":70.0348846629,"imp":14.1956495304,"elo":1371.8,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TabDPT","family":"Foundation Model","x_train":129.2960112707,"imp":13.0943832644,"elo":1413.9,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TabDPT","family":"Foundation Model","x_train":230.7293949461,"imp":12.6784457778,"elo":1431.4,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TabDPT","family":"Foundation Model","x_train":589.0616829286,"imp":11.7243258163,"elo":1477.2,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TabDPT","family":"Foundation Model","x_train":1187.7578308406,"imp":11.1912530117,"elo":1502.7,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TabDPT","family":"Foundation Model","x_train":2376.2279314343,"imp":10.8135073436,"elo":1519.8,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TabDPT","family":"Foundation Model","x_train":3574.1919132683,"imp":10.4831511393,"elo":1533.6,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TabDPT","family":"Foundation Model","x_train":4786.5989331939,"imp":10.296860814,"elo":1538.9,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"TabDPT-Turbo","family":"Foundation Model","x_train":0.7535798582,"imp":10.8199022081,"elo":1540.5,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabFM","family":"Foundation Model","x_train":27.2884140106,"imp":2.6842884759,"elo":1990.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabICLv2","family":"Foundation Model","x_train":0.6015671442,"imp":6.8659561097,"elo":1713.3,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabM","family":"Neural Network","x_train":2.1306936636,"imp":13.9939671673,"elo":1336.4,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabM","family":"Neural Network","x_train":6.7201323021,"imp":13.1386024727,"elo":1384.2,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TabM","family":"Neural Network","x_train":26.071931656,"imp":12.07671084,"elo":1440.9,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TabM","family":"Neural Network","x_train":56.6403905326,"imp":11.465419546,"elo":1482.1,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TabM","family":"Neural Network","x_train":151.6325084544,"imp":10.9150875666,"elo":1514.9,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TabM","family":"Neural Network","x_train":305.4050159003,"imp":10.6347881155,"elo":1536.6,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TabM","family":"Neural Network","x_train":598.166050268,"imp":10.4092043336,"elo":1551.8,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TabM","family":"Neural Network","x_train":909.6246432443,"imp":10.3205639671,"elo":1559.9,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TabM","family":"Neural Network","x_train":1236.8778796591,"imp":10.2623069414,"elo":1568.2,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"TabPFN-2.6","family":"Foundation Model","x_train":2.7558592937,"imp":7.8605289769,"elo":1746.6,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabPFN-3","family":"Foundation Model","x_train":1.0099025842,"imp":5.8834864036,"elo":1798.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabSTAR","family":"Foundation Model","x_train":110.7816266415,"imp":30.6917614221,"elo":842.3,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TabSTAR","family":"Foundation Model","x_train":125.5711234695,"imp":30.609802755,"elo":858.0,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TabSTAR","family":"Foundation Model","x_train":166.4991276653,"imp":30.4571522335,"elo":864.2,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TabSTAR","family":"Foundation Model","x_train":216.8260972869,"imp":30.0179135156,"elo":881.7,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TabSTAR","family":"Foundation Model","x_train":435.6268489691,"imp":29.0532719309,"elo":906.8,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TabSTAR","family":"Foundation Model","x_train":841.7488888841,"imp":27.8654166105,"elo":933.8,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TabSTAR","family":"Foundation Model","x_train":1663.6865760139,"imp":27.0808278838,"elo":956.7,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TabSTAR","family":"Foundation Model","x_train":2487.2049124756,"imp":26.3846780548,"elo":981.0,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TabSTAR","family":"Foundation Model","x_train":3381.7712162192,"imp":25.7887166563,"elo":1007.2,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"TabSwift","family":"Foundation Model","x_train":0.5069992699,"imp":13.3506819035,"elo":1362.2,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TorchMLP","family":"Neural Network","x_train":2.1848199639,"imp":18.1535807635,"elo":1135.4,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"TorchMLP","family":"Neural Network","x_train":9.222603335,"imp":16.9138550883,"elo":1182.8,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"TorchMLP","family":"Neural Network","x_train":41.2363997061,"imp":15.5421029397,"elo":1240.3,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"TorchMLP","family":"Neural Network","x_train":91.3237652004,"imp":14.7262690578,"elo":1284.5,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"TorchMLP","family":"Neural Network","x_train":218.5473202022,"imp":13.8435434487,"elo":1325.1,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"TorchMLP","family":"Neural Network","x_train":447.0507548682,"imp":13.3314756024,"elo":1355.0,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"TorchMLP","family":"Neural Network","x_train":866.7256429369,"imp":12.9284009506,"elo":1377.2,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"TorchMLP","family":"Neural Network","x_train":1331.6601195387,"imp":12.685478784,"elo":1390.2,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"TorchMLP","family":"Neural Network","x_train":1770.5620854906,"imp":12.4629978646,"elo":1401.4,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"XGBoost","family":"Tree-based","x_train":0.4869354634,"imp":12.9207034717,"elo":1387.7,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"XGBoost","family":"Tree-based","x_train":2.4341782987,"imp":11.9175965636,"elo":1466.8,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"XGBoost","family":"Tree-based","x_train":7.341922179,"imp":11.3659122277,"elo":1515.0,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"XGBoost","family":"Tree-based","x_train":13.4253918933,"imp":11.0012314263,"elo":1536.9,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"XGBoost","family":"Tree-based","x_train":35.1370362218,"imp":10.7494419639,"elo":1552.3,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"XGBoost","family":"Tree-based","x_train":69.8388019133,"imp":10.6449945049,"elo":1560.2,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"XGBoost","family":"Tree-based","x_train":138.6843072833,"imp":10.5779558918,"elo":1567.5,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"XGBoost","family":"Tree-based","x_train":209.6003170598,"imp":10.5660972584,"elo":1571.0,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"XGBoost","family":"Tree-based","x_train":282.1320041804,"imp":10.5606176671,"elo":1574.8,"imputed":false,"imputed_pct":0.0,"n_configs":201.0},{"method":"iLTM","family":"Foundation Model","x_train":88.2701787746,"imp":18.4983781039,"elo":1192.9,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"iLTM","family":"Foundation Model","x_train":168.2367198699,"imp":16.3890454014,"elo":1247.3,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"iLTM","family":"Foundation Model","x_train":410.883351941,"imp":16.2186243252,"elo":1345.3,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"iLTM","family":"Foundation Model","x_train":805.5219751868,"imp":13.5594974448,"elo":1442.5,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"iLTM","family":"Foundation Model","x_train":1992.2815124104,"imp":10.2704282323,"elo":1578.8,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"iLTM","family":"Foundation Model","x_train":2067.9528996121,"imp":10.2338269266,"elo":1584.4,"imputed":false,"imputed_pct":0.0,"n_configs":26.0},{"method":"xRFM","family":"Other","x_train":2.4940806965,"imp":25.9875577867,"elo":1051.9,"imputed":false,"imputed_pct":0.0,"n_configs":1.0},{"method":"xRFM","family":"Other","x_train":5.3133350441,"imp":21.3468517179,"elo":1127.7,"imputed":false,"imputed_pct":0.0,"n_configs":2.0},{"method":"xRFM","family":"Other","x_train":13.8020981623,"imp":16.1353961932,"elo":1255.0,"imputed":false,"imputed_pct":0.0,"n_configs":5.0},{"method":"xRFM","family":"Other","x_train":28.3270720096,"imp":13.9002791385,"elo":1372.9,"imputed":false,"imputed_pct":0.0,"n_configs":10.0},{"method":"xRFM","family":"Other","x_train":70.6047440508,"imp":12.9743181235,"elo":1424.6,"imputed":false,"imputed_pct":0.0,"n_configs":25.0},{"method":"xRFM","family":"Other","x_train":140.5453323732,"imp":12.6248944307,"elo":1441.4,"imputed":false,"imputed_pct":0.0,"n_configs":50.0},{"method":"xRFM","family":"Other","x_train":281.1244162931,"imp":12.4891082036,"elo":1446.3,"imputed":false,"imputed_pct":0.0,"n_configs":100.0},{"method":"xRFM","family":"Other","x_train":422.3532460518,"imp":12.4480188978,"elo":1447.6,"imputed":false,"imputed_pct":0.0,"n_configs":150.0},{"method":"xRFM","family":"Other","x_train":566.7369825686,"imp":12.4628187149,"elo":1446.1,"imputed":false,"imputed_pct":0.0,"n_configs":201.0}];
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 341 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 342 |
-
// already share a color, and each holds only a handful of methods.
|
| 343 |
-
const FAM_MERGED = "Baseline / Other";
|
| 344 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 345 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 346 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 347 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 348 |
-
|
| 349 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 350 |
-
const FAM_VAR = {
|
| 351 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 352 |
-
"Tree-based": "var(--fam-tree)",
|
| 353 |
-
"Neural Network": "var(--fam-nn)",
|
| 354 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 355 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 356 |
-
};
|
| 357 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 358 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 359 |
-
// that chip carries both symbols.
|
| 360 |
-
const FAM_SYMBOL = {
|
| 361 |
-
"Foundation Model": "🧠⚡",
|
| 362 |
-
"Tree-based": "🌳",
|
| 363 |
-
"Neural Network": "🧠🔁",
|
| 364 |
-
"Reference Pipeline": "📊",
|
| 365 |
-
[FAM_MERGED]: "📏 ❓",
|
| 366 |
-
};
|
| 367 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 368 |
-
const VARIANT_VAR = {
|
| 369 |
-
"Default": "var(--var-default)",
|
| 370 |
-
"Tuned": "var(--var-tuned)",
|
| 371 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 372 |
-
};
|
| 373 |
-
|
| 374 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 375 |
-
function famChipLabel(family, count) {
|
| 376 |
-
const symbol = FAM_SYMBOL[family];
|
| 377 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 378 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 379 |
-
}
|
| 380 |
-
|
| 381 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 382 |
-
const FAM_INK = {
|
| 383 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 384 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 385 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 386 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 387 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 388 |
-
};
|
| 389 |
-
|
| 390 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 391 |
-
function el(name, attrs, parent) {
|
| 392 |
-
const node = document.createElementNS(NS, name);
|
| 393 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 394 |
-
if (parent) parent.appendChild(node);
|
| 395 |
-
return node;
|
| 396 |
-
}
|
| 397 |
-
|
| 398 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 399 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 400 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 401 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 402 |
-
function fmtNum(v, decimals) {
|
| 403 |
-
if (v == null || !isFinite(v)) return "—";
|
| 404 |
-
return v.toFixed(decimals);
|
| 405 |
-
}
|
| 406 |
-
|
| 407 |
-
function fmtMetric(metric, v) {
|
| 408 |
-
if (v == null || !isFinite(v)) return "—";
|
| 409 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 410 |
-
}
|
| 411 |
-
|
| 412 |
-
function fmtTime(v) {
|
| 413 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 414 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 415 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 416 |
-
return fmtNum(v, 3) + " s";
|
| 417 |
-
}
|
| 418 |
-
|
| 419 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 420 |
-
function niceStep(raw) {
|
| 421 |
-
if (!(raw > 0)) return 1;
|
| 422 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 423 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 424 |
-
if (mag * m >= raw) return mag * m;
|
| 425 |
-
}
|
| 426 |
-
return mag * 10;
|
| 427 |
-
}
|
| 428 |
-
|
| 429 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 430 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 431 |
-
function ticks(min, max, target) {
|
| 432 |
-
const step = niceStep((max - min) / target);
|
| 433 |
-
const first = Math.ceil(min / step);
|
| 434 |
-
const out = [];
|
| 435 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 436 |
-
return out.length ? out : [min];
|
| 437 |
-
}
|
| 438 |
-
|
| 439 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 440 |
-
function makeTooltip(box) {
|
| 441 |
-
const node = box.querySelector(".tooltip");
|
| 442 |
-
return {
|
| 443 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 444 |
-
move(ev) {
|
| 445 |
-
const r = box.getBoundingClientRect();
|
| 446 |
-
let tx = ev.clientX - r.left + 14;
|
| 447 |
-
const ty = ev.clientY - r.top + 12;
|
| 448 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 449 |
-
node.style.left = tx + "px";
|
| 450 |
-
node.style.top = ty + "px";
|
| 451 |
-
},
|
| 452 |
-
hide() { node.style.display = "none"; },
|
| 453 |
-
};
|
| 454 |
-
}
|
| 455 |
-
|
| 456 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 457 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 458 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 459 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 460 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 461 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 462 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 463 |
-
function setUpPaperView(afterToggle, options) {
|
| 464 |
-
const opts = options || {};
|
| 465 |
-
const root = document.documentElement;
|
| 466 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 467 |
-
const btn = document.getElementById("btn-paper");
|
| 468 |
-
const embedded = window.parent !== window;
|
| 469 |
-
|
| 470 |
-
function setPaper(on) {
|
| 471 |
-
document.body.classList.toggle("paper", on);
|
| 472 |
-
if (on) {
|
| 473 |
-
hostTheme = root.getAttribute("data-theme");
|
| 474 |
-
root.setAttribute("data-theme", "light");
|
| 475 |
-
} else if (hostTheme) {
|
| 476 |
-
root.setAttribute("data-theme", hostTheme);
|
| 477 |
-
} else {
|
| 478 |
-
root.removeAttribute("data-theme");
|
| 479 |
-
}
|
| 480 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 481 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 482 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 483 |
-
postHeight();
|
| 484 |
-
}
|
| 485 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 486 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 487 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 488 |
-
// shareable single file) this page needs its own.
|
| 489 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 490 |
-
window.addEventListener("message", ev => {
|
| 491 |
-
const d = ev.data;
|
| 492 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 493 |
-
});
|
| 494 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 495 |
-
// key press, so its label would fall out of step with the frame.
|
| 496 |
-
if (!embedded) {
|
| 497 |
-
document.addEventListener("keydown", ev => {
|
| 498 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 499 |
-
});
|
| 500 |
-
}
|
| 501 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 502 |
-
}
|
| 503 |
-
|
| 504 |
-
// --- Figure export ---------------------------------------------------------
|
| 505 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 506 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 507 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 508 |
-
// the legend is HTML rather than part of the SVG.
|
| 509 |
-
|
| 510 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 511 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 512 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 513 |
-
// break the PNG path.
|
| 514 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 515 |
-
// once the node leaves this document.
|
| 516 |
-
function resolveVars(root, resolve) {
|
| 517 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 518 |
-
for (const attr of ["fill", "stroke"]) {
|
| 519 |
-
const value = node.getAttribute(attr);
|
| 520 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 521 |
-
}
|
| 522 |
-
}
|
| 523 |
-
}
|
| 524 |
-
|
| 525 |
-
function legendToSvg(container, resolve) {
|
| 526 |
-
const base = container.getBoundingClientRect();
|
| 527 |
-
const group = document.createElementNS(NS, "g");
|
| 528 |
-
let height = 0;
|
| 529 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 530 |
-
const box = item.getBoundingClientRect();
|
| 531 |
-
if (!box.width) continue;
|
| 532 |
-
height = Math.max(height, box.bottom - base.top);
|
| 533 |
-
let textLeft = box.left - base.left;
|
| 534 |
-
const glyph = item.querySelector("svg");
|
| 535 |
-
if (glyph) {
|
| 536 |
-
const gbox = glyph.getBoundingClientRect();
|
| 537 |
-
const wrap = el("g", {
|
| 538 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 539 |
-
}, group);
|
| 540 |
-
const glyphClone = glyph.cloneNode(true);
|
| 541 |
-
resolveVars(glyphClone, resolve);
|
| 542 |
-
wrap.appendChild(glyphClone);
|
| 543 |
-
textLeft = gbox.right - base.left + 5;
|
| 544 |
-
}
|
| 545 |
-
const label = item.textContent.trim();
|
| 546 |
-
if (!label) continue;
|
| 547 |
-
const colored = item.querySelector("[style*='color']");
|
| 548 |
-
const text = el("text", {
|
| 549 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 550 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 551 |
-
}, group);
|
| 552 |
-
text.textContent = label;
|
| 553 |
-
}
|
| 554 |
-
return { group, height: Math.ceil(height) };
|
| 555 |
-
}
|
| 556 |
-
|
| 557 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 558 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 559 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 560 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 561 |
-
const resolve = value => String(value).replace(
|
| 562 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 563 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 564 |
-
|
| 565 |
-
let chartW = 0, chartH = 0;
|
| 566 |
-
for (const part of parts) {
|
| 567 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 568 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 569 |
-
}
|
| 570 |
-
|
| 571 |
-
const out = document.createElementNS(NS, "svg");
|
| 572 |
-
out.setAttribute("xmlns", NS);
|
| 573 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 574 |
-
let top = pad;
|
| 575 |
-
const later = []; // built after the width is known
|
| 576 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 577 |
-
if (legend && legend.height) {
|
| 578 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 579 |
-
later.push(() => out.appendChild(legend.group));
|
| 580 |
-
top += legend.height + 8;
|
| 581 |
-
}
|
| 582 |
-
|
| 583 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 584 |
-
const height = top + chartH + pad;
|
| 585 |
-
out.setAttribute("width", Math.ceil(width));
|
| 586 |
-
out.setAttribute("height", Math.ceil(height));
|
| 587 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 588 |
-
for (const build of later) build();
|
| 589 |
-
|
| 590 |
-
for (const part of parts) {
|
| 591 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 592 |
-
const clone = part.svg.cloneNode(true);
|
| 593 |
-
resolveVars(clone, resolve);
|
| 594 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 595 |
-
}
|
| 596 |
-
return out;
|
| 597 |
-
}
|
| 598 |
-
|
| 599 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 600 |
-
function slugify(text) {
|
| 601 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 602 |
-
}
|
| 603 |
-
|
| 604 |
-
function downloadUrl(url, filename) {
|
| 605 |
-
const a = document.createElement("a");
|
| 606 |
-
a.href = url;
|
| 607 |
-
a.download = filename;
|
| 608 |
-
document.body.appendChild(a);
|
| 609 |
-
a.click();
|
| 610 |
-
a.remove();
|
| 611 |
-
}
|
| 612 |
-
|
| 613 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 614 |
-
function rasterize(svg, scale, done, fail) {
|
| 615 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 616 |
-
const img = new Image();
|
| 617 |
-
img.onload = () => {
|
| 618 |
-
const canvas = document.createElement("canvas");
|
| 619 |
-
canvas.width = Math.round(width * scale);
|
| 620 |
-
canvas.height = Math.round(height * scale);
|
| 621 |
-
const ctx = canvas.getContext("2d");
|
| 622 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 623 |
-
ctx.drawImage(img, 0, 0);
|
| 624 |
-
done(canvas, width, height);
|
| 625 |
-
};
|
| 626 |
-
img.onerror = fail;
|
| 627 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 628 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 629 |
-
}
|
| 630 |
-
|
| 631 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 632 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 633 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 634 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 635 |
-
// and the pixels land at 96*scale dpi.
|
| 636 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 637 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 638 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 639 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 640 |
-
rgb[j] = pixels[i];
|
| 641 |
-
rgb[j + 1] = pixels[i + 1];
|
| 642 |
-
rgb[j + 2] = pixels[i + 2];
|
| 643 |
-
}
|
| 644 |
-
const deflated = new Uint8Array(await new Response(
|
| 645 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 646 |
-
|
| 647 |
-
const encoder = new TextEncoder();
|
| 648 |
-
const chunks = [];
|
| 649 |
-
const offsets = [];
|
| 650 |
-
let cursor = 0;
|
| 651 |
-
const put = data => {
|
| 652 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 653 |
-
chunks.push(bytes);
|
| 654 |
-
cursor += bytes.length;
|
| 655 |
-
};
|
| 656 |
-
const object = (id, body, stream) => {
|
| 657 |
-
offsets[id] = cursor;
|
| 658 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 659 |
-
if (stream) {
|
| 660 |
-
put("stream\n");
|
| 661 |
-
put(stream);
|
| 662 |
-
put("\nendstream\n");
|
| 663 |
-
}
|
| 664 |
-
put("endobj\n");
|
| 665 |
-
};
|
| 666 |
-
|
| 667 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 668 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 669 |
-
put("%PDF-1.4\n");
|
| 670 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 671 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 672 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 673 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 674 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 675 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 676 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 677 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 678 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 679 |
-
|
| 680 |
-
const xref = cursor;
|
| 681 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 682 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 683 |
-
put(table);
|
| 684 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 685 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 686 |
-
}
|
| 687 |
-
|
| 688 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 689 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 690 |
-
function setUpExport(getParts, basename) {
|
| 691 |
-
const buttons = {
|
| 692 |
-
svg: document.getElementById("btn-svg"),
|
| 693 |
-
png: document.getElementById("btn-png"),
|
| 694 |
-
pdf: document.getElementById("btn-pdf"),
|
| 695 |
-
};
|
| 696 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 697 |
-
|
| 698 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 699 |
-
function complain(format) {
|
| 700 |
-
const button = buttons[format];
|
| 701 |
-
if (!button) return;
|
| 702 |
-
const label = button.textContent;
|
| 703 |
-
button.textContent = "failed";
|
| 704 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 705 |
-
}
|
| 706 |
-
|
| 707 |
-
function run(format) {
|
| 708 |
-
const svg = figure();
|
| 709 |
-
const name = basename();
|
| 710 |
-
if (format === "svg") {
|
| 711 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 712 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 713 |
-
return;
|
| 714 |
-
}
|
| 715 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 716 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 717 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 718 |
-
if (format === "png") {
|
| 719 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 720 |
-
} else {
|
| 721 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 722 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 723 |
-
.catch(() => complain("pdf"));
|
| 724 |
-
}
|
| 725 |
-
}, () => complain(format));
|
| 726 |
-
}
|
| 727 |
-
|
| 728 |
-
for (const format of Object.keys(buttons)) {
|
| 729 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 730 |
-
}
|
| 731 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 732 |
-
window.addEventListener("message", ev => {
|
| 733 |
-
const d = ev.data;
|
| 734 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 735 |
-
});
|
| 736 |
-
}
|
| 737 |
-
|
| 738 |
-
// When embedded, report the content height so the host page can size the
|
| 739 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 740 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 741 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 742 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 743 |
-
// stops re-posting once the height settles.
|
| 744 |
-
let lastPostedHeight = 0;
|
| 745 |
-
function postHeight() {
|
| 746 |
-
if (window.parent === window) return;
|
| 747 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 748 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 749 |
-
lastPostedHeight = height;
|
| 750 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 751 |
-
}
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
const TRAJECTORY = CONFIG.mode === "trajectory";
|
| 755 |
-
|
| 756 |
-
const titleEl = document.getElementById("title");
|
| 757 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 758 |
-
|
| 759 |
-
// Column order: chips/controls left of the chart, or mirrored.
|
| 760 |
-
document.getElementById("grid").classList.add(CONFIG.chipsSide === "right" ? "chips-right" : "chips-left");
|
| 761 |
-
|
| 762 |
-
const svg = document.getElementById("chart");
|
| 763 |
-
const box = document.getElementById("chartbox");
|
| 764 |
-
const chipsBox = document.getElementById("chips");
|
| 765 |
-
const controlsBox = document.querySelector(".controls");
|
| 766 |
-
const tip = makeTooltip(box);
|
| 767 |
-
|
| 768 |
-
// Marker glyph per variant at (cx, cy); trajectories use circles everywhere.
|
| 769 |
-
function drawMark(parent, cx, cy, variant, color, size, opacity, dataM, whiteStroke) {
|
| 770 |
-
const common = { opacity: opacity, "data-m": dataM };
|
| 771 |
-
let node;
|
| 772 |
-
if (TRAJECTORY || variant === "Default" || !variant) {
|
| 773 |
-
node = el("circle", { ...common, cx, cy, r: size, fill: color }, parent);
|
| 774 |
-
} else if (variant === "Tuned") {
|
| 775 |
-
const s = size * 1.75;
|
| 776 |
-
node = el("rect", { ...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1.5, fill: color }, parent);
|
| 777 |
-
} else if (variant === "Tuned + Ens.") {
|
| 778 |
-
const d = size * 0.95;
|
| 779 |
-
node = el("path", {
|
| 780 |
-
...common,
|
| 781 |
-
d: `M${cx - d},${cy - d} L${cx + d},${cy + d} M${cx - d},${cy + d} L${cx + d},${cy - d}`,
|
| 782 |
-
stroke: color, "stroke-width": size * 0.62, fill: "none", "stroke-linecap": "round",
|
| 783 |
-
}, parent);
|
| 784 |
-
} else {
|
| 785 |
-
// Any other variant (e.g. "Baseline", holdout types): diamond.
|
| 786 |
-
const s = size * 1.45;
|
| 787 |
-
node = el("rect", {
|
| 788 |
-
...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1,
|
| 789 |
-
fill: color, transform: `rotate(45 ${cx} ${cy})`,
|
| 790 |
-
}, parent);
|
| 791 |
-
}
|
| 792 |
-
if (whiteStroke && variant !== "Tuned + Ens.") {
|
| 793 |
-
node.setAttribute("stroke", "var(--card)");
|
| 794 |
-
node.setAttribute("stroke-width", "1");
|
| 795 |
-
}
|
| 796 |
-
return node;
|
| 797 |
-
}
|
| 798 |
-
|
| 799 |
-
function drawImputedRing(parent, cx, cy, size, color, opacity, dataM) {
|
| 800 |
-
el("circle", {
|
| 801 |
-
cx, cy, r: size + 4.5, fill: "none", stroke: color, "stroke-width": 1.4,
|
| 802 |
-
"stroke-dasharray": "3 2.5", opacity: opacity, "data-m": dataM,
|
| 803 |
-
}, parent);
|
| 804 |
-
}
|
| 805 |
-
|
| 806 |
-
// Fat green arrow pointing into the optimal corner (mirrors the static
|
| 807 |
-
// figures' "Optimal" arrow so both read the same way).
|
| 808 |
-
function drawOptimalArrow(parent, lowerBetter, M, W, H) {
|
| 809 |
-
const cornerY = lowerBetter ? H - M.b - 12 : M.t + 12;
|
| 810 |
-
const tailY = lowerBetter ? H - M.b - 64 : M.t + 64;
|
| 811 |
-
const cx = M.l + 12, tx = M.l + 64;
|
| 812 |
-
const dx = cx - tx, dy = cornerY - tailY;
|
| 813 |
-
const len = Math.hypot(dx, dy);
|
| 814 |
-
const ux = dx / len, uy = dy / len;
|
| 815 |
-
const headLen = 16;
|
| 816 |
-
const bx = cx - ux * headLen, by = cornerY - uy * headLen; // head base center
|
| 817 |
-
// line stops at the head base
|
| 818 |
-
el("line", {
|
| 819 |
-
x1: tx, y1: tailY, x2: bx, y2: by,
|
| 820 |
-
stroke: "var(--optimal)", "stroke-width": 13, "stroke-linecap": "round", opacity: 0.92,
|
| 821 |
-
}, parent);
|
| 822 |
-
const px = -uy, py = ux; // perpendicular
|
| 823 |
-
el("polygon", {
|
| 824 |
-
points: `${cx},${cornerY} ${bx + px * 11},${by + py * 11} ${bx - px * 11},${by - py * 11}`,
|
| 825 |
-
fill: "var(--optimal)", opacity: 0.92,
|
| 826 |
-
}, parent);
|
| 827 |
-
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
| 828 |
-
if (angle > 90 || angle < -90) angle += 180;
|
| 829 |
-
const mx = (tx + bx) / 2, my = (tailY + by) / 2;
|
| 830 |
-
const t = el("text", {
|
| 831 |
-
x: mx, y: my, "text-anchor": "middle", "dominant-baseline": "middle",
|
| 832 |
-
"font-size": 10.5, "font-weight": 700, fill: "#ffffff",
|
| 833 |
-
transform: `rotate(${angle} ${mx} ${my})`,
|
| 834 |
-
}, parent);
|
| 835 |
-
t.textContent = "Optimal";
|
| 836 |
-
}
|
| 837 |
-
|
| 838 |
-
// ---------- data ----------
|
| 839 |
-
const byMethod = new Map();
|
| 840 |
-
for (const p of POINTS) {
|
| 841 |
-
if (!byMethod.has(p.method)) byMethod.set(p.method, []);
|
| 842 |
-
byMethod.get(p.method).push(p); // insertion order = builder's point order
|
| 843 |
-
}
|
| 844 |
-
|
| 845 |
-
const METRICS = CONFIG.metrics;
|
| 846 |
-
let metricKey = METRICS[0].key;
|
| 847 |
-
const metricByKey = {};
|
| 848 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 849 |
-
|
| 850 |
-
// Single time axis per explorer (the scatter ships inference time, the
|
| 851 |
-
// trajectories train time).
|
| 852 |
-
const X_AXIS = CONFIG.xAxes[0];
|
| 853 |
-
const xKey = X_AXIS.key;
|
| 854 |
-
|
| 855 |
-
function mval(p, metric) { return p[metric.key]; }
|
| 856 |
-
|
| 857 |
-
function computeFront(metric) {
|
| 858 |
-
const xk = xKey;
|
| 859 |
-
const pts = [...POINTS].sort((a, b) =>
|
| 860 |
-
a[xk] - b[xk] || (metric.lowerBetter ? mval(a, metric) - mval(b, metric) : mval(b, metric) - mval(a, metric)));
|
| 861 |
-
const verts = [];
|
| 862 |
-
const methods = new Set();
|
| 863 |
-
let best = null;
|
| 864 |
-
for (const p of pts) {
|
| 865 |
-
const v = mval(p, metric);
|
| 866 |
-
if (best === null || (metric.lowerBetter ? v < best : v > best)) {
|
| 867 |
-
if (best !== null) verts.push([p[xk], best]);
|
| 868 |
-
verts.push([p[xk], v]);
|
| 869 |
-
best = v;
|
| 870 |
-
methods.add(p.method);
|
| 871 |
-
}
|
| 872 |
-
}
|
| 873 |
-
return { verts, methods };
|
| 874 |
-
}
|
| 875 |
-
|
| 876 |
-
const state = { active: new Set(computeFront(metricByKey[metricKey]).methods) };
|
| 877 |
-
|
| 878 |
-
// ---------- chart ----------
|
| 879 |
-
// A flat, fixed-height plot: two of these panels then fit on one screen.
|
| 880 |
-
const CHART_H = 400;
|
| 881 |
-
const M = { l: 62, r: 18, t: 14, b: 52 };
|
| 882 |
-
|
| 883 |
-
function render() {
|
| 884 |
-
const metric = metricByKey[metricKey];
|
| 885 |
-
svg.textContent = "";
|
| 886 |
-
const W = Math.max(360, Math.round(box.clientWidth));
|
| 887 |
-
const H = CHART_H;
|
| 888 |
-
svg.setAttribute("width", W);
|
| 889 |
-
svg.setAttribute("height", H);
|
| 890 |
-
// Keep the chip list from outgrowing the chart beside it.
|
| 891 |
-
chipsBox.style.maxHeight = Math.max(170, H - controlsBox.offsetHeight + 20) + "px";
|
| 892 |
-
|
| 893 |
-
// x scale (log)
|
| 894 |
-
const xsAll = POINTS.map(p => p[xKey]);
|
| 895 |
-
const xmin = Math.min(...xsAll) * 0.65, xmax = Math.max(...xsAll) * 1.6;
|
| 896 |
-
const lx0 = Math.log10(xmin), lx1 = Math.log10(xmax);
|
| 897 |
-
const X = v => M.l + (Math.log10(v) - lx0) / (lx1 - lx0) * (W - M.l - M.r);
|
| 898 |
-
|
| 899 |
-
const vals = POINTS.map(p => mval(p, metric));
|
| 900 |
-
let y0, y1;
|
| 901 |
-
if (metric.fromZero) {
|
| 902 |
-
y0 = 0; y1 = Math.max(...vals) * 1.07;
|
| 903 |
-
} else {
|
| 904 |
-
const pad = (Math.max(...vals) - Math.min(...vals)) * 0.07;
|
| 905 |
-
y0 = Math.min(...vals) - pad; y1 = Math.max(...vals) + pad;
|
| 906 |
-
}
|
| 907 |
-
const Y = v => M.t + (1 - (v - y0) / (y1 - y0)) * (H - M.t - M.b);
|
| 908 |
-
|
| 909 |
-
// grid + axes
|
| 910 |
-
const grid = el("g", {}, svg);
|
| 911 |
-
for (let e = Math.ceil(lx0); Math.pow(10, e) < xmax; e++) {
|
| 912 |
-
const gx = X(Math.pow(10, e));
|
| 913 |
-
el("line", { x1: gx, y1: M.t, x2: gx, y2: H - M.b, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 914 |
-
const lbl = fmtNum(Math.pow(10, e), e >= 0 ? 0 : -e);
|
| 915 |
-
el("text", { x: gx, y: H - M.b + 20, "text-anchor": "middle", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 916 |
-
.textContent = lbl;
|
| 917 |
-
}
|
| 918 |
-
for (const yv of ticks(y0, y1, 6)) {
|
| 919 |
-
const gy = Y(yv);
|
| 920 |
-
el("line", { x1: M.l, y1: gy, x2: W - M.r, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 921 |
-
el("text", { x: M.l - 8, y: gy + 4, "text-anchor": "end", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 922 |
-
.textContent = fmtNum(yv, Number.isInteger(yv) ? 0 : metric.decimals);
|
| 923 |
-
}
|
| 924 |
-
el("rect", { x: M.l, y: M.t, width: W - M.l - M.r, height: H - M.t - M.b, fill: "none", stroke: "var(--line)" }, grid);
|
| 925 |
-
el("text", {
|
| 926 |
-
x: (M.l + W - M.r) / 2, y: H - 10, "text-anchor": "middle", "font-size": 14,
|
| 927 |
-
"font-weight": 650, fill: "var(--ink)",
|
| 928 |
-
}, grid).textContent = X_AXIS.axisLabel;
|
| 929 |
-
el("text", {
|
| 930 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": 14, "font-weight": 650, fill: "var(--ink)",
|
| 931 |
-
transform: `translate(16 ${(M.t + H - M.b) / 2}) rotate(-90)`,
|
| 932 |
-
}, grid).textContent = metric.axisLabel;
|
| 933 |
-
|
| 934 |
-
drawOptimalArrow(grid, metric.lowerBetter, M, W, H);
|
| 935 |
-
|
| 936 |
-
// pareto front (always shown)
|
| 937 |
-
const front = computeFront(metric);
|
| 938 |
-
const fv = front.verts;
|
| 939 |
-
if (fv.length) {
|
| 940 |
-
let d = `M${X(fv[0][0])},${metric.lowerBetter ? M.t : H - M.b}`;
|
| 941 |
-
for (const [fx, fy] of fv) d += ` L${X(fx)},${Y(fy)}`;
|
| 942 |
-
d += ` L${W - M.r},${Y(fv[fv.length - 1][1])}`;
|
| 943 |
-
el("path", { d, fill: "none", stroke: "var(--ink)", "stroke-width": 1.6, "stroke-dasharray": "7 5", opacity: 0.85 }, svg);
|
| 944 |
-
}
|
| 945 |
-
|
| 946 |
-
const isOn = m => state.active.has(m);
|
| 947 |
-
|
| 948 |
-
// connectors: variant links (scatter) / the trajectory itself
|
| 949 |
-
const conn = el("g", {}, svg);
|
| 950 |
-
for (const [method, pts] of byMethod) {
|
| 951 |
-
if (pts.length < 2) continue;
|
| 952 |
-
const on = isOn(method);
|
| 953 |
-
if (!TRAJECTORY && !on) continue; // scatter: connectors only for active methods
|
| 954 |
-
const dd = pts.map((p, i) => `${i ? "L" : "M"}${X(p[xKey])},${Y(mval(p, metric))}`).join(" ");
|
| 955 |
-
el("path", {
|
| 956 |
-
d: dd, fill: "none",
|
| 957 |
-
stroke: on ? FAM_VAR[pts[0].family] : "var(--pt-muted)",
|
| 958 |
-
"stroke-width": on ? (TRAJECTORY ? 2 : 1.4) : 1,
|
| 959 |
-
opacity: on ? 0.6 : 0.35,
|
| 960 |
-
"data-m": method,
|
| 961 |
-
}, conn);
|
| 962 |
-
}
|
| 963 |
-
|
| 964 |
-
// points: inactive first, active on top
|
| 965 |
-
const ptsOff = el("g", {}, svg);
|
| 966 |
-
const ptsOn = el("g", {}, svg);
|
| 967 |
-
for (const [method, pts] of byMethod) {
|
| 968 |
-
const on = isOn(method);
|
| 969 |
-
for (const p of pts) {
|
| 970 |
-
const color = on ? FAM_VAR[p.family] : "var(--pt-muted)";
|
| 971 |
-
const size = (on ? 7 : 5) * (TRAJECTORY ? 0.8 : 1);
|
| 972 |
-
const op = on ? 0.95 : 0.5;
|
| 973 |
-
drawMark(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), p.variant, color, size, op, p.method, on);
|
| 974 |
-
// Imputation ring: every affected point in scatter mode; only the
|
| 975 |
-
// trajectory's end point in trajectory mode (a ring on all ~8 line
|
| 976 |
-
// points would read as beads, and the chip's ‡ already flags the line).
|
| 977 |
-
if (p.imputed && (!TRAJECTORY || p === pts[pts.length - 1])) {
|
| 978 |
-
drawImputedRing(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), size, color, op, p.method);
|
| 979 |
-
}
|
| 980 |
-
}
|
| 981 |
-
}
|
| 982 |
-
|
| 983 |
-
// labels for active methods at their best point, greedy de-overlap
|
| 984 |
-
const labels = [];
|
| 985 |
-
for (const [method, pts] of byMethod) {
|
| 986 |
-
if (!isOn(method)) continue;
|
| 987 |
-
const best = pts.reduce((a, b) =>
|
| 988 |
-
(metric.lowerBetter ? mval(a, metric) < mval(b, metric) : mval(a, metric) > mval(b, metric)) ? a : b);
|
| 989 |
-
labels.push({ method, family: best.family, x: X(best[xKey]) + 10, y: Y(mval(best, metric)) - 10 });
|
| 990 |
-
}
|
| 991 |
-
labels.sort((a, b) => a.y - b.y);
|
| 992 |
-
for (let i = 1; i < labels.length; i++) {
|
| 993 |
-
for (let j = 0; j < i; j++) {
|
| 994 |
-
if (Math.abs(labels[i].x - labels[j].x) < 110 && Math.abs(labels[i].y - labels[j].y) < 15) {
|
| 995 |
-
labels[i].y = labels[j].y + 15;
|
| 996 |
-
}
|
| 997 |
-
}
|
| 998 |
-
}
|
| 999 |
-
const lg = el("g", {}, svg);
|
| 1000 |
-
for (const l of labels) {
|
| 1001 |
-
const t = el("text", {
|
| 1002 |
-
x: Math.min(l.x, W - M.r - 8), y: Math.max(l.y, M.t + 12), "font-size": 13, "font-weight": 700,
|
| 1003 |
-
fill: FAM_VAR[l.family], "paint-order": "stroke", stroke: "var(--card)", "stroke-width": 3.5,
|
| 1004 |
-
"text-anchor": l.x > W - 120 ? "end" : "start",
|
| 1005 |
-
}, lg);
|
| 1006 |
-
t.textContent = l.method;
|
| 1007 |
-
}
|
| 1008 |
-
|
| 1009 |
-
// invisible hit targets on top (bigger than marks)
|
| 1010 |
-
const hits = el("g", {}, svg);
|
| 1011 |
-
for (const p of POINTS) {
|
| 1012 |
-
const h = el("circle", { cx: X(p[xKey]), cy: Y(mval(p, metric)), r: 12, fill: "transparent", cursor: "pointer" }, hits);
|
| 1013 |
-
h.addEventListener("mouseenter", ev => showTip(p, ev));
|
| 1014 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1015 |
-
h.addEventListener("mouseleave", () => hideTip(p.method));
|
| 1016 |
-
h.addEventListener("click", () => toggle(p.method));
|
| 1017 |
-
}
|
| 1018 |
-
}
|
| 1019 |
-
|
| 1020 |
-
// Temporary hover emphasis without a re-render (a re-render would replace
|
| 1021 |
-
// the hit node under the cursor mid-hover).
|
| 1022 |
-
function emphasize(method, on) {
|
| 1023 |
-
svg.querySelectorAll(`[data-m="${CSS.escape(method)}"]`).forEach(n => {
|
| 1024 |
-
if (on) {
|
| 1025 |
-
if (!n.dataset.save) n.dataset.save = n.getAttribute("opacity") || "1";
|
| 1026 |
-
n.setAttribute("opacity", "0.95");
|
| 1027 |
-
} else if (n.dataset.save) {
|
| 1028 |
-
n.setAttribute("opacity", n.dataset.save);
|
| 1029 |
-
delete n.dataset.save;
|
| 1030 |
-
}
|
| 1031 |
-
});
|
| 1032 |
-
}
|
| 1033 |
-
|
| 1034 |
-
function showTip(p, ev) {
|
| 1035 |
-
emphasize(p.method, true);
|
| 1036 |
-
const sub = TRAJECTORY ? (p.n_configs != null ? `${p.n_configs} configs` : "") : (p.variant || "");
|
| 1037 |
-
let html = `<div class="t-name">${p.method}` + (sub ? ` <span class="t-var">(${sub})</span>` : "") + "</div>" +
|
| 1038 |
-
`<div>${p.family}</div>`;
|
| 1039 |
-
for (const m of METRICS) {
|
| 1040 |
-
html += `<div>${m.label}: <b>${fmtMetric(m, mval(p, m))}</b></div>`;
|
| 1041 |
-
}
|
| 1042 |
-
html += `<div>${X_AXIS.short}: <b>${fmtTime(p[xKey])}</b></div>`;
|
| 1043 |
-
if (p.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(p.imputed_pct, 0)}% of datasets</div>`;
|
| 1044 |
-
tip.show(html, ev);
|
| 1045 |
-
}
|
| 1046 |
-
function hideTip(method) {
|
| 1047 |
-
emphasize(method, false);
|
| 1048 |
-
tip.hide();
|
| 1049 |
-
}
|
| 1050 |
-
|
| 1051 |
-
// ---------- chips ----------
|
| 1052 |
-
const chipByMethod = new Map();
|
| 1053 |
-
const famChips = new Map();
|
| 1054 |
-
function familyMethods(fam) {
|
| 1055 |
-
return [...byMethod.keys()].filter(m => byMethod.get(m)[0].family === fam);
|
| 1056 |
-
}
|
| 1057 |
-
// Chips are listed by leaderboard rank — best Elo first when Elo is
|
| 1058 |
-
// configured, otherwise best value of the primary metric.
|
| 1059 |
-
const RANK_METRIC = metricByKey["elo"] || metricByKey[METRICS[0].key];
|
| 1060 |
-
function bestVal(method) {
|
| 1061 |
-
const vals = byMethod.get(method).map(p => mval(p, RANK_METRIC));
|
| 1062 |
-
return RANK_METRIC.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 1063 |
-
}
|
| 1064 |
-
function rankSorted(methods) {
|
| 1065 |
-
return [...methods].sort((a, b) =>
|
| 1066 |
-
RANK_METRIC.lowerBetter ? bestVal(a) - bestVal(b) : bestVal(b) - bestVal(a));
|
| 1067 |
-
}
|
| 1068 |
-
function buildChips() {
|
| 1069 |
-
for (const fam of FAM_ORDER) {
|
| 1070 |
-
const methods = rankSorted(familyMethods(fam));
|
| 1071 |
-
if (!methods.length) continue;
|
| 1072 |
-
const row = document.createElement("div");
|
| 1073 |
-
row.className = "chiprow";
|
| 1074 |
-
const famBtn = document.createElement("button");
|
| 1075 |
-
famBtn.className = "famchip";
|
| 1076 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1077 |
-
famBtn.innerHTML = famChipLabel(fam, methods.length);
|
| 1078 |
-
famBtn.title = `Toggle all ${methods.length} ${fam} methods`;
|
| 1079 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1080 |
-
row.appendChild(famBtn);
|
| 1081 |
-
famChips.set(fam, famBtn);
|
| 1082 |
-
const set = document.createElement("div");
|
| 1083 |
-
set.className = "chipset";
|
| 1084 |
-
for (const m of methods) {
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "chip";
|
| 1087 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1088 |
-
const imputed = byMethod.get(m).some(p => p.imputed);
|
| 1089 |
-
const label = document.createElement("span");
|
| 1090 |
-
label.textContent = m;
|
| 1091 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1092 |
-
b.appendChild(label);
|
| 1093 |
-
if (imputed) {
|
| 1094 |
-
const mark = document.createElement("span");
|
| 1095 |
-
mark.className = "imp-mark";
|
| 1096 |
-
mark.textContent = "‡";
|
| 1097 |
-
b.appendChild(mark);
|
| 1098 |
-
}
|
| 1099 |
-
b.title = m + (imputed ? " — partially imputed" : "");
|
| 1100 |
-
b.addEventListener("click", () => toggle(m));
|
| 1101 |
-
set.appendChild(b);
|
| 1102 |
-
chipByMethod.set(m, b);
|
| 1103 |
-
}
|
| 1104 |
-
row.appendChild(set);
|
| 1105 |
-
chipsBox.appendChild(row);
|
| 1106 |
-
}
|
| 1107 |
-
}
|
| 1108 |
-
function syncChips() {
|
| 1109 |
-
for (const [m, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.active.has(m)));
|
| 1110 |
-
for (const [fam, b] of famChips) {
|
| 1111 |
-
b.setAttribute("aria-pressed", String(familyMethods(fam).every(m => state.active.has(m))));
|
| 1112 |
-
}
|
| 1113 |
-
}
|
| 1114 |
-
function toggle(m) {
|
| 1115 |
-
if (state.active.has(m)) state.active.delete(m); else state.active.add(m);
|
| 1116 |
-
syncChips();
|
| 1117 |
-
render();
|
| 1118 |
-
}
|
| 1119 |
-
function toggleFamily(fam) {
|
| 1120 |
-
const methods = familyMethods(fam);
|
| 1121 |
-
const allOn = methods.every(m => state.active.has(m));
|
| 1122 |
-
for (const m of methods) {
|
| 1123 |
-
if (allOn) state.active.delete(m); else state.active.add(m);
|
| 1124 |
-
}
|
| 1125 |
-
syncChips();
|
| 1126 |
-
render();
|
| 1127 |
-
}
|
| 1128 |
-
function setActive(methods) {
|
| 1129 |
-
state.active = new Set(methods);
|
| 1130 |
-
syncChips();
|
| 1131 |
-
render();
|
| 1132 |
-
}
|
| 1133 |
-
document.getElementById("btn-front").addEventListener("click",
|
| 1134 |
-
() => setActive(computeFront(metricByKey[metricKey]).methods));
|
| 1135 |
-
document.getElementById("btn-all").addEventListener("click", () => setActive([...byMethod.keys()]));
|
| 1136 |
-
document.getElementById("btn-none").addEventListener("click", () => setActive([]));
|
| 1137 |
-
|
| 1138 |
-
// metric selector (hidden when only one metric is configured)
|
| 1139 |
-
const metricPick = document.getElementById("metricpick");
|
| 1140 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1141 |
-
if (METRICS.length > 1) {
|
| 1142 |
-
metricPick.hidden = false;
|
| 1143 |
-
for (const m of METRICS) {
|
| 1144 |
-
const opt = document.createElement("option");
|
| 1145 |
-
opt.value = m.key;
|
| 1146 |
-
opt.textContent = m.label;
|
| 1147 |
-
metricSelect.appendChild(opt);
|
| 1148 |
-
}
|
| 1149 |
-
metricSelect.addEventListener("change", ev => {
|
| 1150 |
-
metricKey = ev.target.value;
|
| 1151 |
-
render();
|
| 1152 |
-
});
|
| 1153 |
-
}
|
| 1154 |
-
|
| 1155 |
-
// ---------- legend strip ----------
|
| 1156 |
-
function buildLegend() {
|
| 1157 |
-
const box2 = document.getElementById("legendstrip");
|
| 1158 |
-
let html = "";
|
| 1159 |
-
if (!TRAJECTORY) {
|
| 1160 |
-
html +=
|
| 1161 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><circle cx="7" cy="7" r="5" fill="var(--muted)"/></svg> Default</span>' +
|
| 1162 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" rx="1.5" fill="var(--muted)"/></svg> Tuned</span>' +
|
| 1163 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><path d="M3,3 L11,11 M3,11 L11,3" stroke="var(--muted)" stroke-width="2.6" stroke-linecap="round"/></svg> Tuned + Ensembled</span>';
|
| 1164 |
-
} else {
|
| 1165 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--muted)" stroke-width="2"/><circle cx="6" cy="4" r="2.6" fill="var(--muted)"/><circle cx="16" cy="4" r="2.6" fill="var(--muted)"/></svg> Tuning trajectory (more configs → more time)</span>';
|
| 1166 |
-
}
|
| 1167 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--ink)" stroke-width="1.6" stroke-dasharray="6 4"/></svg> Pareto front (always shown)</span>';
|
| 1168 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1169 |
-
html += '<span class="item"><svg width="18" height="18" viewBox="0 0 18 18"><circle cx="9" cy="9" r="4" fill="var(--muted)"/><circle cx="9" cy="9" r="7.5" fill="none" stroke="var(--muted)" stroke-width="1.3" stroke-dasharray="3 2.5"/></svg> ‡ partially imputed</span>';
|
| 1170 |
-
}
|
| 1171 |
-
// Model family, named: highlighted points are colored by family, and in paper
|
| 1172 |
-
// view the chip list that would otherwise decode them is hidden.
|
| 1173 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => p.family === f));
|
| 1174 |
-
if (families.length > 1) {
|
| 1175 |
-
html += '<span class="legendbreak"></span><span class="item">Family:</span>';
|
| 1176 |
-
for (const fam of families) {
|
| 1177 |
-
html += `<span class="item"><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1178 |
-
`<circle cx="6" cy="6" r="5" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1179 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`;
|
| 1180 |
-
}
|
| 1181 |
-
}
|
| 1182 |
-
box2.innerHTML = html;
|
| 1183 |
-
}
|
| 1184 |
-
|
| 1185 |
-
// ---------- paper view ----------
|
| 1186 |
-
setUpPaperView(render);
|
| 1187 |
-
setUpExport(() => [{ svg: svg, dx: 0 }], () => slugify(document.title));
|
| 1188 |
-
|
| 1189 |
-
// ---------- data table ----------
|
| 1190 |
-
function buildTable() {
|
| 1191 |
-
const m0 = metricByKey[METRICS[0].key];
|
| 1192 |
-
const rows = [...POINTS].sort((a, b) =>
|
| 1193 |
-
m0.lowerBetter ? mval(a, m0) - mval(b, m0) : mval(b, m0) - mval(a, m0));
|
| 1194 |
-
let html = "<table><thead><tr><th>Method</th>";
|
| 1195 |
-
html += TRAJECTORY ? "<th>Configs</th>" : "<th>Variant</th>";
|
| 1196 |
-
html += "<th>Family</th>";
|
| 1197 |
-
for (const m of METRICS) html += `<th>${m.label}</th>`;
|
| 1198 |
-
html += `<th>${X_AXIS.short}</th><th>Imputed</th></tr></thead><tbody>`;
|
| 1199 |
-
for (const p of rows) {
|
| 1200 |
-
html += `<tr><td>${p.method}</td><td>${TRAJECTORY ? (p.n_configs != null ? p.n_configs : "—") : p.variant}</td><td>${p.family}</td>`;
|
| 1201 |
-
for (const m of METRICS) html += `<td>${fmtMetric(m, mval(p, m))}</td>`;
|
| 1202 |
-
html += `<td>${fmtNum(p[xKey], 3)}</td>`;
|
| 1203 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1204 |
-
}
|
| 1205 |
-
html += "</tbody></table>";
|
| 1206 |
-
document.getElementById("tblwrap").innerHTML = html;
|
| 1207 |
-
}
|
| 1208 |
-
|
| 1209 |
-
const _renderInner = render;
|
| 1210 |
-
render = function () {
|
| 1211 |
-
_renderInner();
|
| 1212 |
-
postHeight();
|
| 1213 |
-
};
|
| 1214 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1215 |
-
let resizeTimer = null;
|
| 1216 |
-
window.addEventListener("resize", () => {
|
| 1217 |
-
clearTimeout(resizeTimer);
|
| 1218 |
-
resizeTimer = setTimeout(render, 120);
|
| 1219 |
-
});
|
| 1220 |
-
window.addEventListener("load", postHeight);
|
| 1221 |
-
|
| 1222 |
-
buildChips();
|
| 1223 |
-
buildLegend();
|
| 1224 |
-
buildTable();
|
| 1225 |
-
syncChips();
|
| 1226 |
-
render();
|
| 1227 |
-
})();
|
| 1228 |
-
</script>
|
| 1229 |
-
</body>
|
| 1230 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/website_leaderboard.csv
DELETED
|
@@ -1,71 +0,0 @@
|
|
| 1 |
-
#,Type,TypeName,Model,Elo [⬆️],Elo 95% CI,Score [⬆️],Rank [⬇️],Harmonic Rank [⬇️],Improvability (%) [⬇️],Median Train Time (s/1K) [⬇️],Median Predict Time (s/1K) [⬇️],Verified,Imputed (%) [⬇️],Imputed,Hardware
|
| 2 |
-
0,🧠⚡,Foundation Model,[TabFM (default)](https://github.com/google-research/tabfm),1986.0,+306/-145,0.867,4.41,1.69,2.683,27.29,13.119,✔️,0.0,False,GPU
|
| 3 |
-
1,📊,Reference Pipeline,"[AutoGluon 1.5 (extreme, 4h)](https://arxiv.org/abs/2003.06505)",1899.0,+85/-49,0.71,6.33,2.98,4.858,191.18,2.207,✔️,0.0,False,GPU
|
| 4 |
-
2,🧠⚡,Foundation Model,[TabPFN-3 (default)](https://arxiv.org/abs/2605.13986),1794.0,+214/-135,0.659,9.55,3.26,5.878,1.01,0.215,✔️,0.0,False,GPU
|
| 5 |
-
3,📊,Reference Pipeline,"[AutoGluon 1.4 (best, 4h)](https://arxiv.org/abs/2003.06505)",1775.0,+83/-51,0.579,10.23,4.46,6.048,432.36,4.085,✔️,0.0,False,CPU
|
| 6 |
-
4,🧠⚡,Foundation Model,[TabPFN-2.6 (default)](https://arxiv.org/abs/2511.08667),1722.0,+130/-75,0.504,12.39,8.78,7.846,2.76,0.701,✔️,0.0,False,GPU
|
| 7 |
-
5,🧠⚡,Foundation Model,[TabICLv2 (default)](https://arxiv.org/abs/2602.11139),1697.0,+186/-110,0.541,13.53,4.41,6.851,0.6,0.119,✔️,0.0,False,GPU
|
| 8 |
-
6,🧠⚡,Foundation Model,[RealTabPFN-2.5 (tuned + ensembled)](https://arxiv.org/abs/2511.08667),1646.0,+142/-104,0.446,16.07,8.48,8.576,735.58,11.736,✔️,0.0,False,GPU
|
| 9 |
-
7,🧠🔁,Neural Network,[RealMLP (tuned + ensembled)](https://arxiv.org/abs/2407.04491),1625.0,+92/-92,0.412,17.17,11.86,8.917,1719.82,1.675,✔️,0.0,False,GPU
|
| 10 |
-
8,🧠🔁,Neural Network,[ModernNCA (tuned + ensembled)](https://arxiv.org/abs/2407.03257),1615.0,+104/-105,0.397,17.73,12.25,9.07,2526.31,6.013,✔️,0.0,False,GPU
|
| 11 |
-
9,🌳,Tree-based,[CatBoost (tuned + ensembled)](https://arxiv.org/abs/1706.09516),1611.0,+85/-63,0.379,17.97,9.32,8.932,489.93,0.249,✔️,0.0,False,CPU
|
| 12 |
-
10,🧠⚡,Foundation Model,[RealTabPFN-2.5 (tuned)](https://arxiv.org/abs/2511.08667),1600.0,+126/-99,0.403,18.55,10.47,9.218,735.58,1.386,✔️,0.0,False,GPU
|
| 13 |
-
11,🌳,Tree-based,[CatBoost (tuned)](https://arxiv.org/abs/1706.09516),1596.0,+98/-66,0.372,18.8,9.43,9.14,489.93,0.02,✔️,0.0,False,CPU
|
| 14 |
-
12,🌳,Tree-based,[LightGBM (tuned + ensembled)](https://papers.nips.cc/paper_files/paper/2017/hash/6449f44a102fde848669bdd9eb6b76fa-Abstract.html),1589.0,+68/-51,0.327,19.19,13.5,10.466,131.56,2.639,✔️,0.0,False,CPU
|
| 15 |
-
13,🌳,Tree-based,[CatBoost (default)](https://arxiv.org/abs/1706.09516),1576.0,+103/-101,0.378,19.95,9.61,9.095,2.47,0.01,✔️,0.0,False,CPU
|
| 16 |
-
14,🧠⚡,Foundation Model,[iLTM (tuned + ensembled)](https://arxiv.org/abs/2511.15941),1558.0,+70/-52,0.322,20.99,15.67,10.221,2067.95,65.195,✔️,0.0,False,GPU
|
| 17 |
-
15,🌳,Tree-based,[XGBoost (tuned + ensembled)](https://arxiv.org/abs/1603.02754),1548.0,+81/-55,0.295,21.61,14.86,10.546,282.13,0.563,✔️,0.0,False,CPU
|
| 18 |
-
16,🧠🔁,Neural Network,[TabM (tuned + ensembled)](https://arxiv.org/abs/2410.24210),1544.0,+146/-87,0.292,21.87,13.14,10.254,1236.88,0.579,✔️,0.0,False,GPU
|
| 19 |
-
17,🧠🔁,Neural Network,[RealMLP (tuned)](https://arxiv.org/abs/2407.04491),1533.0,+105/-89,0.301,22.52,14.08,10.104,1719.82,0.081,✔️,0.0,False,GPU
|
| 20 |
-
18,🧠⚡,Foundation Model,[RealTabPFN-2.5 (default)](https://arxiv.org/abs/2511.08667),1530.0,+136/-79,0.324,22.69,14.72,10.077,1.88,0.645,✔️,0.0,False,GPU
|
| 21 |
-
19,🧠⚡,Foundation Model,[TabDPT-Turbo (default)](https://openreview.net/pdf?id=Y00pwFyrHR),1526.0,+156/-139,0.355,22.94,10.98,10.809,0.75,0.18,➖,0.0,False,GPU
|
| 22 |
-
20,🧠⚡,Foundation Model,[TabDPT (tuned + ensembled)](https://arxiv.org/abs/2410.18164),1522.0,+134/-119,0.319,23.22,6.34,10.287,4786.6,444.544,✔️,0.0,False,GPU
|
| 23 |
-
21,🌳,Tree-based,[ChimeraBoost (tuned + ensembled)](https://github.com/bbstats/chimeraboost),1517.0,+116/-121,0.314,23.53,13.31,11.684,95.92,0.297,✔️,0.0,False,CPU
|
| 24 |
-
22,🌳,Tree-based,[LightGBM (tuned)](https://papers.nips.cc/paper_files/paper/2017/hash/6449f44a102fde848669bdd9eb6b76fa-Abstract.html),1506.0,+76/-54,0.216,24.2,18.44,11.603,131.56,0.132,✔️,0.0,False,CPU
|
| 25 |
-
23,🌳,Tree-based,[XGBoost (tuned)](https://arxiv.org/abs/1603.02754),1501.0,+64/-55,0.234,24.53,20.07,11.102,282.13,0.066,✔️,0.0,False,CPU
|
| 26 |
-
24,🧠🔁,Neural Network,[TabM (tuned)](https://arxiv.org/abs/2410.24210),1481.0,+130/-76,0.234,25.86,15.63,11.089,1236.88,0.054,✔️,0.0,False,GPU
|
| 27 |
-
25,🧠🔁,Neural Network,[ModernNCA (tuned)](https://arxiv.org/abs/2407.03257),1472.0,+92/-81,0.217,26.42,20.56,11.215,2526.31,0.349,✔️,0.0,False,GPU
|
| 28 |
-
26,🌳,Tree-based,[ChimeraBoost (tuned)](https://github.com/bbstats/chimeraboost),1470.0,+106/-115,0.266,26.58,15.47,12.146,95.92,0.027,✔️,0.0,False,CPU
|
| 29 |
-
27,❓,Other,[xRFM (tuned + ensembled)](https://arxiv.org/abs/2508.10053),1423.0,+106/-114,0.224,29.66,21.18,12.482,566.74,0.951,✔️,0.0,False,GPU
|
| 30 |
-
28,🧠⚡,Foundation Model,[iLTM (tuned)](https://arxiv.org/abs/2511.15941),1423.0,+97/-63,0.155,29.69,18.8,12.112,2067.95,10.881,✔️,0.0,False,GPU
|
| 31 |
-
29,🌳,Tree-based,[ChimeraBoost (default)](https://github.com/bbstats/chimeraboost),1418.0,+112/-119,0.203,30.0,19.33,13.176,0.48,0.023,✔️,0.0,False,CPU
|
| 32 |
-
30,🧠⚡,Foundation Model,[TabDPT (tuned)](https://arxiv.org/abs/2410.18164),1404.0,+123/-118,0.221,30.97,12.53,12.662,4786.6,42.641,✔️,0.0,False,GPU
|
| 33 |
-
31,🧠🔁,Neural Network,[TorchMLP (tuned + ensembled)](https://arxiv.org/abs/2003.06505),1377.0,+71/-61,0.128,32.79,26.34,12.45,1770.56,1.069,✔️,0.0,False,CPU
|
| 34 |
-
32,❓,Other,[xRFM (tuned)](https://arxiv.org/abs/2508.10053),1373.0,+92/-101,0.159,33.01,27.27,13.982,566.74,0.06,✔️,0.0,False,GPU
|
| 35 |
-
33,🌳,Tree-based,[XGBoost (default)](https://arxiv.org/abs/1603.02754),1372.0,+89/-103,0.137,33.13,21.73,12.907,0.49,0.053,✔️,0.0,False,CPU
|
| 36 |
-
34,🧠⚡,Foundation Model,[TabSwift (default)](https://github.com/LAMDA-Tabular/TabSwift),1344.0,+118/-102,0.157,34.99,24.16,13.337,0.51,0.127,➖,0.0,False,GPU
|
| 37 |
-
35,🧠⚡,Foundation Model,[TabDPT (default)](https://arxiv.org/abs/2410.18164),1332.0,+119/-134,0.174,35.84,16.46,15.311,46.62,43.738,✔️,0.0,False,GPU
|
| 38 |
-
36,🧠🔁,Neural Network,[TabM (default)](https://arxiv.org/abs/2410.24210),1326.0,+110/-88,0.096,36.23,29.85,13.982,2.13,0.047,✔️,0.0,False,GPU
|
| 39 |
-
37,🌳,Tree-based,[EBM (tuned + ensembled)](https://www.cs.cornell.edu/~yinlou/papers/lou-kdd13.pdf),1326.0,+113/-128,0.134,36.24,27.26,15.595,695.61,0.085,✔️,0.0,False,CPU
|
| 40 |
-
38,🧠🔁,Neural Network,[ModernNCA (default)](https://arxiv.org/abs/2407.03257),1298.0,+72/-79,0.073,38.1,33.85,14.33,8.06,0.25,✔️,0.0,False,GPU
|
| 41 |
-
39,🧠⚡,Foundation Model,[LimiX (default)](https://arxiv.org/abs/2509.03505),1279.0,+140/-160,0.17,39.33,9.92,16.418,6.55,5.409,➖,0.0,False,GPU
|
| 42 |
-
40,🧠🔁,Neural Network,[TorchMLP (tuned)](https://arxiv.org/abs/2003.06505),1272.0,+70/-75,0.049,39.78,35.01,14.114,1770.56,0.051,✔️,0.0,False,CPU
|
| 43 |
-
41,🧠🔁,Neural Network,[RealMLP (default)](https://arxiv.org/abs/2407.04491),1272.0,+73/-68,0.034,39.84,36.58,15.091,6.75,0.235,✔️,0.0,False,GPU
|
| 44 |
-
42,🌳,Tree-based,[EBM (tuned)](https://www.cs.cornell.edu/~yinlou/papers/lou-kdd13.pdf),1265.0,+104/-133,0.089,40.24,32.83,16.441,695.61,0.006,✔️,0.0,False,CPU
|
| 45 |
-
43,🌳,Tree-based,[LightGBM (default)](https://papers.nips.cc/paper_files/paper/2017/hash/6449f44a102fde848669bdd9eb6b76fa-Abstract.html),1258.0,+51/-64,0.028,40.73,38.32,14.82,0.29,0.045,✔️,0.0,False,CPU
|
| 46 |
-
44,🌳,Tree-based,[RandomForest (tuned + ensembled)](https://link.springer.com/article/10.1023/A:1010933404324),1244.0,+85/-85,0.03,41.64,35.97,15.1,66.0,0.341,✔️,0.0,False,CPU
|
| 47 |
-
45,🌳,Tree-based,[EBM (default)](https://www.cs.cornell.edu/~yinlou/papers/lou-kdd13.pdf),1221.0,+88/-136,0.057,43.14,37.72,17.87,2.18,0.005,✔️,0.0,False,CPU
|
| 48 |
-
46,🌳,Tree-based,[ExtraTrees (tuned + ensembled)](https://link.springer.com/article/10.1007/s10994-006-6226-1),1217.0,+79/-89,0.022,43.4,40.85,15.304,49.61,0.199,✔️,0.0,False,CPU
|
| 49 |
-
47,🌳,Tree-based,[RandomForest (tuned)](https://link.springer.com/article/10.1023/A:1010933404324),1214.0,+86/-84,0.031,43.54,37.85,15.744,66.0,0.024,✔️,0.0,False,CPU
|
| 50 |
-
48,🧠🔁,Neural Network,[FastaiMLP (tuned + ensembled)](https://arxiv.org/abs/2003.06505),1201.0,+110/-138,0.06,44.39,36.49,17.192,351.94,1.658,✔️,0.0,False,CPU
|
| 51 |
-
49,🧠⚡,Foundation Model,[SAP-RPT-OSS (default)](https://arxiv.org/abs/2506.10707),1201.0,+82/-95,0.028,44.41,39.08,16.933,11.44,10.416,➖,0.0,False,GPU
|
| 52 |
-
50,🧠⚡,Foundation Model,[iLTM (default)](https://arxiv.org/abs/2511.15941),1179.0,+84/-111,0.033,45.73,41.33,18.488,88.27,9.62,✔️,0.0,False,GPU
|
| 53 |
-
51,🌳,Tree-based,[ExtraTrees (tuned)](https://link.springer.com/article/10.1007/s10994-006-6226-1),1174.0,+70/-83,0.008,46.07,43.76,16.303,49.61,0.015,✔️,0.0,False,CPU
|
| 54 |
-
52,🧠🔁,Neural Network,[TorchMLP (default)](https://arxiv.org/abs/2003.06505),1126.0,+59/-72,0.001,48.9,47.16,18.145,2.18,0.039,✔️,0.0,False,CPU
|
| 55 |
-
53,🌳,Tree-based,[PerpetualBooster (tuned + ensembled)](https://perpetual-ml.com/),1110.0,+101/-125,0.019,49.83,43.02,21.633,20.26,0.515,✔️,0.0,False,CPU
|
| 56 |
-
54,🧠🔁,Neural Network,[FastaiMLP (tuned)](https://arxiv.org/abs/2003.06505),1101.0,+91/-105,0.015,50.32,45.23,19.294,351.94,0.114,✔️,0.0,False,CPU
|
| 57 |
-
55,🌳,Tree-based,[PerpetualBooster (tuned)](https://perpetual-ml.com/),1060.0,+92/-116,0.004,52.57,48.1,22.747,20.26,0.2,✔️,0.0,False,CPU
|
| 58 |
-
56,❓,Other,[xRFM (default)](https://arxiv.org/abs/2508.10053),1046.0,+147/-184,0.018,53.27,47.13,25.98,2.49,0.145,✔️,0.0,False,GPU
|
| 59 |
-
57,🧠🔁,Neural Network,[FastaiMLP (default)](https://arxiv.org/abs/2003.06505),1031.0,+136/-171,0.018,54.04,48.76,22.864,1.51,0.111,✔️,0.0,False,CPU
|
| 60 |
-
58,🌳,Tree-based,[RandomForest (default)](https://link.springer.com/article/10.1023/A:1010933404324),1000.0,+51/-92,0.0,55.55,54.46,21.197,0.2,0.021,✔️,0.0,False,CPU
|
| 61 |
-
59,📏,Baseline,[KNN (tuned + ensembled)](https://scikit-learn.org/stable/modules/neighbors.html),989.0,+94/-128,0.005,56.06,49.75,24.353,150.3,10.071,✔️,0.0,False,CPU
|
| 62 |
-
60,🧠⚡,Foundation Model,[TabSTAR (tuned)](https://arxiv.org/abs/2505.18125),988.0,+56/-90,0.0,56.13,54.65,25.807,3381.77,1.724,✔️,0.0,False,GPU
|
| 63 |
-
61,🧠⚡,Foundation Model,[TabSTAR (tuned + ensembled)](https://arxiv.org/abs/2505.18125),987.0,+61/-86,0.0,56.18,54.79,25.781,3381.77,5.283,✔️,0.0,False,GPU
|
| 64 |
-
62,🌳,Tree-based,[ExtraTrees (default)](https://link.springer.com/article/10.1007/s10994-006-6226-1),976.0,+94/-121,0.0,56.64,54.71,22.789,0.48,0.073,✔️,0.0,False,CPU
|
| 65 |
-
63,📏,Baseline,[Linear (tuned + ensembled)](https://scikit-learn.org/stable/modules/linear_model.html),935.0,+153/-226,0.004,58.45,53.87,32.872,43.64,0.081,✔️,0.0,False,CPU
|
| 66 |
-
64,🌳,Tree-based,[PerpetualBooster (default)](https://perpetual-ml.com/),901.0,+106/-153,0.0,59.81,57.82,29.424,1.5,0.015,✔️,0.0,False,CPU
|
| 67 |
-
65,📏,Baseline,[Linear (tuned)](https://scikit-learn.org/stable/modules/linear_model.html),892.0,+154/-245,0.002,60.16,56.48,33.73,43.64,0.018,✔️,0.0,False,CPU
|
| 68 |
-
66,🧠⚡,Foundation Model,[TabSTAR (default)](https://arxiv.org/abs/2505.18125),848.0,+50/-88,0.0,61.7,61.11,30.685,110.78,1.964,✔️,0.0,False,GPU
|
| 69 |
-
67,📏,Baseline,[KNN (tuned)](https://scikit-learn.org/stable/modules/neighbors.html),814.0,+53/-106,0.0,62.78,62.5,29.973,150.3,0.482,✔️,0.0,False,CPU
|
| 70 |
-
68,📏,Baseline,[Linear (default)](https://scikit-learn.org/stable/modules/linear_model.html),797.0,+137/-244,0.0,63.27,61.49,35.794,0.19,0.019,✔️,0.0,False,CPU
|
| 71 |
-
69,📏,Baseline,[KNN (default)](https://scikit-learn.org/stable/modules/neighbors.html),593.0,+83/-146,0.0,67.65,67.52,43.501,0.1,0.072,✔️,0.0,False,CPU
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/winrate_explorer.html
DELETED
|
@@ -1,1169 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>Arena win-rate matrix</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* The matrix scrolls in both directions: 40+ models will not fit a page either
|
| 269 |
-
way, and shrinking the cells to fit makes the numbers unreadable. `margin:
|
| 270 |
-
auto` centres it once the selection is small enough to fit — and collapses
|
| 271 |
-
to zero when it overflows, which `justify-content: center` would not. */
|
| 272 |
-
.wr-scroll {
|
| 273 |
-
overflow: auto; max-width: 100%;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.wr-scroll::-webkit-scrollbar { width: 11px; height: 11px; }
|
| 277 |
-
.wr-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
#chart { display: block; margin-inline: auto; }
|
| 282 |
-
.wr-empty { padding: 40px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 283 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 284 |
-
.chips { margin: 2px 0 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 285 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 286 |
-
</style>
|
| 287 |
-
</head>
|
| 288 |
-
<body>
|
| 289 |
-
<div class="viewbar">
|
| 290 |
-
<button class="btn" id="btn-paper" title="White background, matrix only — for slides and papers">Paper view</button>
|
| 291 |
-
</div>
|
| 292 |
-
<p class="explorer-title" id="title"></p>
|
| 293 |
-
<div class="controls">
|
| 294 |
-
<button class="btn toggle" id="btn-best"
|
| 295 |
-
title="Keep only each model's best-performing variant, one row and column per model — as the static figure does">One per model</button>
|
| 296 |
-
<span class="grouplabel">Variants</span>
|
| 297 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 298 |
-
<label class="metricpick">Order
|
| 299 |
-
<select id="order-select">
|
| 300 |
-
<option value="published">As published</option>
|
| 301 |
-
<option value="winrate">Mean win rate</option>
|
| 302 |
-
<option value="name">Name</option>
|
| 303 |
-
</select>
|
| 304 |
-
</label>
|
| 305 |
-
<label class="metricpick">Size
|
| 306 |
-
<select id="zoom-select" title="Fit scales the whole matrix into the panel; the percentages draw it at reading size and scroll">
|
| 307 |
-
<option value="fit">Fit panel</option>
|
| 308 |
-
<option value="0.6">60%</option>
|
| 309 |
-
<option value="0.8">80%</option>
|
| 310 |
-
<option value="1">100%</option>
|
| 311 |
-
</select>
|
| 312 |
-
</label>
|
| 313 |
-
<span class="hint">Click a row or column label to remove that model</span>
|
| 314 |
-
</div>
|
| 315 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 316 |
-
<span class="hint">Export figure</span>
|
| 317 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">Download SVG</button>
|
| 318 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">Download PDF</button>
|
| 319 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">Download PNG</button>
|
| 320 |
-
</div>
|
| 321 |
-
<div class="chips" id="chips"></div>
|
| 322 |
-
<div class="wr-scroll" id="wrap">
|
| 323 |
-
<svg id="chart" role="img" aria-label="Pairwise win-rate matrix"></svg>
|
| 324 |
-
</div>
|
| 325 |
-
<div class="tooltip"></div>
|
| 326 |
-
|
| 327 |
-
<script>
|
| 328 |
-
(function () {
|
| 329 |
-
"use strict";
|
| 330 |
-
const CONFIG = {"title": null, "methods": ["TabFM (default)", "TabPFN-3 (default)", "TabPFN-2.6 (default)", "TabICLv2 (default)", "RealTabPFN-2.5 (T+E)", "RealMLP (T+E)", "ModernNCA (T+E)", "CatBoost (T+E)", "LightGBM (T+E)", "iLTM (T+E)", "XGBoost (T+E)", "TabM (T+E)", "TabDPT-Turbo (default)", "ChimeraBoost (T+E)", "TabDPT (T+E)", "xRFM (T+E)", "TorchMLP (T+E)", "TabSwift (default)", "EBM (T+E)", "LimiX (default)", "RandomForest (T+E)", "FastaiMLP (T+E)", "SAP-RPT-OSS (default)", "ExtraTrees (T+E)", "PerpetualBooster (T+E)", "TabSTAR (T+E)", "KNN (T+E)", "Linear (T+E)"], "matrix": [[NaN, 0.7851851582527161, 0.9333333373069763, 0.9037036895751953, 0.911111056804657, 0.8814814686775208, 0.9259259700775146, 0.8518518209457397, 0.9037036895751953, 0.8962963223457336, 0.9185184836387634, 0.9925926327705383, 0.9629629254341125, 0.9185184836387634, 0.8740740418434143, 0.9259259700775146, 0.9777777194976807, 0.970370352268219, 0.9925926327705383, 0.9037036895751953, 0.9851852059364319, 0.940740704536438, 0.9851852059364319, 0.9925926327705383, 1.0, 1.0, 0.970370352268219, 0.9851852059364319], [0.21481481194496155, NaN, 0.770370364189148, 0.6592592000961304, 0.82962965965271, 0.7629629969596863, 0.859259307384491, 0.7333333492279053, 0.7555555105209351, 0.7851851582527161, 0.7629629373550415, 0.8592592477798462, 0.9185184836387634, 0.7851851582527161, 0.7333333492279053, 0.800000011920929, 0.8888888955116272, 0.9777777791023254, 0.8444444537162781, 0.8666666746139526, 0.9629629850387573, 0.9333333373069763, 0.9481481909751892, 0.9777777791023254, 0.9333333373069763, 1.0, 0.9555556178092957, 0.9481481313705444], [0.06666667014360428, 0.22962965071201324, NaN, 0.4592593014240265, 0.555555522441864, 0.6888889074325562, 0.6740740537643433, 0.6518518328666687, 0.7333333492279053, 0.7037037014961243, 0.7185184955596924, 0.7333333492279053, 0.7185184359550476, 0.770370364189148, 0.7407407164573669, 0.8074074387550354, 0.8962963223457336, 0.9111111164093018, 0.9185184836387634, 0.8518518209457397, 0.970370352268219, 0.911111056804657, 0.970370352268219, 0.9851852059364319, 0.9925926327705383, 1.0, 0.9629629850387573, 0.9777777791023254], [0.09629630297422409, 0.34074074029922485, 0.5407407283782959, NaN, 0.7333333492279053, 0.644444465637207, 0.7407407164573669, 0.6740740537643433, 0.7111111283302307, 0.6888888478279114, 0.6814814209938049, 0.7407407164573669, 0.7851851582527161, 0.6814814805984497, 0.770370364189148, 0.7333333492279053, 0.8074073791503906, 0.940740704536438, 0.770370364189148, 0.8740740418434143, 0.9185184836387634, 0.8962963223457336, 0.9481481313705444, 0.9925926327705383, 0.9333333373069763, 0.9851852059364319, 0.970370352268219, 0.9481481313705444], [0.08888889104127884, 0.17037038505077362, 0.4444444477558136, 0.2666666805744171, NaN, 0.6000000238418579, 0.5777778029441833, 0.585185170173645, 0.6296296715736389, 0.614814817905426, 0.6592592597007751, 0.614814817905426, 0.6296296715736389, 0.6074073910713196, 0.6592592597007751, 0.7629629969596863, 0.8074073791503906, 0.9037037491798401, 0.8222221732139587, 0.7777777314186096, 0.9407407641410828, 0.8222222924232483, 0.9037037491798401, 0.9777777791023254, 0.9777777791023254, 1.0, 0.940740704536438, 0.8962962627410889], [0.11851851642131805, 0.2370370328426361, 0.3111111521720886, 0.35555559396743774, 0.4000000059604645, NaN, 0.5333333611488342, 0.5185185074806213, 0.6074074506759644, 0.6370370388031006, 0.6370370388031006, 0.5925925970077515, 0.5925925970077515, 0.5185185074806213, 0.5777778029441833, 0.859259307384491, 0.8370370864868164, 0.7555555701255798, 0.8222221732139587, 0.888888955116272, 0.9185184836387634, 0.9851852059364319, 0.9259259700775146, 0.9333333373069763, 0.9851852059364319, 1.0, 0.9925926327705383, 1.0], [0.07407407462596893, 0.14074073731899261, 0.32592591643333435, 0.25925925374031067, 0.42222222685813904, 0.46666666865348816, NaN, 0.5259259343147278, 0.5777778029441833, 0.6148148775100708, 0.6296296715736389, 0.6000000834465027, 0.5481481552124023, 0.6222222447395325, 0.6370370984077454, 0.7555555105209351, 0.8222222924232483, 0.7851851582527161, 0.8222222924232483, 0.8814814686775208, 0.859259307384491, 0.911111056804657, 0.9037036895751953, 0.9333333373069763, 0.9925926327705383, 0.9481481313705444, 0.9925926327705383, 0.9333333373069763], [0.14814814925193787, 0.2666666805744171, 0.3481481671333313, 0.32592594623565674, 0.414814829826355, 0.48148149251937866, 0.4740740656852722, NaN, 0.5185185074806213, 0.6000000238418579, 0.6888888478279114, 0.4888888895511627, 0.46666666865348816, 0.6962963342666626, 0.5333333611488342, 0.7185184955596924, 0.7925926446914673, 0.7481481432914734, 0.8962963223457336, 0.6814814805984497, 0.9259259700775146, 0.9111111164093018, 0.9185184836387634, 0.9703704118728638, 0.9777777791023254, 1.0, 0.9925926327705383, 0.9925926327705383], [0.09629630297422409, 0.24444444477558136, 0.2666666805744171, 0.28888893127441406, 0.37037041783332825, 0.39259257912635803, 0.42222222685813904, 0.48148149251937866, NaN, 0.5407407283782959, 0.6888889074325562, 0.4740740954875946, 0.5185185670852661, 0.644444465637207, 0.4962962865829468, 0.6444444060325623, 0.7555555105209351, 0.7259259819984436, 0.8444443941116333, 0.6592592597007751, 0.9333333373069763, 0.8444443941116333, 0.9037036895751953, 0.9851852655410767, 0.9851852059364319, 0.9925926327705383, 0.9851852059364319, 0.9851852059364319], [0.10370371490716934, 0.21481482684612274, 0.29629629850387573, 0.31111112236976624, 0.385185182094574, 0.3629629909992218, 0.38518521189689636, 0.40000003576278687, 0.4592592418193817, NaN, 0.5407407879829407, 0.4888888895511627, 0.43703702092170715, 0.5037037134170532, 0.5111111402511597, 0.6296296715736389, 0.8814815282821655, 0.703703761100769, 0.8000000715255737, 0.6888889074325562, 0.9111111164093018, 0.9703704118728638, 0.9111111164093018, 0.9333333373069763, 0.8666666746139526, 0.9925926327705383, 0.9851852655410767, 0.9851852655410767], [0.08148148655891418, 0.2370370477437973, 0.28148147463798523, 0.3185185492038727, 0.34074074029922485, 0.3629629909992218, 0.37037038803100586, 0.31111109256744385, 0.31111109256744385, 0.4592592120170593, NaN, 0.48888885974884033, 0.48148149251937866, 0.5333333611488342, 0.5259259343147278, 0.644444465637207, 0.8000000715255737, 0.6518518328666687, 0.8666666150093079, 0.6518518328666687, 0.9333333373069763, 0.8666666746139526, 0.9037037491798401, 0.9481481909751892, 0.9037037491798401, 0.9925926327705383, 0.9925926327705383, 1.0], [0.007407407276332378, 0.14074073731899261, 0.2666666805744171, 0.25925928354263306, 0.38518521189689636, 0.40740740299224854, 0.4000000059604645, 0.5111110806465149, 0.5259259343147278, 0.5111110806465149, 0.5111110806465149, NaN, 0.48148149251937866, 0.5185185074806213, 0.46666669845581055, 0.5629629492759705, 0.6666666865348816, 0.7259259819984436, 0.7111110687255859, 0.7111110687255859, 0.8222222924232483, 0.8814814686775208, 0.8666666746139526, 0.8888888955116272, 0.9185184836387634, 1.0, 0.9629629850387573, 0.9555556178092957], [0.03703703731298447, 0.08148147910833359, 0.28148147463798523, 0.21481482684612274, 0.37037035822868347, 0.40740740299224854, 0.45185184478759766, 0.5333333611488342, 0.48148149251937866, 0.5629629492759705, 0.5185185074806213, 0.5185185074806213, NaN, 0.5259259343147278, 0.46666669845581055, 0.6592592597007751, 0.7629629969596863, 0.8074073791503906, 0.6074073910713196, 0.7777777910232544, 0.7851852178573608, 0.7629629969596863, 0.7851851582527161, 0.8444444537162781, 0.9111111164093018, 0.9259259700775146, 0.9037036895751953, 0.8222222924232483], [0.08148147910833359, 0.21481482684612274, 0.22962962090969086, 0.3185185194015503, 0.39259254932403564, 0.48148149251937866, 0.3777777850627899, 0.3037037253379822, 0.35555556416511536, 0.4962962567806244, 0.46666666865348816, 0.48148149251937866, 0.4740740656852722, NaN, 0.5333333611488342, 0.7037037014961243, 0.6740740537643433, 0.6444444060325623, 0.8148148059844971, 0.6296296715736389, 0.859259307384491, 0.8370370268821716, 0.8518518209457397, 0.8370370864868164, 0.8444444537162781, 0.9333333373069763, 0.9629629850387573, 1.0], [0.1259259283542633, 0.2666666805744171, 0.25925925374031067, 0.22962962090969086, 0.34074077010154724, 0.42222222685813904, 0.3629629909992218, 0.46666666865348816, 0.5037037134170532, 0.4888888895511627, 0.4740740656852722, 0.5333333611488342, 0.5333333611488342, 0.46666666865348816, NaN, 0.7037037014961243, 0.7185184955596924, 0.7111110687255859, 0.6296296715736389, 0.7259259819984436, 0.7777777314186096, 0.7925925850868225, 0.82962965965271, 0.7851851582527161, 0.9851852655410767, 0.9037036895751953, 0.8962963223457336, 0.8370370268821716], [0.07407407462596893, 0.20000000298023224, 0.19259260594844818, 0.2666666507720947, 0.2370370477437973, 0.14074073731899261, 0.24444444477558136, 0.28148147463798523, 0.35555556416511536, 0.37037035822868347, 0.35555553436279297, 0.43703705072402954, 0.34074074029922485, 0.29629629850387573, 0.29629629850387573, NaN, 0.6000000238418579, 0.5111111402511597, 0.6296296715736389, 0.703703761100769, 0.7629629969596863, 0.8222221732139587, 0.7259259819984436, 0.8074074387550354, 0.8370370268821716, 0.9037036895751953, 0.9777777194976807, 0.9851852059364319], [0.02222222276031971, 0.111111119389534, 0.10370370745658875, 0.19259260594844818, 0.192592591047287, 0.16296297311782837, 0.17777778208255768, 0.2074074149131775, 0.24444444477558136, 0.11851852387189865, 0.20000000298023224, 0.3333333432674408, 0.2370370477437973, 0.32592594623565674, 0.28148147463798523, 0.4000000059604645, NaN, 0.5185185670852661, 0.5481481552124023, 0.6000000238418579, 0.7259259819984436, 0.7407407164573669, 0.8148148059844971, 0.7555555105209351, 0.7333332896232605, 0.9481481313705444, 0.940740704536438, 0.9407407641410828], [0.029629629105329514, 0.02222222276031971, 0.08888889104127884, 0.05925925821065903, 0.09629630297422409, 0.24444444477558136, 0.21481482684612274, 0.2518518567085266, 0.27407410740852356, 0.29629629850387573, 0.3481481671333313, 0.27407410740852356, 0.192592591047287, 0.35555553436279297, 0.2888889014720917, 0.4888888895511627, 0.48148149251937866, NaN, 0.5481481552124023, 0.5925925374031067, 0.5555555820465088, 0.7481482028961182, 0.6666666865348816, 0.6222221851348877, 0.7925926446914673, 0.8666666746139526, 0.8518518805503845, 0.8148148059844971], [0.007407407276332378, 0.15555556118488312, 0.08148147910833359, 0.22962965071201324, 0.17777778208255768, 0.17777778208255768, 0.17777778208255768, 0.10370370745658875, 0.15555556118488312, 0.20000001788139343, 0.13333334028720856, 0.2888889014720917, 0.3925926089286804, 0.18518519401550293, 0.37037038803100586, 0.37037038803100586, 0.45185184478759766, 0.45185187458992004, NaN, 0.46666666865348816, 0.6148148775100708, 0.6444444060325623, 0.6666666865348816, 0.6666666865348816, 0.6518518328666687, 0.9407407641410828, 0.8370370268821716, 0.9333333373069763], [0.0962962955236435, 0.13333334028720856, 0.14814814925193787, 0.1259259283542633, 0.222222238779068, 0.111111119389534, 0.11851852387189865, 0.3185185194015503, 0.34074074029922485, 0.31111109256744385, 0.3481481671333313, 0.2888889014720917, 0.222222238779068, 0.37037035822868347, 0.27407407760620117, 0.29629629850387573, 0.4000000059604645, 0.40740740299224854, 0.5333333611488342, NaN, 0.5111110806465149, 0.6222222447395325, 0.6000000238418579, 0.48148149251937866, 0.5629628896713257, 0.6888888478279114, 0.7111111283302307, 0.7629629969596863], [0.014814814552664757, 0.03703703731298447, 0.029629629105329514, 0.08148147910833359, 0.05925925821065903, 0.08148147910833359, 0.14074073731899261, 0.07407407462596893, 0.06666667014360428, 0.08888889104127884, 0.06666667014360428, 0.17777778208255768, 0.21481482684612274, 0.14074073731899261, 0.2222222238779068, 0.23703701794147491, 0.27407407760620117, 0.4444444477558136, 0.385185182094574, 0.4888888895511627, NaN, 0.5925925970077515, 0.6666667461395264, 0.555555522441864, 0.6518518328666687, 0.8740740418434143, 0.9259259700775146, 0.8666666746139526], [0.05925925821065903, 0.06666667014360428, 0.08888889104127884, 0.10370370745658875, 0.17777778208255768, 0.014814814552664757, 0.08888889104127884, 0.08888889104127884, 0.15555556118488312, 0.029629629105329514, 0.13333334028720856, 0.11851851642131805, 0.2370370328426361, 0.16296295821666718, 0.2074074149131775, 0.17777778208255768, 0.25925928354263306, 0.2518518567085266, 0.35555553436279297, 0.3777777850627899, 0.40740740299224854, NaN, 0.46666666865348816, 0.4592592418193817, 0.5703703761100769, 0.7185184955596924, 0.7185184955596924, 0.9259259700775146], [0.014814814552664757, 0.05185185372829437, 0.029629629105329514, 0.05185185372829437, 0.09629630297422409, 0.07407407462596893, 0.0962962955236435, 0.08148147910833359, 0.0962962955236435, 0.08888889104127884, 0.0962962955236435, 0.13333334028720856, 0.21481482684612274, 0.14814814925193787, 0.17037037014961243, 0.27407407760620117, 0.18518517911434174, 0.3333333432674408, 0.3333333432674408, 0.4000000059604645, 0.3333333730697632, 0.5333333611488342, NaN, 0.40740740299224854, 0.6814814805984497, 0.7259259819984436, 0.859259307384491, 0.8740740418434143], [0.007407407276332378, 0.02222222276031971, 0.014814814552664757, 0.007407407276332378, 0.02222222276031971, 0.06666667014360428, 0.06666667014360428, 0.029629629105329514, 0.014814814552664757, 0.06666667014360428, 0.05185185372829437, 0.111111119389534, 0.15555556118488312, 0.16296295821666718, 0.21481482684612274, 0.19259260594844818, 0.24444444477558136, 0.37777775526046753, 0.3333333432674408, 0.5185185074806213, 0.444444477558136, 0.5407407283782959, 0.5925925970077515, NaN, 0.6370370388031006, 0.8148148059844971, 0.82962965965271, 0.8148148059844971], [0.0, 0.06666667014360428, 0.007407407276332378, 0.06666667014360428, 0.02222222276031971, 0.014814814552664757, 0.007407407276332378, 0.02222222276031971, 0.014814814552664757, 0.13333334028720856, 0.09629630297422409, 0.08148147910833359, 0.08888889104127884, 0.15555556118488312, 0.014814814552664757, 0.16296297311782837, 0.2666666805744171, 0.2074074149131775, 0.3481481671333313, 0.43703705072402954, 0.3481481671333313, 0.4296296536922455, 0.3185185492038727, 0.3629629909992218, NaN, 0.5111111402511597, 0.6296296715736389, 0.7037037014961243], [0.0, 0.0, 0.0, 0.014814814552664757, 0.0, 0.0, 0.05185185372829437, 0.0, 0.007407407276332378, 0.007407407276332378, 0.007407407276332378, 0.0, 0.07407407462596893, 0.06666667014360428, 0.0962962955236435, 0.09629630297422409, 0.05185185372829437, 0.13333334028720856, 0.059259261935949326, 0.31111112236976624, 0.1259259283542633, 0.28148147463798523, 0.27407407760620117, 0.18518517911434174, 0.4888888895511627, NaN, 0.6074073910713196, 0.7111111283302307], [0.029629629105329514, 0.04444444552063942, 0.03703703731298447, 0.029629629105329514, 0.05925925821065903, 0.007407407276332378, 0.007407407276332378, 0.007407407276332378, 0.014814814552664757, 0.014814814552664757, 0.007407407276332378, 0.03703703731298447, 0.0962962955236435, 0.03703703731298447, 0.10370370745658875, 0.02222222276031971, 0.05925925821065903, 0.14814814925193787, 0.16296295821666718, 0.2888889014720917, 0.07407407462596893, 0.28148147463798523, 0.14074073731899261, 0.17037038505077362, 0.37037038803100586, 0.39259257912635803, NaN, 0.7185184955596924], [0.014814814552664757, 0.05185185372829437, 0.02222222276031971, 0.05185185372829437, 0.10370370745658875, 0.0, 0.06666667014360428, 0.007407407276332378, 0.014814814552664757, 0.014814814552664757, 0.0, 0.04444444552063942, 0.17777778208255768, 0.0, 0.16296295821666718, 0.014814814552664757, 0.05925925821065903, 0.18518517911434174, 0.06666667014360428, 0.2370370328426361, 0.13333334028720856, 0.07407407462596893, 0.1259259283542633, 0.18518519401550293, 0.29629629850387573, 0.2888888716697693, 0.28148147463798523, NaN]], "variants": ["Default", "Tuned", "Tuned + Ens."]};
|
| 331 |
-
const POINTS = [{"method":"TabFM (default)","model":"TabFM","variant":"Default","family":"Foundation Model","mean":0.9366255094},{"method":"TabPFN-3 (default)","model":"TabPFN-3","variant":"Default","family":"Foundation Model","mean":0.8320987677},{"method":"TabPFN-2.6 (default)","model":"TabPFN-2.6","variant":"Default","family":"Foundation Model","mean":0.7629629592},{"method":"TabICLv2 (default)","model":"TabICLv2","variant":"Default","family":"Foundation Model","mean":0.7610425152},{"method":"RealTabPFN-2.5 (T+E)","model":"RealTabPFN-2.5 (T+E)","variant":"","family":"Foundation Model","mean":0.6919067279},{"method":"RealMLP (T+E)","model":"RealMLP (T+E)","variant":"","family":"Neural Network","mean":0.686694116},{"method":"ModernNCA (T+E)","model":"ModernNCA (T+E)","variant":"","family":"Neural Network","mean":0.6661179849},{"method":"CatBoost (T+E)","model":"CatBoost (T+E)","variant":"","family":"Tree-based","mean":0.6658436325},{"method":"LightGBM (T+E)","model":"LightGBM (T+E)","variant":"","family":"Tree-based","mean":0.6359396524},{"method":"iLTM (T+E)","model":"iLTM (T+E)","variant":"","family":"Foundation Model","mean":0.6170096273},{"method":"XGBoost (T+E)","model":"XGBoost (T+E)","variant":"","family":"Tree-based","mean":0.6021947966},{"method":"TabM (T+E)","model":"TabM (T+E)","variant":"","family":"Neural Network","mean":0.5950617325},{"method":"TabDPT-Turbo (default)","model":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","mean":0.5854595403},{"method":"ChimeraBoost (T+E)","model":"ChimeraBoost (T+E)","variant":"","family":"Tree-based","mean":0.5851851876},{"method":"TabDPT (T+E)","model":"TabDPT (T+E)","variant":"","family":"Foundation Model","mean":0.5840877984},{"method":"xRFM (T+E)","model":"xRFM (T+E)","variant":"","family":"Other","mean":0.4946502116},{"method":"TorchMLP (T+E)","model":"TorchMLP (T+E)","variant":"","family":"Neural Network","mean":0.4288065873},{"method":"TabSwift (default)","model":"TabSwift","variant":"Default","family":"Foundation Model","mean":0.409876551},{"method":"EBM (T+E)","model":"EBM (T+E)","variant":"","family":"Tree-based","mean":0.3901234651},{"method":"LimiX (default)","model":"LimiX","variant":"Default","family":"Foundation Model","mean":0.3706447209},{"method":"RandomForest (T+E)","model":"RandomForest (T+E)","variant":"","family":"Tree-based","mean":0.3133059004},{"method":"FastaiMLP (T+E)","model":"FastaiMLP (T+E)","variant":"","family":"Neural Network","mean":0.2748971204},{"method":"SAP-RPT-OSS (default)","model":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","mean":0.2735253841},{"method":"ExtraTrees (T+E)","model":"ExtraTrees (T+E)","variant":"","family":"Tree-based","mean":0.2724279859},{"method":"PerpetualBooster (T+E)","model":"PerpetualBooster (T+E)","variant":"","family":"Tree-based","mean":0.2043895844},{"method":"TabSTAR (T+E)","model":"TabSTAR (T+E)","variant":"","family":"Foundation Model","mean":0.1352537733},{"method":"KNN (T+E)","model":"KNN (T+E)","variant":"","family":"Baseline","mean":0.1245541837},{"method":"Linear (T+E)","model":"Linear (T+E)","variant":"","family":"Baseline","mean":0.0993141289}];
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 335 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 336 |
-
// already share a color, and each holds only a handful of methods.
|
| 337 |
-
const FAM_MERGED = "Baseline / Other";
|
| 338 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 339 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 340 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 341 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 342 |
-
|
| 343 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 344 |
-
const FAM_VAR = {
|
| 345 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 346 |
-
"Tree-based": "var(--fam-tree)",
|
| 347 |
-
"Neural Network": "var(--fam-nn)",
|
| 348 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 349 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 350 |
-
};
|
| 351 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 352 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 353 |
-
// that chip carries both symbols.
|
| 354 |
-
const FAM_SYMBOL = {
|
| 355 |
-
"Foundation Model": "🧠⚡",
|
| 356 |
-
"Tree-based": "🌳",
|
| 357 |
-
"Neural Network": "🧠🔁",
|
| 358 |
-
"Reference Pipeline": "📊",
|
| 359 |
-
[FAM_MERGED]: "📏 ❓",
|
| 360 |
-
};
|
| 361 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 362 |
-
const VARIANT_VAR = {
|
| 363 |
-
"Default": "var(--var-default)",
|
| 364 |
-
"Tuned": "var(--var-tuned)",
|
| 365 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 366 |
-
};
|
| 367 |
-
|
| 368 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 369 |
-
function famChipLabel(family, count) {
|
| 370 |
-
const symbol = FAM_SYMBOL[family];
|
| 371 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 372 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 373 |
-
}
|
| 374 |
-
|
| 375 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 376 |
-
const FAM_INK = {
|
| 377 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 378 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 379 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 380 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 381 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 382 |
-
};
|
| 383 |
-
|
| 384 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 385 |
-
function el(name, attrs, parent) {
|
| 386 |
-
const node = document.createElementNS(NS, name);
|
| 387 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 388 |
-
if (parent) parent.appendChild(node);
|
| 389 |
-
return node;
|
| 390 |
-
}
|
| 391 |
-
|
| 392 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 393 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 394 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 395 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 396 |
-
function fmtNum(v, decimals) {
|
| 397 |
-
if (v == null || !isFinite(v)) return "—";
|
| 398 |
-
return v.toFixed(decimals);
|
| 399 |
-
}
|
| 400 |
-
|
| 401 |
-
function fmtMetric(metric, v) {
|
| 402 |
-
if (v == null || !isFinite(v)) return "—";
|
| 403 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 404 |
-
}
|
| 405 |
-
|
| 406 |
-
function fmtTime(v) {
|
| 407 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 408 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 409 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 410 |
-
return fmtNum(v, 3) + " s";
|
| 411 |
-
}
|
| 412 |
-
|
| 413 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 414 |
-
function niceStep(raw) {
|
| 415 |
-
if (!(raw > 0)) return 1;
|
| 416 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 417 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 418 |
-
if (mag * m >= raw) return mag * m;
|
| 419 |
-
}
|
| 420 |
-
return mag * 10;
|
| 421 |
-
}
|
| 422 |
-
|
| 423 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 424 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 425 |
-
function ticks(min, max, target) {
|
| 426 |
-
const step = niceStep((max - min) / target);
|
| 427 |
-
const first = Math.ceil(min / step);
|
| 428 |
-
const out = [];
|
| 429 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 430 |
-
return out.length ? out : [min];
|
| 431 |
-
}
|
| 432 |
-
|
| 433 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 434 |
-
function makeTooltip(box) {
|
| 435 |
-
const node = box.querySelector(".tooltip");
|
| 436 |
-
return {
|
| 437 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 438 |
-
move(ev) {
|
| 439 |
-
const r = box.getBoundingClientRect();
|
| 440 |
-
let tx = ev.clientX - r.left + 14;
|
| 441 |
-
const ty = ev.clientY - r.top + 12;
|
| 442 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 443 |
-
node.style.left = tx + "px";
|
| 444 |
-
node.style.top = ty + "px";
|
| 445 |
-
},
|
| 446 |
-
hide() { node.style.display = "none"; },
|
| 447 |
-
};
|
| 448 |
-
}
|
| 449 |
-
|
| 450 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 451 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 452 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 453 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 454 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 455 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 456 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 457 |
-
function setUpPaperView(afterToggle, options) {
|
| 458 |
-
const opts = options || {};
|
| 459 |
-
const root = document.documentElement;
|
| 460 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 461 |
-
const btn = document.getElementById("btn-paper");
|
| 462 |
-
const embedded = window.parent !== window;
|
| 463 |
-
|
| 464 |
-
function setPaper(on) {
|
| 465 |
-
document.body.classList.toggle("paper", on);
|
| 466 |
-
if (on) {
|
| 467 |
-
hostTheme = root.getAttribute("data-theme");
|
| 468 |
-
root.setAttribute("data-theme", "light");
|
| 469 |
-
} else if (hostTheme) {
|
| 470 |
-
root.setAttribute("data-theme", hostTheme);
|
| 471 |
-
} else {
|
| 472 |
-
root.removeAttribute("data-theme");
|
| 473 |
-
}
|
| 474 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 475 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 476 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 477 |
-
postHeight();
|
| 478 |
-
}
|
| 479 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 480 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 481 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 482 |
-
// shareable single file) this page needs its own.
|
| 483 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 484 |
-
window.addEventListener("message", ev => {
|
| 485 |
-
const d = ev.data;
|
| 486 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 487 |
-
});
|
| 488 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 489 |
-
// key press, so its label would fall out of step with the frame.
|
| 490 |
-
if (!embedded) {
|
| 491 |
-
document.addEventListener("keydown", ev => {
|
| 492 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 493 |
-
});
|
| 494 |
-
}
|
| 495 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 496 |
-
}
|
| 497 |
-
|
| 498 |
-
// --- Figure export ---------------------------------------------------------
|
| 499 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 500 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 501 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 502 |
-
// the legend is HTML rather than part of the SVG.
|
| 503 |
-
|
| 504 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 505 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 506 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 507 |
-
// break the PNG path.
|
| 508 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 509 |
-
// once the node leaves this document.
|
| 510 |
-
function resolveVars(root, resolve) {
|
| 511 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 512 |
-
for (const attr of ["fill", "stroke"]) {
|
| 513 |
-
const value = node.getAttribute(attr);
|
| 514 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 515 |
-
}
|
| 516 |
-
}
|
| 517 |
-
}
|
| 518 |
-
|
| 519 |
-
function legendToSvg(container, resolve) {
|
| 520 |
-
const base = container.getBoundingClientRect();
|
| 521 |
-
const group = document.createElementNS(NS, "g");
|
| 522 |
-
let height = 0;
|
| 523 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 524 |
-
const box = item.getBoundingClientRect();
|
| 525 |
-
if (!box.width) continue;
|
| 526 |
-
height = Math.max(height, box.bottom - base.top);
|
| 527 |
-
let textLeft = box.left - base.left;
|
| 528 |
-
const glyph = item.querySelector("svg");
|
| 529 |
-
if (glyph) {
|
| 530 |
-
const gbox = glyph.getBoundingClientRect();
|
| 531 |
-
const wrap = el("g", {
|
| 532 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 533 |
-
}, group);
|
| 534 |
-
const glyphClone = glyph.cloneNode(true);
|
| 535 |
-
resolveVars(glyphClone, resolve);
|
| 536 |
-
wrap.appendChild(glyphClone);
|
| 537 |
-
textLeft = gbox.right - base.left + 5;
|
| 538 |
-
}
|
| 539 |
-
const label = item.textContent.trim();
|
| 540 |
-
if (!label) continue;
|
| 541 |
-
const colored = item.querySelector("[style*='color']");
|
| 542 |
-
const text = el("text", {
|
| 543 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 544 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 545 |
-
}, group);
|
| 546 |
-
text.textContent = label;
|
| 547 |
-
}
|
| 548 |
-
return { group, height: Math.ceil(height) };
|
| 549 |
-
}
|
| 550 |
-
|
| 551 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 552 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 553 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 554 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 555 |
-
const resolve = value => String(value).replace(
|
| 556 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 557 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 558 |
-
|
| 559 |
-
let chartW = 0, chartH = 0;
|
| 560 |
-
for (const part of parts) {
|
| 561 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 562 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 563 |
-
}
|
| 564 |
-
|
| 565 |
-
const out = document.createElementNS(NS, "svg");
|
| 566 |
-
out.setAttribute("xmlns", NS);
|
| 567 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 568 |
-
let top = pad;
|
| 569 |
-
const later = []; // built after the width is known
|
| 570 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 571 |
-
if (legend && legend.height) {
|
| 572 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 573 |
-
later.push(() => out.appendChild(legend.group));
|
| 574 |
-
top += legend.height + 8;
|
| 575 |
-
}
|
| 576 |
-
|
| 577 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 578 |
-
const height = top + chartH + pad;
|
| 579 |
-
out.setAttribute("width", Math.ceil(width));
|
| 580 |
-
out.setAttribute("height", Math.ceil(height));
|
| 581 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 582 |
-
for (const build of later) build();
|
| 583 |
-
|
| 584 |
-
for (const part of parts) {
|
| 585 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 586 |
-
const clone = part.svg.cloneNode(true);
|
| 587 |
-
resolveVars(clone, resolve);
|
| 588 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 589 |
-
}
|
| 590 |
-
return out;
|
| 591 |
-
}
|
| 592 |
-
|
| 593 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 594 |
-
function slugify(text) {
|
| 595 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 596 |
-
}
|
| 597 |
-
|
| 598 |
-
function downloadUrl(url, filename) {
|
| 599 |
-
const a = document.createElement("a");
|
| 600 |
-
a.href = url;
|
| 601 |
-
a.download = filename;
|
| 602 |
-
document.body.appendChild(a);
|
| 603 |
-
a.click();
|
| 604 |
-
a.remove();
|
| 605 |
-
}
|
| 606 |
-
|
| 607 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 608 |
-
function rasterize(svg, scale, done, fail) {
|
| 609 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 610 |
-
const img = new Image();
|
| 611 |
-
img.onload = () => {
|
| 612 |
-
const canvas = document.createElement("canvas");
|
| 613 |
-
canvas.width = Math.round(width * scale);
|
| 614 |
-
canvas.height = Math.round(height * scale);
|
| 615 |
-
const ctx = canvas.getContext("2d");
|
| 616 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 617 |
-
ctx.drawImage(img, 0, 0);
|
| 618 |
-
done(canvas, width, height);
|
| 619 |
-
};
|
| 620 |
-
img.onerror = fail;
|
| 621 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 622 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 623 |
-
}
|
| 624 |
-
|
| 625 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 626 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 627 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 628 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 629 |
-
// and the pixels land at 96*scale dpi.
|
| 630 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 631 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 632 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 633 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 634 |
-
rgb[j] = pixels[i];
|
| 635 |
-
rgb[j + 1] = pixels[i + 1];
|
| 636 |
-
rgb[j + 2] = pixels[i + 2];
|
| 637 |
-
}
|
| 638 |
-
const deflated = new Uint8Array(await new Response(
|
| 639 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 640 |
-
|
| 641 |
-
const encoder = new TextEncoder();
|
| 642 |
-
const chunks = [];
|
| 643 |
-
const offsets = [];
|
| 644 |
-
let cursor = 0;
|
| 645 |
-
const put = data => {
|
| 646 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 647 |
-
chunks.push(bytes);
|
| 648 |
-
cursor += bytes.length;
|
| 649 |
-
};
|
| 650 |
-
const object = (id, body, stream) => {
|
| 651 |
-
offsets[id] = cursor;
|
| 652 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 653 |
-
if (stream) {
|
| 654 |
-
put("stream\n");
|
| 655 |
-
put(stream);
|
| 656 |
-
put("\nendstream\n");
|
| 657 |
-
}
|
| 658 |
-
put("endobj\n");
|
| 659 |
-
};
|
| 660 |
-
|
| 661 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 662 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 663 |
-
put("%PDF-1.4\n");
|
| 664 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 665 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 666 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 667 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 668 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 669 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 670 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 671 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 672 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 673 |
-
|
| 674 |
-
const xref = cursor;
|
| 675 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 676 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 677 |
-
put(table);
|
| 678 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 679 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 680 |
-
}
|
| 681 |
-
|
| 682 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 683 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 684 |
-
function setUpExport(getParts, basename) {
|
| 685 |
-
const buttons = {
|
| 686 |
-
svg: document.getElementById("btn-svg"),
|
| 687 |
-
png: document.getElementById("btn-png"),
|
| 688 |
-
pdf: document.getElementById("btn-pdf"),
|
| 689 |
-
};
|
| 690 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 691 |
-
|
| 692 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 693 |
-
function complain(format) {
|
| 694 |
-
const button = buttons[format];
|
| 695 |
-
if (!button) return;
|
| 696 |
-
const label = button.textContent;
|
| 697 |
-
button.textContent = "failed";
|
| 698 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 699 |
-
}
|
| 700 |
-
|
| 701 |
-
function run(format) {
|
| 702 |
-
const svg = figure();
|
| 703 |
-
const name = basename();
|
| 704 |
-
if (format === "svg") {
|
| 705 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 706 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 707 |
-
return;
|
| 708 |
-
}
|
| 709 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 710 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 711 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 712 |
-
if (format === "png") {
|
| 713 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 714 |
-
} else {
|
| 715 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 716 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 717 |
-
.catch(() => complain("pdf"));
|
| 718 |
-
}
|
| 719 |
-
}, () => complain(format));
|
| 720 |
-
}
|
| 721 |
-
|
| 722 |
-
for (const format of Object.keys(buttons)) {
|
| 723 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 724 |
-
}
|
| 725 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 726 |
-
window.addEventListener("message", ev => {
|
| 727 |
-
const d = ev.data;
|
| 728 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 729 |
-
});
|
| 730 |
-
}
|
| 731 |
-
|
| 732 |
-
// When embedded, report the content height so the host page can size the
|
| 733 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 734 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 735 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 736 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 737 |
-
// stops re-posting once the height settles.
|
| 738 |
-
let lastPostedHeight = 0;
|
| 739 |
-
function postHeight() {
|
| 740 |
-
if (window.parent === window) return;
|
| 741 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 742 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 743 |
-
lastPostedHeight = height;
|
| 744 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 745 |
-
}
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
// POINTS is one record per matrix label (its model, variant, family and mean
|
| 749 |
-
// win rate); the matrix itself is CONFIG.matrix, row-major over CONFIG.methods.
|
| 750 |
-
const METHODS = CONFIG.methods;
|
| 751 |
-
const MATRIX = CONFIG.matrix;
|
| 752 |
-
const rowOf = new Map(METHODS.map((m, i) => [m, i]));
|
| 753 |
-
const info = new Map(POINTS.map(p => [p.method, p]));
|
| 754 |
-
const MODELS = [...new Set(POINTS.map(p => p.model))];
|
| 755 |
-
const VARIANTS = CONFIG.variants.filter(v => POINTS.some(p => p.variant === v));
|
| 756 |
-
const VARIANT_BTN = { "Tuned + Ens.": "Tuned + Ensembled" };
|
| 757 |
-
|
| 758 |
-
// Reference pipelines are AutoML systems rather than models, so a first read of
|
| 759 |
-
// the matrix should be model against model; they are one chip click away. Falls
|
| 760 |
-
// back to everything if that would leave nothing to compare.
|
| 761 |
-
const OFF_BY_DEFAULT = new Set(["Reference Pipeline"]);
|
| 762 |
-
const familyOf = new Map(POINTS.map(p => [p.model, p.family]));
|
| 763 |
-
const DEFAULT_MODELS = MODELS.filter(m => !OFF_BY_DEFAULT.has(familyOf.get(m)));
|
| 764 |
-
|
| 765 |
-
const state = {
|
| 766 |
-
models: new Set(DEFAULT_MODELS.length > 1 ? DEFAULT_MODELS : MODELS),
|
| 767 |
-
variants: new Set(VARIANTS),
|
| 768 |
-
// One entry per model by default, as the static figure shows it: 80 rows of
|
| 769 |
-
// model-variant pairs is a wall, and the comparison people want first is
|
| 770 |
-
// between models.
|
| 771 |
-
best: true,
|
| 772 |
-
order: "published",
|
| 773 |
-
// Default to fitting the panel: at reading size the matrix is taller than a
|
| 774 |
-
// screen, and the shape of the heatmap is what most readers want first.
|
| 775 |
-
zoom: "fit",
|
| 776 |
-
};
|
| 777 |
-
// Ceiling on the fitted height. Fitting is normally width-driven; this only bites
|
| 778 |
-
// on very tall selections, and it is set where the labels are still readable
|
| 779 |
-
// rather than at half a screen, which would shrink 30 rows to 8px type.
|
| 780 |
-
const FIT_H = 1040;
|
| 781 |
-
// Nominal (drawn) size of the last render; the display size is a CSS scale of it.
|
| 782 |
-
let nomW = 0, nomH = 0;
|
| 783 |
-
const svg = document.getElementById("chart");
|
| 784 |
-
const wrap = document.getElementById("wrap");
|
| 785 |
-
const tooltip = document.querySelector(".tooltip");
|
| 786 |
-
const chipsBox = document.getElementById("chips");
|
| 787 |
-
const famChips = new Map();
|
| 788 |
-
const chipByModel = new Map();
|
| 789 |
-
|
| 790 |
-
// Sized against the static figure rather than the other explorers: that one uses
|
| 791 |
-
// 16pt tick labels and 18pt axis labels on generously sized cells, and it stayed
|
| 792 |
-
// the easier of the two to read. Weight still matches the explorers' 650, so a
|
| 793 |
-
// model name looks like the same name everywhere.
|
| 794 |
-
const LABEL_SIZE = 16, LABEL_WEIGHT = 650, CAPTION_SIZE = 18, CELL = 42, VALUE_SIZE = 15;
|
| 795 |
-
// The colour key is a vertical bar to the right of the matrix, as on the static
|
| 796 |
-
// figure. It sits beside the rows rather than above them, so it is in view
|
| 797 |
-
// wherever the reader is in a tall matrix.
|
| 798 |
-
const BAR_W = 30, BAR_GAP = 32, TICK_SIZE = 15;
|
| 799 |
-
const SCALE_CAPTION = "win rate of the row over the column";
|
| 800 |
-
const SCALE_CAPTION_SHORT = "win rate";
|
| 801 |
-
|
| 802 |
-
// Purple (the column wins) through white to green (the row wins), the same
|
| 803 |
-
// diverging reading as the static figure's PRGn colormap.
|
| 804 |
-
const LOSE = [118, 42, 131], MID = [247, 247, 247], WIN = [27, 120, 55];
|
| 805 |
-
function cellColor(rate) {
|
| 806 |
-
if (rate == null || !isFinite(rate)) return "#8884";
|
| 807 |
-
const t = Math.max(0, Math.min(1, rate));
|
| 808 |
-
const [a, b, u] = t < 0.5 ? [LOSE, MID, t / 0.5] : [MID, WIN, (t - 0.5) / 0.5];
|
| 809 |
-
return "rgb(" + a.map((v, i) => Math.round(v + u * (b[i] - v))).join(",") + ")";
|
| 810 |
-
}
|
| 811 |
-
|
| 812 |
-
// Measured where possible: the labels are model names of wildly different
|
| 813 |
-
// lengths, and the margins have to clear the longest one exactly or a rotated
|
| 814 |
-
// column label runs into the caption above it. `getComputedTextLength` returns 0
|
| 815 |
-
// when the frame has not been laid out yet (it is lazily loaded, and may still be
|
| 816 |
-
// off-screen on the first paint), which would collapse both margins and push
|
| 817 |
-
// every label outside the viewBox — invisible until something forced a redraw.
|
| 818 |
-
// So fall back to an estimate, and redraw once the fonts have settled.
|
| 819 |
-
function textWidth(text, size, weight) {
|
| 820 |
-
const probe = el("text", {
|
| 821 |
-
"font-size": size || LABEL_SIZE, "font-weight": weight || LABEL_WEIGHT,
|
| 822 |
-
}, svg);
|
| 823 |
-
probe.textContent = text;
|
| 824 |
-
let width = 0;
|
| 825 |
-
try { width = probe.getComputedTextLength(); } catch (e) { width = 0; }
|
| 826 |
-
probe.remove();
|
| 827 |
-
return width > 0 ? width : text.length * (size || LABEL_SIZE) * 0.58;
|
| 828 |
-
}
|
| 829 |
-
|
| 830 |
-
// Labels always carry their variant tag — "(default)" / "(tuned + ensembled)" —
|
| 831 |
-
// including in one-per-model mode, where the tag is precisely what says which
|
| 832 |
-
// variant survived the filter. The static figure labels them the same way.
|
| 833 |
-
function labelText(label) {
|
| 834 |
-
return label;
|
| 835 |
-
}
|
| 836 |
-
|
| 837 |
-
function shown() {
|
| 838 |
-
let list = METHODS.filter(label => {
|
| 839 |
-
const p = info.get(label);
|
| 840 |
-
if (!p || !state.models.has(p.model)) return false;
|
| 841 |
-
return !p.variant || state.variants.has(p.variant);
|
| 842 |
-
});
|
| 843 |
-
if (state.best) {
|
| 844 |
-
// Best *among the variants still selected*, so the variant toggles keep
|
| 845 |
-
// meaning something in this mode.
|
| 846 |
-
const pick = new Map();
|
| 847 |
-
for (const label of list) {
|
| 848 |
-
const p = info.get(label);
|
| 849 |
-
const held = pick.get(p.model);
|
| 850 |
-
if (!held || (info.get(held).mean || 0) < (p.mean || 0)) pick.set(p.model, label);
|
| 851 |
-
}
|
| 852 |
-
list = list.filter(label => pick.get(info.get(label).model) === label);
|
| 853 |
-
}
|
| 854 |
-
if (state.order === "winrate") {
|
| 855 |
-
list.sort((a, b) => (info.get(b).mean || 0) - (info.get(a).mean || 0));
|
| 856 |
-
} else if (state.order === "name") {
|
| 857 |
-
list.sort((a, b) => labelText(a).localeCompare(labelText(b)));
|
| 858 |
-
}
|
| 859 |
-
return list;
|
| 860 |
-
}
|
| 861 |
-
|
| 862 |
-
function render() {
|
| 863 |
-
const list = shown();
|
| 864 |
-
svg.innerHTML = "";
|
| 865 |
-
if (list.length < 2) {
|
| 866 |
-
svg.setAttribute("width", 0);
|
| 867 |
-
svg.setAttribute("height", 0);
|
| 868 |
-
// Also drop the display scale, or the empty chart keeps the last figure's box.
|
| 869 |
-
svg.style.width = svg.style.height = "";
|
| 870 |
-
nomW = nomH = 0;
|
| 871 |
-
wrap.querySelector(".wr-empty") ||
|
| 872 |
-
wrap.insertAdjacentHTML("beforeend",
|
| 873 |
-
'<p class="wr-empty">Select at least two models to compare.</p>');
|
| 874 |
-
postHeight();
|
| 875 |
-
return;
|
| 876 |
-
}
|
| 877 |
-
const empty = wrap.querySelector(".wr-empty");
|
| 878 |
-
if (empty) empty.remove();
|
| 879 |
-
|
| 880 |
-
const widths = list.map(label => textWidth(labelText(label)));
|
| 881 |
-
const longest = Math.max(...widths);
|
| 882 |
-
// A label rotated -60° rises 0.866 of its length; the captions sit in the
|
| 883 |
-
// corner box rather than above the columns, where long names would cross them.
|
| 884 |
-
// Floor the header so the two corner captions always have room, even when
|
| 885 |
-
// every selected name is short.
|
| 886 |
-
const headerH = Math.max(Math.ceil(longest * 0.866) + 14, 2 * CAPTION_SIZE + 26);
|
| 887 |
-
const labelW = Math.ceil(longest) + 16;
|
| 888 |
-
const n = list.length;
|
| 889 |
-
// A -60° label anchored at (x, y) reaches (x + 0.5L, y - 0.866L): it grows up
|
| 890 |
-
// *and right*. headerH covers the rise; this covers the run, or the rightmost
|
| 891 |
-
// column's name is clipped by half its length.
|
| 892 |
-
const overhang = Math.ceil(longest * 0.5);
|
| 893 |
-
const matrixRight = labelW + n * CELL;
|
| 894 |
-
// The key occupies the band to the right of the matrix; the label overhang is
|
| 895 |
-
// above the matrix, so the two never collide and the wider of the two wins.
|
| 896 |
-
const tickW = Math.ceil(textWidth("100%", TICK_SIZE, 700));
|
| 897 |
-
const barX = matrixRight + BAR_GAP;
|
| 898 |
-
const keyRight = barX + BAR_W + 12 + tickW + 10 + CAPTION_SIZE;
|
| 899 |
-
const width = Math.max(matrixRight + overhang + 12, keyRight + 10);
|
| 900 |
-
const height = headerH + n * CELL + 12;
|
| 901 |
-
svg.setAttribute("width", width);
|
| 902 |
-
svg.setAttribute("height", height);
|
| 903 |
-
svg.setAttribute("viewBox", "0 0 " + width + " " + height);
|
| 904 |
-
|
| 905 |
-
// Captions, stacked in the corner box and bold, as on the static figure.
|
| 906 |
-
const capB = el("text", {
|
| 907 |
-
x: 4, y: headerH - 34, "font-size": CAPTION_SIZE, "font-weight": 700, fill: "var(--ink)",
|
| 908 |
-
}, svg);
|
| 909 |
-
capB.textContent = "Model B: loser →";
|
| 910 |
-
const capA = el("text", {
|
| 911 |
-
x: 4, y: headerH - 14, "font-size": CAPTION_SIZE, "font-weight": 700, fill: "var(--ink)",
|
| 912 |
-
}, svg);
|
| 913 |
-
capA.textContent = "Model A: winner ↓";
|
| 914 |
-
|
| 915 |
-
list.forEach((label, j) => {
|
| 916 |
-
const x = labelW + j * CELL + CELL / 2 + 4;
|
| 917 |
-
const text = el("text", {
|
| 918 |
-
x: x, y: headerH - 8, "font-size": LABEL_SIZE, "font-weight": LABEL_WEIGHT,
|
| 919 |
-
"text-anchor": "start", fill: FAM_INK[info.get(label).family] || "var(--ink)",
|
| 920 |
-
transform: "rotate(-60 " + x + " " + (headerH - 8) + ")", cursor: "pointer",
|
| 921 |
-
}, svg);
|
| 922 |
-
text.textContent = labelText(label);
|
| 923 |
-
text.addEventListener("click", () => toggleModel(info.get(label).model));
|
| 924 |
-
});
|
| 925 |
-
|
| 926 |
-
list.forEach((rowLabel, i) => {
|
| 927 |
-
const y = headerH + i * CELL;
|
| 928 |
-
const text = el("text", {
|
| 929 |
-
x: labelW - 12, y: y + CELL / 2 + 6, "font-size": LABEL_SIZE, "font-weight": LABEL_WEIGHT,
|
| 930 |
-
"text-anchor": "end", fill: FAM_INK[info.get(rowLabel).family] || "var(--ink)",
|
| 931 |
-
cursor: "pointer",
|
| 932 |
-
}, svg);
|
| 933 |
-
text.textContent = labelText(rowLabel);
|
| 934 |
-
text.addEventListener("click", () => toggleModel(info.get(rowLabel).model));
|
| 935 |
-
|
| 936 |
-
list.forEach((colLabel, j) => {
|
| 937 |
-
const rate = valueAt(rowLabel, colLabel);
|
| 938 |
-
const x = labelW + j * CELL;
|
| 939 |
-
const same = rowLabel === colLabel;
|
| 940 |
-
const rect = el("rect", {
|
| 941 |
-
x: x, y: y, width: CELL - 1, height: CELL - 1, rx: 2,
|
| 942 |
-
fill: same ? "#8883" : cellColor(rate),
|
| 943 |
-
}, svg);
|
| 944 |
-
if (same) return;
|
| 945 |
-
const value = el("text", {
|
| 946 |
-
x: x + (CELL - 1) / 2, y: y + CELL / 2 + 5.5, "font-size": VALUE_SIZE,
|
| 947 |
-
"font-weight": 600, "text-anchor": "middle",
|
| 948 |
-
fill: Math.abs(rate - 0.5) > 0.3 ? "#ffffff" : "#14161a", "pointer-events": "none",
|
| 949 |
-
}, svg);
|
| 950 |
-
value.textContent = rate == null || !isFinite(rate) ? "" : Math.round(rate * 100);
|
| 951 |
-
rect.addEventListener("mousemove", ev => showTip(ev, rowLabel, colLabel, rate));
|
| 952 |
-
rect.addEventListener("mouseleave", () => { tooltip.style.display = "none"; });
|
| 953 |
-
});
|
| 954 |
-
});
|
| 955 |
-
|
| 956 |
-
drawScale(barX, headerH, n * CELL - 2, tickW);
|
| 957 |
-
nomW = width;
|
| 958 |
-
nomH = height;
|
| 959 |
-
applyZoom();
|
| 960 |
-
}
|
| 961 |
-
|
| 962 |
-
// Scale the figure for display only: the width/height *attributes* stay nominal,
|
| 963 |
-
// so the export helpers keep building full-size figures, and the CSS box drives
|
| 964 |
-
// what the page shows (the viewBox does the scaling, so it stays vector-sharp).
|
| 965 |
-
function applyZoom() {
|
| 966 |
-
if (!nomW || !nomH) return;
|
| 967 |
-
let scale = Number(state.zoom);
|
| 968 |
-
if (!(scale > 0)) {
|
| 969 |
-
const availW = Math.max(240, (wrap.clientWidth || nomW) - 4);
|
| 970 |
-
scale = Math.min(1, availW / nomW, FIT_H / nomH);
|
| 971 |
-
}
|
| 972 |
-
svg.style.width = Math.round(nomW * scale) + "px";
|
| 973 |
-
svg.style.height = Math.round(nomH * scale) + "px";
|
| 974 |
-
postHeight();
|
| 975 |
-
}
|
| 976 |
-
|
| 977 |
-
// The colour key, drawn into the figure so it is there in paper view and in an
|
| 978 |
-
// exported SVG/PNG/PDF, not only beside the live chart.
|
| 979 |
-
function drawScale(x, y, barH, tickW) {
|
| 980 |
-
const id = "wr-ramp";
|
| 981 |
-
const grad = el("linearGradient", { id: id, x1: "0", x2: "0", y1: "0", y2: "1" },
|
| 982 |
-
el("defs", {}, svg));
|
| 983 |
-
// Top of the bar is the row winning outright, the bottom is the column winning.
|
| 984 |
-
for (const [offset, rate] of [[0, 1], [0.5, 0.5], [1, 0]]) {
|
| 985 |
-
el("stop", { offset: offset, "stop-color": cellColor(rate) }, grad);
|
| 986 |
-
}
|
| 987 |
-
el("rect", {
|
| 988 |
-
x: x, y: y, width: BAR_W, height: barH, rx: 7,
|
| 989 |
-
fill: "url(#" + id + ")", stroke: "var(--muted)", "stroke-width": 1,
|
| 990 |
-
}, svg);
|
| 991 |
-
for (const [frac, label] of [[0, "100%"], [0.5, "50%"], [1, "0%"]]) {
|
| 992 |
-
const ty = y + frac * barH;
|
| 993 |
-
el("line", {
|
| 994 |
-
x1: x + BAR_W, y1: ty, x2: x + BAR_W + 6, y2: ty,
|
| 995 |
-
stroke: "var(--muted)", "stroke-width": 1.5,
|
| 996 |
-
}, svg);
|
| 997 |
-
const tick = el("text", {
|
| 998 |
-
x: x + BAR_W + 11, y: ty + TICK_SIZE * 0.36, "font-size": TICK_SIZE,
|
| 999 |
-
"font-weight": 700, "text-anchor": "start", fill: "var(--ink)",
|
| 1000 |
-
}, svg);
|
| 1001 |
-
tick.textContent = label;
|
| 1002 |
-
}
|
| 1003 |
-
// The label reads down the bar. It shortens rather than growing past the bar
|
| 1004 |
-
// when only a couple of models are selected: anything above the bar would run
|
| 1005 |
-
// into the rightmost column's rotated name.
|
| 1006 |
-
const size = CAPTION_SIZE - 2;
|
| 1007 |
-
const cx = x + BAR_W + 11 + tickW + 10 + size * 0.5;
|
| 1008 |
-
const cy = y + barH / 2;
|
| 1009 |
-
const caption = el("text", {
|
| 1010 |
-
x: cx, y: cy, "font-size": size, "font-weight": 700,
|
| 1011 |
-
"text-anchor": "middle", fill: "var(--ink)",
|
| 1012 |
-
transform: "rotate(90 " + cx + " " + cy + ")",
|
| 1013 |
-
}, svg);
|
| 1014 |
-
caption.textContent =
|
| 1015 |
-
textWidth(SCALE_CAPTION, size, 700) <= barH ? SCALE_CAPTION : SCALE_CAPTION_SHORT;
|
| 1016 |
-
}
|
| 1017 |
-
|
| 1018 |
-
function valueAt(rowLabel, colLabel) {
|
| 1019 |
-
const i = rowOf.get(rowLabel), j = rowOf.get(colLabel);
|
| 1020 |
-
if (i == null || j == null) return null;
|
| 1021 |
-
const row = MATRIX[i];
|
| 1022 |
-
return row ? row[j] : null;
|
| 1023 |
-
}
|
| 1024 |
-
|
| 1025 |
-
function showTip(ev, rowLabel, colLabel, rate) {
|
| 1026 |
-
tooltip.style.display = "block";
|
| 1027 |
-
tooltip.innerHTML =
|
| 1028 |
-
'<div class="t-name">' + rowLabel + " vs " + colLabel + "</div>" +
|
| 1029 |
-
"<div>" + rowLabel + " wins " + fmtNum(rate * 100, 1) + "% of tasks</div>" +
|
| 1030 |
-
'<div class="t-var">' + colLabel + " wins " + fmtNum((1 - rate) * 100, 1) + "%</div>";
|
| 1031 |
-
const box = document.body.getBoundingClientRect();
|
| 1032 |
-
tooltip.style.left = (ev.clientX - box.left + 14) + "px";
|
| 1033 |
-
tooltip.style.top = (ev.clientY - box.top + 12) + "px";
|
| 1034 |
-
}
|
| 1035 |
-
|
| 1036 |
-
// ---------- model chips, by family ----------
|
| 1037 |
-
function familyModels(fam) {
|
| 1038 |
-
return [...new Set(POINTS.filter(p => p.family === fam).map(p => p.model))];
|
| 1039 |
-
}
|
| 1040 |
-
function meanOfModel(model) {
|
| 1041 |
-
const values = POINTS.filter(p => p.model === model && isFinite(p.mean)).map(p => p.mean);
|
| 1042 |
-
return values.length ? Math.max(...values) : 0;
|
| 1043 |
-
}
|
| 1044 |
-
function buildChips() {
|
| 1045 |
-
const head = document.createElement("div");
|
| 1046 |
-
head.className = "chips-head";
|
| 1047 |
-
head.textContent = "Models compared — click to remove, click a family to toggle the whole group";
|
| 1048 |
-
chipsBox.appendChild(head);
|
| 1049 |
-
for (const fam of FAM_ORDER) {
|
| 1050 |
-
const members = familyModels(fam);
|
| 1051 |
-
if (!members.length) continue;
|
| 1052 |
-
members.sort((a, b) => meanOfModel(b) - meanOfModel(a));
|
| 1053 |
-
const row = document.createElement("div");
|
| 1054 |
-
row.className = "chiprow";
|
| 1055 |
-
const famBtn = document.createElement("button");
|
| 1056 |
-
famBtn.className = "famchip";
|
| 1057 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1058 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1059 |
-
famBtn.title = "Toggle all " + members.length + " " + fam + " models";
|
| 1060 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1061 |
-
row.appendChild(famBtn);
|
| 1062 |
-
famChips.set(fam, famBtn);
|
| 1063 |
-
const set = document.createElement("div");
|
| 1064 |
-
set.className = "chipset";
|
| 1065 |
-
for (const model of members) {
|
| 1066 |
-
const b = document.createElement("button");
|
| 1067 |
-
b.className = "chip";
|
| 1068 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1069 |
-
b.innerHTML = '<span class="dot"></span><span></span>';
|
| 1070 |
-
b.lastChild.textContent = model;
|
| 1071 |
-
b.title = model + " — best mean win rate " + fmtNum(meanOfModel(model) * 100, 1) + "%";
|
| 1072 |
-
b.addEventListener("click", () => toggleModel(model));
|
| 1073 |
-
set.appendChild(b);
|
| 1074 |
-
chipByModel.set(model, b);
|
| 1075 |
-
}
|
| 1076 |
-
row.appendChild(set);
|
| 1077 |
-
chipsBox.appendChild(row);
|
| 1078 |
-
}
|
| 1079 |
-
}
|
| 1080 |
-
function syncChips() {
|
| 1081 |
-
for (const [model, b] of chipByModel) b.setAttribute("aria-pressed", String(state.models.has(model)));
|
| 1082 |
-
for (const [fam, b] of famChips) {
|
| 1083 |
-
b.setAttribute("aria-pressed", String(familyModels(fam).every(m => state.models.has(m))));
|
| 1084 |
-
}
|
| 1085 |
-
}
|
| 1086 |
-
function toggleModel(model) {
|
| 1087 |
-
if (state.models.has(model)) state.models.delete(model); else state.models.add(model);
|
| 1088 |
-
syncChips();
|
| 1089 |
-
render();
|
| 1090 |
-
}
|
| 1091 |
-
function toggleFamily(fam) {
|
| 1092 |
-
const members = familyModels(fam);
|
| 1093 |
-
const allOn = members.every(m => state.models.has(m));
|
| 1094 |
-
for (const m of members) { if (allOn) state.models.delete(m); else state.models.add(m); }
|
| 1095 |
-
syncChips();
|
| 1096 |
-
render();
|
| 1097 |
-
}
|
| 1098 |
-
|
| 1099 |
-
// ---------- variant toggles ----------
|
| 1100 |
-
const variantBtns = new Map();
|
| 1101 |
-
function buildVariantBtns() {
|
| 1102 |
-
const box = document.getElementById("variant-btns");
|
| 1103 |
-
for (const v of VARIANTS) {
|
| 1104 |
-
const b = document.createElement("button");
|
| 1105 |
-
b.className = "btn toggle";
|
| 1106 |
-
b.innerHTML = '<span class="swatch"></span>';
|
| 1107 |
-
// Spelled out: the matrix labels carry the long form the data uses, so the
|
| 1108 |
-
// toggle should not be the only place showing the abbreviated key.
|
| 1109 |
-
b.appendChild(document.createTextNode(VARIANT_BTN[v] || v));
|
| 1110 |
-
b.style.setProperty("--fam", VARIANT_VAR[v] || "var(--accent)");
|
| 1111 |
-
b.title = "Show or hide the " + (VARIANT_BTN[v] || v).toLowerCase() + " results";
|
| 1112 |
-
b.addEventListener("click", () => {
|
| 1113 |
-
if (state.variants.has(v)) state.variants.delete(v); else state.variants.add(v);
|
| 1114 |
-
syncVariantBtns();
|
| 1115 |
-
render();
|
| 1116 |
-
});
|
| 1117 |
-
box.appendChild(b);
|
| 1118 |
-
variantBtns.set(v, b);
|
| 1119 |
-
}
|
| 1120 |
-
}
|
| 1121 |
-
function syncVariantBtns() {
|
| 1122 |
-
for (const [v, b] of variantBtns) b.setAttribute("aria-pressed", String(state.variants.has(v)));
|
| 1123 |
-
}
|
| 1124 |
-
|
| 1125 |
-
// ---------- boot ----------
|
| 1126 |
-
if (CONFIG.title) document.getElementById("title").textContent = CONFIG.title;
|
| 1127 |
-
document.getElementById("zoom-select").addEventListener("change", ev => {
|
| 1128 |
-
state.zoom = ev.target.value;
|
| 1129 |
-
applyZoom();
|
| 1130 |
-
});
|
| 1131 |
-
window.addEventListener("resize", applyZoom);
|
| 1132 |
-
// Embedded in a lazily shown panel, the first render can measure a zero-width
|
| 1133 |
-
// panel; re-fit once it has a width. Width changes only, so the height applyZoom
|
| 1134 |
-
// itself produces cannot feed back into another fit.
|
| 1135 |
-
if (window.ResizeObserver) {
|
| 1136 |
-
let lastWidth = 0;
|
| 1137 |
-
new ResizeObserver(() => {
|
| 1138 |
-
const w = wrap.clientWidth;
|
| 1139 |
-
if (Math.abs(w - lastWidth) < 2) return;
|
| 1140 |
-
lastWidth = w;
|
| 1141 |
-
applyZoom();
|
| 1142 |
-
}).observe(wrap);
|
| 1143 |
-
}
|
| 1144 |
-
document.getElementById("order-select").addEventListener("change", ev => {
|
| 1145 |
-
state.order = ev.target.value;
|
| 1146 |
-
render();
|
| 1147 |
-
});
|
| 1148 |
-
const bestBtn = document.getElementById("btn-best");
|
| 1149 |
-
bestBtn.style.setProperty("--fam", "var(--accent)");
|
| 1150 |
-
bestBtn.addEventListener("click", () => {
|
| 1151 |
-
state.best = !state.best;
|
| 1152 |
-
bestBtn.setAttribute("aria-pressed", String(state.best));
|
| 1153 |
-
render();
|
| 1154 |
-
});
|
| 1155 |
-
bestBtn.setAttribute("aria-pressed", String(state.best));
|
| 1156 |
-
setUpPaperView(render);
|
| 1157 |
-
setUpExport(() => [{ svg: svg, dx: 0 }], () => slugify(CONFIG.title || document.title));
|
| 1158 |
-
buildVariantBtns();
|
| 1159 |
-
buildChips();
|
| 1160 |
-
syncChips();
|
| 1161 |
-
syncVariantBtns();
|
| 1162 |
-
render();
|
| 1163 |
-
// The first render may have had to estimate label widths (see textWidth); redraw
|
| 1164 |
-
// with real measurements as soon as the fonts are in.
|
| 1165 |
-
if (document.fonts && document.fonts.ready) document.fonts.ready.then(render);
|
| 1166 |
-
})();
|
| 1167 |
-
</script>
|
| 1168 |
-
</body>
|
| 1169 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/winrate_matrix.csv
DELETED
|
@@ -1,29 +0,0 @@
|
|
| 1 |
-
,TabFM (default),TabPFN-3 (default),TabPFN-2.6 (default),TabICLv2 (default),RealTabPFN-2.5 (T+E),RealMLP (T+E),ModernNCA (T+E),CatBoost (T+E),LightGBM (T+E),iLTM (T+E),XGBoost (T+E),TabM (T+E),TabDPT-Turbo (default),ChimeraBoost (T+E),TabDPT (T+E),xRFM (T+E),TorchMLP (T+E),TabSwift (default),EBM (T+E),LimiX (default),RandomForest (T+E),FastaiMLP (T+E),SAP-RPT-OSS (default),ExtraTrees (T+E),PerpetualBooster (T+E),TabSTAR (T+E),KNN (T+E),Linear (T+E)
|
| 2 |
-
TabFM (default),,0.78518516,0.93333334,0.9037037,0.91111106,0.88148147,0.92592597,0.8518518,0.9037037,0.8962963,0.9185185,0.99259263,0.9629629,0.9185185,0.87407404,0.92592597,0.9777777,0.97037035,0.99259263,0.9037037,0.9851852,0.9407407,0.9851852,0.99259263,1.0,1.0,0.97037035,0.9851852
|
| 3 |
-
TabPFN-3 (default),0.21481481,,0.77037036,0.6592592,0.82962966,0.762963,0.8592593,0.73333335,0.7555555,0.78518516,0.76296294,0.85925925,0.9185185,0.78518516,0.73333335,0.8,0.8888889,0.9777778,0.84444445,0.8666667,0.962963,0.93333334,0.9481482,0.9777778,0.93333334,1.0,0.9555556,0.94814813
|
| 4 |
-
TabPFN-2.6 (default),0.06666667,0.22962965,,0.4592593,0.5555555,0.6888889,0.67407405,0.65185183,0.73333335,0.7037037,0.7185185,0.73333335,0.71851844,0.77037036,0.7407407,0.80740744,0.8962963,0.9111111,0.9185185,0.8518518,0.97037035,0.91111106,0.97037035,0.9851852,0.99259263,1.0,0.962963,0.9777778
|
| 5 |
-
TabICLv2 (default),0.0962963,0.34074074,0.5407407,,0.73333335,0.64444447,0.7407407,0.67407405,0.7111111,0.68888885,0.6814814,0.7407407,0.78518516,0.6814815,0.77037036,0.73333335,0.8074074,0.9407407,0.77037036,0.87407404,0.9185185,0.8962963,0.94814813,0.99259263,0.93333334,0.9851852,0.97037035,0.94814813
|
| 6 |
-
RealTabPFN-2.5 (T+E),0.08888889,0.17037039,0.44444445,0.26666668,,0.6,0.5777778,0.58518517,0.6296297,0.6148148,0.65925926,0.6148148,0.6296297,0.6074074,0.65925926,0.762963,0.8074074,0.90370375,0.8222222,0.77777773,0.94074076,0.8222223,0.90370375,0.9777778,0.9777778,1.0,0.9407407,0.89629626
|
| 7 |
-
RealMLP (T+E),0.11851852,0.23703703,0.31111115,0.3555556,0.4,,0.53333336,0.5185185,0.60740745,0.63703704,0.63703704,0.5925926,0.5925926,0.5185185,0.5777778,0.8592593,0.8370371,0.75555557,0.8222222,0.88888896,0.9185185,0.9851852,0.92592597,0.93333334,0.9851852,1.0,0.99259263,1.0
|
| 8 |
-
ModernNCA (T+E),0.074074075,0.14074074,0.32592592,0.25925925,0.42222223,0.46666667,,0.52592593,0.5777778,0.6148149,0.6296297,0.6000001,0.54814816,0.62222224,0.6370371,0.7555555,0.8222223,0.78518516,0.8222223,0.88148147,0.8592593,0.91111106,0.9037037,0.93333334,0.99259263,0.94814813,0.99259263,0.93333334
|
| 9 |
-
CatBoost (T+E),0.14814815,0.26666668,0.34814817,0.32592595,0.41481483,0.4814815,0.47407407,,0.5185185,0.6,0.68888885,0.4888889,0.46666667,0.69629633,0.53333336,0.7185185,0.79259264,0.74814814,0.8962963,0.6814815,0.92592597,0.9111111,0.9185185,0.9703704,0.9777778,1.0,0.99259263,0.99259263
|
| 10 |
-
LightGBM (T+E),0.0962963,0.24444444,0.26666668,0.28888893,0.37037042,0.39259258,0.42222223,0.4814815,,0.5407407,0.6888889,0.4740741,0.51851857,0.64444447,0.4962963,0.6444444,0.7555555,0.725926,0.8444444,0.65925926,0.93333334,0.8444444,0.9037037,0.98518527,0.9851852,0.99259263,0.9851852,0.9851852
|
| 11 |
-
iLTM (T+E),0.103703715,0.21481483,0.2962963,0.31111112,0.38518518,0.362963,0.3851852,0.40000004,0.45925924,,0.5407408,0.4888889,0.43703702,0.5037037,0.51111114,0.6296297,0.8814815,0.70370376,0.8000001,0.6888889,0.9111111,0.9703704,0.9111111,0.93333334,0.8666667,0.99259263,0.98518527,0.98518527
|
| 12 |
-
XGBoost (T+E),0.08148149,0.23703705,0.28148147,0.31851855,0.34074074,0.362963,0.3703704,0.3111111,0.3111111,0.4592592,,0.48888886,0.4814815,0.53333336,0.52592593,0.64444447,0.8000001,0.65185183,0.8666666,0.65185183,0.93333334,0.8666667,0.90370375,0.9481482,0.90370375,0.99259263,0.99259263,1.0
|
| 13 |
-
TabM (T+E),0.0074074073,0.14074074,0.26666668,0.25925928,0.3851852,0.4074074,0.4,0.5111111,0.52592593,0.5111111,0.5111111,,0.4814815,0.5185185,0.4666667,0.56296295,0.6666667,0.725926,0.71111107,0.71111107,0.8222223,0.88148147,0.8666667,0.8888889,0.9185185,1.0,0.962963,0.9555556
|
| 14 |
-
TabDPT-Turbo (default),0.037037037,0.08148148,0.28148147,0.21481483,0.37037036,0.4074074,0.45185184,0.53333336,0.4814815,0.56296295,0.5185185,0.5185185,,0.52592593,0.4666667,0.65925926,0.762963,0.8074074,0.6074074,0.7777778,0.7851852,0.762963,0.78518516,0.84444445,0.9111111,0.92592597,0.9037037,0.8222223
|
| 15 |
-
ChimeraBoost (T+E),0.08148148,0.21481483,0.22962962,0.31851852,0.39259255,0.4814815,0.37777779,0.30370373,0.35555556,0.49629626,0.46666667,0.4814815,0.47407407,,0.53333336,0.7037037,0.67407405,0.6444444,0.8148148,0.6296297,0.8592593,0.837037,0.8518518,0.8370371,0.84444445,0.93333334,0.962963,1.0
|
| 16 |
-
TabDPT (T+E),0.12592593,0.26666668,0.25925925,0.22962962,0.34074077,0.42222223,0.362963,0.46666667,0.5037037,0.4888889,0.47407407,0.53333336,0.53333336,0.46666667,,0.7037037,0.7185185,0.71111107,0.6296297,0.725926,0.77777773,0.7925926,0.82962966,0.78518516,0.98518527,0.9037037,0.8962963,0.837037
|
| 17 |
-
xRFM (T+E),0.074074075,0.2,0.1925926,0.26666665,0.23703705,0.14074074,0.24444444,0.28148147,0.35555556,0.37037036,0.35555553,0.43703705,0.34074074,0.2962963,0.2962963,,0.6,0.51111114,0.6296297,0.70370376,0.762963,0.8222222,0.725926,0.80740744,0.837037,0.9037037,0.9777777,0.9851852
|
| 18 |
-
TorchMLP (T+E),0.022222223,0.11111112,0.10370371,0.1925926,0.19259259,0.16296297,0.17777778,0.20740741,0.24444444,0.118518524,0.2,0.33333334,0.23703705,0.32592595,0.28148147,0.4,,0.51851857,0.54814816,0.6,0.725926,0.7407407,0.8148148,0.7555555,0.7333333,0.94814813,0.9407407,0.94074076
|
| 19 |
-
TabSwift (default),0.02962963,0.022222223,0.08888889,0.05925926,0.0962963,0.24444444,0.21481483,0.25185186,0.2740741,0.2962963,0.34814817,0.2740741,0.19259259,0.35555553,0.2888889,0.4888889,0.4814815,,0.54814816,0.59259254,0.5555556,0.7481482,0.6666667,0.6222222,0.79259264,0.8666667,0.8518519,0.8148148
|
| 20 |
-
EBM (T+E),0.0074074073,0.15555556,0.08148148,0.22962965,0.17777778,0.17777778,0.17777778,0.10370371,0.15555556,0.20000002,0.13333334,0.2888889,0.3925926,0.1851852,0.3703704,0.3703704,0.45185184,0.45185187,,0.46666667,0.6148149,0.6444444,0.6666667,0.6666667,0.65185183,0.94074076,0.837037,0.93333334
|
| 21 |
-
LimiX (default),0.096296296,0.13333334,0.14814815,0.12592593,0.22222224,0.11111112,0.118518524,0.31851852,0.34074074,0.3111111,0.34814817,0.2888889,0.22222224,0.37037036,0.27407408,0.2962963,0.4,0.4074074,0.53333336,,0.5111111,0.62222224,0.6,0.4814815,0.5629629,0.68888885,0.7111111,0.762963
|
| 22 |
-
RandomForest (T+E),0.014814815,0.037037037,0.02962963,0.08148148,0.05925926,0.08148148,0.14074074,0.074074075,0.06666667,0.08888889,0.06666667,0.17777778,0.21481483,0.14074074,0.22222222,0.23703702,0.27407408,0.44444445,0.38518518,0.4888889,,0.5925926,0.66666675,0.5555555,0.65185183,0.87407404,0.92592597,0.8666667
|
| 23 |
-
FastaiMLP (T+E),0.05925926,0.06666667,0.08888889,0.10370371,0.17777778,0.014814815,0.08888889,0.08888889,0.15555556,0.02962963,0.13333334,0.11851852,0.23703703,0.16296296,0.20740741,0.17777778,0.25925928,0.25185186,0.35555553,0.37777779,0.4074074,,0.46666667,0.45925924,0.5703704,0.7185185,0.7185185,0.92592597
|
| 24 |
-
SAP-RPT-OSS (default),0.014814815,0.051851854,0.02962963,0.051851854,0.0962963,0.074074075,0.096296296,0.08148148,0.096296296,0.08888889,0.096296296,0.13333334,0.21481483,0.14814815,0.17037037,0.27407408,0.18518518,0.33333334,0.33333334,0.4,0.33333337,0.53333336,,0.4074074,0.6814815,0.725926,0.8592593,0.87407404
|
| 25 |
-
ExtraTrees (T+E),0.0074074073,0.022222223,0.014814815,0.0074074073,0.022222223,0.06666667,0.06666667,0.02962963,0.014814815,0.06666667,0.051851854,0.11111112,0.15555556,0.16296296,0.21481483,0.1925926,0.24444444,0.37777776,0.33333334,0.5185185,0.44444448,0.5407407,0.5925926,,0.63703704,0.8148148,0.82962966,0.8148148
|
| 26 |
-
PerpetualBooster (T+E),0.0,0.06666667,0.0074074073,0.06666667,0.022222223,0.014814815,0.0074074073,0.022222223,0.014814815,0.13333334,0.0962963,0.08148148,0.08888889,0.15555556,0.014814815,0.16296297,0.26666668,0.20740741,0.34814817,0.43703705,0.34814817,0.42962965,0.31851855,0.362963,,0.51111114,0.6296297,0.7037037
|
| 27 |
-
TabSTAR (T+E),0.0,0.0,0.0,0.014814815,0.0,0.0,0.051851854,0.0,0.0074074073,0.0074074073,0.0074074073,0.0,0.074074075,0.06666667,0.096296296,0.0962963,0.051851854,0.13333334,0.059259262,0.31111112,0.12592593,0.28148147,0.27407408,0.18518518,0.4888889,,0.6074074,0.7111111
|
| 28 |
-
KNN (T+E),0.02962963,0.044444446,0.037037037,0.02962963,0.05925926,0.0074074073,0.0074074073,0.0074074073,0.014814815,0.014814815,0.0074074073,0.037037037,0.096296296,0.037037037,0.10370371,0.022222223,0.05925926,0.14814815,0.16296296,0.2888889,0.074074075,0.28148147,0.14074074,0.17037039,0.3703704,0.39259258,,0.7185185
|
| 29 |
-
Linear (T+E),0.014814815,0.051851854,0.022222223,0.051851854,0.10370371,0.0,0.06666667,0.0074074073,0.014814815,0.014814815,0.0,0.044444446,0.17777778,0.0,0.16296296,0.014814815,0.05925926,0.18518518,0.06666667,0.23703703,0.13333334,0.074074075,0.12592593,0.1851852,0.2962963,0.28888887,0.28148147,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_medium/winrate_matrix.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:5107cfc6dd1a7b0b5399ca58f6b0a125daeec11b7c0b14110459409d99ffa3fa
|
| 3 |
-
size 662271
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/leaderboard_overview_explorer.html
DELETED
|
@@ -1,1411 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena leaderboard explorer — no imputation | All Tasks | Small</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Chart: a fixed y-axis pane beside a horizontally scrolling plot pane, so
|
| 269 |
-
the axis stays readable however far right the reader scrolls. */
|
| 270 |
-
.lb-chartwrap { position: relative; display: flex; align-items: flex-start; }
|
| 271 |
-
.lb-axis { flex: none; }
|
| 272 |
-
.lb-scroll {
|
| 273 |
-
flex: 1 1 auto; min-width: 0; overflow-x: auto; overflow-y: hidden;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.lb-scroll::-webkit-scrollbar { height: 10px; }
|
| 277 |
-
.lb-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
.rangepick input[type=range] { width: 96px; accent-color: var(--accent); cursor: pointer; }
|
| 282 |
-
.rangeval { font-variant-numeric: tabular-nums; font-weight: 500; min-width: 3.4em; }
|
| 283 |
-
.lb-empty { padding: 40px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 284 |
-
/* Puts the family key on its own line of the legend strip. */
|
| 285 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 286 |
-
/* Family blocks pack side by side rather than stacking: below a full-width
|
| 287 |
-
chart, one row per family leaves the small ones (Other, Baseline) each
|
| 288 |
-
wasting a line. The wide families still claim a row of their own. */
|
| 289 |
-
.chips { margin-top: 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 290 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 291 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 292 |
-
</style>
|
| 293 |
-
</head>
|
| 294 |
-
<body>
|
| 295 |
-
<div class="viewbar">
|
| 296 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 297 |
-
</div>
|
| 298 |
-
<p class="explorer-title" id="title"></p>
|
| 299 |
-
<!-- One control row above everything it scopes (axis, sorting, variants, selection). -->
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick">Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<label class="metricpick">Sort
|
| 305 |
-
<select id="sort-select"></select>
|
| 306 |
-
</label>
|
| 307 |
-
<label class="metricpick rangepick" title="Raise the axis floor to spread out the top of the field">Zoom
|
| 308 |
-
<input type="range" id="ymin-range" aria-label="Y-axis minimum">
|
| 309 |
-
<span class="rangeval" id="ymin-val"></span>
|
| 310 |
-
</label>
|
| 311 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 312 |
-
<div class="btnrow">
|
| 313 |
-
<button class="btn" id="btn-all">All methods</button>
|
| 314 |
-
<button class="btn" id="btn-top">Top 15</button>
|
| 315 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 316 |
-
</div>
|
| 317 |
-
<span class="hint">Click a column or chip to remove a method · hover for exact values</span>
|
| 318 |
-
</div>
|
| 319 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 320 |
-
<span class="hint">Export figure</span>
|
| 321 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 322 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 323 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 324 |
-
</div>
|
| 325 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 326 |
-
<div class="lb-chartwrap" id="chartwrap">
|
| 327 |
-
<svg id="axis" class="lb-axis" role="presentation"></svg>
|
| 328 |
-
<div class="lb-scroll" id="scroller">
|
| 329 |
-
<svg id="chart" role="img" aria-label="Leaderboard overview"></svg>
|
| 330 |
-
</div>
|
| 331 |
-
<div class="tooltip"></div>
|
| 332 |
-
</div>
|
| 333 |
-
<div class="chips" id="chips"></div>
|
| 334 |
-
<details class="datatable">
|
| 335 |
-
<summary>Data table</summary>
|
| 336 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 337 |
-
</details>
|
| 338 |
-
|
| 339 |
-
<script>
|
| 340 |
-
(function () {
|
| 341 |
-
"use strict";
|
| 342 |
-
const CONFIG = {"title": null, "metrics": [{"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": "", "ci": {"lo": "elo_lo", "hi": "elo_hi"}}, {"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "score", "label": "Score", "axisLabel": "Score \u2014 higher is better", "lowerBetter": false, "fromZero": true, "decimals": 3, "suffix": ""}, {"key": "rank", "label": "Average rank", "axisLabel": "Average rank \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 2, "suffix": ""}, {"key": "hrank", "label": "Harmonic rank", "axisLabel": "Harmonic rank \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 2, "suffix": ""}], "rankMetric": "elo"};
|
| 343 |
-
const POINTS = [{"method":"TabFM","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/google-research\/tabfm","reference":false,"elo":1744.0,"imp":4.654,"score":0.897,"rank":6.9,"hrank":1.74,"elo_hi":1886.0,"elo_lo":1651.0,"imputed_pct":0.0,"imputed":false},{"method":"AutoGluon 1.5 (extreme, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":true,"elo":1638.0,"imp":9.279,"score":0.642,"rank":10.67,"hrank":4.73,"elo_hi":1712.0,"elo_lo":1586.0,"imputed_pct":0.0,"imputed":false},{"method":"TabPFN-3","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2605.13986","reference":false,"elo":1636.0,"imp":10.766,"score":0.675,"rank":10.77,"hrank":4.53,"elo_hi":1716.0,"elo_lo":1580.0,"imputed_pct":0.0,"imputed":false},{"method":"TabPFN-2.6","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1599.0,"imp":11.961,"score":0.616,"rank":12.44,"hrank":6.63,"elo_hi":1668.0,"elo_lo":1552.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1595.0,"imp":11.198,"score":0.593,"rank":12.63,"hrank":5.6,"elo_hi":1681.0,"elo_lo":1533.0,"imputed_pct":0.0,"imputed":false},{"method":"TabICLv2","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2602.11139","reference":false,"elo":1572.0,"imp":11.56,"score":0.633,"rank":13.78,"hrank":5.25,"elo_hi":1678.0,"elo_lo":1494.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1555.0,"imp":11.907,"score":0.547,"rank":14.67,"hrank":6.51,"elo_hi":1624.0,"elo_lo":1499.0,"imputed_pct":0.0,"imputed":false},{"method":"RealTabPFN-2.5","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","reference":false,"elo":1542.0,"imp":12.32,"score":0.536,"rank":15.41,"hrank":8.41,"elo_hi":1622.0,"elo_lo":1493.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1480.0,"imp":14.533,"score":0.402,"rank":19.13,"hrank":11.38,"elo_hi":1542.0,"elo_lo":1436.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","url":"https:\/\/openreview.net\/pdf?id=Y00pwFyrHR","reference":false,"elo":1448.0,"imp":15.33,"score":0.391,"rank":21.19,"hrank":9.11,"elo_hi":1522.0,"elo_lo":1394.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1448.0,"imp":15.246,"score":0.398,"rank":21.22,"hrank":9.27,"elo_hi":1522.0,"elo_lo":1388.0,"imputed_pct":0.0,"imputed":false},{"method":"AutoGluon 1.4 (best, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":true,"elo":1444.0,"imp":15.598,"score":0.326,"rank":21.52,"hrank":13.45,"elo_hi":1495.0,"elo_lo":1398.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1429.0,"imp":15.675,"score":0.325,"rank":22.52,"hrank":12.22,"elo_hi":1481.0,"elo_lo":1381.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1415.0,"imp":15.884,"score":0.356,"rank":23.49,"hrank":10.85,"elo_hi":1485.0,"elo_lo":1357.0,"imputed_pct":0.0,"imputed":false},{"method":"LimiX","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2509.03505","reference":false,"elo":1405.0,"imp":15.155,"score":0.353,"rank":24.21,"hrank":9.41,"elo_hi":1479.0,"elo_lo":1333.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1400.0,"imp":15.91,"score":0.293,"rank":24.6,"hrank":13.5,"elo_hi":1451.0,"elo_lo":1357.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1390.0,"imp":16.937,"score":0.235,"rank":25.34,"hrank":19.43,"elo_hi":1424.0,"elo_lo":1356.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1373.0,"imp":16.561,"score":0.258,"rank":26.55,"hrank":14.04,"elo_hi":1426.0,"elo_lo":1325.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1368.0,"imp":17.041,"score":0.211,"rank":26.99,"hrank":19.52,"elo_hi":1413.0,"elo_lo":1329.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSwift","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/LAMDA-Tabular\/TabSwift","reference":false,"elo":1363.0,"imp":17.224,"score":0.29,"rank":27.32,"hrank":15.91,"elo_hi":1420.0,"elo_lo":1314.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1361.0,"imp":17.421,"score":0.199,"rank":27.46,"hrank":18.84,"elo_hi":1405.0,"elo_lo":1322.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1354.0,"imp":17.279,"score":0.192,"rank":28.01,"hrank":20.68,"elo_hi":1393.0,"elo_lo":1318.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1353.0,"imp":17.389,"score":0.185,"rank":28.07,"hrank":21.83,"elo_hi":1385.0,"elo_lo":1322.0,"imputed_pct":0.0,"imputed":false},{"method":"TabDPT","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","reference":false,"elo":1332.0,"imp":18.023,"score":0.275,"rank":29.74,"hrank":13.6,"elo_hi":1406.0,"elo_lo":1265.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Tuned + Ens.","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1330.0,"imp":17.868,"score":0.203,"rank":29.84,"hrank":18.17,"elo_hi":1378.0,"elo_lo":1288.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1325.0,"imp":17.924,"score":0.158,"rank":30.28,"hrank":23.33,"elo_hi":1358.0,"elo_lo":1288.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1323.0,"imp":18.056,"score":0.178,"rank":30.38,"hrank":15.63,"elo_hi":1363.0,"elo_lo":1281.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1323.0,"imp":18.319,"score":0.227,"rank":30.39,"hrank":13.02,"elo_hi":1384.0,"elo_lo":1267.0,"imputed_pct":0.0,"imputed":false},{"method":"CatBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","reference":false,"elo":1320.0,"imp":18.203,"score":0.159,"rank":30.6,"hrank":22.44,"elo_hi":1355.0,"elo_lo":1285.0,"imputed_pct":0.0,"imputed":false},{"method":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2506.10707","reference":false,"elo":1319.0,"imp":18.839,"score":0.263,"rank":30.69,"hrank":11.14,"elo_hi":1390.0,"elo_lo":1262.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1306.0,"imp":18.133,"score":0.13,"rank":31.71,"hrank":23.26,"elo_hi":1338.0,"elo_lo":1266.0,"imputed_pct":0.0,"imputed":false},{"method":"TabM","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","reference":false,"elo":1296.0,"imp":18.258,"score":0.188,"rank":32.54,"hrank":19.64,"elo_hi":1349.0,"elo_lo":1251.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Tuned","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1282.0,"imp":18.894,"score":0.157,"rank":33.6,"hrank":20.71,"elo_hi":1324.0,"elo_lo":1240.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1278.0,"imp":19.516,"score":0.133,"rank":33.92,"hrank":23.84,"elo_hi":1329.0,"elo_lo":1232.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1260.0,"imp":19.124,"score":0.125,"rank":35.33,"hrank":24.98,"elo_hi":1300.0,"elo_lo":1211.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1260.0,"imp":19.803,"score":0.11,"rank":35.37,"hrank":25.32,"elo_hi":1312.0,"elo_lo":1210.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1260.0,"imp":19.954,"score":0.109,"rank":35.38,"hrank":25.23,"elo_hi":1302.0,"elo_lo":1215.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1258.0,"imp":19.245,"score":0.092,"rank":35.55,"hrank":26.17,"elo_hi":1295.0,"elo_lo":1223.0,"imputed_pct":0.0,"imputed":false},{"method":"ModernNCA","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","reference":false,"elo":1237.0,"imp":21.221,"score":0.097,"rank":37.17,"hrank":21.05,"elo_hi":1284.0,"elo_lo":1186.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1231.0,"imp":20.511,"score":0.079,"rank":37.67,"hrank":26.59,"elo_hi":1279.0,"elo_lo":1187.0,"imputed_pct":0.0,"imputed":false},{"method":"RealMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","reference":false,"elo":1221.0,"imp":20.018,"score":0.079,"rank":38.44,"hrank":26.97,"elo_hi":1260.0,"elo_lo":1178.0,"imputed_pct":0.0,"imputed":false},{"method":"ChimeraBoost","variant":"Default","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","reference":false,"elo":1216.0,"imp":20.941,"score":0.087,"rank":38.82,"hrank":25.36,"elo_hi":1268.0,"elo_lo":1158.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1214.0,"imp":20.712,"score":0.124,"rank":38.99,"hrank":22.53,"elo_hi":1272.0,"elo_lo":1154.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1211.0,"imp":21.641,"score":0.109,"rank":39.24,"hrank":24.93,"elo_hi":1280.0,"elo_lo":1148.0,"imputed_pct":0.0,"imputed":false},{"method":"EBM","variant":"Default","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","reference":false,"elo":1203.0,"imp":21.249,"score":0.074,"rank":39.86,"hrank":25.92,"elo_hi":1251.0,"elo_lo":1150.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1196.0,"imp":20.862,"score":0.078,"rank":40.43,"hrank":29.54,"elo_hi":1239.0,"elo_lo":1147.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1187.0,"imp":22.339,"score":0.101,"rank":41.1,"hrank":23.0,"elo_hi":1252.0,"elo_lo":1121.0,"imputed_pct":0.0,"imputed":false},{"method":"LightGBM","variant":"Default","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","reference":false,"elo":1166.0,"imp":21.229,"score":0.043,"rank":42.71,"hrank":35.31,"elo_hi":1209.0,"elo_lo":1122.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1165.0,"imp":21.847,"score":0.061,"rank":42.8,"hrank":27.62,"elo_hi":1216.0,"elo_lo":1113.0,"imputed_pct":0.0,"imputed":false},{"method":"XGBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","reference":false,"elo":1163.0,"imp":21.244,"score":0.018,"rank":42.91,"hrank":37.21,"elo_hi":1190.0,"elo_lo":1126.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1150.0,"imp":23.216,"score":0.073,"rank":43.96,"hrank":26.88,"elo_hi":1209.0,"elo_lo":1080.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":1132.0,"imp":25.491,"score":0.178,"rank":45.27,"hrank":12.31,"elo_hi":1209.0,"elo_lo":1049.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":1130.0,"imp":25.525,"score":0.174,"rank":45.38,"hrank":11.81,"elo_hi":1208.0,"elo_lo":1046.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1113.0,"imp":23.948,"score":0.046,"rank":46.61,"hrank":25.91,"elo_hi":1165.0,"elo_lo":1045.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":1084.0,"imp":28.451,"score":0.026,"rank":48.72,"hrank":37.31,"elo_hi":1130.0,"elo_lo":1025.0,"imputed_pct":0.0,"imputed":false},{"method":"iLTM","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","reference":false,"elo":1066.0,"imp":24.914,"score":0.039,"rank":49.88,"hrank":31.58,"elo_hi":1128.0,"elo_lo":992.0,"imputed_pct":0.0,"imputed":false},{"method":"TorchMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1058.0,"imp":24.761,"score":0.015,"rank":50.45,"hrank":36.89,"elo_hi":1104.0,"elo_lo":1008.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Tuned","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":1048.0,"imp":29.908,"score":0.014,"rank":51.08,"hrank":37.33,"elo_hi":1098.0,"elo_lo":991.0,"imputed_pct":0.0,"imputed":false},{"method":"xRFM","variant":"Default","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","reference":false,"elo":1043.0,"imp":26.639,"score":0.034,"rank":51.4,"hrank":42.96,"elo_hi":1104.0,"elo_lo":957.0,"imputed_pct":0.0,"imputed":false},{"method":"TabSTAR","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","reference":false,"elo":1033.0,"imp":30.36,"score":0.109,"rank":52.04,"hrank":19.43,"elo_hi":1112.0,"elo_lo":909.0,"imputed_pct":0.0,"imputed":false},{"method":"ExtraTrees","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","reference":false,"elo":1020.0,"imp":27.588,"score":0.017,"rank":52.89,"hrank":44.87,"elo_hi":1080.0,"elo_lo":951.0,"imputed_pct":0.0,"imputed":false},{"method":"RandomForest","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","reference":false,"elo":1000.0,"imp":28.377,"score":0.004,"rank":54.07,"hrank":48.1,"elo_hi":1058.0,"elo_lo":929.0,"imputed_pct":0.0,"imputed":false},{"method":"FastaiMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","reference":false,"elo":1000.0,"imp":26.856,"score":0.005,"rank":54.08,"hrank":37.17,"elo_hi":1049.0,"elo_lo":938.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":1000.0,"imp":29.267,"score":0.022,"rank":54.08,"hrank":35.68,"elo_hi":1065.0,"elo_lo":906.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":974.0,"imp":33.999,"score":0.042,"rank":55.53,"hrank":37.13,"elo_hi":1060.0,"elo_lo":879.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":954.0,"imp":34.411,"score":0.03,"rank":56.63,"hrank":38.68,"elo_hi":1039.0,"elo_lo":855.0,"imputed_pct":0.0,"imputed":false},{"method":"PerpetualBooster","variant":"Default","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","reference":false,"elo":947.0,"imp":32.717,"score":0.0,"rank":57.02,"hrank":41.72,"elo_hi":988.0,"elo_lo":889.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":912.0,"imp":33.953,"score":0.012,"rank":58.72,"hrank":42.52,"elo_hi":980.0,"elo_lo":823.0,"imputed_pct":0.0,"imputed":false},{"method":"Linear","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","reference":false,"elo":879.0,"imp":37.25,"score":0.019,"rank":60.23,"hrank":43.4,"elo_hi":974.0,"elo_lo":761.0,"imputed_pct":0.0,"imputed":false},{"method":"KNN","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","reference":false,"elo":670.0,"imp":47.022,"score":0.0,"rank":66.58,"hrank":57.89,"elo_hi":768.0,"elo_lo":536.0,"imputed_pct":0.0,"imputed":false}];
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 347 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 348 |
-
// already share a color, and each holds only a handful of methods.
|
| 349 |
-
const FAM_MERGED = "Baseline / Other";
|
| 350 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 351 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 352 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 353 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 354 |
-
|
| 355 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 356 |
-
const FAM_VAR = {
|
| 357 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 358 |
-
"Tree-based": "var(--fam-tree)",
|
| 359 |
-
"Neural Network": "var(--fam-nn)",
|
| 360 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 361 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 362 |
-
};
|
| 363 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 364 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 365 |
-
// that chip carries both symbols.
|
| 366 |
-
const FAM_SYMBOL = {
|
| 367 |
-
"Foundation Model": "🧠⚡",
|
| 368 |
-
"Tree-based": "🌳",
|
| 369 |
-
"Neural Network": "🧠🔁",
|
| 370 |
-
"Reference Pipeline": "📊",
|
| 371 |
-
[FAM_MERGED]: "📏 ❓",
|
| 372 |
-
};
|
| 373 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 374 |
-
const VARIANT_VAR = {
|
| 375 |
-
"Default": "var(--var-default)",
|
| 376 |
-
"Tuned": "var(--var-tuned)",
|
| 377 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 378 |
-
};
|
| 379 |
-
|
| 380 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 381 |
-
function famChipLabel(family, count) {
|
| 382 |
-
const symbol = FAM_SYMBOL[family];
|
| 383 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 384 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 385 |
-
}
|
| 386 |
-
|
| 387 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 388 |
-
const FAM_INK = {
|
| 389 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 390 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 391 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 392 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 393 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 394 |
-
};
|
| 395 |
-
|
| 396 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 397 |
-
function el(name, attrs, parent) {
|
| 398 |
-
const node = document.createElementNS(NS, name);
|
| 399 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 400 |
-
if (parent) parent.appendChild(node);
|
| 401 |
-
return node;
|
| 402 |
-
}
|
| 403 |
-
|
| 404 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 405 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 406 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 407 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 408 |
-
function fmtNum(v, decimals) {
|
| 409 |
-
if (v == null || !isFinite(v)) return "—";
|
| 410 |
-
return v.toFixed(decimals);
|
| 411 |
-
}
|
| 412 |
-
|
| 413 |
-
function fmtMetric(metric, v) {
|
| 414 |
-
if (v == null || !isFinite(v)) return "—";
|
| 415 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 416 |
-
}
|
| 417 |
-
|
| 418 |
-
function fmtTime(v) {
|
| 419 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 420 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 421 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 422 |
-
return fmtNum(v, 3) + " s";
|
| 423 |
-
}
|
| 424 |
-
|
| 425 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 426 |
-
function niceStep(raw) {
|
| 427 |
-
if (!(raw > 0)) return 1;
|
| 428 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 429 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 430 |
-
if (mag * m >= raw) return mag * m;
|
| 431 |
-
}
|
| 432 |
-
return mag * 10;
|
| 433 |
-
}
|
| 434 |
-
|
| 435 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 436 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 437 |
-
function ticks(min, max, target) {
|
| 438 |
-
const step = niceStep((max - min) / target);
|
| 439 |
-
const first = Math.ceil(min / step);
|
| 440 |
-
const out = [];
|
| 441 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 442 |
-
return out.length ? out : [min];
|
| 443 |
-
}
|
| 444 |
-
|
| 445 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 446 |
-
function makeTooltip(box) {
|
| 447 |
-
const node = box.querySelector(".tooltip");
|
| 448 |
-
return {
|
| 449 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 450 |
-
move(ev) {
|
| 451 |
-
const r = box.getBoundingClientRect();
|
| 452 |
-
let tx = ev.clientX - r.left + 14;
|
| 453 |
-
const ty = ev.clientY - r.top + 12;
|
| 454 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 455 |
-
node.style.left = tx + "px";
|
| 456 |
-
node.style.top = ty + "px";
|
| 457 |
-
},
|
| 458 |
-
hide() { node.style.display = "none"; },
|
| 459 |
-
};
|
| 460 |
-
}
|
| 461 |
-
|
| 462 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 463 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 464 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 465 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 466 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 467 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 468 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 469 |
-
function setUpPaperView(afterToggle, options) {
|
| 470 |
-
const opts = options || {};
|
| 471 |
-
const root = document.documentElement;
|
| 472 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 473 |
-
const btn = document.getElementById("btn-paper");
|
| 474 |
-
const embedded = window.parent !== window;
|
| 475 |
-
|
| 476 |
-
function setPaper(on) {
|
| 477 |
-
document.body.classList.toggle("paper", on);
|
| 478 |
-
if (on) {
|
| 479 |
-
hostTheme = root.getAttribute("data-theme");
|
| 480 |
-
root.setAttribute("data-theme", "light");
|
| 481 |
-
} else if (hostTheme) {
|
| 482 |
-
root.setAttribute("data-theme", hostTheme);
|
| 483 |
-
} else {
|
| 484 |
-
root.removeAttribute("data-theme");
|
| 485 |
-
}
|
| 486 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 487 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 488 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 489 |
-
postHeight();
|
| 490 |
-
}
|
| 491 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 492 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 493 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 494 |
-
// shareable single file) this page needs its own.
|
| 495 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 496 |
-
window.addEventListener("message", ev => {
|
| 497 |
-
const d = ev.data;
|
| 498 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 499 |
-
});
|
| 500 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 501 |
-
// key press, so its label would fall out of step with the frame.
|
| 502 |
-
if (!embedded) {
|
| 503 |
-
document.addEventListener("keydown", ev => {
|
| 504 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 505 |
-
});
|
| 506 |
-
}
|
| 507 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 508 |
-
}
|
| 509 |
-
|
| 510 |
-
// --- Figure export ---------------------------------------------------------
|
| 511 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 512 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 513 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 514 |
-
// the legend is HTML rather than part of the SVG.
|
| 515 |
-
|
| 516 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 517 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 518 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 519 |
-
// break the PNG path.
|
| 520 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 521 |
-
// once the node leaves this document.
|
| 522 |
-
function resolveVars(root, resolve) {
|
| 523 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 524 |
-
for (const attr of ["fill", "stroke"]) {
|
| 525 |
-
const value = node.getAttribute(attr);
|
| 526 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 527 |
-
}
|
| 528 |
-
}
|
| 529 |
-
}
|
| 530 |
-
|
| 531 |
-
function legendToSvg(container, resolve) {
|
| 532 |
-
const base = container.getBoundingClientRect();
|
| 533 |
-
const group = document.createElementNS(NS, "g");
|
| 534 |
-
let height = 0;
|
| 535 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 536 |
-
const box = item.getBoundingClientRect();
|
| 537 |
-
if (!box.width) continue;
|
| 538 |
-
height = Math.max(height, box.bottom - base.top);
|
| 539 |
-
let textLeft = box.left - base.left;
|
| 540 |
-
const glyph = item.querySelector("svg");
|
| 541 |
-
if (glyph) {
|
| 542 |
-
const gbox = glyph.getBoundingClientRect();
|
| 543 |
-
const wrap = el("g", {
|
| 544 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 545 |
-
}, group);
|
| 546 |
-
const glyphClone = glyph.cloneNode(true);
|
| 547 |
-
resolveVars(glyphClone, resolve);
|
| 548 |
-
wrap.appendChild(glyphClone);
|
| 549 |
-
textLeft = gbox.right - base.left + 5;
|
| 550 |
-
}
|
| 551 |
-
const label = item.textContent.trim();
|
| 552 |
-
if (!label) continue;
|
| 553 |
-
const colored = item.querySelector("[style*='color']");
|
| 554 |
-
const text = el("text", {
|
| 555 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 556 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 557 |
-
}, group);
|
| 558 |
-
text.textContent = label;
|
| 559 |
-
}
|
| 560 |
-
return { group, height: Math.ceil(height) };
|
| 561 |
-
}
|
| 562 |
-
|
| 563 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 564 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 565 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 566 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 567 |
-
const resolve = value => String(value).replace(
|
| 568 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 569 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 570 |
-
|
| 571 |
-
let chartW = 0, chartH = 0;
|
| 572 |
-
for (const part of parts) {
|
| 573 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 574 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 575 |
-
}
|
| 576 |
-
|
| 577 |
-
const out = document.createElementNS(NS, "svg");
|
| 578 |
-
out.setAttribute("xmlns", NS);
|
| 579 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 580 |
-
let top = pad;
|
| 581 |
-
const later = []; // built after the width is known
|
| 582 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 583 |
-
if (legend && legend.height) {
|
| 584 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 585 |
-
later.push(() => out.appendChild(legend.group));
|
| 586 |
-
top += legend.height + 8;
|
| 587 |
-
}
|
| 588 |
-
|
| 589 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 590 |
-
const height = top + chartH + pad;
|
| 591 |
-
out.setAttribute("width", Math.ceil(width));
|
| 592 |
-
out.setAttribute("height", Math.ceil(height));
|
| 593 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 594 |
-
for (const build of later) build();
|
| 595 |
-
|
| 596 |
-
for (const part of parts) {
|
| 597 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 598 |
-
const clone = part.svg.cloneNode(true);
|
| 599 |
-
resolveVars(clone, resolve);
|
| 600 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 601 |
-
}
|
| 602 |
-
return out;
|
| 603 |
-
}
|
| 604 |
-
|
| 605 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 606 |
-
function slugify(text) {
|
| 607 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 608 |
-
}
|
| 609 |
-
|
| 610 |
-
function downloadUrl(url, filename) {
|
| 611 |
-
const a = document.createElement("a");
|
| 612 |
-
a.href = url;
|
| 613 |
-
a.download = filename;
|
| 614 |
-
document.body.appendChild(a);
|
| 615 |
-
a.click();
|
| 616 |
-
a.remove();
|
| 617 |
-
}
|
| 618 |
-
|
| 619 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 620 |
-
function rasterize(svg, scale, done, fail) {
|
| 621 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 622 |
-
const img = new Image();
|
| 623 |
-
img.onload = () => {
|
| 624 |
-
const canvas = document.createElement("canvas");
|
| 625 |
-
canvas.width = Math.round(width * scale);
|
| 626 |
-
canvas.height = Math.round(height * scale);
|
| 627 |
-
const ctx = canvas.getContext("2d");
|
| 628 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 629 |
-
ctx.drawImage(img, 0, 0);
|
| 630 |
-
done(canvas, width, height);
|
| 631 |
-
};
|
| 632 |
-
img.onerror = fail;
|
| 633 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 634 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 635 |
-
}
|
| 636 |
-
|
| 637 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 638 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 639 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 640 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 641 |
-
// and the pixels land at 96*scale dpi.
|
| 642 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 643 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 644 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 645 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 646 |
-
rgb[j] = pixels[i];
|
| 647 |
-
rgb[j + 1] = pixels[i + 1];
|
| 648 |
-
rgb[j + 2] = pixels[i + 2];
|
| 649 |
-
}
|
| 650 |
-
const deflated = new Uint8Array(await new Response(
|
| 651 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 652 |
-
|
| 653 |
-
const encoder = new TextEncoder();
|
| 654 |
-
const chunks = [];
|
| 655 |
-
const offsets = [];
|
| 656 |
-
let cursor = 0;
|
| 657 |
-
const put = data => {
|
| 658 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 659 |
-
chunks.push(bytes);
|
| 660 |
-
cursor += bytes.length;
|
| 661 |
-
};
|
| 662 |
-
const object = (id, body, stream) => {
|
| 663 |
-
offsets[id] = cursor;
|
| 664 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 665 |
-
if (stream) {
|
| 666 |
-
put("stream\n");
|
| 667 |
-
put(stream);
|
| 668 |
-
put("\nendstream\n");
|
| 669 |
-
}
|
| 670 |
-
put("endobj\n");
|
| 671 |
-
};
|
| 672 |
-
|
| 673 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 674 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 675 |
-
put("%PDF-1.4\n");
|
| 676 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 677 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 678 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 679 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 680 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 681 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 682 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 683 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 684 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 685 |
-
|
| 686 |
-
const xref = cursor;
|
| 687 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 688 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 689 |
-
put(table);
|
| 690 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 691 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 692 |
-
}
|
| 693 |
-
|
| 694 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 695 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 696 |
-
function setUpExport(getParts, basename) {
|
| 697 |
-
const buttons = {
|
| 698 |
-
svg: document.getElementById("btn-svg"),
|
| 699 |
-
png: document.getElementById("btn-png"),
|
| 700 |
-
pdf: document.getElementById("btn-pdf"),
|
| 701 |
-
};
|
| 702 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 703 |
-
|
| 704 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 705 |
-
function complain(format) {
|
| 706 |
-
const button = buttons[format];
|
| 707 |
-
if (!button) return;
|
| 708 |
-
const label = button.textContent;
|
| 709 |
-
button.textContent = "failed";
|
| 710 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 711 |
-
}
|
| 712 |
-
|
| 713 |
-
function run(format) {
|
| 714 |
-
const svg = figure();
|
| 715 |
-
const name = basename();
|
| 716 |
-
if (format === "svg") {
|
| 717 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 718 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 719 |
-
return;
|
| 720 |
-
}
|
| 721 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 722 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 723 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 724 |
-
if (format === "png") {
|
| 725 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 726 |
-
} else {
|
| 727 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 728 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 729 |
-
.catch(() => complain("pdf"));
|
| 730 |
-
}
|
| 731 |
-
}, () => complain(format));
|
| 732 |
-
}
|
| 733 |
-
|
| 734 |
-
for (const format of Object.keys(buttons)) {
|
| 735 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 736 |
-
}
|
| 737 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 738 |
-
window.addEventListener("message", ev => {
|
| 739 |
-
const d = ev.data;
|
| 740 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 741 |
-
});
|
| 742 |
-
}
|
| 743 |
-
|
| 744 |
-
// When embedded, report the content height so the host page can size the
|
| 745 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 746 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 747 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 748 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 749 |
-
// stops re-posting once the height settles.
|
| 750 |
-
let lastPostedHeight = 0;
|
| 751 |
-
function postHeight() {
|
| 752 |
-
if (window.parent === window) return;
|
| 753 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 754 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 755 |
-
lastPostedHeight = height;
|
| 756 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 757 |
-
}
|
| 758 |
-
|
| 759 |
-
|
| 760 |
-
// ---------- geometry ----------
|
| 761 |
-
const AXIS_W = 72; // width of the sticky y-axis pane
|
| 762 |
-
const PLOT_H = 320; // height of the plot area itself
|
| 763 |
-
const TOP = 14; // headroom above the tallest bar
|
| 764 |
-
const LABEL_TOP = 18; // axis line -> first label row
|
| 765 |
-
const LABEL_ROW = 19; // vertical offset of the staggered second row
|
| 766 |
-
const LABEL_SIZE = 14; // method names; the slot below scales with it
|
| 767 |
-
const TICK_SIZE = 12.5;
|
| 768 |
-
// Method names are set horizontally (rotated ones are markedly harder to
|
| 769 |
-
// read), staggered over two rows exactly like the static figure — so a slot
|
| 770 |
-
// has to be wide enough for half a name. Past ~24 methods the chart scrolls
|
| 771 |
-
// rather than squeezing every column into the viewport.
|
| 772 |
-
// No upper bound on the slot: with few methods selected a capped slot left
|
| 773 |
-
// the columns huddled on the left with dead space beside them, so the slots
|
| 774 |
-
// simply share out whatever width there is.
|
| 775 |
-
const MIN_SLOT = 66;
|
| 776 |
-
const BAR_FRAC = 0.88; // share of the slot the widest bar takes
|
| 777 |
-
const MAX_BAR = 70; // ...but never wider than this, however few columns
|
| 778 |
-
|
| 779 |
-
// Variant -> (color token, width relative to the widest bar). The bars are
|
| 780 |
-
// concentric, so the nesting itself encodes the tuning progression.
|
| 781 |
-
const VARIANT_STYLE = {
|
| 782 |
-
"Tuned + Ens.": { color: "var(--var-tunedens)", rel: 1 },
|
| 783 |
-
"Tuned": { color: "var(--var-tuned)", rel: 0.8 },
|
| 784 |
-
"Default": { color: "var(--var-default)", rel: 0.6 },
|
| 785 |
-
};
|
| 786 |
-
const VARIANT_ORDER = ["Default", "Tuned", "Tuned + Ens."];
|
| 787 |
-
// Dash patterns cycle so several reference lines stay distinguishable.
|
| 788 |
-
const REF_DASHES = ["8 5", "2 4", "12 4 3 4"];
|
| 789 |
-
|
| 790 |
-
const titleEl = document.getElementById("title");
|
| 791 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 792 |
-
|
| 793 |
-
const axisSvg = document.getElementById("axis");
|
| 794 |
-
const svg = document.getElementById("chart");
|
| 795 |
-
const scroller = document.getElementById("scroller");
|
| 796 |
-
const wrap = document.getElementById("chartwrap");
|
| 797 |
-
const yminRange = document.getElementById("ymin-range");
|
| 798 |
-
const yminVal = document.getElementById("ymin-val");
|
| 799 |
-
const tip = makeTooltip(wrap);
|
| 800 |
-
|
| 801 |
-
// ---------- data ----------
|
| 802 |
-
const METRICS = CONFIG.metrics;
|
| 803 |
-
const metricByKey = {};
|
| 804 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 805 |
-
|
| 806 |
-
// One entry per method (its variants grouped); reference pipelines are kept
|
| 807 |
-
// apart — they are drawn as threshold lines, not as columns.
|
| 808 |
-
const byMethod = new Map();
|
| 809 |
-
const refs = [];
|
| 810 |
-
for (const p of POINTS) {
|
| 811 |
-
if (p.reference) { refs.push(p); continue; }
|
| 812 |
-
let entry = byMethod.get(p.method);
|
| 813 |
-
if (!entry) {
|
| 814 |
-
entry = { method: p.method, family: p.family, url: p.url, points: [] };
|
| 815 |
-
byMethod.set(p.method, entry);
|
| 816 |
-
}
|
| 817 |
-
entry.points.push(p);
|
| 818 |
-
}
|
| 819 |
-
for (const e of byMethod.values()) {
|
| 820 |
-
e.points.sort((a, b) => VARIANT_ORDER.indexOf(a.variant) - VARIANT_ORDER.indexOf(b.variant));
|
| 821 |
-
e.imputed = e.points.some(p => p.imputed);
|
| 822 |
-
e.imputed_pct = Math.max(...e.points.map(p => p.imputed_pct || 0));
|
| 823 |
-
}
|
| 824 |
-
|
| 825 |
-
const state = {
|
| 826 |
-
metric: METRICS[0].key,
|
| 827 |
-
sort: "best",
|
| 828 |
-
yMin: null, // null = the automatic axis floor; a number = zoomed in
|
| 829 |
-
|
| 830 |
-
methods: new Set(byMethod.keys()),
|
| 831 |
-
refs: new Set(refs.map(r => r.method)),
|
| 832 |
-
variants: new Set(VARIANT_ORDER),
|
| 833 |
-
};
|
| 834 |
-
|
| 835 |
-
function metric() { return metricByKey[state.metric]; }
|
| 836 |
-
|
| 837 |
-
// A method's best value under `m`, ignoring variants the reader switched off.
|
| 838 |
-
function bestOf(entry, m) {
|
| 839 |
-
const vals = entry.points
|
| 840 |
-
.filter(p => state.variants.has(p.variant) && p[m.key] != null)
|
| 841 |
-
.map(p => p[m.key]);
|
| 842 |
-
if (!vals.length) return null;
|
| 843 |
-
return m.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 844 |
-
}
|
| 845 |
-
|
| 846 |
-
function sortedMethods(entries, m) {
|
| 847 |
-
const arr = [...entries];
|
| 848 |
-
const cmp = {
|
| 849 |
-
best: (a, b) => rankVal(a, m) - rankVal(b, m),
|
| 850 |
-
worst: (a, b) => rankVal(b, m) - rankVal(a, m),
|
| 851 |
-
name: (a, b) => a.method.localeCompare(b.method),
|
| 852 |
-
family: (a, b) =>
|
| 853 |
-
FAM_ORDER.indexOf(a.family) - FAM_ORDER.indexOf(b.family) || rankVal(a, m) - rankVal(b, m),
|
| 854 |
-
}[state.sort];
|
| 855 |
-
return arr.sort(cmp);
|
| 856 |
-
}
|
| 857 |
-
// Sort key that puts "better" first for either metric direction, with
|
| 858 |
-
// value-less methods last.
|
| 859 |
-
function rankVal(entry, m) {
|
| 860 |
-
const v = bestOf(entry, m);
|
| 861 |
-
if (v == null) return Infinity;
|
| 862 |
-
return m.lowerBetter ? v : -v;
|
| 863 |
-
}
|
| 864 |
-
|
| 865 |
-
function visibleEntries() {
|
| 866 |
-
const m = metric();
|
| 867 |
-
return sortedMethods([...byMethod.values()].filter(e => state.methods.has(e.method) && bestOf(e, m) != null), m);
|
| 868 |
-
}
|
| 869 |
-
function visibleRefs() {
|
| 870 |
-
return refs.filter(r => state.refs.has(r.method) && r[state.metric] != null);
|
| 871 |
-
}
|
| 872 |
-
|
| 873 |
-
// Rendered width of each label, measured in the live document (font metrics
|
| 874 |
-
// are not knowable up front): it decides whether the names fit on one row or
|
| 875 |
-
// need the two-row stagger, and which ones have to be shortened.
|
| 876 |
-
function measureLabels(names) {
|
| 877 |
-
const probe = el("g", { visibility: "hidden" }, svg);
|
| 878 |
-
const widths = names.map(name => {
|
| 879 |
-
const t = el("text", { "font-size": LABEL_SIZE }, probe);
|
| 880 |
-
t.textContent = name;
|
| 881 |
-
return t.getComputedTextLength();
|
| 882 |
-
});
|
| 883 |
-
probe.remove();
|
| 884 |
-
return widths;
|
| 885 |
-
}
|
| 886 |
-
|
| 887 |
-
// Trim a name to `budget` px, ending in an ellipsis. The full name stays one
|
| 888 |
-
// hover (and one data-table row) away.
|
| 889 |
-
function fitLabel(node, name, width, budget) {
|
| 890 |
-
if (width <= budget) return;
|
| 891 |
-
let text = name;
|
| 892 |
-
while (text.length > 1 && node.getComputedTextLength() > budget) {
|
| 893 |
-
text = text.slice(0, -1);
|
| 894 |
-
node.textContent = text + "…";
|
| 895 |
-
}
|
| 896 |
-
}
|
| 897 |
-
|
| 898 |
-
// ---------- chart ----------
|
| 899 |
-
function render() {
|
| 900 |
-
const m = metric();
|
| 901 |
-
const entries = visibleEntries();
|
| 902 |
-
const shownRefs = visibleRefs();
|
| 903 |
-
svg.textContent = "";
|
| 904 |
-
axisSvg.textContent = "";
|
| 905 |
-
axisSvg.setAttribute("width", AXIS_W);
|
| 906 |
-
|
| 907 |
-
const avail = Math.max(240, scroller.clientWidth - 2);
|
| 908 |
-
if (!entries.length) {
|
| 909 |
-
axisSvg.setAttribute("height", 120);
|
| 910 |
-
svg.setAttribute("width", avail);
|
| 911 |
-
svg.setAttribute("height", 120);
|
| 912 |
-
const t = el("text", { x: avail / 2, y: 60, "text-anchor": "middle", "font-size": 13, fill: "var(--muted)" }, svg);
|
| 913 |
-
t.textContent = "No methods selected — use “All methods” to bring them back.";
|
| 914 |
-
buildLegend(m, shownRefs);
|
| 915 |
-
postHeight();
|
| 916 |
-
return;
|
| 917 |
-
}
|
| 918 |
-
|
| 919 |
-
const slot = Math.max(MIN_SLOT, avail / entries.length);
|
| 920 |
-
const barUnit = Math.min(MAX_BAR, slot * BAR_FRAC);
|
| 921 |
-
const plotW = Math.max(avail, slot * entries.length);
|
| 922 |
-
// Names go on one row when they fit side by side, otherwise on two
|
| 923 |
-
// staggered rows (each label then has two slots of room).
|
| 924 |
-
const labels = entries.map(e => e.method + (e.imputed ? " ‡" : ""));
|
| 925 |
-
const labelWidths = measureLabels(labels);
|
| 926 |
-
const widest = Math.max(...labelWidths);
|
| 927 |
-
const labelRows = widest <= slot - 6 ? 1 : 2;
|
| 928 |
-
const H = TOP + PLOT_H + LABEL_TOP + (labelRows - 1) * LABEL_ROW + 10;
|
| 929 |
-
svg.setAttribute("width", plotW);
|
| 930 |
-
svg.setAttribute("height", H);
|
| 931 |
-
axisSvg.setAttribute("height", H);
|
| 932 |
-
|
| 933 |
-
// -- y domain: from zero where the metric has one, else a floor below the
|
| 934 |
-
// shortest bar (Elo has no meaningful zero, and starting at zero would
|
| 935 |
-
// squash every difference into the top fifth of the chart). The floor
|
| 936 |
-
// ignores the CI whiskers so one wide interval cannot deflate the scale.
|
| 937 |
-
const barVals = [];
|
| 938 |
-
const allVals = [];
|
| 939 |
-
for (const e of entries) {
|
| 940 |
-
for (const p of e.points) {
|
| 941 |
-
if (!state.variants.has(p.variant) || p[m.key] == null) continue;
|
| 942 |
-
barVals.push(p[m.key]);
|
| 943 |
-
allVals.push(p[m.key]);
|
| 944 |
-
if (m.ci && p[m.ci.hi] != null) allVals.push(p[m.ci.hi]);
|
| 945 |
-
}
|
| 946 |
-
}
|
| 947 |
-
for (const r of shownRefs) { barVals.push(r[state.metric]); allVals.push(r[state.metric]); }
|
| 948 |
-
const barMin = Math.min(...barVals), barMax = Math.max(...allVals);
|
| 949 |
-
const span = barMax - barMin || Math.abs(barMax) || 1;
|
| 950 |
-
let autoY0, y1;
|
| 951 |
-
if (m.fromZero) {
|
| 952 |
-
autoY0 = 0;
|
| 953 |
-
y1 = barMax * 1.06 || 1;
|
| 954 |
-
} else {
|
| 955 |
-
// Snap the floor down to a tick multiple so the axis reads in round
|
| 956 |
-
// numbers, and keep it just below the shortest bar: every bar stays
|
| 957 |
-
// visible (the static figure clips the ones below its fixed floor).
|
| 958 |
-
const step = niceStep(span / 6);
|
| 959 |
-
autoY0 = Math.floor((barMin - span * 0.05) / step) * step;
|
| 960 |
-
y1 = barMax + span * 0.04;
|
| 961 |
-
}
|
| 962 |
-
// The zoom slider raises the floor from there toward the top of the field,
|
| 963 |
-
// magnifying the differences between the leaders. Its bounds follow the
|
| 964 |
-
// metric's own scale, so they are refreshed on every render; the bars and
|
| 965 |
-
// whiskers that drop below the new floor are clipped away (see plot-clip).
|
| 966 |
-
const zoomMax = autoY0 + (y1 - autoY0) * 0.9;
|
| 967 |
-
yminRange.min = autoY0;
|
| 968 |
-
yminRange.max = zoomMax;
|
| 969 |
-
yminRange.step = (zoomMax - autoY0) / 200 || 1;
|
| 970 |
-
if (state.yMin != null) state.yMin = Math.min(state.yMin, zoomMax);
|
| 971 |
-
if (state.yMin != null && state.yMin <= autoY0) state.yMin = null;
|
| 972 |
-
const y0 = state.yMin == null ? autoY0 : state.yMin;
|
| 973 |
-
yminRange.value = y0;
|
| 974 |
-
yminVal.textContent = state.yMin == null ? "auto" : fmtNum(y0, m.decimals);
|
| 975 |
-
const Y = v => TOP + (1 - (v - y0) / (y1 - y0)) * PLOT_H;
|
| 976 |
-
const baseY = Y(y0);
|
| 977 |
-
|
| 978 |
-
// -- grid (solid hairlines) in the plot pane, tick labels in the axis pane
|
| 979 |
-
const tickVals = ticks(y0, y1, 6);
|
| 980 |
-
const grid = el("g", {}, svg);
|
| 981 |
-
const tickLabels = [];
|
| 982 |
-
for (const tv of tickVals) {
|
| 983 |
-
const gy = Y(tv);
|
| 984 |
-
el("line", { x1: 0, y1: gy, x2: plotW, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 985 |
-
const t = el("text", {
|
| 986 |
-
x: AXIS_W - 10, y: gy + 4, "text-anchor": "end", "font-size": TICK_SIZE, fill: "var(--muted)",
|
| 987 |
-
}, axisSvg);
|
| 988 |
-
t.textContent = fmtNum(tv, m.decimals);
|
| 989 |
-
tickLabels.push({ y: gy, node: t });
|
| 990 |
-
}
|
| 991 |
-
el("line", { x1: 0, y1: baseY, x2: plotW, y2: baseY, stroke: "var(--muted)", "stroke-width": 1 }, grid);
|
| 992 |
-
el("line", { x1: AXIS_W - 1, y1: TOP, x2: AXIS_W - 1, y2: baseY, stroke: "var(--muted)", "stroke-width": 1 }, axisSvg);
|
| 993 |
-
el("text", {
|
| 994 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": LABEL_SIZE, "font-weight": 650,
|
| 995 |
-
fill: "var(--ink)", transform: `translate(15 ${TOP + PLOT_H / 2}) rotate(-90)`,
|
| 996 |
-
}, axisSvg).textContent = m.axisLabel;
|
| 997 |
-
|
| 998 |
-
// -- hover band behind the marks (highlights the whole column group)
|
| 999 |
-
const band = el("rect", {
|
| 1000 |
-
x: 0, y: TOP, width: slot, height: PLOT_H + 6, fill: "var(--ink)", opacity: 0, "pointer-events": "none",
|
| 1001 |
-
}, svg);
|
| 1002 |
-
|
| 1003 |
-
const defs = el("defs", {}, svg);
|
| 1004 |
-
// -- imputed hatch, reused by every partially imputed bar. Crossed diagonals,
|
| 1005 |
-
// matching the "x" hatch matplotlib draws in the static figure; the
|
| 1006 |
-
// diagonals meet the tile corners exactly, so the grid tiles seamlessly.
|
| 1007 |
-
const pat = el("pattern", {
|
| 1008 |
-
id: "imp-hatch", width: 8, height: 8, patternUnits: "userSpaceOnUse",
|
| 1009 |
-
}, defs);
|
| 1010 |
-
el("path", {
|
| 1011 |
-
d: "M0,0 L8,8 M8,0 L0,8", stroke: "var(--paper)", "stroke-width": 1.5,
|
| 1012 |
-
opacity: 0.85, fill: "none",
|
| 1013 |
-
}, pat);
|
| 1014 |
-
|
| 1015 |
-
// -- Everything data-bearing is clipped to the plot area. The axis floor is
|
| 1016 |
-
// set from the bar values (a couple of very wide intervals would
|
| 1017 |
-
// otherwise deflate the whole scale), so a long lower CI whisker can
|
| 1018 |
-
// reach past it and run into the method names below. Clip it there; the
|
| 1019 |
-
// exact interval stays in the tooltip and the data table.
|
| 1020 |
-
const clip = el("clipPath", { id: "plot-clip" }, defs);
|
| 1021 |
-
el("rect", { x: 0, y: 0, width: plotW, height: baseY }, clip);
|
| 1022 |
-
|
| 1023 |
-
// -- bars: one concentric group per method
|
| 1024 |
-
const barsG = el("g", { "clip-path": "url(#plot-clip)" }, svg);
|
| 1025 |
-
entries.forEach((entry, i) => {
|
| 1026 |
-
const cx = i * slot + slot / 2;
|
| 1027 |
-
// Widest bar first, narrowest last: the bars are concentric, so painting
|
| 1028 |
-
// them by width guarantees each one stays visible. Ordering by height
|
| 1029 |
-
// instead loses a variant outright whenever a narrower bar is the taller
|
| 1030 |
-
// of the two (TabSTAR's tuned bar sat 1 Elo above tuned + ensembled, and
|
| 1031 |
-
// the wider bar covered it completely).
|
| 1032 |
-
const relOf = p => (VARIANT_STYLE[p.variant] || VARIANT_STYLE["Default"]).rel;
|
| 1033 |
-
const drawn = entry.points
|
| 1034 |
-
.filter(p => state.variants.has(p.variant) && p[m.key] != null)
|
| 1035 |
-
.slice()
|
| 1036 |
-
.sort((a, b) => relOf(b) - relOf(a));
|
| 1037 |
-
for (const p of drawn) {
|
| 1038 |
-
const style = VARIANT_STYLE[p.variant] || VARIANT_STYLE["Default"];
|
| 1039 |
-
const w = barUnit * style.rel;
|
| 1040 |
-
const top = Y(p[m.key]);
|
| 1041 |
-
const rect = {
|
| 1042 |
-
x: cx - w / 2, y: Math.min(top, baseY), width: w, height: Math.max(1, Math.abs(baseY - top)),
|
| 1043 |
-
};
|
| 1044 |
-
// 2px surface ring, not a border: it is what keeps a nested bar legible
|
| 1045 |
-
// against the wider bar it sits inside.
|
| 1046 |
-
el("rect", { ...rect, fill: style.color, stroke: "var(--paper)", "stroke-width": 1.5, rx: 2 }, barsG);
|
| 1047 |
-
if (p.imputed) el("rect", { ...rect, fill: "url(#imp-hatch)", rx: 2 }, barsG);
|
| 1048 |
-
if (m.ci && p[m.ci.lo] != null) {
|
| 1049 |
-
const cap = Math.max(2.5, w * 0.34);
|
| 1050 |
-
const whisk = el("g", {
|
| 1051 |
-
stroke: `color-mix(in srgb, ${style.color} 55%, var(--ink))`, "stroke-width": 1.4, opacity: 0.9,
|
| 1052 |
-
}, barsG);
|
| 1053 |
-
el("line", { x1: cx, y1: Y(p[m.ci.lo]), x2: cx, y2: Y(p[m.ci.hi]) }, whisk);
|
| 1054 |
-
el("line", { x1: cx - cap, y1: Y(p[m.ci.hi]), x2: cx + cap, y2: Y(p[m.ci.hi]) }, whisk);
|
| 1055 |
-
el("line", { x1: cx - cap, y1: Y(p[m.ci.lo]), x2: cx + cap, y2: Y(p[m.ci.lo]) }, whisk);
|
| 1056 |
-
}
|
| 1057 |
-
}
|
| 1058 |
-
});
|
| 1059 |
-
|
| 1060 |
-
// -- x axis: the method name, colored by model family (the legend below
|
| 1061 |
-
// names the colors).
|
| 1062 |
-
const xg = el("g", {}, svg);
|
| 1063 |
-
// Hairlines share one group that is painted before every name, so a name
|
| 1064 |
-
// nudged sideways at the edge (see below) passes over a neighbouring
|
| 1065 |
-
// column's hairline instead of being crossed out by it.
|
| 1066 |
-
const xLines = el("g", {}, xg);
|
| 1067 |
-
const xLabels = el("g", {}, xg);
|
| 1068 |
-
entries.forEach((entry, i) => {
|
| 1069 |
-
const cx = i * slot + slot / 2;
|
| 1070 |
-
const row = labelRows === 1 ? 0 : i % 2;
|
| 1071 |
-
const y = baseY + LABEL_TOP + row * LABEL_ROW;
|
| 1072 |
-
// A hairline drops the staggered row back to its own column.
|
| 1073 |
-
if (row) {
|
| 1074 |
-
el("line", {
|
| 1075 |
-
x1: cx, y1: baseY + 3, x2: cx, y2: y - 10,
|
| 1076 |
-
stroke: "var(--line)", "stroke-width": 1,
|
| 1077 |
-
}, xLines);
|
| 1078 |
-
}
|
| 1079 |
-
const t = el("text", {
|
| 1080 |
-
x: cx, y, "font-size": LABEL_SIZE, "text-anchor": "middle", "font-weight": 650,
|
| 1081 |
-
fill: FAM_INK[entry.family] || "var(--ink)",
|
| 1082 |
-
// A halo in the surface color keeps the glyphs legible where a nudged
|
| 1083 |
-
// name crosses a hairline, rather than the line running through them.
|
| 1084 |
-
"paint-order": "stroke", stroke: "var(--paper)", "stroke-width": 3,
|
| 1085 |
-
}, xLabels);
|
| 1086 |
-
t.textContent = labels[i];
|
| 1087 |
-
fitLabel(t, labels[i], labelWidths[i], slot * labelRows - 8);
|
| 1088 |
-
// The outermost columns sit only half a slot from the edge, so a name
|
| 1089 |
-
// wider than one slot would reach past the SVG viewport and be cut off
|
| 1090 |
-
// there (a name may occupy two slots when the rows are staggered). Nudge
|
| 1091 |
-
// it inwards by just enough to stay whole; every other label keeps its
|
| 1092 |
-
// column centre, and the bar below still marks the column.
|
| 1093 |
-
const half = t.getComputedTextLength() / 2;
|
| 1094 |
-
t.setAttribute("x", Math.max(half + 1, Math.min(cx, plotW - half - 1)));
|
| 1095 |
-
});
|
| 1096 |
-
|
| 1097 |
-
// -- reference pipelines as threshold lines. Their names live in the legend
|
| 1098 |
-
// (matched by dash pattern) rather than on the line, where they would
|
| 1099 |
-
// cover the tallest bars at every scroll position.
|
| 1100 |
-
const refG = el("g", {}, svg);
|
| 1101 |
-
const tagYs = [];
|
| 1102 |
-
shownRefs.forEach((r, i) => {
|
| 1103 |
-
const ry = Y(r[state.metric]);
|
| 1104 |
-
if (ry < TOP || ry > baseY) return;
|
| 1105 |
-
el("line", {
|
| 1106 |
-
x1: 0, y1: ry, x2: plotW, y2: ry, stroke: "var(--fam-reference)", "stroke-width": 1.8,
|
| 1107 |
-
"stroke-dasharray": REF_DASHES[i % REF_DASHES.length], opacity: 0.95,
|
| 1108 |
-
}, refG);
|
| 1109 |
-
// Sticky value tag in the axis pane, so the threshold stays readable at
|
| 1110 |
-
// any scroll position. Two nearby thresholds would print on top of each
|
| 1111 |
-
// other, so nudge each tag clear of the ones already placed; a tag wins
|
| 1112 |
-
// over a tick label it would sit on.
|
| 1113 |
-
let ty = ry;
|
| 1114 |
-
while (tagYs.some(y => Math.abs(y - ty) < 12)) ty += 12;
|
| 1115 |
-
tagYs.push(ty);
|
| 1116 |
-
for (const t of tickLabels) {
|
| 1117 |
-
if (Math.abs(t.y - ty) < 10) t.node.remove();
|
| 1118 |
-
}
|
| 1119 |
-
el("text", {
|
| 1120 |
-
x: AXIS_W - 10, y: ty + 4, "text-anchor": "end", "font-size": 11, "font-weight": 650,
|
| 1121 |
-
fill: "var(--fam-reference)",
|
| 1122 |
-
}, axisSvg).textContent = fmtMetric(m, r[state.metric]);
|
| 1123 |
-
});
|
| 1124 |
-
buildLegend(m, shownRefs);
|
| 1125 |
-
|
| 1126 |
-
// -- hit targets: one full-height column per method (>= 34px wide)
|
| 1127 |
-
const hits = el("g", {}, svg);
|
| 1128 |
-
entries.forEach((entry, i) => {
|
| 1129 |
-
const h = el("rect", {
|
| 1130 |
-
x: i * slot, y: TOP, width: slot, height: PLOT_H + 6, fill: "transparent", cursor: "pointer",
|
| 1131 |
-
}, hits);
|
| 1132 |
-
h.addEventListener("mouseenter", ev => {
|
| 1133 |
-
band.setAttribute("x", i * slot);
|
| 1134 |
-
band.setAttribute("opacity", 0.06);
|
| 1135 |
-
showTip(entry, ev);
|
| 1136 |
-
});
|
| 1137 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1138 |
-
h.addEventListener("mouseleave", () => { band.setAttribute("opacity", 0); tip.hide(); });
|
| 1139 |
-
h.addEventListener("click", () => toggleMethod(entry.method));
|
| 1140 |
-
});
|
| 1141 |
-
|
| 1142 |
-
postHeight();
|
| 1143 |
-
}
|
| 1144 |
-
|
| 1145 |
-
function showTip(entry, ev) {
|
| 1146 |
-
const m = metric();
|
| 1147 |
-
let html = `<div class="t-name">${entry.method}</div><div>${entry.family}</div>`;
|
| 1148 |
-
for (const p of entry.points) {
|
| 1149 |
-
if (!state.variants.has(p.variant) || p[m.key] == null) continue;
|
| 1150 |
-
const ci = m.ci && p[m.ci.lo] != null
|
| 1151 |
-
? ` <span class="t-var">(${fmtNum(p[m.ci.lo], m.decimals)}–${fmtNum(p[m.ci.hi], m.decimals)})</span>`
|
| 1152 |
-
: "";
|
| 1153 |
-
html += `<div><span class="t-var">${p.variant}:</span> <b>${fmtMetric(m, p[m.key])}</b>${ci}</div>`;
|
| 1154 |
-
}
|
| 1155 |
-
if (entry.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(entry.imputed_pct, 0)}% of datasets</div>`;
|
| 1156 |
-
tip.show(html, ev);
|
| 1157 |
-
}
|
| 1158 |
-
|
| 1159 |
-
// ---------- chips ----------
|
| 1160 |
-
const chipsBox = document.getElementById("chips");
|
| 1161 |
-
const chipByMethod = new Map();
|
| 1162 |
-
const famChips = new Map();
|
| 1163 |
-
|
| 1164 |
-
function familyMembers(fam) {
|
| 1165 |
-
const out = [...byMethod.values()].filter(e => e.family === fam).map(e => e.method);
|
| 1166 |
-
for (const r of refs) if (r.family === fam) out.push(r.method);
|
| 1167 |
-
return out;
|
| 1168 |
-
}
|
| 1169 |
-
function isOn(name) { return state.methods.has(name) || state.refs.has(name); }
|
| 1170 |
-
|
| 1171 |
-
function buildChips() {
|
| 1172 |
-
const rankMetric = metricByKey[CONFIG.rankMetric] || METRICS[0];
|
| 1173 |
-
const head = document.createElement("div");
|
| 1174 |
-
head.className = "chips-head";
|
| 1175 |
-
head.textContent = "Methods shown — click to remove, click a family to toggle the whole group";
|
| 1176 |
-
chipsBox.appendChild(head);
|
| 1177 |
-
for (const fam of FAM_ORDER) {
|
| 1178 |
-
const members = familyMembers(fam);
|
| 1179 |
-
if (!members.length) continue;
|
| 1180 |
-
members.sort((a, b) => chipRank(a, rankMetric) - chipRank(b, rankMetric));
|
| 1181 |
-
const row = document.createElement("div");
|
| 1182 |
-
row.className = "chiprow";
|
| 1183 |
-
const famBtn = document.createElement("button");
|
| 1184 |
-
famBtn.className = "famchip";
|
| 1185 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1186 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1187 |
-
famBtn.title = `Toggle all ${members.length} ${fam} methods`;
|
| 1188 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1189 |
-
row.appendChild(famBtn);
|
| 1190 |
-
famChips.set(fam, famBtn);
|
| 1191 |
-
const set = document.createElement("div");
|
| 1192 |
-
set.className = "chipset";
|
| 1193 |
-
for (const name of members) {
|
| 1194 |
-
const entry = byMethod.get(name);
|
| 1195 |
-
const b = document.createElement("button");
|
| 1196 |
-
b.className = "chip";
|
| 1197 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1198 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1199 |
-
b.appendChild(Object.assign(document.createElement("span"), { textContent: name }));
|
| 1200 |
-
if (entry && entry.imputed) {
|
| 1201 |
-
const mark = document.createElement("span");
|
| 1202 |
-
mark.className = "imp-mark";
|
| 1203 |
-
mark.textContent = "‡";
|
| 1204 |
-
b.appendChild(mark);
|
| 1205 |
-
}
|
| 1206 |
-
b.title = name + (entry && entry.imputed ? " — partially imputed" : "");
|
| 1207 |
-
b.addEventListener("click", () => toggleMethod(name));
|
| 1208 |
-
set.appendChild(b);
|
| 1209 |
-
chipByMethod.set(name, b);
|
| 1210 |
-
}
|
| 1211 |
-
row.appendChild(set);
|
| 1212 |
-
chipsBox.appendChild(row);
|
| 1213 |
-
}
|
| 1214 |
-
}
|
| 1215 |
-
function chipRank(name, m) {
|
| 1216 |
-
const entry = byMethod.get(name);
|
| 1217 |
-
if (entry) return rankVal(entry, m);
|
| 1218 |
-
const r = refs.find(x => x.method === name);
|
| 1219 |
-
const v = r ? r[m.key] : null;
|
| 1220 |
-
return v == null ? Infinity : (m.lowerBetter ? v : -v);
|
| 1221 |
-
}
|
| 1222 |
-
function syncChips() {
|
| 1223 |
-
for (const [name, b] of chipByMethod) b.setAttribute("aria-pressed", String(isOn(name)));
|
| 1224 |
-
for (const [fam, b] of famChips) b.setAttribute("aria-pressed", String(familyMembers(fam).every(isOn)));
|
| 1225 |
-
}
|
| 1226 |
-
|
| 1227 |
-
function toggleMethod(name) {
|
| 1228 |
-
const set = byMethod.has(name) ? state.methods : state.refs;
|
| 1229 |
-
if (set.has(name)) set.delete(name); else set.add(name);
|
| 1230 |
-
syncChips();
|
| 1231 |
-
render();
|
| 1232 |
-
}
|
| 1233 |
-
function toggleFamily(fam) {
|
| 1234 |
-
const members = familyMembers(fam);
|
| 1235 |
-
const allOn = members.every(isOn);
|
| 1236 |
-
for (const name of members) {
|
| 1237 |
-
const set = byMethod.has(name) ? state.methods : state.refs;
|
| 1238 |
-
if (allOn) set.delete(name); else set.add(name);
|
| 1239 |
-
}
|
| 1240 |
-
syncChips();
|
| 1241 |
-
render();
|
| 1242 |
-
}
|
| 1243 |
-
function setMethods(names) {
|
| 1244 |
-
state.methods = new Set(names);
|
| 1245 |
-
syncChips();
|
| 1246 |
-
render();
|
| 1247 |
-
}
|
| 1248 |
-
|
| 1249 |
-
document.getElementById("btn-all").addEventListener("click", () => {
|
| 1250 |
-
state.refs = new Set(refs.map(r => r.method));
|
| 1251 |
-
setMethods(byMethod.keys());
|
| 1252 |
-
});
|
| 1253 |
-
document.getElementById("btn-none").addEventListener("click", () => {
|
| 1254 |
-
state.refs = new Set();
|
| 1255 |
-
setMethods([]);
|
| 1256 |
-
});
|
| 1257 |
-
document.getElementById("btn-top").addEventListener("click", () => {
|
| 1258 |
-
const m = metric();
|
| 1259 |
-
// Rank explicitly rather than reusing the display sort: which 15 methods are
|
| 1260 |
-
// kept must not depend on which end of the axis the best ones are drawn at
|
| 1261 |
-
// (sorting "best on the right" would otherwise select the 15 worst).
|
| 1262 |
-
const top = [...byMethod.values()]
|
| 1263 |
-
.sort((a, b) => rankVal(a, m) - rankVal(b, m))
|
| 1264 |
-
.slice(0, 15)
|
| 1265 |
-
.map(e => e.method);
|
| 1266 |
-
state.refs = new Set(refs.map(r => r.method));
|
| 1267 |
-
setMethods(top);
|
| 1268 |
-
});
|
| 1269 |
-
|
| 1270 |
-
// ---------- selectors ----------
|
| 1271 |
-
yminRange.addEventListener("input", ev => {
|
| 1272 |
-
state.yMin = Number(ev.target.value);
|
| 1273 |
-
render();
|
| 1274 |
-
});
|
| 1275 |
-
|
| 1276 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1277 |
-
for (const m of METRICS) {
|
| 1278 |
-
metricSelect.appendChild(Object.assign(document.createElement("option"), { value: m.key, textContent: m.label }));
|
| 1279 |
-
}
|
| 1280 |
-
metricSelect.addEventListener("change", ev => {
|
| 1281 |
-
state.metric = ev.target.value;
|
| 1282 |
-
state.yMin = null; // the previous floor means nothing on a new scale
|
| 1283 |
-
buildTable();
|
| 1284 |
-
render();
|
| 1285 |
-
});
|
| 1286 |
-
|
| 1287 |
-
const sortSelect = document.getElementById("sort-select");
|
| 1288 |
-
for (const [value, label] of [
|
| 1289 |
-
["best", "Best on the left"], ["worst", "Best on the right"],
|
| 1290 |
-
["family", "Model family"], ["name", "A–Z"],
|
| 1291 |
-
]) {
|
| 1292 |
-
sortSelect.appendChild(Object.assign(document.createElement("option"), { value, textContent: label }));
|
| 1293 |
-
}
|
| 1294 |
-
sortSelect.value = state.sort;
|
| 1295 |
-
sortSelect.addEventListener("change", ev => { state.sort = ev.target.value; render(); });
|
| 1296 |
-
|
| 1297 |
-
// Variant toggles: buttons rather than chips, since they filter the series
|
| 1298 |
-
// rather than the rows. "Default" gets no button at all — every method has a
|
| 1299 |
-
// default result, so it is the baseline of the chart rather than an option
|
| 1300 |
-
// (switching it off would leave the default-only methods with no bar). Only
|
| 1301 |
-
// the extras layered on top, tuning and ensembling, are toggleable; the legend
|
| 1302 |
-
// still carries Default's color.
|
| 1303 |
-
const ALWAYS_SHOWN = "Default";
|
| 1304 |
-
const variantBtns = document.getElementById("variant-btns");
|
| 1305 |
-
const variantBtnByKey = new Map();
|
| 1306 |
-
for (const v of VARIANT_ORDER) {
|
| 1307 |
-
if (v === ALWAYS_SHOWN || !POINTS.some(p => p.variant === v)) continue;
|
| 1308 |
-
const b = document.createElement("button");
|
| 1309 |
-
b.className = "btn";
|
| 1310 |
-
b.textContent = v === "Tuned + Ens." ? "Tuned + Ensembled" : v;
|
| 1311 |
-
b.style.setProperty("--fam", VARIANT_STYLE[v].color);
|
| 1312 |
-
b.title = `Show or hide the ${b.textContent.toLowerCase()} bars`;
|
| 1313 |
-
b.addEventListener("click", () => {
|
| 1314 |
-
if (state.variants.has(v)) state.variants.delete(v);
|
| 1315 |
-
else state.variants.add(v);
|
| 1316 |
-
syncVariantBtns();
|
| 1317 |
-
render();
|
| 1318 |
-
});
|
| 1319 |
-
variantBtns.appendChild(b);
|
| 1320 |
-
variantBtnByKey.set(v, b);
|
| 1321 |
-
}
|
| 1322 |
-
function syncVariantBtns() {
|
| 1323 |
-
for (const [v, b] of variantBtnByKey) {
|
| 1324 |
-
const on = state.variants.has(v);
|
| 1325 |
-
b.setAttribute("aria-pressed", String(on));
|
| 1326 |
-
b.style.opacity = on ? "1" : "0.45";
|
| 1327 |
-
b.style.borderColor = on ? VARIANT_STYLE[v].color : "var(--line)";
|
| 1328 |
-
}
|
| 1329 |
-
}
|
| 1330 |
-
|
| 1331 |
-
// ---------- legend ----------
|
| 1332 |
-
// Rebuilt on every render: it names the reference lines (each by its dash
|
| 1333 |
-
// pattern and current value), which change with the metric and the selection.
|
| 1334 |
-
function buildLegend(m, shownRefs) {
|
| 1335 |
-
const parts = [];
|
| 1336 |
-
for (const v of VARIANT_ORDER) {
|
| 1337 |
-
if (!POINTS.some(p => p.variant === v)) continue;
|
| 1338 |
-
const label = v === "Tuned + Ens." ? "Tuned + Ensembled" : v;
|
| 1339 |
-
const off = state.variants.has(v) ? "" : ' style="opacity:0.4"';
|
| 1340 |
-
parts.push(
|
| 1341 |
-
`<span class="item"${off}><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1342 |
-
`<rect x="1" y="1" width="10" height="10" rx="2" fill="${VARIANT_STYLE[v].color}"/></svg> ${label}</span>`);
|
| 1343 |
-
}
|
| 1344 |
-
if (m.ci) {
|
| 1345 |
-
parts.push('<span class="item"><svg width="12" height="14" viewBox="0 0 12 14">' +
|
| 1346 |
-
'<path d="M6,2 V12 M2,2 H10 M2,12 H10" stroke="var(--muted)" stroke-width="1.4" fill="none"/></svg> 95% CI</span>');
|
| 1347 |
-
}
|
| 1348 |
-
shownRefs.forEach((r, i) => {
|
| 1349 |
-
parts.push(`<span class="item"><svg width="26" height="8" viewBox="0 0 26 8">` +
|
| 1350 |
-
`<line x1="0" y1="4" x2="26" y2="4" stroke="var(--fam-reference)" stroke-width="1.8" ` +
|
| 1351 |
-
`stroke-dasharray="${REF_DASHES[i % REF_DASHES.length]}"/></svg> ${r.method} · ${fmtMetric(m, r[state.metric])}</span>`);
|
| 1352 |
-
});
|
| 1353 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1354 |
-
parts.push('<span class="item"><svg width="14" height="14" viewBox="0 0 14 14">' +
|
| 1355 |
-
'<rect x="1" y="1" width="12" height="12" rx="2" fill="var(--pt-muted)"/>' +
|
| 1356 |
-
'<path d="M1,1 L7,7 M7,1 L1,7 M7,7 L13,13 M13,7 L7,13 M1,7 L7,13 M7,7 L13,1" ' +
|
| 1357 |
-
'stroke="var(--paper)" stroke-width="1.5" fill="none"/>' +
|
| 1358 |
-
"</svg> ‡ partially imputed</span>");
|
| 1359 |
-
}
|
| 1360 |
-
// Model family, named rather than merely pointed at: without the colors
|
| 1361 |
-
// spelled out, the swatch under each column decodes to nothing.
|
| 1362 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => !p.reference && p.family === f));
|
| 1363 |
-
if (families.length > 1) {
|
| 1364 |
-
parts.push('<span class="legendbreak"></span><span class="item">Family:</span>');
|
| 1365 |
-
for (const fam of families) {
|
| 1366 |
-
parts.push(`<span class="item"><svg width="16" height="9" viewBox="0 0 16 9">` +
|
| 1367 |
-
`<rect x="0" y="1" width="16" height="7" rx="2" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1368 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`);
|
| 1369 |
-
}
|
| 1370 |
-
}
|
| 1371 |
-
document.getElementById("legendstrip").innerHTML = parts.join("");
|
| 1372 |
-
}
|
| 1373 |
-
|
| 1374 |
-
// ---------- data table (the WCAG-clean twin of the chart) ----------
|
| 1375 |
-
function buildTable() {
|
| 1376 |
-
const m = metric();
|
| 1377 |
-
const rows = [...POINTS].filter(p => p[m.key] != null).sort((a, b) =>
|
| 1378 |
-
m.lowerBetter ? a[m.key] - b[m.key] : b[m.key] - a[m.key]);
|
| 1379 |
-
let html = "<table><thead><tr><th>Method</th><th>Variant</th><th>Family</th>";
|
| 1380 |
-
for (const x of METRICS) html += `<th>${x.label}</th>`;
|
| 1381 |
-
html += "<th>Imputed</th></tr></thead><tbody>";
|
| 1382 |
-
for (const p of rows) {
|
| 1383 |
-
html += `<tr><td>${p.method}</td><td>${p.variant || "—"}</td><td>${p.family}</td>`;
|
| 1384 |
-
for (const x of METRICS) html += `<td>${fmtMetric(x, p[x.key])}</td>`;
|
| 1385 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1386 |
-
}
|
| 1387 |
-
document.getElementById("tblwrap").innerHTML = html + "</tbody></table>";
|
| 1388 |
-
}
|
| 1389 |
-
|
| 1390 |
-
// ---------- paper view ----------
|
| 1391 |
-
setUpPaperView(render);
|
| 1392 |
-
// The y-axis lives in its own pane, so it is offset back into place.
|
| 1393 |
-
setUpExport(() => [{ svg: axisSvg, dx: 0 }, { svg: svg, dx: AXIS_W }], () => slugify(document.title));
|
| 1394 |
-
|
| 1395 |
-
// ---------- boot ----------
|
| 1396 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1397 |
-
let resizeTimer = null;
|
| 1398 |
-
window.addEventListener("resize", () => {
|
| 1399 |
-
clearTimeout(resizeTimer);
|
| 1400 |
-
resizeTimer = setTimeout(render, 120);
|
| 1401 |
-
});
|
| 1402 |
-
|
| 1403 |
-
buildChips();
|
| 1404 |
-
buildTable();
|
| 1405 |
-
syncChips();
|
| 1406 |
-
syncVariantBtns();
|
| 1407 |
-
render(); // also builds the legend (it depends on the metric + selection)
|
| 1408 |
-
})();
|
| 1409 |
-
</script>
|
| 1410 |
-
</body>
|
| 1411 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/leaderboard_table.html
DELETED
|
@@ -1,1162 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena leaderboard table — no imputation | All Tasks | Small</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* --- The table ------------------------------------------------------------
|
| 269 |
-
A scroll box with a sticky header, so the column names stay put through 80
|
| 270 |
-
rows. Numbers are tabular so digits line up down a column. */
|
| 271 |
-
.lbt-scroll {
|
| 272 |
-
overflow: auto; max-height: 720px; margin-top: 4px;
|
| 273 |
-
border: 1px solid var(--line); border-radius: 10px;
|
| 274 |
-
scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent;
|
| 275 |
-
}
|
| 276 |
-
.lbt-scroll::-webkit-scrollbar { width: 11px; height: 11px; }
|
| 277 |
-
.lbt-scroll::-webkit-scrollbar-thumb {
|
| 278 |
-
background: var(--pt-muted); border-radius: 8px;
|
| 279 |
-
border: 3px solid transparent; background-clip: content-box;
|
| 280 |
-
}
|
| 281 |
-
table.lbt { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
|
| 282 |
-
table.lbt th, table.lbt td { padding: 5px 9px; text-align: center; border: 1px solid var(--line); }
|
| 283 |
-
table.lbt thead th {
|
| 284 |
-
position: sticky; top: 0; z-index: 3; background: var(--card); font-size: 12px;
|
| 285 |
-
font-weight: 650; white-space: nowrap; cursor: pointer; user-select: none;
|
| 286 |
-
box-shadow: inset 0 -1px 0 var(--line);
|
| 287 |
-
}
|
| 288 |
-
/* The header is both the sort control and the definition, so it gets the
|
| 289 |
-
pointer of the former and the dotted underline of the latter. */
|
| 290 |
-
table.lbt thead th .lbl { text-decoration: underline; text-decoration-style: dotted;
|
| 291 |
-
text-decoration-color: var(--muted); text-underline-offset: 3px; }
|
| 292 |
-
table.lbt thead th:hover { color: var(--accent); }
|
| 293 |
-
table.lbt thead th::after { content: "\2195"; font-size: 0.72em; opacity: 0.3; margin-left: 5px; }
|
| 294 |
-
table.lbt thead th[aria-sort="ascending"]::after { content: "\25B2"; opacity: 0.85; }
|
| 295 |
-
table.lbt thead th[aria-sort="descending"]::after { content: "\25BC"; opacity: 0.85; }
|
| 296 |
-
table.lbt td.name { text-align: left; white-space: nowrap; }
|
| 297 |
-
table.lbt td.pos { color: var(--muted); font-variant-numeric: tabular-nums; }
|
| 298 |
-
table.lbt td.type { white-space: nowrap; width: 1%; }
|
| 299 |
-
table.lbt td.num { font-weight: 600; }
|
| 300 |
-
table.lbt td.na { color: var(--pt-muted); }
|
| 301 |
-
table.lbt tbody tr:hover td { filter: brightness(1.12); }
|
| 302 |
-
.ci { opacity: 0.5; font-weight: 400; font-size: 0.82em; }
|
| 303 |
-
.pill { padding: 1px 7px; border-radius: 999px; font-size: 0.95em; white-space: nowrap; }
|
| 304 |
-
.verified { font-size: 0.85em; }
|
| 305 |
-
.link-icon { font-size: 0.78em; opacity: 0.65; margin-left: 2px; }
|
| 306 |
-
/* Grey rather than a dimmed inherit: dimming leaves the tag tinted with the
|
| 307 |
-
family colour, which the model name already carries, and made this table
|
| 308 |
-
disagree with the cross-subset table on the app page. */
|
| 309 |
-
.variant-tag { color: var(--muted); font-weight: 400; font-size: 0.9em; }
|
| 310 |
-
td.name .imp-mark { color: var(--muted); font-weight: 700; margin-left: 3px; }
|
| 311 |
-
td.name a { text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }
|
| 312 |
-
td.name a:hover { text-decoration-style: solid; }
|
| 313 |
-
|
| 314 |
-
.lbt-search {
|
| 315 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 316 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 317 |
-
padding: 6px 9px; width: 12em;
|
| 318 |
-
}
|
| 319 |
-
.lbt-cap { font-size: 12.5px; color: var(--muted); margin: 7px 0 0; }
|
| 320 |
-
.lbt-empty { padding: 34px 0; text-align: center; color: var(--muted); font-size: 13px; }
|
| 321 |
-
.chips-head { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); font-weight: 600; }
|
| 322 |
-
/* The model selector sits above the table it filters. Families pack side by
|
| 323 |
-
side rather than stacking: one row each would leave the small ones (Baseline,
|
| 324 |
-
Other) wasting a line. */
|
| 325 |
-
.chips { margin: 2px 0 10px; flex-direction: row; flex-wrap: wrap; gap: 12px 28px; align-items: flex-start; }
|
| 326 |
-
.chiprow { flex: 0 1 auto; min-width: 0; }
|
| 327 |
-
|
| 328 |
-
/* The data export, in the same green the website's figure-export controls use,
|
| 329 |
-
so "this downloads something" reads the same across the site. */
|
| 330 |
-
.btn.export {
|
| 331 |
-
color: #063; background: #7ee0b8; border-color: #7ee0b8; font-weight: 700;
|
| 332 |
-
}
|
| 333 |
-
.btn.export:hover { background: #a6efcd; border-color: #a6efcd; }
|
| 334 |
-
/* Paper view keeps the table: here the table *is* the figure. */
|
| 335 |
-
body.paper .lbt-scroll { max-height: none; }
|
| 336 |
-
</style>
|
| 337 |
-
</head>
|
| 338 |
-
<body>
|
| 339 |
-
<div class="viewbar">
|
| 340 |
-
<button class="btn" id="btn-paper" title="White background, table only — for slides and papers">Paper view</button>
|
| 341 |
-
</div>
|
| 342 |
-
<p class="explorer-title" id="title"></p>
|
| 343 |
-
<div class="controls">
|
| 344 |
-
<span class="grouplabel">Variants</span>
|
| 345 |
-
<div class="btnrow" id="variant-btns"></div>
|
| 346 |
-
<button class="btn" id="btn-imputed" title="Models whose score is partly imputed, marked ‡"></button>
|
| 347 |
-
<input class="lbt-search" id="search" type="search" placeholder="Search model or family" aria-label="Search">
|
| 348 |
-
<span class="grouplabel">Columns</span>
|
| 349 |
-
<div class="btnrow" id="col-btns"></div>
|
| 350 |
-
<button class="btn export" id="btn-csv" title="Download the rows and columns shown, in the current sort order">Download CSV</button>
|
| 351 |
-
</div>
|
| 352 |
-
<!-- The shared paper-view helper reveals this bar; a table has no figure to
|
| 353 |
-
export as SVG/PNG/PDF, and its CSV button belongs beside the filters that
|
| 354 |
-
shape the export, so it stays empty here. -->
|
| 355 |
-
<div class="exportbar" id="exportbar" hidden></div>
|
| 356 |
-
<!-- The model selector belongs above the table it filters. It doubles as the
|
| 357 |
-
family key, which is why there is no separate legend strip. -->
|
| 358 |
-
<div class="chips" id="chips"></div>
|
| 359 |
-
<div class="lbt-scroll" id="tblwrap"></div>
|
| 360 |
-
<p class="lbt-cap" id="caption"></p>
|
| 361 |
-
|
| 362 |
-
<script>
|
| 363 |
-
(function () {
|
| 364 |
-
"use strict";
|
| 365 |
-
const CONFIG = {"title": null, "columns": [{"key": "position", "label": "#", "always": true, "hint": "Position in this subset's published ranking."}, {"key": "family", "label": "Type", "always": true, "hint": "Model family \u2014 see the key above the table."}, {"key": "model", "label": "Model", "always": true, "hint": "The model, its tuning variant in brackets, \u2714\ufe0f when the implementation was verified, and \u2021 when some results are imputed."}, {"key": "elo", "label": "Elo", "decimals": 0, "heatmap": true, "hint": "Pairwise win-rate rating; a 400-point gap is about a 91% win rate. Higher is better."}, {"key": "score", "label": "Score", "decimals": 3, "heatmap": true, "hint": "Error rescaled per dataset to 1 (best) \u2026 0 (median), then averaged. Higher is better."}, {"key": "rank", "label": "Rank", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "Mean rank across datasets. Lower is better."}, {"key": "hrank", "label": "Harmonic rank", "short": "H. rank", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "Harmonic mean of per-dataset ranks; rewards being excellent somewhere. Lower is better."}, {"key": "imp", "label": "Improvability (%)", "short": "Improv.", "decimals": 2, "lowerBetter": true, "heatmap": true, "hint": "How much lower the best model's error is than this one's, per dataset. Lower is better."}, {"key": "train_time", "label": "Train time (s/1K)", "short": "Train s", "decimals": 2, "lowerBetter": true, "heatmap": true, "logScale": true, "hint": "Median seconds to fit per 1000 rows. Lower is better; shaded on a log scale."}, {"key": "predict_time", "label": "Predict time (s/1K)", "short": "Predict s", "decimals": 3, "lowerBetter": true, "heatmap": true, "logScale": true, "hint": "Median seconds to predict per 1000 rows. Lower is better; shaded on a log scale."}, {"key": "imputed_pct", "label": "Imputed (%)", "short": "Imputed", "decimals": 1, "lowerBetter": true, "heatmap": true, "hint": "Share of datasets whose score was imputed because the model could not run on them."}, {"key": "hardware", "label": "Hardware", "text": true, "hint": "The hardware the reported runtimes were measured on."}], "rankKey": "elo", "variants": ["Default", "Tuned", "Tuned + Ens."]};
|
| 366 |
-
const POINTS = [{"position":0,"method":"TabFM","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/google-research\/tabfm","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1744.0,"score":0.897,"rank":6.9,"hrank":1.74,"imp":4.654,"train_time":39.57,"predict_time":5.358,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+142\/-93","imputed":false},{"position":1,"method":"AutoGluon 1.5 (extreme, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83d\udcca","verified":true,"elo":1638.0,"score":0.642,"rank":10.67,"hrank":4.73,"imp":9.279,"train_time":346.58,"predict_time":6.557,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+74\/-52","imputed":false},{"position":2,"method":"TabPFN-3","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2605.13986","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1636.0,"score":0.675,"rank":10.77,"hrank":4.53,"imp":10.766,"train_time":9.17,"predict_time":0.416,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+80\/-56","imputed":false},{"position":3,"method":"TabPFN-2.6","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1599.0,"score":0.616,"rank":12.44,"hrank":6.63,"imp":11.961,"train_time":7.03,"predict_time":0.548,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+69\/-47","imputed":false},{"position":4,"method":"RealTabPFN-2.5","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1595.0,"score":0.593,"rank":12.63,"hrank":5.6,"imp":11.198,"train_time":2289.39,"predict_time":8.048,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+86\/-62","imputed":false},{"position":5,"method":"TabICLv2","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2602.11139","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1572.0,"score":0.633,"rank":13.78,"hrank":5.25,"imp":11.56,"train_time":3.93,"predict_time":0.152,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+106\/-78","imputed":false},{"position":6,"method":"RealTabPFN-2.5","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1555.0,"score":0.547,"rank":14.67,"hrank":6.51,"imp":11.907,"train_time":2289.39,"predict_time":1.143,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+69\/-56","imputed":false},{"position":7,"method":"RealTabPFN-2.5","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.08667","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1542.0,"score":0.536,"rank":15.41,"hrank":8.41,"imp":12.32,"train_time":6.76,"predict_time":0.636,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+80\/-49","imputed":false},{"position":8,"method":"RealMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1480.0,"score":0.402,"rank":19.13,"hrank":11.38,"imp":14.533,"train_time":3771.85,"predict_time":21.902,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+62\/-44","imputed":false},{"position":9,"method":"TabDPT-Turbo","variant":"Default","family":"Foundation Model","url":"https:\/\/openreview.net\/pdf?id=Y00pwFyrHR","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1448.0,"score":0.391,"rank":21.19,"hrank":9.11,"imp":15.33,"train_time":4.69,"predict_time":0.192,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+74\/-54","imputed":false},{"position":10,"method":"TabDPT","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1448.0,"score":0.398,"rank":21.22,"hrank":9.27,"imp":15.246,"train_time":5119.78,"predict_time":218.453,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+74\/-60","imputed":false},{"position":11,"method":"AutoGluon 1.4 (best, 4h)","variant":"","family":"Reference Pipeline","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83d\udcca","verified":true,"elo":1444.0,"score":0.326,"rank":21.52,"hrank":13.45,"imp":15.598,"train_time":3716.57,"predict_time":2.547,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+51\/-46","imputed":false},{"position":12,"method":"TabM","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1429.0,"score":0.325,"rank":22.52,"hrank":12.22,"imp":15.675,"train_time":2585.58,"predict_time":3.838,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+52\/-48","imputed":false},{"position":13,"method":"TabDPT","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1415.0,"score":0.356,"rank":23.49,"hrank":10.85,"imp":15.884,"train_time":5119.78,"predict_time":28.351,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+70\/-58","imputed":false},{"position":14,"method":"LimiX","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2509.03505","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1405.0,"score":0.353,"rank":24.21,"hrank":9.41,"imp":15.155,"train_time":35.51,"predict_time":6.828,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+74\/-72","imputed":false},{"position":15,"method":"RealMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1400.0,"score":0.293,"rank":24.6,"hrank":13.5,"imp":15.91,"train_time":3771.85,"predict_time":1.778,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+51\/-43","imputed":false},{"position":16,"method":"LightGBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1390.0,"score":0.235,"rank":25.34,"hrank":19.43,"imp":16.937,"train_time":892.49,"predict_time":2.57,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+34\/-34","imputed":false},{"position":17,"method":"TabM","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1373.0,"score":0.258,"rank":26.55,"hrank":14.04,"imp":16.561,"train_time":2585.58,"predict_time":0.436,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+53\/-48","imputed":false},{"position":18,"method":"CatBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1368.0,"score":0.211,"rank":26.99,"hrank":19.52,"imp":17.041,"train_time":1739.17,"predict_time":0.396,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+45\/-39","imputed":false},{"position":19,"method":"TabSwift","variant":"Default","family":"Foundation Model","url":"https:\/\/github.com\/LAMDA-Tabular\/TabSwift","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1363.0,"score":0.29,"rank":27.32,"hrank":15.91,"imp":17.224,"train_time":2.76,"predict_time":0.058,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+57\/-49","imputed":false},{"position":20,"method":"iLTM","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1361.0,"score":0.199,"rank":27.46,"hrank":18.84,"imp":17.421,"train_time":22811.74,"predict_time":841.446,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+44\/-39","imputed":false},{"position":21,"method":"CatBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1354.0,"score":0.192,"rank":28.01,"hrank":20.68,"imp":17.279,"train_time":1739.17,"predict_time":0.051,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+39\/-36","imputed":false},{"position":22,"method":"LightGBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1353.0,"score":0.185,"rank":28.07,"hrank":21.83,"imp":17.389,"train_time":892.49,"predict_time":0.346,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+32\/-31","imputed":false},{"position":23,"method":"TabDPT","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2410.18164","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1332.0,"score":0.275,"rank":29.74,"hrank":13.6,"imp":18.023,"train_time":50.33,"predict_time":43.707,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+74\/-67","imputed":false},{"position":24,"method":"xRFM","variant":"Tuned + Ens.","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1330.0,"score":0.203,"rank":29.84,"hrank":18.17,"imp":17.868,"train_time":1126.97,"predict_time":2.94,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+48\/-42","imputed":false},{"position":25,"method":"XGBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1325.0,"score":0.158,"rank":30.28,"hrank":23.33,"imp":17.924,"train_time":884.48,"predict_time":2.367,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+33\/-37","imputed":false},{"position":26,"method":"ModernNCA","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1323.0,"score":0.178,"rank":30.38,"hrank":15.63,"imp":18.056,"train_time":6523.55,"predict_time":0.505,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+40\/-42","imputed":false},{"position":27,"method":"ModernNCA","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1323.0,"score":0.227,"rank":30.39,"hrank":13.02,"imp":18.319,"train_time":6523.55,"predict_time":8.39,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+61\/-56","imputed":false},{"position":28,"method":"CatBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1706.09516","family_symbol":"\ud83c\udf33","verified":true,"elo":1320.0,"score":0.159,"rank":30.6,"hrank":22.44,"imp":18.203,"train_time":8.46,"predict_time":0.046,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+35\/-35","imputed":false},{"position":29,"method":"SAP-RPT-OSS","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2506.10707","family_symbol":"\ud83e\udde0\u26a1","verified":false,"elo":1319.0,"score":0.263,"rank":30.69,"hrank":11.14,"imp":18.839,"train_time":16.23,"predict_time":1.277,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+71\/-57","imputed":false},{"position":30,"method":"XGBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1306.0,"score":0.13,"rank":31.71,"hrank":23.26,"imp":18.133,"train_time":884.48,"predict_time":0.393,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+32\/-40","imputed":false},{"position":31,"method":"TabM","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2410.24210","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1296.0,"score":0.188,"rank":32.54,"hrank":19.64,"imp":18.258,"train_time":9.94,"predict_time":0.445,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+53\/-45","imputed":false},{"position":32,"method":"xRFM","variant":"Tuned","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1282.0,"score":0.157,"rank":33.6,"hrank":20.71,"imp":18.894,"train_time":1126.97,"predict_time":0.163,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+42\/-42","imputed":false},{"position":33,"method":"ChimeraBoost","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1278.0,"score":0.133,"rank":33.92,"hrank":23.84,"imp":19.516,"train_time":1218.87,"predict_time":0.455,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+51\/-46","imputed":false},{"position":34,"method":"TorchMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1260.0,"score":0.125,"rank":35.33,"hrank":24.98,"imp":19.124,"train_time":3865.95,"predict_time":2.157,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+40\/-49","imputed":false},{"position":35,"method":"ChimeraBoost","variant":"Tuned","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1260.0,"score":0.11,"rank":35.37,"hrank":25.32,"imp":19.803,"train_time":1218.87,"predict_time":0.036,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+52\/-50","imputed":false},{"position":36,"method":"EBM","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1260.0,"score":0.109,"rank":35.38,"hrank":25.23,"imp":19.954,"train_time":2499.4,"predict_time":0.153,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+42\/-45","imputed":false},{"position":37,"method":"iLTM","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1258.0,"score":0.092,"rank":35.55,"hrank":26.17,"imp":19.245,"train_time":22811.74,"predict_time":161.221,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+37\/-35","imputed":false},{"position":38,"method":"ModernNCA","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.03257","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1237.0,"score":0.097,"rank":37.17,"hrank":21.05,"imp":21.221,"train_time":16.28,"predict_time":0.321,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+47\/-51","imputed":false},{"position":39,"method":"EBM","variant":"Tuned","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1231.0,"score":0.079,"rank":37.67,"hrank":26.59,"imp":20.511,"train_time":2499.4,"predict_time":0.017,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+48\/-44","imputed":false},{"position":40,"method":"RealMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2407.04491","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1221.0,"score":0.079,"rank":38.44,"hrank":26.97,"imp":20.018,"train_time":15.69,"predict_time":4.689,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+39\/-43","imputed":false},{"position":41,"method":"ChimeraBoost","variant":"Default","family":"Tree-based","url":"https:\/\/github.com\/bbstats\/chimeraboost","family_symbol":"\ud83c\udf33","verified":true,"elo":1216.0,"score":0.087,"rank":38.82,"hrank":25.36,"imp":20.941,"train_time":5.49,"predict_time":0.041,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+52\/-58","imputed":false},{"position":42,"method":"FastaiMLP","variant":"Tuned + Ens.","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1214.0,"score":0.124,"rank":38.99,"hrank":22.53,"imp":20.712,"train_time":1679.4,"predict_time":8.069,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+58\/-60","imputed":false},{"position":43,"method":"ExtraTrees","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1211.0,"score":0.109,"rank":39.24,"hrank":24.93,"imp":21.641,"train_time":822.58,"predict_time":1.501,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+69\/-63","imputed":false},{"position":44,"method":"EBM","variant":"Default","family":"Tree-based","url":"https:\/\/www.cs.cornell.edu\/~yinlou\/papers\/lou-kdd13.pdf","family_symbol":"\ud83c\udf33","verified":true,"elo":1203.0,"score":0.074,"rank":39.86,"hrank":25.92,"imp":21.249,"train_time":7.39,"predict_time":0.017,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+48\/-53","imputed":false},{"position":45,"method":"TorchMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1196.0,"score":0.078,"rank":40.43,"hrank":29.54,"imp":20.862,"train_time":3865.95,"predict_time":0.147,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+43\/-49","imputed":false},{"position":46,"method":"ExtraTrees","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1187.0,"score":0.101,"rank":41.1,"hrank":23.0,"imp":22.339,"train_time":822.58,"predict_time":0.214,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+65\/-66","imputed":false},{"position":47,"method":"LightGBM","variant":"Default","family":"Tree-based","url":"https:\/\/papers.nips.cc\/paper_files\/paper\/2017\/hash\/6449f44a102fde848669bdd9eb6b76fa-Abstract.html","family_symbol":"\ud83c\udf33","verified":true,"elo":1166.0,"score":0.043,"rank":42.71,"hrank":35.31,"imp":21.229,"train_time":3.61,"predict_time":0.17,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+43\/-44","imputed":false},{"position":48,"method":"FastaiMLP","variant":"Tuned","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1165.0,"score":0.061,"rank":42.8,"hrank":27.62,"imp":21.847,"train_time":1679.4,"predict_time":0.826,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+51\/-52","imputed":false},{"position":49,"method":"XGBoost","variant":"Default","family":"Tree-based","url":"https:\/\/arxiv.org\/abs\/1603.02754","family_symbol":"\ud83c\udf33","verified":true,"elo":1163.0,"score":0.018,"rank":42.91,"hrank":37.21,"imp":21.244,"train_time":3.29,"predict_time":0.253,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+27\/-37","imputed":false},{"position":50,"method":"RandomForest","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1150.0,"score":0.073,"rank":43.96,"hrank":26.88,"imp":23.216,"train_time":590.04,"predict_time":1.46,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+59\/-70","imputed":false},{"position":51,"method":"TabSTAR","variant":"Tuned","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1132.0,"score":0.178,"rank":45.27,"hrank":12.31,"imp":25.491,"train_time":40848.87,"predict_time":5.606,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+77\/-83","imputed":false},{"position":52,"method":"TabSTAR","variant":"Tuned + Ens.","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1130.0,"score":0.174,"rank":45.38,"hrank":11.81,"imp":25.525,"train_time":40848.87,"predict_time":25.936,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+78\/-84","imputed":false},{"position":53,"method":"RandomForest","variant":"Tuned","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1113.0,"score":0.046,"rank":46.61,"hrank":25.91,"imp":23.948,"train_time":590.04,"predict_time":0.15,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+52\/-68","imputed":false},{"position":54,"method":"PerpetualBooster","variant":"Tuned + Ens.","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":1084.0,"score":0.026,"rank":48.72,"hrank":37.31,"imp":28.451,"train_time":342.04,"predict_time":0.895,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+46\/-59","imputed":false},{"position":55,"method":"iLTM","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2511.15941","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1066.0,"score":0.039,"rank":49.88,"hrank":31.58,"imp":24.914,"train_time":524.48,"predict_time":161.813,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+62\/-74","imputed":false},{"position":56,"method":"TorchMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1058.0,"score":0.015,"rank":50.45,"hrank":36.89,"imp":24.761,"train_time":13.69,"predict_time":0.155,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+46\/-50","imputed":false},{"position":57,"method":"PerpetualBooster","variant":"Tuned","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":1048.0,"score":0.014,"rank":51.08,"hrank":37.33,"imp":29.908,"train_time":342.04,"predict_time":0.313,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+50\/-57","imputed":false},{"position":58,"method":"xRFM","variant":"Default","family":"Other","url":"https:\/\/arxiv.org\/abs\/2508.10053","family_symbol":"\u2753","verified":true,"elo":1043.0,"score":0.034,"rank":51.4,"hrank":42.96,"imp":26.639,"train_time":5.45,"predict_time":1.098,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+61\/-86","imputed":false},{"position":59,"method":"TabSTAR","variant":"Default","family":"Foundation Model","url":"https:\/\/arxiv.org\/abs\/2505.18125","family_symbol":"\ud83e\udde0\u26a1","verified":true,"elo":1033.0,"score":0.109,"rank":52.04,"hrank":19.43,"imp":30.36,"train_time":471.66,"predict_time":7.214,"imputed_pct":0.0,"hardware":"GPU","elo_ci":"+79\/-124","imputed":false},{"position":60,"method":"ExtraTrees","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1007\/s10994-006-6226-1","family_symbol":"\ud83c\udf33","verified":true,"elo":1020.0,"score":0.017,"rank":52.89,"hrank":44.87,"imp":27.588,"train_time":4.19,"predict_time":0.566,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+60\/-69","imputed":false},{"position":61,"method":"RandomForest","variant":"Default","family":"Tree-based","url":"https:\/\/link.springer.com\/article\/10.1023\/A:1010933404324","family_symbol":"\ud83c\udf33","verified":true,"elo":1000.0,"score":0.004,"rank":54.07,"hrank":48.1,"imp":28.377,"train_time":0.51,"predict_time":0.089,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+58\/-71","imputed":false},{"position":62,"method":"FastaiMLP","variant":"Default","family":"Neural Network","url":"https:\/\/arxiv.org\/abs\/2003.06505","family_symbol":"\ud83e\udde0\ud83d\udd01","verified":true,"elo":1000.0,"score":0.005,"rank":54.08,"hrank":37.17,"imp":26.856,"train_time":5.48,"predict_time":0.684,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+49\/-62","imputed":false},{"position":63,"method":"KNN","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":1000.0,"score":0.022,"rank":54.08,"hrank":35.68,"imp":29.267,"train_time":111.87,"predict_time":1.214,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+65\/-94","imputed":false},{"position":64,"method":"Linear","variant":"Tuned + Ens.","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":974.0,"score":0.042,"rank":55.53,"hrank":37.13,"imp":33.999,"train_time":521.07,"predict_time":0.646,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+86\/-95","imputed":false},{"position":65,"method":"Linear","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":954.0,"score":0.03,"rank":56.63,"hrank":38.68,"imp":34.411,"train_time":521.07,"predict_time":0.113,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+85\/-99","imputed":false},{"position":66,"method":"PerpetualBooster","variant":"Default","family":"Tree-based","url":"https:\/\/perpetual-ml.com\/","family_symbol":"\ud83c\udf33","verified":true,"elo":947.0,"score":0.0,"rank":57.02,"hrank":41.72,"imp":32.717,"train_time":39.09,"predict_time":0.041,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+41\/-58","imputed":false},{"position":67,"method":"KNN","variant":"Tuned","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":912.0,"score":0.012,"rank":58.72,"hrank":42.52,"imp":33.953,"train_time":111.87,"predict_time":0.111,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+68\/-89","imputed":false},{"position":68,"method":"Linear","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/linear_model.html","family_symbol":"\ud83d\udccf","verified":true,"elo":879.0,"score":0.019,"rank":60.23,"hrank":43.4,"imp":37.25,"train_time":2.59,"predict_time":0.138,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+95\/-118","imputed":false},{"position":69,"method":"KNN","variant":"Default","family":"Baseline","url":"https:\/\/scikit-learn.org\/stable\/modules\/neighbors.html","family_symbol":"\ud83d\udccf","verified":true,"elo":670.0,"score":0.0,"rank":66.58,"hrank":57.89,"imp":47.022,"train_time":0.37,"predict_time":0.033,"imputed_pct":0.0,"hardware":"CPU","elo_ci":"+98\/-134","imputed":false}];
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 370 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 371 |
-
// already share a color, and each holds only a handful of methods.
|
| 372 |
-
const FAM_MERGED = "Baseline / Other";
|
| 373 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 374 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 375 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 376 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 377 |
-
|
| 378 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 379 |
-
const FAM_VAR = {
|
| 380 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 381 |
-
"Tree-based": "var(--fam-tree)",
|
| 382 |
-
"Neural Network": "var(--fam-nn)",
|
| 383 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 384 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 385 |
-
};
|
| 386 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 387 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 388 |
-
// that chip carries both symbols.
|
| 389 |
-
const FAM_SYMBOL = {
|
| 390 |
-
"Foundation Model": "🧠⚡",
|
| 391 |
-
"Tree-based": "🌳",
|
| 392 |
-
"Neural Network": "🧠🔁",
|
| 393 |
-
"Reference Pipeline": "📊",
|
| 394 |
-
[FAM_MERGED]: "📏 ❓",
|
| 395 |
-
};
|
| 396 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 397 |
-
const VARIANT_VAR = {
|
| 398 |
-
"Default": "var(--var-default)",
|
| 399 |
-
"Tuned": "var(--var-tuned)",
|
| 400 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 401 |
-
};
|
| 402 |
-
|
| 403 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 404 |
-
function famChipLabel(family, count) {
|
| 405 |
-
const symbol = FAM_SYMBOL[family];
|
| 406 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 407 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 408 |
-
}
|
| 409 |
-
|
| 410 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 411 |
-
const FAM_INK = {
|
| 412 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 413 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 414 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 415 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 416 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 417 |
-
};
|
| 418 |
-
|
| 419 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 420 |
-
function el(name, attrs, parent) {
|
| 421 |
-
const node = document.createElementNS(NS, name);
|
| 422 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 423 |
-
if (parent) parent.appendChild(node);
|
| 424 |
-
return node;
|
| 425 |
-
}
|
| 426 |
-
|
| 427 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 428 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 429 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 430 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 431 |
-
function fmtNum(v, decimals) {
|
| 432 |
-
if (v == null || !isFinite(v)) return "—";
|
| 433 |
-
return v.toFixed(decimals);
|
| 434 |
-
}
|
| 435 |
-
|
| 436 |
-
function fmtMetric(metric, v) {
|
| 437 |
-
if (v == null || !isFinite(v)) return "—";
|
| 438 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 439 |
-
}
|
| 440 |
-
|
| 441 |
-
function fmtTime(v) {
|
| 442 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 443 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 444 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 445 |
-
return fmtNum(v, 3) + " s";
|
| 446 |
-
}
|
| 447 |
-
|
| 448 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 449 |
-
function niceStep(raw) {
|
| 450 |
-
if (!(raw > 0)) return 1;
|
| 451 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 452 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 453 |
-
if (mag * m >= raw) return mag * m;
|
| 454 |
-
}
|
| 455 |
-
return mag * 10;
|
| 456 |
-
}
|
| 457 |
-
|
| 458 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 459 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 460 |
-
function ticks(min, max, target) {
|
| 461 |
-
const step = niceStep((max - min) / target);
|
| 462 |
-
const first = Math.ceil(min / step);
|
| 463 |
-
const out = [];
|
| 464 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 465 |
-
return out.length ? out : [min];
|
| 466 |
-
}
|
| 467 |
-
|
| 468 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 469 |
-
function makeTooltip(box) {
|
| 470 |
-
const node = box.querySelector(".tooltip");
|
| 471 |
-
return {
|
| 472 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 473 |
-
move(ev) {
|
| 474 |
-
const r = box.getBoundingClientRect();
|
| 475 |
-
let tx = ev.clientX - r.left + 14;
|
| 476 |
-
const ty = ev.clientY - r.top + 12;
|
| 477 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 478 |
-
node.style.left = tx + "px";
|
| 479 |
-
node.style.top = ty + "px";
|
| 480 |
-
},
|
| 481 |
-
hide() { node.style.display = "none"; },
|
| 482 |
-
};
|
| 483 |
-
}
|
| 484 |
-
|
| 485 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 486 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 487 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 488 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 489 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 490 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 491 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 492 |
-
function setUpPaperView(afterToggle, options) {
|
| 493 |
-
const opts = options || {};
|
| 494 |
-
const root = document.documentElement;
|
| 495 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 496 |
-
const btn = document.getElementById("btn-paper");
|
| 497 |
-
const embedded = window.parent !== window;
|
| 498 |
-
|
| 499 |
-
function setPaper(on) {
|
| 500 |
-
document.body.classList.toggle("paper", on);
|
| 501 |
-
if (on) {
|
| 502 |
-
hostTheme = root.getAttribute("data-theme");
|
| 503 |
-
root.setAttribute("data-theme", "light");
|
| 504 |
-
} else if (hostTheme) {
|
| 505 |
-
root.setAttribute("data-theme", hostTheme);
|
| 506 |
-
} else {
|
| 507 |
-
root.removeAttribute("data-theme");
|
| 508 |
-
}
|
| 509 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 510 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 511 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 512 |
-
postHeight();
|
| 513 |
-
}
|
| 514 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 515 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 516 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 517 |
-
// shareable single file) this page needs its own.
|
| 518 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 519 |
-
window.addEventListener("message", ev => {
|
| 520 |
-
const d = ev.data;
|
| 521 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 522 |
-
});
|
| 523 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 524 |
-
// key press, so its label would fall out of step with the frame.
|
| 525 |
-
if (!embedded) {
|
| 526 |
-
document.addEventListener("keydown", ev => {
|
| 527 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 528 |
-
});
|
| 529 |
-
}
|
| 530 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 531 |
-
}
|
| 532 |
-
|
| 533 |
-
// --- Figure export ---------------------------------------------------------
|
| 534 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 535 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 536 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 537 |
-
// the legend is HTML rather than part of the SVG.
|
| 538 |
-
|
| 539 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 540 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 541 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 542 |
-
// break the PNG path.
|
| 543 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 544 |
-
// once the node leaves this document.
|
| 545 |
-
function resolveVars(root, resolve) {
|
| 546 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 547 |
-
for (const attr of ["fill", "stroke"]) {
|
| 548 |
-
const value = node.getAttribute(attr);
|
| 549 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 550 |
-
}
|
| 551 |
-
}
|
| 552 |
-
}
|
| 553 |
-
|
| 554 |
-
function legendToSvg(container, resolve) {
|
| 555 |
-
const base = container.getBoundingClientRect();
|
| 556 |
-
const group = document.createElementNS(NS, "g");
|
| 557 |
-
let height = 0;
|
| 558 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 559 |
-
const box = item.getBoundingClientRect();
|
| 560 |
-
if (!box.width) continue;
|
| 561 |
-
height = Math.max(height, box.bottom - base.top);
|
| 562 |
-
let textLeft = box.left - base.left;
|
| 563 |
-
const glyph = item.querySelector("svg");
|
| 564 |
-
if (glyph) {
|
| 565 |
-
const gbox = glyph.getBoundingClientRect();
|
| 566 |
-
const wrap = el("g", {
|
| 567 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 568 |
-
}, group);
|
| 569 |
-
const glyphClone = glyph.cloneNode(true);
|
| 570 |
-
resolveVars(glyphClone, resolve);
|
| 571 |
-
wrap.appendChild(glyphClone);
|
| 572 |
-
textLeft = gbox.right - base.left + 5;
|
| 573 |
-
}
|
| 574 |
-
const label = item.textContent.trim();
|
| 575 |
-
if (!label) continue;
|
| 576 |
-
const colored = item.querySelector("[style*='color']");
|
| 577 |
-
const text = el("text", {
|
| 578 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 579 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 580 |
-
}, group);
|
| 581 |
-
text.textContent = label;
|
| 582 |
-
}
|
| 583 |
-
return { group, height: Math.ceil(height) };
|
| 584 |
-
}
|
| 585 |
-
|
| 586 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 587 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 588 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 589 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 590 |
-
const resolve = value => String(value).replace(
|
| 591 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 592 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 593 |
-
|
| 594 |
-
let chartW = 0, chartH = 0;
|
| 595 |
-
for (const part of parts) {
|
| 596 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 597 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 598 |
-
}
|
| 599 |
-
|
| 600 |
-
const out = document.createElementNS(NS, "svg");
|
| 601 |
-
out.setAttribute("xmlns", NS);
|
| 602 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 603 |
-
let top = pad;
|
| 604 |
-
const later = []; // built after the width is known
|
| 605 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 606 |
-
if (legend && legend.height) {
|
| 607 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 608 |
-
later.push(() => out.appendChild(legend.group));
|
| 609 |
-
top += legend.height + 8;
|
| 610 |
-
}
|
| 611 |
-
|
| 612 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 613 |
-
const height = top + chartH + pad;
|
| 614 |
-
out.setAttribute("width", Math.ceil(width));
|
| 615 |
-
out.setAttribute("height", Math.ceil(height));
|
| 616 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 617 |
-
for (const build of later) build();
|
| 618 |
-
|
| 619 |
-
for (const part of parts) {
|
| 620 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 621 |
-
const clone = part.svg.cloneNode(true);
|
| 622 |
-
resolveVars(clone, resolve);
|
| 623 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 624 |
-
}
|
| 625 |
-
return out;
|
| 626 |
-
}
|
| 627 |
-
|
| 628 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 629 |
-
function slugify(text) {
|
| 630 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 631 |
-
}
|
| 632 |
-
|
| 633 |
-
function downloadUrl(url, filename) {
|
| 634 |
-
const a = document.createElement("a");
|
| 635 |
-
a.href = url;
|
| 636 |
-
a.download = filename;
|
| 637 |
-
document.body.appendChild(a);
|
| 638 |
-
a.click();
|
| 639 |
-
a.remove();
|
| 640 |
-
}
|
| 641 |
-
|
| 642 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 643 |
-
function rasterize(svg, scale, done, fail) {
|
| 644 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 645 |
-
const img = new Image();
|
| 646 |
-
img.onload = () => {
|
| 647 |
-
const canvas = document.createElement("canvas");
|
| 648 |
-
canvas.width = Math.round(width * scale);
|
| 649 |
-
canvas.height = Math.round(height * scale);
|
| 650 |
-
const ctx = canvas.getContext("2d");
|
| 651 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 652 |
-
ctx.drawImage(img, 0, 0);
|
| 653 |
-
done(canvas, width, height);
|
| 654 |
-
};
|
| 655 |
-
img.onerror = fail;
|
| 656 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 657 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 658 |
-
}
|
| 659 |
-
|
| 660 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 661 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 662 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 663 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 664 |
-
// and the pixels land at 96*scale dpi.
|
| 665 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 666 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 667 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 668 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 669 |
-
rgb[j] = pixels[i];
|
| 670 |
-
rgb[j + 1] = pixels[i + 1];
|
| 671 |
-
rgb[j + 2] = pixels[i + 2];
|
| 672 |
-
}
|
| 673 |
-
const deflated = new Uint8Array(await new Response(
|
| 674 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 675 |
-
|
| 676 |
-
const encoder = new TextEncoder();
|
| 677 |
-
const chunks = [];
|
| 678 |
-
const offsets = [];
|
| 679 |
-
let cursor = 0;
|
| 680 |
-
const put = data => {
|
| 681 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 682 |
-
chunks.push(bytes);
|
| 683 |
-
cursor += bytes.length;
|
| 684 |
-
};
|
| 685 |
-
const object = (id, body, stream) => {
|
| 686 |
-
offsets[id] = cursor;
|
| 687 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 688 |
-
if (stream) {
|
| 689 |
-
put("stream\n");
|
| 690 |
-
put(stream);
|
| 691 |
-
put("\nendstream\n");
|
| 692 |
-
}
|
| 693 |
-
put("endobj\n");
|
| 694 |
-
};
|
| 695 |
-
|
| 696 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 697 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 698 |
-
put("%PDF-1.4\n");
|
| 699 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 700 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 701 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 702 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 703 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 704 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 705 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 706 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 707 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 708 |
-
|
| 709 |
-
const xref = cursor;
|
| 710 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 711 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 712 |
-
put(table);
|
| 713 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 714 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 715 |
-
}
|
| 716 |
-
|
| 717 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 718 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 719 |
-
function setUpExport(getParts, basename) {
|
| 720 |
-
const buttons = {
|
| 721 |
-
svg: document.getElementById("btn-svg"),
|
| 722 |
-
png: document.getElementById("btn-png"),
|
| 723 |
-
pdf: document.getElementById("btn-pdf"),
|
| 724 |
-
};
|
| 725 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 726 |
-
|
| 727 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 728 |
-
function complain(format) {
|
| 729 |
-
const button = buttons[format];
|
| 730 |
-
if (!button) return;
|
| 731 |
-
const label = button.textContent;
|
| 732 |
-
button.textContent = "failed";
|
| 733 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 734 |
-
}
|
| 735 |
-
|
| 736 |
-
function run(format) {
|
| 737 |
-
const svg = figure();
|
| 738 |
-
const name = basename();
|
| 739 |
-
if (format === "svg") {
|
| 740 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 741 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 742 |
-
return;
|
| 743 |
-
}
|
| 744 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 745 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 746 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 747 |
-
if (format === "png") {
|
| 748 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 749 |
-
} else {
|
| 750 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 751 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 752 |
-
.catch(() => complain("pdf"));
|
| 753 |
-
}
|
| 754 |
-
}, () => complain(format));
|
| 755 |
-
}
|
| 756 |
-
|
| 757 |
-
for (const format of Object.keys(buttons)) {
|
| 758 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 759 |
-
}
|
| 760 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 761 |
-
window.addEventListener("message", ev => {
|
| 762 |
-
const d = ev.data;
|
| 763 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 764 |
-
});
|
| 765 |
-
}
|
| 766 |
-
|
| 767 |
-
// When embedded, report the content height so the host page can size the
|
| 768 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 769 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 770 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 771 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 772 |
-
// stops re-posting once the height settles.
|
| 773 |
-
let lastPostedHeight = 0;
|
| 774 |
-
function postHeight() {
|
| 775 |
-
if (window.parent === window) return;
|
| 776 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 777 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 778 |
-
lastPostedHeight = height;
|
| 779 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 780 |
-
}
|
| 781 |
-
|
| 782 |
-
|
| 783 |
-
const COLUMNS = CONFIG.columns;
|
| 784 |
-
const RANK_KEY = CONFIG.rankKey;
|
| 785 |
-
const colByKey = new Map(COLUMNS.map(c => [c.key, c]));
|
| 786 |
-
const VARIANTS = CONFIG.variants.filter(v => POINTS.some(p => p.variant === v));
|
| 787 |
-
|
| 788 |
-
// How a variant is written out. The short "Tuned + Ens." form is the internal key
|
| 789 |
-
// (the charts' colour and marker tables are keyed by it), but nothing on the page
|
| 790 |
-
// should show the abbreviation: the row tag uses the spelling the data and the
|
| 791 |
-
// app's cross-subset table use, and the toggle spells it out in full.
|
| 792 |
-
const VARIANT_TEXT = {
|
| 793 |
-
"Default": "default",
|
| 794 |
-
"Tuned": "tuned",
|
| 795 |
-
"Tuned + Ens.": "tuned + ensembled",
|
| 796 |
-
};
|
| 797 |
-
const VARIANT_BTN = { "Tuned + Ens.": "Tuned + Ensembled" };
|
| 798 |
-
const variantText = v => VARIANT_TEXT[v] || v;
|
| 799 |
-
const HAS_IMPUTED = POINTS.some(p => p.imputed);
|
| 800 |
-
|
| 801 |
-
const state = {
|
| 802 |
-
methods: new Set(POINTS.map(p => p.method)),
|
| 803 |
-
variants: new Set(VARIANTS),
|
| 804 |
-
columns: new Set(COLUMNS.filter(c => c.on !== false).map(c => c.key)),
|
| 805 |
-
imputed: true,
|
| 806 |
-
search: "",
|
| 807 |
-
sortKey: null,
|
| 808 |
-
sortAsc: false,
|
| 809 |
-
};
|
| 810 |
-
|
| 811 |
-
const tblwrap = document.getElementById("tblwrap");
|
| 812 |
-
const chipsBox = document.getElementById("chips");
|
| 813 |
-
const famChips = new Map();
|
| 814 |
-
const chipByMethod = new Map();
|
| 815 |
-
|
| 816 |
-
// ---------- heat shading ----------
|
| 817 |
-
// Green (best) through olive to red (worst), matching the website's
|
| 818 |
-
// cross-subset overview so a reader moving between them reads one scale.
|
| 819 |
-
const RAMP = [[0, [28, 120, 62]], [0.5, [138, 122, 36]], [1, [160, 58, 58]]];
|
| 820 |
-
function heatColor(frac) {
|
| 821 |
-
const f = Math.max(0, Math.min(1, frac));
|
| 822 |
-
for (let i = 0; i < RAMP.length - 1; i++) {
|
| 823 |
-
const [f0, c0] = RAMP[i], [f1, c1] = RAMP[i + 1];
|
| 824 |
-
if (f <= f1) {
|
| 825 |
-
const t = f1 === f0 ? 0 : (f - f0) / (f1 - f0);
|
| 826 |
-
const mix = c0.map((v, j) => Math.round(v + t * (c1[j] - v)));
|
| 827 |
-
return "rgb(" + mix.join(",") + ")";
|
| 828 |
-
}
|
| 829 |
-
}
|
| 830 |
-
return "rgb(" + RAMP[RAMP.length - 1][1].join(",") + ")";
|
| 831 |
-
}
|
| 832 |
-
// Runtimes span orders of magnitude; shading them linearly paints every model
|
| 833 |
-
// the same green and only the slowest one red, so those normalize in log space.
|
| 834 |
-
function scaleOf(col, v) { return col.logScale ? Math.log10(v) : v; }
|
| 835 |
-
function bounds(rows, col) {
|
| 836 |
-
const values = [];
|
| 837 |
-
for (const p of rows) {
|
| 838 |
-
const v = p[col.key];
|
| 839 |
-
if (v == null || !isFinite(v)) continue;
|
| 840 |
-
if (col.logScale && !(v > 0)) continue;
|
| 841 |
-
values.push(scaleOf(col, v));
|
| 842 |
-
}
|
| 843 |
-
if (values.length < 2) return null;
|
| 844 |
-
const lo = Math.min(...values), hi = Math.max(...values);
|
| 845 |
-
return hi > lo ? [lo, hi] : null;
|
| 846 |
-
}
|
| 847 |
-
|
| 848 |
-
// ---------- cells ----------
|
| 849 |
-
function nameCell(p) {
|
| 850 |
-
const ink = FAM_INK[p.family] || "var(--muted)";
|
| 851 |
-
let inner = escapeHtml(p.method);
|
| 852 |
-
if (p.variant) inner += ' <span class="variant-tag">(' + escapeHtml(variantText(p.variant)) + ")</span>";
|
| 853 |
-
if (p.verified) inner += ' <span class="verified" title="Verified implementation">✔️</span>';
|
| 854 |
-
if (p.imputed) {
|
| 855 |
-
const pct = isFinite(p.imputed_pct) ? fmtNum(p.imputed_pct, 0) + "% " : "";
|
| 856 |
-
inner += ' <span class="imp-mark" title="' + pct + 'imputed">‡</span>';
|
| 857 |
-
}
|
| 858 |
-
const body = p.url
|
| 859 |
-
? '<a href="' + escapeHtml(p.url) + '" target="_blank" rel="noopener" style="color:' + ink +
|
| 860 |
-
';font-weight:600;">' + inner + '<span class="link-icon">↗</span></a>'
|
| 861 |
-
: '<span style="color:' + ink + ';font-weight:600;">' + inner + "</span>";
|
| 862 |
-
return '<td class="name" data-export="' + escapeHtml(plainName(p)) + '">' + body + "</td>";
|
| 863 |
-
}
|
| 864 |
-
function plainName(p) {
|
| 865 |
-
return p.method + (p.variant ? " (" + p.variant + ")" : "");
|
| 866 |
-
}
|
| 867 |
-
function escapeHtml(text) {
|
| 868 |
-
return String(text == null ? "" : text).replace(/[&<>"']/g, c =>
|
| 869 |
-
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
| 870 |
-
}
|
| 871 |
-
|
| 872 |
-
// ---------- rows ----------
|
| 873 |
-
function visibleRows() {
|
| 874 |
-
const term = state.search.trim().toLowerCase();
|
| 875 |
-
return POINTS.filter(p => {
|
| 876 |
-
if (!state.methods.has(p.method)) return false;
|
| 877 |
-
if (p.variant && !state.variants.has(p.variant)) return false;
|
| 878 |
-
if (!state.imputed && p.imputed) return false;
|
| 879 |
-
if (term && !(p.method + " " + (p.variant || "") + " " + p.family).toLowerCase().includes(term)) return false;
|
| 880 |
-
return true;
|
| 881 |
-
});
|
| 882 |
-
}
|
| 883 |
-
function sortRows(rows) {
|
| 884 |
-
const out = rows.slice();
|
| 885 |
-
if (!state.sortKey) return out.sort((a, b) => a.position - b.position);
|
| 886 |
-
const col = colByKey.get(state.sortKey);
|
| 887 |
-
const sign = state.sortAsc ? 1 : -1;
|
| 888 |
-
const keyOf = p => {
|
| 889 |
-
const v = p[state.sortKey];
|
| 890 |
-
if (col && col.text) return String(v == null ? "" : v).toLowerCase();
|
| 891 |
-
return v == null || !isFinite(v) ? null : v;
|
| 892 |
-
};
|
| 893 |
-
return out.sort((a, b) => {
|
| 894 |
-
const ka = keyOf(a), kb = keyOf(b);
|
| 895 |
-
if (ka === null || kb === null) return ka === kb ? 0 : ka === null ? 1 : -1;
|
| 896 |
-
return ka < kb ? -sign : ka > kb ? sign : 0;
|
| 897 |
-
});
|
| 898 |
-
}
|
| 899 |
-
|
| 900 |
-
function activeColumns() {
|
| 901 |
-
return COLUMNS.filter(c => c.always || state.columns.has(c.key));
|
| 902 |
-
}
|
| 903 |
-
|
| 904 |
-
function render() {
|
| 905 |
-
const rows = sortRows(visibleRows());
|
| 906 |
-
const cols = activeColumns();
|
| 907 |
-
if (!rows.length) {
|
| 908 |
-
tblwrap.innerHTML = '<p class="lbt-empty">Nothing selected — turn a family or variant back on.</p>';
|
| 909 |
-
document.getElementById("caption").textContent = "";
|
| 910 |
-
postHeight();
|
| 911 |
-
return;
|
| 912 |
-
}
|
| 913 |
-
// No medals here: this table is the full ranking, so the position column
|
| 914 |
-
// already says who is where. They belong to the cross-subset overview.
|
| 915 |
-
const heat = new Map();
|
| 916 |
-
for (const col of cols) if (col.heatmap) heat.set(col.key, bounds(rows, col));
|
| 917 |
-
|
| 918 |
-
let html = '<table class="lbt"><thead><tr>';
|
| 919 |
-
for (const col of cols) {
|
| 920 |
-
const sorted = state.sortKey === col.key
|
| 921 |
-
? ' aria-sort="' + (state.sortAsc ? "ascending" : "descending") + '"' : "";
|
| 922 |
-
html += "<th" + sorted + ' data-key="' + col.key + '" title="' + escapeHtml(col.hint || col.label) +
|
| 923 |
-
'"><span class="lbl">' + escapeHtml(col.label) + "</span>" +
|
| 924 |
-
(col.key === "elo" ? ' <span class="ci">(95% CI)</span>' : "") + "</th>";
|
| 925 |
-
}
|
| 926 |
-
html += "</tr></thead><tbody>";
|
| 927 |
-
for (const p of rows) {
|
| 928 |
-
html += "<tr>";
|
| 929 |
-
for (const col of cols) {
|
| 930 |
-
if (col.key === "position") {
|
| 931 |
-
html += '<td class="pos num" data-sort="' + p.position + '">' + p.position + "</td>";
|
| 932 |
-
} else if (col.key === "family") {
|
| 933 |
-
const mark = FAM_VAR[p.family] || "var(--fam-baseline)";
|
| 934 |
-
html += '<td class="type" data-sort="' + escapeHtml(p.family) + '" data-export="' + escapeHtml(p.family) +
|
| 935 |
-
'"><span class="pill" style="background:color-mix(in srgb, ' + mark +
|
| 936 |
-
' 13%, transparent);color:' + (FAM_INK[p.family] || "var(--muted)") +
|
| 937 |
-
";border:1px solid color-mix(in srgb, " + mark + ' 40%, transparent);">' +
|
| 938 |
-
escapeHtml(p.family_symbol || "") + "</span></td>";
|
| 939 |
-
} else if (col.key === "model") {
|
| 940 |
-
html += nameCell(p);
|
| 941 |
-
} else {
|
| 942 |
-
html += valueCell(p, col, heat.get(col.key));
|
| 943 |
-
}
|
| 944 |
-
}
|
| 945 |
-
html += "</tr>";
|
| 946 |
-
}
|
| 947 |
-
tblwrap.innerHTML = html + "</tbody></table>";
|
| 948 |
-
for (const th of tblwrap.querySelectorAll("th")) {
|
| 949 |
-
th.addEventListener("click", () => sortBy(th.dataset.key));
|
| 950 |
-
}
|
| 951 |
-
document.getElementById("caption").textContent =
|
| 952 |
-
rows.length + (rows.length === 1 ? " row" : " rows") +
|
| 953 |
-
" · click a column header to sort, hover one for what it means" +
|
| 954 |
-
(heat.size ? " · green is better, red is worse, per column" : "") +
|
| 955 |
-
(HAS_IMPUTED ? " · ‡ marks a partly imputed score" : "");
|
| 956 |
-
postHeight();
|
| 957 |
-
}
|
| 958 |
-
|
| 959 |
-
function valueCell(p, col, span) {
|
| 960 |
-
const v = p[col.key];
|
| 961 |
-
if (v == null || (typeof v === "number" && !isFinite(v))) return '<td class="na">–</td>';
|
| 962 |
-
if (col.text) {
|
| 963 |
-
return '<td data-sort="' + escapeHtml(v) + '" data-export="' + escapeHtml(v) + '">' + escapeHtml(v) + "</td>";
|
| 964 |
-
}
|
| 965 |
-
let style = "";
|
| 966 |
-
if (span) {
|
| 967 |
-
let frac = (scaleOf(col, v) - span[0]) / (span[1] - span[0]);
|
| 968 |
-
if (!col.lowerBetter) frac = 1 - frac;
|
| 969 |
-
style = ' style="background:' + heatColor(frac) + ';color:#f7f7f7;"';
|
| 970 |
-
}
|
| 971 |
-
let text = fmtNum(v, col.decimals) + (col.suffix || "");
|
| 972 |
-
let ci = "";
|
| 973 |
-
if (col.key === "elo" && p.elo_ci) {
|
| 974 |
-
ci = ' <span class="ci">(' + escapeHtml(p.elo_ci) + ")</span>";
|
| 975 |
-
}
|
| 976 |
-
return '<td class="num" data-sort="' + v + '"' + (ci ? ' data-ci="' + escapeHtml(p.elo_ci) + '"' : "") +
|
| 977 |
-
style + ">" + text + ci + "</td>";
|
| 978 |
-
}
|
| 979 |
-
|
| 980 |
-
function sortBy(key) {
|
| 981 |
-
if (!key) return;
|
| 982 |
-
if (state.sortKey === key) state.sortAsc = !state.sortAsc;
|
| 983 |
-
else { state.sortKey = key; state.sortAsc = !!(colByKey.get(key) || {}).lowerBetter; }
|
| 984 |
-
render();
|
| 985 |
-
}
|
| 986 |
-
|
| 987 |
-
// ---------- chips (families and their methods) ----------
|
| 988 |
-
function familyMembers(fam) {
|
| 989 |
-
return [...new Set(POINTS.filter(p => p.family === fam).map(p => p.method))];
|
| 990 |
-
}
|
| 991 |
-
function methodRank(name) {
|
| 992 |
-
const col = colByKey.get(RANK_KEY);
|
| 993 |
-
const values = POINTS.filter(p => p.method === name && isFinite(p[RANK_KEY])).map(p => p[RANK_KEY]);
|
| 994 |
-
if (!values.length) return Infinity;
|
| 995 |
-
return col.lowerBetter ? Math.min(...values) : -Math.max(...values);
|
| 996 |
-
}
|
| 997 |
-
function buildChips() {
|
| 998 |
-
const head = document.createElement("div");
|
| 999 |
-
head.className = "chips-head";
|
| 1000 |
-
head.textContent = "Models shown — click to remove, click a family to toggle the whole group";
|
| 1001 |
-
chipsBox.appendChild(head);
|
| 1002 |
-
for (const fam of FAM_ORDER) {
|
| 1003 |
-
const members = familyMembers(fam);
|
| 1004 |
-
if (!members.length) continue;
|
| 1005 |
-
members.sort((a, b) => methodRank(a) - methodRank(b));
|
| 1006 |
-
const row = document.createElement("div");
|
| 1007 |
-
row.className = "chiprow";
|
| 1008 |
-
const famBtn = document.createElement("button");
|
| 1009 |
-
famBtn.className = "famchip";
|
| 1010 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1011 |
-
famBtn.innerHTML = famChipLabel(fam, members.length);
|
| 1012 |
-
famBtn.title = "Toggle all " + members.length + " " + fam + " models";
|
| 1013 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1014 |
-
row.appendChild(famBtn);
|
| 1015 |
-
famChips.set(fam, famBtn);
|
| 1016 |
-
const set = document.createElement("div");
|
| 1017 |
-
set.className = "chipset";
|
| 1018 |
-
for (const name of members) {
|
| 1019 |
-
const imputed = POINTS.some(p => p.method === name && p.imputed);
|
| 1020 |
-
const b = document.createElement("button");
|
| 1021 |
-
b.className = "chip";
|
| 1022 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1023 |
-
b.innerHTML = '<span class="dot"></span><span>' + escapeHtml(name) + "</span>" +
|
| 1024 |
-
(imputed ? '<span class="imp-mark">‡</span>' : "");
|
| 1025 |
-
b.title = name + (imputed ? " — partially imputed" : "");
|
| 1026 |
-
b.addEventListener("click", () => toggleMethod(name));
|
| 1027 |
-
set.appendChild(b);
|
| 1028 |
-
chipByMethod.set(name, b);
|
| 1029 |
-
}
|
| 1030 |
-
row.appendChild(set);
|
| 1031 |
-
chipsBox.appendChild(row);
|
| 1032 |
-
}
|
| 1033 |
-
}
|
| 1034 |
-
function syncChips() {
|
| 1035 |
-
for (const [name, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.methods.has(name)));
|
| 1036 |
-
for (const [fam, b] of famChips) {
|
| 1037 |
-
b.setAttribute("aria-pressed", String(familyMembers(fam).every(m => state.methods.has(m))));
|
| 1038 |
-
}
|
| 1039 |
-
}
|
| 1040 |
-
function toggleMethod(name) {
|
| 1041 |
-
if (state.methods.has(name)) state.methods.delete(name); else state.methods.add(name);
|
| 1042 |
-
syncChips();
|
| 1043 |
-
render();
|
| 1044 |
-
}
|
| 1045 |
-
function toggleFamily(fam) {
|
| 1046 |
-
const members = familyMembers(fam);
|
| 1047 |
-
const allOn = members.every(m => state.methods.has(m));
|
| 1048 |
-
for (const m of members) { if (allOn) state.methods.delete(m); else state.methods.add(m); }
|
| 1049 |
-
syncChips();
|
| 1050 |
-
render();
|
| 1051 |
-
}
|
| 1052 |
-
|
| 1053 |
-
// ---------- variant / imputed / column toggles ----------
|
| 1054 |
-
const variantBtns = new Map();
|
| 1055 |
-
function buildVariantBtns() {
|
| 1056 |
-
const box = document.getElementById("variant-btns");
|
| 1057 |
-
for (const v of VARIANTS) {
|
| 1058 |
-
const b = document.createElement("button");
|
| 1059 |
-
b.className = "btn toggle";
|
| 1060 |
-
b.innerHTML = '<span class="swatch"></span>' + escapeHtml(VARIANT_BTN[v] || v);
|
| 1061 |
-
b.style.setProperty("--fam", VARIANT_VAR[v] || "var(--accent)");
|
| 1062 |
-
b.title = "Show or hide the " + variantText(v) + " results";
|
| 1063 |
-
b.addEventListener("click", () => {
|
| 1064 |
-
if (state.variants.has(v)) state.variants.delete(v); else state.variants.add(v);
|
| 1065 |
-
syncVariantBtns();
|
| 1066 |
-
render();
|
| 1067 |
-
});
|
| 1068 |
-
box.appendChild(b);
|
| 1069 |
-
variantBtns.set(v, b);
|
| 1070 |
-
}
|
| 1071 |
-
}
|
| 1072 |
-
function syncVariantBtns() {
|
| 1073 |
-
for (const [v, b] of variantBtns) b.setAttribute("aria-pressed", String(state.variants.has(v)));
|
| 1074 |
-
const imp = document.getElementById("btn-imputed");
|
| 1075 |
-
imp.hidden = !HAS_IMPUTED;
|
| 1076 |
-
imp.className = "btn toggle";
|
| 1077 |
-
imp.innerHTML = '<span class="swatch"></span>‡ Imputed';
|
| 1078 |
-
imp.setAttribute("aria-pressed", String(state.imputed));
|
| 1079 |
-
imp.style.setProperty("--fam", "var(--muted)");
|
| 1080 |
-
}
|
| 1081 |
-
function buildColumnBtns() {
|
| 1082 |
-
const box = document.getElementById("col-btns");
|
| 1083 |
-
for (const col of COLUMNS) {
|
| 1084 |
-
if (col.always) continue;
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "btn toggle";
|
| 1087 |
-
b.textContent = col.short || col.label;
|
| 1088 |
-
b.title = "Show or hide " + col.label;
|
| 1089 |
-
b.style.setProperty("--fam", "var(--accent)");
|
| 1090 |
-
b.addEventListener("click", () => {
|
| 1091 |
-
if (state.columns.has(col.key)) state.columns.delete(col.key); else state.columns.add(col.key);
|
| 1092 |
-
b.setAttribute("aria-pressed", String(state.columns.has(col.key)));
|
| 1093 |
-
render();
|
| 1094 |
-
});
|
| 1095 |
-
b.setAttribute("aria-pressed", String(state.columns.has(col.key)));
|
| 1096 |
-
box.appendChild(b);
|
| 1097 |
-
}
|
| 1098 |
-
}
|
| 1099 |
-
|
| 1100 |
-
// ---------- CSV ----------
|
| 1101 |
-
// Exports what the reader is looking at: the rows the filters left, the
|
| 1102 |
-
// columns they picked, in the order they sorted.
|
| 1103 |
-
function downloadCsv() {
|
| 1104 |
-
const cols = activeColumns();
|
| 1105 |
-
const rows = sortRows(visibleRows());
|
| 1106 |
-
const quote = v => '"' + String(v == null ? "" : v).replace(/"/g, '""') + '"';
|
| 1107 |
-
const head = [];
|
| 1108 |
-
for (const col of cols) {
|
| 1109 |
-
head.push(col.label);
|
| 1110 |
-
if (col.key === "elo" && rows.some(p => p.elo_ci)) head.push("Elo 95% CI");
|
| 1111 |
-
}
|
| 1112 |
-
const lines = [head.map(quote).join(",")];
|
| 1113 |
-
for (const p of rows) {
|
| 1114 |
-
const values = [];
|
| 1115 |
-
for (const col of cols) {
|
| 1116 |
-
if (col.key === "model") values.push(plainName(p));
|
| 1117 |
-
else values.push(p[col.key]);
|
| 1118 |
-
if (col.key === "elo" && rows.some(q => q.elo_ci)) values.push(p.elo_ci || "");
|
| 1119 |
-
}
|
| 1120 |
-
lines.push(values.map(quote).join(","));
|
| 1121 |
-
}
|
| 1122 |
-
const blob = new Blob([lines.join("\n") + "\n"], { type: "text/csv;charset=utf-8" });
|
| 1123 |
-
const url = URL.createObjectURL(blob);
|
| 1124 |
-
downloadUrl(url, slugify(CONFIG.title || document.title || "leaderboard") + ".csv");
|
| 1125 |
-
URL.revokeObjectURL(url);
|
| 1126 |
-
}
|
| 1127 |
-
|
| 1128 |
-
// ---------- boot ----------
|
| 1129 |
-
if (CONFIG.title) document.getElementById("title").textContent = CONFIG.title;
|
| 1130 |
-
document.getElementById("search").addEventListener("input", ev => {
|
| 1131 |
-
state.search = ev.target.value;
|
| 1132 |
-
render();
|
| 1133 |
-
});
|
| 1134 |
-
document.getElementById("btn-imputed").addEventListener("click", () => {
|
| 1135 |
-
state.imputed = !state.imputed;
|
| 1136 |
-
syncVariantBtns();
|
| 1137 |
-
render();
|
| 1138 |
-
});
|
| 1139 |
-
document.getElementById("btn-csv").addEventListener("click", downloadCsv);
|
| 1140 |
-
// Embedded, the host page puts its own CSV button in the panel header (next to
|
| 1141 |
-
// the title) and asks for the download over postMessage, the same way it drives
|
| 1142 |
-
// the figure exports. Standalone, this page needs its own button.
|
| 1143 |
-
if (window.parent !== window) {
|
| 1144 |
-
document.getElementById("btn-csv").hidden = true;
|
| 1145 |
-
window.addEventListener("message", ev => {
|
| 1146 |
-
if (ev.data && ev.data.type === "tabarena-leaderboard-csv") downloadCsv();
|
| 1147 |
-
});
|
| 1148 |
-
}
|
| 1149 |
-
// Opens with the controls: the filters are the point of this page, not chrome
|
| 1150 |
-
// around a figure.
|
| 1151 |
-
setUpPaperView(render, { openInPaper: false });
|
| 1152 |
-
buildVariantBtns();
|
| 1153 |
-
buildColumnBtns();
|
| 1154 |
-
buildChips();
|
| 1155 |
-
syncChips();
|
| 1156 |
-
syncVariantBtns();
|
| 1157 |
-
render();
|
| 1158 |
-
window.addEventListener("resize", postHeight);
|
| 1159 |
-
})();
|
| 1160 |
-
</script>
|
| 1161 |
-
</body>
|
| 1162 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/n_datasets_36
DELETED
|
File without changes
|
data/imputation_no/splits_all/tasks_all/datasets_small/pareto_front_explorer.html
DELETED
|
@@ -1,1230 +0,0 @@
|
|
| 1 |
-
<!doctype html>
|
| 2 |
-
<html lang="en">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="utf-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 6 |
-
<title>TabArena Pareto explorer</title>
|
| 7 |
-
<style>
|
| 8 |
-
:root {
|
| 9 |
-
--fam-foundation: #b07cf0;
|
| 10 |
-
--fam-nn: #5aa9e6;
|
| 11 |
-
--fam-tree: #5cb85c;
|
| 12 |
-
--fam-reference: #f0a35a;
|
| 13 |
-
--fam-baseline: #9e9e9e;
|
| 14 |
-
--fam-other: #9e9e9e;
|
| 15 |
-
--paper: #ffffff;
|
| 16 |
-
--card: #ffffff;
|
| 17 |
-
--ink: #14161a;
|
| 18 |
-
--muted: #6d6c65;
|
| 19 |
-
--line: #e4e3db;
|
| 20 |
-
--accent: #2a78d6;
|
| 21 |
-
--chip-bg: #f2f1ec;
|
| 22 |
-
--pt-muted: #b9b8b1;
|
| 23 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 24 |
-
drop below readable contrast as small labels on the light surface, so
|
| 25 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 26 |
-
--fam-foundation-ink: #7d3fc2;
|
| 27 |
-
--fam-nn-ink: #1c6fa8;
|
| 28 |
-
--fam-tree-ink: #2f7d32;
|
| 29 |
-
--fam-reference-ink: #a4600f;
|
| 30 |
-
--fam-baseline-ink: #5f5f5f;
|
| 31 |
-
--fam-other-ink: #5f5f5f;
|
| 32 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 33 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 34 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 35 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 36 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 37 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 38 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 39 |
-
--var-default: #a1c9f4;
|
| 40 |
-
--var-tuned: #ffb482;
|
| 41 |
-
--var-tunedens: #8de5a1;
|
| 42 |
-
--optimal: #228b22;
|
| 43 |
-
--tooltip-bg: #14161a;
|
| 44 |
-
--tooltip-ink: #fbfbf9;
|
| 45 |
-
color-scheme: light;
|
| 46 |
-
}
|
| 47 |
-
@media (prefers-color-scheme: dark) {
|
| 48 |
-
:root {
|
| 49 |
-
--paper: #131316;
|
| 50 |
-
--card: #1b1b1f;
|
| 51 |
-
--ink: #f0efea;
|
| 52 |
-
--muted: #9b9a92;
|
| 53 |
-
--line: #2e2e33;
|
| 54 |
-
--accent: #3987e5;
|
| 55 |
-
--chip-bg: #232327;
|
| 56 |
-
--pt-muted: #55555c;
|
| 57 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 58 |
-
--fam-nn-ink: var(--fam-nn);
|
| 59 |
-
--fam-tree-ink: var(--fam-tree);
|
| 60 |
-
--fam-reference-ink: var(--fam-reference);
|
| 61 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 62 |
-
--fam-other-ink: var(--fam-other);
|
| 63 |
-
--var-default: #4386d5;
|
| 64 |
-
--var-tuned: #c05f38;
|
| 65 |
-
--var-tunedens: #289972;
|
| 66 |
-
--optimal: #2ea043;
|
| 67 |
-
--tooltip-bg: #f0efea;
|
| 68 |
-
--tooltip-ink: #14161a;
|
| 69 |
-
color-scheme: dark;
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
:root[data-theme="dark"] {
|
| 73 |
-
--paper: #131316;
|
| 74 |
-
--card: #1b1b1f;
|
| 75 |
-
--ink: #f0efea;
|
| 76 |
-
--muted: #9b9a92;
|
| 77 |
-
--line: #2e2e33;
|
| 78 |
-
--accent: #3987e5;
|
| 79 |
-
--chip-bg: #232327;
|
| 80 |
-
--pt-muted: #55555c;
|
| 81 |
-
--fam-foundation-ink: var(--fam-foundation);
|
| 82 |
-
--fam-nn-ink: var(--fam-nn);
|
| 83 |
-
--fam-tree-ink: var(--fam-tree);
|
| 84 |
-
--fam-reference-ink: var(--fam-reference);
|
| 85 |
-
--fam-baseline-ink: var(--fam-baseline);
|
| 86 |
-
--fam-other-ink: var(--fam-other);
|
| 87 |
-
--var-default: #4386d5;
|
| 88 |
-
--var-tuned: #c05f38;
|
| 89 |
-
--var-tunedens: #289972;
|
| 90 |
-
--optimal: #2ea043;
|
| 91 |
-
--tooltip-bg: #f0efea;
|
| 92 |
-
--tooltip-ink: #14161a;
|
| 93 |
-
color-scheme: dark;
|
| 94 |
-
}
|
| 95 |
-
:root[data-theme="light"] {
|
| 96 |
-
--paper: #ffffff;
|
| 97 |
-
--card: #ffffff;
|
| 98 |
-
--ink: #14161a;
|
| 99 |
-
--muted: #6d6c65;
|
| 100 |
-
--line: #e4e3db;
|
| 101 |
-
--accent: #2a78d6;
|
| 102 |
-
--chip-bg: #f2f1ec;
|
| 103 |
-
--pt-muted: #b9b8b1;
|
| 104 |
-
/* The same family hues as *text*. The mark colors are tuned for fills and
|
| 105 |
-
drop below readable contrast as small labels on the light surface, so
|
| 106 |
-
light mode darkens them; dark mode reuses the mark colors as-is. */
|
| 107 |
-
--fam-foundation-ink: #7d3fc2;
|
| 108 |
-
--fam-nn-ink: #1c6fa8;
|
| 109 |
-
--fam-tree-ink: #2f7d32;
|
| 110 |
-
--fam-reference-ink: #a4600f;
|
| 111 |
-
--fam-baseline-ink: #5f5f5f;
|
| 112 |
-
--fam-other-ink: #5f5f5f;
|
| 113 |
-
/* Tuning-variant series (default / tuned / tuned + ensembled). Light mode
|
| 114 |
-
is the paper view's surface, so it uses the *static figures' own* seaborn
|
| 115 |
-
pastels — figures exported from here drop straight into a paper beside
|
| 116 |
-
them. The cost is colorblind separation: green vs. orange is 4.0 deutan
|
| 117 |
-
ΔE, well inside the band that needs secondary encoding, which here is the
|
| 118 |
-
fixed concentric bar widths plus the legend and the data table. Dark mode
|
| 119 |
-
(the website) keeps the stepped, better-separated version below. */
|
| 120 |
-
--var-default: #a1c9f4;
|
| 121 |
-
--var-tuned: #ffb482;
|
| 122 |
-
--var-tunedens: #8de5a1;
|
| 123 |
-
--optimal: #228b22;
|
| 124 |
-
--tooltip-bg: #14161a;
|
| 125 |
-
--tooltip-ink: #fbfbf9;
|
| 126 |
-
color-scheme: light;
|
| 127 |
-
}
|
| 128 |
-
html, body { margin: 0; background: var(--paper); }
|
| 129 |
-
/* The colour emoji fonts are named *before* the generic `sans-serif`. A generic
|
| 130 |
-
family matches every character through the browser's own fallback chain, so
|
| 131 |
-
anything listed after it is unreachable — and that fallback resolves emoji to
|
| 132 |
-
a monochrome font on Linux, which flattens the family symbols on the chips.
|
| 133 |
-
Latin glyphs are unaffected: the emoji fonts carry none. */
|
| 134 |
-
body {
|
| 135 |
-
color: var(--ink);
|
| 136 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 137 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 138 |
-
line-height: 1.5;
|
| 139 |
-
padding: 10px 12px 14px;
|
| 140 |
-
}
|
| 141 |
-
/* The [hidden] attribute must beat author display rules (e.g. the
|
| 142 |
-
inline-flex on .metricpick), else hidden controls render empty. */
|
| 143 |
-
[hidden] { display: none !important; }
|
| 144 |
-
|
| 145 |
-
.explorer-title { font-size: 15px; font-weight: 650; margin: 0 0 8px; }
|
| 146 |
-
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-bottom: 10px; }
|
| 147 |
-
.controls .hint { font-size: 12.5px; color: var(--muted); }
|
| 148 |
-
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; }
|
| 149 |
-
.btn {
|
| 150 |
-
font: 600 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 151 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 152 |
-
padding: 6px 11px; cursor: pointer;
|
| 153 |
-
}
|
| 154 |
-
.btn:hover { border-color: var(--muted); }
|
| 155 |
-
.btn:focus-visible, .chip:focus-visible, .famchip:focus-visible, select:focus-visible {
|
| 156 |
-
outline: 2px solid var(--accent); outline-offset: 2px;
|
| 157 |
-
}
|
| 158 |
-
.metricpick { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 159 |
-
.metricpick select {
|
| 160 |
-
font: 600 12.5px/1.2 system-ui, sans-serif; color: var(--ink);
|
| 161 |
-
background: var(--chip-bg); border: 1px solid var(--line); border-radius: 7px;
|
| 162 |
-
padding: 5px 7px; cursor: pointer;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.chips { display: flex; flex-direction: column; gap: 9px; }
|
| 166 |
-
/* One block per family: the family toggle on top, its chips wrapping below. */
|
| 167 |
-
.chiprow { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
|
| 168 |
-
.famchip {
|
| 169 |
-
display: inline-flex; align-items: center; gap: 6px;
|
| 170 |
-
font: 650 10.5px/1.3 system-ui, sans-serif; letter-spacing: 0.06em; text-transform: uppercase;
|
| 171 |
-
color: var(--muted); background: var(--chip-bg); border: 1px dashed var(--line);
|
| 172 |
-
border-radius: 999px; padding: 5px 10px; cursor: pointer;
|
| 173 |
-
}
|
| 174 |
-
.famchip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--fam); flex: none; }
|
| 175 |
-
.famchip .count { font-weight: 500; letter-spacing: 0; opacity: 0.75; }
|
| 176 |
-
/* The family symbol sits at text size, not the chip's small-caps size. */
|
| 177 |
-
.famchip .sym { font-size: 1.05em; letter-spacing: 0; }
|
| 178 |
-
.famchip:hover { border-color: var(--fam); color: var(--ink); }
|
| 179 |
-
.famchip[aria-pressed="true"] {
|
| 180 |
-
border: 1px solid var(--fam);
|
| 181 |
-
background: color-mix(in srgb, var(--fam) 13%, transparent);
|
| 182 |
-
color: var(--ink);
|
| 183 |
-
}
|
| 184 |
-
/* A toggle button that carries its own colour: off is faded with a neutral
|
| 185 |
-
border, on takes the colour as border and tint. Opt-in via `.toggle` so the
|
| 186 |
-
older explorers, which fade their variant buttons with inline styles, are
|
| 187 |
-
unaffected. */
|
| 188 |
-
.btn.toggle[aria-pressed] { opacity: 0.5; }
|
| 189 |
-
.btn.toggle[aria-pressed="true"] {
|
| 190 |
-
opacity: 1;
|
| 191 |
-
border-color: var(--fam);
|
| 192 |
-
background: color-mix(in srgb, var(--fam) 18%, var(--chip-bg));
|
| 193 |
-
}
|
| 194 |
-
.btn.toggle .swatch {
|
| 195 |
-
display: inline-block; width: 8px; height: 8px; border-radius: 50%;
|
| 196 |
-
background: var(--fam); margin-right: 6px; vertical-align: middle;
|
| 197 |
-
}
|
| 198 |
-
.btn.toggle[aria-pressed="false"] .swatch { background: var(--pt-muted); }
|
| 199 |
-
.grouplabel { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 200 |
-
|
| 201 |
-
.chipset { display: flex; flex-wrap: wrap; gap: 4px; }
|
| 202 |
-
.chip {
|
| 203 |
-
display: inline-flex; align-items: center; gap: 5px;
|
| 204 |
-
font: 500 12.5px/1 system-ui, sans-serif; color: var(--ink);
|
| 205 |
-
background: none; border: 1px solid var(--line); border-radius: 999px;
|
| 206 |
-
padding: 5px 10px 5px 8px; cursor: pointer;
|
| 207 |
-
}
|
| 208 |
-
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--pt-muted); flex: none; }
|
| 209 |
-
.chip .imp-mark { color: var(--muted); font-weight: 700; margin-left: -2px; }
|
| 210 |
-
.chip[aria-pressed="true"] { border-color: var(--fam); background: color-mix(in srgb, var(--fam) 13%, transparent); font-weight: 650; }
|
| 211 |
-
.chip[aria-pressed="true"] .dot { background: var(--fam); }
|
| 212 |
-
.chip:hover { border-color: var(--muted); }
|
| 213 |
-
|
| 214 |
-
.legendstrip {
|
| 215 |
-
display: flex; flex-wrap: wrap; gap: 5px 16px; align-items: center;
|
| 216 |
-
font-size: 12.5px; color: var(--muted); padding: 2px 2px 8px;
|
| 217 |
-
}
|
| 218 |
-
.legendstrip .item { display: inline-flex; align-items: center; gap: 6px; }
|
| 219 |
-
|
| 220 |
-
.tooltip {
|
| 221 |
-
position: absolute; pointer-events: none; display: none;
|
| 222 |
-
background: var(--tooltip-bg); color: var(--tooltip-ink);
|
| 223 |
-
border-radius: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.45;
|
| 224 |
-
max-width: 260px; z-index: 5; font-variant-numeric: tabular-nums;
|
| 225 |
-
box-shadow: 0 4px 14px rgba(0,0,0,0.25);
|
| 226 |
-
}
|
| 227 |
-
.tooltip .t-name { font-weight: 700; font-size: 12.5px; }
|
| 228 |
-
.tooltip .t-var { opacity: 0.75; }
|
| 229 |
-
.tooltip .t-imp { opacity: 0.85; font-style: italic; }
|
| 230 |
-
|
| 231 |
-
details.datatable { margin-top: 8px; font-size: 12.5px; }
|
| 232 |
-
details.datatable summary { cursor: pointer; color: var(--muted); font-weight: 600; }
|
| 233 |
-
details.datatable .tblwrap { overflow-x: auto; margin-top: 8px; }
|
| 234 |
-
details.datatable table { border-collapse: collapse; font-variant-numeric: tabular-nums; min-width: 560px; }
|
| 235 |
-
details.datatable th, details.datatable td {
|
| 236 |
-
text-align: left; padding: 3px 12px 3px 0; border-bottom: 1px solid var(--line);
|
| 237 |
-
}
|
| 238 |
-
details.datatable th { font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
|
| 239 |
-
|
| 240 |
-
svg text {
|
| 241 |
-
font-family: system-ui, -apple-system, "Segoe UI",
|
| 242 |
-
"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
|
| 243 |
-
}
|
| 244 |
-
|
| 245 |
-
@media (prefers-reduced-motion: no-preference) {
|
| 246 |
-
.chip, .btn, .famchip { transition: border-color 120ms ease, background-color 120ms ease; }
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
/* --- Paper view -----------------------------------------------------------
|
| 250 |
-
A figure-ready state for slides and papers: white surface, and only the
|
| 251 |
-
things needed to read the plot — the caption, the legend and the chart.
|
| 252 |
-
The controls, the chip list and the data table are interactive scaffolding,
|
| 253 |
-
not part of the figure. Entered via the "Paper view" button (which stamps
|
| 254 |
-
data-theme="light" on the root, see the scopes above). */
|
| 255 |
-
/* One toggle, in the same place in both states and never hidden — an exit
|
| 256 |
-
tucked into a corner of the figure was easy to miss. */
|
| 257 |
-
.viewbar { display: flex; align-items: center; gap: 10px; margin: 0 0 9px; }
|
| 258 |
-
body.paper .controls,
|
| 259 |
-
body.paper .chips,
|
| 260 |
-
body.paper .sidebox,
|
| 261 |
-
body.paper details.datatable { display: none !important; }
|
| 262 |
-
body.paper { padding: 14px 18px 18px; }
|
| 263 |
-
/* Export controls, revealed with the paper view. */
|
| 264 |
-
.exportbar { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
|
| 265 |
-
.exportbar .hint { font-size: 12.5px; font-weight: 600; color: var(--muted); }
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
/* Two-column layout: controls + chips in a side panel, chart beside it.
|
| 269 |
-
``chips-right`` mirrors the columns. Wraps to stacked when narrow. */
|
| 270 |
-
.explorer-grid { display: flex; gap: 18px; align-items: flex-start; }
|
| 271 |
-
.explorer-grid.chips-right { flex-direction: row-reverse; }
|
| 272 |
-
.sidebox { flex: 0 0 330px; min-width: 250px; display: flex; flex-direction: column; gap: 10px; }
|
| 273 |
-
.mainbox { flex: 1 1 auto; min-width: 0; }
|
| 274 |
-
@media (max-width: 860px) {
|
| 275 |
-
.explorer-grid { flex-wrap: wrap; }
|
| 276 |
-
.sidebox { flex: 1 1 100%; }
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
-
.legendstrip .legendbreak { flex-basis: 100%; height: 0; }
|
| 280 |
-
.chartbox { position: relative; }
|
| 281 |
-
/* The chart is sized in device pixels by render() rather than scaled from a
|
| 282 |
-
viewBox: scaling stretched the type along with the plot, and a viewBox tall
|
| 283 |
-
enough to read made the whole panel own the screen. */
|
| 284 |
-
.chartbox svg { display: block; }
|
| 285 |
-
/* Chips scroll within the column so the panel height follows the chart. */
|
| 286 |
-
.sidebox .chips { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--pt-muted) transparent; }
|
| 287 |
-
.sidebox .chips::-webkit-scrollbar { width: 9px; }
|
| 288 |
-
.sidebox .chips::-webkit-scrollbar-thumb {
|
| 289 |
-
background: var(--pt-muted); border-radius: 8px; border: 3px solid transparent; background-clip: content-box;
|
| 290 |
-
}
|
| 291 |
-
</style>
|
| 292 |
-
</head>
|
| 293 |
-
<body>
|
| 294 |
-
<div class="viewbar">
|
| 295 |
-
<button class="btn" id="btn-paper" title="White background, chart and legend only — for slides and papers">Paper view</button>
|
| 296 |
-
</div>
|
| 297 |
-
<p class="explorer-title" id="title"></p>
|
| 298 |
-
<div class="explorer-grid" id="grid">
|
| 299 |
-
<div class="sidebox">
|
| 300 |
-
<div class="controls">
|
| 301 |
-
<label class="metricpick" id="metricpick" hidden>Y-axis
|
| 302 |
-
<select id="metric-select"></select>
|
| 303 |
-
</label>
|
| 304 |
-
<div class="btnrow">
|
| 305 |
-
<button class="btn" id="btn-front">Pareto front</button>
|
| 306 |
-
<button class="btn" id="btn-all">All</button>
|
| 307 |
-
<button class="btn" id="btn-none">Clear</button>
|
| 308 |
-
</div>
|
| 309 |
-
<span class="hint">Click methods or family buttons to highlight · hover points for details</span>
|
| 310 |
-
</div>
|
| 311 |
-
<div class="chips" id="chips"></div>
|
| 312 |
-
</div>
|
| 313 |
-
<div class="mainbox">
|
| 314 |
-
<div class="exportbar" id="exportbar" hidden>
|
| 315 |
-
<span class="hint">Export figure</span>
|
| 316 |
-
<button class="btn" id="btn-svg" title="Download as SVG — vector, keeps text selectable">SVG</button>
|
| 317 |
-
<button class="btn" id="btn-pdf" title="Download as a one-page PDF">PDF</button>
|
| 318 |
-
<button class="btn" id="btn-png" title="Download as PNG at 3x scale">PNG</button>
|
| 319 |
-
</div>
|
| 320 |
-
<!-- Legend above the chart so readers decode the marks before the data. -->
|
| 321 |
-
<div class="legendstrip" id="legendstrip"></div>
|
| 322 |
-
<div class="chartbox" id="chartbox">
|
| 323 |
-
<svg id="chart" role="img" aria-label="Pareto front explorer"></svg>
|
| 324 |
-
<div class="tooltip"></div>
|
| 325 |
-
</div>
|
| 326 |
-
</div>
|
| 327 |
-
</div>
|
| 328 |
-
<details class="datatable">
|
| 329 |
-
<summary>Data table</summary>
|
| 330 |
-
<div class="tblwrap" id="tblwrap"></div>
|
| 331 |
-
</details>
|
| 332 |
-
|
| 333 |
-
<script>
|
| 334 |
-
(function () {
|
| 335 |
-
"use strict";
|
| 336 |
-
const CONFIG = {"mode": "scatter", "title": null, "metrics": [{"key": "imp", "label": "Improvability (%)", "axisLabel": "Improvability (%) \u2014 lower is better", "lowerBetter": true, "fromZero": true, "decimals": 1, "suffix": "%"}, {"key": "elo", "label": "Elo", "axisLabel": "Elo \u2014 higher is better", "lowerBetter": false, "fromZero": false, "decimals": 0, "suffix": ""}], "xAxes": [{"key": "x_infer", "label": "Inference time", "axisLabel": "Inference time per 1K samples (s), median \u2014 log scale", "short": "Inference (s/1K, median)"}], "chipsSide": "left"};
|
| 337 |
-
const POINTS = [{"method":"CatBoost","family":"Tree-based","x_infer":0.0455896074,"imp":18.2032871809,"elo":1320.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"CatBoost","family":"Tree-based","x_infer":0.0508532668,"imp":17.2788594488,"elo":1354.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"CatBoost","family":"Tree-based","x_infer":0.3960267603,"imp":17.0406428568,"elo":1367.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.0413889487,"imp":20.9409846453,"elo":1216.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.0359833093,"imp":19.8033433908,"elo":1259.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ChimeraBoost","family":"Tree-based","x_infer":0.454903865,"imp":19.5160246588,"elo":1278.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"EBM","family":"Tree-based","x_infer":0.0171560587,"imp":21.2493491202,"elo":1203.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"EBM","family":"Tree-based","x_infer":0.0172938338,"imp":20.510545928,"elo":1230.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"EBM","family":"Tree-based","x_infer":0.1529693961,"imp":19.9544651059,"elo":1259.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.5663988088,"imp":27.5877514986,"elo":1019.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ExtraTrees","family":"Tree-based","x_infer":0.2136923717,"imp":22.3391093508,"elo":1187.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ExtraTrees","family":"Tree-based","x_infer":1.5011279394,"imp":21.6412157659,"elo":1210.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"FastaiMLP","family":"Neural Network","x_infer":0.6842938244,"imp":26.8558318039,"elo":999.9,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"FastaiMLP","family":"Neural Network","x_infer":0.82578692,"imp":21.847378167,"elo":1164.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"FastaiMLP","family":"Neural Network","x_infer":8.0688374767,"imp":20.7123810494,"elo":1214.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"LightGBM","family":"Tree-based","x_infer":0.1695753133,"imp":21.2294827321,"elo":1166.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"LightGBM","family":"Tree-based","x_infer":0.3458375858,"imp":17.3893988993,"elo":1353.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"LightGBM","family":"Tree-based","x_infer":2.5704534161,"imp":16.9366876587,"elo":1389.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"LimiX","family":"Foundation Model","x_infer":6.8284826783,"imp":15.1548850837,"elo":1405.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ModernNCA","family":"Neural Network","x_infer":0.320600689,"imp":21.2208702147,"elo":1237.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"ModernNCA","family":"Neural Network","x_infer":0.5053503954,"imp":18.0561303362,"elo":1323.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"ModernNCA","family":"Neural Network","x_infer":8.3903226253,"imp":18.3187609832,"elo":1323.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.0406570787,"imp":32.7166050918,"elo":946.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.3125464363,"imp":29.9076789954,"elo":1048.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"PerpetualBooster","family":"Tree-based","x_infer":0.8948102984,"imp":28.4508866176,"elo":1083.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RandomForest","family":"Tree-based","x_infer":0.0885648768,"imp":28.3765267033,"elo":1000.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RandomForest","family":"Tree-based","x_infer":0.1503007896,"imp":23.9480322533,"elo":1113.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RandomForest","family":"Tree-based","x_infer":1.4602306271,"imp":23.2155091609,"elo":1149.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RealMLP","family":"Neural Network","x_infer":4.6888676463,"imp":20.0184669583,"elo":1221.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RealMLP","family":"Neural Network","x_infer":1.7776750936,"imp":15.9097834653,"elo":1399.9,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RealMLP","family":"Neural Network","x_infer":21.9024962791,"imp":14.5333602982,"elo":1479.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":0.6362272808,"imp":12.3200887376,"elo":1541.9,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":1.1425914845,"imp":11.9071180723,"elo":1555.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"RealTabPFN-2.5","family":"Foundation Model","x_infer":8.0475948482,"imp":11.1975772448,"elo":1595.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"SAP-RPT-OSS","family":"Foundation Model","x_infer":1.2773508677,"imp":18.8388371702,"elo":1319.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabDPT","family":"Foundation Model","x_infer":43.7074010359,"imp":18.0230648308,"elo":1331.6,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabDPT","family":"Foundation Model","x_infer":28.3513403832,"imp":15.883723432,"elo":1415.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabDPT","family":"Foundation Model","x_infer":218.4533640735,"imp":15.2464708261,"elo":1448.0,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabDPT-Turbo","family":"Foundation Model","x_infer":0.1922706752,"imp":15.3295501945,"elo":1448.5,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabFM","family":"Foundation Model","x_infer":5.3578381333,"imp":4.6543552541,"elo":1743.7,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabICLv2","family":"Foundation Model","x_infer":0.1520731745,"imp":11.5604085785,"elo":1572.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabM","family":"Neural Network","x_infer":0.444937792,"imp":18.2578343688,"elo":1295.8,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabM","family":"Neural Network","x_infer":0.4361574183,"imp":16.5609732873,"elo":1373.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabM","family":"Neural Network","x_infer":3.8381409686,"imp":15.6750950369,"elo":1429.1,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabPFN-2.6","family":"Foundation Model","x_infer":0.548288662,"imp":11.9607415625,"elo":1599.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabPFN-3","family":"Foundation Model","x_infer":0.4158216639,"imp":10.7658050052,"elo":1636.0,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabSTAR","family":"Foundation Model","x_infer":7.2137264423,"imp":30.3598793602,"elo":1033.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TabSTAR","family":"Foundation Model","x_infer":5.6062080426,"imp":25.4914369812,"elo":1131.8,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TabSTAR","family":"Foundation Model","x_infer":25.9362072534,"imp":25.5248178568,"elo":1130.2,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"TabSwift","family":"Foundation Model","x_infer":0.0579126899,"imp":17.2241080479,"elo":1363.2,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TorchMLP","family":"Neural Network","x_infer":0.1550906392,"imp":24.7609027784,"elo":1057.8,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"TorchMLP","family":"Neural Network","x_infer":0.1474394112,"imp":20.8615927184,"elo":1195.6,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"TorchMLP","family":"Neural Network","x_infer":2.1570271396,"imp":19.1243302341,"elo":1260.5,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"XGBoost","family":"Tree-based","x_infer":0.2525411892,"imp":21.2442258572,"elo":1163.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"XGBoost","family":"Tree-based","x_infer":0.3929683731,"imp":18.1328413794,"elo":1306.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"XGBoost","family":"Tree-based","x_infer":2.3674863949,"imp":17.9237428347,"elo":1324.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"iLTM","family":"Foundation Model","x_infer":161.8134383214,"imp":24.9136024932,"elo":1066.4,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"iLTM","family":"Foundation Model","x_infer":161.2206474003,"imp":19.245205487,"elo":1257.7,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"iLTM","family":"Foundation Model","x_infer":841.4458907481,"imp":17.4214786951,"elo":1361.3,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."},{"method":"xRFM","family":"Other","x_infer":1.0976028857,"imp":26.6387104203,"elo":1043.3,"imputed":false,"imputed_pct":0.0,"variant":"Default"},{"method":"xRFM","family":"Other","x_infer":0.1632446807,"imp":18.8938182398,"elo":1282.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned"},{"method":"xRFM","family":"Other","x_infer":2.9395549707,"imp":17.8683612217,"elo":1330.4,"imputed":false,"imputed_pct":0.0,"variant":"Tuned + Ens."}];
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
const NS = "http://www.w3.org/2000/svg";
|
| 341 |
-
// Baseline and Other are one bucket, as in the site's own type legend: they
|
| 342 |
-
// already share a color, and each holds only a handful of methods.
|
| 343 |
-
const FAM_MERGED = "Baseline / Other";
|
| 344 |
-
const famOf = (family) => (family === "Baseline" || family === "Other" ? FAM_MERGED : family);
|
| 345 |
-
// Normalized up front so every later lookup — colors, chips, sorting — sees
|
| 346 |
-
// the merged family. Both templates declare POINTS above this block.
|
| 347 |
-
for (const p of POINTS) p.family = famOf(p.family);
|
| 348 |
-
|
| 349 |
-
const FAM_ORDER = ["Foundation Model", "Tree-based", "Neural Network", "Reference Pipeline", FAM_MERGED];
|
| 350 |
-
const FAM_VAR = {
|
| 351 |
-
"Foundation Model": "var(--fam-foundation)",
|
| 352 |
-
"Tree-based": "var(--fam-tree)",
|
| 353 |
-
"Neural Network": "var(--fam-nn)",
|
| 354 |
-
"Reference Pipeline": "var(--fam-reference)",
|
| 355 |
-
[FAM_MERGED]: "var(--fam-baseline)",
|
| 356 |
-
};
|
| 357 |
-
// The symbol the website shows for each family, so a family chip here reads the
|
| 358 |
-
// same as the Type column on the site. Baseline and Other are one bucket, so
|
| 359 |
-
// that chip carries both symbols.
|
| 360 |
-
const FAM_SYMBOL = {
|
| 361 |
-
"Foundation Model": "🧠⚡",
|
| 362 |
-
"Tree-based": "🌳",
|
| 363 |
-
"Neural Network": "🧠🔁",
|
| 364 |
-
"Reference Pipeline": "📊",
|
| 365 |
-
[FAM_MERGED]: "📏 ❓",
|
| 366 |
-
};
|
| 367 |
-
// Tuning-variant colours, matching the --var-* tokens the charts plot with.
|
| 368 |
-
const VARIANT_VAR = {
|
| 369 |
-
"Default": "var(--var-default)",
|
| 370 |
-
"Tuned": "var(--var-tuned)",
|
| 371 |
-
"Tuned + Ens.": "var(--var-tunedens)",
|
| 372 |
-
};
|
| 373 |
-
|
| 374 |
-
// A family chip's label: its symbol, its name and how many methods it holds.
|
| 375 |
-
function famChipLabel(family, count) {
|
| 376 |
-
const symbol = FAM_SYMBOL[family];
|
| 377 |
-
return '<span class="dot"></span>' + (symbol ? '<span class="sym">' + symbol + "</span> " : "") +
|
| 378 |
-
family + ' <span class="count">×' + count + "</span>";
|
| 379 |
-
}
|
| 380 |
-
|
| 381 |
-
// The same hues stepped for use as text (see the --fam-*-ink tokens).
|
| 382 |
-
const FAM_INK = {
|
| 383 |
-
"Foundation Model": "var(--fam-foundation-ink)",
|
| 384 |
-
"Tree-based": "var(--fam-tree-ink)",
|
| 385 |
-
"Neural Network": "var(--fam-nn-ink)",
|
| 386 |
-
"Reference Pipeline": "var(--fam-reference-ink)",
|
| 387 |
-
[FAM_MERGED]: "var(--fam-baseline-ink)",
|
| 388 |
-
};
|
| 389 |
-
|
| 390 |
-
// Create an SVG element with attributes, optionally appended to `parent`.
|
| 391 |
-
function el(name, attrs, parent) {
|
| 392 |
-
const node = document.createElementNS(NS, name);
|
| 393 |
-
for (const k in attrs) node.setAttribute(k, attrs[k]);
|
| 394 |
-
if (parent) parent.appendChild(node);
|
| 395 |
-
return node;
|
| 396 |
-
}
|
| 397 |
-
|
| 398 |
-
// Plain, ungrouped numbers with a "." decimal separator. `toFixed` is
|
| 399 |
-
// locale-independent by definition, which is the point: `toLocaleString`
|
| 400 |
-
// would follow the *viewer's* browser locale and print 1234,5 for a German
|
| 401 |
-
// visitor, disagreeing with the figures and CSVs beside it.
|
| 402 |
-
function fmtNum(v, decimals) {
|
| 403 |
-
if (v == null || !isFinite(v)) return "—";
|
| 404 |
-
return v.toFixed(decimals);
|
| 405 |
-
}
|
| 406 |
-
|
| 407 |
-
function fmtMetric(metric, v) {
|
| 408 |
-
if (v == null || !isFinite(v)) return "—";
|
| 409 |
-
return fmtNum(v, metric.decimals) + (metric.suffix || "");
|
| 410 |
-
}
|
| 411 |
-
|
| 412 |
-
function fmtTime(v) {
|
| 413 |
-
if (v >= 100) return fmtNum(v, 0) + " s";
|
| 414 |
-
if (v >= 1) return fmtNum(v, 1) + " s";
|
| 415 |
-
if (v >= 0.1) return fmtNum(v, 2) + " s";
|
| 416 |
-
return fmtNum(v, 3) + " s";
|
| 417 |
-
}
|
| 418 |
-
|
| 419 |
-
// Smallest "nice" (1/2/2.5/5 x a power of ten) step that is at least `raw`.
|
| 420 |
-
function niceStep(raw) {
|
| 421 |
-
if (!(raw > 0)) return 1;
|
| 422 |
-
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
|
| 423 |
-
for (const m of [1, 2, 2.5, 5, 10]) {
|
| 424 |
-
if (mag * m >= raw) return mag * m;
|
| 425 |
-
}
|
| 426 |
-
return mag * 10;
|
| 427 |
-
}
|
| 428 |
-
|
| 429 |
-
// ~`target` evenly spaced "nice" tick values covering [min, max]. Stepped by
|
| 430 |
-
// index rather than by accumulation so fractional steps do not drift.
|
| 431 |
-
function ticks(min, max, target) {
|
| 432 |
-
const step = niceStep((max - min) / target);
|
| 433 |
-
const first = Math.ceil(min / step);
|
| 434 |
-
const out = [];
|
| 435 |
-
for (let i = 0; first * step + i * step <= max + 1e-9; i++) out.push((first + i) * step);
|
| 436 |
-
return out.length ? out : [min];
|
| 437 |
-
}
|
| 438 |
-
|
| 439 |
-
// A hover tooltip anchored inside `box` (which must be position:relative).
|
| 440 |
-
function makeTooltip(box) {
|
| 441 |
-
const node = box.querySelector(".tooltip");
|
| 442 |
-
return {
|
| 443 |
-
show(html, ev) { node.innerHTML = html; node.style.display = "block"; this.move(ev); },
|
| 444 |
-
move(ev) {
|
| 445 |
-
const r = box.getBoundingClientRect();
|
| 446 |
-
let tx = ev.clientX - r.left + 14;
|
| 447 |
-
const ty = ev.clientY - r.top + 12;
|
| 448 |
-
if (tx > r.width - 270) tx = ev.clientX - r.left - 274;
|
| 449 |
-
node.style.left = tx + "px";
|
| 450 |
-
node.style.top = ty + "px";
|
| 451 |
-
},
|
| 452 |
-
hide() { node.style.display = "none"; },
|
| 453 |
-
};
|
| 454 |
-
}
|
| 455 |
-
|
| 456 |
-
// Paper view — white surface, legend + chart only — is the *default*: what a
|
| 457 |
-
// reader wants first is the figure, and it is the state worth exporting. The
|
| 458 |
-
// controls, chip list and data table are one click away behind "Edit view".
|
| 459 |
-
// `afterToggle` re-renders charts whose size is measured from the layout.
|
| 460 |
-
// `options.openInPaper` (default true) decides the state the page opens in. A
|
| 461 |
-
// chart opens as the figure; the leaderboard table opens with its controls,
|
| 462 |
-
// since there the interaction is the point rather than scaffolding around it.
|
| 463 |
-
function setUpPaperView(afterToggle, options) {
|
| 464 |
-
const opts = options || {};
|
| 465 |
-
const root = document.documentElement;
|
| 466 |
-
let hostTheme = null; // the embedding page's choice, captured on entry
|
| 467 |
-
const btn = document.getElementById("btn-paper");
|
| 468 |
-
const embedded = window.parent !== window;
|
| 469 |
-
|
| 470 |
-
function setPaper(on) {
|
| 471 |
-
document.body.classList.toggle("paper", on);
|
| 472 |
-
if (on) {
|
| 473 |
-
hostTheme = root.getAttribute("data-theme");
|
| 474 |
-
root.setAttribute("data-theme", "light");
|
| 475 |
-
} else if (hostTheme) {
|
| 476 |
-
root.setAttribute("data-theme", hostTheme);
|
| 477 |
-
} else {
|
| 478 |
-
root.removeAttribute("data-theme");
|
| 479 |
-
}
|
| 480 |
-
btn.textContent = on ? "Edit view" : "Paper view";
|
| 481 |
-
document.getElementById("exportbar").hidden = !on || embedded;
|
| 482 |
-
if (afterToggle) requestAnimationFrame(afterToggle);
|
| 483 |
-
postHeight();
|
| 484 |
-
}
|
| 485 |
-
btn.addEventListener("click", () => setPaper(!document.body.classList.contains("paper")));
|
| 486 |
-
// Embedded, the host page owns these controls — they sit beside the panel's
|
| 487 |
-
// static-figure toggle and are driven from the outside. Standalone (the
|
| 488 |
-
// shareable single file) this page needs its own.
|
| 489 |
-
if (embedded) document.querySelector(".viewbar").hidden = true;
|
| 490 |
-
window.addEventListener("message", ev => {
|
| 491 |
-
const d = ev.data;
|
| 492 |
-
if (d && d.type === "tabarena-explorer-paper" && typeof d.on === "boolean") setPaper(d.on);
|
| 493 |
-
});
|
| 494 |
-
// Only standalone: embedded, the host owns the button and would not see the
|
| 495 |
-
// key press, so its label would fall out of step with the frame.
|
| 496 |
-
if (!embedded) {
|
| 497 |
-
document.addEventListener("keydown", ev => {
|
| 498 |
-
if (ev.key === "Escape" && !document.body.classList.contains("paper")) setPaper(true);
|
| 499 |
-
});
|
| 500 |
-
}
|
| 501 |
-
setPaper(opts.openInPaper !== false); // for a chart, the figure is what opens
|
| 502 |
-
}
|
| 503 |
-
|
| 504 |
-
// --- Figure export ---------------------------------------------------------
|
| 505 |
-
// The chart is live SVG, so a file can be built from it directly. Three things
|
| 506 |
-
// a copy has to fix up: the colors are CSS custom properties (var(--x) means
|
| 507 |
-
// nothing outside this document), it has no background or font of its own, and
|
| 508 |
-
// the legend is HTML rather than part of the SVG.
|
| 509 |
-
|
| 510 |
-
// Rebuild the HTML legend as SVG, reusing its live layout: each item's glyph is
|
| 511 |
-
// cloned and its label re-emitted at the measured position. foreignObject would
|
| 512 |
-
// be far simpler, but Chrome refuses to rasterize it onto a canvas, which would
|
| 513 |
-
// break the PNG path.
|
| 514 |
-
// Rewrite every var(--x) in a clone's paint attributes; they resolve to nothing
|
| 515 |
-
// once the node leaves this document.
|
| 516 |
-
function resolveVars(root, resolve) {
|
| 517 |
-
for (const node of [root, ...root.querySelectorAll("*")]) {
|
| 518 |
-
for (const attr of ["fill", "stroke"]) {
|
| 519 |
-
const value = node.getAttribute(attr);
|
| 520 |
-
if (value && value.includes("var(")) node.setAttribute(attr, resolve(value));
|
| 521 |
-
}
|
| 522 |
-
}
|
| 523 |
-
}
|
| 524 |
-
|
| 525 |
-
function legendToSvg(container, resolve) {
|
| 526 |
-
const base = container.getBoundingClientRect();
|
| 527 |
-
const group = document.createElementNS(NS, "g");
|
| 528 |
-
let height = 0;
|
| 529 |
-
for (const item of container.querySelectorAll(".item")) {
|
| 530 |
-
const box = item.getBoundingClientRect();
|
| 531 |
-
if (!box.width) continue;
|
| 532 |
-
height = Math.max(height, box.bottom - base.top);
|
| 533 |
-
let textLeft = box.left - base.left;
|
| 534 |
-
const glyph = item.querySelector("svg");
|
| 535 |
-
if (glyph) {
|
| 536 |
-
const gbox = glyph.getBoundingClientRect();
|
| 537 |
-
const wrap = el("g", {
|
| 538 |
-
transform: `translate(${gbox.left - base.left} ${gbox.top - base.top})`,
|
| 539 |
-
}, group);
|
| 540 |
-
const glyphClone = glyph.cloneNode(true);
|
| 541 |
-
resolveVars(glyphClone, resolve);
|
| 542 |
-
wrap.appendChild(glyphClone);
|
| 543 |
-
textLeft = gbox.right - base.left + 5;
|
| 544 |
-
}
|
| 545 |
-
const label = item.textContent.trim();
|
| 546 |
-
if (!label) continue;
|
| 547 |
-
const colored = item.querySelector("[style*='color']");
|
| 548 |
-
const text = el("text", {
|
| 549 |
-
x: textLeft, y: box.top - base.top + box.height / 2 + 4, "font-size": 12.5,
|
| 550 |
-
fill: resolve(getComputedStyle(colored || item).color),
|
| 551 |
-
}, group);
|
| 552 |
-
text.textContent = label;
|
| 553 |
-
}
|
| 554 |
-
return { group, height: Math.ceil(height) };
|
| 555 |
-
}
|
| 556 |
-
|
| 557 |
-
// `parts` is a list of {svg, dx}, so a chart split across panes (the sticky
|
| 558 |
-
// y-axis beside the scrolling plot) still exports as one figure.
|
| 559 |
-
function buildExportSvg(parts, legendEl, pad = 10) {
|
| 560 |
-
const rootStyle = getComputedStyle(document.documentElement);
|
| 561 |
-
const resolve = value => String(value).replace(
|
| 562 |
-
/var\((--[\w-]+)\)/g, (_, name) => rootStyle.getPropertyValue(name).trim() || "none");
|
| 563 |
-
const paper = rootStyle.getPropertyValue("--paper").trim() || "#ffffff";
|
| 564 |
-
|
| 565 |
-
let chartW = 0, chartH = 0;
|
| 566 |
-
for (const part of parts) {
|
| 567 |
-
chartW = Math.max(chartW, part.dx + Number(part.svg.getAttribute("width")));
|
| 568 |
-
chartH = Math.max(chartH, Number(part.svg.getAttribute("height")));
|
| 569 |
-
}
|
| 570 |
-
|
| 571 |
-
const out = document.createElementNS(NS, "svg");
|
| 572 |
-
out.setAttribute("xmlns", NS);
|
| 573 |
-
out.setAttribute("font-family", 'system-ui, -apple-system, "Segoe UI", sans-serif');
|
| 574 |
-
let top = pad;
|
| 575 |
-
const later = []; // built after the width is known
|
| 576 |
-
const legend = legendEl ? legendToSvg(legendEl, resolve) : null;
|
| 577 |
-
if (legend && legend.height) {
|
| 578 |
-
legend.group.setAttribute("transform", `translate(${pad} ${top})`);
|
| 579 |
-
later.push(() => out.appendChild(legend.group));
|
| 580 |
-
top += legend.height + 8;
|
| 581 |
-
}
|
| 582 |
-
|
| 583 |
-
const width = Math.max(chartW, legendEl ? legendEl.getBoundingClientRect().width : 0) + pad * 2;
|
| 584 |
-
const height = top + chartH + pad;
|
| 585 |
-
out.setAttribute("width", Math.ceil(width));
|
| 586 |
-
out.setAttribute("height", Math.ceil(height));
|
| 587 |
-
el("rect", { x: 0, y: 0, width: Math.ceil(width), height: Math.ceil(height), fill: paper }, out);
|
| 588 |
-
for (const build of later) build();
|
| 589 |
-
|
| 590 |
-
for (const part of parts) {
|
| 591 |
-
const group = el("g", { transform: `translate(${part.dx + pad} ${top})` }, out);
|
| 592 |
-
const clone = part.svg.cloneNode(true);
|
| 593 |
-
resolveVars(clone, resolve);
|
| 594 |
-
while (clone.firstChild) group.appendChild(clone.firstChild);
|
| 595 |
-
}
|
| 596 |
-
return out;
|
| 597 |
-
}
|
| 598 |
-
|
| 599 |
-
// Page title -> a safe file stem, e.g. "tabarena-leaderboard-explorer-all-tasks".
|
| 600 |
-
function slugify(text) {
|
| 601 |
-
return (text || "chart").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
| 602 |
-
}
|
| 603 |
-
|
| 604 |
-
function downloadUrl(url, filename) {
|
| 605 |
-
const a = document.createElement("a");
|
| 606 |
-
a.href = url;
|
| 607 |
-
a.download = filename;
|
| 608 |
-
document.body.appendChild(a);
|
| 609 |
-
a.click();
|
| 610 |
-
a.remove();
|
| 611 |
-
}
|
| 612 |
-
|
| 613 |
-
// Rasterize the export SVG into a canvas at `scale`, then hand it to `done`.
|
| 614 |
-
function rasterize(svg, scale, done, fail) {
|
| 615 |
-
const width = Number(svg.getAttribute("width")), height = Number(svg.getAttribute("height"));
|
| 616 |
-
const img = new Image();
|
| 617 |
-
img.onload = () => {
|
| 618 |
-
const canvas = document.createElement("canvas");
|
| 619 |
-
canvas.width = Math.round(width * scale);
|
| 620 |
-
canvas.height = Math.round(height * scale);
|
| 621 |
-
const ctx = canvas.getContext("2d");
|
| 622 |
-
ctx.setTransform(scale, 0, 0, scale, 0, 0);
|
| 623 |
-
ctx.drawImage(img, 0, 0);
|
| 624 |
-
done(canvas, width, height);
|
| 625 |
-
};
|
| 626 |
-
img.onerror = fail;
|
| 627 |
-
img.src = "data:image/svg+xml;charset=utf-8,"
|
| 628 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg));
|
| 629 |
-
}
|
| 630 |
-
|
| 631 |
-
// A one-page PDF wrapping the rendered figure, written by hand: a library would
|
| 632 |
-
// cost this page its zero-dependency, single-file property. The image is stored
|
| 633 |
-
// losslessly (raw RGB + /FlateDecode via CompressionStream) and the page is sized
|
| 634 |
-
// in points to the figure's CSS size, so it prints at the size it appears here
|
| 635 |
-
// and the pixels land at 96*scale dpi.
|
| 636 |
-
async function buildPdf(canvas, cssWidth, cssHeight) {
|
| 637 |
-
const pixels = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height).data;
|
| 638 |
-
const rgb = new Uint8Array((pixels.length / 4) * 3);
|
| 639 |
-
for (let i = 0, j = 0; i < pixels.length; i += 4, j += 3) {
|
| 640 |
-
rgb[j] = pixels[i];
|
| 641 |
-
rgb[j + 1] = pixels[i + 1];
|
| 642 |
-
rgb[j + 2] = pixels[i + 2];
|
| 643 |
-
}
|
| 644 |
-
const deflated = new Uint8Array(await new Response(
|
| 645 |
-
new Blob([rgb]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
|
| 646 |
-
|
| 647 |
-
const encoder = new TextEncoder();
|
| 648 |
-
const chunks = [];
|
| 649 |
-
const offsets = [];
|
| 650 |
-
let cursor = 0;
|
| 651 |
-
const put = data => {
|
| 652 |
-
const bytes = typeof data === "string" ? encoder.encode(data) : data;
|
| 653 |
-
chunks.push(bytes);
|
| 654 |
-
cursor += bytes.length;
|
| 655 |
-
};
|
| 656 |
-
const object = (id, body, stream) => {
|
| 657 |
-
offsets[id] = cursor;
|
| 658 |
-
put(`${id} 0 obj\n${body}\n`);
|
| 659 |
-
if (stream) {
|
| 660 |
-
put("stream\n");
|
| 661 |
-
put(stream);
|
| 662 |
-
put("\nendstream\n");
|
| 663 |
-
}
|
| 664 |
-
put("endobj\n");
|
| 665 |
-
};
|
| 666 |
-
|
| 667 |
-
const ptW = (cssWidth * 0.75).toFixed(2), ptH = (cssHeight * 0.75).toFixed(2);
|
| 668 |
-
const content = `q ${ptW} 0 0 ${ptH} 0 0 cm /Im0 Do Q`;
|
| 669 |
-
put("%PDF-1.4\n");
|
| 670 |
-
put(new Uint8Array([0x25, 0xe2, 0xe3, 0xcf, 0xd3, 0x0a])); // binary marker
|
| 671 |
-
object(1, "<< /Type /Catalog /Pages 2 0 R >>");
|
| 672 |
-
object(2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>");
|
| 673 |
-
object(3, `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${ptW} ${ptH}] `
|
| 674 |
-
+ "/Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>");
|
| 675 |
-
object(4, "<< /Type /XObject /Subtype /Image "
|
| 676 |
-
+ `/Width ${canvas.width} /Height ${canvas.height} /ColorSpace /DeviceRGB `
|
| 677 |
-
+ `/BitsPerComponent 8 /Filter /FlateDecode /Length ${deflated.length} >>`, deflated);
|
| 678 |
-
object(5, `<< /Length ${content.length} >>`, content);
|
| 679 |
-
|
| 680 |
-
const xref = cursor;
|
| 681 |
-
let table = "xref\n0 6\n0000000000 65535 f \n";
|
| 682 |
-
for (let id = 1; id <= 5; id++) table += String(offsets[id]).padStart(10, "0") + " 00000 n \n";
|
| 683 |
-
put(table);
|
| 684 |
-
put(`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`);
|
| 685 |
-
return new Blob(chunks, { type: "application/pdf" });
|
| 686 |
-
}
|
| 687 |
-
|
| 688 |
-
// Wire up the export buttons; `getParts` is called per click so the file always
|
| 689 |
-
// matches what is on screen. Returns a `run(format)` the host page can drive.
|
| 690 |
-
function setUpExport(getParts, basename) {
|
| 691 |
-
const buttons = {
|
| 692 |
-
svg: document.getElementById("btn-svg"),
|
| 693 |
-
png: document.getElementById("btn-png"),
|
| 694 |
-
pdf: document.getElementById("btn-pdf"),
|
| 695 |
-
};
|
| 696 |
-
const figure = () => buildExportSvg(getParts(), document.getElementById("legendstrip"));
|
| 697 |
-
|
| 698 |
-
// A sandboxed frame has no modals, so a failure is reported on the button.
|
| 699 |
-
function complain(format) {
|
| 700 |
-
const button = buttons[format];
|
| 701 |
-
if (!button) return;
|
| 702 |
-
const label = button.textContent;
|
| 703 |
-
button.textContent = "failed";
|
| 704 |
-
setTimeout(() => { button.textContent = label; }, 2500);
|
| 705 |
-
}
|
| 706 |
-
|
| 707 |
-
function run(format) {
|
| 708 |
-
const svg = figure();
|
| 709 |
-
const name = basename();
|
| 710 |
-
if (format === "svg") {
|
| 711 |
-
downloadUrl("data:image/svg+xml;charset=utf-8,"
|
| 712 |
-
+ encodeURIComponent(new XMLSerializer().serializeToString(svg)), name + ".svg");
|
| 713 |
-
return;
|
| 714 |
-
}
|
| 715 |
-
// 3x for a screen-resolution PNG; 2x for the PDF, whose page is sized in
|
| 716 |
-
// points so the pixels already land near 200 dpi at print size.
|
| 717 |
-
rasterize(svg, format === "pdf" ? 2 : 3, (canvas, cssWidth, cssHeight) => {
|
| 718 |
-
if (format === "png") {
|
| 719 |
-
canvas.toBlob(blob => downloadUrl(URL.createObjectURL(blob), name + ".png"), "image/png");
|
| 720 |
-
} else {
|
| 721 |
-
buildPdf(canvas, cssWidth, cssHeight)
|
| 722 |
-
.then(blob => downloadUrl(URL.createObjectURL(blob), name + ".pdf"))
|
| 723 |
-
.catch(() => complain("pdf"));
|
| 724 |
-
}
|
| 725 |
-
}, () => complain(format));
|
| 726 |
-
}
|
| 727 |
-
|
| 728 |
-
for (const format of Object.keys(buttons)) {
|
| 729 |
-
if (buttons[format]) buttons[format].addEventListener("click", () => run(format));
|
| 730 |
-
}
|
| 731 |
-
// Embedded, the buttons live in the host's panel header (see main.taExport).
|
| 732 |
-
window.addEventListener("message", ev => {
|
| 733 |
-
const d = ev.data;
|
| 734 |
-
if (d && d.type === "tabarena-explorer-export" && buttons[d.format] !== undefined) run(d.format);
|
| 735 |
-
});
|
| 736 |
-
}
|
| 737 |
-
|
| 738 |
-
// When embedded, report the content height so the host page can size the
|
| 739 |
-
// iframe to fit (avoids an inner scrollbar). Works from a sandboxed frame.
|
| 740 |
-
// Measure the body (viewport-independent) — documentElement.scrollHeight is
|
| 741 |
-
// clamped to at least the iframe's current viewport, which turns the
|
| 742 |
-
// resize round-trip into a grow-forever feedback loop. The change guard
|
| 743 |
-
// stops re-posting once the height settles.
|
| 744 |
-
let lastPostedHeight = 0;
|
| 745 |
-
function postHeight() {
|
| 746 |
-
if (window.parent === window) return;
|
| 747 |
-
const height = Math.ceil(document.body.offsetHeight);
|
| 748 |
-
if (Math.abs(height - lastPostedHeight) < 3) return;
|
| 749 |
-
lastPostedHeight = height;
|
| 750 |
-
window.parent.postMessage({ type: "tabarena-explorer-height", height: height }, "*");
|
| 751 |
-
}
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
const TRAJECTORY = CONFIG.mode === "trajectory";
|
| 755 |
-
|
| 756 |
-
const titleEl = document.getElementById("title");
|
| 757 |
-
if (CONFIG.title) titleEl.textContent = CONFIG.title; else titleEl.hidden = true;
|
| 758 |
-
|
| 759 |
-
// Column order: chips/controls left of the chart, or mirrored.
|
| 760 |
-
document.getElementById("grid").classList.add(CONFIG.chipsSide === "right" ? "chips-right" : "chips-left");
|
| 761 |
-
|
| 762 |
-
const svg = document.getElementById("chart");
|
| 763 |
-
const box = document.getElementById("chartbox");
|
| 764 |
-
const chipsBox = document.getElementById("chips");
|
| 765 |
-
const controlsBox = document.querySelector(".controls");
|
| 766 |
-
const tip = makeTooltip(box);
|
| 767 |
-
|
| 768 |
-
// Marker glyph per variant at (cx, cy); trajectories use circles everywhere.
|
| 769 |
-
function drawMark(parent, cx, cy, variant, color, size, opacity, dataM, whiteStroke) {
|
| 770 |
-
const common = { opacity: opacity, "data-m": dataM };
|
| 771 |
-
let node;
|
| 772 |
-
if (TRAJECTORY || variant === "Default" || !variant) {
|
| 773 |
-
node = el("circle", { ...common, cx, cy, r: size, fill: color }, parent);
|
| 774 |
-
} else if (variant === "Tuned") {
|
| 775 |
-
const s = size * 1.75;
|
| 776 |
-
node = el("rect", { ...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1.5, fill: color }, parent);
|
| 777 |
-
} else if (variant === "Tuned + Ens.") {
|
| 778 |
-
const d = size * 0.95;
|
| 779 |
-
node = el("path", {
|
| 780 |
-
...common,
|
| 781 |
-
d: `M${cx - d},${cy - d} L${cx + d},${cy + d} M${cx - d},${cy + d} L${cx + d},${cy - d}`,
|
| 782 |
-
stroke: color, "stroke-width": size * 0.62, fill: "none", "stroke-linecap": "round",
|
| 783 |
-
}, parent);
|
| 784 |
-
} else {
|
| 785 |
-
// Any other variant (e.g. "Baseline", holdout types): diamond.
|
| 786 |
-
const s = size * 1.45;
|
| 787 |
-
node = el("rect", {
|
| 788 |
-
...common, x: cx - s / 2, y: cy - s / 2, width: s, height: s, rx: 1,
|
| 789 |
-
fill: color, transform: `rotate(45 ${cx} ${cy})`,
|
| 790 |
-
}, parent);
|
| 791 |
-
}
|
| 792 |
-
if (whiteStroke && variant !== "Tuned + Ens.") {
|
| 793 |
-
node.setAttribute("stroke", "var(--card)");
|
| 794 |
-
node.setAttribute("stroke-width", "1");
|
| 795 |
-
}
|
| 796 |
-
return node;
|
| 797 |
-
}
|
| 798 |
-
|
| 799 |
-
function drawImputedRing(parent, cx, cy, size, color, opacity, dataM) {
|
| 800 |
-
el("circle", {
|
| 801 |
-
cx, cy, r: size + 4.5, fill: "none", stroke: color, "stroke-width": 1.4,
|
| 802 |
-
"stroke-dasharray": "3 2.5", opacity: opacity, "data-m": dataM,
|
| 803 |
-
}, parent);
|
| 804 |
-
}
|
| 805 |
-
|
| 806 |
-
// Fat green arrow pointing into the optimal corner (mirrors the static
|
| 807 |
-
// figures' "Optimal" arrow so both read the same way).
|
| 808 |
-
function drawOptimalArrow(parent, lowerBetter, M, W, H) {
|
| 809 |
-
const cornerY = lowerBetter ? H - M.b - 12 : M.t + 12;
|
| 810 |
-
const tailY = lowerBetter ? H - M.b - 64 : M.t + 64;
|
| 811 |
-
const cx = M.l + 12, tx = M.l + 64;
|
| 812 |
-
const dx = cx - tx, dy = cornerY - tailY;
|
| 813 |
-
const len = Math.hypot(dx, dy);
|
| 814 |
-
const ux = dx / len, uy = dy / len;
|
| 815 |
-
const headLen = 16;
|
| 816 |
-
const bx = cx - ux * headLen, by = cornerY - uy * headLen; // head base center
|
| 817 |
-
// line stops at the head base
|
| 818 |
-
el("line", {
|
| 819 |
-
x1: tx, y1: tailY, x2: bx, y2: by,
|
| 820 |
-
stroke: "var(--optimal)", "stroke-width": 13, "stroke-linecap": "round", opacity: 0.92,
|
| 821 |
-
}, parent);
|
| 822 |
-
const px = -uy, py = ux; // perpendicular
|
| 823 |
-
el("polygon", {
|
| 824 |
-
points: `${cx},${cornerY} ${bx + px * 11},${by + py * 11} ${bx - px * 11},${by - py * 11}`,
|
| 825 |
-
fill: "var(--optimal)", opacity: 0.92,
|
| 826 |
-
}, parent);
|
| 827 |
-
let angle = Math.atan2(dy, dx) * 180 / Math.PI;
|
| 828 |
-
if (angle > 90 || angle < -90) angle += 180;
|
| 829 |
-
const mx = (tx + bx) / 2, my = (tailY + by) / 2;
|
| 830 |
-
const t = el("text", {
|
| 831 |
-
x: mx, y: my, "text-anchor": "middle", "dominant-baseline": "middle",
|
| 832 |
-
"font-size": 10.5, "font-weight": 700, fill: "#ffffff",
|
| 833 |
-
transform: `rotate(${angle} ${mx} ${my})`,
|
| 834 |
-
}, parent);
|
| 835 |
-
t.textContent = "Optimal";
|
| 836 |
-
}
|
| 837 |
-
|
| 838 |
-
// ---------- data ----------
|
| 839 |
-
const byMethod = new Map();
|
| 840 |
-
for (const p of POINTS) {
|
| 841 |
-
if (!byMethod.has(p.method)) byMethod.set(p.method, []);
|
| 842 |
-
byMethod.get(p.method).push(p); // insertion order = builder's point order
|
| 843 |
-
}
|
| 844 |
-
|
| 845 |
-
const METRICS = CONFIG.metrics;
|
| 846 |
-
let metricKey = METRICS[0].key;
|
| 847 |
-
const metricByKey = {};
|
| 848 |
-
for (const m of METRICS) metricByKey[m.key] = m;
|
| 849 |
-
|
| 850 |
-
// Single time axis per explorer (the scatter ships inference time, the
|
| 851 |
-
// trajectories train time).
|
| 852 |
-
const X_AXIS = CONFIG.xAxes[0];
|
| 853 |
-
const xKey = X_AXIS.key;
|
| 854 |
-
|
| 855 |
-
function mval(p, metric) { return p[metric.key]; }
|
| 856 |
-
|
| 857 |
-
function computeFront(metric) {
|
| 858 |
-
const xk = xKey;
|
| 859 |
-
const pts = [...POINTS].sort((a, b) =>
|
| 860 |
-
a[xk] - b[xk] || (metric.lowerBetter ? mval(a, metric) - mval(b, metric) : mval(b, metric) - mval(a, metric)));
|
| 861 |
-
const verts = [];
|
| 862 |
-
const methods = new Set();
|
| 863 |
-
let best = null;
|
| 864 |
-
for (const p of pts) {
|
| 865 |
-
const v = mval(p, metric);
|
| 866 |
-
if (best === null || (metric.lowerBetter ? v < best : v > best)) {
|
| 867 |
-
if (best !== null) verts.push([p[xk], best]);
|
| 868 |
-
verts.push([p[xk], v]);
|
| 869 |
-
best = v;
|
| 870 |
-
methods.add(p.method);
|
| 871 |
-
}
|
| 872 |
-
}
|
| 873 |
-
return { verts, methods };
|
| 874 |
-
}
|
| 875 |
-
|
| 876 |
-
const state = { active: new Set(computeFront(metricByKey[metricKey]).methods) };
|
| 877 |
-
|
| 878 |
-
// ---------- chart ----------
|
| 879 |
-
// A flat, fixed-height plot: two of these panels then fit on one screen.
|
| 880 |
-
const CHART_H = 400;
|
| 881 |
-
const M = { l: 62, r: 18, t: 14, b: 52 };
|
| 882 |
-
|
| 883 |
-
function render() {
|
| 884 |
-
const metric = metricByKey[metricKey];
|
| 885 |
-
svg.textContent = "";
|
| 886 |
-
const W = Math.max(360, Math.round(box.clientWidth));
|
| 887 |
-
const H = CHART_H;
|
| 888 |
-
svg.setAttribute("width", W);
|
| 889 |
-
svg.setAttribute("height", H);
|
| 890 |
-
// Keep the chip list from outgrowing the chart beside it.
|
| 891 |
-
chipsBox.style.maxHeight = Math.max(170, H - controlsBox.offsetHeight + 20) + "px";
|
| 892 |
-
|
| 893 |
-
// x scale (log)
|
| 894 |
-
const xsAll = POINTS.map(p => p[xKey]);
|
| 895 |
-
const xmin = Math.min(...xsAll) * 0.65, xmax = Math.max(...xsAll) * 1.6;
|
| 896 |
-
const lx0 = Math.log10(xmin), lx1 = Math.log10(xmax);
|
| 897 |
-
const X = v => M.l + (Math.log10(v) - lx0) / (lx1 - lx0) * (W - M.l - M.r);
|
| 898 |
-
|
| 899 |
-
const vals = POINTS.map(p => mval(p, metric));
|
| 900 |
-
let y0, y1;
|
| 901 |
-
if (metric.fromZero) {
|
| 902 |
-
y0 = 0; y1 = Math.max(...vals) * 1.07;
|
| 903 |
-
} else {
|
| 904 |
-
const pad = (Math.max(...vals) - Math.min(...vals)) * 0.07;
|
| 905 |
-
y0 = Math.min(...vals) - pad; y1 = Math.max(...vals) + pad;
|
| 906 |
-
}
|
| 907 |
-
const Y = v => M.t + (1 - (v - y0) / (y1 - y0)) * (H - M.t - M.b);
|
| 908 |
-
|
| 909 |
-
// grid + axes
|
| 910 |
-
const grid = el("g", {}, svg);
|
| 911 |
-
for (let e = Math.ceil(lx0); Math.pow(10, e) < xmax; e++) {
|
| 912 |
-
const gx = X(Math.pow(10, e));
|
| 913 |
-
el("line", { x1: gx, y1: M.t, x2: gx, y2: H - M.b, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 914 |
-
const lbl = fmtNum(Math.pow(10, e), e >= 0 ? 0 : -e);
|
| 915 |
-
el("text", { x: gx, y: H - M.b + 20, "text-anchor": "middle", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 916 |
-
.textContent = lbl;
|
| 917 |
-
}
|
| 918 |
-
for (const yv of ticks(y0, y1, 6)) {
|
| 919 |
-
const gy = Y(yv);
|
| 920 |
-
el("line", { x1: M.l, y1: gy, x2: W - M.r, y2: gy, stroke: "var(--line)", "stroke-width": 1 }, grid);
|
| 921 |
-
el("text", { x: M.l - 8, y: gy + 4, "text-anchor": "end", "font-size": 12.5, fill: "var(--muted)" }, grid)
|
| 922 |
-
.textContent = fmtNum(yv, Number.isInteger(yv) ? 0 : metric.decimals);
|
| 923 |
-
}
|
| 924 |
-
el("rect", { x: M.l, y: M.t, width: W - M.l - M.r, height: H - M.t - M.b, fill: "none", stroke: "var(--line)" }, grid);
|
| 925 |
-
el("text", {
|
| 926 |
-
x: (M.l + W - M.r) / 2, y: H - 10, "text-anchor": "middle", "font-size": 14,
|
| 927 |
-
"font-weight": 650, fill: "var(--ink)",
|
| 928 |
-
}, grid).textContent = X_AXIS.axisLabel;
|
| 929 |
-
el("text", {
|
| 930 |
-
x: 0, y: 0, "text-anchor": "middle", "font-size": 14, "font-weight": 650, fill: "var(--ink)",
|
| 931 |
-
transform: `translate(16 ${(M.t + H - M.b) / 2}) rotate(-90)`,
|
| 932 |
-
}, grid).textContent = metric.axisLabel;
|
| 933 |
-
|
| 934 |
-
drawOptimalArrow(grid, metric.lowerBetter, M, W, H);
|
| 935 |
-
|
| 936 |
-
// pareto front (always shown)
|
| 937 |
-
const front = computeFront(metric);
|
| 938 |
-
const fv = front.verts;
|
| 939 |
-
if (fv.length) {
|
| 940 |
-
let d = `M${X(fv[0][0])},${metric.lowerBetter ? M.t : H - M.b}`;
|
| 941 |
-
for (const [fx, fy] of fv) d += ` L${X(fx)},${Y(fy)}`;
|
| 942 |
-
d += ` L${W - M.r},${Y(fv[fv.length - 1][1])}`;
|
| 943 |
-
el("path", { d, fill: "none", stroke: "var(--ink)", "stroke-width": 1.6, "stroke-dasharray": "7 5", opacity: 0.85 }, svg);
|
| 944 |
-
}
|
| 945 |
-
|
| 946 |
-
const isOn = m => state.active.has(m);
|
| 947 |
-
|
| 948 |
-
// connectors: variant links (scatter) / the trajectory itself
|
| 949 |
-
const conn = el("g", {}, svg);
|
| 950 |
-
for (const [method, pts] of byMethod) {
|
| 951 |
-
if (pts.length < 2) continue;
|
| 952 |
-
const on = isOn(method);
|
| 953 |
-
if (!TRAJECTORY && !on) continue; // scatter: connectors only for active methods
|
| 954 |
-
const dd = pts.map((p, i) => `${i ? "L" : "M"}${X(p[xKey])},${Y(mval(p, metric))}`).join(" ");
|
| 955 |
-
el("path", {
|
| 956 |
-
d: dd, fill: "none",
|
| 957 |
-
stroke: on ? FAM_VAR[pts[0].family] : "var(--pt-muted)",
|
| 958 |
-
"stroke-width": on ? (TRAJECTORY ? 2 : 1.4) : 1,
|
| 959 |
-
opacity: on ? 0.6 : 0.35,
|
| 960 |
-
"data-m": method,
|
| 961 |
-
}, conn);
|
| 962 |
-
}
|
| 963 |
-
|
| 964 |
-
// points: inactive first, active on top
|
| 965 |
-
const ptsOff = el("g", {}, svg);
|
| 966 |
-
const ptsOn = el("g", {}, svg);
|
| 967 |
-
for (const [method, pts] of byMethod) {
|
| 968 |
-
const on = isOn(method);
|
| 969 |
-
for (const p of pts) {
|
| 970 |
-
const color = on ? FAM_VAR[p.family] : "var(--pt-muted)";
|
| 971 |
-
const size = (on ? 7 : 5) * (TRAJECTORY ? 0.8 : 1);
|
| 972 |
-
const op = on ? 0.95 : 0.5;
|
| 973 |
-
drawMark(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), p.variant, color, size, op, p.method, on);
|
| 974 |
-
// Imputation ring: every affected point in scatter mode; only the
|
| 975 |
-
// trajectory's end point in trajectory mode (a ring on all ~8 line
|
| 976 |
-
// points would read as beads, and the chip's ‡ already flags the line).
|
| 977 |
-
if (p.imputed && (!TRAJECTORY || p === pts[pts.length - 1])) {
|
| 978 |
-
drawImputedRing(on ? ptsOn : ptsOff, X(p[xKey]), Y(mval(p, metric)), size, color, op, p.method);
|
| 979 |
-
}
|
| 980 |
-
}
|
| 981 |
-
}
|
| 982 |
-
|
| 983 |
-
// labels for active methods at their best point, greedy de-overlap
|
| 984 |
-
const labels = [];
|
| 985 |
-
for (const [method, pts] of byMethod) {
|
| 986 |
-
if (!isOn(method)) continue;
|
| 987 |
-
const best = pts.reduce((a, b) =>
|
| 988 |
-
(metric.lowerBetter ? mval(a, metric) < mval(b, metric) : mval(a, metric) > mval(b, metric)) ? a : b);
|
| 989 |
-
labels.push({ method, family: best.family, x: X(best[xKey]) + 10, y: Y(mval(best, metric)) - 10 });
|
| 990 |
-
}
|
| 991 |
-
labels.sort((a, b) => a.y - b.y);
|
| 992 |
-
for (let i = 1; i < labels.length; i++) {
|
| 993 |
-
for (let j = 0; j < i; j++) {
|
| 994 |
-
if (Math.abs(labels[i].x - labels[j].x) < 110 && Math.abs(labels[i].y - labels[j].y) < 15) {
|
| 995 |
-
labels[i].y = labels[j].y + 15;
|
| 996 |
-
}
|
| 997 |
-
}
|
| 998 |
-
}
|
| 999 |
-
const lg = el("g", {}, svg);
|
| 1000 |
-
for (const l of labels) {
|
| 1001 |
-
const t = el("text", {
|
| 1002 |
-
x: Math.min(l.x, W - M.r - 8), y: Math.max(l.y, M.t + 12), "font-size": 13, "font-weight": 700,
|
| 1003 |
-
fill: FAM_VAR[l.family], "paint-order": "stroke", stroke: "var(--card)", "stroke-width": 3.5,
|
| 1004 |
-
"text-anchor": l.x > W - 120 ? "end" : "start",
|
| 1005 |
-
}, lg);
|
| 1006 |
-
t.textContent = l.method;
|
| 1007 |
-
}
|
| 1008 |
-
|
| 1009 |
-
// invisible hit targets on top (bigger than marks)
|
| 1010 |
-
const hits = el("g", {}, svg);
|
| 1011 |
-
for (const p of POINTS) {
|
| 1012 |
-
const h = el("circle", { cx: X(p[xKey]), cy: Y(mval(p, metric)), r: 12, fill: "transparent", cursor: "pointer" }, hits);
|
| 1013 |
-
h.addEventListener("mouseenter", ev => showTip(p, ev));
|
| 1014 |
-
h.addEventListener("mousemove", ev => tip.move(ev));
|
| 1015 |
-
h.addEventListener("mouseleave", () => hideTip(p.method));
|
| 1016 |
-
h.addEventListener("click", () => toggle(p.method));
|
| 1017 |
-
}
|
| 1018 |
-
}
|
| 1019 |
-
|
| 1020 |
-
// Temporary hover emphasis without a re-render (a re-render would replace
|
| 1021 |
-
// the hit node under the cursor mid-hover).
|
| 1022 |
-
function emphasize(method, on) {
|
| 1023 |
-
svg.querySelectorAll(`[data-m="${CSS.escape(method)}"]`).forEach(n => {
|
| 1024 |
-
if (on) {
|
| 1025 |
-
if (!n.dataset.save) n.dataset.save = n.getAttribute("opacity") || "1";
|
| 1026 |
-
n.setAttribute("opacity", "0.95");
|
| 1027 |
-
} else if (n.dataset.save) {
|
| 1028 |
-
n.setAttribute("opacity", n.dataset.save);
|
| 1029 |
-
delete n.dataset.save;
|
| 1030 |
-
}
|
| 1031 |
-
});
|
| 1032 |
-
}
|
| 1033 |
-
|
| 1034 |
-
function showTip(p, ev) {
|
| 1035 |
-
emphasize(p.method, true);
|
| 1036 |
-
const sub = TRAJECTORY ? (p.n_configs != null ? `${p.n_configs} configs` : "") : (p.variant || "");
|
| 1037 |
-
let html = `<div class="t-name">${p.method}` + (sub ? ` <span class="t-var">(${sub})</span>` : "") + "</div>" +
|
| 1038 |
-
`<div>${p.family}</div>`;
|
| 1039 |
-
for (const m of METRICS) {
|
| 1040 |
-
html += `<div>${m.label}: <b>${fmtMetric(m, mval(p, m))}</b></div>`;
|
| 1041 |
-
}
|
| 1042 |
-
html += `<div>${X_AXIS.short}: <b>${fmtTime(p[xKey])}</b></div>`;
|
| 1043 |
-
if (p.imputed) html += `<div class="t-imp">Imputed on ${fmtNum(p.imputed_pct, 0)}% of datasets</div>`;
|
| 1044 |
-
tip.show(html, ev);
|
| 1045 |
-
}
|
| 1046 |
-
function hideTip(method) {
|
| 1047 |
-
emphasize(method, false);
|
| 1048 |
-
tip.hide();
|
| 1049 |
-
}
|
| 1050 |
-
|
| 1051 |
-
// ---------- chips ----------
|
| 1052 |
-
const chipByMethod = new Map();
|
| 1053 |
-
const famChips = new Map();
|
| 1054 |
-
function familyMethods(fam) {
|
| 1055 |
-
return [...byMethod.keys()].filter(m => byMethod.get(m)[0].family === fam);
|
| 1056 |
-
}
|
| 1057 |
-
// Chips are listed by leaderboard rank — best Elo first when Elo is
|
| 1058 |
-
// configured, otherwise best value of the primary metric.
|
| 1059 |
-
const RANK_METRIC = metricByKey["elo"] || metricByKey[METRICS[0].key];
|
| 1060 |
-
function bestVal(method) {
|
| 1061 |
-
const vals = byMethod.get(method).map(p => mval(p, RANK_METRIC));
|
| 1062 |
-
return RANK_METRIC.lowerBetter ? Math.min(...vals) : Math.max(...vals);
|
| 1063 |
-
}
|
| 1064 |
-
function rankSorted(methods) {
|
| 1065 |
-
return [...methods].sort((a, b) =>
|
| 1066 |
-
RANK_METRIC.lowerBetter ? bestVal(a) - bestVal(b) : bestVal(b) - bestVal(a));
|
| 1067 |
-
}
|
| 1068 |
-
function buildChips() {
|
| 1069 |
-
for (const fam of FAM_ORDER) {
|
| 1070 |
-
const methods = rankSorted(familyMethods(fam));
|
| 1071 |
-
if (!methods.length) continue;
|
| 1072 |
-
const row = document.createElement("div");
|
| 1073 |
-
row.className = "chiprow";
|
| 1074 |
-
const famBtn = document.createElement("button");
|
| 1075 |
-
famBtn.className = "famchip";
|
| 1076 |
-
famBtn.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1077 |
-
famBtn.innerHTML = famChipLabel(fam, methods.length);
|
| 1078 |
-
famBtn.title = `Toggle all ${methods.length} ${fam} methods`;
|
| 1079 |
-
famBtn.addEventListener("click", () => toggleFamily(fam));
|
| 1080 |
-
row.appendChild(famBtn);
|
| 1081 |
-
famChips.set(fam, famBtn);
|
| 1082 |
-
const set = document.createElement("div");
|
| 1083 |
-
set.className = "chipset";
|
| 1084 |
-
for (const m of methods) {
|
| 1085 |
-
const b = document.createElement("button");
|
| 1086 |
-
b.className = "chip";
|
| 1087 |
-
b.style.setProperty("--fam", FAM_VAR[fam]);
|
| 1088 |
-
const imputed = byMethod.get(m).some(p => p.imputed);
|
| 1089 |
-
const label = document.createElement("span");
|
| 1090 |
-
label.textContent = m;
|
| 1091 |
-
b.appendChild(Object.assign(document.createElement("span"), { className: "dot" }));
|
| 1092 |
-
b.appendChild(label);
|
| 1093 |
-
if (imputed) {
|
| 1094 |
-
const mark = document.createElement("span");
|
| 1095 |
-
mark.className = "imp-mark";
|
| 1096 |
-
mark.textContent = "‡";
|
| 1097 |
-
b.appendChild(mark);
|
| 1098 |
-
}
|
| 1099 |
-
b.title = m + (imputed ? " — partially imputed" : "");
|
| 1100 |
-
b.addEventListener("click", () => toggle(m));
|
| 1101 |
-
set.appendChild(b);
|
| 1102 |
-
chipByMethod.set(m, b);
|
| 1103 |
-
}
|
| 1104 |
-
row.appendChild(set);
|
| 1105 |
-
chipsBox.appendChild(row);
|
| 1106 |
-
}
|
| 1107 |
-
}
|
| 1108 |
-
function syncChips() {
|
| 1109 |
-
for (const [m, b] of chipByMethod) b.setAttribute("aria-pressed", String(state.active.has(m)));
|
| 1110 |
-
for (const [fam, b] of famChips) {
|
| 1111 |
-
b.setAttribute("aria-pressed", String(familyMethods(fam).every(m => state.active.has(m))));
|
| 1112 |
-
}
|
| 1113 |
-
}
|
| 1114 |
-
function toggle(m) {
|
| 1115 |
-
if (state.active.has(m)) state.active.delete(m); else state.active.add(m);
|
| 1116 |
-
syncChips();
|
| 1117 |
-
render();
|
| 1118 |
-
}
|
| 1119 |
-
function toggleFamily(fam) {
|
| 1120 |
-
const methods = familyMethods(fam);
|
| 1121 |
-
const allOn = methods.every(m => state.active.has(m));
|
| 1122 |
-
for (const m of methods) {
|
| 1123 |
-
if (allOn) state.active.delete(m); else state.active.add(m);
|
| 1124 |
-
}
|
| 1125 |
-
syncChips();
|
| 1126 |
-
render();
|
| 1127 |
-
}
|
| 1128 |
-
function setActive(methods) {
|
| 1129 |
-
state.active = new Set(methods);
|
| 1130 |
-
syncChips();
|
| 1131 |
-
render();
|
| 1132 |
-
}
|
| 1133 |
-
document.getElementById("btn-front").addEventListener("click",
|
| 1134 |
-
() => setActive(computeFront(metricByKey[metricKey]).methods));
|
| 1135 |
-
document.getElementById("btn-all").addEventListener("click", () => setActive([...byMethod.keys()]));
|
| 1136 |
-
document.getElementById("btn-none").addEventListener("click", () => setActive([]));
|
| 1137 |
-
|
| 1138 |
-
// metric selector (hidden when only one metric is configured)
|
| 1139 |
-
const metricPick = document.getElementById("metricpick");
|
| 1140 |
-
const metricSelect = document.getElementById("metric-select");
|
| 1141 |
-
if (METRICS.length > 1) {
|
| 1142 |
-
metricPick.hidden = false;
|
| 1143 |
-
for (const m of METRICS) {
|
| 1144 |
-
const opt = document.createElement("option");
|
| 1145 |
-
opt.value = m.key;
|
| 1146 |
-
opt.textContent = m.label;
|
| 1147 |
-
metricSelect.appendChild(opt);
|
| 1148 |
-
}
|
| 1149 |
-
metricSelect.addEventListener("change", ev => {
|
| 1150 |
-
metricKey = ev.target.value;
|
| 1151 |
-
render();
|
| 1152 |
-
});
|
| 1153 |
-
}
|
| 1154 |
-
|
| 1155 |
-
// ---------- legend strip ----------
|
| 1156 |
-
function buildLegend() {
|
| 1157 |
-
const box2 = document.getElementById("legendstrip");
|
| 1158 |
-
let html = "";
|
| 1159 |
-
if (!TRAJECTORY) {
|
| 1160 |
-
html +=
|
| 1161 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><circle cx="7" cy="7" r="5" fill="var(--muted)"/></svg> Default</span>' +
|
| 1162 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" rx="1.5" fill="var(--muted)"/></svg> Tuned</span>' +
|
| 1163 |
-
'<span class="item"><svg width="14" height="14" viewBox="0 0 14 14"><path d="M3,3 L11,11 M3,11 L11,3" stroke="var(--muted)" stroke-width="2.6" stroke-linecap="round"/></svg> Tuned + Ensembled</span>';
|
| 1164 |
-
} else {
|
| 1165 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--muted)" stroke-width="2"/><circle cx="6" cy="4" r="2.6" fill="var(--muted)"/><circle cx="16" cy="4" r="2.6" fill="var(--muted)"/></svg> Tuning trajectory (more configs → more time)</span>';
|
| 1166 |
-
}
|
| 1167 |
-
html += '<span class="item"><svg width="26" height="8" viewBox="0 0 26 8"><line x1="0" y1="4" x2="26" y2="4" stroke="var(--ink)" stroke-width="1.6" stroke-dasharray="6 4"/></svg> Pareto front (always shown)</span>';
|
| 1168 |
-
if (POINTS.some(p => p.imputed)) {
|
| 1169 |
-
html += '<span class="item"><svg width="18" height="18" viewBox="0 0 18 18"><circle cx="9" cy="9" r="4" fill="var(--muted)"/><circle cx="9" cy="9" r="7.5" fill="none" stroke="var(--muted)" stroke-width="1.3" stroke-dasharray="3 2.5"/></svg> ‡ partially imputed</span>';
|
| 1170 |
-
}
|
| 1171 |
-
// Model family, named: highlighted points are colored by family, and in paper
|
| 1172 |
-
// view the chip list that would otherwise decode them is hidden.
|
| 1173 |
-
const families = FAM_ORDER.filter(f => POINTS.some(p => p.family === f));
|
| 1174 |
-
if (families.length > 1) {
|
| 1175 |
-
html += '<span class="legendbreak"></span><span class="item">Family:</span>';
|
| 1176 |
-
for (const fam of families) {
|
| 1177 |
-
html += `<span class="item"><svg width="12" height="12" viewBox="0 0 12 12">` +
|
| 1178 |
-
`<circle cx="6" cy="6" r="5" fill="${FAM_VAR[fam]}"/></svg> ` +
|
| 1179 |
-
`<span style="color:${FAM_INK[fam]}">${fam}</span></span>`;
|
| 1180 |
-
}
|
| 1181 |
-
}
|
| 1182 |
-
box2.innerHTML = html;
|
| 1183 |
-
}
|
| 1184 |
-
|
| 1185 |
-
// ---------- paper view ----------
|
| 1186 |
-
setUpPaperView(render);
|
| 1187 |
-
setUpExport(() => [{ svg: svg, dx: 0 }], () => slugify(document.title));
|
| 1188 |
-
|
| 1189 |
-
// ---------- data table ----------
|
| 1190 |
-
function buildTable() {
|
| 1191 |
-
const m0 = metricByKey[METRICS[0].key];
|
| 1192 |
-
const rows = [...POINTS].sort((a, b) =>
|
| 1193 |
-
m0.lowerBetter ? mval(a, m0) - mval(b, m0) : mval(b, m0) - mval(a, m0));
|
| 1194 |
-
let html = "<table><thead><tr><th>Method</th>";
|
| 1195 |
-
html += TRAJECTORY ? "<th>Configs</th>" : "<th>Variant</th>";
|
| 1196 |
-
html += "<th>Family</th>";
|
| 1197 |
-
for (const m of METRICS) html += `<th>${m.label}</th>`;
|
| 1198 |
-
html += `<th>${X_AXIS.short}</th><th>Imputed</th></tr></thead><tbody>`;
|
| 1199 |
-
for (const p of rows) {
|
| 1200 |
-
html += `<tr><td>${p.method}</td><td>${TRAJECTORY ? (p.n_configs != null ? p.n_configs : "—") : p.variant}</td><td>${p.family}</td>`;
|
| 1201 |
-
for (const m of METRICS) html += `<td>${fmtMetric(m, mval(p, m))}</td>`;
|
| 1202 |
-
html += `<td>${fmtNum(p[xKey], 3)}</td>`;
|
| 1203 |
-
html += `<td>${p.imputed ? fmtNum(p.imputed_pct, 0) + "%" : "—"}</td></tr>`;
|
| 1204 |
-
}
|
| 1205 |
-
html += "</tbody></table>";
|
| 1206 |
-
document.getElementById("tblwrap").innerHTML = html;
|
| 1207 |
-
}
|
| 1208 |
-
|
| 1209 |
-
const _renderInner = render;
|
| 1210 |
-
render = function () {
|
| 1211 |
-
_renderInner();
|
| 1212 |
-
postHeight();
|
| 1213 |
-
};
|
| 1214 |
-
document.querySelector("details.datatable").addEventListener("toggle", postHeight);
|
| 1215 |
-
let resizeTimer = null;
|
| 1216 |
-
window.addEventListener("resize", () => {
|
| 1217 |
-
clearTimeout(resizeTimer);
|
| 1218 |
-
resizeTimer = setTimeout(render, 120);
|
| 1219 |
-
});
|
| 1220 |
-
window.addEventListener("load", postHeight);
|
| 1221 |
-
|
| 1222 |
-
buildChips();
|
| 1223 |
-
buildLegend();
|
| 1224 |
-
buildTable();
|
| 1225 |
-
syncChips();
|
| 1226 |
-
render();
|
| 1227 |
-
})();
|
| 1228 |
-
</script>
|
| 1229 |
-
</body>
|
| 1230 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/pareto_front_improvability_vs_time_infer.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:cf51441148edad29a2482f34433c299274409cb28be2a14cf7f3dc0c47832872
|
| 3 |
-
size 275180
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/pareto_front_points.csv
DELETED
|
@@ -1,63 +0,0 @@
|
|
| 1 |
-
method,variant,family,x_infer,x_train,imp,elo,imputed,imputed_pct
|
| 2 |
-
TabFM,Default,Foundation Model,5.357838133261318,39.5720422516442,4.654355254106112,1743.7,False,0.0
|
| 3 |
-
TabPFN-3,Default,Foundation Model,0.4158216638576948,9.169929954447653,10.76580500520397,1636.0,False,0.0
|
| 4 |
-
TabPFN-2.6,Default,Foundation Model,0.5482886619733942,7.034289077293122,11.96074156251044,1599.2,False,0.0
|
| 5 |
-
RealTabPFN-2.5,Tuned + Ens.,Foundation Model,8.047594848219795,2289.3887157667205,11.197577244820794,1595.2,False,0.0
|
| 6 |
-
TabICLv2,Default,Foundation Model,0.1520731744535504,3.9320097545321064,11.560408578460901,1572.2,False,0.0
|
| 7 |
-
RealTabPFN-2.5,Tuned,Foundation Model,1.1425914844543796,2289.3887157667205,11.907118072301099,1555.4,False,0.0
|
| 8 |
-
RealTabPFN-2.5,Default,Foundation Model,0.6362272807949252,6.7587899978217045,12.320088737585506,1541.9,False,0.0
|
| 9 |
-
RealMLP,Tuned + Ens.,Neural Network,21.902496279105236,3771.8540221067997,14.53336029824196,1479.7,False,0.0
|
| 10 |
-
TabDPT-Turbo,Default,Foundation Model,0.19227067519018423,4.691113094573359,15.329550194505407,1448.5,False,0.0
|
| 11 |
-
TabDPT,Tuned + Ens.,Foundation Model,218.45336407352897,5119.776985103065,15.246470826087291,1448.0,False,0.0
|
| 12 |
-
TabM,Tuned + Ens.,Neural Network,3.8381409685971137,2585.579863640918,15.6750950369016,1429.1,False,0.0
|
| 13 |
-
TabDPT,Tuned,Foundation Model,28.351340383207884,5119.776985103065,15.883723432046265,1415.3,False,0.0
|
| 14 |
-
LimiX,Default,Foundation Model,6.828482678301318,35.50961056314309,15.154885083708347,1405.3,False,0.0
|
| 15 |
-
RealMLP,Tuned,Neural Network,1.7776750936346917,3771.8540221067997,15.90978346527886,1399.9,False,0.0
|
| 16 |
-
LightGBM,Tuned + Ens.,Tree-based,2.5704534160747796,892.4854074789564,16.936687658650524,1389.8,False,0.0
|
| 17 |
-
TabM,Tuned,Neural Network,0.4361574183230644,2585.579863640918,16.56097328725307,1373.4,False,0.0
|
| 18 |
-
CatBoost,Tuned + Ens.,Tree-based,0.39602676030046535,1739.1690497297914,17.040642856753067,1367.6,False,0.0
|
| 19 |
-
TabSwift,Default,Foundation Model,0.05791268987655686,2.756051243933877,17.22410804787243,1363.2,False,0.0
|
| 20 |
-
iLTM,Tuned + Ens.,Foundation Model,841.445890748085,22811.744051243128,17.42147869511167,1361.3,False,0.0
|
| 21 |
-
CatBoost,Tuned,Tree-based,0.050853266781756806,1739.1690497297914,17.278859448847676,1354.2,False,0.0
|
| 22 |
-
LightGBM,Tuned,Tree-based,0.3458375857654502,892.4854074789564,17.38939889928507,1353.4,False,0.0
|
| 23 |
-
TabDPT,Default,Foundation Model,43.707401035938005,50.32502415266903,18.02306483084254,1331.6,False,0.0
|
| 24 |
-
xRFM,Tuned + Ens.,Other,2.9395549707468733,1126.9686387245144,17.868361221740837,1330.4,False,0.0
|
| 25 |
-
XGBoost,Tuned + Ens.,Tree-based,2.3674863948529943,884.4808277373293,17.92374283473731,1324.7,False,0.0
|
| 26 |
-
ModernNCA,Tuned,Neural Network,0.5053503954101921,6523.550336157642,18.056130336227604,1323.4,False,0.0
|
| 27 |
-
ModernNCA,Tuned + Ens.,Neural Network,8.390322625318314,6523.550336157642,18.318760983199105,1323.2,False,0.0
|
| 28 |
-
CatBoost,Default,Tree-based,0.0455896073914258,8.462590335549091,18.2032871809493,1320.5,False,0.0
|
| 29 |
-
SAP-RPT-OSS,Default,Foundation Model,1.2773508676992504,16.230459759105607,18.838837170210166,1319.4,False,0.0
|
| 30 |
-
XGBoost,Tuned,Tree-based,0.3929683730676072,884.4808277373293,18.132841379402812,1306.4,False,0.0
|
| 31 |
-
TabM,Default,Neural Network,0.4449377919636944,9.936009218949234,18.257834368806115,1295.8,False,0.0
|
| 32 |
-
xRFM,Tuned,Other,0.16324468073957168,1126.9686387245144,18.89381823983451,1282.4,False,0.0
|
| 33 |
-
ChimeraBoost,Tuned + Ens.,Tree-based,0.45490386498083757,1218.8724153795765,19.516024658787416,1278.2,False,0.0
|
| 34 |
-
TorchMLP,Tuned + Ens.,Neural Network,2.1570271396274556,3865.9507169384297,19.12433023409986,1260.5,False,0.0
|
| 35 |
-
ChimeraBoost,Tuned,Tree-based,0.03598330933688246,1218.8724153795765,19.80334339083033,1259.9,False,0.0
|
| 36 |
-
EBM,Tuned + Ens.,Tree-based,0.15296939610611437,2499.3997394448907,19.95446510594069,1259.8,False,0.0
|
| 37 |
-
iLTM,Tuned,Foundation Model,161.22064740025013,22811.744051243128,19.245205487016797,1257.7,False,0.0
|
| 38 |
-
ModernNCA,Default,Neural Network,0.32060068900263267,16.279623910227823,21.22087021471567,1237.3,False,0.0
|
| 39 |
-
EBM,Tuned,Tree-based,0.017293833845938654,2499.3997394448907,20.51054592802531,1230.9,False,0.0
|
| 40 |
-
RealMLP,Default,Neural Network,4.688867646313849,15.69323516601608,20.018466958314622,1221.0,False,0.0
|
| 41 |
-
ChimeraBoost,Default,Tree-based,0.04138894865138677,5.4899520078266,20.940984645291863,1216.2,False,0.0
|
| 42 |
-
FastaiMLP,Tuned + Ens.,Neural Network,8.068837476686,1679.3959423676156,20.712381049385332,1214.1,False,0.0
|
| 43 |
-
ExtraTrees,Tuned + Ens.,Tree-based,1.501127939369875,822.5846846042664,21.641215765915888,1210.9,False,0.0
|
| 44 |
-
EBM,Default,Tree-based,0.017156058727181196,7.388420291453219,21.249349120209597,1203.0,False,0.0
|
| 45 |
-
TorchMLP,Tuned,Neural Network,0.14743941123732562,3865.9507169384297,20.861592718401972,1195.6,False,0.0
|
| 46 |
-
ExtraTrees,Tuned,Tree-based,0.21369237168913796,822.5846846042664,22.339109350750974,1187.0,False,0.0
|
| 47 |
-
LightGBM,Default,Tree-based,0.1695753132718836,3.608651599211503,21.229482732106593,1166.0,False,0.0
|
| 48 |
-
FastaiMLP,Tuned,Neural Network,0.8257869199912973,1679.3959423676156,21.847378167043086,1164.8,False,0.0
|
| 49 |
-
XGBoost,Default,Tree-based,0.2525411892114416,3.2873922338088355,21.244225857245823,1163.3,False,0.0
|
| 50 |
-
RandomForest,Tuned + Ens.,Tree-based,1.4602306270544885,590.0394439850668,23.21550916091867,1149.5,False,0.0
|
| 51 |
-
TabSTAR,Tuned,Foundation Model,5.606208042584258,40848.86657483013,25.49143698118923,1131.8,False,0.0
|
| 52 |
-
TabSTAR,Tuned + Ens.,Foundation Model,25.936207253387835,40848.86657483013,25.524817856764482,1130.2,False,0.0
|
| 53 |
-
RandomForest,Tuned,Tree-based,0.15030078963359184,590.0394439850668,23.948032253297473,1113.3,False,0.0
|
| 54 |
-
PerpetualBooster,Tuned + Ens.,Tree-based,0.8948102983830184,342.03900946680346,28.450886617554755,1083.5,False,0.0
|
| 55 |
-
iLTM,Default,Foundation Model,161.81343832142903,524.4765295003572,24.91360249315293,1066.4,False,0.0
|
| 56 |
-
TorchMLP,Default,Neural Network,0.1550906391981672,13.688894957032199,24.760902778404247,1057.8,False,0.0
|
| 57 |
-
PerpetualBooster,Tuned,Tree-based,0.3125464363490111,342.03900946680346,29.907678995353514,1048.2,False,0.0
|
| 58 |
-
xRFM,Default,Other,1.0976028857093967,5.446030178240368,26.63871042030792,1043.3,False,0.0
|
| 59 |
-
TabSTAR,Default,Foundation Model,7.213726442305473,471.6614585494219,30.359879360159113,1033.2,False,0.0
|
| 60 |
-
ExtraTrees,Default,Tree-based,0.5663988088013532,4.194175284298607,27.587751498606593,1019.7,False,0.0
|
| 61 |
-
RandomForest,Default,Tree-based,0.08856487680890945,0.5088535014091562,28.376526703294413,1000.0,False,0.0
|
| 62 |
-
FastaiMLP,Default,Neural Network,0.6842938244078286,5.483894573958628,26.85583180391888,999.9,False,0.0
|
| 63 |
-
PerpetualBooster,Default,Tree-based,0.040657078690582577,39.09071168560041,32.716605091837856,946.6,False,0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/pareto_n_configs_imp.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:9c8e41934eb6ef16329d06ac04b8db793c65701922a4ad688d432cf4ddb3cb84
|
| 3 |
-
size 284634
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/tuning-impact-elo.png.zip
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:c4d225aebd506c0101a8f80663ba3b30195fb7255fe829dd3f88480bd4c9791a
|
| 3 |
-
size 105251
|
|
|
|
|
|
|
|
|
|
|
|
data/imputation_no/splits_all/tasks_all/datasets_small/tuning_trajectories.csv
DELETED
|
@@ -1,163 +0,0 @@
|
|
| 1 |
-
method,family,x_train,x_infer,imp,elo,n_configs,imputed,imputed_pct
|
| 2 |
-
CatBoost,Tree-based,8.462590335549091,0.0455896073914258,18.22801872127607,1332.9,1.0,False,0.0
|
| 3 |
-
CatBoost,Tree-based,20.346193555734267,0.09660970481496081,17.61917864571887,1359.4,2.0,False,0.0
|
| 4 |
-
CatBoost,Tree-based,49.72308624090884,0.18065285816060878,17.253007428845667,1378.3,5.0,False,0.0
|
| 5 |
-
CatBoost,Tree-based,92.48508500945157,0.23983440670665684,17.118130773175917,1383.8,10.0,False,0.0
|
| 6 |
-
CatBoost,Tree-based,216.01313992020846,0.2815893316185425,17.013055738158688,1387.4,25.0,False,0.0
|
| 7 |
-
CatBoost,Tree-based,428.4029173434785,0.31791456478804925,17.01617892461794,1386.5,50.0,False,0.0
|
| 8 |
-
CatBoost,Tree-based,862.8837988810473,0.38060021065068383,17.033005196506924,1384.7,100.0,False,0.0
|
| 9 |
-
CatBoost,Tree-based,1291.843839644664,0.38736151225316695,17.05742025825018,1383.1,150.0,False,0.0
|
| 10 |
-
CatBoost,Tree-based,1739.1690497297914,0.39602676030046535,17.06360104170376,1382.1,201.0,False,0.0
|
| 11 |
-
ChimeraBoost,Tree-based,5.4899520078266,0.04138894865138677,20.96498333861501,1223.2,1.0,False,0.0
|
| 12 |
-
ChimeraBoost,Tree-based,11.334103150400939,0.08018211274281706,20.65170109104463,1240.6,2.0,False,0.0
|
| 13 |
-
ChimeraBoost,Tree-based,28.892796772186244,0.14570389969215242,20.467788555456597,1251.3,5.0,False,0.0
|
| 14 |
-
ChimeraBoost,Tree-based,58.87203197884595,0.2046887661505208,20.295471078639483,1259.3,10.0,False,0.0
|
| 15 |
-
ChimeraBoost,Tree-based,150.36569983602635,0.2874258032409872,19.988689801038134,1271.3,25.0,False,0.0
|
| 16 |
-
ChimeraBoost,Tree-based,302.47871980891523,0.3447163363004163,19.831121378401004,1278.9,50.0,False,0.0
|
| 17 |
-
ChimeraBoost,Tree-based,606.008218265041,0.4006058604567584,19.657543111625316,1285.9,100.0,False,0.0
|
| 18 |
-
ChimeraBoost,Tree-based,908.7557510717904,0.43279691313346724,19.584581550555765,1288.3,150.0,False,0.0
|
| 19 |
-
ChimeraBoost,Tree-based,1218.8724153795765,0.4496610990803296,19.539677456769304,1291.1,201.0,False,0.0
|
| 20 |
-
EBM,Tree-based,7.388420291453219,0.017156058727181196,21.274096684434205,1208.5,1.0,False,0.0
|
| 21 |
-
EBM,Tree-based,19.13979943869537,0.033315531949338485,20.997222169689923,1219.6,2.0,False,0.0
|
| 22 |
-
EBM,Tree-based,59.65680170213522,0.06020202098143048,20.637488816426607,1238.7,5.0,False,0.0
|
| 23 |
-
EBM,Tree-based,123.90743183396125,0.07941086088006653,20.487930220731542,1246.8,10.0,False,0.0
|
| 24 |
-
EBM,Tree-based,318.46001064068014,0.10750903547065471,20.29035237779537,1254.9,25.0,False,0.0
|
| 25 |
-
EBM,Tree-based,623.1113495162684,0.12378308877985164,20.153558096828956,1262.2,50.0,False,0.0
|
| 26 |
-
EBM,Tree-based,1256.5403166692183,0.14405226317495906,20.047775272582818,1267.3,100.0,False,0.0
|
| 27 |
-
EBM,Tree-based,1885.0271107114127,0.14697197529268866,20.009669417130617,1270.3,150.0,False,0.0
|
| 28 |
-
EBM,Tree-based,2499.3997394448907,0.1440681396038307,19.98337359606066,1271.9,201.0,False,0.0
|
| 29 |
-
ExtraTrees,Tree-based,4.194175284298607,0.5663988088013532,27.60941462253397,1021.2,1.0,False,0.0
|
| 30 |
-
ExtraTrees,Tree-based,8.720078438945333,0.7011757791959015,25.885989616663245,1062.0,2.0,False,0.0
|
| 31 |
-
ExtraTrees,Tree-based,21.685275973670596,0.7330007012763398,23.441225219730892,1129.0,5.0,False,0.0
|
| 32 |
-
ExtraTrees,Tree-based,43.12316999769439,0.7428670659282961,22.61451466400202,1170.4,10.0,False,0.0
|
| 33 |
-
ExtraTrees,Tree-based,107.39538737179987,1.018855954643115,22.001487160366885,1202.3,25.0,False,0.0
|
| 34 |
-
ExtraTrees,Tree-based,210.06024633928405,1.2214373513463619,21.841068527707396,1212.3,50.0,False,0.0
|
| 35 |
-
ExtraTrees,Tree-based,412.0764862110399,1.4038021731459822,21.736976146908678,1218.6,100.0,False,0.0
|
| 36 |
-
ExtraTrees,Tree-based,614.240675925616,1.462695758694767,21.676622474397757,1223.4,150.0,False,0.0
|
| 37 |
-
ExtraTrees,Tree-based,822.5846846042664,1.501127939369875,21.666099480679918,1223.9,201.0,False,0.0
|
| 38 |
-
FastaiMLP,Neural Network,5.483894573958628,0.6842938244078286,26.87947257075784,1003.6,1.0,False,0.0
|
| 39 |
-
FastaiMLP,Neural Network,14.530250474180118,1.4234649143152087,25.605440571288423,1045.8,2.0,False,0.0
|
| 40 |
-
FastaiMLP,Neural Network,42.06854030037134,2.70863815575737,23.540793521493093,1120.3,5.0,False,0.0
|
| 41 |
-
FastaiMLP,Neural Network,79.19690331067542,3.9064906778565582,22.577900990668017,1157.8,10.0,False,0.0
|
| 42 |
-
FastaiMLP,Neural Network,202.91650957601354,5.517691743805193,21.700240847904297,1190.3,25.0,False,0.0
|
| 43 |
-
FastaiMLP,Neural Network,413.0147999434225,6.825523560748225,21.29778091361426,1207.5,50.0,False,0.0
|
| 44 |
-
FastaiMLP,Neural Network,829.4495951905283,7.579914014700657,21.015252947637034,1217.1,100.0,False,0.0
|
| 45 |
-
FastaiMLP,Neural Network,1248.122171700538,7.913305846749778,20.83696614773943,1223.8,150.0,False,0.0
|
| 46 |
-
FastaiMLP,Neural Network,1679.3959423676156,8.077227734441916,20.733431000267178,1228.0,201.0,False,0.0
|
| 47 |
-
LightGBM,Tree-based,3.608651599211503,0.1695753132718836,21.25370273435017,1168.5,1.0,False,0.0
|
| 48 |
-
LightGBM,Tree-based,8.865955424310329,0.7271936335358054,19.364659272170424,1257.8,2.0,False,0.0
|
| 49 |
-
LightGBM,Tree-based,21.921505878230747,1.165245524912983,18.189015923605755,1330.5,5.0,False,0.0
|
| 50 |
-
LightGBM,Tree-based,43.593394992671044,1.4098790833754133,17.69549232887076,1361.8,10.0,False,0.0
|
| 51 |
-
LightGBM,Tree-based,110.8314003139697,1.8172136653942288,17.328862875062654,1386.4,25.0,False,0.0
|
| 52 |
-
LightGBM,Tree-based,222.35789421136602,2.0744273860536486,17.20742840636462,1395.5,50.0,False,0.0
|
| 53 |
-
LightGBM,Tree-based,444.73169339543847,2.3211352586207132,17.060104033808077,1404.9,100.0,False,0.0
|
| 54 |
-
LightGBM,Tree-based,664.9958936778935,2.425276738483371,16.99791358203584,1408.0,150.0,False,0.0
|
| 55 |
-
LightGBM,Tree-based,892.4854074789564,2.5817474842043104,16.96093514844105,1409.4,201.0,False,0.0
|
| 56 |
-
LimiX,Foundation Model,35.50961056314309,6.828482678301318,15.210524360691757,1422.0,1.0,False,0.0
|
| 57 |
-
ModernNCA,Neural Network,16.279623910227823,0.32060068900263267,21.245019708709258,1248.3,1.0,False,0.0
|
| 58 |
-
ModernNCA,Neural Network,54.21648382537063,0.8565664694763102,20.025741966024626,1273.8,2.0,False,0.0
|
| 59 |
-
ModernNCA,Neural Network,158.53994120196415,1.9156693463145684,18.07905172582486,1349.3,5.0,False,0.0
|
| 60 |
-
ModernNCA,Neural Network,318.0880622722443,2.785843758633247,17.66819528267606,1366.9,10.0,False,0.0
|
| 61 |
-
ModernNCA,Neural Network,784.3400464923684,4.219514475452051,17.252774036865365,1384.0,25.0,False,0.0
|
| 62 |
-
ModernNCA,Neural Network,1619.6093744476316,5.574964791511255,17.44680453759096,1373.4,50.0,False,0.0
|
| 63 |
-
ModernNCA,Neural Network,3239.1118632438247,7.063712430292479,17.866481656519923,1357.5,100.0,False,0.0
|
| 64 |
-
ModernNCA,Neural Network,4838.988606911565,7.8596602241219475,18.173570968320877,1345.3,150.0,False,0.0
|
| 65 |
-
ModernNCA,Neural Network,6523.550336157642,8.384898189151137,18.347650200624336,1337.3,201.0,False,0.0
|
| 66 |
-
PerpetualBooster,Tree-based,39.09071168560041,0.040657078690582577,33.318479094829,943.0,1.0,False,0.0
|
| 67 |
-
PerpetualBooster,Tree-based,114.19680170724877,0.3252722557923411,31.1917379277461,1003.6,2.0,False,0.0
|
| 68 |
-
PerpetualBooster,Tree-based,285.35259642784723,0.7833048920276815,28.661518170215118,1083.2,5.0,False,0.0
|
| 69 |
-
PerpetualBooster,Tree-based,342.03900946680346,0.8948102983830184,28.46978900579733,1090.2,6.0,False,0.0
|
| 70 |
-
RandomForest,Tree-based,0.5088535014091562,0.08856487680890945,28.409946673399666,999.4,1.0,False,0.0
|
| 71 |
-
RandomForest,Tree-based,3.3556051422440136,0.274181271644493,26.104844103809437,1044.0,2.0,False,0.0
|
| 72 |
-
RandomForest,Tree-based,12.849220132990748,0.4818339926449089,24.811989847138584,1078.7,5.0,False,0.0
|
| 73 |
-
RandomForest,Tree-based,27.96770195892894,0.678992572925596,24.054151765770364,1108.8,10.0,False,0.0
|
| 74 |
-
RandomForest,Tree-based,70.75466255009994,0.8688853999623392,23.5114987788157,1142.5,25.0,False,0.0
|
| 75 |
-
RandomForest,Tree-based,143.98648318866492,1.0449947563121842,23.377294359921297,1150.8,50.0,False,0.0
|
| 76 |
-
RandomForest,Tree-based,290.43930986552186,1.2523875096341897,23.290473049028794,1155.8,100.0,False,0.0
|
| 77 |
-
RandomForest,Tree-based,439.37065780631167,1.373768748735566,23.253662020587587,1157.7,150.0,False,0.0
|
| 78 |
-
RandomForest,Tree-based,590.0394439850668,1.459960166778112,23.236025263760705,1158.9,201.0,False,0.0
|
| 79 |
-
RealMLP,Neural Network,15.69323516601608,4.688867646313849,20.044269579375932,1226.9,1.0,False,0.0
|
| 80 |
-
RealMLP,Neural Network,33.849680863187785,6.699336819048018,17.62429168840669,1331.3,2.0,False,0.0
|
| 81 |
-
RealMLP,Neural Network,89.022575403558,10.361104313047106,15.892895926486114,1424.2,5.0,False,0.0
|
| 82 |
-
RealMLP,Neural Network,186.9144346810765,12.414049216861697,15.349194410543715,1457.8,10.0,False,0.0
|
| 83 |
-
RealMLP,Neural Network,469.4672918764594,14.92712763820984,14.975087750590802,1481.7,25.0,False,0.0
|
| 84 |
-
RealMLP,Neural Network,941.4479936377176,17.204325480320684,14.796073064558938,1494.2,50.0,False,0.0
|
| 85 |
-
RealMLP,Neural Network,1881.3658212549644,19.31438802167681,14.69171546627355,1499.1,100.0,False,0.0
|
| 86 |
-
RealMLP,Neural Network,2818.5782940853887,20.502682004182418,14.625770234730705,1503.0,150.0,False,0.0
|
| 87 |
-
RealMLP,Neural Network,3771.8540221067997,21.902496279105236,14.561284232977489,1503.7,201.0,False,0.0
|
| 88 |
-
RealTabPFN-2.5,Foundation Model,6.7587899978217045,0.6362272807949252,12.347361057130597,1560.3,1.0,False,0.0
|
| 89 |
-
RealTabPFN-2.5,Foundation Model,20.022077391499224,1.3637258308022322,12.279214993920386,1565.3,2.0,False,0.0
|
| 90 |
-
RealTabPFN-2.5,Foundation Model,54.35009239022621,2.776795940260542,11.894270631404149,1583.4,5.0,False,0.0
|
| 91 |
-
RealTabPFN-2.5,Foundation Model,108.98790128787763,4.002983246839659,11.698528996854291,1602.2,10.0,False,0.0
|
| 92 |
-
RealTabPFN-2.5,Foundation Model,284.7684460336686,5.7106402075573115,11.497664190753204,1612.7,25.0,False,0.0
|
| 93 |
-
RealTabPFN-2.5,Foundation Model,566.4138152118644,6.793591917858365,11.389525351312809,1616.4,50.0,False,0.0
|
| 94 |
-
RealTabPFN-2.5,Foundation Model,1137.2039338041147,7.389127054143678,11.31389385903684,1617.8,100.0,False,0.0
|
| 95 |
-
RealTabPFN-2.5,Foundation Model,1710.4116369596145,7.871864394392892,11.27848674027812,1617.9,150.0,False,0.0
|
| 96 |
-
RealTabPFN-2.5,Foundation Model,2289.3887157667205,8.353344818085464,11.234666170306504,1616.2,201.0,False,0.0
|
| 97 |
-
SAP-RPT-OSS,Foundation Model,16.230459759105607,1.2773508676992504,18.86416005851036,1334.7,1.0,False,0.0
|
| 98 |
-
TabDPT,Foundation Model,50.32502415266903,43.707401035938005,18.046661408364585,1344.8,1.0,False,0.0
|
| 99 |
-
TabDPT,Foundation Model,73.76989416372965,52.11201629009561,17.357261978922008,1371.3,2.0,False,0.0
|
| 100 |
-
TabDPT,Foundation Model,139.81847708335647,66.0787878176586,16.66239317547098,1406.0,5.0,False,0.0
|
| 101 |
-
TabDPT,Foundation Model,256.4808826588974,83.6221921836606,16.33348620385194,1422.6,10.0,False,0.0
|
| 102 |
-
TabDPT,Foundation Model,631.0078513375786,110.24799428469449,15.78109587578097,1444.2,25.0,False,0.0
|
| 103 |
-
TabDPT,Foundation Model,1275.2299790654088,138.47537424399025,15.519607804715541,1455.2,50.0,False,0.0
|
| 104 |
-
TabDPT,Foundation Model,2539.0709530625045,167.42760567363604,15.363851740247936,1463.0,100.0,False,0.0
|
| 105 |
-
TabDPT,Foundation Model,3811.208024605316,188.43165590675713,15.300477535033266,1465.0,150.0,False,0.0
|
| 106 |
-
TabDPT,Foundation Model,5119.776985103065,214.0824864784409,15.276643056444033,1465.8,201.0,False,0.0
|
| 107 |
-
TabDPT-Turbo,Foundation Model,4.691113094573359,0.19227067519018423,15.353850262933463,1462.3,1.0,False,0.0
|
| 108 |
-
TabFM,Foundation Model,39.5720422516442,5.357838133261318,4.6820290320989635,1759.4,1.0,False,0.0
|
| 109 |
-
TabICLv2,Foundation Model,3.9320097545321064,0.1520731744535504,11.587733779799482,1591.2,1.0,False,0.0
|
| 110 |
-
TabM,Neural Network,9.936009218949234,0.4449377919636944,18.283509667248886,1306.3,1.0,False,0.0
|
| 111 |
-
TabM,Neural Network,21.74621272792782,0.8480171202367977,17.894564704745637,1326.5,2.0,False,0.0
|
| 112 |
-
TabM,Neural Network,59.987973874757685,1.6121786403349327,17.43245203223984,1355.9,5.0,False,0.0
|
| 113 |
-
TabM,Neural Network,127.11365194789559,2.0828680316925148,16.877134813139428,1388.9,10.0,False,0.0
|
| 114 |
-
TabM,Neural Network,318.70836323157647,2.669847945333597,16.408830515598016,1413.4,25.0,False,0.0
|
| 115 |
-
TabM,Neural Network,637.1067463952677,3.1238178806065933,16.117502164814745,1428.6,50.0,False,0.0
|
| 116 |
-
TabM,Neural Network,1278.8911702563391,3.484415328611071,15.923231118886452,1439.4,100.0,False,0.0
|
| 117 |
-
TabM,Neural Network,1925.3471149571128,3.6365060901989694,15.755545263622809,1445.3,150.0,False,0.0
|
| 118 |
-
TabM,Neural Network,2585.579863640918,3.8381409685971137,15.701798864789993,1449.6,201.0,False,0.0
|
| 119 |
-
TabPFN-2.6,Foundation Model,7.034289077293122,0.5482886619733942,11.987793670213447,1622.7,1.0,False,0.0
|
| 120 |
-
TabPFN-3,Foundation Model,9.169929954447653,0.4158216638576948,10.794768217873633,1658.6,1.0,False,0.0
|
| 121 |
-
TabSTAR,Foundation Model,471.6614585494219,7.213726442305473,30.38344157705401,1039.3,1.0,False,0.0
|
| 122 |
-
TabSTAR,Foundation Model,797.2338293006283,8.246177063271318,30.237553936314576,1046.8,2.0,False,0.0
|
| 123 |
-
TabSTAR,Foundation Model,1402.6890753281787,10.34737673805446,29.924190478466507,1055.6,5.0,False,0.0
|
| 124 |
-
TabSTAR,Foundation Model,2175.087851949379,11.90188157751366,29.172366849727666,1073.6,10.0,False,0.0
|
| 125 |
-
TabSTAR,Foundation Model,5045.522576046773,16.22592614581593,27.879960409008085,1096.7,25.0,False,0.0
|
| 126 |
-
TabSTAR,Foundation Model,10226.355347764464,19.60206628408606,26.676519669081177,1116.4,50.0,False,0.0
|
| 127 |
-
TabSTAR,Foundation Model,20731.065214537048,22.976985584065375,26.05309621070424,1130.9,100.0,False,0.0
|
| 128 |
-
TabSTAR,Foundation Model,30617.587787993205,24.374053334119353,25.758833587093893,1138.9,150.0,False,0.0
|
| 129 |
-
TabSTAR,Foundation Model,40848.86657483013,25.936207253387835,25.549963365203965,1146.9,201.0,False,0.0
|
| 130 |
-
TabSwift,Foundation Model,2.756051243933877,0.05791268987655686,17.248500496240368,1378.7,1.0,False,0.0
|
| 131 |
-
TorchMLP,Neural Network,13.688894957032199,0.1550906391981672,24.777879162175854,1066.7,1.0,False,0.0
|
| 132 |
-
TorchMLP,Neural Network,32.17994192224896,0.31084197868517116,22.857678180346667,1125.6,2.0,False,0.0
|
| 133 |
-
TorchMLP,Neural Network,92.74701914680642,0.6204009276541033,21.269571665469336,1176.9,5.0,False,0.0
|
| 134 |
-
TorchMLP,Neural Network,198.403788246261,0.8859862453217204,20.581217131435597,1207.4,10.0,False,0.0
|
| 135 |
-
TorchMLP,Neural Network,483.47393881962074,1.278904806328708,19.98364615139698,1234.2,25.0,False,0.0
|
| 136 |
-
TorchMLP,Neural Network,974.006991783206,1.6522358141598805,19.609261912778692,1252.9,50.0,False,0.0
|
| 137 |
-
TorchMLP,Neural Network,1885.3999284295999,1.896272359232266,19.36020456048911,1264.1,100.0,False,0.0
|
| 138 |
-
TorchMLP,Neural Network,2882.886561733708,2.0769295602160094,19.23934880995436,1271.3,150.0,False,0.0
|
| 139 |
-
TorchMLP,Neural Network,3865.9507169384297,2.1462178944525663,19.14239455337929,1276.2,201.0,False,0.0
|
| 140 |
-
XGBoost,Tree-based,3.2873922338088355,0.2525411892114416,21.26768770126012,1165.7,1.0,False,0.0
|
| 141 |
-
XGBoost,Tree-based,8.297510696816628,0.6687217930403135,19.35164883335737,1250.3,2.0,False,0.0
|
| 142 |
-
XGBoost,Tree-based,21.70877790629026,1.3135984732073058,18.82692276742906,1282.1,5.0,False,0.0
|
| 143 |
-
XGBoost,Tree-based,42.697141308868254,1.473664156253216,18.528925418023455,1303.0,10.0,False,0.0
|
| 144 |
-
XGBoost,Tree-based,109.82739796316375,1.8610108954727544,18.285221069896405,1318.5,25.0,False,0.0
|
| 145 |
-
XGBoost,Tree-based,219.73481796370584,2.0831926002011665,18.182502263747296,1324.9,50.0,False,0.0
|
| 146 |
-
XGBoost,Tree-based,439.60203143007277,2.243969897476304,18.0937437910342,1331.2,100.0,False,0.0
|
| 147 |
-
XGBoost,Tree-based,659.3117486381539,2.3416077193265945,18.01469070173085,1335.9,150.0,False,0.0
|
| 148 |
-
XGBoost,Tree-based,884.4808277373293,2.446295688771306,17.94866937141705,1340.9,201.0,False,0.0
|
| 149 |
-
iLTM,Foundation Model,524.4765295003572,161.81343832142903,24.936616681743956,1075.2,1.0,False,0.0
|
| 150 |
-
iLTM,Foundation Model,1309.3726391156104,315.1785851675429,21.999424996697776,1153.1,2.0,False,0.0
|
| 151 |
-
iLTM,Foundation Model,3961.6553268098314,530.0687097749746,19.8928754460769,1262.6,5.0,False,0.0
|
| 152 |
-
iLTM,Foundation Model,8841.914391496262,748.7519406764377,19.201295532808242,1314.2,10.0,False,0.0
|
| 153 |
-
iLTM,Foundation Model,21737.971561100163,828.5067468065782,17.472125844838516,1374.1,25.0,False,0.0
|
| 154 |
-
iLTM,Foundation Model,22811.744051243128,841.445890748085,17.446263555512726,1377.3,26.0,False,0.0
|
| 155 |
-
xRFM,Other,5.446030178240368,1.0976028857093967,26.6617497580556,1050.7,1.0,False,0.0
|
| 156 |
-
xRFM,Other,11.040462649383006,1.2469331487108437,24.011085249631414,1111.0,2.0,False,0.0
|
| 157 |
-
xRFM,Other,27.95095076157401,1.484274975682999,20.58091874620733,1229.2,5.0,False,0.0
|
| 158 |
-
xRFM,Other,55.941341031883795,1.8164722650517409,19.035002211287427,1299.2,10.0,False,0.0
|
| 159 |
-
xRFM,Other,140.09100956098132,1.8569378725651828,18.243543201581396,1333.9,25.0,False,0.0
|
| 160 |
-
xRFM,Other,280.2176062526802,2.3361472688801364,18.007335846730587,1344.6,50.0,False,0.0
|
| 161 |
-
xRFM,Other,560.4680551302398,2.551869632074315,17.918464562812115,1346.4,100.0,False,0.0
|
| 162 |
-
xRFM,Other,840.8353293444695,2.7950483190335644,17.90537995796114,1346.9,150.0,False,0.0
|
| 163 |
-
xRFM,Other,1126.9686387245144,2.9237006693146794,17.894431738395728,1346.6,201.0,False,0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|