From cc3353b7c483c1ffcf07146b6e12fe528b77e458 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 13:15:25 +0000 Subject: [PATCH 1/4] feat(seaborn): implement timeseries-forecast-uncertainty Regen from quality 90. Addressed LM-02 (Distinctive Features): - Switched ax.plot() to sns.lineplot() with long-form data, hue+style+dashes - Added sns.despine() for seaborn-native spine management - Fixed title missing python language token (mandatory format) - Explicit Line2D+Patch legend handles for all series and CI bands --- .../implementations/python/seaborn.py | 119 +++++++++--------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py b/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py index 79ade74284..16b3615393 100644 --- a/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py +++ b/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py @@ -1,7 +1,7 @@ -""" anyplot.ai +"""anyplot.ai timeseries-forecast-uncertainty: Time Series Forecast with Uncertainty Band Library: seaborn 0.13.2 | Python 3.13.13 -Quality: 90/100 | Updated: 2026-05-16 +Quality: 90/100 | Updated: 2026-05-19 """ import os @@ -10,6 +10,8 @@ import numpy as np import pandas as pd import seaborn as sns +from matplotlib.lines import Line2D +from matplotlib.patches import Patch # Theme tokens @@ -21,45 +23,31 @@ # Okabe-Ito palette OKABE_ITO = ["#009E73", "#D55E00", "#0072B2", "#CC79A7", "#E69F00", "#56B4E9", "#F0E442"] -COLOR_HISTORICAL = OKABE_ITO[0] # Green -COLOR_FORECAST = OKABE_ITO[1] # Vermillion +COLOR_HISTORICAL = OKABE_ITO[0] +COLOR_FORECAST = OKABE_ITO[1] -# Set seed for reproducibility np.random.seed(42) -# Generate stock price time series with forecast -n_historical = 60 # 60 trading days (~3 months) -n_forecast = 20 # 20 trading days (~4 weeks) -n_total = n_historical + n_forecast +# Data — stock price with ~3-month history and 4-week forecast +n_historical = 60 +n_forecast = 20 +dates = pd.date_range(start="2025-01-01", periods=n_historical + n_forecast, freq="B") -dates = pd.date_range(start="2025-01-01", periods=n_total, freq="B") # Business days - -# Generate historical stock prices with trend and volatility t = np.arange(n_historical) -base_price = 150 -trend = 0.15 * t # Slight upward trend -volatility = 2.5 * np.sin(2 * np.pi * t / 20) # 20-day cycles -noise = np.random.normal(0, 1.5, n_historical) -historical_prices = base_price + trend + volatility + noise - -# Generate forecast with increasing uncertainty -t_forecast = np.arange(n_historical, n_total) -trend_forecast = base_price + 0.15 * t_forecast -seasonality_forecast = 2.5 * np.sin(2 * np.pi * t_forecast / 20) -forecast_prices = trend_forecast + seasonality_forecast - -# Confidence intervals widen over forecast horizon -forecast_horizon = np.arange(1, n_forecast + 1) -std_base = 1.5 -std_growth = std_base * np.sqrt(forecast_horizon) +historical_prices = 150 + 0.15 * t + 2.5 * np.sin(2 * np.pi * t / 20) + np.random.normal(0, 1.5, n_historical) + +t_fc = np.arange(n_historical, n_historical + n_forecast) +forecast_prices = 150 + 0.15 * t_fc + 2.5 * np.sin(2 * np.pi * t_fc / 20) +horizon = np.arange(1, n_forecast + 1) +std_growth = 1.5 * np.sqrt(horizon) lower_95 = forecast_prices - 1.96 * std_growth upper_95 = forecast_prices + 1.96 * std_growth lower_80 = forecast_prices - 1.28 * std_growth upper_80 = forecast_prices + 1.28 * std_growth -# Create DataFrame -df = pd.DataFrame( +# Wide-form for CI bands; long-form for seaborn's data-aware lineplot +df_wide = pd.DataFrame( { "date": dates, "actual": list(historical_prices) + [np.nan] * n_forecast, @@ -71,7 +59,14 @@ } ) -# Configure seaborn theme with theme-adaptive colors +long_data = pd.concat( + [ + df_wide[["date", "actual"]].rename(columns={"actual": "price"}).assign(series="Historical"), + df_wide[["date", "forecast"]].rename(columns={"forecast": "price"}).assign(series="Forecast"), + ] +).dropna() + +# Configure seaborn theme sns.set_theme( style="ticks", rc={ @@ -89,52 +84,60 @@ }, ) -# Create figure +# Plot fig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG) ax.set_facecolor(PAGE_BG) -# Plot confidence intervals (95% lighter, 80% darker) -ax.fill_between(df["date"], df["lower_95"], df["upper_95"], alpha=0.15, color=COLOR_FORECAST, label="95% Confidence") -ax.fill_between(df["date"], df["lower_80"], df["upper_80"], alpha=0.25, color=COLOR_FORECAST, label="80% Confidence") - -# Plot historical data -ax.plot(df["date"], df["actual"], color=COLOR_HISTORICAL, linewidth=3, label="Historical", zorder=3) - -# Plot forecast with dashed line -ax.plot( - df[df["forecast"].notna()]["date"], - df[df["forecast"].notna()]["forecast"], - color=COLOR_FORECAST, +# Confidence interval bands (95% lightest, 80% more opaque — nested) +ax.fill_between(df_wide["date"], df_wide["lower_95"], df_wide["upper_95"], alpha=0.15, color=COLOR_FORECAST) +ax.fill_between(df_wide["date"], df_wide["lower_80"], df_wide["upper_80"], alpha=0.28, color=COLOR_FORECAST) + +# Seaborn lineplot — idiomatic long-form API with hue + style + dashes +sns.lineplot( + data=long_data, + x="date", + y="price", + hue="series", + style="series", + palette={"Historical": COLOR_HISTORICAL, "Forecast": COLOR_FORECAST}, + dashes={"Historical": (1, 0), "Forecast": (6, 2)}, linewidth=3, - linestyle="--", - label="Forecast", - zorder=3, + ax=ax, + legend=False, ) -# Add vertical line at forecast start -forecast_start = dates[n_historical - 1] -ax.axvline(x=forecast_start, color=INK_SOFT, linestyle=":", linewidth=1.5, alpha=0.5) +# Forecast boundary marker +ax.axvline(x=dates[n_historical - 1], color=INK_SOFT, linestyle=":", linewidth=1.5, alpha=0.5) -# Styling +# Style ax.set_title( - "timeseries-forecast-uncertainty · seaborn · anyplot.ai", fontsize=24, fontweight="medium", color=INK, pad=20 + "timeseries-forecast-uncertainty · python · seaborn · anyplot.ai", + fontsize=24, + fontweight="medium", + color=INK, + pad=20, ) ax.set_xlabel("Date", fontsize=20, color=INK) ax.set_ylabel("Stock Price ($)", fontsize=20, color=INK) ax.tick_params(axis="both", labelsize=16, colors=INK_SOFT) -# Remove top and right spines -ax.spines["top"].set_visible(False) -ax.spines["right"].set_visible(False) +sns.despine(ax=ax) ax.spines["left"].set_color(INK_SOFT) ax.spines["bottom"].set_color(INK_SOFT) -# Subtle grid on y-axis only ax.yaxis.grid(True, alpha=0.15, linewidth=0.8, color=INK) ax.set_axisbelow(True) -# Legend -ax.legend(fontsize=16, loc="upper left", framealpha=1.0, fancybox=False, edgecolor=INK_SOFT) +# Combined legend: line handles + CI band patches +legend_elements = [ + Line2D([0], [0], color=COLOR_HISTORICAL, linewidth=3, label="Historical"), + Line2D([0], [0], color=COLOR_FORECAST, linewidth=3, linestyle=(0, (6, 2)), label="Forecast"), + Patch(facecolor=COLOR_FORECAST, alpha=0.28, label="80% Confidence"), + Patch(facecolor=COLOR_FORECAST, alpha=0.15, label="95% Confidence"), +] +ax.legend(handles=legend_elements, fontsize=16, loc="upper left", framealpha=1.0, fancybox=False, edgecolor=INK_SOFT) plt.tight_layout() + +# Save plt.savefig(f"plot-{THEME}.png", dpi=300, bbox_inches="tight", facecolor=PAGE_BG) From 708b48d289be04e298ed79cdf632040e606b35be Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 13:15:48 +0000 Subject: [PATCH 2/4] chore(seaborn): add metadata for timeseries-forecast-uncertainty --- .../metadata/python/seaborn.yaml | 239 +----------------- 1 file changed, 9 insertions(+), 230 deletions(-) diff --git a/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml b/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml index 48dca0d764..cf839a10c5 100644 --- a/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml +++ b/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml @@ -1,10 +1,13 @@ +# Per-library metadata for seaborn implementation of timeseries-forecast-uncertainty +# Auto-generated by impl-generate.yml + library: seaborn language: python specification_id: timeseries-forecast-uncertainty created: '2026-01-07T16:28:34Z' -updated: '2026-05-16T22:34:02Z' -generated_by: claude-haiku -workflow_run: 25974439026 +updated: '2026-05-19T13:15:47Z' +generated_by: claude-sonnet +workflow_run: 26099068645 issue: 3188 language_version: 3.13.13 library_version: 0.13.2 @@ -12,231 +15,7 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/timeserie preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/seaborn/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: 90 +quality_score: null review: - strengths: - - Perfect visual quality across all dimensions (text legibility, layout, palette - compliance, no overlap) - - Excellent theme adaptation with proper chrome switching while maintaining data - color consistency - - Strong visual storytelling through confidence band widening and color hierarchy - - Robust code structure with proper reproducibility and clean imports - - All spec requirements met comprehensively - - Realistic, well-chosen example data demonstrating the plot type effectively - - Proper use of seaborn theme system for systematic color management - weaknesses: - - Design excellence could be elevated through more distinctive library-specific - features or advanced visualization techniques - image_description: |- - Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) - correct, not pure white - Chrome: Title (24pt), axis labels (20pt), tick labels (16pt) all in dark text and clearly readable - Data: Historical line in green (#009E73), forecast line in orange dashed (#D55E00), confidence bands in orange with nested alpha (0.25 for 80%, 0.15 for 95%) - Grid: Subtle y-axis only with low alpha (0.15) - Legend: Clean and well-positioned in upper left with descriptive labels - Spines: L-shaped (top/right removed) - Legibility verdict: PASS - all elements readable - - Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) - correct, not pure black - Chrome: Title, axis labels, tick labels now in light text (#F0EFE8 and #B8B7B0) and clearly readable against dark background - Data: Historical green (#009E73) and forecast orange (#D55E00) colors are identical to light render - only chrome has changed - Grid: Subtle gridlines properly styled - Vertical line: Dotted line at forecast boundary clearly visible - Legibility verdict: PASS - no dark-on-dark failures, all text light-colored and readable, brand green remains clearly visible - - Both renders demonstrate perfect theme adaptation: data colors constant, chrome properly theme-dependent. - criteria_checklist: - visual_quality: - score: 30 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 8 - max: 8 - passed: true - comment: All font sizes explicitly set (24pt, 20pt, 16pt); perfectly readable - in both light and dark themes - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: No overlapping elements; legend well-positioned; date labels properly - spaced - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Historical line (3px), forecast line (3px dashed), confidence bands - (alpha-blended) optimally visible - - id: VQ-04 - name: Color Accessibility - score: 2 - max: 2 - passed: true - comment: Okabe-Ito palette (green vs. orange) provides excellent contrast; - CVD-safe - - id: VQ-05 - name: Layout & Canvas - score: 4 - max: 4 - passed: true - comment: Plot fills 60-70% of canvas with balanced margins; no wasted space - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: 'Descriptive labels with units: ''Date'' and ''Stock Price ($)''' - - id: VQ-07 - name: Palette Compliance - score: 2 - max: 2 - passed: true - comment: 'First series #009E73, second #D55E00; backgrounds #FAF8F1 light - / #1A1A17 dark; data colors identical in both themes' - design_excellence: - score: 13 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 5 - max: 8 - passed: true - comment: Intentional color hierarchy with nested alpha-blended confidence - bands; professional polish above defaults - - id: DE-02 - name: Visual Refinement - score: 4 - max: 6 - passed: true - comment: L-shaped spines, subtle y-axis grid, generous whitespace, refined - legend; strong attention to detail - - id: DE-03 - name: Data Storytelling - score: 4 - max: 6 - passed: true - comment: Visual hierarchy with solid vs. dashed lines; band widening tells - story of increasing uncertainty - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: 'Correct: time series with forecast and dual confidence intervals' - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: 'All features present: historical, forecast, 80%/95% bands, boundary - marker, legend' - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: Date and stock price correctly mapped; all data visible - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Title format correct; legend labels match data - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: 'Shows all aspects: trend, volatility, forecast, dual confidence - levels, boundary condition' - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Stock price forecasting is real-world, neutral, plausible scenario - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: Realistic prices ($145-175); correct business day frequency; mathematically - correct CI expansion - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: Linear flow; no unnecessary functions/classes - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: np.random.seed(42) set; deterministic - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: 'All imports used: os, matplotlib, numpy, pandas, seaborn' - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Clean, Pythonic, well-organized; no fake functionality - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Correct output format (plot-{THEME}.png); current API - library_mastery: - score: 7 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 5 - max: 5 - passed: true - comment: Expertly uses sns.set_theme(), axes-level API, proper legend handling - - id: LM-02 - name: Distinctive Features - score: 2 - max: 5 - passed: false - comment: Uses seaborn theme system and matplotlib fill_between(); solid but - somewhat standard - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - custom-legend - patterns: - - data-generation - - explicit-figure - dataprep: - - time-series - styling: - - alpha-blending - - grid-styling + strengths: [] + weaknesses: [] From e9f8682b3ae1dddb42c469eec98701781ccc29c5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 13:23:21 +0000 Subject: [PATCH 3/4] chore(seaborn): update quality score 88 and review feedback for timeseries-forecast-uncertainty --- .../implementations/python/seaborn.py | 4 +- .../metadata/python/seaborn.yaml | 248 +++++++++++++++++- 2 files changed, 243 insertions(+), 9 deletions(-) diff --git a/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py b/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py index 16b3615393..00ec74aed7 100644 --- a/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py +++ b/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai timeseries-forecast-uncertainty: Time Series Forecast with Uncertainty Band Library: seaborn 0.13.2 | Python 3.13.13 -Quality: 90/100 | Updated: 2026-05-19 +Quality: 88/100 | Updated: 2026-05-19 """ import os diff --git a/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml b/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml index cf839a10c5..ca33fa788c 100644 --- a/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml +++ b/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for seaborn implementation of timeseries-forecast-uncertainty -# Auto-generated by impl-generate.yml - library: seaborn language: python specification_id: timeseries-forecast-uncertainty created: '2026-01-07T16:28:34Z' -updated: '2026-05-19T13:15:47Z' +updated: '2026-05-19T13:23:20Z' generated_by: claude-sonnet workflow_run: 26099068645 issue: 3188 @@ -15,7 +12,244 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/timeserie preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/seaborn/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: null +quality_score: 88 review: - strengths: [] - weaknesses: [] + strengths: + - Expert use of seaborn's hue+style+dashes combo in a single lineplot call — textbook + idiomatic seaborn for multi-series with semantic style differentiation + - Color semantics (green=history, orange=forecast) create an immediately readable + narrative without requiring annotations + - 'Full spec compliance: all required CI bands, boundary marker, and legend elements + correctly implemented' + - 'Statistically sound data: sqrt-horizon uncertainty growth, business-day date + range, realistic stock prices' + - All theme-adaptive chrome tokens correctly threaded throughout (title, labels, + ticks, spines, grid, legend) + - Widening CI bands create a natural focal point and visual hierarchy that guides + the viewer toward the forecast region + weaknesses: + - 'CI bands are nearly invisible in dark mode: alpha=0.15 for the 95% band blends + orange with #1A1A17 to ~#362414 (dark brownish), essentially indistinguishable + from the background; alpha=0.28 for the 80% band is visible but muddy. Use theme-adaptive + alpha values: ALPHA_95 = 0.15 if THEME == ''light'' else 0.35, ALPHA_80 = 0.28 + if THEME == ''light'' else 0.50' + - 'Canvas size deviation: figsize=(16, 9) at dpi=300 produces 4800x2700 px — the + style guide and library spec call for figsize=(8, 4.5) at dpi=400 for the canonical + 3200x1800 output' + - 'Design excellence ceiling: no focal-point annotation (e.g., a small label for + the forecast boundary date), no subtitle or secondary descriptive element that + would elevate from ''strong default'' to ''publication-ready''' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white #FAF8F1 — correct, not pure white + Chrome: Title "timeseries-forecast-uncertainty · python · seaborn · anyplot.ai" in dark ink (~fontsize 24), clearly readable. X-axis label "Date" and Y-axis label "Stock Price ($)" in dark ink, readable. Tick labels in INK_SOFT, readable. Legend in upper-left with warm elevated background. + Data: Solid green (#009E73) historical line ~$148-$161, dashed orange (#D55E00) forecast line, nested orange CI bands (80% more opaque at alpha=0.28, 95% lighter at alpha=0.15) clearly visible against warm background. Vertical dotted boundary line at forecast start. + Legibility verdict: PASS + + Dark render (plot-dark.png): + Background: Warm near-black #1A1A17 — correct, not pure black + Chrome: Title and all text elements flip to light ink (#F0EFE8/#B8B7B0) — all text is clearly readable. No dark-on-dark failures observed for any text element. + Data: Green (#009E73) and orange (#D55E00) data colors are identical to light render (Okabe-Ito positions 1-2 unchanged). CI bands suffer significant visibility loss: alpha=0.15 orange on #1A1A17 blends to ~#362414 (near-imperceptible dark brownish); alpha=0.28 produces ~#4F2D11 (visible but muddy). Nesting distinction between 80% and 95% bands substantially reduced compared to light render. + Legibility verdict: PASS for text and lines; PARTIAL FAIL for CI bands — visible but with significantly degraded clarity + criteria_checklist: + visual_quality: + score: 27 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All font sizes explicitly set (title=24, labels=20, ticks=16, legend=16). + Readable in both themes. 'Date' at fontsize=20 slightly generous for a 4-letter + label but acceptable. + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping text or data collisions anywhere. + - id: VQ-03 + name: Element Visibility + score: 4 + max: 6 + passed: false + comment: 'Lines clearly visible in both themes. CI bands severely degraded + in dark mode: alpha=0.15 orange on #1A1A17 blends to ~#362414 (nearly invisible); + alpha=0.28 produces muddy dark brownish. Both bands exist but nesting hierarchy + largely lost in dark.' + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Okabe-Ito palette, CVD-safe green/orange combination. Band distinction + uses alpha (universally readable). + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Good canvas utilization, balanced margins, legend in upper-left doesn't + cover data. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: '''Date'' and ''Stock Price ($)'' with units.' + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'First series #009E73, second #D55E00. Backgrounds #FAF8F1/#1A1A17. + All chrome tokens theme-adaptive.' + design_excellence: + score: 13 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: Intentional color semantics (green=history, orange=forecast), warm + backgrounds, solid vs dashed line contrast. Above defaults but not publication-ready. + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: Despine applied, subtle grid (alpha=0.15), styled legend (fancybox=False, + explicit edgecolor), spines colored with INK_SOFT. + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: 'Clear narrative: green=known/history, orange+widening bands=uncertain + future. Vertical boundary line crisp. Widening CI creates natural focal + point.' + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: 'Correct: time series with historical + forecast + nested 80%/95% + CI bands + vertical transition marker.' + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: 'All present: solid historical, dashed forecast, 80% CI, 95% CI, + boundary marker, legend.' + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: Date on X, Stock Price on Y, all data periods covered. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Correct title format. Legend labels match data series exactly. + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: Upward trend + seasonality in history, widening 80%/95% CI bands, + correct nesting, sqrt(horizon) growth. + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Stock price forecasting with business-day frequency. Neutral, realistic, + comprehensible scenario. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Stock prices ~$148-175 plausible. sqrt(horizon) uncertainty growth + is statistically correct for random-walk forecast. Business days appropriate. + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: Linear imports -> data -> plot -> save, no functions or classes. + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42). + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All imports used (Line2D, Patch for manual legend handles). + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Wide-form + long-form dual DataFrames well-motivated. Clean, no over-engineering. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves as plot-{THEME}.png. + library_mastery: + score: 8 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: 'Expert: hue+style+dashes in one lineplot call, long-form data, sns.set_theme(rc={...}), + sns.despine. Very idiomatic seaborn.' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: hue+style+dashes combo is distinctively seaborn. CI bands require + matplotlib fill_between fallback (seaborn limitation). + verdict: REJECTED +impl_tags: + dependencies: [] + techniques: + - custom-legend + patterns: + - data-generation + - wide-to-long + - explicit-figure + dataprep: + - time-series + styling: + - alpha-blending + - grid-styling From 483bf99608246596eecff50c2985cbf050e4dbd5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 19 May 2026 13:32:03 +0000 Subject: [PATCH 4/4] chore(seaborn): update quality score 90 and review feedback for timeseries-forecast-uncertainty --- .../implementations/python/seaborn.py | 2 +- .../metadata/python/seaborn.yaml | 150 +++++++++--------- 2 files changed, 72 insertions(+), 80 deletions(-) diff --git a/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py b/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py index 00ec74aed7..7970c2c235 100644 --- a/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py +++ b/plots/timeseries-forecast-uncertainty/implementations/python/seaborn.py @@ -1,7 +1,7 @@ """ anyplot.ai timeseries-forecast-uncertainty: Time Series Forecast with Uncertainty Band Library: seaborn 0.13.2 | Python 3.13.13 -Quality: 88/100 | Updated: 2026-05-19 +Quality: 90/100 | Updated: 2026-05-19 """ import os diff --git a/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml b/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml index ca33fa788c..70bd4161ad 100644 --- a/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml +++ b/plots/timeseries-forecast-uncertainty/metadata/python/seaborn.yaml @@ -2,7 +2,7 @@ library: seaborn language: python specification_id: timeseries-forecast-uncertainty created: '2026-01-07T16:28:34Z' -updated: '2026-05-19T13:23:20Z' +updated: '2026-05-19T13:32:03Z' generated_by: claude-sonnet workflow_run: 26099068645 issue: 3188 @@ -12,48 +12,40 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/timeserie preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/timeseries-forecast-uncertainty/python/seaborn/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: 88 +quality_score: 90 review: strengths: - - Expert use of seaborn's hue+style+dashes combo in a single lineplot call — textbook - idiomatic seaborn for multi-series with semantic style differentiation - - Color semantics (green=history, orange=forecast) create an immediately readable - narrative without requiring annotations - - 'Full spec compliance: all required CI bands, boundary marker, and legend elements - correctly implemented' - - 'Statistically sound data: sqrt-horizon uncertainty growth, business-day date - range, realistic stock prices' - - All theme-adaptive chrome tokens correctly threaded throughout (title, labels, - ticks, spines, grid, legend) - - Widening CI bands create a natural focal point and visual hierarchy that guides - the viewer toward the forecast region + - Idiomatic seaborn long-form API with hue+style+dashes for clean multi-series line + styling + - 'Full theme-adaptive chrome: all tokens correctly set for both light and dark + renders' + - 'All spec requirements met: dual CI bands (80%+95%), forecast boundary marker, + distinct line styles, comprehensive legend' + - Realistic self-contained data generation with widening CI bands over forecast + horizon (±1.96σ√t) + - Clean code structure with proper seed, KISS linear flow, and all imports used weaknesses: - - 'CI bands are nearly invisible in dark mode: alpha=0.15 for the 95% band blends - orange with #1A1A17 to ~#362414 (dark brownish), essentially indistinguishable - from the background; alpha=0.28 for the 80% band is visible but muddy. Use theme-adaptive - alpha values: ALPHA_95 = 0.15 if THEME == ''light'' else 0.35, ALPHA_80 = 0.28 - if THEME == ''light'' else 0.50' - - 'Canvas size deviation: figsize=(16, 9) at dpi=300 produces 4800x2700 px — the - style guide and library spec call for figsize=(8, 4.5) at dpi=400 for the canonical - 3200x1800 output' - - 'Design excellence ceiling: no focal-point annotation (e.g., a small label for - the forecast boundary date), no subtitle or secondary descriptive element that - would elevate from ''strong default'' to ''publication-ready''' + - Axis label fontsize=20 slightly disproportionate for short labels 'Date' and 'Stock + Price ($)' on the 4800x2700 canvas — reduce to ~14pt + - CI band visual separation slightly compressed in dark render — increase alphas + to 0.20 (95%) and 0.35 (80%) for better differentiation + - Canvas is 4800x2700 (dpi=300, figsize=(16,9)) — exceeds standard 3200x1800; use + dpi=200 or adjust figsize to match standard pixel target image_description: |- Light render (plot-light.png): - Background: Warm off-white #FAF8F1 — correct, not pure white - Chrome: Title "timeseries-forecast-uncertainty · python · seaborn · anyplot.ai" in dark ink (~fontsize 24), clearly readable. X-axis label "Date" and Y-axis label "Stock Price ($)" in dark ink, readable. Tick labels in INK_SOFT, readable. Legend in upper-left with warm elevated background. - Data: Solid green (#009E73) historical line ~$148-$161, dashed orange (#D55E00) forecast line, nested orange CI bands (80% more opaque at alpha=0.28, 95% lighter at alpha=0.15) clearly visible against warm background. Vertical dotted boundary line at forecast start. + Background: Warm off-white #FAF8F1 — correct light surface token + Chrome: Title "timeseries-forecast-uncertainty · python · seaborn · anyplot.ai" in dark ink, readable. Axis labels "Date" (x) and "Stock Price ($)" (y) in dark INK. Tick labels in INK_SOFT. All text clearly visible against light background. + Data: Historical line in #009E73 (brand green, Okabe-Ito position 1) as solid line. Forecast in #D55E00 (vermillion, Okabe-Ito position 2) as dashed line. Two nested CI bands in same vermillion family (80% alpha=0.28, 95% alpha=0.15). Vertical dotted boundary line at forecast start. Legibility verdict: PASS Dark render (plot-dark.png): - Background: Warm near-black #1A1A17 — correct, not pure black - Chrome: Title and all text elements flip to light ink (#F0EFE8/#B8B7B0) — all text is clearly readable. No dark-on-dark failures observed for any text element. - Data: Green (#009E73) and orange (#D55E00) data colors are identical to light render (Okabe-Ito positions 1-2 unchanged). CI bands suffer significant visibility loss: alpha=0.15 orange on #1A1A17 blends to ~#362414 (near-imperceptible dark brownish); alpha=0.28 produces ~#4F2D11 (visible but muddy). Nesting distinction between 80% and 95% bands substantially reduced compared to light render. - Legibility verdict: PASS for text and lines; PARTIAL FAIL for CI bands — visible but with significantly degraded clarity + Background: Warm near-black #1A1A17 — correct dark surface token + Chrome: Title, axis labels, and tick labels render in light text (F0EFE8/B8B7B0) — all readable against dark background. Legend background uses elevated dark token #242420. No dark-on-dark text failures observed. + Data: Historical green line and forecast orange line identical in color to light render (only chrome flips). CI bands appear as dark brownish-orange (95%) and brighter orange (80%) — distinguishable though slightly compressed contrast compared to light render. + Legibility verdict: PASS criteria_checklist: visual_quality: - score: 27 + score: 29 max: 30 items: - id: VQ-01 @@ -61,51 +53,47 @@ review: score: 7 max: 8 passed: true - comment: All font sizes explicitly set (title=24, labels=20, ticks=16, legend=16). - Readable in both themes. 'Date' at fontsize=20 slightly generous for a 4-letter - label but acceptable. + comment: All font sizes explicitly set (title=24, labels=20, ticks=16); proportional + for large canvas but axis labels slightly generous for short labels - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text or data collisions anywhere. + comment: No overlapping text or data elements in either render - id: VQ-03 name: Element Visibility - score: 4 + score: 6 max: 6 - passed: false - comment: 'Lines clearly visible in both themes. CI bands severely degraded - in dark mode: alpha=0.15 orange on #1A1A17 blends to ~#362414 (nearly invisible); - alpha=0.28 produces muddy dark brownish. Both bands exist but nesting hierarchy - largely lost in dark.' + passed: true + comment: Lines and CI bands well-sized and clearly visible; appropriate alpha + for overlapping bands - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Okabe-Ito palette, CVD-safe green/orange combination. Band distinction - uses alpha (universally readable). + comment: Okabe-Ito green/vermillion pair is CVD-safe; series also distinguished + by line style - id: VQ-05 name: Layout & Canvas score: 4 max: 4 passed: true - comment: Good canvas utilization, balanced margins, legend in upper-left doesn't - cover data. + comment: Good canvas utilization, balanced margins, tight_layout applied - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: '''Date'' and ''Stock Price ($)'' with units.' + comment: Y-axis has units (Stock Price ($)), X-axis is Date - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'First series #009E73, second #D55E00. Backgrounds #FAF8F1/#1A1A17. - All chrome tokens theme-adaptive.' + comment: 'First series #009E73, second #D55E00 (Okabe-Ito order); backgrounds + #FAF8F1/#1A1A17; all chrome tokens theme-adaptive' design_excellence: score: 13 max: 20 @@ -115,23 +103,24 @@ review: score: 5 max: 8 passed: true - comment: Intentional color semantics (green=history, orange=forecast), warm - backgrounds, solid vs dashed line contrast. Above defaults but not publication-ready. + comment: 'Above defaults: two-color Okabe-Ito scheme, solid/dashed distinction, + nested CI bands, vertical boundary marker, clean legend. Not publication-ready + — CI band differentiation weak in dark render' - id: DE-02 name: Visual Refinement score: 4 max: 6 passed: true - comment: Despine applied, subtle grid (alpha=0.15), styled legend (fancybox=False, - explicit edgecolor), spines colored with INK_SOFT. + comment: Spines despined, subtle y-axis-only grid (alpha=0.15), elevated legend + background, fancybox=False - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: 'Clear narrative: green=known/history, orange+widening bands=uncertain - future. Vertical boundary line crisp. Widening CI creates natural focal - point.' + comment: Growing uncertainty bands communicate forecast uncertainty naturally; + vertical divider clearly marks transition; color+linestyle reinforcement + makes narrative immediately readable spec_compliance: score: 15 max: 15 @@ -141,27 +130,28 @@ review: score: 5 max: 5 passed: true - comment: 'Correct: time series with historical + forecast + nested 80%/95% - CI bands + vertical transition marker.' + comment: Correct time-series forecast with uncertainty; historical line, forecast + line, dual CI bands all present - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: 'All present: solid historical, dashed forecast, 80% CI, 95% CI, - boundary marker, legend.' + comment: Solid historical line, dashed forecast, 80%+95% CI bands, vertical + boundary marker, semi-transparent fills, comprehensive legend - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Date on X, Stock Price on Y, all data periods covered. + comment: Date on x-axis, stock price on y-axis, all data periods visible - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Correct title format. Legend labels match data series exactly. + comment: 'Title exact format; legend labels: Historical, Forecast, 80% Confidence, + 95% Confidence' data_quality: score: 15 max: 15 @@ -171,22 +161,21 @@ review: score: 6 max: 6 passed: true - comment: Upward trend + seasonality in history, widening 80%/95% CI bands, - correct nesting, sqrt(horizon) growth. + comment: 'All aspects shown: trending historical with noise, forecast continuation, + widening CI bands, clear transition' - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Stock price forecasting with business-day frequency. Neutral, realistic, - comprehensible scenario. + comment: Stock price forecasting — neutral, comprehensible real-world scenario - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Stock prices ~$148-175 plausible. sqrt(horizon) uncertainty growth - is statistically correct for random-walk forecast. Business days appropriate. + comment: ~$150 stock with gentle upward trend; CI widths grow proportionally + (±1.96σ√t) — all values plausible code_quality: score: 10 max: 10 @@ -196,31 +185,33 @@ review: score: 3 max: 3 passed: true - comment: Linear imports -> data -> plot -> save, no functions or classes. + comment: 'Linear flow: imports → tokens → data → theme → plot → style → legend + → save; no functions or classes' - 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 (Line2D, Patch for manual legend handles). + comment: 'All 7 imports used: os, plt, np, pd, sns, Line2D, Patch' - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Wide-form + long-form dual DataFrames well-motivated. Clean, no over-engineering. + comment: Clean, Pythonic; wide-form for CI bands + long-form for seaborn lineplot + is sensible separation - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot-{THEME}.png. + comment: Saves as plot-{THEME}.png; current seaborn/matplotlib API library_mastery: score: 8 max: 10 @@ -230,16 +221,17 @@ review: score: 5 max: 5 passed: true - comment: 'Expert: hue+style+dashes in one lineplot call, long-form data, sns.set_theme(rc={...}), - sns.despine. Very idiomatic seaborn.' + comment: 'Exemplary seaborn: long-form data with hue+style+dashes dict; sns.set_theme() + with rc; sns.despine()' - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: hue+style+dashes combo is distinctively seaborn. CI bands require - matplotlib fill_between fallback (seaborn limitation). - verdict: REJECTED + comment: Seaborn-distinctive dashes parameter for per-hue line styles and + theme/rc system; CI bands use matplotlib fill_between (correct — seaborn + CI is for statistical aggregates) + verdict: APPROVED impl_tags: dependencies: [] techniques: