diff --git a/plots/waffle-basic/implementations/python/plotnine.py b/plots/waffle-basic/implementations/python/plotnine.py index 363c0e3697..665c9a92fb 100644 --- a/plots/waffle-basic/implementations/python/plotnine.py +++ b/plots/waffle-basic/implementations/python/plotnine.py @@ -1,4 +1,4 @@ -""" anyplot.ai +"""anyplot.ai waffle-basic: Basic Waffle Chart Library: plotnine 0.15.4 | Python 3.13.13 Quality: 79/100 | Created: 2026-05-05 @@ -14,7 +14,6 @@ from plotnine import ( aes, coord_equal, - element_blank, element_rect, element_text, geom_tile, @@ -24,7 +23,7 @@ labs, scale_fill_manual, theme, - theme_minimal, + theme_void, ) @@ -33,19 +32,24 @@ ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" INK = "#1A1A17" if THEME == "light" else "#F0EFE8" INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" +# Imprint palette — 8 hues, theme-independent, hybrid-v3 sort IMPRINT = ["#009E73", "#C475FD", "#4467A3", "#BD8233"] -# Data - Budget allocation by category +# Data — a $5,000 monthly household budget, allocated by category. +# Values sum to exactly 100 (one waffle square = 1% = $50). categories = ["Housing", "Food", "Transport", "Entertainment"] -values = [35, 25, 18, 12] -category_order = categories +values = [39, 28, 20, 13] +monthly_budget = 5000 +amounts = [round(v / 100 * monthly_budget) for v in values] +assert sum(values) == 100 -# Create waffle grid (10x10 = 100 squares) +# Waffle grid: 10x10 = 100 squares, filled row-major so each category +# forms a contiguous reading-order block. grid_size = 10 squares = [] square_id = 0 - for val, cat in zip(values, categories, strict=True): for _ in range(val): row = square_id // grid_size @@ -54,41 +58,42 @@ square_id += 1 df = pd.DataFrame(squares) -df["category"] = pd.Categorical(df["category"], categories=category_order, ordered=True) +df["category"] = pd.Categorical(df["category"], categories=categories, ordered=True) -# Create color mapping with Okabe-Ito palette -color_map = dict(zip(category_order, IMPRINT, strict=True)) +color_map = dict(zip(categories, IMPRINT, strict=True)) value_map = dict(zip(categories, values, strict=True)) +amount_map = dict(zip(categories, amounts, strict=True)) +legend_labels = {cat: f"{cat} — {value_map[cat]}% (${amount_map[cat]:,})" for cat in categories} -# Build legend labels with percentages -legend_labels = {cat: f"{cat} ({value_map[cat]}%)" for cat in category_order} - -# Theme configuration anyplot_theme = theme( - figure_size=(16, 9), + figure_size=(6, 6), plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG), - plot_title=element_text(size=24, color=INK, ha="center"), - legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT), - legend_title=element_text(size=18, color=INK), - legend_text=element_text(size=16, color=INK_SOFT), - legend_position="right", - axis_text=element_blank(), - axis_title=element_blank(), - axis_ticks=element_blank(), - panel_grid=element_blank(), + plot_title=element_text(size=20, weight="bold", color=INK, ha="center"), + plot_subtitle=element_text(size=12, color=INK_SOFT, ha="center", style="italic"), + plot_caption=element_text(size=9, color=INK_MUTED, ha="center"), + legend_position="bottom", + legend_direction="horizontal", + legend_background=element_rect(fill=PAGE_BG, color=PAGE_BG), + legend_key=element_rect(fill=PAGE_BG, color=PAGE_BG), + legend_title=element_text(size=14, weight="bold", color=INK), + legend_text=element_text(size=12, color=INK_SOFT), ) -# Plot plot = ( ggplot(df, aes(x="x", y="y", fill="category")) - + geom_tile(color=PAGE_BG, size=0.8) - + scale_fill_manual(values=color_map, labels=lambda x: [legend_labels[c] for c in x]) + + geom_tile(color=PAGE_BG, size=1.4) + + scale_fill_manual(values=color_map, labels=lambda cats: [legend_labels[c] for c in cats]) + coord_equal() - + labs(title="waffle-basic · plotnine · anyplot.ai", fill="Category") + + labs( + title="waffle-basic · plotnine · anyplot.ai", + subtitle=f"Monthly Household Budget Allocation — ${monthly_budget:,} Total", + caption="Each square represents 1% of the total monthly budget", + fill="Category", + ) + guides(fill=guide_legend(ncol=1)) - + theme_minimal() + + theme_void() + anyplot_theme ) -plot.save(f"plot-{THEME}.png", dpi=300, verbose=False) +plot.save(f"plot-{THEME}.png", dpi=400, width=6, height=6, units="in", verbose=False) diff --git a/plots/waffle-basic/metadata/python/plotnine.yaml b/plots/waffle-basic/metadata/python/plotnine.yaml index 5d2ea55b4b..46bf70b0be 100644 --- a/plots/waffle-basic/metadata/python/plotnine.yaml +++ b/plots/waffle-basic/metadata/python/plotnine.yaml @@ -1,221 +1,21 @@ +# Per-library metadata for plotnine implementation of waffle-basic +# Auto-generated by impl-generate.yml + library: plotnine language: python specification_id: waffle-basic created: 2025-12-16 07:44:55+00:00 -updated: '2026-05-05T18:25:01Z' -generated_by: claude-haiku -workflow_run: 25393441505 +updated: '2026-07-26T10:32:50Z' +generated_by: claude-sonnet +workflow_run: 30198308403 issue: 998 -python_version: 3.13.13 -library_version: 0.15.4 +language_version: 3.13.14 +library_version: 0.15.7 preview_url_light: https://storage.googleapis.com/anyplot-images/plots/waffle-basic/python/plotnine/plot-light.png preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/waffle-basic/python/plotnine/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: 79 +quality_score: null review: - strengths: - - Perfect theme adaptation with correct light/dark backgrounds and text colors - - Proper Okabe-Ito palette with brand green as first series - - All text legible and explicitly sized for large canvas - - Clean waffle grid implementation with clear proportional squares - - Correct title format and legend with percentages - - No theme-chrome failures in either render - weaknesses: - - Data values sum to 90 instead of 100 — creates ~10% proportional gap - - Generic design relying on library defaults with minimal visual refinement - - No visual hierarchy or storytelling — data displayed factually without emphasis - - Legend styling is minimal; could leverage plotnine theme features for sophistication - - Typography could be more intentional beyond minimum readable sizes - image_description: |- - Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct theme surface - Chrome: Title centered in dark text (#1A1A17), legend on right with dark labels (#4A4A44) — all clearly readable - Data: 10×9 waffle grid with Housing (green #009E73, 35 squares), Food (vermillion #D55E00, 25), Transport (blue #0072B2, 18), Entertainment (purple #CC79A7, 12); white grid dividers separate squares cleanly - Legibility verdict: PASS — all elements readable, no contrast failures - - Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct dark surface - Chrome: Title in light text (#F0EFE8), legend labels in secondary light (#B8B7B0) — all clearly readable; dark grid dividers visible against surface - Data: Identical colors to light render (#009E73, #D55E00, #0072B2, #CC79A7 unchanged); brand green remains vivid against dark background - Legibility verdict: PASS — no dark-on-dark failures, all text light-colored and readable - criteria_checklist: - visual_quality: - score: 29 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 7 - max: 8 - passed: true - comment: Explicit sizing (title 24pt, legend 16pt), all readable but typography - could be more refined - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: Zero overlap, all elements fully legible - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Squares properly sized and distinct - - id: VQ-04 - name: Color Accessibility - score: 2 - max: 2 - passed: true - comment: Okabe-Ito palette is CVD-safe with excellent contrast - - id: VQ-05 - name: Layout & Canvas - score: 4 - max: 4 - passed: true - comment: Plot fills 50-60% of canvas with balanced margins - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: Descriptive title in correct format - - id: VQ-07 - name: Palette Compliance - score: 2 - max: 2 - passed: true - comment: 'First series #009E73, colors follow Okabe-Ito order, backgrounds - correct in both themes' - design_excellence: - score: 8 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 4 - max: 8 - passed: false - comment: Well-configured defaults but no distinctive visual innovation - - id: DE-02 - name: Visual Refinement - score: 2 - max: 6 - passed: false - comment: Grid styling functional but minimal; legend styling default - - id: DE-03 - name: Data Storytelling - score: 2 - max: 6 - passed: false - comment: Displays data without visual hierarchy or emphasis - spec_compliance: - score: 14 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct 10×9 waffle chart - - id: SC-02 - name: Required Features - score: 3 - max: 4 - passed: false - comment: Grid and legend present; values sum to 90 instead of 100 - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: Categories correctly mapped to grid - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Correct format with percentages - data_quality: - score: 13 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 5 - max: 6 - passed: true - comment: Shows four distinct categories - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Budget allocation is realistic and neutral - - id: DQ-03 - name: Appropriate Scale - score: 3 - max: 4 - passed: false - comment: Values reasonable but sum to 90% not 100% - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: Linear structure with clear flow - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: Deterministic hardcoded data - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: Only necessary plotnine imports - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Clean and Pythonic - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Correct plot-{THEME}.png format - library_mastery: - score: 5 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: Correct ggplot + geom_tile pattern - - id: LM-02 - name: Distinctive Features - score: 1 - max: 5 - passed: false - comment: Generic grammar-of-graphics usage; doesn't leverage distinctive plotnine - features - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: [] - patterns: - - data-generation - dataprep: [] - styling: [] + strengths: [] + weaknesses: []