Skip to content

Commit 29c244c

Browse files
feat(plotly): implement gauge-basic (#5393)
## Implementation: `gauge-basic` - python/plotly Implements the **python/plotly** version of `gauge-basic`. **File:** `plots/gauge-basic/implementations/python/plotly.py` **Parent Issue:** #857 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/24931039693)* --------- 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 8c24003 commit 29c244c

2 files changed

Lines changed: 263 additions & 152 deletions

File tree

Lines changed: 107 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,137 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
gauge-basic: Basic Gauge Chart
3-
Library: plotly 6.5.0 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: plotly 6.7.0 | Python 3.14.4
4+
Quality: 94/100 | Updated: 2026-04-25
55
"""
66

7+
import os
8+
79
import plotly.graph_objects as go
810

911

10-
# Data - Sales performance against quarterly target
11-
value = 72 # Current sales achievement percentage
12+
# Theme tokens
13+
THEME = os.getenv("ANYPLOT_THEME", "light")
14+
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
15+
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
16+
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
17+
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
18+
INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
19+
20+
# Okabe-Ito colorblind-safe stand-ins for the red/amber/green convention
21+
ZONE_LOW = "#D55E00" # vermillion (bad)
22+
ZONE_MID = "#E69F00" # orange (caution)
23+
ZONE_HIGH = "#009E73" # bluish green — Okabe-Ito brand (good)
24+
25+
# Data — Sales target achievement for the quarter
26+
value = 72
1227
min_value = 0
1328
max_value = 100
14-
thresholds = [30, 70] # Red/Yellow/Green zones
29+
thresholds = [30, 70]
1530

16-
# Create gauge chart
31+
# Plot
1732
fig = go.Figure(
1833
go.Indicator(
1934
mode="gauge+number",
2035
value=value,
36+
number={"font": {"size": 96, "color": INK}, "suffix": "%"},
2137
title={
22-
"text": "Sales Target Achievement<br><span style='font-size:24px'>gauge-basic · plotly · pyplots.ai</span>",
23-
"font": {"size": 32},
38+
"text": (
39+
"<b>Sales Target Achievement</b>"
40+
f"<br><span style='font-size:22px;color:{INK_SOFT}'>"
41+
"gauge-basic · plotly · anyplot.ai</span>"
42+
),
43+
"font": {"size": 32, "color": INK},
2444
},
25-
number={"font": {"size": 72}, "suffix": "%"},
2645
gauge={
46+
"shape": "angular",
2747
"axis": {
2848
"range": [min_value, max_value],
29-
"tickwidth": 3,
30-
"tickcolor": "#306998",
31-
"tickfont": {"size": 22},
49+
"tickwidth": 2,
50+
"tickcolor": INK_SOFT,
51+
"tickfont": {"size": 18, "color": INK_SOFT},
3252
"ticksuffix": "%",
3353
"dtick": 10,
3454
},
35-
"bar": {"color": "#306998", "thickness": 0.25},
36-
"bgcolor": "white",
37-
"borderwidth": 3,
38-
"bordercolor": "#306998",
55+
# Slim needle-style indicator so the zone colors stay visible
56+
"bar": {"color": INK, "thickness": 0.06, "line": {"color": INK, "width": 0}},
57+
"bgcolor": ELEVATED_BG,
58+
"borderwidth": 1,
59+
"bordercolor": INK_SOFT,
3960
"steps": [
40-
{"range": [min_value, thresholds[0]], "color": "#FF6B6B"},
41-
{"range": [thresholds[0], thresholds[1]], "color": "#FFD43B"},
42-
{"range": [thresholds[1], max_value], "color": "#4CAF50"},
61+
{"range": [min_value, thresholds[0]], "color": ZONE_LOW},
62+
{"range": [thresholds[0], thresholds[1]], "color": ZONE_MID},
63+
{"range": [thresholds[1], max_value], "color": ZONE_HIGH},
4364
],
44-
"threshold": {"line": {"color": "#306998", "width": 8}, "thickness": 0.85, "value": value},
65+
"threshold": {"line": {"color": INK, "width": 5}, "thickness": 0.95, "value": value},
4566
},
46-
domain={"x": [0.05, 0.95], "y": [0.1, 0.95]},
67+
domain={"x": [0.05, 0.95], "y": [0.30, 0.95]},
4768
)
4869
)
4970

50-
# Layout for 4800x2700 px
71+
# Layout — page surface + zone legend + target-exceeded callout
5172
fig.update_layout(
52-
font={"family": "Arial", "size": 22},
53-
paper_bgcolor="white",
54-
plot_bgcolor="white",
55-
margin={"l": 80, "r": 80, "t": 120, "b": 60},
73+
paper_bgcolor=PAGE_BG,
74+
plot_bgcolor=PAGE_BG,
75+
font={"family": "Arial", "color": INK},
76+
margin={"l": 80, "r": 80, "t": 140, "b": 120},
77+
annotations=[
78+
# Zone legend row — three color-coded chips below the gauge
79+
{
80+
"x": 0.20,
81+
"y": 0.14,
82+
"xref": "paper",
83+
"yref": "paper",
84+
"text": (
85+
f"<span style='color:{ZONE_LOW};font-size:24px'>●</span> "
86+
f"<b>At Risk</b> "
87+
f"<span style='color:{INK_MUTED}'>0–30%</span>"
88+
),
89+
"showarrow": False,
90+
"font": {"size": 18, "color": INK},
91+
},
92+
{
93+
"x": 0.50,
94+
"y": 0.14,
95+
"xref": "paper",
96+
"yref": "paper",
97+
"text": (
98+
f"<span style='color:{ZONE_MID};font-size:24px'>●</span> "
99+
f"<b>On Track</b> "
100+
f"<span style='color:{INK_MUTED}'>30–70%</span>"
101+
),
102+
"showarrow": False,
103+
"font": {"size": 18, "color": INK},
104+
},
105+
{
106+
"x": 0.80,
107+
"y": 0.14,
108+
"xref": "paper",
109+
"yref": "paper",
110+
"text": (
111+
f"<span style='color:{ZONE_HIGH};font-size:24px'>●</span> "
112+
f"<b>Exceeds Target</b> "
113+
f"<span style='color:{INK_MUTED}'>70–100%</span>"
114+
),
115+
"showarrow": False,
116+
"font": {"size": 18, "color": INK},
117+
},
118+
# Target-exceeded callout — emphasises the threshold-crossing story
119+
{
120+
"x": 0.5,
121+
"y": 0.02,
122+
"xref": "paper",
123+
"yref": "paper",
124+
"text": "<b>✓ Target Exceeded</b> · 72% surpasses the 70% goal",
125+
"showarrow": False,
126+
"font": {"size": 22, "color": ZONE_HIGH},
127+
"bgcolor": ELEVATED_BG,
128+
"bordercolor": ZONE_HIGH,
129+
"borderwidth": 2,
130+
"borderpad": 12,
131+
},
132+
],
56133
)
57134

58-
# Save as PNG and HTML
59-
fig.write_image("plot.png", width=1600, height=900, scale=3)
60-
fig.write_html("plot.html")
135+
# Save
136+
fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3)
137+
fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")

0 commit comments

Comments
 (0)