Skip to content

Commit c9a6424

Browse files
feat(bokeh): implement slider-control-basic (#3111)
## Implementation: `slider-control-basic` - bokeh Implements the **bokeh** version of `slider-control-basic`. **File:** `plots/slider-control-basic/implementations/bokeh.py` **Parent Issue:** #3071 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20620344869)* --------- 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 5c39236 commit c9a6424

2 files changed

Lines changed: 172 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
""" pyplots.ai
2+
slider-control-basic: Interactive Plot with Slider Control
3+
Library: bokeh 3.8.1 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-31
5+
"""
6+
7+
import numpy as np
8+
from bokeh.io import export_png, save
9+
from bokeh.layouts import column
10+
from bokeh.models import ColumnDataSource, CustomJS, Label, Legend, LegendItem, Slider
11+
from bokeh.plotting import figure
12+
13+
14+
# Data - Sales data across multiple years
15+
np.random.seed(42)
16+
17+
years = list(range(2018, 2025))
18+
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
19+
20+
# Generate sales data for each year with realistic growth trend
21+
all_data = {}
22+
for year in years:
23+
base = 50 + (year - 2018) * 8 # Growth trend
24+
seasonal = np.array([0.8, 0.75, 0.9, 1.0, 1.1, 1.15, 1.2, 1.15, 1.05, 1.1, 1.25, 1.4])
25+
noise = np.random.normal(0, 5, 12)
26+
sales = base * seasonal + noise
27+
all_data[year] = sales.tolist()
28+
29+
# Initial data for 2024 (most recent year)
30+
initial_year = 2024
31+
source = ColumnDataSource(data={"months": months, "sales": all_data[initial_year]})
32+
33+
# Create figure with categorical x-axis
34+
p = figure(
35+
width=4800,
36+
height=2700,
37+
x_range=months,
38+
y_range=(0, 180),
39+
title=f"Monthly Sales ({initial_year}) · slider-control-basic · bokeh · pyplots.ai",
40+
x_axis_label="Month",
41+
y_axis_label="Sales (thousands USD)",
42+
tools="pan,wheel_zoom,box_zoom,reset,save",
43+
toolbar_location="right",
44+
)
45+
46+
# Style the plot for large canvas (4800x2700)
47+
p.title.text_font_size = "42pt"
48+
p.xaxis.axis_label_text_font_size = "32pt"
49+
p.yaxis.axis_label_text_font_size = "32pt"
50+
p.xaxis.major_label_text_font_size = "24pt"
51+
p.yaxis.major_label_text_font_size = "24pt"
52+
53+
# Add bar chart
54+
bars = p.vbar(
55+
x="months",
56+
top="sales",
57+
source=source,
58+
width=0.7,
59+
fill_color="#306998",
60+
line_color="#306998",
61+
fill_alpha=0.85,
62+
line_width=2,
63+
)
64+
65+
# Add line connecting the bars
66+
trend_line = p.line(x="months", y="sales", source=source, line_width=4, line_color="#FFD43B", line_alpha=0.9)
67+
68+
# Add scatter points on top of bars
69+
trend_points = p.scatter(
70+
x="months",
71+
y="sales",
72+
source=source,
73+
size=20,
74+
fill_color="#FFD43B",
75+
line_color="#306998",
76+
line_width=3,
77+
fill_alpha=1.0,
78+
)
79+
80+
# Add legend
81+
legend = Legend(
82+
items=[
83+
LegendItem(label="Monthly Sales", renderers=[bars]),
84+
LegendItem(label="Trend Line", renderers=[trend_line, trend_points]),
85+
],
86+
location="top_left",
87+
label_text_font_size="24pt",
88+
spacing=20,
89+
padding=20,
90+
background_fill_alpha=0.8,
91+
)
92+
p.add_layout(legend, "right")
93+
94+
# Style grid
95+
p.xgrid.grid_line_color = None
96+
p.ygrid.grid_line_alpha = 0.3
97+
p.ygrid.grid_line_dash = [6, 4]
98+
99+
# Background
100+
p.background_fill_color = "#fafafa"
101+
p.border_fill_color = "#ffffff"
102+
103+
# Create slider with width proportional to plot (4800 * 0.8 = 3840)
104+
slider = Slider(
105+
start=2018, end=2024, value=2024, step=1, title="Select Year (2018-2024)", width=3840, bar_color="#306998"
106+
)
107+
108+
# Add annotation to indicate interactive functionality (visible in static PNG context)
109+
interactive_note = Label(
110+
x=3800,
111+
y=170,
112+
x_units="screen",
113+
y_units="data",
114+
text="[Interactive] Use slider to change year (2018-2024)",
115+
text_font_size="22pt",
116+
text_color="#666666",
117+
text_align="right",
118+
)
119+
p.add_layout(interactive_note)
120+
121+
# Prepare data for JavaScript callback
122+
all_data_js = {str(k): v for k, v in all_data.items()}
123+
124+
# JavaScript callback for slider interaction
125+
callback = CustomJS(
126+
args={"source": source, "all_data": all_data_js, "title": p.title},
127+
code="""
128+
const year = cb_obj.value;
129+
const data = source.data;
130+
data['sales'] = all_data[year.toString()];
131+
source.change.emit();
132+
title.text = 'Monthly Sales (' + year + ') · slider-control-basic · bokeh · pyplots.ai';
133+
""",
134+
)
135+
136+
slider.js_on_change("value", callback)
137+
138+
# Layout with slider below the plot
139+
layout = column(p, slider, sizing_mode="fixed")
140+
141+
# Save as HTML (interactive version)
142+
save(layout, filename="plot.html", title="slider-control-basic · bokeh · pyplots.ai")
143+
144+
# Export static PNG (shows 2024 data)
145+
export_png(p, filename="plot.png")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library: bokeh
2+
specification_id: slider-control-basic
3+
created: '2025-12-31T13:56:20Z'
4+
updated: '2025-12-31T14:24:16Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20620344869
7+
issue: 3071
8+
python_version: 3.13.11
9+
library_version: 3.8.1
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/slider-control-basic/bokeh/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/slider-control-basic/bokeh/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/slider-control-basic/bokeh/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent implementation of interactive slider control with CustomJS callback
17+
for client-side updates
18+
- Clean visual design with professional color scheme (Python blue/yellow)
19+
- Proper title format including dynamic year update in callback
20+
- Good use of ColumnDataSource pattern for data management
21+
- Generates both static PNG and interactive HTML outputs appropriately
22+
- Seasonal sales pattern adds realistic data variation
23+
weaknesses:
24+
- Legend area shows some visual artifacts/rendering issues on the right side
25+
- Missing HoverTool which would enhance the interactive experience by showing exact
26+
values on hover
27+
- The interactive note annotation could be more visually integrated

0 commit comments

Comments
 (0)