Skip to content

Commit df90483

Browse files
maps
1 parent 5b6dc25 commit df90483

13 files changed

Lines changed: 58 additions & 352 deletions

cybench/runs/analysis/collect_walk_forward_results.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
from cybench.runs.viz.region_map_lib import (
5959
build_region_map_payload,
6060
bundle_region_map_assets,
61-
strip_map_pngs_from_records,
6261
write_region_map_sidecar,
6362
)
6463

@@ -379,7 +378,7 @@ def _panel_search_dirs(output_dir: Path, row: dict[str, Any]) -> list[Path]:
379378
def _panel_images_for_dataset(
380379
output_dir: Path, row: dict[str, Any], dataset: str
381380
) -> dict[str, str]:
382-
panel_names = ("map_actual", "map_pred", "scatter", "temporal")
381+
panel_names = ("scatter", "temporal")
383382
for base in _panel_search_dirs(output_dir, row):
384383
assets = base / "report_assets"
385384
rel: dict[str, str] = {}
@@ -466,10 +465,6 @@ def write_model_comparison_dashboard(
466465
)
467466
if map_payload.get("geojson_by_country"):
468467
write_region_map_sidecar(output_dir, map_payload)
469-
if map_payload.get("datasets") and map_payload.get("geojson_by_country"):
470-
records = strip_map_pngs_from_records(records)
471-
elif map_payload.get("datasets") and map_payload.get("geojson_by_country"):
472-
records = strip_map_pngs_from_records(records)
473468
html_path = output_dir / "compare_models.html"
474469
html_path.write_text(build_html(records, map_payload=map_payload), encoding="utf-8")
475470
return html_path

cybench/runs/analysis/dashboard_targets.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ defaults:
1414
repo_root: /lustre/backup/SHARED/AIN/agml/AgML-CY-Bench-AAAI
1515
publish_root: /lustre/backup/SHARED/AIN/agml/CY-Bench-dashboard
1616
min_run_fraction: 1.0
17-
# Downscale map PNGs in published bundles (~50% map bytes; keeps all panels).
18-
pages_lite: true
1917

2018
# include:
2119
# - country: DE

cybench/runs/analysis/publish_dashboard_bundle.py

Lines changed: 15 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
from pathlib import Path
2525
from typing import Any
2626

