Skip to content

Commit a307c96

Browse files
feat(bokeh): implement lollipop-basic (#5444)
## Implementation: `lollipop-basic` - python/bokeh Implements the **python/bokeh** version of `lollipop-basic`. **File:** `plots/lollipop-basic/implementations/python/bokeh.py` **Parent Issue:** #934 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/24956899574)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 8e6f310 commit a307c96

2 files changed

Lines changed: 189 additions & 155 deletions

File tree

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
lollipop-basic: Basic Lollipop Chart
3-
Library: bokeh 3.8.1 | Python 3.13.11
4-
Quality: 91/100 | Created: 2025-12-23
3+
Library: bokeh 3.9.0 | Python 3.14.4
4+
Quality: 85/100 | Updated: 2026-04-26
55
"""
66

7+
import os
8+
79
from bokeh.io import export_png, output_file, save
810
from bokeh.models import ColumnDataSource, NumeralTickFormatter
911
from bokeh.plotting import figure
1012

1113

12-
# Data - Product sales by category, sorted by value
14+
# Theme tokens
15+
THEME = os.getenv("ANYPLOT_THEME", "light")
16+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
17+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
18+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
19+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
20+
BRAND = "#009E73"
21+
22+
# Data — product sales by category (pre-sorted descending)
1323
categories = [
1424
"Electronics",
1525
"Clothing",
@@ -22,55 +32,60 @@
2232
"Automotive",
2333
"Office",
2434
]
25-
values = [85000, 72000, 58000, 45000, 42000, 38000, 35000, 28000, 22000, 15000]
26-
27-
# Sort by value (descending) for better readability
28-
sorted_pairs = sorted(zip(categories, values, strict=True), key=lambda x: x[1], reverse=True)
29-
categories = [p[0] for p in sorted_pairs]
30-
values = [p[1] for p in sorted_pairs]
35+
values = [85000, 72000, 61000, 53000, 47000, 39000, 33000, 28000, 22000, 15000]
3136

32-
# Create source
3337
source = ColumnDataSource(data={"categories": categories, "values": values, "zeros": [0] * len(values)})
3438

35-
# Create figure with categorical x-axis
39+
# Plot
3640
p = figure(
3741
width=4800,
3842
height=2700,
3943
x_range=categories,
40-
title="lollipop-basic · bokeh · pyplots.ai",
44+
title="lollipop-basic · bokeh · anyplot.ai",
4145
x_axis_label="Product Category",
42-
y_axis_label="Sales ($)",
46+
y_axis_label="Sales (USD)",
47+
toolbar_location=None,
4348
)
4449

45-
# Draw stems (thin lines from baseline to value)
46-
p.segment(x0="categories", y0="zeros", x1="categories", y1="values", source=source, line_width=4, color="#306998")
50+
p.segment(x0="categories", y0="zeros", x1="categories", y1="values", source=source, line_width=4, color=BRAND)
4751

48-
# Draw markers (circles at data values)
49-
p.scatter(x="categories", y="values", source=source, size=25, color="#FFD43B", line_color="#306998", line_width=3)
52+
p.scatter(x="categories", y="values", source=source, size=42, color=BRAND, line_color=PAGE_BG, line_width=3)
5053

51-
# Styling for 4800x2700 canvas
52-
p.title.text_font_size = "32pt"
53-
p.xaxis.axis_label_text_font_size = "24pt"
54-
p.yaxis.axis_label_text_font_size = "24pt"
54+
# Style
55+
p.title.text_font_size = "28pt"
56+
p.title.text_color = INK
57+
p.title.text_font_style = "normal"
58+
59+
p.xaxis.axis_label_text_font_size = "22pt"
60+
p.yaxis.axis_label_text_font_size = "22pt"
5561
p.xaxis.major_label_text_font_size = "18pt"
5662
p.yaxis.major_label_text_font_size = "18pt"
5763

58-
# Rotate x-axis labels for readability
59-
p.xaxis.major_label_orientation = 0.7
64+
p.xaxis.axis_label_text_color = INK
65+
p.yaxis.axis_label_text_color = INK
66+
p.xaxis.major_label_text_color = INK_SOFT
67+
p.yaxis.major_label_text_color = INK_SOFT
68+
69+
p.xaxis.axis_line_color = INK_SOFT
70+
p.yaxis.axis_line_color = INK_SOFT
71+
p.xaxis.major_tick_line_color = INK_SOFT
72+
p.yaxis.major_tick_line_color = INK_SOFT
73+
p.xaxis.minor_tick_line_color = None
74+
p.yaxis.minor_tick_line_color = None
75+
76+
p.xaxis.major_label_orientation = 0.6
6077

61-
# Grid styling - subtle
6278
p.xgrid.grid_line_color = None
63-
p.ygrid.grid_line_alpha = 0.3
64-
p.ygrid.grid_line_dash = "dashed"
79+
p.ygrid.grid_line_color = INK
80+
p.ygrid.grid_line_alpha = 0.10
6581

66-
# Background
67-
p.background_fill_color = "#fafafa"
68-
p.border_fill_color = "#ffffff"
82+
p.background_fill_color = PAGE_BG
83+
p.border_fill_color = PAGE_BG
84+
p.outline_line_color = None
6985

70-
# Format y-axis with thousands separator
7186
p.yaxis.formatter = NumeralTickFormatter(format="$0,0")
7287

73-
# Save as PNG and HTML
74-
export_png(p, filename="plot.png")
75-
output_file("plot.html")
88+
# Save
89+
export_png(p, filename=f"plot-{THEME}.png")
90+
output_file(f"plot-{THEME}.html")
7691
save(p)

0 commit comments

Comments
 (0)