Download scripts/build_task_rank_map.py from RAI-Lab/Wildfire-FM: direct link, hf CLI and curl.
- Browser
- Download file 5.26 kB
-
https://huggingface.co/RAI-Lab/Wildfire-FM/resolve/refs%2Fpr%2F2/scripts/build_task_rank_map.py
- Command line
-
hf download hf://RAI-Lab/Wildfire-FM@refs/pr/2/scripts/build_task_rank_map.py
-
curl -L -o build_task_rank_map.py https://huggingface.co/RAI-Lab/Wildfire-FM/resolve/refs%2Fpr%2F2/scripts/build_task_rank_map.py
5.26 kB
| #!/usr/bin/env python3 | |
| """Build the RQ4 task-rank map from released paper table TeX. | |
| This uses only the Python standard library plus the small PDF helper bundled in | |
| this repository. It does not require raw data, feature caches, or matplotlib. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from pathlib import Path | |
| from simple_pdf import PdfCanvas, mix | |
| ROOT = Path(__file__).resolve().parents[1] | |
| TABLE_DIR = ROOT / "paper_outputs" / "tables" | |
| OUT = ROOT / "paper_outputs" / "figures" / "fig_task_rank_map.pdf" | |
| MODELS = [ | |
| "FireWx-FM ref.", | |
| "Prithvi-WxC", | |
| "Aurora", | |
| "ClimaX", | |
| "StormCast", | |
| "DLWP", | |
| "FCN", | |
| "FengWu", | |
| "FuXi", | |
| "Pangu-Weather", | |
| "AlphaEarth", | |
| ] | |
| DISPLAY_MODELS = [ | |
| "FireWx-FM ref.", | |
| "Prithvi-WxC", | |
| "Aurora", | |
| "ClimaX", | |
| "StormCast", | |
| "DLWP", | |
| "FCN", | |
| "FengWu", | |
| "FuXi", | |
| "Pangu-Weather", | |
| "AlphaEarth", | |
| ] | |
| def means_from_row(block: str, label: str, occurrence: int = 0) -> list[float]: | |
| starts = [m.start() for m in re.finditer(re.escape(label), block)] | |
| if len(starts) <= occurrence: | |
| raise ValueError(f"Missing row {label!r} occurrence {occurrence}") | |
| start = starts[occurrence] | |
| end = block.find(r"\\", start) | |
| if end < 0: | |
| raise ValueError(f"Missing row terminator after {label!r}") | |
| row = block[start:end] | |
| values = [float(x) for x in re.findall(r"\\ms\{(-?\d+(?:\.\d+)?)\}\{", row)] | |
| if not values: | |
| raise ValueError(f"No values found for row {label!r}") | |
| return values | |
| def rank_values(values: list[float], higher_is_better: bool) -> list[int]: | |
| order = sorted(range(len(values)), key=lambda i: values[i], reverse=higher_is_better) | |
| ranks = [0] * len(values) | |
| for rank, idx in enumerate(order, start=1): | |
| ranks[idx] = rank | |
| return ranks | |
| def rank_color(rank: int, n_cols: int) -> tuple[float, float, float]: | |
| t = (n_cols - rank) / max(1, n_cols - 1) | |
| if t <= 0.5: | |
| return mix((0.93, 0.95, 0.94), (0.55, 0.78, 0.75), t / 0.5) | |
| return mix((0.55, 0.78, 0.75), (0.05, 0.40, 0.42), (t - 0.5) / 0.5) | |
| def fmt_value(value: float) -> str: | |
| return f"{value:.2f}" if abs(value) >= 1 else f"{value:.3f}" | |
| def main() -> None: | |
| primary = (TABLE_DIR / "tab_primary_results.tex").read_text() | |
| supporting = (TABLE_DIR / "tab_supporting_results.tex").read_text() | |
| primary_rows = {label: means_from_row(primary, label) for label in MODELS} | |
| supporting_top = {label: means_from_row(supporting, label, occurrence=0) for label in MODELS} | |
| supporting_bottom = {label: means_from_row(supporting, label, occurrence=1) for label in MODELS} | |
| tasks = [ | |
| ("Occupancy", "Union F1 (%)", "higher better", [primary_rows[m][2] for m in MODELS], True), | |
| ("Fire spread", "AP (%)", "higher better", [primary_rows[m][5] for m in MODELS], True), | |
| ("Burned area", "log-RMSE", "lower better", [supporting_top[m][0] for m in MODELS], False), | |
| ("Analog retrieval", "nDCG@10", "higher better", [supporting_top[m][3] for m in MODELS], True), | |
| ("Smoke PM2.5", "RMSE", "lower better", [supporting_bottom[m][0] for m in MODELS], False), | |
| ("Extreme heat", "RMSE-C", "lower better", [supporting_bottom[m][3] for m in MODELS], False), | |
| ] | |
| n_rows = len(tasks) | |
| n_cols = len(MODELS) | |
| c = PdfCanvas(width=1120, height=430) | |
| c.rect(0, 0, c.width, c.height, fill=(1, 1, 1)) | |
| x0, y0 = 108, 90 | |
| cell_w, cell_h = 86, 42 | |
| grid_top = y0 + n_rows * cell_h | |
| for j, model in enumerate(DISPLAY_MODELS): | |
| c.text(x0 + j * cell_w + cell_w / 2, grid_top + 34, model, size=8.7, align="center", bold=True, color=(0.12, 0.14, 0.16)) | |
| for i, (task, metric, direction, values, higher) in enumerate(tasks): | |
| y = grid_top - (i + 1) * cell_h | |
| c.text(12, y + 25, task, size=7.7, bold=True, color=(0.12, 0.14, 0.16)) | |
| c.text(12, y + 14, metric, size=7.1, bold=True, color=(0.12, 0.14, 0.16)) | |
| c.text(12, y + 3, direction, size=6.4, color=(0.42, 0.44, 0.46)) | |
| ranks = rank_values(values, higher) | |
| for j, (rank, value) in enumerate(zip(ranks, values)): | |
| x = x0 + j * cell_w | |
| color = rank_color(rank, n_cols) | |
| text_color = (1, 1, 1) if rank <= 2 else (0.07, 0.09, 0.11) | |
| c.rect(x, y, cell_w, cell_h, fill=color, stroke=(1, 1, 1), lw=0.8) | |
| c.text(x + cell_w / 2, y + 24, f"#{rank}", size=11.2, align="center", bold=True, color=text_color) | |
| c.text(x + cell_w / 2, y + 9, fmt_value(value), size=7.0, align="center", color=text_color) | |
| c.rect(x0, y0, cell_w * n_cols, cell_h * n_rows, stroke=(0.20, 0.22, 0.24), lw=0.8) | |
| key_x, key_y = x0 + cell_w * n_cols - 220, 38 | |
| c.text(key_x + 110, key_y + 25, "within-row rank", size=9.0, bold=True, align="center", color=(0.24, 0.25, 0.26)) | |
| for i in range(80): | |
| color = rank_color(n_cols - int(i / 80 * (n_cols - 1)), n_cols) | |
| c.rect(key_x + i * 2.5, key_y + 8, 2.6, 10, fill=color) | |
| c.text(key_x, key_y - 4, f"rank {n_cols}", size=7.0, color=(0.25, 0.26, 0.27)) | |
| c.text(key_x + 200, key_y - 4, "rank 1", size=7.0, align="right", color=(0.25, 0.26, 0.27)) | |
| OUT.parent.mkdir(parents=True, exist_ok=True) | |
| c.save(OUT) | |
| if __name__ == "__main__": | |
| main() | |