Skip to content

Commit 4d54914

Browse files
feat(pygal): implement radar-multi (#10299)
## Implementation: `radar-multi` - python/pygal Implements the **python/pygal** version of `radar-multi`. **File:** `plots/radar-multi/implementations/python/pygal.py` **Parent Issue:** #2026 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/32046977179)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent c339da7 commit 4d54914

2 files changed

Lines changed: 175 additions & 115 deletions

File tree

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,90 @@
11
""" anyplot.ai
22
radar-multi: Multi-Series Radar Chart
3-
Library: pygal 3.1.0 | Python 3.13.13
4-
Quality: 86/100 | Updated: 2026-05-07
3+
Library: pygal 3.1.3 | Python 3.13.15
4+
Quality: 90/100 | Updated: 2026-08-17
55
"""
66

7+
import os
8+
79
import pygal
810
from pygal.style import Style
911

1012

13+
# Theme tokens (see prompts/default-style-guide.md "Background" + "Theme-adaptive Chrome")
14+
THEME = os.getenv("ANYPLOT_THEME", "light")
15+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
16+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
17+
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
18+
19+
# Imprint categorical palette — position 1 is always the brand green
20+
IMPRINT_PALETTE = ("#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030", "#2ABCCD", "#954477", "#99B314")
21+
1122
# Data - Team performance comparison across skill dimensions
1223
categories = ["Communication", "Technical", "Leadership", "Creativity", "Teamwork", "Problem Solving"]
13-
teams = {
14-
"Alpha Team": [85, 90, 75, 80, 88, 82],
15-
"Beta Team": [78, 72, 85, 90, 70, 88],
16-
"Gamma Team": [65, 88, 70, 75, 92, 78],
17-
}
24+
teams = [
25+
("Alpha Team", [85, 90, 75, 80, 88, 82]),
26+
("Beta Team", [78, 72, 85, 90, 70, 88]),
27+
("Gamma Team", [65, 88, 70, 75, 92, 78]),
28+
]
1829

19-
# Custom style for 3600x3600 canvas (square for radar)
30+
# Highest overall average becomes the visual "hero" series — a bolder, solid
31+
# stroke and larger dots build a focal point so the viewer immediately spots
32+
# the top all-round team, while the other two recede behind a thinner dashed
33+
# outline.
34+
hero_name, _ = max(teams, key=lambda t: sum(t[1]) / len(t[1]))
35+
36+
# Style — theme-adaptive chrome, Imprint palette, sizing tuned for the 2400x2400 canvas
2037
custom_style = Style(
21-
background="white",
22-
plot_background="white",
23-
foreground="#333333",
24-
foreground_strong="#333333",
25-
foreground_subtle="#666666",
26-
colors=("#306998", "#FFD43B", "#E74C3C"),
27-
title_font_size=72,
28-
label_font_size=42,
29-
major_label_font_size=36,
30-
legend_font_size=42,
31-
value_font_size=32,
38+
font_family='"Liberation Sans", "DejaVu Sans", Arial, sans-serif',
39+
background=PAGE_BG,
40+
plot_background=PAGE_BG,
41+
foreground=INK,
42+
foreground_strong=INK,
43+
foreground_subtle=INK_MUTED,
44+
colors=IMPRINT_PALETTE,
45+
title_font_size=66,
46+
label_font_size=56,
47+
major_label_font_size=44,
48+
legend_font_size=44,
49+
value_font_size=36,
3250
opacity=0.25,
3351
opacity_hover=0.5,
3452
)
3553

36-
# Create radar chart
54+
# Plot — square canvas for the symmetric radar layout. Legend moved to the
55+
# bottom (rather than the default left column) so the polar plot area is no
56+
# longer squeezed toward the top-right of the canvas, balancing whitespace.
3757
chart = pygal.Radar(
38-
width=3600,
39-
height=3600,
58+
width=2400,
59+
height=2400,
4060
style=custom_style,
41-
title="radar-multi · pygal · pyplots.ai",
61+
title="radar-multi · python · pygal · anyplot.ai",
4262
show_legend=True,
43-
legend_at_bottom=False,
44-
legend_box_size=30,
45-
dots_size=12,
46-
stroke_style={"width": 5},
63+
legend_at_bottom=True,
64+
legend_at_bottom_columns=3,
4765
show_dots=True,
4866
fill=True,
4967
inner_radius=0.1,
5068
range=(0, 100),
69+
margin=30,
70+
spacing=16,
5171
)
52-
53-
# Set axis labels
5472
chart.x_labels = categories
5573

56-
# Add data series
57-
for team_name, values in teams.items():
58-
chart.add(team_name, values)
74+
# Add data series — hero team gets a bold solid stroke + larger dots, the
75+
# other two recede behind a thinner dashed outline.
76+
for team_name, values in teams:
77+
is_hero = team_name == hero_name
78+
chart.add(
79+
team_name,
80+
values,
81+
dots_size=12 if is_hero else 7,
82+
stroke_style={"width": 6, "linecap": "round", "linejoin": "round"}
83+
if is_hero
84+
else {"width": 2.5, "linecap": "round", "linejoin": "round", "dasharray": "12,6"},
85+
)
5986

60-
# Save outputs
61-
chart.render_to_png("plot.png")
62-
chart.render_to_file("plot.html")
87+
# Save
88+
chart.render_to_png(f"plot-{THEME}.png")
89+
with open(f"plot-{THEME}.html", "wb") as f:
90+
f.write(chart.render())

0 commit comments

Comments
 (0)