From 1d5c06eed3405e6b50f70325debac31a6b01a83d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 5 May 2026 03:33:23 +0000 Subject: [PATCH 1/4] chore(pygal): add metadata for streamgraph-basic --- .../implementations/python/pygal.py | 108 +++++++++--------- .../metadata/python/pygal.yaml | 48 +++----- 2 files changed, 67 insertions(+), 89 deletions(-) diff --git a/plots/streamgraph-basic/implementations/python/pygal.py b/plots/streamgraph-basic/implementations/python/pygal.py index 5eb401088a..1e6472ed6a 100644 --- a/plots/streamgraph-basic/implementations/python/pygal.py +++ b/plots/streamgraph-basic/implementations/python/pygal.py @@ -1,14 +1,31 @@ -""" pyplots.ai +"""anyplot.ai streamgraph-basic: Basic Stream Graph -Library: pygal 3.1.0 | Python 3.13.11 -Quality: 75/100 | Created: 2025-12-23 +Library: pygal | Python 3.13 +Quality: pending | Updated: 2026-05-05 """ +import os +import sys + + +# Remove script directory from sys.path so 'import pygal' finds the installed package +_script_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path = [p for p in sys.path if os.path.abspath(p) != _script_dir] + import numpy as np import pygal from pygal.style import Style +# Theme tokens +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" + +OKABE_ITO = ("#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00") + # Data: monthly streaming hours by music genre over two years np.random.seed(42) @@ -40,63 +57,49 @@ "Dec 24", ] genres = ["Pop", "Rock", "Hip-Hop", "Electronic", "Jazz"] - -# Generate smooth, realistic streaming data with trends base_values = {"Pop": 45, "Rock": 35, "Hip-Hop": 40, "Electronic": 30, "Jazz": 15} data = {} for genre in genres: base = base_values[genre] - # Add trend over time trend = np.linspace(0, np.random.uniform(-10, 15), months) - # Seasonal variation seasonal = 8 * np.sin(np.linspace(0, 4 * np.pi, months) + np.random.uniform(0, 2 * np.pi)) - # Random noise noise = np.random.randn(months) * 3 values = base + trend + seasonal + noise - values = np.maximum(values, 5) # Ensure positive values + values = np.maximum(values, 5) data[genre] = values.tolist() -# Convert data to array for streamgraph calculation +# Centered baseline for streamgraph effect data_array = np.array([data[genre] for genre in genres]) - -# Calculate centered baseline for true streamgraph effect -# Symmetric baseline: streams expand outward from center (x-axis at y=0) total_at_each_time = data_array.sum(axis=0) baseline_offset = total_at_each_time / 2 -# Custom style with colorblind-safe palette -# Colors ordered for maximum contrast between adjacent layers +y_min = -baseline_offset.max() * 1.1 +y_max = baseline_offset.max() * 1.1 + +# Style custom_style = Style( - background="white", - plot_background="white", - foreground="#2c3e50", - foreground_strong="#2c3e50", - foreground_subtle="#7f8c8d", - # High contrast palette: dark blue, orange, teal, crimson, gold - colors=("#1a5276", "#e67e22", "#138d75", "#c0392b", "#d4ac0d"), - title_font_size=80, - label_font_size=48, - major_label_font_size=40, - legend_font_size=48, - value_font_size=36, - opacity=0.90, + background=PAGE_BG, + plot_background=PAGE_BG, + foreground=INK, + foreground_strong=INK, + foreground_subtle=INK_MUTED, + colors=OKABE_ITO, + title_font_size=28, + label_font_size=22, + major_label_font_size=18, + legend_font_size=16, + value_font_size=14, + stroke_width=3, + opacity=0.88, opacity_hover=0.95, - guide_stroke_color="#e0e0e0", - major_guide_stroke_color="#cccccc", ) -# Calculate y-axis range based on actual data -# After centering, min is -baseline_offset, max is baseline_offset (total stack height) -y_min = -baseline_offset.max() * 1.1 # Add 10% padding -y_max = baseline_offset.max() * 1.1 - -# Create StackedLine chart - pygal's native stacked area chart -# We'll shift all data to center around zero by subtracting half the total from each layer +# Chart chart = pygal.StackedLine( width=4800, height=2700, - title="streamgraph-basic · pygal · pyplots.ai", + title="streamgraph-basic · pygal · anyplot.ai", x_title="Month", y_title="Streaming Hours (centered)", style=custom_style, @@ -105,42 +108,33 @@ show_y_guides=True, show_x_guides=False, legend_at_bottom=True, - legend_box_size=36, + legend_box_size=30, margin=100, spacing=40, truncate_legend=-1, - truncate_label=-1, # Prevent x-axis label truncation - interpolate="cubic", # Smooth flowing curves + truncate_label=-1, + interpolate="cubic", show_minor_x_labels=False, - x_label_rotation=45, # Rotate labels to prevent overlap - range=(y_min, y_max), # Dynamic y-axis range based on data + x_label_rotation=45, + range=(y_min, y_max), ) -# Set x-axis labels showing months chart.x_labels = month_labels chart.x_labels_major = ["Jan 23", "Jul 23", "Jan 24", "Jul 24"] -# To create a centered streamgraph with StackedLine: -# We need to shift each layer's values so the visual center is at y=0 -# First layer starts at -baseline_offset, subsequent layers stack on top - -# Calculate shifted values for each layer -# The first (bottom) layer is shifted down by baseline_offset -# This makes the visual center of the total stack sit at y=0 +# Shift first layer to center the streamgraph around y=0 shifted_data = [] for i, genre in enumerate(genres): if i == 0: - # First layer: shift down by baseline to center the stream shifted_values = (np.array(data[genre]) - baseline_offset).tolist() else: - # Subsequent layers: use original values (they stack on top) shifted_values = data[genre] shifted_data.append((genre, shifted_values)) -# Add all layers for genre, values in shifted_data: chart.add(genre, values) -# Save as PNG and HTML -chart.render_to_png("plot.png") -chart.render_to_file("plot.html") +# Save +chart.render_to_png(f"plot-{THEME}.png") +with open(f"plot-{THEME}.html", "wb") as f: + f.write(chart.render()) diff --git a/plots/streamgraph-basic/metadata/python/pygal.yaml b/plots/streamgraph-basic/metadata/python/pygal.yaml index 8d13abdb51..0bc704ae3f 100644 --- a/plots/streamgraph-basic/metadata/python/pygal.yaml +++ b/plots/streamgraph-basic/metadata/python/pygal.yaml @@ -1,37 +1,21 @@ +# Per-library metadata for pygal implementation of streamgraph-basic +# Auto-generated by impl-generate.yml + library: pygal +language: python specification_id: streamgraph-basic created: '2025-12-23T21:57:05Z' -updated: '2025-12-23T22:25:41Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20472385283 -issue: 0 -python_version: 3.13.11 +updated: '2026-05-05T03:33:23Z' +generated_by: claude-sonnet +workflow_run: 25356184730 +issue: 856 +python_version: 3.13.13 library_version: 3.1.0 -preview_url: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/pygal/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/pygal/plot.html -quality_score: 75 -impl_tags: - dependencies: [] - techniques: - - html-export - patterns: - - data-generation - - matrix-construction - dataprep: [] - styling: - - alpha-blending +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-dark.html +quality_score: null review: - strengths: - - Successfully implements a centered streamgraph using pygal StackedLine chart with - mathematical baseline shifting - - Excellent colorblind-safe palette with high contrast between adjacent layers (dark - blue, orange, teal, crimson, gold) - - Smooth flowing curves achieved through cubic interpolation - - Realistic data scenario with seasonal patterns and genre trends - - Clean code structure following KISS principles with proper random seed - weaknesses: - - X-axis labels are truncated showing Jan... instead of full Jan 23 labels despite - truncate_label=-1 setting - - Y-axis label includes (centered) which is a technical detail not a meaningful - unit - - Grid lines are not visible in the output despite configuration + strengths: [] + weaknesses: [] From a5ee2fcca3792203aa88660e8042eb8ffc130e83 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 5 May 2026 03:41:39 +0000 Subject: [PATCH 2/4] chore(pygal): update quality score 79 and review feedback for streamgraph-basic --- .../implementations/python/pygal.py | 6 +- .../metadata/python/pygal.yaml | 241 +++++++++++++++++- 2 files changed, 237 insertions(+), 10 deletions(-) diff --git a/plots/streamgraph-basic/implementations/python/pygal.py b/plots/streamgraph-basic/implementations/python/pygal.py index 1e6472ed6a..8f2cb1b6c1 100644 --- a/plots/streamgraph-basic/implementations/python/pygal.py +++ b/plots/streamgraph-basic/implementations/python/pygal.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai streamgraph-basic: Basic Stream Graph -Library: pygal | Python 3.13 -Quality: pending | Updated: 2026-05-05 +Library: pygal 3.1.0 | Python 3.13.13 +Quality: 79/100 | Updated: 2026-05-05 """ import os diff --git a/plots/streamgraph-basic/metadata/python/pygal.yaml b/plots/streamgraph-basic/metadata/python/pygal.yaml index 0bc704ae3f..9bd69b341c 100644 --- a/plots/streamgraph-basic/metadata/python/pygal.yaml +++ b/plots/streamgraph-basic/metadata/python/pygal.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for pygal implementation of streamgraph-basic -# Auto-generated by impl-generate.yml - library: pygal language: python specification_id: streamgraph-basic created: '2025-12-23T21:57:05Z' -updated: '2026-05-05T03:33:23Z' +updated: '2026-05-05T03:41:39Z' generated_by: claude-sonnet workflow_run: 25356184730 issue: 856 @@ -15,7 +12,237 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/streamgra preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-dark.html -quality_score: null +quality_score: 79 review: - strengths: [] - weaknesses: [] + strengths: + - Correct title format (streamgraph-basic · pygal · anyplot.ai) + - 'Okabe-Ito palette correctly applied with #009E73 as first series (Pop)' + - Theme-adaptive style tokens properly derived from ANYPLOT_THEME for both light + and dark renders + - Cubic interpolation via interpolate="cubic" gives smooth flowing curves + - Smart x-axis label management (x_labels_major + show_minor_x_labels=False) reduces + clutter + - Data seed set (np.random.seed(42)) for reproducibility + - 'Correct dual output: plot-{THEME}.png and plot-{THEME}.html' + weaknesses: + - Large empty space below data in lower half of chart — centered baseline only shifts + first series (Pop), resulting in data occupying y=-45 to +85 while y-axis extends + to -100, making the lower ~25% of plot area empty and unbalanced + - Streamgraph centering is imperfect — a true streamgraph should distribute the + stacked area symmetrically around y=0, but the current approach produces asymmetric + layout + - Design is a well-configured library default — no aesthetic sophistication beyond + palette and theme tokens; no visual refinement beyond subtle y-grid and no dots + - No data storytelling — chart displays genre trends but provides no visual hierarchy + or emphasis to guide the viewer toward an insight + - 'CQ-04 minor: the baseline-centering approach (shifting only the first series + and passing the rest as raw positive values) is a suboptimal workaround that does + not produce the desired symmetric result' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct, clearly warm not pure white. + Chrome: Title "streamgraph-basic · pygal · anyplot.ai" is dark text at top, readable. Y-axis label "Streaming Hours (centered)" rotated vertically, readable. X-axis label "Month" readable. Tick labels visible in dark ink. Four x-axis major labels (Jan 23, Jul 23, Jan 24, Jul 24) rotated 45°, readable without overlap. + Data: Five stacked filled areas with smooth cubic curves. Pop (#009E73 green) forms the baseline shifted below zero. Rock (#D55E00 orange-brown) visible below zero spanning a thin band. Hip-Hop (#0072B2 blue) is the dominant area spanning zero and above. Electronic (#CC79A7 pink-purple) above Hip-Hop. Jazz (#E69F00 yellow-gold) at the top. Subtle horizontal y-grid lines (dotted) visible. + Layout issue: The data region spans roughly y=-45 to y=+85 while the y-axis extends to ±100. The lower quarter of the plot area (y=-100 to ~-45) is entirely empty, creating a significant unbalanced empty zone at the bottom of the chart area. + Legibility verdict: PASS — all text is readable against the light background, no light-on-light failures. + + Dark render (plot-dark.png): + Background: Very dark near-black (#1A1A17) — code-confirmed, not pure black. + Chrome: Title, axis labels, tick labels, and legend text all appear in light-colored ink against the dark background. All text is clearly readable. No dark-on-dark failures detected. + Data: Colors are identical to the light render — Pop (#009E73), Rock (#D55E00), Hip-Hop (#0072B2), Electronic (#CC79A7), Jazz (#E69F00). Opacity 0.88 slightly mutes the fills but all areas remain distinguishable. + Same layout issue as light render: large empty space in the lower portion of the plot area. + Legibility verdict: PASS — all text readable against the dark background; no dark-on-dark failures. + criteria_checklist: + visual_quality: + score: 28 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 8 + max: 8 + passed: true + comment: 'All font sizes explicitly set: title=28px, labels=22px, major_label=18px, + legend=16px. Readable in both themes.' + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: Only 4 major x-axis labels, no overlap; y-ticks clear; legend at + bottom with adequate spacing. + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: All five stacked areas clearly visible with distinct Okabe-Ito colors; + opacity=0.88 preserves distinction. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Okabe-Ito palette is CVD-safe; adjacent areas have sufficient contrast. + - id: VQ-05 + name: Layout & Canvas + score: 2 + max: 4 + passed: false + comment: Data spans y=-45 to +85 but y-axis extends to ±100; lower ~25% of + plot area (y=-100 to -45) is entirely empty, creating an unbalanced layout. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: 'Y-axis: ''Streaming Hours (centered)'' — descriptive. X-axis: ''Month'' + — descriptive. Title correct.' + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'First series (Pop) is #009E73; Okabe-Ito order followed; background + #FAF8F1 (light) / #1A1A17 (dark); foreground tokens theme-adaptive.' + design_excellence: + score: 9 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 4 + max: 8 + passed: false + comment: Well-configured library default with Okabe-Ito palette and theme + tokens. No exceptional design choices. + - id: DE-02 + name: Visual Refinement + score: 3 + max: 6 + passed: false + comment: 'Some visible refinement: y-guides only (no x-guides), no dots, legend + at bottom, generous margin. Above default but not ''good'' level.' + - id: DE-03 + name: Data Storytelling + score: 2 + max: 6 + passed: false + comment: Music streaming data is displayed but no visual emphasis, hierarchy, + or focal insight is communicated. + spec_compliance: + score: 12 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 3 + max: 5 + passed: false + comment: Uses StackedLine + fill + cubic interpolation — correct base type + but centered baseline is imperfect. Data asymmetrically distributed, not + a symmetric river-like streamgraph. + - id: SC-02 + name: Required Features + score: 3 + max: 4 + passed: false + comment: Smooth interpolation ✓, distinct colors ✓, legend ✓. Centered baseline + attempted but not achieved symmetrically — large empty space below data + breaks the river appearance. + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: Time on x-axis, streaming hours on y-axis, categories as stacked + areas. Correct. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title 'streamgraph-basic · pygal · anyplot.ai' correct. Legend shows + all 5 genres. + data_quality: + score: 14 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 5 + max: 6 + passed: true + comment: 5 genres with trend + seasonal + noise. Shows varying shapes and + proportions. Good coverage. + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Monthly streaming hours by music genre (Pop, Rock, Hip-Hop, Electronic, + Jazz) over 2023-2024. Realistic and neutral. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Base values 15-45 hours/month per genre, plausible relative proportions. + code_quality: + score: 9 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Linear: imports → tokens → data → style → chart → save. No functions + or classes.' + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42) set. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: os, sys, numpy, pygal, pygal.style.Style — all used. + - id: CQ-04 + name: Code Elegance + score: 1 + max: 2 + passed: false + comment: The baseline-centering workaround (shifting only the first series + to negative while leaving others as raw positive values) is a suboptimal + approach that doesn't produce a true streamgraph and creates the layout + issue. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png and plot-{THEME}.html. Correct for pygal. + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: Uses StackedLine appropriately, Style object for theming, chart.add() + API, x_labels/x_labels_major. Good idiomatic usage. + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses interpolate='cubic' (pygal-native), x_labels_major + show_minor_x_labels=False + (pygal-specific label system), opacity_hover (pygal interactivity token), + HTML output. + verdict: REJECTED From bd2d90bcb847ec296c75228125eb08f6b423737d Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 21:51:02 +0000 Subject: [PATCH 3/4] fix(pygal): fix streamgraph centering with proper symmetric baseline --- .../implementations/python/pygal.py | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/plots/streamgraph-basic/implementations/python/pygal.py b/plots/streamgraph-basic/implementations/python/pygal.py index 8f2cb1b6c1..71690ce43a 100644 --- a/plots/streamgraph-basic/implementations/python/pygal.py +++ b/plots/streamgraph-basic/implementations/python/pygal.py @@ -1,7 +1,7 @@ -""" anyplot.ai +"""anyplot.ai streamgraph-basic: Basic Stream Graph Library: pygal 3.1.0 | Python 3.13.13 -Quality: 79/100 | Updated: 2026-05-05 +Quality: 79/100 | Updated: 2026-05-06 """ import os @@ -26,6 +26,9 @@ OKABE_ITO = ("#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00") +# Prepend background color for the invisible baseline series, then Okabe-Ito for genres +COLORS = (PAGE_BG,) + OKABE_ITO + # Data: monthly streaming hours by music genre over two years np.random.seed(42) @@ -69,13 +72,15 @@ values = np.maximum(values, 5) data[genre] = values.tolist() -# Centered baseline for streamgraph effect +# True streamgraph baseline: center the entire stack symmetrically around y=0. +# baseline[t] = -total[t]/2 so the stack spans from -total/2 to +total/2. data_array = np.array([data[genre] for genre in genres]) total_at_each_time = data_array.sum(axis=0) -baseline_offset = total_at_each_time / 2 +baseline = (-total_at_each_time / 2).tolist() -y_min = -baseline_offset.max() * 1.1 -y_max = baseline_offset.max() * 1.1 +# Symmetric y-axis range with a small margin +half_total_max = total_at_each_time.max() / 2 +y_range = half_total_max * 1.12 # Style custom_style = Style( @@ -84,7 +89,7 @@ foreground=INK, foreground_strong=INK, foreground_subtle=INK_MUTED, - colors=OKABE_ITO, + colors=COLORS, title_font_size=28, label_font_size=22, major_label_font_size=18, @@ -101,7 +106,7 @@ height=2700, title="streamgraph-basic · pygal · anyplot.ai", x_title="Month", - y_title="Streaming Hours (centered)", + y_title="Streaming Hours", style=custom_style, fill=True, show_dots=False, @@ -116,23 +121,19 @@ interpolate="cubic", show_minor_x_labels=False, x_label_rotation=45, - range=(y_min, y_max), + range=(-y_range, y_range), ) chart.x_labels = month_labels chart.x_labels_major = ["Jan 23", "Jul 23", "Jan 24", "Jul 24"] -# Shift first layer to center the streamgraph around y=0 -shifted_data = [] -for i, genre in enumerate(genres): - if i == 0: - shifted_values = (np.array(data[genre]) - baseline_offset).tolist() - else: - shifted_values = data[genre] - shifted_data.append((genre, shifted_values)) - -for genre, values in shifted_data: - chart.add(genre, values) +# Invisible baseline series shifts the stack so genres span -total/2 to +total/2. +# Color matches background (PAGE_BG) so it renders as transparent. +chart.add("", baseline) + +# Genre series added with actual positive values — pygal stacks them on top of baseline +for genre in genres: + chart.add(genre, data[genre]) # Save chart.render_to_png(f"plot-{THEME}.png") From 5560db2c125f24ab35e7a0bd503e86747672b18b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 6 May 2026 21:56:37 +0000 Subject: [PATCH 4/4] chore(pygal): update quality score 82 and review feedback for streamgraph-basic --- .../implementations/python/pygal.py | 4 +- .../metadata/python/pygal.yaml | 193 +++++++++--------- 2 files changed, 99 insertions(+), 98 deletions(-) diff --git a/plots/streamgraph-basic/implementations/python/pygal.py b/plots/streamgraph-basic/implementations/python/pygal.py index 71690ce43a..a6d0ed33cb 100644 --- a/plots/streamgraph-basic/implementations/python/pygal.py +++ b/plots/streamgraph-basic/implementations/python/pygal.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai streamgraph-basic: Basic Stream Graph Library: pygal 3.1.0 | Python 3.13.13 -Quality: 79/100 | Updated: 2026-05-06 +Quality: 82/100 | Updated: 2026-05-06 """ import os diff --git a/plots/streamgraph-basic/metadata/python/pygal.yaml b/plots/streamgraph-basic/metadata/python/pygal.yaml index 9bd69b341c..aad8421a45 100644 --- a/plots/streamgraph-basic/metadata/python/pygal.yaml +++ b/plots/streamgraph-basic/metadata/python/pygal.yaml @@ -2,7 +2,7 @@ library: pygal language: python specification_id: streamgraph-basic created: '2025-12-23T21:57:05Z' -updated: '2026-05-05T03:41:39Z' +updated: '2026-05-06T21:56:36Z' generated_by: claude-sonnet workflow_run: 25356184730 issue: 856 @@ -12,46 +12,36 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/streamgra preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/pygal/plot-dark.html -quality_score: 79 +quality_score: 82 review: strengths: - - Correct title format (streamgraph-basic · pygal · anyplot.ai) - - 'Okabe-Ito palette correctly applied with #009E73 as first series (Pop)' - - Theme-adaptive style tokens properly derived from ANYPLOT_THEME for both light - and dark renders - - Cubic interpolation via interpolate="cubic" gives smooth flowing curves - - Smart x-axis label management (x_labels_major + show_minor_x_labels=False) reduces - clutter - - Data seed set (np.random.seed(42)) for reproducibility - - 'Correct dual output: plot-{THEME}.png and plot-{THEME}.html' + - 'Perfect spec compliance: symmetric streamgraph baseline correctly computed via + invisible series trick' + - Canonical Okabe-Ito palette in correct order; full theme-adaptive chrome in both + light and dark renders + - Cubic interpolation delivers authentic smooth flowing curves as specified + - Clean flat code structure with seed for reproducibility; saves both PNG and HTML + as required + - No dark-on-dark failures; both renders fully legible weaknesses: - - Large empty space below data in lower half of chart — centered baseline only shifts - first series (Pop), resulting in data occupying y=-45 to +85 while y-axis extends - to -100, making the lower ~25% of plot area empty and unbalanced - - Streamgraph centering is imperfect — a true streamgraph should distribute the - stacked area symmetrically around y=0, but the current approach produces asymmetric - layout - - Design is a well-configured library default — no aesthetic sophistication beyond - palette and theme tokens; no visual refinement beyond subtle y-grid and no dots - - No data storytelling — chart displays genre trends but provides no visual hierarchy - or emphasis to guide the viewer toward an insight - - 'CQ-04 minor: the baseline-centering approach (shifting only the first series - and passing the rest as raw positive values) is a suboptimal workaround that does - not produce the desired symmetric result' + - 'Design Excellence is modest (9/20): technically correct but visually generic + — no visual hierarchy, focal points, or emphasis guiding the viewer to an insight' + - 'No data storytelling: all 5 genres given equal visual weight; viewer cannot easily + discern which genre is trending up or down' + - Layout leaves minor wasted space in corners; refined padding/margin pass could + improve canvas utilization image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct, clearly warm not pure white. - Chrome: Title "streamgraph-basic · pygal · anyplot.ai" is dark text at top, readable. Y-axis label "Streaming Hours (centered)" rotated vertically, readable. X-axis label "Month" readable. Tick labels visible in dark ink. Four x-axis major labels (Jan 23, Jul 23, Jan 24, Jul 24) rotated 45°, readable without overlap. - Data: Five stacked filled areas with smooth cubic curves. Pop (#009E73 green) forms the baseline shifted below zero. Rock (#D55E00 orange-brown) visible below zero spanning a thin band. Hip-Hop (#0072B2 blue) is the dominant area spanning zero and above. Electronic (#CC79A7 pink-purple) above Hip-Hop. Jazz (#E69F00 yellow-gold) at the top. Subtle horizontal y-grid lines (dotted) visible. - Layout issue: The data region spans roughly y=-45 to y=+85 while the y-axis extends to ±100. The lower quarter of the plot area (y=-100 to ~-45) is entirely empty, creating a significant unbalanced empty zone at the bottom of the chart area. - Legibility verdict: PASS — all text is readable against the light background, no light-on-light failures. + Background: Warm off-white (#FAF8F1) — correct, not pure white + Chrome: Title "streamgraph-basic · pygal · anyplot.ai" in dark text — readable; Y-axis label "Streaming Hours" and X-axis label "Month" clearly visible; major x-axis tick labels (Jan 23, Jul 23, Jan 24, Jul 24) rotated 45° — readable; y-axis numeric ticks visible; legend at bottom with all 5 genre labels + Data: Five stream bands in Okabe-Ito order from bottom: green (#009E73, Pop), orange-red (#D55E00, Rock), blue (#0072B2, Hip-Hop), pink (#CC79A7, Electronic), yellow (#E69F00, Jazz); smooth cubic curves; symmetric centering around y=0 + Legibility verdict: PASS Dark render (plot-dark.png): - Background: Very dark near-black (#1A1A17) — code-confirmed, not pure black. - Chrome: Title, axis labels, tick labels, and legend text all appear in light-colored ink against the dark background. All text is clearly readable. No dark-on-dark failures detected. - Data: Colors are identical to the light render — Pop (#009E73), Rock (#D55E00), Hip-Hop (#0072B2), Electronic (#CC79A7), Jazz (#E69F00). Opacity 0.88 slightly mutes the fills but all areas remain distinguishable. - Same layout issue as light render: large empty space in the lower portion of the plot area. - Legibility verdict: PASS — all text readable against the dark background; no dark-on-dark failures. + Background: Near-black (#1A1A17) — correct, not pure black + Chrome: Title, axis labels, tick labels, and legend text all appear in light off-white tones — fully readable; invisible baseline series (#1A1A17) merges with background — no visible artifact; no dark-on-dark failures detected + Data: Colors identical to light render — all five Okabe-Ito positions preserved; brand green #009E73 clearly visible on dark surface + Legibility verdict: PASS criteria_checklist: visual_quality: score: 28 @@ -59,52 +49,52 @@ review: items: - id: VQ-01 name: Text Legibility - score: 8 + score: 7 max: 8 passed: true - comment: 'All font sizes explicitly set: title=28px, labels=22px, major_label=18px, - legend=16px. Readable in both themes.' + comment: All font sizes explicitly set (title=28, label=22, major_label=18, + legend=16); readable in both renders - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: Only 4 major x-axis labels, no overlap; y-ticks clear; legend at - bottom with adequate spacing. + comment: Major-only x-axis labels with 45deg rotation prevent crowding; legend + at bottom has adequate spacing - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: All five stacked areas clearly visible with distinct Okabe-Ito colors; - opacity=0.88 preserves distinction. + comment: Stream bands clearly distinct with strong fill colors and 0.88 opacity - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Okabe-Ito palette is CVD-safe; adjacent areas have sufficient contrast. + comment: Okabe-Ito palette is CVD-safe; all 5 bands distinguishable by hue + and brightness - id: VQ-05 name: Layout & Canvas - score: 2 + score: 3 max: 4 - passed: false - comment: Data spans y=-45 to +85 but y-axis extends to ±100; lower ~25% of - plot area (y=-100 to -45) is entirely empty, creating an unbalanced layout. + passed: true + comment: Chart fills ~65% of 4800x2700 canvas with balanced margins; minor + wasted space in upper right - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: 'Y-axis: ''Streaming Hours (centered)'' — descriptive. X-axis: ''Month'' - — descriptive. Title correct.' + comment: Streaming Hours and Month are descriptive labels - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'First series (Pop) is #009E73; Okabe-Ito order followed; background - #FAF8F1 (light) / #1A1A17 (dark); foreground tokens theme-adaptive.' + comment: 'First real series (Pop) = #009E73; all 5 genres follow canonical + Okabe-Ito order; backgrounds are #FAF8F1 / #1A1A17; chrome is theme-correct + in both renders' design_excellence: score: 9 max: 20 @@ -114,58 +104,58 @@ review: score: 4 max: 8 passed: false - comment: Well-configured library default with Okabe-Ito palette and theme - tokens. No exceptional design choices. + comment: Well-configured style with Okabe-Ito palette and correct chrome tokens; + clean and professional but no outstanding visual design choices above a + library default - id: DE-02 name: Visual Refinement score: 3 max: 6 passed: false - comment: 'Some visible refinement: y-guides only (no x-guides), no dots, legend - at bottom, generous margin. Above default but not ''good'' level.' + comment: y-guides only (no x-guides), explicit font hierarchy, opacity softening; + adequate refinement but no spine treatment or advanced polish - id: DE-03 name: Data Storytelling score: 2 max: 6 passed: false - comment: Music streaming data is displayed but no visual emphasis, hierarchy, - or focal insight is communicated. + comment: Five streaming genres over two years with seasonal variation; data + is displayed but no visual hierarchy, emphasis, or focal point guides the + viewer spec_compliance: - score: 12 + score: 15 max: 15 items: - id: SC-01 name: Plot Type - score: 3 + score: 5 max: 5 - passed: false - comment: Uses StackedLine + fill + cubic interpolation — correct base type - but centered baseline is imperfect. Data asymmetrically distributed, not - a symmetric river-like streamgraph. + passed: true + comment: StackedLine with fill + invisible symmetric baseline correctly implements + streamgraph centered around y=0 - id: SC-02 name: Required Features - score: 3 + score: 4 max: 4 - passed: false - comment: Smooth interpolation ✓, distinct colors ✓, legend ✓. Centered baseline - attempted but not achieved symmetrically — large empty space below data - breaks the river appearance. + passed: true + comment: Cubic interpolation for smooth curves, symmetric baseline centering, + distinct Okabe-Ito colors per category, legend present - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Time on x-axis, streaming hours on y-axis, categories as stacked - areas. Correct. + comment: Time (months) on x-axis, streaming magnitude on y-axis, all 5 categories + visible - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title 'streamgraph-basic · pygal · anyplot.ai' correct. Legend shows - all 5 genres. + comment: Title is exactly streamgraph-basic · pygal · anyplot.ai; legend labels + match the 5 genre series data_quality: - score: 14 + score: 13 max: 15 items: - id: DQ-01 @@ -173,23 +163,25 @@ review: score: 5 max: 6 passed: true - comment: 5 genres with trend + seasonal + noise. Shows varying shapes and - proportions. Good coverage. + comment: Shows 5 genres with distinct trends, seasonal oscillations, and varying + magnitudes; demonstrates relative flow clearly - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Monthly streaming hours by music genre (Pop, Rock, Hip-Hop, Electronic, - Jazz) over 2023-2024. Realistic and neutral. + comment: 'Monthly music genre streaming over two years: neutral, comprehensible, + real-world scenario' - id: DQ-03 name: Appropriate Scale - score: 4 + score: 3 max: 4 passed: true - comment: Base values 15-45 hours/month per genre, plausible relative proportions. + comment: Base values (Pop 45, Hip-Hop 40, Rock 35, Electronic 30, Jazz 15) + are plausible relative proportions; y-axis shows negative values as expected + streamgraph artifact from symmetric centering code_quality: - score: 9 + score: 10 max: 10 items: - id: CQ-01 @@ -197,35 +189,34 @@ review: score: 3 max: 3 passed: true - comment: 'Linear: imports → tokens → data → style → chart → save. No functions - or classes.' + comment: 'Flat linear structure: imports -> theme tokens -> data generation + -> style -> chart -> save' - 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: os, sys, numpy, pygal, pygal.style.Style — all used. + comment: numpy, pygal, pygal.style, os, sys — all used; sys needed for path + workaround - id: CQ-04 name: Code Elegance - score: 1 + score: 2 max: 2 - passed: false - comment: The baseline-centering workaround (shifting only the first series - to negative while leaving others as raw positive values) is a suboptimal - approach that doesn't produce a true streamgraph and creates the layout - issue. + passed: true + comment: Clean, Pythonic; invisible baseline trick for stream centering is + a clever workaround - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html. Correct for pygal. + comment: Saves plot-{THEME}.png and plot-{THEME}.html; current API library_mastery: score: 7 max: 10 @@ -235,14 +226,24 @@ review: score: 4 max: 5 passed: true - comment: Uses StackedLine appropriately, Style object for theming, chart.add() - API, x_labels/x_labels_major. Good idiomatic usage. + comment: Uses StackedLine with fill, Style object for full theming, cubic + interpolation, legend_at_bottom, major vs minor label distinction - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: Uses interpolate='cubic' (pygal-native), x_labels_major + show_minor_x_labels=False - (pygal-specific label system), opacity_hover (pygal interactivity token), - HTML output. - verdict: REJECTED + comment: Leverages pygal's cubic interpolation for smooth stream curves and + interactive HTML export; invisible baseline exploits pygal's stacking model + to achieve streamgraph centering + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - html-export + patterns: + - data-generation + - iteration-over-groups + dataprep: [] + styling: + - alpha-blending