Skip to content

Commit 4188968

Browse files
update(bullet-basic): matplotlib — comprehensive quality review
Comprehensive quality review improving visual design, data quality, spec compliance, and library feature usage.
1 parent 1e072e3 commit 4188968

3 files changed

Lines changed: 78 additions & 57 deletions

File tree

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,128 @@
1-
""" pyplots.ai
1+
"""pyplots.ai
22
bullet-basic: Basic Bullet Chart
3-
Library: matplotlib 3.10.8 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: matplotlib 3.10.8 | Python 3.14.3
4+
Quality: /100 | Updated: 2026-02-22
55
"""
66

7+
import matplotlib.patheffects as pe
78
import matplotlib.pyplot as plt
89
from matplotlib.lines import Line2D
9-
from matplotlib.patches import Patch
10+
from matplotlib.patches import FancyBboxPatch, Patch
1011

1112

12-
# Data - Multiple KPIs with actual values, targets, and qualitative ranges
13+
# Data - Quarterly KPI dashboard with percentage-based metrics for consistent comparison
1314
metrics = [
14-
{"label": "Revenue", "actual": 275, "target": 250, "ranges": [150, 200, 300], "unit": "$K"},
15-
{"label": "Profit", "actual": 45, "target": 50, "ranges": [20, 40, 60], "unit": "%"},
16-
{"label": "New Customers", "actual": 85, "target": 100, "ranges": [50, 75, 120], "unit": ""},
17-
{"label": "Satisfaction", "actual": 4.2, "target": 4.5, "ranges": [3.0, 4.0, 5.0], "unit": "/5"},
15+
{"label": "Revenue", "actual": 92, "target": 85, "ranges": [40, 70, 100]},
16+
{"label": "Profit Margin", "actual": 38, "target": 45, "ranges": [20, 40, 60]},
17+
{"label": "Customer Growth", "actual": 71, "target": 80, "ranges": [30, 60, 100]},
18+
{"label": "Satisfaction", "actual": 84, "target": 90, "ranges": [50, 75, 100]},
19+
{"label": "On-Time Delivery", "actual": 96, "target": 95, "ranges": [60, 80, 100]},
1820
]
1921

2022
# Qualitative band colors (grayscale: poor -> satisfactory -> good)
21-
band_colors = ["#d9d9d9", "#bfbfbf", "#a6a6a6"]
23+
band_colors = ["#e0e0e0", "#c8c8c8", "#b0b0b0"]
24+
actual_color = "#306998"
25+
target_color = "#1a1a1a"
2226

2327
# Create plot (4800x2700 px)
2428
fig, ax = plt.subplots(figsize=(16, 9))
2529

26-
bar_height = 0.4
27-
spacing = 1.5
30+
bar_height = 0.32
31+
band_height = bar_height * 2.4
32+
spacing = 1.2
2833
y_positions = [i * spacing for i in range(len(metrics))]
2934

3035
for i, metric in enumerate(metrics):
3136
y = y_positions[i]
3237
ranges = metric["ranges"]
33-
max_range = ranges[-1]
3438

35-
# Draw qualitative range bands (background bands from low to high)
39+
# Draw qualitative range bands using FancyBboxPatch for rounded corners
3640
band_starts = [0] + ranges[:-1]
37-
band_ends = ranges
38-
39-
for j, (start, end) in enumerate(zip(band_starts, band_ends, strict=True)):
41+
for j, (start, end) in enumerate(zip(band_starts, ranges, strict=True)):
4042
width = end - start
41-
ax.barh(y, width, left=start, height=bar_height * 2.2, color=band_colors[j], edgecolor="none", zorder=1)
42-
43-
# Draw actual value bar (the main measure)
44-
ax.barh(y, metric["actual"], height=bar_height, color="#306998", edgecolor="none", zorder=2)
43+
box = FancyBboxPatch(
44+
(start, y - band_height / 2),
45+
width,
46+
band_height,
47+
boxstyle="round,pad=0,rounding_size=0.08",
48+
facecolor=band_colors[j],
49+
edgecolor="none",
50+
zorder=1,
51+
)
52+
ax.add_patch(box)
53+
54+
# Draw actual value bar
55+
actual_bar = FancyBboxPatch(
56+
(0, y - bar_height / 2),
57+
metric["actual"],
58+
bar_height,
59+
boxstyle="round,pad=0,rounding_size=0.06",
60+
facecolor=actual_color,
61+
edgecolor="none",
62+
zorder=2,
63+
)
64+
ax.add_patch(actual_bar)
4565

46-
# Draw target marker (vertical line)
66+
# Draw target marker (diamond with white outline for visibility)
4767
ax.plot(
48-
[metric["target"], metric["target"]],
49-
[y - bar_height * 0.7, y + bar_height * 0.7],
50-
color="#1a1a1a",
51-
linewidth=4,
52-
solid_capstyle="butt",
68+
metric["target"],
69+
y,
70+
marker="D",
71+
markersize=11,
72+
color=target_color,
5373
zorder=3,
74+
path_effects=[pe.withStroke(linewidth=3, foreground="white")],
5475
)
5576

56-
# Add actual value as text label (positioned after the max range for consistency)
57-
label_x = max_range + max_range * 0.03
77+
# Actual value label to the right of the max range
5878
ax.text(
59-
label_x,
79+
ranges[-1] + 2,
6080
y,
61-
f"{metric['actual']}{metric['unit']}",
81+
f"{metric['actual']}%",
6282
va="center",
6383
ha="left",
6484
fontsize=16,
6585
fontweight="bold",
66-
color="#306998",
86+
color=actual_color,
6787
zorder=4,
6888
)
6989

7090
# Y-axis labels (metric names)
7191
ax.set_yticks(y_positions)
72-
ax.set_yticklabels([m["label"] for m in metrics], fontsize=18)
92+
ax.set_yticklabels([m["label"] for m in metrics], fontsize=18, fontweight="bold")
7393

74-
# X-axis styling - no label since metrics have different units
94+
# X-axis label — all metrics share a percentage scale
95+
ax.set_xlabel("Performance (%)", fontsize=20)
7596
ax.tick_params(axis="x", labelsize=16)
76-
ax.tick_params(axis="y", labelsize=18)
97+
ax.tick_params(axis="y", length=0)
7798

7899
# Title
79-
ax.set_title("bullet-basic · matplotlib · pyplots.ai", fontsize=24, pad=20)
100+
ax.set_title("bullet-basic \u00b7 matplotlib \u00b7 pyplots.ai", fontsize=24, fontweight="medium", pad=20)
80101

81102
# Grid on x-axis only, subtle
82-
ax.xaxis.grid(True, alpha=0.3, linestyle="--", zorder=0)
103+
ax.xaxis.grid(True, alpha=0.2, linewidth=0.8, linestyle="--", zorder=0)
83104
ax.set_axisbelow(True)
84105

85106
# Remove spines for cleaner look
86-
ax.spines["top"].set_visible(False)
87-
ax.spines["right"].set_visible(False)
88-
ax.spines["left"].set_visible(False)
89-
90-
# Set x-axis to start at 0
91-
ax.set_xlim(left=0)
107+
for spine in ["top", "right", "left"]:
108+
ax.spines[spine].set_visible(False)
92109

93-
# Adjust y-axis limits for padding
94-
ax.set_ylim(-spacing * 0.4, y_positions[-1] + spacing * 0.4)
110+
# Set axis limits
111+
ax.set_xlim(left=0, right=112)
112+
ax.set_ylim(-spacing * 0.5, y_positions[-1] + spacing * 0.5)
95113

96114
# Invert y-axis so first metric is at top
97115
ax.invert_yaxis()
98116

99-
# Add legend
117+
# Legend
100118
legend_elements = [
101-
Patch(facecolor="#306998", edgecolor="none", label="Actual"),
102-
Line2D([0], [0], color="#1a1a1a", linewidth=4, label="Target"),
103-
Patch(facecolor="#a6a6a6", edgecolor="none", label="Good"),
104-
Patch(facecolor="#bfbfbf", edgecolor="none", label="Satisfactory"),
105-
Patch(facecolor="#d9d9d9", edgecolor="none", label="Poor"),
119+
Patch(facecolor=actual_color, edgecolor="none", label="Actual"),
120+
Line2D([0], [0], marker="D", color="w", markerfacecolor=target_color, markersize=8, label="Target"),
121+
Patch(facecolor=band_colors[2], edgecolor="none", label="Good"),
122+
Patch(facecolor=band_colors[1], edgecolor="none", label="Satisfactory"),
123+
Patch(facecolor=band_colors[0], edgecolor="none", label="Poor"),
106124
]
107-
ax.legend(handles=legend_elements, loc="lower right", fontsize=14, framealpha=0.9)
125+
ax.legend(handles=legend_elements, loc="upper center", bbox_to_anchor=(0.5, -0.08), ncol=5, fontsize=14, frameon=False)
108126

109127
plt.tight_layout()
110128
plt.savefig("plot.png", dpi=300, bbox_inches="tight")

plots/bullet-basic/metadata/matplotlib.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
library: matplotlib
22
specification_id: bullet-basic
33
created: '2025-12-23T09:18:21Z'
4-
updated: '2025-12-23T09:20:35Z'
5-
generated_by: claude-opus-4-5-20251101
4+
updated: '2026-02-22T12:00:00+00:00'
5+
generated_by: claude-opus-4-6
66
workflow_run: 20456603104
77
issue: 0
8-
python_version: 3.13.11
8+
python_version: 3.14.3
99
library_version: 3.10.8
1010
preview_url: https://storage.googleapis.com/pyplots-images/plots/bullet-basic/matplotlib/plot.png
1111
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bullet-basic/matplotlib/plot_thumb.png
1212
preview_html: null
13-
quality_score: 92
13+
quality_score: null
1414
impl_tags:
1515
dependencies: []
1616
techniques:

plots/bullet-basic/specification.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ title: Basic Bullet Chart
66

77
# Specification tracking
88
created: 2025-12-15T20:44:46Z
9-
updated: 2025-12-15T20:44:46Z
9+
updated: 2026-02-22T12:00:00Z
1010
issue: 999
1111
suggested: MarkusNeusinger
1212

@@ -15,10 +15,13 @@ tags:
1515
plot_type:
1616
- bullet
1717
- bar
18+
- gauge
1819
data_type:
1920
- numeric
21+
- categorical
2022
domain:
2123
- business
24+
- general
2225
features:
2326
- basic
2427
- comparison

0 commit comments

Comments
 (0)