From ef4222d687a581e31b96b5a924c110e7306d0664 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:40:55 +0100 Subject: [PATCH 1/8] =?UTF-8?q?update(bubble-packed):=20matplotlib=20?= =?UTF-8?q?=E2=80=94=20comprehensive=20quality=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comprehensive review improving code quality, data choice, visual design, spec compliance, and library feature usage. --- .../implementations/matplotlib.py | 186 ++++++++++-------- plots/bubble-packed/metadata/matplotlib.yaml | 10 +- plots/bubble-packed/specification.yaml | 6 +- 3 files changed, 117 insertions(+), 85 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index 71e2c2a196..63c3bc6cd3 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,16 +1,16 @@ -""" pyplots.ai +"""pyplots.ai bubble-packed: Basic Packed Bubble Chart -Library: matplotlib 3.10.8 | Python 3.13.11 -Quality: 92/100 | Created: 2025-12-23 +Library: matplotlib 3.10.8 | Python 3.14.3 +Quality: /100 | Updated: 2026-02-23 """ +import matplotlib.collections as mcoll import matplotlib.patches as mpatches import matplotlib.pyplot as plt import numpy as np # Data - Department budget allocation (in thousands) -np.random.seed(42) labels = [ "Engineering", "Marketing", @@ -28,131 +28,144 @@ "Security", "QA", ] -values = [850, 420, 680, 320, 180, 290, 750, 210, 150, 380, 240, 550, 460, 170, 195] - -# Colors by group (Python Blue primary, Yellow secondary, others colorblind-safe) -colors = [ - "#306998", # Engineering - Blue (Tech) - "#FFD43B", # Marketing - Yellow (Business) - "#306998", # Sales - Blue (Revenue) - "#4A90A4", # Operations - Teal (Support) - "#4A90A4", # HR - Teal (Support) - "#4A90A4", # Finance - Teal (Support) - "#FFD43B", # R&D - Yellow (Innovation) - "#4A90A4", # Customer Support - Teal (Support) - "#7B9E89", # Legal - Sage (Compliance) - "#306998", # IT - Blue (Tech) - "#FFD43B", # Design - Yellow (Creative) - "#306998", # Product - Blue (Tech) - "#FFD43B", # Data Science - Yellow (Analytics) - "#7B9E89", # Security - Sage (Compliance) - "#7B9E89", # QA - Sage (Quality) -] +values = [950, 420, 680, 310, 160, 280, 820, 200, 130, 370, 230, 580, 470, 145, 175] + +# Group assignments and colors (colorblind-safe palette) +group_map = { + "Engineering": "Tech", + "IT": "Tech", + "Product": "Tech", + "Sales": "Tech", + "Marketing": "Creative", + "R&D": "Creative", + "Design": "Creative", + "Data Science": "Creative", + "Operations": "Support", + "HR": "Support", + "Finance": "Support", + "Customer Support": "Support", + "Legal": "Compliance", + "Security": "Compliance", + "QA": "Compliance", +} +group_colors = {"Tech": "#306998", "Creative": "#FFD43B", "Support": "#4A90A4", "Compliance": "#7B9E89"} +colors = [group_colors[group_map[label]] for label in labels] # Scale values to radius (sqrt for area-proportional sizing) -min_radius = 0.35 -max_radius = 1.9 -values_array = np.array(values) +min_radius = 0.30 +max_radius = 2.0 +values_array = np.array(values, dtype=float) radii = min_radius + (max_radius - min_radius) * np.sqrt( (values_array - values_array.min()) / (values_array.max() - values_array.min()) ) -# Circle packing using physics simulation -n = len(labels) - -# Initial positions in grid -grid_size = int(np.ceil(np.sqrt(n))) -positions = np.zeros((n, 2)) -for i in range(n): - positions[i] = [(i % grid_size) * 4 - grid_size * 2, (i // grid_size) * 4 - grid_size * 2] - # Sort by size (largest first) for better packing +n = len(labels) order = np.argsort(-radii) -positions = positions[order] radii_sorted = radii[order] labels_sorted = [labels[i] for i in order] values_sorted = [values[i] for i in order] colors_sorted = [colors[i] for i in order] +# Initial positions in spiral pattern for tighter convergence +angles = np.linspace(0, 4 * np.pi, n) +spiral_r = np.linspace(0, 3, n) +positions = np.column_stack([spiral_r * np.cos(angles), spiral_r * np.sin(angles)]) + # Physics simulation for packing -for iteration in range(350): - # Pull toward center with decreasing strength - pull_strength = 0.06 * (1 - iteration / 400) +for iteration in range(400): + pull_strength = 0.07 * (1 - iteration / 450) + + # Pull toward center for i in range(n): - dist = np.sqrt(positions[i, 0] ** 2 + positions[i, 1] ** 2) + dist = np.linalg.norm(positions[i]) if dist > 0.01: positions[i] -= pull_strength * positions[i] / dist # Push apart overlapping circles for i in range(n): for j in range(i + 1, n): - dx = positions[j, 0] - positions[i, 0] - dy = positions[j, 1] - positions[i, 1] - dist = np.sqrt(dx**2 + dy**2) - min_dist = radii_sorted[i] + radii_sorted[j] + 0.05 # Small gap between circles + delta = positions[j] - positions[i] + dist = np.linalg.norm(delta) + min_dist = radii_sorted[i] + radii_sorted[j] + 0.06 if dist < min_dist and dist > 0.001: overlap = (min_dist - dist) / 2 - dx_norm = dx / dist - dy_norm = dy / dist - positions[i, 0] -= overlap * dx_norm - positions[i, 1] -= overlap * dy_norm - positions[j, 0] += overlap * dx_norm - positions[j, 1] += overlap * dy_norm - -# Create plot (4800x2700 px at 300 dpi) + direction = delta / dist + positions[i] -= overlap * direction + positions[j] += overlap * direction + +# Plot (4800x2700 px at 300 dpi) fig, ax = plt.subplots(figsize=(16, 9)) -# Draw circles +# Draw circles using PatchCollection for efficient rendering +circles = [] +face_colors = [] for i in range(n): - circle = mpatches.Circle( - (positions[i, 0], positions[i, 1]), - radii_sorted[i], - facecolor=colors_sorted[i], - edgecolor="white", - linewidth=2.5, - alpha=0.88, - ) - ax.add_patch(circle) - - # Add labels inside larger circles - label_len = len(labels_sorted[i]) - min_radius_for_label = 0.55 + label_len * 0.025 - if radii_sorted[i] > min_radius_for_label: + circle = mpatches.Circle((positions[i, 0], positions[i, 1]), radii_sorted[i]) + circles.append(circle) + face_colors.append(colors_sorted[i]) + +collection = mcoll.PatchCollection( + circles, facecolors=face_colors, edgecolors="white", linewidths=2.5, alpha=0.90, zorder=2 +) +ax.add_collection(collection) + +# Add labels inside circles that are large enough +for i in range(n): + label_chars = len(labels_sorted[i]) + min_r_for_label = 0.48 + label_chars * 0.018 + if radii_sorted[i] > min_r_for_label: font_scale = min(1.0, radii_sorted[i] / 1.4) label_fontsize = max(9, int(15 * font_scale)) value_fontsize = max(8, int(13 * font_scale)) + + # Determine text color based on background brightness + bg_color = colors_sorted[i] + text_color = "#1a1a2e" if bg_color == "#FFD43B" else "white" + + # Wrap long labels for smaller circles + display_label = labels_sorted[i] + is_wrapped = False + if " " in display_label and radii_sorted[i] < 1.0: + display_label = display_label.replace(" ", "\n") + is_wrapped = True + + # Adjust vertical offsets for wrapped vs single-line labels + label_y_offset = 0.05 if is_wrapped else 0.12 + value_y_offset = -0.35 if is_wrapped else -0.22 + ax.text( positions[i, 0], - positions[i, 1] + radii_sorted[i] * 0.1, - labels_sorted[i], + positions[i, 1] + radii_sorted[i] * label_y_offset, + display_label, ha="center", va="center", fontsize=label_fontsize, fontweight="bold", - color="white", + color=text_color, + zorder=3, ) ax.text( positions[i, 0], - positions[i, 1] - radii_sorted[i] * 0.22, + positions[i, 1] + radii_sorted[i] * value_y_offset, f"${values_sorted[i]}K", ha="center", va="center", fontsize=value_fontsize, - color="white", - alpha=0.95, + color=text_color, + alpha=0.85, + zorder=3, ) -# Set axis limits with padding +# Axis limits with padding all_x = positions[:, 0] all_y = positions[:, 1] max_r = radii_sorted.max() -padding = 0.6 +padding = 0.8 ax.set_xlim(all_x.min() - max_r - padding, all_x.max() + max_r + padding) ax.set_ylim(all_y.min() - max_r - padding, all_y.max() + max_r + padding) ax.set_aspect("equal") - -# Remove axes for clean visualization ax.axis("off") # Title @@ -160,5 +173,22 @@ "Department Budget Allocation · bubble-packed · matplotlib · pyplots.ai", fontsize=24, fontweight="bold", pad=20 ) +# Legend for group colors +legend_handles = [ + mpatches.Patch(facecolor=color, edgecolor="white", linewidth=1.5, label=group) + for group, color in group_colors.items() +] +ax.legend( + handles=legend_handles, + loc="lower right", + fontsize=16, + framealpha=0.9, + edgecolor="#cccccc", + fancybox=True, + borderpad=0.8, + handlelength=1.5, + handleheight=1.2, +) + plt.tight_layout() plt.savefig("plot.png", dpi=300, bbox_inches="tight", facecolor="white") diff --git a/plots/bubble-packed/metadata/matplotlib.yaml b/plots/bubble-packed/metadata/matplotlib.yaml index 78a38059c7..8cdabc10f2 100644 --- a/plots/bubble-packed/metadata/matplotlib.yaml +++ b/plots/bubble-packed/metadata/matplotlib.yaml @@ -1,16 +1,16 @@ library: matplotlib specification_id: bubble-packed created: '2025-12-23T09:16:10Z' -updated: '2025-12-23T09:18:25Z' -generated_by: claude-opus-4-5-20251101 +updated: 2026-02-23T15:35:00+00:00 +generated_by: claude-opus-4-6 workflow_run: 20456558183 issue: 0 -python_version: 3.13.11 -library_version: 3.10.8 +python_version: "3.14.3" +library_version: "3.10.8" preview_url: https://storage.googleapis.com/pyplots-images/plots/bubble-packed/matplotlib/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bubble-packed/matplotlib/plot_thumb.png preview_html: null -quality_score: 92 +quality_score: null impl_tags: dependencies: [] techniques: diff --git a/plots/bubble-packed/specification.yaml b/plots/bubble-packed/specification.yaml index 64027537f4..48e8112bee 100644 --- a/plots/bubble-packed/specification.yaml +++ b/plots/bubble-packed/specification.yaml @@ -6,7 +6,7 @@ title: Basic Packed Bubble Chart # Specification tracking created: 2025-12-15T20:43:45Z -updated: 2025-12-15T20:43:45Z +updated: 2026-02-23T12:00:00Z issue: 992 suggested: MarkusNeusinger @@ -15,13 +15,15 @@ tags: plot_type: - bubble - packed + - circlepacking data_type: - categorical - numeric + - proportional domain: - general - business features: - basic - comparison - - hierarchical + - proportional From b47ecd881aa3411c3dcd3e5bb8bbccc79d147742 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 15:48:01 +0000 Subject: [PATCH 2/8] chore(matplotlib): update quality score 82 and review feedback for bubble-packed --- .../implementations/matplotlib.py | 4 +- plots/bubble-packed/metadata/matplotlib.yaml | 256 ++++++++++-------- 2 files changed, 147 insertions(+), 113 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index 63c3bc6cd3..8377193496 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai bubble-packed: Basic Packed Bubble Chart Library: matplotlib 3.10.8 | Python 3.14.3 -Quality: /100 | Updated: 2026-02-23 +Quality: 82/100 | Updated: 2026-02-23 """ import matplotlib.collections as mcoll diff --git a/plots/bubble-packed/metadata/matplotlib.yaml b/plots/bubble-packed/metadata/matplotlib.yaml index 8cdabc10f2..ea07d71a26 100644 --- a/plots/bubble-packed/metadata/matplotlib.yaml +++ b/plots/bubble-packed/metadata/matplotlib.yaml @@ -1,158 +1,185 @@ library: matplotlib specification_id: bubble-packed created: '2025-12-23T09:16:10Z' -updated: 2026-02-23T15:35:00+00:00 +updated: '2026-02-23T15:48:01Z' generated_by: claude-opus-4-6 workflow_run: 20456558183 issue: 0 -python_version: "3.14.3" -library_version: "3.10.8" +python_version: 3.14.3 +library_version: 3.10.8 preview_url: https://storage.googleapis.com/pyplots-images/plots/bubble-packed/matplotlib/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bubble-packed/matplotlib/plot_thumb.png preview_html: null -quality_score: null +quality_score: 82 impl_tags: dependencies: [] techniques: - patches + - custom-legend + - annotations patterns: - - data-generation - - matrix-construction - dataprep: [] + - iteration-over-groups + dataprep: + - normalization styling: - - alpha-blending - minimal-chrome + - alpha-blending + - edge-highlighting review: strengths: - - Excellent physics-based circle packing algorithm with 350 iterations ensuring - no overlap - - Area-proportional sizing using sqrt scaling for accurate visual perception - - Clean, colorblind-safe palette with logical grouping by department function - - Smart label placement - only shows labels in circles large enough to fit them - - Professional title format following pyplots.ai convention - - Realistic department budget data scenario + - Well-implemented physics simulation for circle packing produces a clean, non-overlapping + layout + - Adaptive text sizing and contrast (dark text on yellow, white text on dark backgrounds) + shows attention to readability + - Efficient use of PatchCollection for rendering demonstrates matplotlib knowledge + - Realistic department budget context with meaningful value range ($130K-$950K) + - Clean, deterministic code that produces identical output every run weaknesses: - - Missing a color legend explaining the groupings (Tech, Support, Business, Compliance) - - Some smaller bubbles (Legal, Security) are unlabeled and their departments are - unclear without a legend - - Customer Support bubble is not visible in the visualization - image_description: 'The plot displays a packed bubble chart representing "Department - Budget Allocation" with 15 circular bubbles of varying sizes. The largest bubbles - are Engineering ($850K), R&D ($750K), Sales ($680K), and Product ($550K). The - bubbles are color-coded into four groups: blue (Tech: Engineering, Sales, IT, - Product), yellow (Business/Creative: Marketing, R&D, Design, Data Science), teal - (Support: Operations, HR, Finance, Customer Support), and sage green (Compliance/Quality: - Legal, Security, QA). Larger bubbles display department names in bold white text - with values below. The bubbles are tightly packed without overlapping, demonstrating - the physics simulation. The title reads "Department Budget Allocation · bubble-packed - · matplotlib · pyplots.ai" in bold at the top. The background is white with axes - turned off for a clean visualization.' + - Support (teal) and Compliance (muted green) colors are too similar, hurting colorblind + accessibility + - Two smallest circles (Security, Legal) are unlabeled and unidentifiable without + external reference + - Groups are colored but not spatially clustered, weakening the group narrative + - Some group assignments are unrealistic (Sales in Tech, Data Science in Creative) + - Design lacks a strong data insight or storytelling emphasis beyond relative sizes + image_description: 'The plot displays a packed bubble chart of department budget + allocations. Fifteen circles of varying sizes are packed together in the center + of the canvas. The largest circle is Engineering ($950K, dark blue), followed + by R&D ($820K, yellow), Sales ($680K, dark blue), and Product ($580K, dark blue). + Medium circles include Data Science ($470K, yellow), Marketing ($420K, yellow), + IT ($370K, dark blue), Operations ($310K, teal), and Finance ($280K, teal). Smaller + labeled circles include Design ($230K, yellow), Customer Support ($200K, teal), + QA ($175K, muted green), and HR ($160K, teal). Two very small circles (Security + and Legal) are present but unlabeled. Colors encode four groups: Tech (dark steel + blue), Creative (golden yellow), Support (teal), and Compliance (muted sage green). + White edges separate circles. A legend in the lower-right shows group colors. + The title reads "Department Budget Allocation · bubble-packed · matplotlib · pyplots.ai" + in bold black at the top. Axes are turned off.' criteria_checklist: visual_quality: - score: 36 - max: 40 + score: 26 + max: 30 items: - id: VQ-01 name: Text Legibility - score: 9 - max: 10 + score: 7 + max: 8 passed: true - comment: Title is 24pt and clear; labels inside bubbles are readable but some - smaller bubbles (HR, QA) have slightly cramped text + comment: Title at 24pt bold, legend at 16pt, circle labels 9-15pt. Two smallest + circles unlabeled. - id: VQ-02 name: No Overlap - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: Excellent bubble packing with no overlapping elements + comment: No overlapping text or circles. Physics simulation ensures separation. - id: VQ-03 name: Element Visibility - score: 8 - max: 8 + score: 5 + max: 6 passed: true - comment: Circle sizes well-adapted, proper area-based scaling using sqrt + comment: All 15 circles visible. Two smallest are tiny and unlabeled. - id: VQ-04 name: Color Accessibility - score: 5 - max: 5 + score: 3 + max: 4 passed: true - comment: Four distinct, colorblind-safe colors (blue, yellow, teal, sage) + comment: Blue and yellow distinguishable. Support teal and Compliance green + too similar for colorblind. - id: VQ-05 - name: Layout Balance - score: 4 - max: 5 + name: Layout & Canvas + score: 3 + max: 4 passed: true - comment: Good proportions, slight asymmetry but natural for packed bubbles - - id: VQ-07 - name: Grid & Legend + comment: Circles fill center well. Some empty corners but appropriate for + chart type. + - id: VQ-06 + name: Axis Labels & Title score: 2 max: 2 passed: true - comment: No grid needed; color grouping is implicit and clear + comment: Descriptive title with context. Axes appropriately off for packed + bubble chart. + design_excellence: + score: 12 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: Custom palette, adaptive text colors, white circle edges. Above defaults + but not publication-level. + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: Clean axis removal, white edge highlighting, alpha blending. Some + refinement visible. + - id: DE-03 + name: Data Storytelling + score: 3 + max: 6 + passed: false + comment: Size hierarchy creates focal point but groups are spatially scattered, + weakening group narrative. spec_compliance: - score: 25 - max: 25 + score: 14 + max: 15 items: - id: SC-01 name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct packed bubble chart with physics simulation - - id: SC-02 - name: Data Mapping score: 5 max: 5 passed: true - comment: Size correctly represents budget values - - id: SC-03 + comment: Correct packed bubble chart with physics-based packing. + - id: SC-02 name: Required Features - score: 5 - max: 5 + score: 3 + max: 4 passed: true - comment: Labels, values, color grouping all present - - id: SC-04 - name: Data Range + comment: Most features present. Groups colored but not spatially clustered + as spec suggests. + - id: SC-03 + name: Data Mapping score: 3 max: 3 passed: true - comment: All 15 departments visible and readable - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: Color grouping is intuitive (no explicit legend needed) - - id: SC-06 - name: Title Format - score: 2 - max: 2 + comment: Values correctly mapped to area via sqrt scaling. All 15 data points + represented. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 passed: true - comment: 'Correctly formatted: "{description} · bubble-packed · matplotlib - · pyplots.ai"' + comment: Title follows required format. Legend shows all four group colors + correctly. data_quality: - score: 18 - max: 20 + score: 13 + max: 15 items: - id: DQ-01 name: Feature Coverage - score: 7 - max: 8 + score: 5 + max: 6 passed: true - comment: Shows varying sizes, groupings, and labels; could show more extreme - size variation + comment: 15 departments with wide value range and 4 groups. Good demonstration + of packed bubble features. - id: DQ-02 name: Realistic Context - score: 7 - max: 7 + score: 4 + max: 5 passed: true - comment: Department budgets is a real, comprehensible business scenario + comment: Department budgets are realistic and neutral. Some group assignments + questionable (Sales in Tech). - id: DQ-03 name: Appropriate Scale score: 4 - max: 5 + max: 4 passed: true - comment: Budget values ($150K-$850K) are realistic for departments + comment: Budget values $130K-$950K are realistic for department budgets. code_quality: score: 10 max: 10 @@ -162,41 +189,48 @@ review: score: 3 max: 3 passed: true - comment: 'Clean sequential structure: imports → data → packing simulation - → plot → save' + comment: 'Linear script: imports, data, physics simulation, plot, save. No + functions or classes.' - id: CQ-02 name: Reproducibility - score: 3 - max: 3 + score: 2 + max: 2 passed: true - comment: Uses np.random.seed(42) + comment: Fully deterministic. No random elements. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: Only matplotlib.pyplot, matplotlib.patches, numpy used + comment: 'All four imports used: matplotlib.collections, matplotlib.patches, + matplotlib.pyplot, numpy.' - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 + name: Code Elegance + score: 2 + max: 2 passed: true - comment: All APIs current + comment: Clean, well-structured. Physics simulation is appropriately complex. - id: CQ-05 - name: Output Correct + name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png - library_features: - score: 3 - max: 5 + comment: Saves as plot.png with dpi=300 and bbox_inches tight. Current API. + library_mastery: + score: 7 + max: 10 items: - - id: LF-01 - name: Uses distinctive library features + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: PatchCollection for efficient rendering, proper ax methods, custom + legend handles. + - id: LM-02 + name: Distinctive Features score: 3 max: 5 passed: true - comment: Uses matplotlib patches (Circle) and custom physics simulation; could - leverage matplotlib.collections for efficiency - verdict: APPROVED + comment: PatchCollection and Circle patches are distinctive matplotlib patterns. + verdict: REJECTED From 47b40f7745c63a45282d33b034c796bdcfcaaa1e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 15:52:30 +0000 Subject: [PATCH 3/8] fix(matplotlib): address review feedback for bubble-packed Attempt 1/3 - fixes based on AI review --- .../implementations/matplotlib.py | 95 ++++++++++++++----- 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index 8377193496..ae8c26a9f5 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,4 +1,4 @@ -""" pyplots.ai +"""pyplots.ai bubble-packed: Basic Packed Bubble Chart Library: matplotlib 3.10.8 | Python 3.14.3 Quality: 82/100 | Updated: 2026-02-23 @@ -30,25 +30,27 @@ ] values = [950, 420, 680, 310, 160, 280, 820, 200, 130, 370, 230, 580, 470, 145, 175] -# Group assignments and colors (colorblind-safe palette) +# Group assignments - realistic organizational structure group_map = { - "Engineering": "Tech", - "IT": "Tech", - "Product": "Tech", - "Sales": "Tech", - "Marketing": "Creative", - "R&D": "Creative", - "Design": "Creative", - "Data Science": "Creative", - "Operations": "Support", - "HR": "Support", - "Finance": "Support", - "Customer Support": "Support", + "Engineering": "Engineering", + "IT": "Engineering", + "Data Science": "Engineering", + "R&D": "Engineering", + "Marketing": "Business", + "Sales": "Business", + "Product": "Business", + "Design": "Business", + "Operations": "Operations", + "HR": "Operations", + "Finance": "Operations", + "Customer Support": "Operations", "Legal": "Compliance", "Security": "Compliance", "QA": "Compliance", } -group_colors = {"Tech": "#306998", "Creative": "#FFD43B", "Support": "#4A90A4", "Compliance": "#7B9E89"} + +# Colorblind-safe palette with high hue separation +group_colors = {"Engineering": "#306998", "Business": "#FFD43B", "Operations": "#D4654A", "Compliance": "#8B6DB0"} colors = [group_colors[group_map[label]] for label in labels] # Scale values to radius (sqrt for area-proportional sizing) @@ -66,28 +68,50 @@ labels_sorted = [labels[i] for i in order] values_sorted = [values[i] for i in order] colors_sorted = [colors[i] for i in order] +groups_sorted = [group_map[labels[i]] for i in order] + +# Assign group IDs for clustering +unique_groups = list(group_colors.keys()) +group_ids = np.array([unique_groups.index(g) for g in groups_sorted]) # Initial positions in spiral pattern for tighter convergence angles = np.linspace(0, 4 * np.pi, n) spiral_r = np.linspace(0, 3, n) positions = np.column_stack([spiral_r * np.cos(angles), spiral_r * np.sin(angles)]) -# Physics simulation for packing -for iteration in range(400): - pull_strength = 0.07 * (1 - iteration / 450) +# Physics simulation with group-aware clustering +for iteration in range(500): + progress = iteration / 500 + pull_strength = 0.06 * (1 - progress * 0.8) + group_pull = 0.04 * (1 - progress * 0.5) - # Pull toward center + # Compute group centers of mass + group_centers = {} + for gid in range(len(unique_groups)): + mask = group_ids == gid + if np.any(mask): + group_centers[gid] = positions[mask].mean(axis=0) + + # Pull toward center + pull toward own group center for i in range(n): dist = np.linalg.norm(positions[i]) if dist > 0.01: positions[i] -= pull_strength * positions[i] / dist + gc = group_centers[group_ids[i]] + to_group = gc - positions[i] + gd = np.linalg.norm(to_group) + if gd > 0.01: + positions[i] += group_pull * to_group / gd + # Push apart overlapping circles for i in range(n): for j in range(i + 1, n): delta = positions[j] - positions[i] dist = np.linalg.norm(delta) - min_dist = radii_sorted[i] + radii_sorted[j] + 0.06 + same_group = group_ids[i] == group_ids[j] + gap = 0.04 if same_group else 0.15 + min_dist = radii_sorted[i] + radii_sorted[j] + gap if dist < min_dist and dist > 0.001: overlap = (min_dist - dist) / 2 @@ -111,7 +135,8 @@ ) ax.add_collection(collection) -# Add labels inside circles that are large enough +# Add labels inside circles that are large enough, external labels for small ones +small_circles = [] for i in range(n): label_chars = len(labels_sorted[i]) min_r_for_label = 0.48 + label_chars * 0.018 @@ -157,12 +182,38 @@ alpha=0.85, zorder=3, ) + else: + small_circles.append(i) + +# External labels with leader lines for small circles +for i in small_circles: + cx, cy = positions[i, 0], positions[i, 1] + r = radii_sorted[i] + + # Find direction away from center for label placement + angle = np.arctan2(cy, cx) + offset_dist = r + 0.6 + lx = cx + offset_dist * np.cos(angle) + ly = cy + offset_dist * np.sin(angle) + + ax.annotate( + f"{labels_sorted[i]}\n${values_sorted[i]}K", + xy=(cx, cy), + xytext=(lx, ly), + fontsize=9, + fontweight="bold", + color="#333333", + ha="center", + va="center", + arrowprops={"arrowstyle": "-", "color": "#666666", "lw": 1.2, "shrinkA": 0, "shrinkB": 2}, + zorder=4, + ) # Axis limits with padding all_x = positions[:, 0] all_y = positions[:, 1] max_r = radii_sorted.max() -padding = 0.8 +padding = 1.2 ax.set_xlim(all_x.min() - max_r - padding, all_x.max() + max_r + padding) ax.set_ylim(all_y.min() - max_r - padding, all_y.max() + max_r + padding) ax.set_aspect("equal") From 3746bc7741d3f4652b69a71afdb054d81b46e25a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 16:00:00 +0000 Subject: [PATCH 4/8] chore(matplotlib): update quality score 87 and review feedback for bubble-packed --- .../implementations/matplotlib.py | 4 +- plots/bubble-packed/metadata/matplotlib.yaml | 166 +++++++++--------- 2 files changed, 89 insertions(+), 81 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index ae8c26a9f5..b8173eeb73 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai bubble-packed: Basic Packed Bubble Chart Library: matplotlib 3.10.8 | Python 3.14.3 -Quality: 82/100 | Updated: 2026-02-23 +Quality: 87/100 | Updated: 2026-02-23 """ import matplotlib.collections as mcoll diff --git a/plots/bubble-packed/metadata/matplotlib.yaml b/plots/bubble-packed/metadata/matplotlib.yaml index ea07d71a26..7cc4b52914 100644 --- a/plots/bubble-packed/metadata/matplotlib.yaml +++ b/plots/bubble-packed/metadata/matplotlib.yaml @@ -1,7 +1,7 @@ library: matplotlib specification_id: bubble-packed created: '2025-12-23T09:16:10Z' -updated: '2026-02-23T15:48:01Z' +updated: '2026-02-23T15:59:59Z' generated_by: claude-opus-4-6 workflow_run: 20456558183 issue: 0 @@ -10,14 +10,15 @@ library_version: 3.10.8 preview_url: https://storage.googleapis.com/pyplots-images/plots/bubble-packed/matplotlib/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bubble-packed/matplotlib/plot_thumb.png preview_html: null -quality_score: 82 +quality_score: 87 impl_tags: dependencies: [] techniques: - patches - - custom-legend - annotations + - custom-legend patterns: + - data-generation - iteration-over-groups dataprep: - normalization @@ -27,34 +28,33 @@ impl_tags: - edge-highlighting review: strengths: - - Well-implemented physics simulation for circle packing produces a clean, non-overlapping - layout - - Adaptive text sizing and contrast (dark text on yellow, white text on dark backgrounds) - shows attention to readability - - Efficient use of PatchCollection for rendering demonstrates matplotlib knowledge - - Realistic department budget context with meaningful value range ($130K-$950K) - - Clean, deterministic code that produces identical output every run + - Excellent physics simulation with group-aware clustering produces a professional + packed bubble layout with natural grouping + - 'Smart adaptive labeling system: font sizes scale with circle radius, text color + adapts to background brightness, and leader lines handle small circles gracefully' + - Area-proportional sizing correctly implemented with sqrt scaling for accurate + visual perception + - Perfect spec compliance with all required features implemented including optional + grouping + - Realistic department budget data with logical organizational structure weaknesses: - - Support (teal) and Compliance (muted green) colors are too similar, hurting colorblind - accessibility - - Two smallest circles (Security, Legal) are unlabeled and unidentifiable without - external reference - - Groups are colored but not spatially clustered, weakening the group narrative - - Some group assignments are unrealistic (Sales in Tech, Data Science in Creative) - - Design lacks a strong data insight or storytelling emphasis beyond relative sizes - image_description: 'The plot displays a packed bubble chart of department budget - allocations. Fifteen circles of varying sizes are packed together in the center - of the canvas. The largest circle is Engineering ($950K, dark blue), followed - by R&D ($820K, yellow), Sales ($680K, dark blue), and Product ($580K, dark blue). - Medium circles include Data Science ($470K, yellow), Marketing ($420K, yellow), - IT ($370K, dark blue), Operations ($310K, teal), and Finance ($280K, teal). Smaller - labeled circles include Design ($230K, yellow), Customer Support ($200K, teal), - QA ($175K, muted green), and HR ($160K, teal). Two very small circles (Security - and Legal) are present but unlabeled. Colors encode four groups: Tech (dark steel - blue), Creative (golden yellow), Support (teal), and Compliance (muted sage green). - White edges separate circles. A legend in the lower-right shows group colors. + - External labels (9pt) and smallest internal labels are at the lower end of legibility + for 4800x2700 output + - Layout is slightly asymmetric with the large Engineering bubble pulling the visual + center of mass downward + image_description: The plot shows a packed bubble chart depicting department budget + allocation for 15 departments grouped into 4 organizational categories. The largest + circle is Engineering ($950K) in steel blue at the bottom-center, followed by + R&D ($820K) in the same blue at the right. Business group circles (Product $580K, + Sales $680K, Marketing $420K, Design $230K) appear in bright gold/yellow, clustered + in the upper-left area. Operations group (Operations $310K, Finance $280K, Customer + Support $200K, HR $160K) uses coral/salmon. Compliance group (Legal $130K, Security + $145K, QA $175K) uses purple. Circles are packed together with visible separation + between groups. Larger circles have white bold text labels and dollar values inside; + smaller circles (Legal, Security) have external labels with thin gray leader lines. The title reads "Department Budget Allocation · bubble-packed · matplotlib · pyplots.ai" - in bold black at the top. Axes are turned off.' + in bold black at the top. A legend in the lower-right corner shows the four group + colors with labels. Background is white, axes are hidden. criteria_checklist: visual_quality: score: 26 @@ -62,71 +62,74 @@ review: items: - id: VQ-01 name: Text Legibility - score: 7 + score: 6 max: 8 passed: true - comment: Title at 24pt bold, legend at 16pt, circle labels 9-15pt. Two smallest - circles unlabeled. + comment: All font sizes explicitly set. Title 24pt, legend 16pt, internal + labels 9-15pt. External and smallest internal text at 9pt borderline for + 4800x2700. - id: VQ-02 name: No Overlap - score: 6 + score: 5 max: 6 passed: true - comment: No overlapping text or circles. Physics simulation ensures separation. + comment: No text-on-text overlap. Middle cluster (Finance, Customer Support, + HR, QA) has tight spacing but remains readable. - id: VQ-03 name: Element Visibility - score: 5 + score: 6 max: 6 passed: true - comment: All 15 circles visible. Two smallest are tiny and unlabeled. + comment: All 15 circles clearly visible with strong size differentiation via + sqrt-based area-proportional scaling. - id: VQ-04 name: Color Accessibility - score: 3 + score: 4 max: 4 passed: true - comment: Blue and yellow distinguishable. Support teal and Compliance green - too similar for colorblind. + comment: Blue, yellow, coral, purple all distinguishable for colorblind users. + No red-green sole distinction. - id: VQ-05 name: Layout & Canvas score: 3 max: 4 passed: true - comment: Circles fill center well. Some empty corners but appropriate for - chart type. + comment: Good canvas utilization but slightly asymmetric — Engineering bubble + extends below center creating unbalanced whitespace. - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Descriptive title with context. Axes appropriately off for packed + comment: Descriptive title with context. Axes correctly hidden for packed bubble chart. design_excellence: - score: 12 + score: 15 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 5 + score: 6 max: 8 passed: true - comment: Custom palette, adaptive text colors, white circle edges. Above defaults - but not publication-level. + comment: Custom 4-color palette, white circle edges with alpha 0.90, adaptive + text color. Yellow slightly over-saturated relative to other colors. - id: DE-02 name: Visual Refinement - score: 4 + score: 5 max: 6 passed: true - comment: Clean axis removal, white edge highlighting, alpha blending. Some - refinement visible. + comment: Axes hidden, white edge borders polished, alpha blending, custom + legend styling with fancybox and framealpha. - id: DE-03 name: Data Storytelling - score: 3 + score: 4 max: 6 - passed: false - comment: Size hierarchy creates focal point but groups are spatially scattered, - weakening group narrative. + passed: true + comment: Size hierarchy shows Engineering and R&D dominate. Group clustering + adds organizational narrative. Dollar values provide context. spec_compliance: - score: 14 + score: 15 max: 15 items: - id: SC-01 @@ -134,30 +137,30 @@ review: score: 5 max: 5 passed: true - comment: Correct packed bubble chart with physics-based packing. + comment: Correct packed bubble chart with physics simulation for circle packing. - id: SC-02 name: Required Features - score: 3 + score: 4 max: 4 passed: true - comment: Most features present. Groups colored but not spatially clustered - as spec suggests. + comment: 'All features: area-proportional sizing, force simulation, adaptive + labels, color grouping, group clustering.' - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Values correctly mapped to area via sqrt scaling. All 15 data points - represented. + comment: Values correctly mapped to circle area via sqrt scaling. Groups correctly + clustered. - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title follows required format. Legend shows all four group colors - correctly. + comment: Title follows format with descriptive prefix. Legend correctly labels + all 4 groups. data_quality: - score: 13 + score: 14 max: 15 items: - id: DQ-01 @@ -165,21 +168,21 @@ review: score: 5 max: 6 passed: true - comment: 15 departments with wide value range and 4 groups. Good demonstration - of packed bubble features. + comment: 15 departments across 4 groups with good size variation ($130K-$950K). + Both internal and external labeling demonstrated. - id: DQ-02 name: Realistic Context - score: 4 + score: 5 max: 5 passed: true - comment: Department budgets are realistic and neutral. Some group assignments - questionable (Sales in Tech). + comment: Department budget allocation is a real, comprehensible, neutral business + scenario. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Budget values $130K-$950K are realistic for department budgets. + comment: Budget values ($130K-$950K) realistic for department-level allocations. code_quality: score: 10 max: 10 @@ -189,33 +192,36 @@ review: score: 3 max: 3 passed: true - comment: 'Linear script: imports, data, physics simulation, plot, save. No - functions or classes.' + comment: 'Linear flow: imports, data, scaling, sorting, physics simulation, + plotting, save. No functions or classes.' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: Fully deterministic. No random elements. + comment: 'Fully deterministic: hard-coded data, spiral initial positions from + linspace, deterministic physics.' - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: 'All four imports used: matplotlib.collections, matplotlib.patches, - matplotlib.pyplot, numpy.' + comment: 'All 4 imports used: mcoll (PatchCollection), mpatches (Circle/Patch), + plt (figure/save), np (math).' - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Clean, well-structured. Physics simulation is appropriately complex. + comment: Physics simulation complexity appropriate for plot type. Well-commented. + Adaptive labeling logic clean. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png with dpi=300 and bbox_inches tight. Current API. + comment: Saves as plot.png at 300 DPI with bbox_inches='tight'. No deprecated + API. library_mastery: score: 7 max: 10 @@ -225,12 +231,14 @@ review: score: 4 max: 5 passed: true - comment: PatchCollection for efficient rendering, proper ax methods, custom - legend handles. + comment: Uses PatchCollection for efficient batch rendering, mpatches.Circle, + ax.annotate with arrowprops. Expert approach for a chart type with no high-level + API. - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: PatchCollection and Circle patches are distinctive matplotlib patterns. + comment: PatchCollection for efficient patch rendering is distinctly matplotlib. + Combination with mpatches.Circle and annotate arrowprops is library-specific. verdict: REJECTED From e51d866aee42fcee1ca080b7f7e353b3233d81c2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 16:03:42 +0000 Subject: [PATCH 5/8] fix(matplotlib): address review feedback for bubble-packed Attempt 2/3 - fixes based on AI review --- plots/bubble-packed/implementations/matplotlib.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index b8173eeb73..3b0a894c49 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,4 +1,4 @@ -""" pyplots.ai +"""pyplots.ai bubble-packed: Basic Packed Bubble Chart Library: matplotlib 3.10.8 | Python 3.14.3 Quality: 87/100 | Updated: 2026-02-23 @@ -50,7 +50,7 @@ } # Colorblind-safe palette with high hue separation -group_colors = {"Engineering": "#306998", "Business": "#FFD43B", "Operations": "#D4654A", "Compliance": "#8B6DB0"} +group_colors = {"Engineering": "#306998", "Business": "#E8C33A", "Operations": "#D4654A", "Compliance": "#8B6DB0"} colors = [group_colors[group_map[label]] for label in labels] # Scale values to radius (sqrt for area-proportional sizing) @@ -119,6 +119,11 @@ positions[i] -= overlap * direction positions[j] += overlap * direction +# Center the layout: shift all positions so the bounding box is centered at origin +bbox_min = positions.min(axis=0) - radii_sorted.max() +bbox_max = positions.max(axis=0) + radii_sorted.max() +positions -= (bbox_min + bbox_max) / 2 + # Plot (4800x2700 px at 300 dpi) fig, ax = plt.subplots(figsize=(16, 9)) @@ -142,8 +147,8 @@ min_r_for_label = 0.48 + label_chars * 0.018 if radii_sorted[i] > min_r_for_label: font_scale = min(1.0, radii_sorted[i] / 1.4) - label_fontsize = max(9, int(15 * font_scale)) - value_fontsize = max(8, int(13 * font_scale)) + label_fontsize = max(11, int(15 * font_scale)) + value_fontsize = max(10, int(13 * font_scale)) # Determine text color based on background brightness bg_color = colors_sorted[i] @@ -200,7 +205,7 @@ f"{labels_sorted[i]}\n${values_sorted[i]}K", xy=(cx, cy), xytext=(lx, ly), - fontsize=9, + fontsize=11, fontweight="bold", color="#333333", ha="center", From ea0779a59b716b73fd28bf818d17912d66e7c63c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 16:11:03 +0000 Subject: [PATCH 6/8] chore(matplotlib): update quality score 87 and review feedback for bubble-packed --- .../implementations/matplotlib.py | 2 +- plots/bubble-packed/metadata/matplotlib.yaml | 157 +++++++++--------- 2 files changed, 80 insertions(+), 79 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index 3b0a894c49..811a8deab6 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,4 +1,4 @@ -"""pyplots.ai +""" pyplots.ai bubble-packed: Basic Packed Bubble Chart Library: matplotlib 3.10.8 | Python 3.14.3 Quality: 87/100 | Updated: 2026-02-23 diff --git a/plots/bubble-packed/metadata/matplotlib.yaml b/plots/bubble-packed/metadata/matplotlib.yaml index 7cc4b52914..a7f54e1cc7 100644 --- a/plots/bubble-packed/metadata/matplotlib.yaml +++ b/plots/bubble-packed/metadata/matplotlib.yaml @@ -1,7 +1,7 @@ library: matplotlib specification_id: bubble-packed created: '2025-12-23T09:16:10Z' -updated: '2026-02-23T15:59:59Z' +updated: '2026-02-23T16:11:03Z' generated_by: claude-opus-4-6 workflow_run: 20456558183 issue: 0 @@ -14,8 +14,8 @@ quality_score: 87 impl_tags: dependencies: [] techniques: - - patches - annotations + - patches - custom-legend patterns: - data-generation @@ -28,36 +28,41 @@ impl_tags: - edge-highlighting review: strengths: - - Excellent physics simulation with group-aware clustering produces a professional - packed bubble layout with natural grouping - - 'Smart adaptive labeling system: font sizes scale with circle radius, text color - adapts to background brightness, and leader lines handle small circles gracefully' - - Area-proportional sizing correctly implemented with sqrt scaling for accurate - visual perception - - Perfect spec compliance with all required features implemented including optional - grouping - - Realistic department budget data with logical organizational structure + - Physics simulation produces well-packed, visually appealing bubble arrangement + with group-aware clustering + - Smart labeling strategy with internal labels for large circles and external leader-line + labels for small ones + - Custom four-color palette with strong hue separation is colorblind-safe and visually + cohesive + - Excellent spec compliance with all required features including area-proportional + sizing, grouping, and force simulation + - Realistic neutral dataset with plausible organizational structure and budget values + - PatchCollection usage for efficient rendering is an idiomatic matplotlib pattern weaknesses: - - External labels (9pt) and smallest internal labels are at the lower end of legibility - for 4800x2700 output - - Layout is slightly asymmetric with the large Engineering bubble pulling the visual - center of mass downward - image_description: The plot shows a packed bubble chart depicting department budget - allocation for 15 departments grouped into 4 organizational categories. The largest - circle is Engineering ($950K) in steel blue at the bottom-center, followed by - R&D ($820K) in the same blue at the right. Business group circles (Product $580K, - Sales $680K, Marketing $420K, Design $230K) appear in bright gold/yellow, clustered - in the upper-left area. Operations group (Operations $310K, Finance $280K, Customer - Support $200K, HR $160K) uses coral/salmon. Compliance group (Legal $130K, Security - $145K, QA $175K) uses purple. Circles are packed together with visible separation - between groups. Larger circles have white bold text labels and dollar values inside; - smaller circles (Legal, Security) have external labels with thin gray leader lines. - The title reads "Department Budget Allocation · bubble-packed · matplotlib · pyplots.ai" - in bold black at the top. A legend in the lower-right corner shows the four group - colors with labels. Background is white, axes are hidden. + - White text on golden-yellow circles has reduced contrast due to text_color condition + checking wrong hex value + - Some label text in smaller circles (10-11pt) is on the small side for 4800x2700 + canvas + - Minor text cramping in medium-small circles like Customer Support + - Layout slightly unbalanced with more empty space on the left side + image_description: 'The plot displays a packed bubble chart titled "Department Budget + Allocation · bubble-packed · matplotlib · pyplots.ai". Fifteen circles of varying + sizes represent department budgets ranging from $130K (Legal) to $950K (Engineering). + Circles are color-coded by organizational group: steel blue (#306998) for Engineering + group (Engineering, R&D, IT, Data Science), golden yellow (#E8C33A) for Business + group (Product, Sales, Marketing, Design), salmon/coral (#D4654A) for Operations + group (Operations, Finance, Customer Support, HR), and muted purple (#8B6DB0) + for Compliance group (Legal, Security, QA). Circles are packed together via physics + simulation with group-aware clustering — Engineering group circles cluster toward + the bottom-right, Business toward the upper-left, Operations in the center, and + Compliance interspersed among them. White edges (2.5px) separate circles cleanly. + Labels and dollar values appear inside larger circles in white bold text, while + smaller circles (Legal, Security) use external labels with thin leader lines. + A legend in the lower right identifies the four groups. Axes are hidden for a + clean, diagrammatic appearance.' criteria_checklist: visual_quality: - score: 26 + score: 25 max: 30 items: - id: VQ-01 @@ -65,44 +70,43 @@ review: score: 6 max: 8 passed: true - comment: All font sizes explicitly set. Title 24pt, legend 16pt, internal - labels 9-15pt. External and smallest internal text at 9pt borderline for - 4800x2700. + comment: Font sizes explicitly set; title 24pt, legend 16pt. Value text in + smaller circles drops to 10-11pt, slightly small for 4800x2700 canvas. - id: VQ-02 name: No Overlap score: 5 max: 6 passed: true - comment: No text-on-text overlap. Middle cluster (Finance, Customer Support, - HR, QA) has tight spacing but remains readable. + comment: Most text clearly readable. Minor cramping in smaller circles like + Customer Support where label and value fill the space tightly. - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: All 15 circles clearly visible with strong size differentiation via - sqrt-based area-proportional scaling. + comment: All circles clearly visible with good size variation. White edge + borders and alpha=0.90 ensure clean separation. - id: VQ-04 name: Color Accessibility - score: 4 + score: 3 max: 4 passed: true - comment: Blue, yellow, coral, purple all distinguishable for colorblind users. - No red-green sole distinction. + comment: Good hue separation and colorblind-safe palette. White text on yellow + (#E8C33A) has reduced contrast due to text_color bug checking wrong hex. - id: VQ-05 name: Layout & Canvas score: 3 max: 4 passed: true - comment: Good canvas utilization but slightly asymmetric — Engineering bubble - extends below center creating unbalanced whitespace. + comment: Bubbles fill reasonable portion of canvas. Slight imbalance with + more empty space on left side. - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Descriptive title with context. Axes correctly hidden for packed - bubble chart. + comment: Axes appropriately hidden. Descriptive title with budget context. + Values in $K format. design_excellence: score: 15 max: 20 @@ -112,22 +116,22 @@ review: score: 6 max: 8 passed: true - comment: Custom 4-color palette, white circle edges with alpha 0.90, adaptive - text color. Yellow slightly over-saturated relative to other colors. + comment: Custom four-color palette, white circle edges, smart internal/external + labeling. Clearly above defaults. - id: DE-02 name: Visual Refinement score: 5 max: 6 passed: true - comment: Axes hidden, white edge borders polished, alpha blending, custom - legend styling with fancybox and framealpha. + comment: Axes hidden, white edge borders, alpha transparency, styled legend + with fancybox, thin leader lines. - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: Size hierarchy shows Engineering and R&D dominate. Group clustering - adds organizational narrative. Dollar values provide context. + comment: Size variation communicates budget hierarchy. Color grouping reveals + organizational structure. Group clustering visible. spec_compliance: score: 15 max: 15 @@ -137,52 +141,52 @@ review: score: 5 max: 5 passed: true - comment: Correct packed bubble chart with physics simulation for circle packing. + comment: Correct packed bubble chart with physics-simulated circle packing. - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: 'All features: area-proportional sizing, force simulation, adaptive - labels, color grouping, group clustering.' + comment: Area-proportional sizing, force simulation, smart labeling, color-coded + groups, group clustering. - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Values correctly mapped to circle area via sqrt scaling. Groups correctly - clustered. + comment: Values correctly mapped to circle area via sqrt normalization. All + 15 items visible. - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title follows format with descriptive prefix. Legend correctly labels - all 4 groups. + comment: Title follows required format. Legend correctly shows all 4 groups + with matching colors. data_quality: - score: 14 + score: 15 max: 15 items: - id: DQ-01 name: Feature Coverage - score: 5 + score: 6 max: 6 passed: true - comment: 15 departments across 4 groups with good size variation ($130K-$950K). - Both internal and external labeling demonstrated. + comment: Wide range of values ($130K-$950K). Four groups with varying membership. + Mix of large and small circles. - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Department budget allocation is a real, comprehensible, neutral business - scenario. + comment: Department budget allocation is a real-world corporate scenario. + Neutral business topic. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Budget values ($130K-$950K) realistic for department-level allocations. + comment: Budget values $130K-$950K realistic for department-level allocations. code_quality: score: 10 max: 10 @@ -192,36 +196,34 @@ review: score: 3 max: 3 passed: true - comment: 'Linear flow: imports, data, scaling, sorting, physics simulation, - plotting, save. No functions or classes.' + comment: 'Linear flow: imports, data, simulation, plot, save. No functions + or classes.' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: 'Fully deterministic: hard-coded data, spiral initial positions from - linspace, deterministic physics.' + comment: All data hardcoded. Physics simulation uses deterministic initial + positions. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: 'All 4 imports used: mcoll (PatchCollection), mpatches (Circle/Patch), - plt (figure/save), np (math).' + comment: 'All four imports used: collections, patches, pyplot, numpy.' - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Physics simulation complexity appropriate for plot type. Well-commented. - Adaptive labeling logic clean. + comment: Well-organized sections. Physics simulation complexity appropriate + for the task. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png at 300 DPI with bbox_inches='tight'. No deprecated - API. + comment: Saves as plot.png at 300 dpi. Current matplotlib API. library_mastery: score: 7 max: 10 @@ -231,14 +233,13 @@ review: score: 4 max: 5 passed: true - comment: Uses PatchCollection for efficient batch rendering, mpatches.Circle, - ax.annotate with arrowprops. Expert approach for a chart type with no high-level - API. + comment: PatchCollection for batch rendering. ax methods throughout. annotate + with arrowprops for leader lines. - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: PatchCollection for efficient patch rendering is distinctly matplotlib. - Combination with mpatches.Circle and annotate arrowprops is library-specific. + comment: PatchCollection with custom Circle patches is distinctively matplotlib. + Patches/collections module usage. verdict: REJECTED From 8b8107f4d5635b8241abfb983beb68b15c222745 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 16:15:32 +0000 Subject: [PATCH 7/8] fix(matplotlib): address review feedback for bubble-packed Attempt 3/3 - fixes based on AI review --- .../implementations/matplotlib.py | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index 811a8deab6..f161ed96ae 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,4 +1,4 @@ -""" pyplots.ai +"""pyplots.ai bubble-packed: Basic Packed Bubble Chart Library: matplotlib 3.10.8 | Python 3.14.3 Quality: 87/100 | Updated: 2026-02-23 @@ -6,6 +6,7 @@ import matplotlib.collections as mcoll import matplotlib.patches as mpatches +import matplotlib.patheffects as pe import matplotlib.pyplot as plt import numpy as np @@ -147,12 +148,19 @@ min_r_for_label = 0.48 + label_chars * 0.018 if radii_sorted[i] > min_r_for_label: font_scale = min(1.0, radii_sorted[i] / 1.4) - label_fontsize = max(11, int(15 * font_scale)) - value_fontsize = max(10, int(13 * font_scale)) + label_fontsize = max(12, int(15 * font_scale)) + value_fontsize = max(12, int(13 * font_scale)) - # Determine text color based on background brightness + # Determine text color based on background luminance (WCAG relative luminance) bg_color = colors_sorted[i] - text_color = "#1a1a2e" if bg_color == "#FFD43B" else "white" + rgb = [int(bg_color[j : j + 2], 16) / 255 for j in (1, 3, 5)] + luminance = 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2] + text_color = "#1a1a2e" if luminance > 0.45 else "white" + text_outline = ( + pe.withStroke(linewidth=3, foreground="#00000033") + if luminance <= 0.45 + else pe.withStroke(linewidth=3, foreground="#ffffff33") + ) # Wrap long labels for smaller circles display_label = labels_sorted[i] @@ -174,6 +182,7 @@ fontsize=label_fontsize, fontweight="bold", color=text_color, + path_effects=[text_outline], zorder=3, ) ax.text( @@ -185,6 +194,7 @@ fontsize=value_fontsize, color=text_color, alpha=0.85, + path_effects=[text_outline], zorder=3, ) else: @@ -205,7 +215,7 @@ f"{labels_sorted[i]}\n${values_sorted[i]}K", xy=(cx, cy), xytext=(lx, ly), - fontsize=11, + fontsize=12, fontweight="bold", color="#333333", ha="center", @@ -218,15 +228,19 @@ all_x = positions[:, 0] all_y = positions[:, 1] max_r = radii_sorted.max() -padding = 1.2 +padding = 0.9 ax.set_xlim(all_x.min() - max_r - padding, all_x.max() + max_r + padding) ax.set_ylim(all_y.min() - max_r - padding, all_y.max() + max_r + padding) ax.set_aspect("equal") ax.axis("off") -# Title +# Title with total budget subtitle for context +total_budget = sum(values) ax.set_title( - "Department Budget Allocation · bubble-packed · matplotlib · pyplots.ai", fontsize=24, fontweight="bold", pad=20 + f"Department Budget Allocation (${total_budget / 1000:.1f}M Total)\nbubble-packed · matplotlib · pyplots.ai", + fontsize=24, + fontweight="bold", + pad=20, ) # Legend for group colors From bfb7ca27d383fc20558ee80e58b432b19a79713f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 16:23:51 +0000 Subject: [PATCH 8/8] chore(matplotlib): update quality score 87 and review feedback for bubble-packed --- .../implementations/matplotlib.py | 2 +- plots/bubble-packed/metadata/matplotlib.yaml | 156 +++++++++--------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/plots/bubble-packed/implementations/matplotlib.py b/plots/bubble-packed/implementations/matplotlib.py index f161ed96ae..372b099446 100644 --- a/plots/bubble-packed/implementations/matplotlib.py +++ b/plots/bubble-packed/implementations/matplotlib.py @@ -1,4 +1,4 @@ -"""pyplots.ai +""" pyplots.ai bubble-packed: Basic Packed Bubble Chart Library: matplotlib 3.10.8 | Python 3.14.3 Quality: 87/100 | Updated: 2026-02-23 diff --git a/plots/bubble-packed/metadata/matplotlib.yaml b/plots/bubble-packed/metadata/matplotlib.yaml index a7f54e1cc7..6c222e6801 100644 --- a/plots/bubble-packed/metadata/matplotlib.yaml +++ b/plots/bubble-packed/metadata/matplotlib.yaml @@ -1,7 +1,7 @@ library: matplotlib specification_id: bubble-packed created: '2025-12-23T09:16:10Z' -updated: '2026-02-23T16:11:03Z' +updated: '2026-02-23T16:23:51Z' generated_by: claude-opus-4-6 workflow_run: 20456558183 issue: 0 @@ -28,38 +28,33 @@ impl_tags: - edge-highlighting review: strengths: - - Physics simulation produces well-packed, visually appealing bubble arrangement - with group-aware clustering - - Smart labeling strategy with internal labels for large circles and external leader-line - labels for small ones - - Custom four-color palette with strong hue separation is colorblind-safe and visually - cohesive - - Excellent spec compliance with all required features including area-proportional - sizing, grouping, and force simulation - - Realistic neutral dataset with plausible organizational structure and budget values - - PatchCollection usage for efficient rendering is an idiomatic matplotlib pattern + - Excellent data storytelling with realistic department budget theme and organizational + group clustering + - WCAG-aware text contrast switching based on background luminance + - PatchCollection for efficient batch circle rendering is idiomatic matplotlib + - Physics simulation with group-aware clustering produces well-organized layout + - Path effects on text ensure readability against varied background colors weaknesses: - - White text on golden-yellow circles has reduced contrast due to text_color condition - checking wrong hex value - - Some label text in smaller circles (10-11pt) is on the small side for 4800x2700 - canvas - - Minor text cramping in medium-small circles like Customer Support - - Layout slightly unbalanced with more empty space on the left side - image_description: 'The plot displays a packed bubble chart titled "Department Budget - Allocation · bubble-packed · matplotlib · pyplots.ai". Fifteen circles of varying - sizes represent department budgets ranging from $130K (Legal) to $950K (Engineering). - Circles are color-coded by organizational group: steel blue (#306998) for Engineering - group (Engineering, R&D, IT, Data Science), golden yellow (#E8C33A) for Business - group (Product, Sales, Marketing, Design), salmon/coral (#D4654A) for Operations - group (Operations, Finance, Customer Support, HR), and muted purple (#8B6DB0) - for Compliance group (Legal, Security, QA). Circles are packed together via physics - simulation with group-aware clustering — Engineering group circles cluster toward - the bottom-right, Business toward the upper-left, Operations in the center, and - Compliance interspersed among them. White edges (2.5px) separate circles cleanly. - Labels and dollar values appear inside larger circles in white bold text, while - smaller circles (Legal, Security) use external labels with thin leader lines. - A legend in the lower right identifies the four groups. Axes are hidden for a - clean, diagrammatic appearance.' + - Center area crowding where smaller circles pack tightly making labels harder to + read + - Layout is somewhat bottom-heavy due to Engineering circle dominating the lower + portion + - Smallest circle labels at 12pt are below ideal size for this canvas resolution + image_description: 'The plot shows a packed bubble chart titled "Department Budget + Allocation ($5.9M Total)" with subtitle "bubble-packed · matplotlib · pyplots.ai". + Fifteen circles of varying sizes represent department budgets ranging from $130K + (Legal) to $950K (Engineering). Circles are colored by organizational group: steel + blue (#306998) for Engineering group (Engineering, R&D, Data Science, IT), golden + yellow (#E8C33A) for Business group (Sales, Product, Marketing, Design), coral + red (#D4654A) for Operations group (Operations, Finance, Customer Support, HR), + and muted purple (#8B6DB0) for Compliance group (Legal, Security, QA). Circles + are packed together with visible group clustering — Engineering-related departments + cluster at the bottom, Business at the upper-left, Operations in the center, and + Compliance scattered among them. White edges separate circles cleanly. Labels + with department names and dollar values appear inside larger circles with bold + text and subtle path-effect outlines. Smaller circles (Legal, Security) have external + labels with leader lines. A legend in the lower right identifies the four groups. + The overall layout is clean with axes turned off and a white background.' criteria_checklist: visual_quality: score: 25 @@ -67,46 +62,48 @@ review: items: - id: VQ-01 name: Text Legibility - score: 6 + score: 7 max: 8 passed: true - comment: Font sizes explicitly set; title 24pt, legend 16pt. Value text in - smaller circles drops to 10-11pt, slightly small for 4800x2700 canvas. + comment: Font sizes explicitly set throughout (title 24pt, labels 12-15pt, + legend 16pt). Smallest labels at 12pt below ideal 16pt guideline but acceptable + for packed bubble constraints. - id: VQ-02 name: No Overlap - score: 5 + score: 4 max: 6 passed: true - comment: Most text clearly readable. Minor cramping in smaller circles like - Customer Support where label and value fill the space tightly. + comment: Some crowding in center cluster where smaller circles pack tightly. + Customer Support label cramped in small wrapped text. No severe unreadable + overlap. - id: VQ-03 name: Element Visibility - score: 6 + score: 5 max: 6 passed: true - comment: All circles clearly visible with good size variation. White edge - borders and alpha=0.90 ensure clean separation. + comment: All 15 circles visible with area-proportional sizing. Smallest circles + are tiny but distinguishable. White edges and alpha=0.90 provide clean separation. - id: VQ-04 name: Color Accessibility - score: 3 + score: 4 max: 4 passed: true - comment: Good hue separation and colorblind-safe palette. White text on yellow - (#E8C33A) has reduced contrast due to text_color bug checking wrong hex. + comment: Four-color palette with strong hue separation. No red-green reliance. + WCAG-aware text contrast switching. - id: VQ-05 name: Layout & Canvas score: 3 max: 4 passed: true - comment: Bubbles fill reasonable portion of canvas. Slight imbalance with - more empty space on left side. + comment: Good canvas utilization (~60-70%). Layout somewhat bottom-heavy due + to largest circle placement. Content not cut off. - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Axes appropriately hidden. Descriptive title with budget context. - Values in $K format. + comment: Descriptive title with aggregate budget value. No axes needed for + packed bubble chart. design_excellence: score: 15 max: 20 @@ -116,22 +113,23 @@ review: score: 6 max: 8 passed: true - comment: Custom four-color palette, white circle edges, smart internal/external - labeling. Clearly above defaults. + comment: 'Strong design: custom four-color palette, WCAG text contrast, path + effect outlines, white circle edges. Clearly above library defaults.' - id: DE-02 name: Visual Refinement score: 5 max: 6 passed: true - comment: Axes hidden, white edge borders, alpha transparency, styled legend - with fancybox, thin leader lines. + comment: Axes removed, white circle edges, alpha transparency, group spacing + differentiation, path effects on text. Minor center crowding. - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: Size variation communicates budget hierarchy. Color grouping reveals - organizational structure. Group clustering visible. + comment: Group clustering creates organizational narrative. Size variation + guides the eye. Title adds total budget context. Color grouping reveals + structure. spec_compliance: score: 15 max: 15 @@ -141,28 +139,28 @@ review: score: 5 max: 5 passed: true - comment: Correct packed bubble chart with physics-simulated circle packing. + comment: Correct packed bubble chart with physics simulation packing. - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Area-proportional sizing, force simulation, smart labeling, color-coded - groups, group clustering. + comment: 'All spec features: area-proportional sizing, physics simulation, + labels inside/outside, color encoding, group clustering.' - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Values correctly mapped to circle area via sqrt normalization. All - 15 items visible. + comment: Values correctly mapped to circle area via sqrt scaling. All 15 items + represented. - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title follows required format. Legend correctly shows all 4 groups - with matching colors. + comment: Title includes bubble-packed · matplotlib · pyplots.ai. Legend shows + all four groups with matching colors. data_quality: score: 15 max: 15 @@ -172,21 +170,22 @@ review: score: 6 max: 6 passed: true - comment: Wide range of values ($130K-$950K). Four groups with varying membership. - Mix of large and small circles. + comment: Wide range of sizes, four distinct groups, internal and external + labels, group clustering with spacing. - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Department budget allocation is a real-world corporate scenario. - Neutral business topic. + comment: Department budget allocation is a concrete neutral business scenario + with recognizable department names. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Budget values $130K-$950K realistic for department-level allocations. + comment: Budget values $130K-$950K are realistic. Total $5.9M plausible for + mid-size tech company. code_quality: score: 10 max: 10 @@ -196,34 +195,35 @@ review: score: 3 max: 3 passed: true - comment: 'Linear flow: imports, data, simulation, plot, save. No functions - or classes.' + comment: 'Linear structure: imports, data, scaling, physics simulation, plotting, + saving. No functions or classes.' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: All data hardcoded. Physics simulation uses deterministic initial - positions. + comment: 'Fully deterministic: hardcoded data, deterministic spiral positions, + no randomness in simulation.' - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: 'All four imports used: collections, patches, pyplot, numpy.' + comment: 'All five imports used: collections, patches, patheffects, pyplot, + numpy.' - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Well-organized sections. Physics simulation complexity appropriate - for the task. + comment: Complexity appropriate for packed bubble in matplotlib. Well-commented, + no over-engineering. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png at 300 dpi. Current matplotlib API. + comment: Saves as plot.png at 300 DPI. No deprecated API usage. library_mastery: score: 7 max: 10 @@ -233,13 +233,13 @@ review: score: 4 max: 5 passed: true - comment: PatchCollection for batch rendering. ax methods throughout. annotate - with arrowprops for leader lines. + comment: Good use of PatchCollection, mpatches.Circle, ax.annotate with arrowprops, + path_effects. OO API throughout. - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: PatchCollection with custom Circle patches is distinctively matplotlib. - Patches/collections module usage. + comment: PatchCollection for batch rendering, patheffects for text outlines, + annotate with arrowprops. Distinctive matplotlib features. verdict: REJECTED