|
1 | 1 | """ anyplot.ai |
2 | 2 | gauge-basic: Basic Gauge Chart |
3 | | -Library: plotly 6.7.0 | Python 3.14.4 |
4 | | -Quality: 94/100 | Updated: 2026-04-25 |
| 3 | +Library: plotly 6.8.0 | Python 3.13.14 |
| 4 | +Quality: 94/100 | Updated: 2026-06-30 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import os |
|
17 | 17 | INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" |
18 | 18 | INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" |
19 | 19 |
|
20 | | -# Okabe-Ito colorblind-safe stand-ins for the red/amber/green convention |
21 | | -ZONE_LOW = "#AE3030" # imprint red — bad |
22 | | -ZONE_MID = "#DDCC77" # imprint amber — caution |
23 | | -ZONE_HIGH = "#009E73" # imprint green — good |
| 20 | +# Imprint palette zone colors: red=bad, amber=caution, green=good |
| 21 | +ZONE_LOW = "#AE3030" # Imprint matte red — At Risk |
| 22 | +ZONE_MID = "#DDCC77" # Imprint amber — On Track |
| 23 | +ZONE_HIGH = "#009E73" # Imprint brand green — Exceeds Target |
24 | 24 |
|
25 | 25 | # Data — Sales target achievement for the quarter |
26 | 26 | value = 72 |
27 | 27 | min_value = 0 |
28 | 28 | max_value = 100 |
29 | 29 | thresholds = [30, 70] |
30 | 30 |
|
| 31 | +goal = thresholds[1] |
| 32 | + |
31 | 33 | # Plot |
32 | 34 | fig = go.Figure( |
33 | 35 | go.Indicator( |
34 | | - mode="gauge+number", |
| 36 | + mode="gauge+number+delta", |
35 | 37 | value=value, |
36 | | - number={"font": {"size": 96, "color": INK}, "suffix": "%"}, |
| 38 | + number={"font": {"size": 48, "color": INK, "family": "Arial"}, "suffix": "%"}, |
| 39 | + delta={ |
| 40 | + "reference": goal, |
| 41 | + "relative": False, |
| 42 | + "valueformat": "+.0f", |
| 43 | + "suffix": "pp vs. goal", |
| 44 | + "font": {"size": 13, "color": INK, "family": "Arial"}, |
| 45 | + "increasing": {"color": ZONE_HIGH}, |
| 46 | + "decreasing": {"color": ZONE_LOW}, |
| 47 | + }, |
37 | 48 | title={ |
38 | 49 | "text": ( |
39 | 50 | "<b>Sales Target Achievement</b>" |
40 | | - f"<br><span style='font-size:22px;color:{INK_SOFT}'>" |
41 | | - "gauge-basic · plotly · anyplot.ai</span>" |
| 51 | + f"<br><span style='font-size:11px;color:{INK_SOFT}'>" |
| 52 | + "gauge-basic · python · plotly · anyplot.ai</span>" |
42 | 53 | ), |
43 | | - "font": {"size": 32, "color": INK}, |
| 54 | + "font": {"size": 16, "color": INK, "family": "Arial"}, |
44 | 55 | }, |
45 | 56 | gauge={ |
46 | 57 | "shape": "angular", |
47 | 58 | "axis": { |
48 | 59 | "range": [min_value, max_value], |
49 | | - "tickwidth": 2, |
| 60 | + "tickwidth": 1, |
50 | 61 | "tickcolor": INK_SOFT, |
51 | | - "tickfont": {"size": 18, "color": INK_SOFT}, |
| 62 | + "tickfont": {"size": 10, "color": INK_SOFT, "family": "Arial"}, |
52 | 63 | "ticksuffix": "%", |
53 | 64 | "dtick": 10, |
54 | 65 | }, |
55 | | - # Slim needle-style indicator so the zone colors stay visible |
| 66 | + # Slim needle keeps zone colors fully visible |
56 | 67 | "bar": {"color": INK, "thickness": 0.06, "line": {"color": INK, "width": 0}}, |
57 | 68 | "bgcolor": ELEVATED_BG, |
58 | 69 | "borderwidth": 1, |
|
62 | 73 | {"range": [thresholds[0], thresholds[1]], "color": ZONE_MID}, |
63 | 74 | {"range": [thresholds[1], max_value], "color": ZONE_HIGH}, |
64 | 75 | ], |
65 | | - "threshold": {"line": {"color": INK, "width": 5}, "thickness": 0.95, "value": value}, |
| 76 | + "threshold": {"line": {"color": INK, "width": 3}, "thickness": 0.95, "value": value}, |
66 | 77 | }, |
67 | 78 | domain={"x": [0.05, 0.95], "y": [0.30, 0.95]}, |
68 | 79 | ) |
69 | 80 | ) |
70 | 81 |
|
71 | | -# Layout — page surface + zone legend + target-exceeded callout |
| 82 | +# Layout — page surface + zone legend + callout |
72 | 83 | fig.update_layout( |
73 | 84 | paper_bgcolor=PAGE_BG, |
74 | 85 | plot_bgcolor=PAGE_BG, |
75 | 86 | font={"family": "Arial", "color": INK}, |
76 | | - margin={"l": 80, "r": 80, "t": 140, "b": 120}, |
| 87 | + autosize=False, |
| 88 | + margin={"l": 40, "r": 40, "t": 70, "b": 60}, |
77 | 89 | annotations=[ |
78 | 90 | # Zone legend row — three color-coded chips below the gauge |
79 | 91 | { |
|
82 | 94 | "xref": "paper", |
83 | 95 | "yref": "paper", |
84 | 96 | "text": ( |
85 | | - f"<span style='color:{ZONE_LOW};font-size:24px'>●</span> " |
| 97 | + f"<span style='color:{ZONE_LOW};font-size:13px'>●</span> " |
86 | 98 | f"<b>At Risk</b> " |
87 | 99 | f"<span style='color:{INK_MUTED}'>0–30%</span>" |
88 | 100 | ), |
89 | 101 | "showarrow": False, |
90 | | - "font": {"size": 18, "color": INK}, |
| 102 | + "font": {"size": 12, "color": INK, "family": "Arial"}, |
91 | 103 | }, |
92 | 104 | { |
93 | 105 | "x": 0.50, |
94 | 106 | "y": 0.14, |
95 | 107 | "xref": "paper", |
96 | 108 | "yref": "paper", |
97 | 109 | "text": ( |
98 | | - f"<span style='color:{ZONE_MID};font-size:24px'>●</span> " |
| 110 | + f"<span style='color:{ZONE_MID};font-size:13px'>●</span> " |
99 | 111 | f"<b>On Track</b> " |
100 | 112 | f"<span style='color:{INK_MUTED}'>30–70%</span>" |
101 | 113 | ), |
102 | 114 | "showarrow": False, |
103 | | - "font": {"size": 18, "color": INK}, |
| 115 | + "font": {"size": 12, "color": INK, "family": "Arial"}, |
104 | 116 | }, |
105 | 117 | { |
106 | 118 | "x": 0.80, |
107 | 119 | "y": 0.14, |
108 | 120 | "xref": "paper", |
109 | 121 | "yref": "paper", |
110 | 122 | "text": ( |
111 | | - f"<span style='color:{ZONE_HIGH};font-size:24px'>●</span> " |
| 123 | + f"<span style='color:{ZONE_HIGH};font-size:13px'>●</span> " |
112 | 124 | f"<b>Exceeds Target</b> " |
113 | 125 | f"<span style='color:{INK_MUTED}'>70–100%</span>" |
114 | 126 | ), |
115 | 127 | "showarrow": False, |
116 | | - "font": {"size": 18, "color": INK}, |
| 128 | + "font": {"size": 12, "color": INK, "family": "Arial"}, |
117 | 129 | }, |
118 | | - # Target-exceeded callout — emphasises the threshold-crossing story |
| 130 | + # Target-exceeded callout — immediate data story |
119 | 131 | { |
120 | 132 | "x": 0.5, |
121 | | - "y": 0.02, |
| 133 | + "y": 0.03, |
122 | 134 | "xref": "paper", |
123 | 135 | "yref": "paper", |
124 | 136 | "text": "<b>✓ Target Exceeded</b> · 72% surpasses the 70% goal", |
125 | 137 | "showarrow": False, |
126 | | - "font": {"size": 22, "color": ZONE_HIGH}, |
| 138 | + "font": {"size": 12, "color": ZONE_HIGH, "family": "Arial"}, |
127 | 139 | "bgcolor": ELEVATED_BG, |
128 | 140 | "bordercolor": ZONE_HIGH, |
129 | | - "borderwidth": 2, |
130 | | - "borderpad": 12, |
| 141 | + "borderwidth": 1, |
| 142 | + "borderpad": 6, |
131 | 143 | }, |
132 | 144 | ], |
133 | 145 | ) |
134 | 146 |
|
135 | 147 | # Save |
136 | | -fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3) |
| 148 | +fig.write_image(f"plot-{THEME}.png", width=800, height=450, scale=4) |
137 | 149 | fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn") |
0 commit comments