Skip to content

Commit 345b4fd

Browse files
feat(bokeh): implement line-interactive (#2825)
## Implementation: `line-interactive` - bokeh Implements the **bokeh** version of `line-interactive`. **File:** `plots/line-interactive/implementations/bokeh.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20602452572)* --------- 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 4174937 commit 345b4fd

2 files changed

Lines changed: 159 additions & 0 deletions

File tree

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
""" pyplots.ai
2+
line-interactive: Interactive Line Chart with Hover and Zoom
3+
Library: bokeh 3.8.1 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-30
5+
"""
6+
7+
import numpy as np
8+
import pandas as pd
9+
from bokeh.io import export_png
10+
from bokeh.models import BoxZoomTool, ColumnDataSource, HoverTool, PanTool, ResetTool, WheelZoomTool
11+
from bokeh.plotting import figure, output_file, save
12+
13+
14+
# Data - Daily temperature readings for a year
15+
np.random.seed(42)
16+
dates = pd.date_range("2024-01-01", periods=365, freq="D")
17+
18+
# Simulate realistic temperature pattern with seasonal variation
19+
day_of_year = np.arange(365)
20+
seasonal = 15 * np.sin(2 * np.pi * (day_of_year - 80) / 365) # Peak in summer
21+
noise = np.random.normal(0, 3, 365)
22+
temperature = 12 + seasonal + noise # Base temp ~12°C
23+
24+
# Create DataFrame
25+
df = pd.DataFrame({"date": dates, "temperature": temperature})
26+
27+
# Create ColumnDataSource with formatted date for hover
28+
source = ColumnDataSource(
29+
data={
30+
"date": df["date"],
31+
"temperature": df["temperature"],
32+
"date_str": df["date"].dt.strftime("%Y-%m-%d"),
33+
"temp_str": [f"{t:.1f}" for t in df["temperature"]],
34+
}
35+
)
36+
37+
# Create figure with 4800×2700 px dimensions
38+
p = figure(
39+
width=4800,
40+
height=2700,
41+
title="line-interactive · bokeh · pyplots.ai",
42+
x_axis_label="Date",
43+
y_axis_label="Temperature (°C)",
44+
x_axis_type="datetime",
45+
tools="", # Start with empty tools, add custom ones
46+
toolbar_location="right",
47+
)
48+
49+
# Add interactive tools
50+
wheel_zoom = WheelZoomTool()
51+
pan = PanTool()
52+
box_zoom = BoxZoomTool()
53+
reset = ResetTool()
54+
55+
p.add_tools(wheel_zoom, pan, box_zoom, reset)
56+
p.toolbar.active_scroll = wheel_zoom
57+
58+
# Add hover tool with detailed tooltip
59+
hover = HoverTool(
60+
tooltips=[("Date", "@date_str"), ("Temperature", "@temp_str °C")], mode="vline", line_policy="nearest"
61+
)
62+
p.add_tools(hover)
63+
64+
# Plot line with Python Blue color
65+
p.line(
66+
x="date",
67+
y="temperature",
68+
source=source,
69+
line_width=4,
70+
line_color="#306998",
71+
alpha=0.9,
72+
legend_label="Daily Temperature",
73+
)
74+
75+
# Add circle markers at data points for hover interaction
76+
p.scatter(
77+
x="date",
78+
y="temperature",
79+
source=source,
80+
size=10,
81+
fill_color="#306998",
82+
line_color="#FFD43B",
83+
line_width=2,
84+
alpha=0.8,
85+
)
86+
87+
# Styling - Text sizes for large canvas
88+
p.title.text_font_size = "36pt"
89+
p.title.text_color = "#306998"
90+
p.xaxis.axis_label_text_font_size = "28pt"
91+
p.yaxis.axis_label_text_font_size = "28pt"
92+
p.xaxis.major_label_text_font_size = "22pt"
93+
p.yaxis.major_label_text_font_size = "22pt"
94+
95+
# Axis styling
96+
p.xaxis.axis_line_width = 3
97+
p.yaxis.axis_line_width = 3
98+
p.xaxis.major_tick_line_width = 3
99+
p.yaxis.major_tick_line_width = 3
100+
101+
# Grid styling - subtle
102+
p.xgrid.grid_line_color = "#000000"
103+
p.xgrid.grid_line_alpha = 0.2
104+
p.xgrid.grid_line_dash = "dashed"
105+
p.ygrid.grid_line_color = "#000000"
106+
p.ygrid.grid_line_alpha = 0.2
107+
p.ygrid.grid_line_dash = "dashed"
108+
109+
# Legend styling
110+
p.legend.location = "top_left"
111+
p.legend.label_text_font_size = "22pt"
112+
p.legend.glyph_width = 50
113+
p.legend.glyph_height = 50
114+
p.legend.border_line_color = "#306998"
115+
p.legend.border_line_width = 2
116+
p.legend.background_fill_alpha = 0.8
117+
118+
# Background
119+
p.background_fill_color = "#FAFAFA"
120+
p.border_fill_color = "#FFFFFF"
121+
122+
# Toolbar styling
123+
p.toolbar.logo = None
124+
125+
# Save as HTML for interactivity
126+
output_file("plot.html", title="Interactive Line Chart")
127+
save(p)
128+
129+
# Save as PNG for static preview
130+
export_png(p, filename="plot.png")
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
library: bokeh
2+
specification_id: line-interactive
3+
created: '2025-12-30T17:50:19Z'
4+
updated: '2025-12-30T18:03:47Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20602452572
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 3.8.1
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-interactive/bokeh/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-interactive/bokeh/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/line-interactive/bokeh/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent use of Bokeh interactive tools (WheelZoom, BoxZoom, PanTool, ResetTool)
17+
with wheel zoom as default active scroll
18+
- Well-configured HoverTool with vline mode and formatted date/temperature display
19+
- Appropriate text sizing for 4800x2700 canvas with readable fonts throughout
20+
- Realistic seasonal temperature data pattern demonstrating time series characteristics
21+
- Clean code structure following KISS principles with proper ColumnDataSource usage
22+
- Dual output (HTML for interactivity, PNG for preview) is best practice for Bokeh
23+
weaknesses:
24+
- Legend placement in top_left overlaps with data peaks in winter months - consider
25+
top_right or outside placement
26+
- Missing RangeSlider or RangeTool widget for quick time range navigation as specified
27+
in requirements
28+
- Marker size could be reduced to 6-8 with alpha 0.6 for 365 data points to reduce
29+
visual clutter

0 commit comments

Comments
 (0)