Skip to content

Commit 1863880

Browse files
update(density-basic): bokeh — comprehensive quality review (#4383)
## Summary Updated **bokeh** implementation for **density-basic**. **Changes:** Comprehensive quality review ### Changes - Added HoverTool with vline mode for interactive density inspection - Added NumeralTickFormatter for cleaner y-axis display - Refined grid to y-only at 15% opacity, removed tick marks - Improved rug plot visibility - Quality: 85/100 (local self-evaluation, after 1 iteration) ## Test Plan - [x] Preview images uploaded to GCS staging - [x] Implementation file passes ruff format/check - [x] Metadata YAML updated with current versions - [ ] Automated review triggered --- Generated with [Claude Code](https://claude.com/claude-code) `/update` command --------- 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 556c76e commit 1863880

2 files changed

Lines changed: 226 additions & 138 deletions

File tree

plots/density-basic/implementations/bokeh.py

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
""" pyplots.ai
22
density-basic: Basic Density Plot
3-
Library: bokeh 3.8.1 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: bokeh 3.8.2 | Python 3.14.3
4+
Quality: 91/100 | Updated: 2026-02-23
55
"""
66

77
import numpy as np
88
from bokeh.io import export_png
9-
from bokeh.models import ColumnDataSource
9+
from bokeh.models import ColumnDataSource, HoverTool, Label, NumeralTickFormatter
1010
from bokeh.plotting import figure
1111

1212

@@ -32,20 +32,32 @@
3232
density += np.exp(-0.5 * ((x_range - xi) / bandwidth) ** 2)
3333
density /= n * bandwidth * np.sqrt(2 * np.pi)
3434

35+
# Identify peaks for visual storytelling
36+
peak1_idx = np.argmax(density[:250])
37+
peak2_idx = 250 + np.argmax(density[250:])
38+
peak1_x, peak1_y = x_range[peak1_idx], density[peak1_idx]
39+
peak2_x, peak2_y = x_range[peak2_idx], density[peak2_idx]
40+
3541
# Create data source
3642
source = ColumnDataSource(data={"x": x_range, "density": density})
3743

44+
# Highlight regions around each peak (for visual emphasis)
45+
mask1 = (x_range > peak1_x - 60) & (x_range < peak1_x + 60)
46+
mask2 = (x_range > peak2_x - 55) & (x_range < peak2_x + 55)
47+
highlight1 = ColumnDataSource(data={"x": x_range[mask1], "density": density[mask1]})
48+
highlight2 = ColumnDataSource(data={"x": x_range[mask2], "density": density[mask2]})
49+
3850
# Rug plot data (individual observations)
39-
rug_y_pos = -0.0004 # Position below x-axis
51+
rug_y_pos = -0.0006
4052
rug_source = ColumnDataSource(
4153
data={
4254
"x": response_times,
4355
"y0": np.full_like(response_times, rug_y_pos),
44-
"y1": np.full_like(response_times, rug_y_pos + 0.0004),
56+
"y1": np.full_like(response_times, rug_y_pos + 0.0008),
4557
}
4658
)
4759

48-
# Create figure (4800 x 2700 px for 16:9 landscape)
60+
# Create figure
4961
p = figure(
5062
width=4800,
5163
height=2700,
@@ -55,36 +67,82 @@
5567
)
5668

5769
# Fill under the curve
58-
p.varea(x="x", y1=0, y2="density", source=source, fill_color="#306998", fill_alpha=0.35)
70+
p.varea(x="x", y1=0, y2="density", source=source, fill_color="#306998", fill_alpha=0.25)
5971

6072
# Density curve
61-
p.line(x="x", y="density", source=source, line_color="#306998", line_width=5, line_alpha=0.95)
73+
density_line = p.line(x="x", y="density", source=source, line_color="#306998", line_width=6, line_alpha=0.9)
74+
75+
# Emphasize peak regions with darker fill
76+
p.varea(x="x", y1=0, y2="density", source=highlight1, fill_color="#306998", fill_alpha=0.15)
77+
p.varea(x="x", y1=0, y2="density", source=highlight2, fill_color="#306998", fill_alpha=0.15)
78+
79+
# Annotate peaks for data storytelling
80+
p.add_layout(
81+
Label(
82+
x=peak1_x,
83+
y=peak1_y,
84+
text="Fast Responses",
85+
text_font_size="22pt",
86+
text_color="#1a3d5c",
87+
text_font_style="bold",
88+
text_align="center",
89+
y_offset=18,
90+
)
91+
)
92+
p.add_layout(
93+
Label(
94+
x=peak2_x,
95+
y=peak2_y,
96+
text="Slower Responses",
97+
text_font_size="22pt",
98+
text_color="#1a3d5c",
99+
text_font_style="bold",
100+
text_align="center",
101+
y_offset=18,
102+
)
103+
)
104+
105+
# Hover tool showing density values at cursor position
106+
hover = HoverTool(
107+
renderers=[density_line],
108+
tooltips=[("Response Time", "@x{0.0} ms"), ("Density", "@density{0.00000}")],
109+
mode="vline",
110+
line_policy="nearest",
111+
)
112+
p.add_tools(hover)
62113

63114
# Rug plot - vertical segments at bottom
64-
p.segment(x0="x", y0="y0", x1="x", y1="y1", source=rug_source, line_color="#306998", line_width=2, line_alpha=0.5)
115+
p.segment(x0="x", y0="y0", x1="x", y1="y1", source=rug_source, line_color="#306998", line_width=3, line_alpha=0.65)
65116

66-
# Style text sizes for large canvas (scaled up)
117+
# Text sizes for large canvas
67118
p.title.text_font_size = "36pt"
68119
p.xaxis.axis_label_text_font_size = "28pt"
69120
p.yaxis.axis_label_text_font_size = "28pt"
70121
p.xaxis.major_label_text_font_size = "22pt"
71122
p.yaxis.major_label_text_font_size = "22pt"
72123

73-
# Axis styling
74-
p.xaxis.axis_line_width = 2
75-
p.yaxis.axis_line_width = 2
76-
p.xaxis.major_tick_line_width = 2
77-
p.yaxis.major_tick_line_width = 2
124+
# Y-axis tick format
125+
p.yaxis.formatter = NumeralTickFormatter(format="0.0000")
126+
127+
# Axis styling - softened to match minimalist chrome
128+
p.xaxis.axis_line_width = 1
129+
p.yaxis.axis_line_width = 1
130+
p.xaxis.axis_line_alpha = 0.5
131+
p.yaxis.axis_line_alpha = 0.5
132+
p.xaxis.minor_tick_line_color = None
133+
p.yaxis.minor_tick_line_color = None
134+
p.xaxis.major_tick_line_color = None
135+
p.yaxis.major_tick_line_color = None
78136

79-
# Grid styling
80-
p.xgrid.grid_line_alpha = 0.3
81-
p.ygrid.grid_line_alpha = 0.3
82-
p.xgrid.grid_line_dash = "dashed"
83-
p.ygrid.grid_line_dash = "dashed"
137+
# Grid - y-axis only, subtle
138+
p.xgrid.grid_line_color = None
139+
p.ygrid.grid_line_alpha = 0.15
140+
p.ygrid.grid_line_width = 1
84141

85142
# Background
86143
p.background_fill_color = "#fafafa"
87144
p.border_fill_color = "#ffffff"
145+
p.outline_line_color = None
88146

89147
# Remove toolbar
90148
p.toolbar_location = None

0 commit comments

Comments
 (0)