Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 41 additions & 33 deletions plots/bland-altman-basic/implementations/python/letsplot.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
""" pyplots.ai
""" anyplot.ai
bland-altman-basic: Bland-Altman Agreement Plot
Library: letsplot 4.8.2 | Python 3.13.11
Quality: 92/100 | Created: 2025-12-25
Library: letsplot 4.9.0 | Python 3.13.13
Quality: 92/100 | Updated: 2026-05-07
"""

import os

import numpy as np
import pandas as pd
from lets_plot import *


LetsPlot.setup_html()

# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"

# Okabe-Ito palette
BRAND = "#009E73" # Position 1 - first categorical series
SECONDARY = "#D55E00" # Position 2
ACCENT = "#0072B2" # Position 3

# Data: Simulated blood pressure readings from two sphygmomanometers
np.random.seed(42)
n = 80
Expand Down Expand Up @@ -38,7 +52,7 @@

# Annotation data - position labels at the left side with offset from line
annot_x = df["mean"].min() + 2
y_offset = 0.8 # Offset so labels don't overlap lines
y_offset = 0.8
annot_df = pd.DataFrame(
{
"x": [annot_x, annot_x, annot_x],
Expand All @@ -48,60 +62,54 @@
f"+1.96 SD: {upper_loa:.2f} mmHg",
f"-1.96 SD: {lower_loa:.2f} mmHg",
],
"color": ["bias", "loa", "loa"],
"line_type": ["bias", "loa", "loa"],
}
)

# Build plot
# Build plot with theme-adaptive styling
plot = (
ggplot()
# Scatter points
+ geom_point(aes(x="mean", y="diff"), data=df, color="#306998", size=5, alpha=0.7)
# Mean difference line (bias)
+ geom_hline(yintercept=mean_diff, color="#16a34a", size=1.5)
# Upper limit of agreement
+ geom_hline(yintercept=upper_loa, color="#dc2626", size=1.2, linetype="dashed")
# Lower limit of agreement
+ geom_hline(yintercept=lower_loa, color="#dc2626", size=1.2, linetype="dashed")
# Annotations using geom_label for better visibility
+ geom_point(aes(x="mean", y="diff"), data=df, color=BRAND, size=6, alpha=0.7, stroke=0.5)
+ geom_hline(yintercept=mean_diff, color=BRAND, size=1.5)
+ geom_hline(yintercept=upper_loa, color=SECONDARY, size=1.2, linetype="dashed")
+ geom_hline(yintercept=lower_loa, color=SECONDARY, size=1.2, linetype="dashed")
+ geom_label(
aes(x="x", y="y", label="label"),
data=annot_df[annot_df["color"] == "bias"],
data=annot_df[annot_df["line_type"] == "bias"],
size=12,
color="#16a34a",
fill="white",
color=BRAND,
fill=ELEVATED_BG,
hjust=0,
label_padding=0.3,
)
+ geom_label(
aes(x="x", y="y", label="label"),
data=annot_df[annot_df["color"] == "loa"],
data=annot_df[annot_df["line_type"] == "loa"],
size=12,
color="#dc2626",
fill="white",
color=SECONDARY,
fill=ELEVATED_BG,
hjust=0,
label_padding=0.3,
)
# Labels and title
+ labs(
x="Mean of Two Methods (mmHg)",
y="Difference (Method 1 - Method 2) (mmHg)",
title="bland-altman-basic · letsplot · pyplots.ai",
title="bland-altman-basic · letsplot · anyplot.ai",
)
# Size and theme
+ ggsize(1600, 900)
+ theme_minimal()
+ theme(
plot_title=element_text(size=24),
axis_title=element_text(size=20),
axis_text=element_text(size=16),
panel_grid_major=element_line(color="#e5e5e5", size=0.5),
plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),
panel_grid_major=element_line(color=INK, size=0.3, linetype="solid"),
panel_grid_minor=element_blank(),
plot_title=element_text(size=24, color=INK),
axis_title=element_text(size=20, color=INK),
axis_text=element_text(size=16, color=INK_SOFT),
axis_line=element_line(color=INK_SOFT, size=0.5),
)
)

# Save PNG (scale 3x for 4800x2700)
ggsave(plot, "plot.png", scale=3, path=".")

# Save HTML for interactive version
ggsave(plot, "plot.html", path=".")
# Save PNG and HTML with theme-suffixed filenames
ggsave(plot, f"plot-{THEME}.png", scale=3, path=".")
ggsave(plot, f"plot-{THEME}.html", path=".")
Loading
Loading