Skip to content

Commit 11842d4

Browse files
feat(bokeh): implement line-filled (#6486)
## Implementation: `line-filled` - python/bokeh Implements the **python/bokeh** version of `line-filled`. **File:** `plots/line-filled/implementations/python/bokeh.py` **Parent Issue:** #2643 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25749578526)* --------- 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 d6d4c46 commit 11842d4

2 files changed

Lines changed: 220 additions & 142 deletions

File tree

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
line-filled: Filled Line Plot
3-
Library: bokeh 3.8.1 | Python 3.13.11
4-
Quality: 91/100 | Created: 2025-12-30
3+
Library: bokeh 3.9.0 | Python 3.13.13
4+
Quality: 91/100 | Updated: 2026-05-12
55
"""
66

7+
import os
8+
import time
9+
from pathlib import Path
10+
711
import numpy as np
8-
from bokeh.io import export_png, save
12+
from bokeh.io import output_file, save
913
from bokeh.models import ColumnDataSource, HoverTool
1014
from bokeh.plotting import figure
11-
from bokeh.resources import CDN
15+
from selenium import webdriver
16+
from selenium.webdriver.chrome.options import Options
17+
1218

19+
# Theme tokens
20+
THEME = os.getenv("ANYPLOT_THEME", "light")
21+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
22+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
23+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
24+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
25+
BRAND = "#009E73"
1326

1427
# Data - Monthly website traffic over a year
1528
np.random.seed(42)
@@ -29,19 +42,19 @@
2942
p = figure(
3043
width=4800,
3144
height=2700,
32-
title="line-filled · bokeh · pyplots.ai",
45+
title="line-filled · bokeh · anyplot.ai",
3346
x_axis_label="Month",
34-
y_axis_label="Website Visitors",
47+
y_axis_label="Website Visitors (count)",
3548
)
3649

3750
# Filled area using varea
38-
p.varea(x="month", y1="traffic_zero", y2="traffic", source=source, fill_color="#306998", fill_alpha=0.4)
51+
p.varea(x="month", y1="traffic_zero", y2="traffic", source=source, fill_color=BRAND, fill_alpha=0.35)
3952

4053
# Line on top of the fill
41-
p.line(x="month", y="traffic", source=source, line_color="#306998", line_width=4)
54+
p.line(x="month", y="traffic", source=source, line_color=BRAND, line_width=4)
4255

4356
# Add points for visual emphasis
44-
p.scatter(x="month", y="traffic", source=source, size=12, color="#306998", fill_alpha=0.8)
57+
p.scatter(x="month", y="traffic", source=source, size=12, color=BRAND, fill_alpha=0.8)
4558

4659
# Add hover tool
4760
hover = HoverTool(tooltips=[("Month", "@month"), ("Visitors", "@traffic{0,0}")])
@@ -54,21 +67,53 @@
5467
p.xaxis.major_label_text_font_size = "18pt"
5568
p.yaxis.major_label_text_font_size = "18pt"
5669

70+
# Theme-adaptive text colors
71+
p.title.text_color = INK
72+
p.xaxis.axis_label_text_color = INK
73+
p.yaxis.axis_label_text_color = INK
74+
p.xaxis.major_label_text_color = INK_SOFT
75+
p.yaxis.major_label_text_color = INK_SOFT
76+
5777
# Grid styling
58-
p.xgrid.grid_line_alpha = 0.3
59-
p.ygrid.grid_line_alpha = 0.3
60-
p.xgrid.grid_line_dash = [6, 4]
61-
p.ygrid.grid_line_dash = [6, 4]
78+
p.xgrid.grid_line_alpha = 0.10
79+
p.ygrid.grid_line_alpha = 0.10
80+
p.xgrid.grid_line_color = INK
81+
p.ygrid.grid_line_color = INK
82+
83+
# Axis styling
84+
p.xaxis.axis_line_color = INK_SOFT
85+
p.yaxis.axis_line_color = INK_SOFT
86+
p.xaxis.major_tick_line_color = INK_SOFT
87+
p.yaxis.major_tick_line_color = INK_SOFT
6288

6389
# Background
64-
p.background_fill_color = "#fafafa"
65-
p.border_fill_color = "#ffffff"
90+
p.background_fill_color = PAGE_BG
91+
p.border_fill_color = PAGE_BG
92+
p.outline_line_color = INK_SOFT
6693

6794
# X-axis ticks for each month
6895
p.xaxis.ticker = list(range(1, 13))
6996

70-
# Save as PNG and HTML
71-
export_png(p, filename="plot.png")
97+
# Save as interactive HTML
98+
output_file(f"plot-{THEME}.html")
99+
save(p)
100+
101+
# Screenshot with headless Chrome
102+
W, H = 4800, 2700
103+
opts = Options()
104+
for arg in (
105+
"--headless=new",
106+
"--no-sandbox",
107+
"--disable-dev-shm-usage",
108+
"--disable-gpu",
109+
f"--window-size={W},{H}",
110+
"--hide-scrollbars",
111+
):
112+
opts.add_argument(arg)
72113

73-
# Also save interactive HTML
74-
save(p, filename="plot.html", resources=CDN, title="line-filled · bokeh · pyplots.ai")
114+
driver = webdriver.Chrome(options=opts)
115+
driver.set_window_size(W, H)
116+
driver.get(f"file://{Path(f'plot-{THEME}.html').resolve()}")
117+
time.sleep(3) # Let bokeh's JS render the canvas
118+
driver.save_screenshot(f"plot-{THEME}.png")
119+
driver.quit()

0 commit comments

Comments
 (0)