| |
| from __future__ import annotations |
|
|
| import argparse |
| import json |
| import sys |
| from pathlib import Path |
|
|
| PROJECT_ROOT = Path(__file__).resolve().parents[1] |
| if str(PROJECT_ROOT) not in sys.path: |
| sys.path.insert(0, str(PROJECT_ROOT)) |
|
|
| from dovla_cil.generation.tangent_chart_synthesis import ( |
| ChartSynthesisConfig, |
| evaluate_chart_synthesis, |
| ) |
|
|
|
|
| def main(argv: list[str] | None = None) -> int: |
| parser = argparse.ArgumentParser( |
| description="Evaluate local chart synthesis for positive tangent support." |
| ) |
| parser.add_argument("--targets", type=Path, required=True) |
| parser.add_argument("--out", type=Path, required=True) |
| parser.add_argument("--k-values", default="1,2,4,8,16") |
| parser.add_argument("--thresholds", default="0.05,0.1,0.2,0.4") |
| parser.add_argument("--obs-dim", type=int, default=96) |
| parser.add_argument("--text-dim", type=int, default=64) |
| parser.add_argument("--val-fraction", type=float, default=0.2) |
| parser.add_argument("--seed", type=int, default=0) |
| parser.add_argument("--neighbor-pool", type=int, default=64) |
| parser.add_argument("--direct-count", type=int, default=12) |
| parser.add_argument("--barycentric-windows", default="4,8,16,32") |
| parser.add_argument("--barycentric-temperature", type=float, default=0.5) |
| parser.add_argument("--utility-weight", type=float, default=0.0) |
| parser.add_argument( |
| "--order", |
| choices=("direct_first", "means_first", "interleave"), |
| default="direct_first", |
| ) |
| parser.add_argument("--all-tasks", action="store_true") |
| parser.add_argument("--no-groups", action="store_true", help="Drop per-group rows from output.") |
| args = parser.parse_args(argv) |
|
|
| payload = json.loads(args.targets.read_text()) |
| config = ChartSynthesisConfig( |
| obs_dim=args.obs_dim, |
| text_dim=args.text_dim, |
| val_fraction=args.val_fraction, |
| seed=args.seed, |
| neighbor_pool=args.neighbor_pool, |
| direct_count=args.direct_count, |
| barycentric_windows=_parse_ints(args.barycentric_windows), |
| barycentric_temperature=args.barycentric_temperature, |
| utility_weight=args.utility_weight, |
| order=args.order, |
| same_task_only=not args.all_tasks, |
| ) |
| report = evaluate_chart_synthesis( |
| list(payload.get("targets", [])), |
| config=config, |
| k_values=_parse_ints(args.k_values), |
| thresholds=_parse_floats(args.thresholds), |
| ) |
| report["targets"] = str(args.targets) |
| if args.no_groups: |
| report.pop("groups", None) |
| args.out.parent.mkdir(parents=True, exist_ok=True) |
| args.out.write_text(json.dumps(report, indent=2) + "\n") |
| summary = {key: value for key, value in report.items() if key != "groups"} |
| print(json.dumps(summary, indent=2)) |
| print(f"Wrote {args.out}") |
| return 0 |
|
|
|
|
| def _parse_ints(value: str) -> tuple[int, ...]: |
| items = tuple(int(item.strip()) for item in value.split(",") if item.strip()) |
| if not items or any(item <= 0 for item in items): |
| raise ValueError("integer list must contain positive values") |
| return items |
|
|
|
|
| def _parse_floats(value: str) -> tuple[float, ...]: |
| items = tuple(float(item.strip()) for item in value.split(",") if item.strip()) |
| if not items or any(item < 0 for item in items): |
| raise ValueError("float list must contain non-negative values") |
| return items |
|
|
|
|
| if __name__ == "__main__": |
| raise SystemExit(main()) |
|
|