27-
from PIL import Image
28-
2927
_COUNTRY_NAMES: dict[str, str] = {
3028
"ao": "Angola",
3129
"ar": "Argentina",
@@ -177,47 +175,19 @@ def prune_obsolete_dashboard_dirs(
177175
# GitHub Pages artifact limit (deploy fails above this).
178176
GITHUB_PAGES_MAX_BYTES = 1_073_741_824
179177

180-
# Map PNGs are ~45% of each dashboard; downscale for Pages to stay under 1 GB.
181-
PAGES_MAP_MARKERS = ("map_actual", "map_pred")
182-
# Linear scale before palette quantize (~65% side length, 128-color maps).
183-
PAGES_MAP_SCALE = 0.65
184-
PAGES_MAP_PALETTE_COLORS = 128
185-
PAGES_MAP_PNG_OPTIMIZE = True
186-
187-
188-
def _is_map_asset(filename: str) -> bool:
189-
return any(marker in filename for marker in PAGES_MAP_MARKERS)
190-
191178

192-
def _flatten_for_map_export(img: Image.Image) -> Image.Image:
193-
"""RGBA/LA choropleth panels → RGB on white (better PNG palette compression)."""
194-
if img.mode in ("RGBA", "LA"):
195-
background = Image.new("RGB", img.size, (255, 255, 255))
196-
background.paste(img, mask=img.split()[-1])
197-
return background
198-
if img.mode != "RGB":
199-
return img.convert("RGB")
200-
return img
201-
202-
203-
def downgrade_map_png(
204-
src: Path,
205-
dest: Path,
206-
*,
207-
scale: float = PAGES_MAP_SCALE,
208-
palette_colors: int = PAGES_MAP_PALETTE_COLORS,
209-
) -> int:
210-
"""Downscale + palette-compress a map PNG for GitHub Pages."""
211-
with Image.open(src) as img:
212-
img = _flatten_for_map_export(img)
213-
width, height = img.size
214-
new_size = (max(1, int(width * scale)), max(1, int(height * scale)))
215-
if new_size != (width, height):
216-
img = img.resize(new_size, Image.Resampling.LANCZOS)
217-
img = img.convert("P", palette=Image.Palette.ADAPTIVE, colors=palette_colors)
218-
dest.parent.mkdir(parents=True, exist_ok=True)
219-
img.save(dest, format="PNG", optimize=PAGES_MAP_PNG_OPTIMIZE)
220-
return dest.stat().st_size
179+
def _copy_assets(assets_src: Path, dest_assets: Path) -> int:
180+
"""Copy assets/; return number of files copied."""
181+
if dest_assets.exists():
182+
shutil.rmtree(dest_assets)
183+
dest_assets.mkdir(parents=True)
184+
n_copied = 0
185+
for src_file in sorted(assets_src.iterdir()):
186+
if not src_file.is_file():
187+
continue
188+
shutil.copy2(src_file, dest_assets / src_file.name)
189+
n_copied += 1
190+
return n_copied
221191

222192

223193
def estimate_publish_bundle_size(publish_root: Path) -> dict[str, Any]:
@@ -259,47 +229,6 @@ def estimate_publish_bundle_size(publish_root: Path) -> dict[str, Any]:
259229
}
260230

261231

262-
def apply_pages_lite_to_publish_root(
263-
publish_root: Path,
264-
*,
265-
dry_run: bool = False,
266-
scale: float = PAGES_MAP_SCALE,
267-
) -> tuple[int, int]:
268-
"""Downscale map PNGs in every published dashboard (scatter/temporal unchanged).
269-
270-
Returns (maps_processed, bytes_saved).
271-
"""
272-
publish_root = publish_root.resolve()
273-
processed = 0
274-
saved = 0
275-
for child in publish_root.iterdir():
276-
if not child.is_dir() or child.name in {"assets", ".git"}:
277-
continue
278-
assets = child / "assets"
279-
if not assets.is_dir():
280-
continue
281-
for asset in assets.glob("*.png"):
282-
if not _is_map_asset(asset.name):
283-
continue
284-
before = asset.stat().st_size
285-
if dry_run:
286-
print(f"[DRY-RUN] downgrade {child.name}/assets/{asset.name}")
287-
processed += 1
288-
continue
289-
tmp = asset.with_name(asset.name + ".tmp")
290-
after = downgrade_map_png(asset, tmp, scale=scale)
291-
tmp.replace(asset)
292-
processed += 1
293-
saved += max(0, before - after)
294-
if processed:
295-
action = "would downgrade" if dry_run else "downgraded"
296-
print(
297-
f"[OK] {action} {processed} map PNG(s)"
298-
+ (f", saved {saved / (1024 * 1024):.1f} MB" if saved else "")
299-
)
300-
return processed, saved
301-
302-
303232
def report_publish_bundle_size(publish_root: Path) -> None:
304233
stats = estimate_publish_bundle_size(publish_root)
305234
print(
@@ -313,42 +242,18 @@ def report_publish_bundle_size(publish_root: Path) -> None:
313242
over_mb = stats["total_bytes"] / (1024 * 1024) - stats["pages_limit_mb"]
314243
print(
315244
f"[WARN] Over GitHub Pages artifact limit ({stats['pages_limit_mb']} MB) "
316-
f"by ~{over_mb:.0f} MB. Run --downgrade-maps-only or republish with --pages-lite."
245+
f"by ~{over_mb:.0f} MB."
317246
)
318247
else:
319248
headroom = stats["pages_limit_mb"] - stats["total_mb"]
320249
print(f"[OK] Within GitHub Pages limit ({headroom:.0f} MB headroom)")
321250

322251

323-
def _copy_assets(
324-
assets_src: Path,
325-
dest_assets: Path,
326-
*,
327-
pages_lite: bool,
328-
) -> int:
329-
"""Copy assets/; return number of files copied."""
330-
if dest_assets.exists():
331-
shutil.rmtree(dest_assets)
332-
dest_assets.mkdir(parents=True)
333-
n_copied = 0
334-
for src_file in sorted(assets_src.iterdir()):
335-
if not src_file.is_file():
336-
continue
337-
dest_file = dest_assets / src_file.name
338-
if pages_lite and _is_map_asset(src_file.name):
339-
downgrade_map_png(src_file, dest_file)
340-
else:
341-
shutil.copy2(src_file, dest_file)
342-
n_copied += 1
343-
return n_copied
344-
345-
346252
def publish_bundle(
347253
*,
348254
source_dir: Path,
349255
dest_dir: Path,
350256
title: str | None = None,
351-
pages_lite: bool = False,
352257
) -> Path:
353258
"""Copy HTML + assets into dest_dir/dashboard.html (+ assets/)."""
354259
html_src, assets_src = _resolve_html_and_assets(source_dir)
@@ -359,12 +264,8 @@ def publish_bundle(
359264

360265
dest_assets = dest_dir / "assets"
361266
if assets_src and assets_src.is_dir():
362-
n_assets = _copy_assets(assets_src, dest_assets, pages_lite=pages_lite)
363-
if pages_lite:
364-
print(
365-
f"[INFO] pages-lite: copied {n_assets} asset(s) "
366-
f"(maps → {PAGES_MAP_SCALE:.0%} scale, {PAGES_MAP_PALETTE_COLORS}-color palette)"
367-
)
267+
n_assets = _copy_assets(assets_src, dest_assets)
268+
print(f"[INFO] copied {n_assets} asset(s)")
368269
elif dest_assets.exists():
369270
shutil.rmtree(dest_assets)
370271

@@ -681,21 +582,6 @@ def main() -> None:
681582
action="store_true",
682583
help="Print prune actions without deleting",
683584
)
684-
parser.add_argument(
685-
"--pages-lite",
686-
action="store_true",
687-
help="Downscale map PNGs when copying assets (keeps all panels; fits GitHub Pages 1 GB limit)",
688-
)
689-
parser.add_argument(
690-
"--downgrade-maps-only",
691-
action="store_true",
692-
help="Downscale map PNGs in existing published dashboards, then report size",
693-
)
694-
parser.add_argument(
695-
"--strip-maps-only",
696-
action="store_true",
697-
help=argparse.SUPPRESS,
698-
)
699585
parser.add_argument(
700586
"--report-size",
701587
action="store_true",
@@ -710,12 +596,6 @@ def main() -> None:
710596
report_publish_bundle_size(publish_root)
711597
return
712598

713-
if args.downgrade_maps_only or args.strip_maps_only:
714-
apply_pages_lite_to_publish_root(publish_root, dry_run=args.dry_run)
715-
if not args.dry_run:
716-
report_publish_bundle_size(publish_root)
717-
return
718-
719599
if args.prune_only:
720600
removed = prune_obsolete_dashboard_dirs(publish_root, dry_run=args.dry_run)
721601
print(f"[DONE] Pruned {len(removed)} obsolete folder(s)")
@@ -737,7 +617,6 @@ def main() -> None:
737617
source_dir=source_dir,
738618
dest_dir=dest_dir,
739619
title=args.title,
740-
pages_lite=args.pages_lite,
741620
)
742621
print(f"[DONE] Bundle: {html_path}")
743622
if (dest_dir / "assets").is_dir():

cybench/runs/analysis/publish_pipeline_lib.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from cybench.runs.analysis.collect_walk_forward_results import load_pooled_predictions
1515
from cybench.runs.analysis.publish_dashboard_bundle import (
1616
_COUNTRY_NAMES,
17-
apply_pages_lite_to_publish_root,
1817
discover_index_entries,
1918
prune_obsolete_dashboard_dirs,
2019
publish_bundle,
@@ -62,7 +61,6 @@ class PipelineDefaults:
6261
repo_root: Path = Path("/lustre/backup/SHARED/AIN/agml/AgML-CY-Bench-AAAI")
6362
publish_root: Path = Path("/lustre/backup/SHARED/AIN/agml/CY-Bench-dashboard")
6463
min_run_fraction: float = 1.0
65-
pages_lite: bool = True
6664

6765

6866
@dataclass
@@ -74,7 +72,6 @@ class PublishTarget:
7472
repo_root: Path = field(default_factory=lambda: PipelineDefaults().repo_root)
7573
publish_root: Path = field(default_factory=lambda: PipelineDefaults().publish_root)
7674
min_run_fraction: float = 1.0
77-
pages_lite: bool = True
7875
title: str | None = None
7976

8077
@property
@@ -243,7 +240,6 @@ def discover_baselines_batches(
243240
repo_root=defaults.repo_root,
244241
publish_root=defaults.publish_root,
245242
min_run_fraction=defaults.min_run_fraction,
246-
pages_lite=defaults.pages_lite,
247243
)
248244
)
249245

@@ -269,7 +265,6 @@ def discover_baselines_batches(
269265
repo_root=defaults.repo_root,
270266
publish_root=defaults.publish_root,
271267
min_run_fraction=defaults.min_run_fraction,
272-
pages_lite=defaults.pages_lite,
273268
)
274269
)
275270
return targets
@@ -306,7 +301,6 @@ def discover_baselines_batches_fast(
306301
repo_root=defaults.repo_root,
307302
publish_root=defaults.publish_root,
308303
min_run_fraction=defaults.min_run_fraction,
309-
pages_lite=defaults.pages_lite,
310304
)
311305
)
312306
return targets
@@ -359,7 +353,6 @@ def discover_paper_walk_forward_targets(
359353
repo_root=defaults.repo_root,
360354
publish_root=defaults.publish_root,
361355
min_run_fraction=defaults.min_run_fraction,
362-
pages_lite=defaults.pages_lite,
363356
)
364357
)
365358
return filter_publish_targets(
@@ -428,7 +421,6 @@ def load_pipeline_defaults(
428421
repo_root=Path(cfg.get("repo_root", base.repo_root)),
429422
publish_root=Path(cfg.get("publish_root", base.publish_root)).expanduser(),
430423
min_run_fraction=float(cfg.get("min_run_fraction", base.min_run_fraction)),
431-
pages_lite=bool(cfg.get("pages_lite", base.pages_lite)),
432424
)
433425

434426

@@ -456,7 +448,6 @@ def _explicit_targets_from_config(
456448
repo_root=defaults.repo_root,
457449
publish_root=defaults.publish_root,
458450
min_run_fraction=float(item.get("min_run_fraction", defaults.min_run_fraction)),
459-
pages_lite=bool(item.get("pages_lite", defaults.pages_lite)),
460451
title=item.get("title"),
461452
)
462453
)
@@ -769,7 +760,6 @@ def run_publish_stage(
769760
source_dir=target.collect_dir,
770761
dest_dir=target.publish_dir,
771762
title=target.default_title(),
772-
pages_lite=target.pages_lite,
773763
)
774764
collect_state = _read_json(collect_state_path(target)) or {}
775765
_write_json(
@@ -795,8 +785,6 @@ def run_index_stage(
795785
print(f"[DRY-RUN] rebuild index under {target.publish_root}")
796786
return StageStatus("index", False, "would rebuild index.html")
797787
prune_obsolete_dashboard_dirs(target.publish_root)
798-
if target.pages_lite:
799-
apply_pages_lite_to_publish_root(target.publish_root)
800788
entries = discover_index_entries(target.publish_root)
801789
index_path = update_index(target.publish_root, entries)
802790
version = insights_version if insights_version is not None else target.version

0 commit comments

Comments
 (0)