Skip to content

oversampleqa.report

oversampleqa.report

Report generation for oversampleqa.

frame_to_html(frame, *, float_format='{:.4f}')

Render a DataFrame as an HTML table.

Parameters:

Name Type Description Default
frame DataFrame

Frame to render. A named index becomes the first column.

required
float_format str

Format applied to floating-point cells.

'{:.4f}'

Returns:

Type Description
str

An HTML table, or a note when the frame is empty.

Source code in src/oversampleqa/_render.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def frame_to_html(frame: pd.DataFrame, *, float_format: str = "{:.4f}") -> str:
    """Render a DataFrame as an HTML table.

    Args:
        frame: Frame to render. A named index becomes the first column.
        float_format: Format applied to floating-point cells.

    Returns:
        An HTML table, or a note when the frame is empty.
    """
    if frame.empty:
        return "<p><em>No results.</em></p>"
    display = frame.reset_index() if frame.index.name else frame
    # pandas ships no type information, so to_html is typed Any. str() makes
    # the declared return type honest instead of suppressing the error.
    return str(display.to_html(index=False, float_format=float_format.format))

frame_to_markdown(frame, *, float_format='{:.4f}')

Render a DataFrame as a GitHub-flavoured Markdown table.

Written out rather than delegated to DataFrame.to_markdown, which needs tabulate. That is installed here only as a transitive dependency of something else, and depending on a package nobody declared is how a working install becomes a broken one after an unrelated upgrade.

The previous implementation used to_csv(sep="|"), which is not Markdown: it has no header separator row and no leading or trailing pipes, so it rendered as one run-on paragraph rather than a table.

Parameters:

Name Type Description Default
frame DataFrame

Frame to render. The index becomes the first column when it is named, since compute_ranking returns the oversampler there.

required
float_format str

Format applied to floating-point cells. Raw repr leaks values like 0.21000000000000002 into a document meant to be read.

'{:.4f}'

Returns:

Type Description
str

A Markdown table, or a note when the frame is empty.

Source code in src/oversampleqa/_render.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def frame_to_markdown(frame: pd.DataFrame, *, float_format: str = "{:.4f}") -> str:
    """Render a DataFrame as a GitHub-flavoured Markdown table.

    Written out rather than delegated to ``DataFrame.to_markdown``, which needs
    ``tabulate``. That is installed here only as a transitive dependency of
    something else, and depending on a package nobody declared is how a working
    install becomes a broken one after an unrelated upgrade.

    The previous implementation used ``to_csv(sep="|")``, which is not Markdown:
    it has no header separator row and no leading or trailing pipes, so it
    rendered as one run-on paragraph rather than a table.

    Args:
        frame: Frame to render. The index becomes the first column when it is
            named, since ``compute_ranking`` returns the oversampler there.
        float_format: Format applied to floating-point cells. Raw repr leaks
            values like ``0.21000000000000002`` into a document meant to be read.

    Returns:
        A Markdown table, or a note when the frame is empty.
    """
    if frame.empty:
        return "_No results._"

    display = frame.reset_index() if frame.index.name else frame.copy()

    def render(value: Any) -> str:
        if isinstance(value, float):
            return float_format.format(value)
        return str(value)

    headers = [str(c) for c in display.columns]
    rows = [[render(v) for v in row] for row in display.itertuples(index=False)]

    widths = [
        max(len(headers[i]), *(len(r[i]) for r in rows)) if rows else len(headers[i])
        for i in range(len(headers))
    ]

    def line(cells: list[str]) -> str:
        padded = [c.ljust(w) for c, w in zip(cells, widths, strict=True)]
        return "| " + " | ".join(padded) + " |"

    separator = "| " + " | ".join("-" * w for w in widths) + " |"
    return "\n".join([line(headers), separator, *(line(r) for r in rows)])

generate_report(benchmark_results, output_format='markdown', output_path=None, include_plots=True, fidelity_reports=None)

Generate a report from benchmark results.

Parameters:

Name Type Description Default
benchmark_results DataFrame

Benchmark results dataframe.

required
output_format str

Output format (markdown or html).

'markdown'
output_path str | None

Optional output file path.

None
include_plots bool

Whether to include plot artifacts.

True
fidelity_reports dict[str, Any] | None

Optional mapping of oversampler name to :class:~oversampleqa.fidelity.FidelityReport. When given, a fidelity section is appended covering the axis the error rate cannot express.

None

Returns:

Type Description
str

Rendered report content as a string.

Raises:

Type Description
ValueError

If output_format is not recognised.

Source code in src/oversampleqa/report.py
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
def generate_report(
    benchmark_results: pd.DataFrame,
    output_format: str = "markdown",
    output_path: str | None = None,
    include_plots: bool = True,
    fidelity_reports: dict[str, Any] | None = None,
) -> str:
    """Generate a report from benchmark results.

    Args:
        benchmark_results: Benchmark results dataframe.
        output_format: Output format (``markdown`` or ``html``).
        output_path: Optional output file path.
        include_plots: Whether to include plot artifacts.
        fidelity_reports: Optional mapping of oversampler name to
            :class:`~oversampleqa.fidelity.FidelityReport`. When given, a
            fidelity section is appended covering the axis the error rate
            cannot express.

    Returns:
        Rendered report content as a string.

    Raises:
        ValueError: If ``output_format`` is not recognised.
    """
    if output_format not in {"markdown", "html"}:
        raise ValueError("output_format must be 'markdown' or 'html'")

    summary = compute_ranking(benchmark_results)
    if output_format == "markdown":
        content = "\n".join(
            [
                "# OversampleQA Report",
                "",
                "## Run metadata",
                "",
                report_metadata_markdown(benchmark_results),
                "",
                "## Ranking",
                "",
                frame_to_markdown(summary),
            ]
        )
    else:
        content = (
            "<h1>OversampleQA Report</h1><h2>Run metadata</h2>"
            + report_metadata_html(benchmark_results)
            + "<h2>Ranking</h2>"
            + summary.to_html()
        )

    if fidelity_reports:
        content += _fidelity_section(fidelity_reports, output_format)

    if include_plots and output_path:
        base = str(output_path).rsplit(".", 1)[0]
        box_path = base + "_box.png"
        rank_path = base + "_rank.png"
        plot_error_boxplot(benchmark_results, save_path=box_path)
        plot_error_ranking(benchmark_results, save_path=rank_path)
        if output_format == "markdown":
            content += f"\n\n![boxplot]({box_path})\n![ranking]({rank_path})\n"

    if output_path:
        with open(output_path, "w", encoding="utf-8") as f:
            f.write(content)
        write_export_metadata(
            output_path,
            export_kind="benchmark_report",
            data=summary,
            extra={
                "source": {
                    "row_count": len(benchmark_results),
                    "columns": [str(column) for column in benchmark_results.columns],
                    "attrs": dict(benchmark_results.attrs),
                }
            },
        )
    return content