Spaces:
Runtime error
Runtime error
Commit ·
09e1c5e
1
Parent(s): 9511d23
fix(cp5): close PNG figures on error + force Agg + _title unit tests
Browse files- proteus/viz/png.py +9 -7
- tests/viz/test_png.py +26 -0
proteus/viz/png.py
CHANGED
|
@@ -36,7 +36,7 @@ def write_pngs(
|
|
| 36 |
"""Render every frame to `<out_dir>/frame_NNN.png`; return the paths in order."""
|
| 37 |
import matplotlib
|
| 38 |
|
| 39 |
-
matplotlib.use("Agg") # headless
|
| 40 |
import matplotlib.pyplot as plt
|
| 41 |
|
| 42 |
out_dir = Path(out_dir)
|
|
@@ -47,12 +47,14 @@ def write_pngs(
|
|
| 47 |
# scale: int = 4, color_map: Optional[dict] = None) -> ndarray
|
| 48 |
# The first `steps` arg is a display counter (ignored inside the function).
|
| 49 |
rgb = frame_to_rgb_array(0, step.frame, scale, COLOR_MAP)
|
| 50 |
-
fig, ax = plt.subplots(figsize=(4.0, 4.4))
|
| 51 |
-
ax.imshow(rgb, interpolation="nearest")
|
| 52 |
-
ax.axis("off")
|
| 53 |
-
ax.set_title(_title(step), fontsize=9)
|
| 54 |
path = out_dir / f"frame_{i:03d}.png"
|
| 55 |
-
fig
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
paths.append(path)
|
| 58 |
return paths
|
|
|
|
| 36 |
"""Render every frame to `<out_dir>/frame_NNN.png`; return the paths in order."""
|
| 37 |
import matplotlib
|
| 38 |
|
| 39 |
+
matplotlib.use("Agg", force=True) # headless; force switch even if a GUI backend pre-loaded pyplot via the engine
|
| 40 |
import matplotlib.pyplot as plt
|
| 41 |
|
| 42 |
out_dir = Path(out_dir)
|
|
|
|
| 47 |
# scale: int = 4, color_map: Optional[dict] = None) -> ndarray
|
| 48 |
# The first `steps` arg is a display counter (ignored inside the function).
|
| 49 |
rgb = frame_to_rgb_array(0, step.frame, scale, COLOR_MAP)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
path = out_dir / f"frame_{i:03d}.png"
|
| 51 |
+
fig, ax = plt.subplots(figsize=(4.0, 4.4))
|
| 52 |
+
try:
|
| 53 |
+
ax.imshow(rgb, interpolation="nearest")
|
| 54 |
+
ax.axis("off")
|
| 55 |
+
ax.set_title(_title(step), fontsize=9)
|
| 56 |
+
fig.savefig(path, dpi=100, bbox_inches="tight")
|
| 57 |
+
finally:
|
| 58 |
+
plt.close(fig)
|
| 59 |
paths.append(path)
|
| 60 |
return paths
|
tests/viz/test_png.py
CHANGED
|
@@ -34,3 +34,29 @@ def test_write_pngs_creates_missing_dir(tmp_path):
|
|
| 34 |
paths = write_pngs(steps, nested)
|
| 35 |
assert nested.is_dir()
|
| 36 |
assert len(paths) == len(steps)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
paths = write_pngs(steps, nested)
|
| 35 |
assert nested.is_dir()
|
| 36 |
assert len(paths) == len(steps)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
from proteus.viz.png import _title
|
| 40 |
+
from proteus.viz.reconstruct import FrameMeta, FrameStep
|
| 41 |
+
import numpy as np
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def _step(meta):
|
| 45 |
+
return FrameStep(np.zeros((2, 2), dtype=int), meta)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def test_title_cut_phase():
|
| 49 |
+
assert _title(_step(FrameMeta(phase="cut", index=1))) == "Cut 1 (pre-roll)"
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def test_title_play_congruent_no_terminal():
|
| 53 |
+
meta = FrameMeta(phase="play", index=2, turn_idx=2, action="up", was_congruent=True)
|
| 54 |
+
assert _title(_step(meta)) == "Turn 2: action=up ✓"
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def test_title_play_diverged_with_terminal():
|
| 58 |
+
meta = FrameMeta(
|
| 59 |
+
phase="play", index=3, turn_idx=3, action="down",
|
| 60 |
+
was_congruent=False, terminal="survived",
|
| 61 |
+
)
|
| 62 |
+
assert _title(_step(meta)) == "Turn 3: action=down ✗ [survived]"
|