diff --git a/.gitignore b/.gitignore index 956c041..49d8feb 100644 --- a/.gitignore +++ b/.gitignore @@ -437,3 +437,4 @@ runs/*/ultralytics/ runs/*/gold_predictions/ runs/*/dataset.resolved.yaml runs/slurm-*.out +runs/_measure_*/ diff --git a/tools/measure_weights.py b/tools/measure_weights.py new file mode 100644 index 0000000..183ce28 --- /dev/null +++ b/tools/measure_weights.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +"""Measure any weights on the gold set and store the report in the registry. + +Used once to give the deployed model its ``gold_report.json``, the baseline the +gate compares every new run against: + + python tools/measure_weights.py /path/to/best.pt --version yolo26n-seg-overlap-false-2026-04-12 +""" + +from __future__ import annotations + +import argparse +import json +import sys +from datetime import datetime +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT)) + +from tools.train_run import measure # noqa: E402 + +DEFAULT_NAMES = ["loop_all", "pin", "crystal", "loop_face", "ice", "needle"] + + +def main(argv=None) -> int: + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("weights") + ap.add_argument("--version", required=True, help="registry directory name to write gold_report.json into") + ap.add_argument("--conf", type=float, default=0.25) + ap.add_argument("--names", default=",".join(DEFAULT_NAMES)) + args = ap.parse_args(argv) + reg = ROOT / "models" / "registry" / args.version + reg.mkdir(parents=True, exist_ok=True) + work = ROOT / "runs" / f"_measure_{args.version}" + work.mkdir(parents=True, exist_ok=True) + report = measure(Path(args.weights), work, args.names.split(","), conf=args.conf) + report["weights"] = str(Path(args.weights).resolve()) + report["measured_at"] = datetime.now().isoformat(timespec="seconds") + out = reg / "gold_report.json" + out.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8") + meta = reg / "metadata.json" + if not meta.exists(): + meta.write_text(json.dumps({"model_id": args.version, "task": "segmentation", + "metrics": report["overall"], "note": "metadata written by measure_weights.py"}, + indent=2) + "\n", encoding="utf-8") + o = report["overall"] + print(f"{args.version}: f1 {o['f1']:.3f} mask IoU {o['mean_mask_iou']:.3f} -> {out}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())