File size: 5,770 Bytes
1d0f191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
64
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
"""The admission predicted-vs-observed figure.

Design §15 phase 4 lists "admission predicted-vs-observed plot generated" as an
exit criterion, and it did not exist. These tests cover the part that can go
wrong silently: the plot must not hide the finding.

The finding is that the fit has a negative intercept and the measured marginal
peaks are mostly zero. A chart with a truncated y-axis, or one that clips
negative values, would render that as an ordinary-looking graph and defeat the
point of generating it.
"""

from __future__ import annotations

import re
import xml.etree.ElementTree as ET

import pytest

from forgesight.bench.plot import Series, _nice_ticks, predicted_vs_observed_svg

# The real shape from data/reports/report-2026-10-05.json: the measured marginal
# peaks are ~0 for b=1,2,4 and jump at b=8, and the fitted intercept is negative.
REAL = Series(
    label="egret-medium / onnxruntime",
    samples={1: 81_920, 2: 0, 4: 0, 8: 128_909_312},
    m0=-39_183_405.0,
    m_item=19_050_000.0,
    valid=False,
)


def test_it_is_wellformed_svg():
    svg = predicted_vs_observed_svg([REAL])
    # Parses as XML: a malformed chart is worse than no chart, because a broken
    # image in a tracked report is easy to miss.
    root = ET.fromstring(svg)
    assert root.tag.endswith("svg")


def test_it_is_deterministic():
    """The figure is tracked in git, so it must not churn between runs."""
    assert predicted_vs_observed_svg([REAL]) == predicted_vs_observed_svg([REAL])


def test_the_negative_intercept_is_not_clipped_away():
    """A truncated axis would hide the entire finding.

    The fit's intercept is below zero, which is what makes it invalid. Clamping
    the axis at zero would draw a dashed line starting at the floor and make the
    claim look ordinary.

    Asserted on the rendered y-axis tick labels rather than by scraping
    coordinates out of the `points` attribute. An earlier version regexed the
    polyline for `[\d.]+` before a comma, which cannot match a leading minus --
    so the assertion passed for the wrong reason on a chart that did clip. The
    axis labels are what a reader actually sees, and a negative one on the scale
    is direct evidence the range was not clamped.
    """
    svg = predicted_vs_observed_svg([REAL])
    ticks = re.findall(r'text-anchor="end">(-?[\d.]+[KM]?)</text>', svg)
    assert ticks, "no y-axis ticks were rendered"
    assert any(t.startswith("-") for t in ticks), (
        f"no negative tick on the y-axis; the negative intercept was clipped "
        f"(ticks={ticks})"
    )


def test_the_zero_marginal_peaks_are_plotted_not_skipped():
    """Three of the four samples are zero, and those zeros are the result.

    Filtering them would produce a tidy rising line through three points and
    hide the fact that batch size 1 through 4 cost nothing measurable.
    """
    svg = predicted_vs_observed_svg([REAL])
    titles = re.findall(r"<title>([^<]+)</title>", svg)
    assert len(titles) == len(REAL.samples), (
        f"expected one marker per sample, got {len(titles)} for {len(REAL.samples)}"
    )
    # b=2 and b=4 measured exactly zero. b=1 measured 81920 bytes, which is not
    # zero and must not be labelled as such: an earlier version rounded to whole
    # megabytes and rendered all three as "0 MB", collapsing a real 82 KB sample
    # into the very thing the chart is about.
    zeros = [t for t in titles if t.endswith("measured 0")]
    assert len(zeros) == 2, f"expected exactly the two true zeros, got {zeros}"
    tiny = [t for t in titles if "measured 80K" in t]
    assert tiny, f"the 82 KB sample was not labelled in KB; titles={titles}"


def test_an_invalid_fit_is_drawn_dashed_and_labelled():
    svg = predicted_vs_observed_svg([REAL])
    assert "stroke-dasharray" in svg, "an unusable fit is not marked as unusable"
    assert "not usable" in svg, "the figure does not say the fit is unusable"


def test_a_valid_fit_is_not_marked_unusable():
    ok = Series(label="x", samples={1: 10, 2: 20, 4: 40}, m0=5, m_item=10, valid=True)
    svg = predicted_vs_observed_svg([ok])
    assert "not usable" not in svg


def test_a_single_sample_still_renders():
    """One point has no line to join, so the polyline must degrade to markers."""
    svg = predicted_vs_observed_svg([Series(label="one", samples={2: 5},
                                            m0=1, m_item=2, valid=True)])
    assert "<circle" in svg
    ET.fromstring(svg)


def test_multiple_series_are_distinguished():
    a = Series(label="torch", samples={1: 10, 2: 20}, m0=5, m_item=8, valid=True)
    b = Series(label="ort", samples={1: 12, 2: 22}, m0=6, m_item=8, valid=True)
    svg = predicted_vs_observed_svg([a, b])
    assert "torch" in svg and "ort" in svg
    ET.fromstring(svg)


def test_empty_series_is_refused():
    """Better to fail than to emit a chart with no axes labelled."""
    with pytest.raises(ValueError, match="no series"):
        predicted_vs_observed_svg([])


def test_ticks_cover_the_range_and_are_ordered():
    ticks = _nice_ticks(0, 100)
    assert ticks == sorted(ticks)
    assert ticks[0] <= 0 and ticks[-1] >= 100


def test_ticks_survive_a_degenerate_range():
    """All samples identical: the axis must still render rather than divide by zero."""
    flat = Series(label="flat", samples={1: 5, 2: 5}, m0=5, m_item=0, valid=True)
    svg = predicted_vs_observed_svg([flat])
    ET.fromstring(svg)


def test_no_nan_or_inf_reaches_the_output():
    """A NaN coordinate silently drops the whole shape in most renderers."""
    for s in (REAL, Series(label="z", samples={1: 0}, m0=0, m_item=0, valid=True)):
        svg = predicted_vs_observed_svg([s])
        assert "nan" not in svg.lower()
        assert "inf" not in svg.lower()