Skip to content

Commit 10b29b8

Browse files
feat(pygal): implement rug-basic (#5590)
## Implementation: `rug-basic` - python/pygal Implements the **python/pygal** version of `rug-basic`. **File:** `plots/rug-basic/implementations/python/pygal.py` **Parent Issue:** #978 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25148765512)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 1a8a3e4 commit 10b29b8

2 files changed

Lines changed: 285 additions & 70 deletions

File tree

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,93 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
rug-basic: Basic Rug Plot
3-
Library: pygal 3.1.0 | Python 3.13.11
4-
Quality: 85/100 | Created: 2025-12-23
3+
Library: pygal 3.1.0 | Python 3.13.13
4+
Quality: 81/100 | Updated: 2026-04-30
55
"""
66

7+
import os
8+
import sys
9+
710
import numpy as np
8-
import pygal
9-
from pygal.style import Style
1011

1112

12-
# Data - Response times (in milliseconds) showing realistic clustering patterns
13+
# Pop script directory so local pygal.py doesn't shadow the installed package
14+
_script_dir = sys.path.pop(0)
15+
import pygal # noqa: E402
16+
from pygal.style import Style # noqa: E402
17+
18+
19+
sys.path.insert(0, _script_dir)
20+
21+
# Theme tokens
22+
THEME = os.getenv("ANYPLOT_THEME", "light")
23+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
24+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
25+
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
26+
BRAND = "#009E73" # Okabe-Ito position 1
27+
28+
# Data - API response times (ms) with realistic multi-modal distribution
1329
np.random.seed(42)
1430
values = np.concatenate(
1531
[
16-
np.random.normal(150, 20, 60), # Main cluster of typical responses
17-
np.random.normal(250, 30, 25), # Slower responses
18-
np.random.normal(400, 15, 10), # Occasional outliers
19-
np.random.uniform(50, 100, 5), # Very fast responses
32+
np.random.normal(150, 20, 60), # Typical fast responses
33+
np.random.normal(250, 30, 25), # Medium responses
34+
np.random.normal(400, 15, 10), # Slow outlier cluster
35+
np.random.uniform(50, 100, 5), # Very fast cache hits
2036
]
2137
)
22-
values = np.clip(values, 30, 500) # Realistic bounds
23-
values = np.sort(values) # Sort for better visual ordering
38+
values = np.clip(values, 30, 500)
39+
values = np.sort(values)
2440

25-
# Custom style - keep text readable, minimize distracting elements
41+
# Style - single color so all rug ticks share brand green
2642
custom_style = Style(
27-
background="white",
28-
plot_background="white",
29-
foreground="#333333",
30-
foreground_strong="#333333",
31-
foreground_subtle="#666666",
32-
colors=("#306998",), # Python Blue
33-
title_font_size=72,
34-
label_font_size=48,
35-
major_label_font_size=42,
36-
legend_font_size=42,
37-
value_font_size=36,
38-
opacity=0.85,
39-
opacity_hover=1.0,
40-
tooltip_font_size=36,
43+
background=PAGE_BG,
44+
plot_background=PAGE_BG,
45+
foreground=INK,
46+
foreground_strong=INK,
47+
foreground_subtle=INK_MUTED,
48+
colors=(BRAND,), # All ticks cycle through brand green only
49+
title_font_size=28,
50+
label_font_size=22,
51+
major_label_font_size=18,
52+
legend_font_size=16,
53+
value_font_size=14,
54+
stroke_width=8,
55+
opacity=0.7,
4156
)
4257

43-
# Create XY chart for rug plot visualization
58+
# Plot - XY chart used as rug plot
4459
chart = pygal.XY(
4560
width=4800,
4661
height=2700,
4762
style=custom_style,
48-
title="rug-basic · pygal · pyplots.ai",
63+
title="rug-basic · pygal · anyplot.ai",
4964
x_title="Response Time (ms)",
5065
y_title=None,
5166
show_legend=False,
5267
show_dots=False,
5368
stroke=True,
54-
stroke_style={"width": 10},
5569
show_x_guides=False,
5670
show_y_guides=False,
5771
show_y_labels=False,
5872
print_values=False,
5973
explicit_size=True,
60-
margin=80,
61-
margin_top=180,
62-
margin_bottom=280,
63-
margin_left=80,
64-
margin_right=80,
65-
tooltip_border_radius=10,
66-
xrange=(30, 450),
67-
range=(0, 1),
74+
margin=100,
75+
margin_top=220,
76+
margin_bottom=300,
77+
xrange=(30, 520),
78+
range=(0, 0.2),
6879
)
6980

70-
# Rug ticks - uniform height filling 90% of vertical canvas
71-
tick_bottom = 0.05
72-
tick_top = 0.95
81+
# Rug ticks - short vertical marks along the x-axis
82+
tick_bottom = 0.0
83+
tick_top = 0.15
7384

74-
# Add rug ticks with interactive tooltips showing exact values
7585
for val in values:
76-
x = float(val)
77-
chart.add(f"{val:.1f} ms", [(x, tick_bottom), (x, tick_top)], stroke_style={"width": 10}, show_dots=False)
86+
chart.add(
87+
f"{val:.1f} ms", [(float(val), tick_bottom), (float(val), tick_top)], stroke_style={"width": 8}, show_dots=False
88+
)
7889

79-
# Save outputs - HTML preserves pygal's SVG interactivity with hover tooltips
80-
chart.render_to_png("plot.png")
81-
chart.render_to_file("plot.html")
90+
# Save
91+
chart.render_to_png(f"plot-{THEME}.png")
92+
with open(f"plot-{THEME}.html", "wb") as f:
93+
f.write(chart.render())

0 commit comments

Comments
 (0)