Skip to content

Commit 2f34828

Browse files
feat(letsplot): implement box-horizontal (#6407)
## Implementation: `box-horizontal` - python/letsplot Implements the **python/letsplot** version of `box-horizontal`. **File:** `plots/box-horizontal/implementations/python/letsplot.py` **Parent Issue:** #2548 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25707004796)* --------- 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 9e50f33 commit 2f34828

2 files changed

Lines changed: 204 additions & 149 deletions

File tree

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,47 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
box-horizontal: Horizontal Box Plot
3-
Library: letsplot 4.8.2 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-30
3+
Library: letsplot 4.9.0 | Python 3.13.13
4+
Quality: 87/100 | Updated: 2026-05-12
55
"""
66

7+
import os
8+
79
import numpy as np
810
import pandas as pd
911
from lets_plot import *
1012

1113

1214
LetsPlot.setup_html()
1315

14-
# Data - Response times by service type (realistic scenario with varied distributions)
16+
# Theme tokens
17+
THEME = os.getenv("ANYPLOT_THEME", "light")
18+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
19+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
20+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
21+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
22+
BRAND = "#009E73" # Okabe-Ito position 1
23+
24+
# Data - Response times by service type
1525
np.random.seed(42)
1626

1727
services = ["API Gateway", "Database Query", "Authentication", "File Storage", "Cache Lookup", "Email Service"]
1828

1929
data = []
20-
# Different distributions to showcase boxplot features (medians, spreads, outliers)
2130
distributions = {
22-
"API Gateway": (120, 40, 3), # Medium response, moderate spread, some outliers
23-
"Database Query": (250, 100, 5), # Slower, high variability, more outliers
24-
"Authentication": (80, 25, 2), # Fast, consistent
25-
"File Storage": (300, 80, 4), # Slowest, variable
26-
"Cache Lookup": (15, 8, 2), # Very fast, tight distribution
27-
"Email Service": (180, 60, 6), # Medium, some outliers
31+
"API Gateway": (120, 40, 3),
32+
"Database Query": (250, 100, 5),
33+
"Authentication": (80, 25, 2),
34+
"File Storage": (300, 80, 4),
35+
"Cache Lookup": (15, 8, 2),
36+
"Email Service": (180, 60, 6),
2837
}
2938

3039
for service in services:
3140
mean, std, n_outliers = distributions[service]
32-
# Main distribution
3341
values = np.random.normal(mean, std, 80)
34-
# Add some outliers
3542
outliers = np.random.normal(mean + 4 * std, std / 2, n_outliers)
3643
all_values = np.concatenate([values, outliers])
37-
all_values = np.maximum(all_values, 5) # Ensure positive values
44+
all_values = np.maximum(all_values, 5)
3845

3946
for val in all_values:
4047
data.append({"Service": service, "Response Time (ms)": val})
@@ -45,23 +52,27 @@
4552
plot = (
4653
ggplot(df, aes(x="Response Time (ms)", y="Service"))
4754
+ geom_boxplot(
48-
fill="#306998", color="#1a3a4f", alpha=0.7, outlier_color="#FFD43B", outlier_size=4, outlier_alpha=0.8, size=1.2
55+
fill=BRAND, color=INK_SOFT, alpha=0.7, outlier_color=INK_SOFT, outlier_size=4, outlier_alpha=0.6, size=1.0
4956
)
50-
+ labs(x="Response Time (ms)", y="Service Type", title="box-horizontal · letsplot · pyplots.ai")
57+
+ labs(x="Response Time (ms)", y="Service Type", title="box-horizontal · letsplot · anyplot.ai")
5158
+ theme_minimal()
5259
+ theme(
53-
axis_title=element_text(size=20),
54-
axis_text=element_text(size=16),
55-
axis_text_y=element_text(size=16),
56-
plot_title=element_text(size=24),
60+
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
61+
panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
62+
axis_title=element_text(size=20, color=INK),
63+
axis_text=element_text(size=16, color=INK_SOFT),
64+
axis_text_y=element_text(size=16, color=INK_SOFT),
65+
plot_title=element_text(size=24, color=INK),
66+
panel_grid_major_x=element_line(color=INK_SOFT, size=0.2),
5767
panel_grid_major_y=element_blank(),
5868
panel_grid_minor=element_blank(),
69+
axis_line=element_line(color=INK_SOFT, size=0.5),
5970
)
6071
+ ggsize(1600, 900)
6172
)
6273

63-
# Save as PNG (scale 3x to get 4800 x 2700 px)
64-
ggsave(plot, "plot.png", path=".", scale=3)
74+
# Save PNG (scale 3x to get 4800 x 2700 px)
75+
ggsave(plot, f"plot-{THEME}.png", path=".", scale=3)
6576

66-
# Save interactive HTML version
67-
ggsave(plot, "plot.html", path=".")
77+
# Save interactive HTML
78+
ggsave(plot, f"plot-{THEME}.html", path=".")

0 commit comments

Comments
 (0)