from __future__ import annotations from pathlib import Path import pandas as pd from jinja2 import Template from .utils import ensure_dir REPORT_TEMPLATE = """
This is a weak-label mining report. Treat candidates as review targets, not truth.
| Metric | Value |
|---|---|
| Total candidates | {{ total }} |
| Average score | {{ avg_score }} |
| Median score | {{ med_score }} |
{{ overlay.name }}
No candidates.
" if not df.empty: style_table = df.groupby("fill_style").agg(count=("fill_style", "size"), avg_score=("score", "mean")).reset_index().to_html(index=False) overlay_items = [] for ov in overlays: ov = Path(ov) try: rel = ov.relative_to(out_html.parent) except ValueError: rel = ov overlay_items.append({"name": ov.name, "rel": str(rel).replace("\\", "/")}) html = Template(REPORT_TEMPLATE).render( total=0 if df.empty else len(df), avg_score="—" if df.empty else f"{df['score'].mean():.3f}", med_score="—" if df.empty else f"{df['score'].median():.3f}", style_table=style_table, overlays=overlay_items, ) out_html.write_text(html, encoding="utf-8") return out_html