#!/usr/bin/env python3 """Create thesis-ready plots from network_timing_benchmark.py results. The script reads one or more benchmark result directories containing `summary.json`, extracts the most relevant metrics, writes CSV files for checking, and exports publication-friendly figures. """ from __future__ import annotations import argparse import json import re import sys from pathlib import Path from typing import Any def import_plotting_stack() -> tuple[Any, Any, Any]: try: import matplotlib.pyplot as plt import pandas as pd import seaborn as sns except ModuleNotFoundError as exc: missing = exc.name or "plotting dependency" print( f"Missing Python package: {missing}\n\n" "Install the plotting dependencies with:\n" " python3 -m pip install pandas matplotlib seaborn\n\n" "On Ubuntu with apt packages, this usually also works:\n" " sudo apt install python3-pandas python3-matplotlib python3-seaborn", file=sys.stderr, ) raise SystemExit(2) from exc return pd, plt, sns def safe_name(value: str) -> str: return re.sub(r"[^A-Za-z0-9_.-]+", "_", value).strip("_") or "plot" def find_summary_files(input_paths: list[Path]) -> list[Path]: files: list[Path] = [] for path in input_paths: if path.is_file() and path.name == "summary.json": files.append(path) elif path.is_dir(): files.extend(path.rglob("summary.json")) return sorted(set(files)) def infer_setup_name(summary_path: Path, payload: dict[str, Any]) -> str: label = str(payload.get("label") or "").strip() if label: return label folder = summary_path.parent.name match = re.match(r"^\d{8}-\d{6}-(?P