From e68c43ed536d488f5681ab8307d5da0b70e9bd31 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Sun, 15 Feb 2026 22:28:00 +0100 Subject: [PATCH 1/8] =?UTF-8?q?update(heatmap-basic):=20plotnine=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 quality review: fix weaknesses from prior reviews, preserve strengths, improve quality across all dimensions. --- .../heatmap-basic/implementations/plotnine.py | 77 ++++++++++--------- plots/heatmap-basic/metadata/plotnine.yaml | 10 +-- plots/heatmap-basic/specification.md | 2 +- plots/heatmap-basic/specification.yaml | 3 +- 4 files changed, 50 insertions(+), 42 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index f28feba654..87bd29f503 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,7 +1,7 @@ -""" pyplots.ai +"""pyplots.ai heatmap-basic: Basic Heatmap -Library: plotnine 0.15.2 | Python 3.13.11 -Quality: 92/100 | Created: 2025-12-23 +Library: plotnine 0.15.3 | Python 3.14.3 +Quality: /100 | Updated: 2026-02-15 """ import numpy as np @@ -9,67 +9,74 @@ from plotnine import ( aes, element_blank, + element_rect, element_text, geom_text, geom_tile, ggplot, labs, + scale_color_identity, scale_fill_gradient2, + scale_x_discrete, + scale_y_discrete, theme, theme_minimal, ) -# Data - 8x8 matrix with meaningful patterns (performance metrics by region and quarter) +# Data - 8x8 matrix: quarterly growth rates (%) by department np.random.seed(42) -rows = ["Region A", "Region B", "Region C", "Region D", "Region E", "Region F", "Region G", "Region H"] -cols = ["Q1 2023", "Q2 2023", "Q3 2023", "Q4 2023", "Q1 2024", "Q2 2024", "Q3 2024", "Q4 2024"] +departments = ["Engineering", "Marketing", "Sales", "Finance", "Operations", "HR", "Research", "Support"] +quarters = ["Q1 '23", "Q2 '23", "Q3 '23", "Q4 '23", "Q1 '24", "Q2 '24", "Q3 '24", "Q4 '24"] -# Create data with a trend and variation -base_values = np.linspace(-30, 40, 8) # Trend across columns -row_effects = np.random.uniform(-10, 10, 8) # Row-specific offsets +# Growth rates with a recovery trend and departmental variation +base_trend = np.linspace(-15, 20, 8) +dept_offsets = np.array([-5, 8, 12, -2, 3, -8, 6, -4]) values = np.zeros((8, 8)) for i in range(8): for j in range(8): - values[i, j] = base_values[j] + row_effects[i] + np.random.uniform(-8, 8) + values[i, j] = round(base_trend[j] + dept_offsets[i] + np.random.normal(0, 4), 1) -# Create long-form DataFrame for plotnine -data = [] -for i, row in enumerate(rows): - for j, col in enumerate(cols): - data.append({"x": col, "y": row, "value": round(values[i, j], 1)}) +# Long-form DataFrame +records = [] +for i, dept in enumerate(departments): + for j, qtr in enumerate(quarters): + records.append({"Department": dept, "Quarter": qtr, "Growth": values[i, j]}) -df = pd.DataFrame(data) +df = pd.DataFrame(records) +df["Quarter"] = pd.Categorical(df["Quarter"], categories=quarters, ordered=True) +df["Department"] = pd.Categorical(df["Department"], categories=departments[::-1], ordered=True) -# Preserve ordering -df["x"] = pd.Categorical(df["x"], categories=cols, ordered=True) -df["y"] = pd.Categorical(df["y"], categories=rows[::-1], ordered=True) # Reverse for top-to-bottom +# Conditional text color: white on dark blue cells, dark on light cells +df["text_color"] = df["Growth"].apply(lambda v: "white" if v < -10 else "#333333") + +# Format labels with sign +df["label"] = df["Growth"].apply(lambda v: f"{v:+.1f}") # Plot plot = ( - ggplot(df, aes(x="x", y="y", fill="value")) - + geom_tile(color="white", size=0.5) - + geom_text(aes(label="value"), size=12, color="black") - + scale_fill_gradient2( - low="#306998", # Python Blue for negative - mid="white", - high="#FFD43B", # Python Yellow for positive - midpoint=0, - name="Value", - ) - + labs(x="Time Period", y="Region", title="heatmap-basic · plotnine · pyplots.ai") + ggplot(df, aes(x="Quarter", y="Department")) + + geom_tile(aes(fill="Growth"), color="white", size=0.8) + + geom_text(aes(label="label", color="text_color"), size=11, fontweight="bold", show_legend=False) + + scale_fill_gradient2(low="#306998", mid="#f5f5f0", high="#FFD43B", midpoint=0, name="Growth (%)") + + scale_color_identity() + + scale_x_discrete(expand=(0, 0.5)) + + scale_y_discrete(expand=(0, 0.5)) + + labs(x="", y="", title="Quarterly Growth by Department · heatmap-basic · plotnine · pyplots.ai") + theme_minimal() + theme( figure_size=(16, 9), - text=element_text(size=14), - axis_title=element_text(size=20), - axis_text_x=element_text(size=14, rotation=45, ha="right"), - axis_text_y=element_text(size=16), - plot_title=element_text(size=24), + text=element_text(family="sans-serif"), + plot_title=element_text(size=22, ha="center", margin={"b": 15}), + axis_text_x=element_text(size=16, rotation=45, ha="right", margin={"t": 5}), + axis_text_y=element_text(size=16, ha="right", margin={"r": 5}), legend_title=element_text(size=16), legend_text=element_text(size=14), + legend_position="right", panel_grid_major=element_blank(), panel_grid_minor=element_blank(), + panel_background=element_rect(fill="white"), + plot_background=element_rect(fill="white"), ) ) diff --git a/plots/heatmap-basic/metadata/plotnine.yaml b/plots/heatmap-basic/metadata/plotnine.yaml index 9263e7671c..f952a00f22 100644 --- a/plots/heatmap-basic/metadata/plotnine.yaml +++ b/plots/heatmap-basic/metadata/plotnine.yaml @@ -1,16 +1,16 @@ library: plotnine specification_id: heatmap-basic created: '2025-12-23T00:47:36Z' -updated: '2025-12-23T00:51:16Z' -generated_by: claude-opus-4-5-20251101 +updated: '2026-02-15T21:25:00+00:00' +generated_by: claude-opus-4-6 workflow_run: 20447967616 issue: 0 -python_version: 3.13.11 -library_version: 0.15.2 +python_version: 3.14.3 +library_version: 0.15.3 preview_url: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot_thumb.png preview_html: null -quality_score: 92 +quality_score: null impl_tags: dependencies: [] techniques: diff --git a/plots/heatmap-basic/specification.md b/plots/heatmap-basic/specification.md index cef917e2dc..4b790ff068 100644 --- a/plots/heatmap-basic/specification.md +++ b/plots/heatmap-basic/specification.md @@ -23,4 +23,4 @@ A heatmap displaying values in a matrix format using color intensity. Each cell' - Use a diverging colormap for data with positive/negative values - Add value annotations in cells when readable - Include a colorbar legend -- Consider clustering rows/columns for better pattern visibility +- Order rows/columns logically (alphabetical, by magnitude, or by similarity) diff --git a/plots/heatmap-basic/specification.yaml b/plots/heatmap-basic/specification.yaml index 8c02cfc6a5..82b0687684 100644 --- a/plots/heatmap-basic/specification.yaml +++ b/plots/heatmap-basic/specification.yaml @@ -6,7 +6,7 @@ title: Basic Heatmap # Specification tracking created: 2025-12-14T09:02:34Z -updated: 2025-12-14T09:02:34Z +updated: 2026-02-15T12:00:00Z issue: 691 suggested: MarkusNeusinger @@ -18,6 +18,7 @@ tags: data_type: - numeric - categorical + - matrix domain: - statistics - general From 0724dc07cd5b489fe88f202a305982177d64f589 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Feb 2026 21:30:57 +0000 Subject: [PATCH 2/8] chore(plotnine): update quality score 89 and review feedback for heatmap-basic --- .../heatmap-basic/implementations/plotnine.py | 4 +- plots/heatmap-basic/metadata/plotnine.yaml | 249 +++++++++--------- 2 files changed, 133 insertions(+), 120 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index 87bd29f503..7bb1542579 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai heatmap-basic: Basic Heatmap Library: plotnine 0.15.3 | Python 3.14.3 -Quality: /100 | Updated: 2026-02-15 +Quality: 89/100 | Updated: 2026-02-15 """ import numpy as np diff --git a/plots/heatmap-basic/metadata/plotnine.yaml b/plots/heatmap-basic/metadata/plotnine.yaml index f952a00f22..1ec6a7a22e 100644 --- a/plots/heatmap-basic/metadata/plotnine.yaml +++ b/plots/heatmap-basic/metadata/plotnine.yaml @@ -1,7 +1,7 @@ library: plotnine specification_id: heatmap-basic created: '2025-12-23T00:47:36Z' -updated: '2026-02-15T21:25:00+00:00' +updated: '2026-02-15T21:30:56Z' generated_by: claude-opus-4-6 workflow_run: 20447967616 issue: 0 @@ -10,163 +10,171 @@ library_version: 0.15.3 preview_url: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot_thumb.png preview_html: null -quality_score: null +quality_score: 89 impl_tags: dependencies: [] techniques: - - colorbar - annotations + - colorbar - layer-composition patterns: - data-generation - - wide-to-long + - matrix-construction + - iteration-over-groups dataprep: [] styling: + - custom-colormap - edge-highlighting + - minimal-chrome review: strengths: - - Excellent diverging color scheme using Python brand colors (blue/yellow) that - is colorblind-safe - - Clear value annotations in each cell make exact values easy to read - - Well-structured data with meaningful trend pattern showing performance improvement - over time - - Clean use of plotnine grammar of graphics with proper layering (geom_tile + geom_text) - - Correct categorical ordering preserves temporal sequence on x-axis and intuitive - top-to-bottom region ordering - - Title follows exact specification format + - Excellent use of Python Blue (#306998) and Python Yellow (#FFD43B) as a thematic + diverging palette — on-brand and colorblind-safe + - Conditional text color (white on dark blue, dark on light) ensures readability + across the entire range + - Data tells a clear recovery story that is immediately apparent from the color + gradient progression + - Clean, idiomatic plotnine code with appropriate use of scale_fill_gradient2 and + scale_color_identity + - Bold value annotations with +/- signs make precise values easy to read weaknesses: - - Axis labels lack units or additional context (e.g., Value could specify Performance - Index or similar) - - Cell annotation text color is always black, which reduces contrast on darker blue - cells (e.g., Region G, Q1 2023 at -45.4) - image_description: The heatmap displays an 8x8 matrix showing performance metrics - across 8 regions (A-H on the y-axis) and 8 time periods (Q1 2023 through Q4 2024 - on the x-axis). The color scheme uses a diverging palette with Python Blue (#306998) - for negative values and Python Yellow (#FFD43B) for positive values, with white - at the midpoint (0). Each cell contains its numerical value as a text annotation. - The colorbar legend on the right shows the "Value" scale ranging from approximately - -25 to +25. The title "heatmap-basic · plotnine · pyplots.ai" appears at the top. - The plot clearly shows a trend pattern where earlier quarters have predominantly - negative values (blue) and later quarters show positive values (yellow), demonstrating - regional performance improvement over time. + - Title font size is 22pt, below the recommended 24pt minimum for the output resolution + - Axis labels are empty strings — for a standalone visualization, even minimal labels + like Quarter and Department would improve clarity + - Layout has some extra whitespace at the bottom due to rotated x-axis labels; tighter + margins could improve canvas utilization + image_description: 'The plot displays an 8x8 heatmap titled "Quarterly Growth by + Department · heatmap-basic · plotnine · pyplots.ai". Eight departments (Engineering, + Marketing, Sales, Finance, Operations, HR, Research, Support) are on the Y-axis + and eight quarters (Q1 ''23 through Q4 ''24) on the X-axis. Each cell is colored + using a diverging blue-white-yellow gradient: blue (#306998) for negative growth, + cream/white near zero, and yellow (#FFD43B) for positive growth. Every cell contains + a bold annotation showing the growth percentage with a +/- sign. Text color adapts + — white on dark blue cells, dark gray (#333) on lighter cells. White borders separate + tiles. A colorbar on the right labeled "Growth (%)" ranges from approximately + -20 to +20. X-axis labels are rotated 45 degrees. The data tells a clear recovery + story: left columns (2023) are predominantly blue (negative), transitioning to + yellow (positive) on the right (2024), with varying recovery rates across departments.' criteria_checklist: visual_quality: - score: 37 - max: 40 + score: 26 + max: 30 items: - id: VQ-01 name: Text Legibility - score: 10 - max: 10 + score: 6 + max: 8 passed: true - comment: Title at 24pt, axis labels at 20pt, tick labels at 14-16pt, cell - annotations at size 12 - all clearly readable + comment: All text readable; title is 22pt (below recommended 24pt), axis text + 16pt meets tick label standard - id: VQ-02 name: No Overlap - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: No overlapping text elements, x-axis labels rotated 45° to avoid - collision + comment: No overlapping text elements anywhere - id: VQ-03 name: Element Visibility - score: 8 - max: 8 + score: 6 + max: 6 passed: true - comment: Tiles are well-sized with clear white borders, annotations visible - on all backgrounds + comment: Tiles well-sized, annotations clearly visible in every cell - id: VQ-04 name: Color Accessibility - score: 5 - max: 5 + score: 4 + max: 4 passed: true - comment: Blue-white-yellow diverging palette is colorblind-safe (avoids red-green) + comment: Blue-to-yellow diverging scheme is colorblind-safe - id: VQ-05 name: Layout Balance - score: 4 - max: 5 + score: 3 + max: 4 passed: true - comment: Good proportions, slight white space on right side near colorbar - but acceptable + comment: Good proportions, slight extra whitespace at bottom from rotated + labels - id: VQ-06 - name: Axis Labels + name: Axis Labels & Title score: 1 max: 2 passed: true - comment: '"Time Period" and "Region" are descriptive but lack units' - - id: VQ-07 - name: Grid & Legend - score: 1 - max: 2 + comment: Axes use empty string labels; colorbar has units but axes lack labels + design_excellence: + score: 15 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 6 + max: 8 passed: true - comment: 'Grid removed for clean heatmap look, legend well placed; minor: - panel_grid_major=element_blank removes subtle structure' + comment: Custom Python Blue/Yellow diverging palette, conditional text coloring, + white tile borders + - id: DE-02 + name: Visual Refinement + score: 5 + max: 6 + passed: true + comment: Grid removed, minimal theme, white backgrounds, tile borders provide + clean structure + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Clear temporal recovery narrative visible through color progression + left-to-right spec_compliance: - score: 25 - max: 25 + score: 15 + max: 15 items: - id: SC-01 name: Plot Type - score: 8 - max: 8 + score: 5 + max: 5 passed: true comment: Correct heatmap using geom_tile - id: SC-02 - name: Data Mapping - score: 5 - max: 5 + name: Required Features + score: 4 + max: 4 passed: true - comment: X=time periods, Y=regions, fill=value correctly assigned + comment: Diverging colormap, value annotations, colorbar legend, logical ordering + all present - id: SC-03 - name: Required Features - score: 5 - max: 5 + name: Data Mapping + score: 3 + max: 3 passed: true - comment: Diverging colormap for +/- values ✓, value annotations ✓, colorbar - legend + comment: Quarters on X, departments on Y, growth as fill - id: SC-04 - name: Data Range + name: Title & Legend score: 3 max: 3 passed: true - comment: All data visible, axes show complete range - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: '"Value" legend label correct with proper scale' - - id: SC-06 - name: Title Format - score: 2 - max: 2 - passed: true - comment: Uses exact format "heatmap-basic · plotnine · pyplots.ai" + comment: Title format correct, colorbar labeled with units data_quality: - score: 18 - max: 20 + score: 14 + max: 15 items: - id: DQ-01 name: Feature Coverage - score: 7 - max: 8 + score: 5 + max: 6 passed: true - comment: Shows both positive and negative values, trend patterns, regional - variation; could show more extreme outliers + comment: Shows positive and negative values, varying magnitudes, clear temporal + and departmental patterns - id: DQ-02 name: Realistic Context - score: 7 - max: 7 + score: 5 + max: 5 passed: true - comment: Performance metrics by region and quarter is a real, comprehensible - business scenario + comment: Quarterly departmental growth rates — realistic business scenario - id: DQ-03 name: Appropriate Scale score: 4 - max: 5 + max: 4 passed: true - comment: Values range from ~-45 to ~+47, plausible for performance metrics - but units undefined + comment: Growth rates -22% to +29% are plausible for quarterly metrics code_quality: score: 10 max: 10 @@ -176,41 +184,46 @@ review: score: 3 max: 3 passed: true - comment: Clean imports → data → plot → save structure, no unnecessary functions/classes + comment: Clean imports, data, plot, save structure - id: CQ-02 name: Reproducibility - score: 3 - max: 3 + score: 2 + max: 2 passed: true - comment: Uses np.random.seed(42) + comment: np.random.seed(42) set - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used + comment: All imports used - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 + name: Code Elegance + score: 2 + max: 2 passed: true - comment: Uses current plotnine API + comment: Clean, Pythonic, appropriate complexity - id: CQ-05 - name: Output Correct + name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png - library_features: - score: 2 - max: 5 + comment: Saves as plot.png, no deprecated functions + library_mastery: + score: 9 + max: 10 items: - - id: LF-01 - name: Uses distinctive library features - score: 2 + - id: LM-01 + name: Idiomatic Usage + score: 5 max: 5 - passed: false - comment: Good use of ggplot grammar with geom_tile + geom_text layering, but - scale_fill_gradient2 is basic; could leverage faceting or more advanced - theming - verdict: APPROVED + passed: true + comment: Excellent ggplot2 grammar composition with layers, scales, and themes + - id: LM-02 + name: Distinctive Features + score: 4 + max: 5 + passed: true + comment: scale_fill_gradient2, scale_color_identity, pd.Categorical ordering + — distinctively ggplot2-style + verdict: REJECTED From 422fda167eec34e45442e9921046a8e4a7e3c9dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Feb 2026 21:34:50 +0000 Subject: [PATCH 3/8] fix(plotnine): address review feedback for heatmap-basic Attempt 1/3 - fixes based on AI review --- plots/heatmap-basic/implementations/plotnine.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index 7bb1542579..4593d52cfc 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,7 +1,6 @@ -""" pyplots.ai +"""pyplots.ai heatmap-basic: Basic Heatmap Library: plotnine 0.15.3 | Python 3.14.3 -Quality: 89/100 | Updated: 2026-02-15 """ import numpy as np @@ -62,12 +61,14 @@ + scale_color_identity() + scale_x_discrete(expand=(0, 0.5)) + scale_y_discrete(expand=(0, 0.5)) - + labs(x="", y="", title="Quarterly Growth by Department · heatmap-basic · plotnine · pyplots.ai") + + labs(x="Quarter", y="Department", title="Quarterly Growth by Department · heatmap-basic · plotnine · pyplots.ai") + theme_minimal() + theme( figure_size=(16, 9), text=element_text(family="sans-serif"), - plot_title=element_text(size=22, ha="center", margin={"b": 15}), + plot_title=element_text(size=24, ha="center", weight="bold", margin={"b": 15}), + axis_title_x=element_text(size=20, margin={"t": 10}), + axis_title_y=element_text(size=20, margin={"r": 10}), axis_text_x=element_text(size=16, rotation=45, ha="right", margin={"t": 5}), axis_text_y=element_text(size=16, ha="right", margin={"r": 5}), legend_title=element_text(size=16), From f7a6691914cc2662a16fcf20a5092b5fd6f45c18 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Feb 2026 21:38:34 +0000 Subject: [PATCH 4/8] chore(plotnine): update quality score 89 and review feedback for heatmap-basic --- .../heatmap-basic/implementations/plotnine.py | 3 +- plots/heatmap-basic/metadata/plotnine.yaml | 141 +++++++++--------- 2 files changed, 72 insertions(+), 72 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index 4593d52cfc..6884187f20 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,6 +1,7 @@ -"""pyplots.ai +""" pyplots.ai heatmap-basic: Basic Heatmap Library: plotnine 0.15.3 | Python 3.14.3 +Quality: 89/100 | Updated: 2026-02-15 """ import numpy as np diff --git a/plots/heatmap-basic/metadata/plotnine.yaml b/plots/heatmap-basic/metadata/plotnine.yaml index 1ec6a7a22e..fea02ce30b 100644 --- a/plots/heatmap-basic/metadata/plotnine.yaml +++ b/plots/heatmap-basic/metadata/plotnine.yaml @@ -1,7 +1,7 @@ library: plotnine specification_id: heatmap-basic created: '2025-12-23T00:47:36Z' -updated: '2026-02-15T21:30:56Z' +updated: '2026-02-15T21:38:34Z' generated_by: claude-opus-4-6 workflow_run: 20447967616 issue: 0 @@ -15,7 +15,6 @@ impl_tags: dependencies: [] techniques: - annotations - - colorbar - layer-composition patterns: - data-generation @@ -25,104 +24,104 @@ impl_tags: styling: - custom-colormap - edge-highlighting - - minimal-chrome review: strengths: - - Excellent use of Python Blue (#306998) and Python Yellow (#FFD43B) as a thematic - diverging palette — on-brand and colorblind-safe - - Conditional text color (white on dark blue, dark on light) ensures readability - across the entire range - - Data tells a clear recovery story that is immediately apparent from the color - gradient progression - - Clean, idiomatic plotnine code with appropriate use of scale_fill_gradient2 and - scale_color_identity - - Bold value annotations with +/- signs make precise values easy to read + - Excellent use of plotnine grammar of graphics with scale_fill_gradient2 for a + Python-themed diverging palette (blue-to-yellow) + - Bold cell annotations with conditional text color (white on dark, dark on light) + ensure readability across all cells + - Data tells a compelling recovery story — the left-to-right blue-to-yellow progression + is immediately apparent + - Clean KISS code structure with appropriate use of pd.Categorical for axis ordering + - 'All spec requirements fully met: diverging colormap, annotations, colorbar, logical + ordering' weaknesses: - - Title font size is 22pt, below the recommended 24pt minimum for the output resolution - - Axis labels are empty strings — for a standalone visualization, even minimal labels - like Quarter and Department would improve clarity - - Layout has some extra whitespace at the bottom due to rotated x-axis labels; tighter - margins could improve canvas utilization + - Axis labels lack units or additional context — consider appending percent or YoY + context to subtitle + - Light yellow cells could benefit from slightly stronger saturation for better + visual contrast + - Left margin has slightly more whitespace than needed, reducing canvas efficiency image_description: 'The plot displays an 8x8 heatmap titled "Quarterly Growth by - Department · heatmap-basic · plotnine · pyplots.ai". Eight departments (Engineering, - Marketing, Sales, Finance, Operations, HR, Research, Support) are on the Y-axis - and eight quarters (Q1 ''23 through Q4 ''24) on the X-axis. Each cell is colored - using a diverging blue-white-yellow gradient: blue (#306998) for negative growth, - cream/white near zero, and yellow (#FFD43B) for positive growth. Every cell contains - a bold annotation showing the growth percentage with a +/- sign. Text color adapts - — white on dark blue cells, dark gray (#333) on lighter cells. White borders separate - tiles. A colorbar on the right labeled "Growth (%)" ranges from approximately - -20 to +20. X-axis labels are rotated 45 degrees. The data tells a clear recovery - story: left columns (2023) are predominantly blue (negative), transitioning to - yellow (positive) on the right (2024), with varying recovery rates across departments.' + Department · heatmap-basic · plotnine · pyplots.ai." Eight departments (Engineering, + Marketing, Sales, Finance, Operations, HR, Research, Support) are arranged on + the y-axis, and eight quarters (Q1 ''23 through Q4 ''24) on the x-axis. A diverging + color scheme transitions from steel blue (#306998) for negative values through + off-white for near-zero to golden yellow (#FFD43B) for positive values. Each cell + contains a bold annotation showing the exact growth percentage with a +/- sign. + White borders cleanly separate the tiles. The colorbar on the right is labeled + "Growth (%)" with a scale from approximately -20 to +20. X-axis labels are rotated + 45 degrees for readability. The visual story is immediately clear: a recovery + trend flows from left (blue/negative) to right (yellow/positive), with departmental + variation adding depth. HR and Support show the deepest early negatives while + Sales and Research recover most strongly.' criteria_checklist: visual_quality: - score: 26 + score: 27 max: 30 items: - id: VQ-01 name: Text Legibility - score: 6 + score: 8 max: 8 passed: true - comment: All text readable; title is 22pt (below recommended 24pt), axis text - 16pt meets tick label standard + comment: 'All font sizes explicitly set: title 24pt, axis titles 20pt, axis + text 16pt, legend 14-16pt' - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text elements anywhere + comment: No overlapping text; rotated x-labels and well-sized annotations - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: Tiles well-sized, annotations clearly visible in every cell + comment: Tiles perfectly fill the grid, annotations clearly visible - id: VQ-04 name: Color Accessibility - score: 4 + score: 3 max: 4 - passed: true - comment: Blue-to-yellow diverging scheme is colorblind-safe + passed: false + comment: Blue-to-yellow diverging is colorblind-friendly; light yellow cells + have slightly lower contrast with dark text - id: VQ-05 name: Layout Balance score: 3 max: 4 - passed: true - comment: Good proportions, slight extra whitespace at bottom from rotated - labels + passed: false + comment: Good canvas utilization; slight excess whitespace on left side - id: VQ-06 name: Axis Labels & Title score: 1 max: 2 - passed: true - comment: Axes use empty string labels; colorbar has units but axes lack labels + passed: false + comment: Descriptive labels but lack units; growth % only in colorbar legend design_excellence: - score: 15 + score: 14 max: 20 items: - id: DE-01 name: Aesthetic Sophistication score: 6 max: 8 - passed: true - comment: Custom Python Blue/Yellow diverging palette, conditional text coloring, - white tile borders + passed: false + comment: Custom Python Blue-to-Yellow palette is thematic; bold annotations, + white borders, clearly above defaults - id: DE-02 name: Visual Refinement - score: 5 + score: 4 max: 6 - passed: true - comment: Grid removed, minimal theme, white backgrounds, tile borders provide - clean structure + passed: false + comment: Grid removed, minimal theme, white backgrounds; good but not fully + publication-level polish - id: DE-03 name: Data Storytelling score: 4 max: 6 - passed: true - comment: Clear temporal recovery narrative visible through color progression - left-to-right + passed: false + comment: Recovery trend immediately visible through color gradient; department + variation adds narrative depth spec_compliance: score: 15 max: 15 @@ -132,26 +131,25 @@ review: score: 5 max: 5 passed: true - comment: Correct heatmap using geom_tile + comment: Correct heatmap via geom_tile - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Diverging colormap, value annotations, colorbar legend, logical ordering - all present + comment: Diverging colormap, annotations, colorbar, logical ordering all present - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Quarters on X, departments on Y, growth as fill + comment: X/Y correctly assigned - id: SC-04 - name: Title & Legend + name: Title Format score: 3 max: 3 passed: true - comment: Title format correct, colorbar labeled with units + comment: Correct format with spec-id, library, pyplots.ai data_quality: score: 14 max: 15 @@ -160,21 +158,21 @@ review: name: Feature Coverage score: 5 max: 6 - passed: true - comment: Shows positive and negative values, varying magnitudes, clear temporal - and departmental patterns + passed: false + comment: Shows positive/negative values, temporal trend, departmental variation; + could benefit from more extreme outliers - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Quarterly departmental growth rates — realistic business scenario + comment: Quarterly department growth rates — realistic neutral business scenario - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Growth rates -22% to +29% are plausible for quarterly metrics + comment: Values from -22% to +30% are realistic for quarterly performance code_quality: score: 10 max: 10 @@ -184,13 +182,13 @@ review: score: 3 max: 3 passed: true - comment: Clean imports, data, plot, save structure + comment: Imports, data, plot, save — no functions or classes - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set + comment: np.random.seed(42) - id: CQ-03 name: Clean Imports score: 2 @@ -202,7 +200,7 @@ review: score: 2 max: 2 passed: true - comment: Clean, Pythonic, appropriate complexity + comment: Clean conditional text color logic, appropriate complexity - id: CQ-05 name: Output & API score: 1 @@ -218,12 +216,13 @@ review: score: 5 max: 5 passed: true - comment: Excellent ggplot2 grammar composition with layers, scales, and themes + comment: Expert grammar-of-graphics composition, proper aes(), scales, themes, + pd.Categorical ordering - id: LM-02 name: Distinctive Features score: 4 max: 5 - passed: true - comment: scale_fill_gradient2, scale_color_identity, pd.Categorical ordering - — distinctively ggplot2-style + passed: false + comment: scale_fill_gradient2 for diverging, scale_color_identity for conditional + text, pd.Categorical for axis ordering verdict: REJECTED From 810bab196c578b4175709643e3b20ef8b997c232 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Feb 2026 21:42:14 +0000 Subject: [PATCH 5/8] fix(plotnine): address review feedback for heatmap-basic Attempt 2/3 - fixes based on AI review --- .../heatmap-basic/implementations/plotnine.py | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index 6884187f20..5e396d6d17 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,4 +1,4 @@ -""" pyplots.ai +"""pyplots.ai heatmap-basic: Basic Heatmap Library: plotnine 0.15.3 | Python 3.14.3 Quality: 89/100 | Updated: 2026-02-15 @@ -30,55 +30,71 @@ quarters = ["Q1 '23", "Q2 '23", "Q3 '23", "Q4 '23", "Q1 '24", "Q2 '24", "Q3 '24", "Q4 '24"] # Growth rates with a recovery trend and departmental variation -base_trend = np.linspace(-15, 20, 8) -dept_offsets = np.array([-5, 8, 12, -2, 3, -8, 6, -4]) +# Include a wider range with a few extreme outliers for feature coverage +base_trend = np.linspace(-18, 22, 8) +dept_offsets = np.array([-6, 10, 14, -3, 4, -10, 8, -5]) values = np.zeros((8, 8)) for i in range(8): for j in range(8): values[i, j] = round(base_trend[j] + dept_offsets[i] + np.random.normal(0, 4), 1) +# Inject a few distinctive extreme values for storytelling +values[5, 0] = -32.5 # HR deep crisis in Q1 '23 +values[2, 7] = 38.2 # Sales strong recovery in Q4 '24 +values[6, 6] = 33.7 # Research surge in Q3 '24 + # Long-form DataFrame records = [] for i, dept in enumerate(departments): for j, qtr in enumerate(quarters): - records.append({"Department": dept, "Quarter": qtr, "Growth": values[i, j]}) + records.append({"Department": dept, "Quarter": qtr, "Growth (%)": values[i, j]}) df = pd.DataFrame(records) df["Quarter"] = pd.Categorical(df["Quarter"], categories=quarters, ordered=True) df["Department"] = pd.Categorical(df["Department"], categories=departments[::-1], ordered=True) -# Conditional text color: white on dark blue cells, dark on light cells -df["text_color"] = df["Growth"].apply(lambda v: "white" if v < -10 else "#333333") +# Conditional text color for optimal contrast on all cell backgrounds +df["text_color"] = df["Growth (%)"].apply(lambda v: "white" if v < -12 else ("#444444" if v < 18 else "#5a3e00")) # Format labels with sign -df["label"] = df["Growth"].apply(lambda v: f"{v:+.1f}") +df["label"] = df["Growth (%)"].apply(lambda v: f"{v:+.1f}") # Plot plot = ( ggplot(df, aes(x="Quarter", y="Department")) - + geom_tile(aes(fill="Growth"), color="white", size=0.8) - + geom_text(aes(label="label", color="text_color"), size=11, fontweight="bold", show_legend=False) - + scale_fill_gradient2(low="#306998", mid="#f5f5f0", high="#FFD43B", midpoint=0, name="Growth (%)") + + geom_tile(aes(fill="Growth (%)"), color="white", size=1.0) + + geom_text(aes(label="label", color="text_color"), size=10, fontweight="bold", show_legend=False) + + scale_fill_gradient2( + low="#1a4971", mid="#f0eeeb", high="#cc8400", midpoint=0, name="Growth (%)", limits=(-35, 40) + ) + scale_color_identity() + scale_x_discrete(expand=(0, 0.5)) + scale_y_discrete(expand=(0, 0.5)) - + labs(x="Quarter", y="Department", title="Quarterly Growth by Department · heatmap-basic · plotnine · pyplots.ai") + + labs( + x="Quarter", + y="Department", + title="Quarterly Growth by Department · heatmap-basic · plotnine · pyplots.ai", + subtitle="Year-over-year growth rate (%) across departments, Q1 2023 – Q4 2024", + ) + theme_minimal() + theme( figure_size=(16, 9), text=element_text(family="sans-serif"), - plot_title=element_text(size=24, ha="center", weight="bold", margin={"b": 15}), - axis_title_x=element_text(size=20, margin={"t": 10}), - axis_title_y=element_text(size=20, margin={"r": 10}), - axis_text_x=element_text(size=16, rotation=45, ha="right", margin={"t": 5}), - axis_text_y=element_text(size=16, ha="right", margin={"r": 5}), - legend_title=element_text(size=16), - legend_text=element_text(size=14), + plot_title=element_text(size=22, ha="center", weight="bold", margin={"b": 4}), + plot_subtitle=element_text(size=15, ha="center", color="#666666", margin={"b": 12}), + axis_title_x=element_text(size=18, margin={"t": 10}), + axis_title_y=element_text(size=18, margin={"r": 8}), + axis_text_x=element_text(size=15, rotation=45, ha="right", margin={"t": 5}), + axis_text_y=element_text(size=15, ha="right", margin={"r": 5}), + legend_title=element_text(size=15, weight="bold"), + legend_text=element_text(size=13), legend_position="right", + legend_key_height=40, panel_grid_major=element_blank(), panel_grid_minor=element_blank(), - panel_background=element_rect(fill="white"), - plot_background=element_rect(fill="white"), + panel_background=element_rect(fill="white", color="none"), + plot_background=element_rect(fill="#fafafa", color="none"), + plot_margin=0.02, ) ) From ced82943de5b547d43edf12a3c34f13c0a06e73b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Feb 2026 21:46:32 +0000 Subject: [PATCH 6/8] chore(plotnine): update quality score 86 and review feedback for heatmap-basic --- .../heatmap-basic/implementations/plotnine.py | 4 +- plots/heatmap-basic/metadata/plotnine.yaml | 167 ++++++++++-------- 2 files changed, 92 insertions(+), 79 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index 5e396d6d17..84600da033 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,7 +1,7 @@ -"""pyplots.ai +""" pyplots.ai heatmap-basic: Basic Heatmap Library: plotnine 0.15.3 | Python 3.14.3 -Quality: 89/100 | Updated: 2026-02-15 +Quality: 86/100 | Updated: 2026-02-15 """ import numpy as np diff --git a/plots/heatmap-basic/metadata/plotnine.yaml b/plots/heatmap-basic/metadata/plotnine.yaml index fea02ce30b..803149d405 100644 --- a/plots/heatmap-basic/metadata/plotnine.yaml +++ b/plots/heatmap-basic/metadata/plotnine.yaml @@ -1,7 +1,7 @@ library: plotnine specification_id: heatmap-basic created: '2025-12-23T00:47:36Z' -updated: '2026-02-15T21:38:34Z' +updated: '2026-02-15T21:46:32Z' generated_by: claude-opus-4-6 workflow_run: 20447967616 issue: 0 @@ -10,7 +10,7 @@ library_version: 0.15.3 preview_url: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot_thumb.png preview_html: null -quality_score: 89 +quality_score: 86 impl_tags: dependencies: [] techniques: @@ -19,84 +19,95 @@ impl_tags: patterns: - data-generation - matrix-construction - - iteration-over-groups dataprep: [] styling: - custom-colormap - edge-highlighting review: strengths: - - Excellent use of plotnine grammar of graphics with scale_fill_gradient2 for a - Python-themed diverging palette (blue-to-yellow) - - Bold cell annotations with conditional text color (white on dark, dark on light) - ensure readability across all cells - - Data tells a compelling recovery story — the left-to-right blue-to-yellow progression - is immediately apparent - - Clean KISS code structure with appropriate use of pd.Categorical for axis ordering - - 'All spec requirements fully met: diverging colormap, annotations, colorbar, logical + - Excellent use of plotnine grammar of graphics with idiomatic layer composition + (geom_tile + geom_text) + - Smart conditional text coloring via scale_color_identity ensures readability across + all cell backgrounds + - Clear data storytelling with recovery trend from negative (blue) to positive (gold) + across quarters + - Custom diverging palette (steel blue to off-white to gold) with well-chosen midpoint=0 + - Deliberate extreme values (HR -32.5%, Sales +38.2%) create visual focal points + - Realistic neutral business scenario with plausible growth rate values + - 'All spec requirements met: diverging colormap, cell annotations, colorbar, logical ordering' weaknesses: - - Axis labels lack units or additional context — consider appending percent or YoY - context to subtitle - - Light yellow cells could benefit from slightly stronger saturation for better - visual contrast - - Left margin has slightly more whitespace than needed, reducing canvas efficiency + - Title font size 22pt slightly under the 24pt guideline for optimal readability + at full resolution + - Mid-range color contrast could be stronger — values near zero on off-white background + are less visually distinct + - Code uses nested loops for matrix construction where vectorized numpy operations + could be more concise + - Categorical axis labels Quarter and Department lack units (though units are not + natural for categories) image_description: 'The plot displays an 8x8 heatmap titled "Quarterly Growth by - Department · heatmap-basic · plotnine · pyplots.ai." Eight departments (Engineering, - Marketing, Sales, Finance, Operations, HR, Research, Support) are arranged on - the y-axis, and eight quarters (Q1 ''23 through Q4 ''24) on the x-axis. A diverging - color scheme transitions from steel blue (#306998) for negative values through - off-white for near-zero to golden yellow (#FFD43B) for positive values. Each cell - contains a bold annotation showing the exact growth percentage with a +/- sign. - White borders cleanly separate the tiles. The colorbar on the right is labeled - "Growth (%)" with a scale from approximately -20 to +20. X-axis labels are rotated - 45 degrees for readability. The visual story is immediately clear: a recovery - trend flows from left (blue/negative) to right (yellow/positive), with departmental - variation adding depth. HR and Support show the deepest early negatives while - Sales and Research recover most strongly.' + Department · heatmap-basic · plotnine · pyplots.ai" with a subtitle "Year-over-year + growth rate (%) across departments, Q1 2023 – Q4 2024". The Y-axis lists eight + departments (Engineering, Marketing, Sales, Finance, Operations, HR, Research, + Support) and the X-axis shows eight quarters (Q1 ''23 through Q4 ''24, rotated + 45 degrees). Each cell is colored using a diverging scheme: steel blue for negative + values, off-white/cream for near-zero, and gold/amber for positive values. Every + cell contains a bold annotation showing the growth rate with a sign prefix (e.g., + "-32.5", "+38.2"). A vertical colorbar legend on the right labeled "Growth (%)" + shows the scale from approximately -20 to +40. The overall layout has a light + gray (#fafafa) background, white cell borders separating tiles, and no grid lines. + The data tells a clear recovery story: the left columns are predominantly blue + (negative growth) transitioning to gold (positive growth) on the right. Notable + extremes include HR at -32.5% in Q1 ''23 (deepest blue) and Sales at +38.2% in + Q4 ''24 (deepest gold). Text contrast is managed with white text on dark blue + cells, dark gray on mid-range cells, and dark brown/amber on bright gold cells.' criteria_checklist: visual_quality: - score: 27 + score: 26 max: 30 items: - id: VQ-01 name: Text Legibility - score: 8 + score: 7 max: 8 passed: true - comment: 'All font sizes explicitly set: title 24pt, axis titles 20pt, axis - text 16pt, legend 14-16pt' + comment: Font sizes explicitly set (title=22, subtitle=15, axis titles=18, + axis text=15, annotations size=10). Title slightly under 24pt guideline + but all text clearly readable. - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text; rotated x-labels and well-sized annotations + comment: No overlapping text anywhere. Rotated x-axis labels, well-spaced + cells. - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: Tiles perfectly fill the grid, annotations clearly visible + comment: Tiles perfectly sized for 8x8 grid, annotations clear and well-positioned. - id: VQ-04 name: Color Accessibility score: 3 max: 4 - passed: false - comment: Blue-to-yellow diverging is colorblind-friendly; light yellow cells - have slightly lower contrast with dark text + passed: true + comment: Blue-to-gold diverging scheme avoids red-green issues. Mid-range + contrast could be slightly stronger. - id: VQ-05 - name: Layout Balance + name: Layout & Canvas score: 3 max: 4 - passed: false - comment: Good canvas utilization; slight excess whitespace on left side + passed: true + comment: Good canvas utilization. Minor wasted space at top-left and between + subtitle and heatmap body. - id: VQ-06 name: Axis Labels & Title score: 1 max: 2 - passed: false - comment: Descriptive labels but lack units; growth % only in colorbar legend + passed: true + comment: Descriptive labels but categorical axes lack units. Subtitle provides + percent context. design_excellence: score: 14 max: 20 @@ -105,25 +116,25 @@ review: name: Aesthetic Sophistication score: 6 max: 8 - passed: false - comment: Custom Python Blue-to-Yellow palette is thematic; bold annotations, - white borders, clearly above defaults + passed: true + comment: Custom diverging palette, intentional typography hierarchy, conditional + text coloring. Clearly above defaults. - id: DE-02 name: Visual Refinement score: 4 max: 6 - passed: false - comment: Grid removed, minimal theme, white backgrounds; good but not fully - publication-level polish + passed: true + comment: Grid removed, minimal theme, white cell borders, light background, + explicit panel/plot background styling. - id: DE-03 name: Data Storytelling score: 4 max: 6 - passed: false - comment: Recovery trend immediately visible through color gradient; department - variation adds narrative depth + passed: true + comment: Clear recovery narrative. Extreme values create focal points. Conditional + text coloring adds visual hierarchy. spec_compliance: - score: 15 + score: 14 max: 15 items: - id: SC-01 @@ -131,25 +142,26 @@ review: score: 5 max: 5 passed: true - comment: Correct heatmap via geom_tile + comment: Correct heatmap using geom_tile. - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Diverging colormap, annotations, colorbar, logical ordering all present + comment: 'All spec features present: diverging colormap, value annotations, + colorbar legend, logically ordered rows/columns.' - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X/Y correctly assigned + comment: X=Quarter, Y=Department, value mapped to fill correctly. - id: SC-04 - name: Title Format - score: 3 + name: Title & Legend + score: 2 max: 3 passed: true - comment: Correct format with spec-id, library, pyplots.ai + comment: Title format correct with descriptive prefix. Colorbar legend appropriate. data_quality: score: 14 max: 15 @@ -158,23 +170,24 @@ review: name: Feature Coverage score: 5 max: 6 - passed: false - comment: Shows positive/negative values, temporal trend, departmental variation; - could benefit from more extreme outliers + passed: true + comment: Shows positive/negative values, extreme outliers, gradual trends, + departmental variation. - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Quarterly department growth rates — realistic neutral business scenario + comment: Realistic business scenario with department growth rates. Neutral + and comprehensible. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Values from -22% to +30% are realistic for quarterly performance + comment: Growth rates from -32.5% to +38.2% are realistic for business context. code_quality: - score: 10 + score: 9 max: 10 items: - id: CQ-01 @@ -182,31 +195,31 @@ review: score: 3 max: 3 passed: true - comment: Imports, data, plot, save — no functions or classes + comment: Clean imports, data, plot, save structure. - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) + comment: np.random.seed(42) set. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used + comment: All imports used. - id: CQ-04 name: Code Elegance - score: 2 + score: 1 max: 2 - passed: true - comment: Clean conditional text color logic, appropriate complexity + passed: false + comment: Slightly verbose with nested loops for matrix and DataFrame construction. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png, no deprecated functions + comment: Saves as plot.png, no deprecated functions. library_mastery: score: 9 max: 10 @@ -216,13 +229,13 @@ review: score: 5 max: 5 passed: true - comment: Expert grammar-of-graphics composition, proper aes(), scales, themes, - pd.Categorical ordering + comment: Excellent ggplot2-style grammar with aes mappings, geom layering, + scales, and theme customization. - id: LM-02 name: Distinctive Features score: 4 max: 5 - passed: false - comment: scale_fill_gradient2 for diverging, scale_color_identity for conditional - text, pd.Categorical for axis ordering - verdict: REJECTED + passed: true + comment: Uses scale_fill_gradient2, scale_color_identity for conditional text, + pd.Categorical for ordered factors. + verdict: APPROVED From fa67e35ae820cab35839fb46dc665de545f826cf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Feb 2026 21:50:08 +0000 Subject: [PATCH 7/8] fix(plotnine): address review feedback for heatmap-basic Attempt 3/3 - fixes based on AI review --- .../heatmap-basic/implementations/plotnine.py | 63 +++++++++---------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index 84600da033..95280cad13 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,7 +1,6 @@ -""" pyplots.ai +"""pyplots.ai heatmap-basic: Basic Heatmap Library: plotnine 0.15.3 | Python 3.14.3 -Quality: 86/100 | Updated: 2026-02-15 """ import numpy as np @@ -29,43 +28,41 @@ departments = ["Engineering", "Marketing", "Sales", "Finance", "Operations", "HR", "Research", "Support"] quarters = ["Q1 '23", "Q2 '23", "Q3 '23", "Q4 '23", "Q1 '24", "Q2 '24", "Q3 '24", "Q4 '24"] -# Growth rates with a recovery trend and departmental variation -# Include a wider range with a few extreme outliers for feature coverage +# Vectorized growth rates with recovery trend and departmental variation base_trend = np.linspace(-18, 22, 8) dept_offsets = np.array([-6, 10, 14, -3, 4, -10, 8, -5]) -values = np.zeros((8, 8)) -for i in range(8): - for j in range(8): - values[i, j] = round(base_trend[j] + dept_offsets[i] + np.random.normal(0, 4), 1) +values = np.round(base_trend[np.newaxis, :] + dept_offsets[:, np.newaxis] + np.random.normal(0, 4, (8, 8)), 1) -# Inject a few distinctive extreme values for storytelling +# Inject distinctive extreme values for storytelling focal points values[5, 0] = -32.5 # HR deep crisis in Q1 '23 values[2, 7] = 38.2 # Sales strong recovery in Q4 '24 values[6, 6] = 33.7 # Research surge in Q3 '24 -# Long-form DataFrame -records = [] -for i, dept in enumerate(departments): - for j, qtr in enumerate(quarters): - records.append({"Department": dept, "Quarter": qtr, "Growth (%)": values[i, j]}) - -df = pd.DataFrame(records) -df["Quarter"] = pd.Categorical(df["Quarter"], categories=quarters, ordered=True) -df["Department"] = pd.Categorical(df["Department"], categories=departments[::-1], ordered=True) +# Build long-form DataFrame via meshgrid indexing +dept_idx, qtr_idx = np.meshgrid(np.arange(8), np.arange(8), indexing="ij") +df = pd.DataFrame( + { + "Department": pd.Categorical( + [departments[i] for i in dept_idx.ravel()], categories=departments[::-1], ordered=True + ), + "Quarter": pd.Categorical([quarters[j] for j in qtr_idx.ravel()], categories=quarters, ordered=True), + "Growth (%)": values.ravel(), + } +) -# Conditional text color for optimal contrast on all cell backgrounds -df["text_color"] = df["Growth (%)"].apply(lambda v: "white" if v < -12 else ("#444444" if v < 18 else "#5a3e00")) +# Conditional text color: white on dark blue, dark gray on mid, dark brown on gold +df["text_color"] = np.where(df["Growth (%)"] < -12, "white", np.where(df["Growth (%)"] < 18, "#3a3a3a", "#4a2e00")) -# Format labels with sign -df["label"] = df["Growth (%)"].apply(lambda v: f"{v:+.1f}") +# Signed annotation labels +df["label"] = [f"{v:+.1f}" for v in df["Growth (%)"]] # Plot plot = ( ggplot(df, aes(x="Quarter", y="Department")) - + geom_tile(aes(fill="Growth (%)"), color="white", size=1.0) + + geom_tile(aes(fill="Growth (%)"), color="white", size=1.2) + geom_text(aes(label="label", color="text_color"), size=10, fontweight="bold", show_legend=False) + scale_fill_gradient2( - low="#1a4971", mid="#f0eeeb", high="#cc8400", midpoint=0, name="Growth (%)", limits=(-35, 40) + low="#14405e", mid="#ede8e3", high="#c47d00", midpoint=0, name="Growth (%)", limits=(-35, 40) ) + scale_color_identity() + scale_x_discrete(expand=(0, 0.5)) @@ -80,20 +77,20 @@ + theme( figure_size=(16, 9), text=element_text(family="sans-serif"), - plot_title=element_text(size=22, ha="center", weight="bold", margin={"b": 4}), - plot_subtitle=element_text(size=15, ha="center", color="#666666", margin={"b": 12}), - axis_title_x=element_text(size=18, margin={"t": 10}), - axis_title_y=element_text(size=18, margin={"r": 8}), - axis_text_x=element_text(size=15, rotation=45, ha="right", margin={"t": 5}), - axis_text_y=element_text(size=15, ha="right", margin={"r": 5}), - legend_title=element_text(size=15, weight="bold"), - legend_text=element_text(size=13), + plot_title=element_text(size=24, ha="center", weight="bold", margin={"b": 2}), + plot_subtitle=element_text(size=16, ha="center", color="#555555", margin={"b": 8}), + axis_title_x=element_text(size=20, margin={"t": 10}), + axis_title_y=element_text(size=20, margin={"r": 8}), + axis_text_x=element_text(size=16, rotation=45, ha="right", margin={"t": 4}), + axis_text_y=element_text(size=16, ha="right", margin={"r": 4}), + legend_title=element_text(size=16, weight="bold"), + legend_text=element_text(size=14), legend_position="right", legend_key_height=40, panel_grid_major=element_blank(), panel_grid_minor=element_blank(), panel_background=element_rect(fill="white", color="none"), - plot_background=element_rect(fill="#fafafa", color="none"), + plot_background=element_rect(fill="#f7f7f7", color="none"), plot_margin=0.02, ) ) From 66bd44dde1b0221d8ed7d0f74118bb3b43d460e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 16 Feb 2026 20:34:16 +0000 Subject: [PATCH 8/8] chore(plotnine): update quality score 92 and review feedback for heatmap-basic --- .../heatmap-basic/implementations/plotnine.py | 3 +- plots/heatmap-basic/metadata/plotnine.yaml | 162 ++++++++---------- 2 files changed, 78 insertions(+), 87 deletions(-) diff --git a/plots/heatmap-basic/implementations/plotnine.py b/plots/heatmap-basic/implementations/plotnine.py index 95280cad13..d3cc860b10 100644 --- a/plots/heatmap-basic/implementations/plotnine.py +++ b/plots/heatmap-basic/implementations/plotnine.py @@ -1,6 +1,7 @@ -"""pyplots.ai +""" pyplots.ai heatmap-basic: Basic Heatmap Library: plotnine 0.15.3 | Python 3.14.3 +Quality: 92/100 | Updated: 2026-02-16 """ import numpy as np diff --git a/plots/heatmap-basic/metadata/plotnine.yaml b/plots/heatmap-basic/metadata/plotnine.yaml index 803149d405..d1098bff26 100644 --- a/plots/heatmap-basic/metadata/plotnine.yaml +++ b/plots/heatmap-basic/metadata/plotnine.yaml @@ -1,7 +1,7 @@ library: plotnine specification_id: heatmap-basic created: '2025-12-23T00:47:36Z' -updated: '2026-02-15T21:46:32Z' +updated: '2026-02-16T20:34:16Z' generated_by: claude-opus-4-6 workflow_run: 20447967616 issue: 0 @@ -10,7 +10,7 @@ library_version: 0.15.3 preview_url: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot.png preview_thumb: https://storage.googleapis.com/pyplots-images/plots/heatmap-basic/plotnine/plot_thumb.png preview_html: null -quality_score: 86 +quality_score: 92 impl_tags: dependencies: [] techniques: @@ -25,116 +25,106 @@ impl_tags: - edge-highlighting review: strengths: - - Excellent use of plotnine grammar of graphics with idiomatic layer composition - (geom_tile + geom_text) - - Smart conditional text coloring via scale_color_identity ensures readability across - all cell backgrounds - - Clear data storytelling with recovery trend from negative (blue) to positive (gold) - across quarters - - Custom diverging palette (steel blue to off-white to gold) with well-chosen midpoint=0 - - Deliberate extreme values (HR -32.5%, Sales +38.2%) create visual focal points - - Realistic neutral business scenario with plausible growth rate values - - 'All spec requirements met: diverging colormap, cell annotations, colorbar, logical - ordering' + - Excellent diverging color palette (steel blue to cream to gold) with well-chosen + midpoint at 0, creating an intuitive visual encoding of positive/negative growth + - Conditional text color logic (white on dark, dark gray on mid, dark brown on gold) + ensures all annotations are readable against their cell background + - Data tells a compelling recovery story with intentional extreme values (HR -32.5 + crisis, Sales +38.2 surge) serving as visual focal points + - Clean, idiomatic plotnine code with vectorized data generation and meshgrid-based + long-form DataFrame construction + - 'Fully polished theme: removed grid lines, custom background, generous margins, + rotated tick labels' weaknesses: - - Title font size 22pt slightly under the 24pt guideline for optimal readability - at full resolution - - Mid-range color contrast could be stronger — values near zero on off-white background - are less visually distinct - - Code uses nested loops for matrix construction where vectorized numpy operations - could be more concise - - Categorical axis labels Quarter and Department lack units (though units are not - natural for categories) - image_description: 'The plot displays an 8x8 heatmap titled "Quarterly Growth by - Department · heatmap-basic · plotnine · pyplots.ai" with a subtitle "Year-over-year - growth rate (%) across departments, Q1 2023 – Q4 2024". The Y-axis lists eight - departments (Engineering, Marketing, Sales, Finance, Operations, HR, Research, - Support) and the X-axis shows eight quarters (Q1 ''23 through Q4 ''24, rotated - 45 degrees). Each cell is colored using a diverging scheme: steel blue for negative - values, off-white/cream for near-zero, and gold/amber for positive values. Every - cell contains a bold annotation showing the growth rate with a sign prefix (e.g., - "-32.5", "+38.2"). A vertical colorbar legend on the right labeled "Growth (%)" - shows the scale from approximately -20 to +40. The overall layout has a light - gray (#fafafa) background, white cell borders separating tiles, and no grid lines. - The data tells a clear recovery story: the left columns are predominantly blue - (negative growth) transitioning to gold (positive growth) on the right. Notable - extremes include HR at -32.5% in Q1 ''23 (deepest blue) and Sales at +38.2% in - Q4 ''24 (deepest gold). Text contrast is managed with white text on dark blue - cells, dark gray on mid-range cells, and dark brown/amber on bright gold cells.' + - The colorbar legend could benefit from more tick marks to better communicate the + full range of the scale + - Minor wasted horizontal space on the right side between the plot and the legend + area + image_description: 'The heatmap displays an 8x8 grid of quarterly growth rates (%) + across 8 departments (Engineering, Marketing, Sales, Finance, Operations, HR, + Research, Support) over 8 quarters (Q1 ''23 through Q4 ''24). A diverging color + scheme is used: dark steel blue for strongly negative values, cream/beige for + near-zero values, and gold/amber for strongly positive values. Each cell contains + a bold, signed numeric annotation (e.g., "+38.2", "-32.5"). Text color adapts + to background: white on dark blue cells, dark gray on mid-range cells, and dark + brown on gold cells. The title "Quarterly Growth by Department · heatmap-basic + · plotnine · pyplots.ai" is centered and bold at the top, with a subtitle describing + the data. X-axis labels are rotated 45 degrees showing quarter names, Y-axis shows + department names. A vertical colorbar legend labeled "Growth (%)" appears on the + right with a range from approximately -20 to 40. White borders separate cells + cleanly. The background is light gray (#f7f7f7). The plot clearly shows a recovery + narrative from left (negative) to right (positive).' criteria_checklist: visual_quality: - score: 26 + score: 28 max: 30 items: - id: VQ-01 name: Text Legibility - score: 7 + score: 8 max: 8 passed: true - comment: Font sizes explicitly set (title=22, subtitle=15, axis titles=18, - axis text=15, annotations size=10). Title slightly under 24pt guideline - but all text clearly readable. + comment: 'All font sizes explicitly set: title 24pt, axis labels 20pt, ticks + 16pt, annotations bold size=10' - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text anywhere. Rotated x-axis labels, well-spaced - cells. + comment: No overlapping text anywhere, rotated x-axis labels, well-spaced + annotations - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: Tiles perfectly sized for 8x8 grid, annotations clear and well-positioned. + comment: Tiles fill grid perfectly, annotations clearly visible in every cell - id: VQ-04 name: Color Accessibility score: 3 max: 4 passed: true - comment: Blue-to-gold diverging scheme avoids red-green issues. Mid-range - contrast could be slightly stronger. + comment: Diverging blue-cream-gold avoids red-green issues; not a standard + perceptually-uniform palette - id: VQ-05 - name: Layout & Canvas + name: Layout Balance score: 3 max: 4 passed: true - comment: Good canvas utilization. Minor wasted space at top-left and between - subtitle and heatmap body. + comment: Good canvas utilization, minor wasted space near legend on right - id: VQ-06 name: Axis Labels & Title - score: 1 + score: 2 max: 2 passed: true - comment: Descriptive labels but categorical axes lack units. Subtitle provides - percent context. + comment: Descriptive labels with units in annotations and legend design_excellence: - score: 14 + score: 16 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 6 + score: 7 max: 8 passed: true - comment: Custom diverging palette, intentional typography hierarchy, conditional - text coloring. Clearly above defaults. + comment: Custom diverging palette, conditional text colors, white cell borders, + light gray background — publication-quality - id: DE-02 name: Visual Refinement - score: 4 + score: 5 max: 6 passed: true - comment: Grid removed, minimal theme, white cell borders, light background, - explicit panel/plot background styling. + comment: Grid removed, custom backgrounds, generous whitespace, spines absent + — highly polished - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: Clear recovery narrative. Extreme values create focal points. Conditional - text coloring adds visual hierarchy. + comment: Recovery narrative with extreme focal points, conditional text color + guides attention spec_compliance: - score: 14 + score: 15 max: 15 items: - id: SC-01 @@ -142,26 +132,27 @@ review: score: 5 max: 5 passed: true - comment: Correct heatmap using geom_tile. + comment: Correct heatmap using geom_tile - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: 'All spec features present: diverging colormap, value annotations, - colorbar legend, logically ordered rows/columns.' + comment: 'All spec features present: diverging colormap, annotations, colorbar, + logical ordering' - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X=Quarter, Y=Department, value mapped to fill correctly. + comment: X=Quarter, Y=Department, fill=Growth (%) — correct - id: SC-04 name: Title & Legend - score: 2 + score: 3 max: 3 passed: true - comment: Title format correct with descriptive prefix. Colorbar legend appropriate. + comment: Title contains heatmap-basic · plotnine · pyplots.ai, legend labeled + Growth (%) data_quality: score: 14 max: 15 @@ -171,23 +162,22 @@ review: score: 5 max: 6 passed: true - comment: Shows positive/negative values, extreme outliers, gradual trends, - departmental variation. + comment: Shows positive/negative, near-zero, extremes, variation across both + dimensions - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Realistic business scenario with department growth rates. Neutral - and comprehensible. + comment: 'Realistic business scenario: quarterly departmental growth rates' - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Growth rates from -32.5% to +38.2% are realistic for business context. + comment: Growth rates -32.5% to +38.2% are plausible code_quality: - score: 9 + score: 10 max: 10 items: - id: CQ-01 @@ -195,31 +185,31 @@ review: score: 3 max: 3 passed: true - comment: Clean imports, data, plot, save structure. + comment: Clean imports → data → plot → save, no functions/classes - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set. + comment: np.random.seed(42) - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used. + comment: All imports used - id: CQ-04 name: Code Elegance - score: 1 + score: 2 max: 2 - passed: false - comment: Slightly verbose with nested loops for matrix and DataFrame construction. + passed: true + comment: Well-organized, vectorized data generation, appropriate complexity - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot.png, no deprecated functions. + comment: Saves as plot.png, no deprecated functions library_mastery: score: 9 max: 10 @@ -229,13 +219,13 @@ review: score: 5 max: 5 passed: true - comment: Excellent ggplot2-style grammar with aes mappings, geom layering, - scales, and theme customization. + comment: 'Idiomatic grammar of graphics: ggplot + aes + geom_tile + geom_text + + scales + theme' - id: LM-02 name: Distinctive Features score: 4 max: 5 passed: true - comment: Uses scale_fill_gradient2, scale_color_identity for conditional text, - pd.Categorical for ordered factors. + comment: scale_fill_gradient2 with midpoint, scale_color_identity for conditional + text, pd.Categorical ordering verdict: APPROVED