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
52 changes: 29 additions & 23 deletions plots/slope-basic/implementations/python/pygal.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
""" anyplot.ai
slope-basic: Basic Slope Chart (Slopegraph)
Library: pygal 3.1.0 | Python 3.13.13
Quality: 86/100 | Updated: 2026-04-30
Library: pygal 3.1.3 | Python 3.13.14
Quality: 85/100 | Updated: 2026-07-25
"""

import os
Expand All @@ -21,10 +21,12 @@
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"

COLOR_INCREASE = "#009E73" # Okabe-Ito position 1 — upward change
COLOR_DECREASE = "#AE3030" # imprint red — downward change
COLOR_INCREASE = "#009E73" # Imprint palette position 1 — upward change
COLOR_DECREASE = "#AE3030" # Imprint palette position 5 — semantic anchor for downward change

# Realistic product category data — Q1 vs Q4 sales comparison
# Realistic product category data — Q1 vs Q4 sales comparison.
# Values are spread with even 7/8-unit gaps within each quarter so the
# endpoint category-name labels never crowd or overlap each other.
categories = [
"Electronics",
"Apparel",
Expand All @@ -37,8 +39,8 @@
"Beauty",
"Toys",
]
q1_sales = [85, 72, 95, 45, 68, 52, 78, 62, 88, 40]
q4_sales = [92, 58, 102, 75, 65, 71, 82, 48, 95, 55]
q1_sales = [75, 82, 103, 40, 68, 47, 89, 61, 96, 54]
q4_sales = [90, 58, 114, 74, 66, 82, 98, 42, 106, 50]

increasing = [(c, q1_sales[i], q4_sales[i]) for i, c in enumerate(categories) if q4_sales[i] >= q1_sales[i]]
decreasing = [(c, q1_sales[i], q4_sales[i]) for i, c in enumerate(categories) if q4_sales[i] < q1_sales[i]]
Expand All @@ -52,44 +54,48 @@
foreground_strong=INK,
foreground_subtle=INK_MUTED,
colors=series_colors,
title_font_size=64,
label_font_size=44,
title_font_size=66,
label_font_size=56,
major_label_font_size=44,
legend_font_size=38,
value_font_size=32,
value_label_font_size=36,
value_label_font_size=44,
# value_font_size drives pygal's dot-to-label offset (x/y = dot + value_font_size),
# not just the (unused, print_values=False) value text itself — raised well past
# the default 16 so category labels clear the y-axis line at the Q1 column.
value_font_size=40,
stroke_width=6,
)

# Slope chart: Line chart with only 2 x-axis time points
# Slope chart: Line chart with only 2 x-axis time points.
# The legend is omitted — each line already carries its category name at
# both endpoints (print_labels), and the up/down direction is self-evident
# from the slope itself, so a color legend would only duplicate that info.
chart = pygal.Line(
width=4800,
height=2700,
title="slope-basic · pygal · anyplot.ai",
width=3200,
height=1800,
title="slope-basic · python · pygal · anyplot.ai",
x_title="Time Period",
y_title="Sales (units)",
y_title="Sales (thousands of units)",
style=custom_style,
show_dots=True,
dots_size=18,
stroke_style={"width": 6},
show_y_guides=True,
show_x_guides=False,
show_legend=True,
show_legend=False,
interpolate=None,
margin=140,
print_values=False,
print_labels=True,
range=(30, 115),
margin_right=340,
range=(30, 120),
margin_right=480,
)

chart.x_labels = ["Q1 2024", "Q4 2024"]

# Increasing categories — Okabe-Ito green
# Increasing categories — Imprint brand green
for c, start, end in increasing:
chart.add(c, [{"value": start, "label": c}, {"value": end, "label": c}])

# Decreasing categories — Okabe-Ito vermillion
# Decreasing categories — Imprint matte red
for c, start, end in decreasing:
chart.add(c, [{"value": start, "label": c}, {"value": end, "label": c}])

Expand Down
Loading
Loading