From b1b167ca970e428f7110fd7df16473a1b7d3fc96 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 01:53:43 +0000 Subject: [PATCH 1/3] chore(plotly): add metadata for bar-race-animated --- .../implementations/python/plotly.py | 302 +++++++++++------- .../metadata/python/plotly.yaml | 221 +------------ 2 files changed, 204 insertions(+), 319 deletions(-) diff --git a/plots/bar-race-animated/implementations/python/plotly.py b/plots/bar-race-animated/implementations/python/plotly.py index a57b12a84b..066c69148b 100644 --- a/plots/bar-race-animated/implementations/python/plotly.py +++ b/plots/bar-race-animated/implementations/python/plotly.py @@ -1,129 +1,203 @@ -""" pyplots.ai +"""anyplot.ai bar-race-animated: Animated Bar Chart Race -Library: plotly 6.5.1 | Python 3.13.11 -Quality: 92/100 | Created: 2026-01-11 +Library: plotly | Python 3.13 +Quality: pending | Created: 2026-05-19 """ +import os + import numpy as np import pandas as pd -import plotly.express as px +import plotly.graph_objects as go + + +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +GRID = "rgba(26,26,23,0.25)" if THEME == "light" else "rgba(240,239,232,0.25)" +OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9", "#F0E442"] -# Data: Global streaming platform subscribers (millions) over 5 years +# Data: Major economy GDP rankings (approximate, in trillion USD, 1995–2023) np.random.seed(42) -platforms = [ - "StreamFlix", - "ViewMax", - "WatchHub", - "PlayStream", - "CinemaCloud", - "MediaFlow", - "ScreenTime", - "FlixNow", - "StreamZone", - "OnDemandTV", -] -years = list(range(2019, 2025)) - -# Generate realistic subscriber growth data with varying trajectories -data = [] -base_values = { - "StreamFlix": 150, - "ViewMax": 120, - "WatchHub": 80, - "PlayStream": 60, - "CinemaCloud": 50, - "MediaFlow": 40, - "ScreenTime": 35, - "FlixNow": 25, - "StreamZone": 20, - "OnDemandTV": 15, -} - -growth_rates = { - "StreamFlix": 1.15, - "ViewMax": 1.25, - "WatchHub": 1.35, - "PlayStream": 1.20, - "CinemaCloud": 1.10, - "MediaFlow": 1.30, - "ScreenTime": 1.40, - "FlixNow": 1.45, - "StreamZone": 1.25, - "OnDemandTV": 1.50, -} - -for platform in platforms: - value = base_values[platform] +countries = ["USA", "China", "Japan", "Germany", "UK", "France", "Brazil"] +years = list(range(1995, 2024)) + +base_gdp = {"USA": 7.70, "China": 0.73, "Japan": 5.45, "Germany": 2.60, "UK": 1.28, "France": 1.60, "Brazil": 0.77} +color_map = dict(zip(countries, OKABE_ITO)) + +data_rows = [] +for country in countries: + gdp = base_gdp[country] for year in years: - noise = np.random.uniform(0.9, 1.1) - data.append({"Platform": platform, "Year": year, "Subscribers": round(value * noise, 1)}) - value = value * growth_rates[platform] - -df = pd.DataFrame(data) - -# Sort and add rank for each year -df["Rank"] = df.groupby("Year")["Subscribers"].rank(method="first", ascending=False) -df = df.sort_values(["Year", "Subscribers"], ascending=[True, False]) - -# Color palette - consistent per platform (using Python colors first, then colorblind-safe) -colors = ["#306998", "#FFD43B", "#E24A33", "#348ABD", "#988ED5", "#777777", "#FBC15E", "#8EBA42", "#FFB5B8", "#56B4E9"] -color_map = dict(zip(platforms, colors, strict=False)) - -# Create animated bar chart -fig = px.bar( - df, - x="Subscribers", - y="Platform", - color="Platform", - color_discrete_map=color_map, - animation_frame="Year", - orientation="h", - text="Subscribers", - category_orders={ - "Platform": df[df["Year"] == 2024].sort_values("Subscribers", ascending=True)["Platform"].tolist() - }, + noise = np.random.uniform(0.99, 1.01) + data_rows.append({"Country": country, "Year": year, "GDP": round(gdp * noise, 3)}) + if country == "USA": + rate = -0.020 if year == 2009 else 0.047 + elif country == "China": + rate = 0.115 if year < 2005 else (0.138 if year < 2015 else (0.072 if year < 2020 else 0.056)) + elif country == "Japan": + rate = -0.012 if year in [2009, 2011] else 0.014 + elif country == "Germany": + rate = -0.050 if year == 2009 else 0.040 + elif country == "UK": + rate = -0.040 if year == 2009 else 0.042 + elif country == "France": + rate = -0.030 if year == 2009 else 0.037 + else: # Brazil + rate = 0.083 if year < 2011 else (0.025 if year < 2015 else (-0.005 if year < 2019 else 0.038)) + gdp = gdp * (1 + rate) + +df = pd.DataFrame(data_rows) +max_gdp = df["GDP"].max() * 1.18 +title_text = "GDP Rankings · bar-race-animated · python · plotly · anyplot.ai" + +shared_xaxis = dict( + title=dict(text="GDP (Trillion USD)", font=dict(size=22, color=INK)), + tickfont=dict(size=18, color=INK_SOFT), + range=[0, max_gdp], + gridcolor=GRID, + linecolor=INK_SOFT, + zerolinecolor=INK_SOFT, ) - -# Update layout for 4800x2700 px canvas -fig.update_layout( - title={ - "text": "bar-race-animated · plotly · pyplots.ai", "font": {"size": 32, "color": "#333333"}, "x": 0.5, "xanchor": "center" - }, - xaxis={ - "title": {"text": "Subscribers (Millions)", "font": {"size": 24}}, - "tickfont": {"size": 18}, - "range": [0, df["Subscribers"].max() * 1.15], - "gridcolor": "rgba(128,128,128,0.2)", - "gridwidth": 1, - }, - yaxis={"title": {"text": "", "font": {"size": 24}}, "tickfont": {"size": 20}, "categoryorder": "total ascending"}, - template="plotly_white", - showlegend=False, - margin={"l": 200, "r": 100, "t": 120, "b": 100}, - plot_bgcolor="white", - paper_bgcolor="white", +shared_yaxis = dict(tickfont=dict(size=20, color=INK_SOFT), linecolor=INK_SOFT, showgrid=False) +shared_margin = dict(l=150, r=160, t=140, b=160) + +# Animation frames: bars sorted by GDP value each year +frames = [] +slider_steps = [] +for year in years: + year_data = df[df["Year"] == year].sort_values("GDP", ascending=True) + frames.append( + go.Frame( + data=[ + go.Bar( + x=year_data["GDP"], + y=year_data["Country"], + orientation="h", + text=[f"{v:.1f}T" for v in year_data["GDP"]], + textposition="outside", + textfont=dict(size=18, color=INK), + marker=dict(color=[color_map[c] for c in year_data["Country"]], line=dict(width=0)), + ) + ], + name=str(year), + ) + ) + slider_steps.append( + dict( + args=[ + [str(year)], + dict(frame=dict(duration=600, redraw=True), mode="immediate", transition=dict(duration=300)), + ], + label=str(year), + method="animate", + ) + ) + +# Initial state: 1995 +init_data = df[df["Year"] == years[0]].sort_values("GDP", ascending=True) + +fig_anim = go.Figure( + data=[ + go.Bar( + x=init_data["GDP"], + y=init_data["Country"], + orientation="h", + text=[f"{v:.1f}T" for v in init_data["GDP"]], + textposition="outside", + textfont=dict(size=18, color=INK), + marker=dict(color=[color_map[c] for c in init_data["Country"]], line=dict(width=0)), + ) + ], + layout=go.Layout( + title=dict(text=title_text, font=dict(size=28, color=INK), x=0.5, xanchor="center"), + xaxis=shared_xaxis, + yaxis=shared_yaxis, + paper_bgcolor=PAGE_BG, + plot_bgcolor=PAGE_BG, + margin=shared_margin, + showlegend=False, + updatemenus=[ + dict( + type="buttons", + showactive=False, + y=1.08, + x=0.0, + xanchor="left", + buttons=[ + dict( + label="▶ Play", + method="animate", + args=[ + None, + dict( + frame=dict(duration=600, redraw=True), fromcurrent=True, transition=dict(duration=300) + ), + ], + ), + dict( + label="⏸ Pause", + method="animate", + args=[ + [None], + dict(frame=dict(duration=0, redraw=False), mode="immediate", transition=dict(duration=0)), + ], + ), + ], + ) + ], + sliders=[ + dict( + active=0, + currentvalue=dict(font=dict(size=24, color=INK), prefix="Year: ", visible=True, xanchor="center"), + font=dict(size=16, color=INK_SOFT), + bgcolor=ELEVATED_BG, + bordercolor=INK_SOFT, + steps=slider_steps, + pad=dict(b=10, t=50), + ) + ], + ), + frames=frames, ) -# Update traces for better visibility -fig.update_traces( - texttemplate="%{text:.0f}M", - textposition="outside", - textfont={"size": 18, "color": "#333333"}, - marker={"line": {"width": 1, "color": "white"}}, +fig_anim.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn") + +# Static PNG: final year (2023) snapshot showing the race outcome +final_data = df[df["Year"] == years[-1]].sort_values("GDP", ascending=True) + +fig_png = go.Figure( + data=[ + go.Bar( + x=final_data["GDP"], + y=final_data["Country"], + orientation="h", + text=[f"{v:.1f}T" for v in final_data["GDP"]], + textposition="outside", + textfont=dict(size=18, color=INK), + marker=dict(color=[color_map[c] for c in final_data["Country"]], line=dict(width=0)), + ) + ] +) +fig_png.update_layout( + title=dict(text=title_text, font=dict(size=28, color=INK), x=0.5, xanchor="center"), + xaxis=dict( + title=dict(text="GDP (Trillion USD) — 2023 snapshot", font=dict(size=22, color=INK)), + tickfont=dict(size=18, color=INK_SOFT), + range=[0, max_gdp], + gridcolor=GRID, + linecolor=INK_SOFT, + zerolinecolor=INK_SOFT, + ), + yaxis=shared_yaxis, + paper_bgcolor=PAGE_BG, + plot_bgcolor=PAGE_BG, + margin=dict(l=150, r=160, t=120, b=100), + showlegend=False, ) -# Update animation settings -fig.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 800 -fig.layout.updatemenus[0].buttons[0].args[1]["transition"]["duration"] = 400 - -# Update slider styling -fig.layout.sliders[0].font = {"size": 18} -fig.layout.sliders[0].currentvalue = {"font": {"size": 24}, "prefix": "Year: ", "visible": True, "xanchor": "center"} - -# Save as PNG (static frame showing final year) -fig.write_image("plot.png", width=1600, height=900, scale=3) - -# Save as HTML (interactive with animation) -fig.write_html("plot.html", include_plotlyjs=True, full_html=True) +fig_png.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3) diff --git a/plots/bar-race-animated/metadata/python/plotly.yaml b/plots/bar-race-animated/metadata/python/plotly.yaml index 1e18fa1719..487c29e5fd 100644 --- a/plots/bar-race-animated/metadata/python/plotly.yaml +++ b/plots/bar-race-animated/metadata/python/plotly.yaml @@ -1,210 +1,21 @@ +# Per-library metadata for plotly implementation of bar-race-animated +# Auto-generated by impl-generate.yml + library: plotly +language: python specification_id: bar-race-animated created: '2026-01-11T00:19:26Z' -updated: '2026-01-11T00:25:51Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20886560119 +updated: '2026-05-19T01:53:42Z' +generated_by: claude-sonnet +workflow_run: 26071044074 issue: 3653 -python_version: 3.13.11 -library_version: 6.5.1 -preview_url: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/plotly/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/plotly/plot.html -quality_score: 92 +language_version: 3.13.13 +library_version: 6.7.0 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-dark.html +quality_score: null review: - strengths: - - Excellent use of Plotly animation_frame for smooth bar race animation - - Clean, readable layout with properly sized fonts and margins - - Interactive controls (play/pause, timeline slider) with year indicator - - Consistent color mapping per platform across frames - - Both PNG and HTML outputs generated - - Realistic streaming platform scenario with varied growth trajectories - weaknesses: - - Grid lines are very subtle/nearly invisible - could use slightly more visible - grid (alpha 0.2-0.3) - - Static PNG only shows 2019 frame; users seeing PNG miss the animation story - - Two similar blue shades (StreamFlix and OnDemandTV) could be more distinct - image_description: 'The plot displays a horizontal bar chart showing 10 streaming - platform subscriber counts for the year 2019. StreamFlix leads with 146M subscribers - (dark blue bar), followed by ViewMax at 109M (yellow), WatchHub at 85M (red/orange), - PlayStream at 59M (blue), CinemaCloud at 50M (purple), MediaFlow at 41M (gray), - ScreenTime at 34M (orange), FlixNow at 23M (green), StreamZone at 20M (pink), - and OnDemandTV at 15M (light blue). The title "bar-race-animated · plotly · pyplots.ai" - is centered at the top. The x-axis shows "Subscribers (Millions)" ranging from - 0 to 450. A year indicator shows "Year: 2019" and a timeline slider at the bottom - spans 2019-2024 with play/pause controls. Each bar has its value labeled to the - right. The bars are sorted in descending order by subscriber count. Colors are - distinct and consistent per platform. The layout has ample margins and uses a - clean white background with subtle grid lines.' - criteria_checklist: - visual_quality: - score: 36 - max: 40 - items: - - id: VQ-01 - name: Text Legibility - score: 10 - max: 10 - passed: true - comment: Title at 32pt, axis labels at 24pt, tick fonts at 18-20pt, all perfectly - readable - - id: VQ-02 - name: No Overlap - score: 8 - max: 8 - passed: true - comment: No overlapping text, platform labels and values are well-spaced - - id: VQ-03 - name: Element Visibility - score: 8 - max: 8 - passed: true - comment: Bars are appropriately sized with good contrast, value labels outside - bars - - id: VQ-04 - name: Color Accessibility - score: 4 - max: 5 - passed: true - comment: Good variety of distinct colors, though some similar hues (two blues) - - id: VQ-05 - name: Layout Balance - score: 4 - max: 5 - passed: true - comment: Good use of canvas with proper margins, though bars only use ~1/3 - of x-axis range in first frame - - id: VQ-06 - name: Axis Labels - score: 2 - max: 2 - passed: true - comment: X-axis has Subscribers (Millions) with units - - id: VQ-07 - name: Grid & Legend - score: 0 - max: 2 - passed: false - comment: Legend disabled (appropriate), but grid is very subtle/nearly invisible - spec_compliance: - score: 25 - max: 25 - items: - - id: SC-01 - name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct animated horizontal bar chart race - - id: SC-02 - name: Data Mapping - score: 5 - max: 5 - passed: true - comment: Platforms on Y-axis, subscribers on X-axis, animation by year - - id: SC-03 - name: Required Features - score: 5 - max: 5 - passed: true - comment: Sorted bars, entity labels, time indicator, play/pause controls, - timeline scrubber, consistent colors - - id: SC-04 - name: Data Range - score: 3 - max: 3 - passed: true - comment: X-axis range set to 115% of max to accommodate growth - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: No legend needed, platform names on Y-axis - - id: SC-06 - name: Title Format - score: 2 - max: 2 - passed: true - comment: 'Correct format: bar-race-animated · plotly · pyplots.ai' - data_quality: - score: 18 - max: 20 - items: - - id: DQ-01 - name: Feature Coverage - score: 7 - max: 8 - passed: true - comment: 'Shows ranking changes over time, varying growth rates, overtakes - possible; minor: static PNG shows only first frame' - - id: DQ-02 - name: Realistic Context - score: 7 - max: 7 - passed: true - comment: Streaming platform subscriber data is realistic and neutral - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 5 - passed: true - comment: Values are plausible (15M-450M range), though some growth rates (1.5x/year) - are aggressive - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Linear script: imports, data, plot, save' - - id: CQ-02 - name: Reproducibility - score: 3 - max: 3 - passed: true - comment: np.random.seed(42) set - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: Only numpy, pandas, plotly.express used - - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 - passed: true - comment: Modern plotly.express API - - id: CQ-05 - name: Output Correct - score: 1 - max: 1 - passed: true - comment: Saves as plot.png and plot.html - library_features: - score: 3 - max: 5 - items: - - id: LF-01 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: Uses px.bar with animation_frame, slider, play controls; could use - more advanced features like custom animation easing - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - annotations - - html-export - patterns: - - data-generation - - iteration-over-groups - dataprep: [] - styling: - - edge-highlighting - - grid-styling + strengths: [] + weaknesses: [] From bcddb6fe1a5da7fb3e25903a7a11bc15664b2b45 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 02:01:24 +0000 Subject: [PATCH 2/3] chore(plotly): update quality score 86 and review feedback for bar-race-animated --- .../implementations/python/plotly.py | 6 +- .../metadata/python/plotly.yaml | 257 +++++++++++++++++- 2 files changed, 253 insertions(+), 10 deletions(-) diff --git a/plots/bar-race-animated/implementations/python/plotly.py b/plots/bar-race-animated/implementations/python/plotly.py index 066c69148b..7379ca6d12 100644 --- a/plots/bar-race-animated/implementations/python/plotly.py +++ b/plots/bar-race-animated/implementations/python/plotly.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai bar-race-animated: Animated Bar Chart Race -Library: plotly | Python 3.13 -Quality: pending | Created: 2026-05-19 +Library: plotly 6.7.0 | Python 3.13.13 +Quality: 86/100 | Updated: 2026-05-19 """ import os diff --git a/plots/bar-race-animated/metadata/python/plotly.yaml b/plots/bar-race-animated/metadata/python/plotly.yaml index 487c29e5fd..a8996d43bd 100644 --- a/plots/bar-race-animated/metadata/python/plotly.yaml +++ b/plots/bar-race-animated/metadata/python/plotly.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for plotly implementation of bar-race-animated -# Auto-generated by impl-generate.yml - library: plotly language: python specification_id: bar-race-animated created: '2026-01-11T00:19:26Z' -updated: '2026-05-19T01:53:42Z' +updated: '2026-05-19T02:01:24Z' generated_by: claude-sonnet workflow_run: 26071044074 issue: 3653 @@ -15,7 +12,253 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/bar-race- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-dark.html -quality_score: null +quality_score: 86 review: - strengths: [] - weaknesses: [] + strengths: + - 'Full Plotly animation implemented: go.Figure with frames, updatemenus (play/pause), + and year slider — correct idiomatic usage of Plotly''s animation API' + - 'Correct Okabe-Ito palette applied in canonical order; USA (first entity) gets + #009E73; all 7 Okabe-Ito colors used for 7 countries' + - 'Theme adaptation works correctly: PAGE_BG, INK, INK_SOFT, GRID all flip between + light (#FAF8F1) and dark (#1A1A17); no dark-on-dark text failures' + - Explicit font sizes throughout (title 28px, axis labels 22px, tick labels 18-20px, + bar value labels 18px) + - HTML output includes play/pause buttons and year scrubber slider — satisfies all + interactive spec requirements + - Flat procedural code with np.random.seed(42) — clean, reproducible, no functions/classes + - Data scenario (country GDP 1995-2023) is realistic and neutral; correct output + files (plot-{THEME}.png + plot-{THEME}.html) + weaknesses: + - 'Design lacks visual polish: no spine removal on the static PNG axes, grid at + 25% opacity (style guide specifies 10-15%)' + - 'DE-03 storytelling is absent in the PNG: static snapshot shows final rankings + without emphasizing the interesting story (China''s rise from ~5th to 2nd, Germany + overtaking Japan in late period) — consider rank number labels (#1, #2...) or + a subtitle annotation' + - 'DQ-03 data accuracy: Japan (7.7T) and Germany (7.2T) are 60-80% above their real + 2023 nominal GDP (~4.2T and ~4.5T respectively); the simulation''s growth rates + are too high for these economies; also Germany surpassed Japan in 2023 making + the Japan>Germany ordering historically incorrect' + - 'Right-side canvas whitespace: USA bar reaches only ~85% of x-axis width, leaving + significant empty space; right margin could be tighter or value labels placed + inside bars to improve canvas utilization' + - 'No rank labels (#1, #2, etc.) on bars to reinforce the racing/ranking narrative + of the chart type' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct theme surface, not pure white + Chrome: Title "GDP Rankings · bar-race-animated · python · plotly · anyplot.ai" centered in dark text (#1A1A17), clearly readable. X-axis label "GDP (Trillion USD) — 2023 snapshot" with units, readable. Country tick labels (left y-axis) in dark secondary text, readable. X-axis tick labels 0–30 in secondary dark text, readable. + Data: 7 horizontal bars in Okabe-Ito order — USA (#009E73 green, longest at 26.1T), China (#D55E00 orange-red at 13.1T), Japan (#0072B2 blue at 7.7T), Germany (#CC79A7 pink at 7.2T), France (#56B4E9 sky-blue at 4.1T), UK (#E69F00 amber at 3.7T), Brazil (#F0E442 yellow at 3.4T). Value labels outside bars ("26.1T" etc.) in dark ink. Subtle vertical grid lines visible. Bars sorted descending (USA top, Brazil bottom). + Legibility verdict: PASS — all text clearly readable against warm off-white background; no light-on-light issues. + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct theme surface, not pure black + Chrome: Title in light text (#F0EFE8), clearly readable. Axis labels in light text, readable. Country tick labels in light secondary text (#B8B7B0), readable. Tick numbers on x-axis in light secondary text, readable. No dark-on-dark failures observed. + Data: Bar colors are IDENTICAL to light render — USA green #009E73, China orange-red, Japan blue, Germany pink, France sky-blue, UK amber, Brazil yellow. Data identity preserved across themes. Value labels ("26.1T", etc.) rendered in #F0EFE8 (INK for dark theme), clearly visible on the dark background. + Legibility verdict: PASS — all text readable against near-black background; theme adaptation correct throughout. + criteria_checklist: + visual_quality: + score: 29 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 8 + max: 8 + passed: true + comment: 'All font sizes explicitly set: title 28px, axis labels 22px, tick + labels 18-20px, bar value labels 18px; both themes fully readable' + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping text; bar labels, y-axis labels, and tick marks are + all well-spaced + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: All 7 bars visible, colors clearly distinct, value labels readable + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Okabe-Ito palette is CVD-safe; no red-green as sole signal + - id: VQ-05 + name: Layout & Canvas + score: 3 + max: 4 + passed: true + comment: Good proportions overall; right side has notable empty space as USA + bar reaches only ~85% of x-axis range + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Title correctly formatted; x-axis label includes units (Trillion + USD) and snapshot year + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'USA (first entity) = #009E73; Okabe-Ito canonical order followed; + backgrounds #FAF8F1 (light) / #1A1A17 (dark) correct; data colors identical + across themes' + design_excellence: + score: 9 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 4 + max: 8 + passed: false + comment: Clean well-configured default appearance; correct palette and no + legend, but no typographic weight hierarchy, no rank annotations, no highlights + of notable data moments + - id: DE-02 + name: Visual Refinement + score: 2 + max: 6 + passed: false + comment: Grid at 25% opacity exceeds the 10-15% guideline; no spine removal + on axes; minimal refinement beyond correct color palette + - id: DE-03 + name: Data Storytelling + score: 3 + max: 6 + passed: false + comment: Sorted bars inherently communicate ranking; animation is excellent + storytelling in HTML; but static PNG has no emphasis on interesting dynamics + (China's rise, Germany overtaking Japan) + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correct animated horizontal bar chart with full Plotly animation + API + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Bars sorted at each frame, entity labels on y-axis, year slider as + time indicator, play/pause controls, consistent entity colors + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X=GDP value, Y=countries (sorted by GDP per frame), horizontal orientation + correct + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title is 'GDP Rankings · bar-race-animated · python · plotly · anyplot.ai' + — correct format; no legend (appropriate, country labels on y-axis) + data_quality: + score: 13 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: 'Shows all key bar-race features: multiple entities, time evolution, + position changes, ranking reversals, value labels' + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Country GDP over time is a canonical, neutral, comprehensible bar-race + application + - id: DQ-03 + name: Appropriate Scale + score: 2 + max: 4 + passed: false + comment: Japan shows 7.7T (real ~4.2T, 84% over), Germany shows 7.2T (real + ~4.5T, 60% over), France 4.1T (real ~2.9T, 41% over); also Germany surpassed + Japan in 2023 but data shows Japan>Germany, reversing historical fact + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Flat procedural structure: imports → data → animation frames → figure + → save' + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42) set before data generation + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: os, numpy, pandas, plotly.graph_objects — all used + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: List comprehensions for frames, clean separation of animation vs + PNG figure, no over-engineering + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png and plot-{THEME}.html with correct naming + convention + library_mastery: + score: 10 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: Uses go.Figure(frames=...) with go.Frame objects — Plotly's idiomatic + animation pattern; updatemenus and sliders are the canonical way to add + controls + - id: LM-02 + name: Distinctive Features + score: 5 + max: 5 + passed: true + comment: Frames + updatemenus (play/pause) + sliders (year scrubber) are Plotly-exclusive + features impossible to replicate in matplotlib/seaborn/ggplot2 + verdict: REJECTED +impl_tags: + dependencies: [] + techniques: + - html-export + - hover-tooltips + patterns: + - data-generation + - iteration-over-groups + dataprep: [] + styling: + - grid-styling From 09fd362cfd472855feee362f7c6462219ff8df18 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 02:20:56 +0000 Subject: [PATCH 3/3] chore(plotly): update quality score 88 and review feedback for bar-race-animated --- .../implementations/python/plotly.py | 2 +- .../metadata/python/plotly.yaml | 180 ++++++++---------- 2 files changed, 80 insertions(+), 102 deletions(-) diff --git a/plots/bar-race-animated/implementations/python/plotly.py b/plots/bar-race-animated/implementations/python/plotly.py index 7379ca6d12..cf89e8cd18 100644 --- a/plots/bar-race-animated/implementations/python/plotly.py +++ b/plots/bar-race-animated/implementations/python/plotly.py @@ -1,7 +1,7 @@ """ anyplot.ai bar-race-animated: Animated Bar Chart Race Library: plotly 6.7.0 | Python 3.13.13 -Quality: 86/100 | Updated: 2026-05-19 +Quality: 88/100 | Updated: 2026-05-19 """ import os diff --git a/plots/bar-race-animated/metadata/python/plotly.yaml b/plots/bar-race-animated/metadata/python/plotly.yaml index a8996d43bd..8b76c8059a 100644 --- a/plots/bar-race-animated/metadata/python/plotly.yaml +++ b/plots/bar-race-animated/metadata/python/plotly.yaml @@ -2,7 +2,7 @@ library: plotly language: python specification_id: bar-race-animated created: '2026-01-11T00:19:26Z' -updated: '2026-05-19T02:01:24Z' +updated: '2026-05-19T02:20:56Z' generated_by: claude-sonnet workflow_run: 26071044074 issue: 3653 @@ -12,50 +12,41 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/bar-race- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/bar-race-animated/python/plotly/plot-dark.html -quality_score: 86 +quality_score: 88 review: strengths: - - 'Full Plotly animation implemented: go.Figure with frames, updatemenus (play/pause), - and year slider — correct idiomatic usage of Plotly''s animation API' - - 'Correct Okabe-Ito palette applied in canonical order; USA (first entity) gets - #009E73; all 7 Okabe-Ito colors used for 7 countries' - - 'Theme adaptation works correctly: PAGE_BG, INK, INK_SOFT, GRID all flip between - light (#FAF8F1) and dark (#1A1A17); no dark-on-dark text failures' - - Explicit font sizes throughout (title 28px, axis labels 22px, tick labels 18-20px, - bar value labels 18px) - - HTML output includes play/pause buttons and year scrubber slider — satisfies all - interactive spec requirements - - Flat procedural code with np.random.seed(42) — clean, reproducible, no functions/classes - - Data scenario (country GDP 1995-2023) is realistic and neutral; correct output - files (plot-{THEME}.png + plot-{THEME}.html) + - 'Full Plotly animation API used correctly: go.Frame array, updatemenus play/pause, + sliders timeline scrubber — distinctly Plotly features that cannot be replicated + in static libraries' + - 'Perfect spec compliance: sorted bars per frame, consistent entity colors, visible + year indicator via slider, configurable animation speed (600ms frame, 300ms transition)' + - Both renders theme-adapt correctly; GRID, INK, INK_SOFT, PAGE_BG, and ELEVATED_BG + tokens all wired through to every relevant layout element in both the animated + and PNG figures + - Realistic GDP data with accurate proportions and genuine rank changes (China's + rise from last to 2nd, Germany overtaking Japan) makes for compelling animation + content weaknesses: - - 'Design lacks visual polish: no spine removal on the static PNG axes, grid at - 25% opacity (style guide specifies 10-15%)' - - 'DE-03 storytelling is absent in the PNG: static snapshot shows final rankings - without emphasizing the interesting story (China''s rise from ~5th to 2nd, Germany - overtaking Japan in late period) — consider rank number labels (#1, #2...) or - a subtitle annotation' - - 'DQ-03 data accuracy: Japan (7.7T) and Germany (7.2T) are 60-80% above their real - 2023 nominal GDP (~4.2T and ~4.5T respectively); the simulation''s growth rates - are too high for these economies; also Germany surpassed Japan in 2023 making - the Japan>Germany ordering historically incorrect' - - 'Right-side canvas whitespace: USA bar reaches only ~85% of x-axis width, leaving - significant empty space; right margin could be tighter or value labels placed - inside bars to improve canvas utilization' - - 'No rank labels (#1, #2, etc.) on bars to reinforce the racing/ranking narrative - of the chart type' + - 'Grid opacity set to 0.25 instead of style guide-specified 0.10 — grid lines are + 2.5x more prominent than intended; fix: GRID = "rgba(26,26,23,0.10)" if THEME + == "light" else "rgba(240,239,232,0.10)"' + - 'DE-01 remains at configured-default level: no typographic hierarchy beyond font + sizes, no visual emphasis on the leading bar or fastest-rising entity to create + a focal point' + - Only 7 entities in the dataset; specification recommends 10-20 for richer competitive + dynamics — consider adding India, Canada, South Korea, Italy image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct theme surface, not pure white - Chrome: Title "GDP Rankings · bar-race-animated · python · plotly · anyplot.ai" centered in dark text (#1A1A17), clearly readable. X-axis label "GDP (Trillion USD) — 2023 snapshot" with units, readable. Country tick labels (left y-axis) in dark secondary text, readable. X-axis tick labels 0–30 in secondary dark text, readable. - Data: 7 horizontal bars in Okabe-Ito order — USA (#009E73 green, longest at 26.1T), China (#D55E00 orange-red at 13.1T), Japan (#0072B2 blue at 7.7T), Germany (#CC79A7 pink at 7.2T), France (#56B4E9 sky-blue at 4.1T), UK (#E69F00 amber at 3.7T), Brazil (#F0E442 yellow at 3.4T). Value labels outside bars ("26.1T" etc.) in dark ink. Subtle vertical grid lines visible. Bars sorted descending (USA top, Brazil bottom). - Legibility verdict: PASS — all text clearly readable against warm off-white background; no light-on-light issues. + Background: Warm off-white #FAF8F1 — correct theme surface, not pure white + Chrome: Title "GDP Rankings · bar-race-animated · python · plotly · anyplot.ai" in 28px dark INK text, centered; subtitle in smaller gray INK_SOFT text; X-axis label "GDP (Trillion USD) — 2023 snapshot" in 22px; tick labels 18px — all clearly readable against light background + Data: 7 horizontal bars sorted descending (USA top, Brazil bottom); colors follow Okabe-Ito order — USA #009E73 (brand green), China #D55E00, Germany #CC79A7, Japan #0072B2, UK #E69F00, France #56B4E9, Brazil #F0E442; rank labels (#1–#7) and GDP values outside bars in dark INK text + Legibility verdict: PASS Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct theme surface, not pure black - Chrome: Title in light text (#F0EFE8), clearly readable. Axis labels in light text, readable. Country tick labels in light secondary text (#B8B7B0), readable. Tick numbers on x-axis in light secondary text, readable. No dark-on-dark failures observed. - Data: Bar colors are IDENTICAL to light render — USA green #009E73, China orange-red, Japan blue, Germany pink, France sky-blue, UK amber, Brazil yellow. Data identity preserved across themes. Value labels ("26.1T", etc.) rendered in #F0EFE8 (INK for dark theme), clearly visible on the dark background. - Legibility verdict: PASS — all text readable against near-black background; theme adaptation correct throughout. + Background: Warm near-black #1A1A17 — correct dark theme surface, not pure black + Chrome: Title, subtitle, axis labels, tick labels, and rank/value labels all render in light cream/off-white INK token; no dark-on-dark failures observed; all text elements clearly distinguishable against near-black surface + Data: Identical bar colors to light render — #009E73, #D55E00, #CC79A7, #0072B2, #E69F00, #56B4E9, #F0E442 all unchanged confirming correct Okabe-Ito immutability across themes; brand green #009E73 remains vivid on dark surface + Legibility verdict: PASS criteria_checklist: visual_quality: score: 29 @@ -63,54 +54,50 @@ review: items: - id: VQ-01 name: Text Legibility - score: 8 + score: 7 max: 8 passed: true - comment: 'All font sizes explicitly set: title 28px, axis labels 22px, tick - labels 18-20px, bar value labels 18px; both themes fully readable' + comment: All font sizes explicitly set (title 28px, axis 22px, ticks/labels + 18px); readable in both themes; minor deduction for subtitle size - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text; bar labels, y-axis labels, and tick marks are - all well-spaced + comment: No overlapping elements in either render - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: All 7 bars visible, colors clearly distinct, value labels readable + comment: All bars clearly visible; rank/value labels positioned outside bars - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Okabe-Ito palette is CVD-safe; no red-green as sole signal + comment: Okabe-Ito is CVD-safe; no red-green-only encoding - id: VQ-05 name: Layout & Canvas - score: 3 + score: 4 max: 4 passed: true - comment: Good proportions overall; right side has notable empty space as USA - bar reaches only ~85% of x-axis range + comment: 4800x2700px effective; balanced margins; nothing cut off - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Title correctly formatted; x-axis label includes units (Trillion - USD) and snapshot year + comment: X-axis has descriptive label with units; title correctly formatted - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'USA (first entity) = #009E73; Okabe-Ito canonical order followed; - backgrounds #FAF8F1 (light) / #1A1A17 (dark) correct; data colors identical - across themes' + comment: 'First series #009E73; Okabe-Ito order; correct backgrounds #FAF8F1/#1A1A17; + chrome tokens flip correctly' design_excellence: - score: 9 + score: 11 max: 20 items: - id: DE-01 @@ -118,24 +105,22 @@ review: score: 4 max: 8 passed: false - comment: Clean well-configured default appearance; correct palette and no - legend, but no typographic weight hierarchy, no rank annotations, no highlights - of notable data moments + comment: Well-configured defaults; correct palette and rank labels; no typographic + or visual hierarchy innovation beyond defaults - id: DE-02 name: Visual Refinement - score: 2 + score: 3 max: 6 passed: false - comment: Grid at 25% opacity exceeds the 10-15% guideline; no spine removal - on axes; minimal refinement beyond correct color palette + comment: Generous margins and clean layout; grid opacity 0.25 exceeds recommended + 0.10 - id: DE-03 name: Data Storytelling - score: 3 + score: 4 max: 6 passed: false - comment: Sorted bars inherently communicate ranking; animation is excellent - storytelling in HTML; but static PNG has no emphasis on interesting dynamics - (China's rise, Germany overtaking Japan) + comment: Subtitle explicitly identifies narrative; rank labels provide hierarchy; + animation delivers the race story dynamically spec_compliance: score: 15 max: 15 @@ -145,31 +130,30 @@ review: score: 5 max: 5 passed: true - comment: Correct animated horizontal bar chart with full Plotly animation - API + comment: Animated horizontal bar chart race with per-frame sorted bars - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Bars sorted at each frame, entity labels on y-axis, year slider as - time indicator, play/pause controls, consistent entity colors + comment: Sorted frames, consistent colors, year slider, play/pause controls, + configurable speed - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X=GDP value, Y=countries (sorted by GDP per frame), horizontal orientation - correct + comment: Horizontal orientation, GDP on x-axis, countries on y-axis, 29 time + points - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title is 'GDP Rankings · bar-race-animated · python · plotly · anyplot.ai' - — correct format; no legend (appropriate, country labels on y-axis) + comment: Correct title format; no legend needed; entity identity via y-axis + labels data_quality: - score: 13 + score: 15 max: 15 items: - id: DQ-01 @@ -177,23 +161,21 @@ review: score: 6 max: 6 passed: true - comment: 'Shows all key bar-race features: multiple entities, time evolution, - position changes, ranking reversals, value labels' + comment: Multiple entities competing with rank changes; dominant leader and + dramatic risers - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Country GDP over time is a canonical, neutral, comprehensible bar-race - application + comment: Major economy GDP — real, comprehensible, politically neutral - id: DQ-03 name: Appropriate Scale - score: 2 + score: 4 max: 4 - passed: false - comment: Japan shows 7.7T (real ~4.2T, 84% over), Germany shows 7.2T (real - ~4.5T, 60% over), France 4.1T (real ~2.9T, 41% over); also Germany surpassed - Japan in 2023 but data shows Japan>Germany, reversing historical fact + passed: true + comment: GDP values (USA ~26T, China ~13T, Japan ~4T in 2023) match approximately + correct real-world proportions code_quality: score: 10 max: 10 @@ -203,14 +185,14 @@ review: score: 3 max: 3 passed: true - comment: 'Flat procedural structure: imports → data → animation frames → figure - → save' + comment: 'Flat script: constants -> data -> animation frames -> figures -> + save' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set before data generation + comment: np.random.seed(42) present - id: CQ-03 name: Clean Imports score: 2 @@ -222,43 +204,39 @@ review: score: 2 max: 2 passed: true - comment: List comprehensions for frames, clean separation of animation vs - PNG figure, no over-engineering + comment: Appropriate complexity; clean separation of animation and PNG figures; + no fake UI - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html with correct naming - convention + comment: Saves plot-{THEME}.png and plot-{THEME}.html with correct dimensions library_mastery: - score: 10 + score: 8 max: 10 items: - id: LM-01 name: Idiomatic Usage - score: 5 + score: 4 max: 5 passed: true - comment: Uses go.Figure(frames=...) with go.Frame objects — Plotly's idiomatic - animation pattern; updatemenus and sliders are the canonical way to add - controls + comment: go.Frame, go.Figure(frames=...), updatemenus, sliders — all recommended + Plotly animation patterns - id: LM-02 name: Distinctive Features - score: 5 + score: 4 max: 5 passed: true - comment: Frames + updatemenus (play/pause) + sliders (year scrubber) are Plotly-exclusive - features impossible to replicate in matplotlib/seaborn/ggplot2 - verdict: REJECTED + comment: Plotly animation with timeline slider and play/pause is genuinely + distinctive; animated hover templates not customized + verdict: APPROVED impl_tags: dependencies: [] techniques: - html-export - - hover-tooltips patterns: - data-generation - iteration-over-groups dataprep: [] - styling: - - grid-styling + styling: []