work-blog/scripts/svg-to-png.py
Gregory Gauthier 1396de6a7e feat(diagrams): add PNG diagrams for Testing Telos post
Update testing-telos.md with relative asset paths and refined content.
Add generated PNGs: telos-feature-iteration.png, telos-invariance-testing.png,
telos-cross-cutting.png, telos-targeted-concerns.png.
Introduce pyproject.toml and poetry.lock for diagram generation dependencies.
Add svg-to-png.py script for generating diagrams.
Rename drafts/testing-telos.html to references/testing-telos.html.
2026-04-17 11:46:40 +01:00

105 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Testing Telos - Diagram PNG Generator
=====================================
Generates the four high-resolution PNG diagrams for the "Testing Telos" blog post.
Saves them directly into an `assets/` folder (created automatically if missing).
Run this script once in the root of your work-blog repository:
python3 generate-telos-diagrams.py
It will produce:
assets/telos-feature-iteration.png
assets/telos-invariance-testing.png
assets/telos-cross-cutting.png
assets/telos-targeted-concerns.png
All images are 260×260 px at 300 DPI for crisp rendering on the blog.
"""
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon, Circle
import numpy as np
import os
# Ensure assets/ directory exists
os.makedirs("assets", exist_ok=True)
DPI = 300
SIZE = 260
def save_fig(fig, filename):
"""Save figure with consistent styling and transparency."""
fig.savefig(f"assets/{filename}", dpi=DPI, bbox_inches="tight", pad_inches=0.02, transparent=True)
plt.close(fig)
print(f"✓ Generated: assets/{filename}")
# 1. Feature Iteration — The Triangle (Pyramid)
fig1, ax1 = plt.subplots(figsize=(SIZE/100, SIZE/100))
ax1.set_xlim(0, 100)
ax1.set_ylim(0, 105)
ax1.set_aspect("equal")
ax1.axis("off")
# Main pyramid triangle
triangle = Polygon([[50, 12], [92, 92], [8, 92]], closed=True,
facecolor="#F8E4C4", edgecolor="#A07828", linewidth=6)
ax1.add_patch(triangle)
# Unit-test layer line (widest)
ax1.plot([22, 78], [73, 73], color="#A07828", linewidth=3)
# Integration-test layer line (middle)
ax1.plot([35, 65], [46, 46], color="#A07828", linewidth=3)
save_fig(fig1, "telos-feature-iteration.png")
# 2. Invariance Testing — The Bullseye
fig2, ax2 = plt.subplots(figsize=(SIZE/100, SIZE/100))
ax2.set_xlim(0, 100)
ax2.set_ylim(0, 100)
ax2.set_aspect("equal")
ax2.axis("off")
# Outermost ring
ax2.add_patch(Circle((50, 50), 44, facecolor="#D4B896", edgecolor="#A07828", linewidth=4))
# Middle ring
ax2.add_patch(Circle((50, 50), 29, facecolor="#C4A276", edgecolor="#8B7560", linewidth=4))
# Innermost ring
ax2.add_patch(Circle((50, 50), 14, facecolor="#A0522D", edgecolor="#7A3E20", linewidth=4))
save_fig(fig2, "telos-invariance-testing.png")
# 3. Cross-Cutting Structural Changes — The Diamond
fig3, ax3 = plt.subplots(figsize=(SIZE/100, SIZE/100))
ax3.set_xlim(0, 100)
ax3.set_ylim(0, 100)
ax3.set_aspect("equal")
ax3.axis("off")
diamond_points = [[50, 6], [94, 50], [50, 94], [6, 50]]
diamond = Polygon(diamond_points, closed=True,
facecolor="#7BA085", edgecolor="#5A7A63", linewidth=6)
ax3.add_patch(diamond)
save_fig(fig3, "telos-cross-cutting.png")
# 4. Targeted Non-Functional Concerns — The Star
fig4, ax4 = plt.subplots(figsize=(SIZE/100, SIZE/100))
ax4.set_xlim(0, 100)
ax4.set_ylim(0, 100)
ax4.set_aspect("equal")
ax4.axis("off")
# Star vertices (10-pointed star)
star_points = np.array([
[50, 4], [61, 36], [96, 36], [68, 58], [78, 92],
[50, 72], [22, 92], [32, 58], [4, 36], [39, 36]
])
star = Polygon(star_points, closed=True,
facecolor="#C07060", edgecolor="#8B4040", linewidth=6)
ax4.add_patch(star)
save_fig(fig4, "telos-targeted-concerns.png")
print("\n🎉 All four Testing Telos PNG diagrams have been generated successfully!")
print(" They are now ready to be referenced in your Markdown post.")