feat(map): add peak highlights and live metrics to PNG export
- Draw rings around hottest and coldest sensors on export. - Extend export_image to support second line for live metrics. - Format detailed sensor stats in export footer. - Add test coverage for footer rows, overlays, and stats.
This commit is contained in:
@@ -111,6 +111,76 @@ def test_export_image_includes_metrics_footer(tmp_path):
|
||||
assert loaded.pixelColor(5, loaded.height() - 5).alpha() == 255
|
||||
|
||||
|
||||
def test_export_image_extra_line_grows_footer(tmp_path):
|
||||
"""Live export passes an extra metrics line; the footer gains a second
|
||||
row for it. Review export (no extra) keeps the single-row footer."""
|
||||
from PySide6.QtGui import QImage
|
||||
|
||||
from pygui.backend.visualization.wafer_map_item import WaferMapItem
|
||||
|
||||
item = WaferMapItem()
|
||||
item.setWidth(200)
|
||||
item.setHeight(200)
|
||||
item.values = [10.0, 20.0, 30.0]
|
||||
|
||||
review = tmp_path / "review.png"
|
||||
live = tmp_path / "live.png"
|
||||
assert item.export_image(str(review)) is True
|
||||
assert item.export_image(str(live), "Frames: 42 Errors: 0") is True
|
||||
|
||||
h_review = QImage(str(review)).height()
|
||||
h_live = QImage(str(live)).height()
|
||||
assert h_review > 200 # readout footer present
|
||||
assert h_live > h_review # extra live row appended
|
||||
|
||||
|
||||
def test_export_image_highlights_hottest_and_coldest(tmp_path):
|
||||
"""The exported map rings the hottest sensor in the high color and the
|
||||
coldest in the low color. With no bands set every marker fill is the
|
||||
in-range green, so any high/low-colored pixels must come from the rings."""
|
||||
from PySide6.QtGui import QImage
|
||||
|
||||
from pygui.backend.visualization.wafer_map_item import WaferMapItem
|
||||
|
||||
item = WaferMapItem()
|
||||
item.setWidth(200)
|
||||
item.setHeight(200)
|
||||
item.sensors = [
|
||||
{"label": "1", "x": -50.0, "y": 0.0},
|
||||
{"label": "2", "x": 0.0, "y": 0.0},
|
||||
{"label": "3", "x": 50.0, "y": 0.0},
|
||||
]
|
||||
item.values = [10.0, 20.0, 30.0]
|
||||
out = tmp_path / "wafer.png"
|
||||
assert item.export_image(str(out)) is True
|
||||
|
||||
img = QImage(str(out))
|
||||
found = {img.pixelColor(x, y).name()
|
||||
for y in range(img.height()) for x in range(img.width())}
|
||||
assert "#ef4444" in found # hottest ring (sensorHigh)
|
||||
assert "#5b9df5" in found # coldest ring (sensorLow)
|
||||
|
||||
|
||||
def test_readout_text_full_stats():
|
||||
"""Export footer readout carries every READOUT stat with sensor indices.
|
||||
|
||||
Worked example: [10, 20, 30] → min 10 (#1), max 30 (#3), diff 20,
|
||||
avg 20, σ = sqrt(200/3) ≈ 8.16, 3σ ≈ 24.49.
|
||||
"""
|
||||
from pygui.backend.visualization.wafer_map_item import readout_text
|
||||
|
||||
assert readout_text([10.0, 20.0, 30.0]) == (
|
||||
"Sensors: 3 Min: 10.00°C (#1) Max: 30.00°C (#3) "
|
||||
"Diff: 20.00 Avg: 20.00 σ: 8.16 3σ: 24.49"
|
||||
)
|
||||
|
||||
|
||||
def test_readout_text_empty():
|
||||
from pygui.backend.visualization.wafer_map_item import readout_text
|
||||
|
||||
assert readout_text([]) == ""
|
||||
|
||||
|
||||
def test_export_image_no_data_fails(tmp_path):
|
||||
"""No file loaded / no stream played -> nothing meaningful to export."""
|
||||
from pygui.backend.visualization.wafer_map_item import WaferMapItem
|
||||
|
||||
Reference in New Issue
Block a user