From e694c7f7b9cf7d17a4d163125253eb8175fce3ab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Apr 2026 07:05:51 +0000 Subject: [PATCH 1/3] chore(altair): add metadata for rose-basic --- .../implementations/python/altair.py | 183 ++++----------- plots/rose-basic/metadata/python/altair.yaml | 222 ++---------------- 2 files changed, 63 insertions(+), 342 deletions(-) diff --git a/plots/rose-basic/implementations/python/altair.py b/plots/rose-basic/implementations/python/altair.py index dc57813d28..4ae48cc498 100644 --- a/plots/rose-basic/implementations/python/altair.py +++ b/plots/rose-basic/implementations/python/altair.py @@ -1,139 +1,89 @@ -""" pyplots.ai +"""anyplot.ai rose-basic: Basic Rose Chart -Library: altair 6.0.0 | Python 3.13.11 -Quality: 92/100 | Created: 2025-12-23 +Library: altair | Python 3.13 +Quality: pending | Created: 2026-04-30 """ +import os + import altair as alt import numpy as np import pandas as pd -# Data - Monthly rainfall in mm (cyclical 12-month pattern) +# Theme +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" + +# Data - Monthly rainfall in mm (12-month cyclical pattern) months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] rainfall = [78, 52, 68, 45, 35, 28, 22, 30, 55, 85, 92, 88] n = len(months) - -# Calculate angles starting at 12 o'clock (top) and going clockwise -# -90 degrees offset to start at top, then proceeding clockwise angle_step = 360 / n start_angles = [-90 + i * angle_step for i in range(n)] end_angles = [-90 + (i + 1) * angle_step for i in range(n)] -# Create DataFrame with explicit angles df = pd.DataFrame( - { - "month": months, - "value": rainfall, - "order": range(n), - "startAngle": np.radians(start_angles), - "endAngle": np.radians(end_angles), - } + {"month": months, "value": rainfall, "startAngle": np.radians(start_angles), "endAngle": np.radians(end_angles)} ) -# Max value for radius scaling - use 100 for nicer gridline values max_val = 100 +chart_radius = 460 -# Color palette - colorblind-friendly distinct colors -colors = [ - "#306998", # Python Blue (Jan) - "#FFD43B", # Python Yellow (Feb) - "#4ECDC4", # Teal (Mar) - "#FF6B6B", # Coral (Apr) - "#95E1D3", # Mint (May) - "#F38181", # Salmon (Jun) - "#A8D5BA", # Sage (Jul) - "#FFC93C", # Gold (Aug) - "#5D9CEC", # Sky Blue (Sep) - "#AC92EB", # Lavender (Oct) - "#EC87C0", # Pink (Nov) - "#48CFAD", # Seafoam (Dec) -] - -# Create radial gridlines data (concentric circles at 25, 50, 75, 100 mm) +# Radial gridlines at 25, 50, 75, 100 mm grid_values = [25, 50, 75, 100] -grid_data = pd.DataFrame({"value": grid_values, "label": [f"{v}" for v in grid_values]}) +grid_data = pd.DataFrame({"value": grid_values}) -# Chart radius for the radial visualization -chart_radius = 450 - -# Radial gridlines - concentric circles using mark_arc gridlines = ( alt.Chart(grid_data) - .mark_arc(filled=False, stroke="#cccccc", strokeWidth=1.5, strokeDash=[6, 4]) + .mark_arc(filled=False, stroke=INK_SOFT, strokeWidth=1.0, strokeOpacity=0.35, strokeDash=[6, 4]) .encode( - theta=alt.value(2 * np.pi), # Full circle + theta=alt.value(2 * np.pi), radius=alt.Radius("value:Q", scale=alt.Scale(type="linear", domain=[0, max_val], range=[0, chart_radius])), ) ) -# Grid labels positioned at 3 o'clock position (right side) to avoid overlap with data +# Grid labels at 3 o'clock position grid_label_data = pd.DataFrame( - { - "value": grid_values, - "label": [f"{v} mm" for v in grid_values], - # Position labels at 3 o'clock (right) - angle = 0 degrees - "theta": [0.0] * len(grid_values), - } + {"value": grid_values, "label": [f"{v} mm" for v in grid_values], "theta": [0.0] * len(grid_values)} ) grid_labels = ( alt.Chart(grid_label_data) - .mark_text(fontSize=18, fontWeight="bold", dx=12, color="#666666", align="left", baseline="middle") + .mark_text(fontSize=18, dx=10, align="left", baseline="middle") .encode( theta=alt.Theta("theta:Q"), radius=alt.Radius("value:Q", scale=alt.Scale(type="linear", domain=[0, max_val], range=[0, chart_radius])), text="label:N", + color=alt.value(INK_SOFT), ) ) -# Rose chart using mark_arc with explicit angles to start at 12 o'clock +# Rose chart segments — viridis colormap for value-based color encoding (12 categories) rose = ( alt.Chart(df) - .mark_arc(stroke="#ffffff", strokeWidth=2, innerRadius=0) + .mark_arc(stroke=PAGE_BG, strokeWidth=2, innerRadius=0) .encode( theta=alt.Theta("startAngle:Q", stack=None), theta2=alt.Theta2("endAngle:Q"), radius=alt.Radius("value:Q", scale=alt.Scale(type="linear", domain=[0, max_val], range=[0, chart_radius])), - color=alt.Color( - "month:N", - scale=alt.Scale(domain=months, range=colors), - legend=None, # Legend disabled to control canvas size; colors are self-explanatory with labels - ), + color=alt.Color("value:Q", scale=alt.Scale(scheme="viridis"), legend=None), tooltip=[alt.Tooltip("month:N", title="Month"), alt.Tooltip("value:Q", title="Rainfall (mm)")], ) ) -# Calculate label positions - midpoint angle for each segment -mid_angles = [(-90 + (i + 0.5) * angle_step) for i in range(n)] +# Value labels near segment tips +mid_angles = [-90 + (i + 0.5) * angle_step for i in range(n)] mid_angles_rad = np.radians(mid_angles) -# For small values that cluster together (Jun-Aug: 28, 22, 30), push labels further out -# to prevent crowding; larger values can have labels closer to segment edge -label_radii = [] -for v in rainfall: - if v < 35: - # Small segments - push label further outside segment - label_radii.append(max(v * 1.35, 45)) - else: - # Normal segments - position just outside - label_radii.append(v * 1.15) - -# Create label data with theta and radius for polar positioning -label_data = pd.DataFrame({"month": months, "value": rainfall, "theta": mid_angles_rad, "labelRadius": label_radii}) +label_radii = [max(v * 1.35, 45) if v < 35 else v * 1.15 for v in rainfall] -# Create month labels positioned at outer edge of chart -month_label_data = pd.DataFrame( - { - "month": months, - "theta": mid_angles_rad, - "labelRadius": [115] * n, # Just outside the 100mm gridline - } -) +label_data = pd.DataFrame({"month": months, "value": rainfall, "theta": mid_angles_rad, "labelRadius": label_radii}) -# Text labels showing values on each segment using polar coordinates -text = ( +value_labels = ( alt.Chart(label_data) .mark_text(fontSize=20, fontWeight="bold") .encode( @@ -142,11 +92,13 @@ "labelRadius:Q", scale=alt.Scale(type="linear", domain=[0, max_val], range=[0, chart_radius]) ), text=alt.Text("value:Q"), - color=alt.value("#333333"), + color=alt.value(INK), ) ) -# Month labels at outer edge +# Month labels at outer edge — just beyond the 100 mm gridline +month_label_data = pd.DataFrame({"month": months, "theta": mid_angles_rad, "labelRadius": [115.0] * n}) + month_labels = ( alt.Chart(month_label_data) .mark_text(fontSize=22, fontWeight="bold") @@ -156,66 +108,23 @@ "labelRadius:Q", scale=alt.Scale(type="linear", domain=[0, max_val], range=[0, chart_radius]) ), text=alt.Text("month:N"), - color=alt.value("#333333"), + color=alt.value(INK), ) ) # Combine all layers chart = ( - alt.layer(gridlines, grid_labels, rose, text, month_labels) - .properties(title=alt.Title(text="rose-basic · altair · pyplots.ai", fontSize=32, anchor="middle", offset=15)) - .configure_view(strokeWidth=0) + alt.layer(gridlines, grid_labels, rose, value_labels, month_labels) + .properties( + width=1200, + height=1200, + background=PAGE_BG, + title=alt.Title(text="rose-basic · altair · anyplot.ai", fontSize=32, anchor="middle", offset=20, color=INK), + ) + .configure_view(strokeWidth=0, fill=PAGE_BG) .configure_axis(grid=False, domain=False, ticks=False, labels=False, title=None) ) -# Save chart - Altair radial charts position content in upper portion -# Use high scale factor to ensure quality, then crop to center the content -chart.save("plot_raw.png", scale_factor=3.0) -chart.save("plot.html") - -# Post-process: crop to center the radial chart and resize to 3600x3600 (square format) -from PIL import Image - - -img = Image.open("plot_raw.png") -width, height = img.size - -# Altair radial charts center content horizontally but place it in the upper portion vertically -# The radial center is approximately at 36% from the top of the rendered image -content_center_y = int(height * 0.36) -content_center_x = width // 2 - -# Use a crop size that captures all content including outer month labels with some padding -crop_size = min(width, int(height * 0.80)) - -# Center the crop on the content -left = content_center_x - crop_size // 2 -top = content_center_y - crop_size // 2 -right = left + crop_size -bottom = top + crop_size - -# Adjust if crop extends beyond image boundaries -if left < 0: - left = 0 - right = crop_size -if top < 0: - top = 0 - bottom = crop_size -if right > width: - right = width - left = width - crop_size -if bottom > height: - bottom = height - top = height - crop_size - -cropped = img.crop((left, top, right, bottom)) - -# Resize to target 3600x3600 -final = cropped.resize((3600, 3600), Image.Resampling.LANCZOS) -final.save("plot.png") - -# Clean up temp file -import os - - -os.remove("plot_raw.png") +# Save +chart.save(f"plot-{THEME}.png", scale_factor=3.0) +chart.save(f"plot-{THEME}.html") diff --git a/plots/rose-basic/metadata/python/altair.yaml b/plots/rose-basic/metadata/python/altair.yaml index d829462235..8122875ad8 100644 --- a/plots/rose-basic/metadata/python/altair.yaml +++ b/plots/rose-basic/metadata/python/altair.yaml @@ -1,209 +1,21 @@ +# Per-library metadata for altair implementation of rose-basic +# Auto-generated by impl-generate.yml + library: altair +language: python specification_id: rose-basic created: '2025-12-23T19:45:47Z' -updated: '2025-12-23T20:20:47Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 20469994919 -issue: 0 -python_version: 3.13.11 -library_version: 6.0.0 -preview_url: https://storage.googleapis.com/anyplot-images/plots/rose-basic/altair/plot.png -preview_html: https://storage.googleapis.com/anyplot-images/plots/rose-basic/altair/plot.html -quality_score: 92 -impl_tags: - dependencies: - - pillow - techniques: - - html-export - - layer-composition - patterns: - - data-generation - - iteration-over-groups - dataprep: [] - styling: [] +updated: '2026-04-30T07:05:51Z' +generated_by: claude-sonnet +workflow_run: 25151891021 +issue: 1003 +python_version: 3.13.13 +library_version: 6.1.0 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-dark.png +preview_html_light: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-light.html +preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-dark.html +quality_score: null review: - strengths: - - Proper rose chart implementation with radial segments where radius represents - values - - Colorblind-friendly distinct color palette for all 12 months - - Radial gridlines at 25/50/75/100 mm with labels for scale reference - - Value labels positioned intelligently to avoid crowding on smaller segments - - Correct title format following pyplots.ai convention - weaknesses: - - Chart occupies only upper-left quadrant of canvas leaving excessive whitespace - in lower portion - - Month labels missing from outer edge - only values shown without category context - on chart itself - - Legend placed far to the right isolated from the chart rather than integrated - image_description: The plot displays a rose chart (Nightingale/coxcomb diagram) - showing monthly rainfall data in a radial format. The chart features 12 colorful - wedge segments representing each month, with radius proportional to rainfall values - (ranging from 22mm for July to 92mm for November). Colors used include Python - blue (Jan), yellow (Feb), teal (Mar), coral (Apr), mint (May), salmon (Jun), sage - (Jul), gold (Aug), sky blue (Sep), lavender (Oct), pink (Nov), and seafoam (Dec). - Two dashed concentric gridlines appear at approximately 75mm and 100mm levels - with labels on the right side. Value labels (22-92) are positioned near each segment. - A legend in the upper right lists all months with their corresponding colors. - The title "rose-basic · altair · pyplots.ai" appears at the top. The chart is - positioned in the upper portion of the canvas with significant empty space below. - criteria_checklist: - visual_quality: - score: 35 - max: 40 - items: - - id: VQ-01 - name: Text Legibility - score: 10 - max: 10 - passed: true - comment: Title, value labels, and legend text are all clearly readable at - full size - - id: VQ-02 - name: No Overlap - score: 8 - max: 8 - passed: true - comment: No overlapping text elements; value labels well positioned - - id: VQ-03 - name: Element Visibility - score: 8 - max: 8 - passed: true - comment: All 12 wedge segments clearly visible with appropriate sizing - - id: VQ-04 - name: Color Accessibility - score: 5 - max: 5 - passed: true - comment: Colorblind-friendly palette with distinct hues for each month - - id: VQ-05 - name: Layout Balance - score: 2 - max: 5 - passed: false - comment: Chart occupies upper-left area with excessive whitespace below; not - centered - - id: VQ-06 - name: Axis Labels - score: 0 - max: 2 - passed: true - comment: N/A for radial chart without traditional axes (gridlines provide - scale) - - id: VQ-07 - name: Grid & Legend - score: 2 - max: 2 - passed: true - comment: Subtle dashed gridlines at 75mm and 100mm; legend well formatted - spec_compliance: - score: 25 - max: 25 - items: - - id: SC-01 - name: Plot Type - score: 8 - max: 8 - passed: true - comment: Correct rose/coxcomb chart type with radial segments - - id: SC-02 - name: Data Mapping - score: 5 - max: 5 - passed: true - comment: Values correctly mapped to segment radius - - id: SC-03 - name: Required Features - score: 5 - max: 5 - passed: true - comment: 'All spec requirements met: cyclical data, radial gridlines, 12-month - pattern' - - id: SC-04 - name: Data Range - score: 3 - max: 3 - passed: true - comment: All values visible within gridline scale (0-100mm) - - id: SC-05 - name: Legend Accuracy - score: 2 - max: 2 - passed: true - comment: Legend correctly maps colors to months - - id: SC-06 - name: Title Format - score: 2 - max: 2 - passed: true - comment: Correct format "rose-basic · altair · pyplots.ai" - data_quality: - score: 20 - max: 20 - items: - - id: DQ-01 - name: Feature Coverage - score: 8 - max: 8 - passed: true - comment: 'Shows full variation: low summer values (22-35mm), high autumn/winter - (78-92mm)' - - id: DQ-02 - name: Realistic Context - score: 7 - max: 7 - passed: true - comment: Monthly rainfall pattern is realistic and relatable - - id: DQ-03 - name: Appropriate Scale - score: 5 - max: 5 - passed: true - comment: Values in plausible rainfall range (22-92mm) - code_quality: - score: 9 - 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: Deterministic data (no random generation) - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: All imports used (altair, numpy, pandas, PIL for post-processing) - - id: CQ-04 - name: No Deprecated API - score: 1 - max: 1 - passed: true - comment: Uses current Altair API - - id: CQ-05 - name: Output Correct - score: 0 - max: 1 - passed: false - comment: Creates intermediate file plot_raw.png before final plot.png - library_features: - score: 3 - max: 5 - items: - - id: LF-01 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: Good use of mark_arc, layered composition, and polar coordinates; - however post-processing with PIL for cropping detracts from pure Altair - solution - verdict: APPROVED + strengths: [] + weaknesses: [] From 971ad19e91d0f0f9271906a2da86ef71a2f094f8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Apr 2026 07:12:28 +0000 Subject: [PATCH 2/3] chore(altair): update quality score 86 and review feedback for rose-basic --- .../implementations/python/altair.py | 6 +- plots/rose-basic/metadata/python/altair.yaml | 270 +++++++++++++++++- 2 files changed, 266 insertions(+), 10 deletions(-) diff --git a/plots/rose-basic/implementations/python/altair.py b/plots/rose-basic/implementations/python/altair.py index 4ae48cc498..15a09c180d 100644 --- a/plots/rose-basic/implementations/python/altair.py +++ b/plots/rose-basic/implementations/python/altair.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai rose-basic: Basic Rose Chart -Library: altair | Python 3.13 -Quality: pending | Created: 2026-04-30 +Library: altair 6.1.0 | Python 3.13.13 +Quality: 86/100 | Updated: 2026-04-30 """ import os diff --git a/plots/rose-basic/metadata/python/altair.yaml b/plots/rose-basic/metadata/python/altair.yaml index 8122875ad8..10978ce55f 100644 --- a/plots/rose-basic/metadata/python/altair.yaml +++ b/plots/rose-basic/metadata/python/altair.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for altair implementation of rose-basic -# Auto-generated by impl-generate.yml - library: altair language: python specification_id: rose-basic created: '2025-12-23T19:45:47Z' -updated: '2026-04-30T07:05:51Z' +updated: '2026-04-30T07:12:28Z' generated_by: claude-sonnet workflow_run: 25151891021 issue: 1003 @@ -15,7 +12,266 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/rose-basi preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-dark.html -quality_score: null +quality_score: 86 review: - strengths: [] - weaknesses: [] + strengths: + - Correct rose/Nightingale chart with 12 equal-angle wedge segments and radius proportional + to value + - Viridis continuous colormap applied to value:Q is appropriate and perceptually + uniform, creating effective dual encoding (radius + color) for the rainfall data + - Radial gridlines at 25/50/75/100 mm with unit labels ('75 mm', '100 mm') aid value + estimation as required by spec + - All font sizes explicitly set and appropriate for the 3600x3600 canvas (title + 32px, month labels 22px, value labels 20px, grid labels 18px) + - 'Full theme-adaptive chrome: PAGE_BG, INK, INK_SOFT tokens used correctly; both + light (#FAF8F1) and dark (#1A1A17) backgrounds render correctly' + - Layer composition with alt.layer() combining gridlines + arcs + value labels + + month labels demonstrates idiomatic Altair usage + - Both PNG and HTML saved per Altair interactive library requirements + - 'Title format correct: ''rose-basic · altair · anyplot.ai''' + - Data is deterministic (hardcoded monthly rainfall array), no seed needed + - KISS code structure with no functions or classes + weaknesses: + - 'Design Excellence gap (13/20): viridis colormap is effective but the overall + layout lacks visual polish — consider adding a subtle center dot, refining gridline + labels with an elevated background box, or adding a concise subtitle with the + scenario (''Monthly Rainfall, mm'')' + - 'DE-03 Data Storytelling: the dual encoding (radius + viridis) is good but could + be stronger — consider annotating the peak month (Nov: 92mm) and trough (Jul: + 22mm) with callout labels or brief annotation text to direct the viewer''s attention + to the story' + - 'DE-02 Visual Refinement: the circular gridlines use strokeOpacity=0.35 and strokeDash=[6,4] + which is appropriate, but the overall chrome could be more refined — the plain + title with no subtitle and the sparse grid label positioning at 3 o''clock feels + unfinished' + - 'LM-02 Distinctive Features: while layer-composition and mark_arc with theta2 + are Altair-specific, the implementation could leverage Altair''s selection or + a more distinctive Vega-Lite feature (e.g., a center circle mark, a custom radial + label layout technique) to differentiate it further from a generic polar chart' + - 'VQ-02 minor label crowding: value labels for June (28), July (22), August (30) + cluster near center due to small segment radii; the label placement formula `max(v + * 1.35, 45)` places them all at similar radii which creates a tight cluster at + bottom' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct, not pure white. + Chrome: Title "rose-basic · altair · anyplot.ai" at top center in dark ink, clearly readable. Month labels (Jan–Dec) in bold dark text around the outer ring, readable. Value labels (22–92) near segment tips in bold dark text, readable. Grid labels "75 mm" and "100 mm" at 3 o'clock position in muted INK_SOFT, small but legible. Dashed circular gridlines at 25/50/75/100 mm in subtle gray. + Data: 12 arc segments colored with viridis palette (purple/dark-blue for low values Jun=28, Jul=22; transitioning to teal, green, yellow-green, yellow for high values Nov=92, Dec=88, Oct=85). Segment radii visibly proportional to rainfall values. Winter months (Oct–Jan) dominate with taller, brighter segments. + Legibility verdict: PASS — all text readable against light background; no light-on-light issues. + + Dark render (plot-dark.png): + Background: Near-black (#1A1A17) — correct, not pure black. + Chrome: Title in light text at top, readable. Month labels in light bold text around outer ring, readable. Value labels in light bold text near segment tips, readable. Grid labels "75 mm" and "100 mm" in muted light-gray (INK_SOFT dark token), readable. Dashed circular gridlines visible against dark background. + Data: Viridis segment colors appear identical to the light render — same purple-to-yellow gradient encoding rainfall values. No color shift between themes, data identity preserved. + Legibility verdict: PASS — no dark-on-dark issues; all text uses light INK/INK_SOFT tokens appropriate for dark surface. + criteria_checklist: + visual_quality: + score: 26 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: 'All font sizes explicitly set: title 32px, month labels 22px, value + labels 20px, grid labels 18px. All readable at 3600x3600. Grid labels slightly + small at 18px but within spec.' + - id: VQ-02 + name: No Overlap + score: 5 + max: 6 + passed: true + comment: Mostly no overlap; slight crowding of value labels for small segments + (Jun=28, Jul=22, Aug=30) which cluster at similar radii near center. + - id: VQ-03 + name: Element Visibility + score: 5 + max: 6 + passed: true + comment: Segments clearly visible with viridis coloring. Small segments (Jun/Jul/Aug) + are genuinely small due to low values, which is correct for a rose chart. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Viridis is perceptually uniform and CVD-safe. Good luminance progression. + - id: VQ-05 + name: Layout & Canvas + score: 3 + max: 4 + passed: true + comment: 'Chart fills ~60-70% of 3600x3600 canvas. Circular layout with gridlines + is well-proportioned. Minor: data-heavy upper quadrant leaves lower portion + visually sparse.' + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Grid labels include units ('75 mm', '100 mm'). Month labels descriptive. + Title correct. + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Viridis applied to continuous value:Q is correct per style guide. + Backgrounds are #FAF8F1 (light) and #1A1A17 (dark). All chrome uses theme-adaptive + tokens. Both renders correct.' + design_excellence: + score: 13 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: 'Above default: viridis dual-encoding (radius + color) is a thoughtful + design choice. White segment strokes add definition. Overall feels professional + but not exceptional.' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: 'Good refinement: dashed radial gridlines with low opacity, no axis + chrome, configure_view strokeWidth=0. Could refine grid label positioning + and add a subtitle.' + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Dual encoding (radius + viridis color) makes winter peak immediately + visible. Value labels enable precise reading. Missing explicit annotation + of peak/trough to direct viewer attention. + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correct rose/Nightingale chart with equal-angle wedge segments and + radius proportional to value. + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: 'All spec features present: circular arrangement, radius proportional + to value, radial gridlines, 12-month cyclical data, starts at top (12 o''clock).' + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: Categories at angular positions, values determine radius. All 12 + months represented. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title 'rose-basic · altair · anyplot.ai' correct. No legend (appropriate + — value labels shown directly on segments, continuous color has no legend). + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: Full range from 22 to 92 mm shows meaningful variation. Both high-value + (winter) and low-value (summer) months clearly represented. Cyclical pattern + visible. + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Monthly rainfall is a classic rose chart use case (Florence Nightingale's + original application). Neutral, real-world scenario. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Monthly rainfall values 22-92mm are factually plausible for a Mediterranean/temperate + climate with winter-dominant rainfall. + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'Clean linear structure: theme setup -> data -> chart layers -> combine + -> save. No functions or classes.' + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: Deterministic hardcoded data. No random seed needed. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: Only os, altair, numpy, pandas — all used. + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Appropriately complex for a layered polar chart. Separate DataFrames + for each layer type is necessary for Altair's architecture. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png and plot-{THEME}.html. Correct for Altair + (interactive library). + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: 'Good idiomatic use: mark_arc with theta/theta2/radius, alt.layer() + composition, configure_view/configure_axis, scale with domain/range. Solid + Altair patterns.' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Layer composition with multiple mark types is Altair-distinctive. + Theta2 for arc spans, radius scale with explicit domain/range for polar + layout. Could go further with more uniquely Altair features. + verdict: REJECTED +impl_tags: + dependencies: [] + techniques: + - layer-composition + - hover-tooltips + - html-export + patterns: [] + dataprep: [] + styling: + - custom-colormap + - edge-highlighting From 773605dd5c12aefe1af3d448c48ac35517ea633d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Apr 2026 07:33:39 +0000 Subject: [PATCH 3/3] chore(altair): update quality score 87 and review feedback for rose-basic --- .../implementations/python/altair.py | 2 +- plots/rose-basic/metadata/python/altair.yaml | 190 ++++++++---------- 2 files changed, 81 insertions(+), 111 deletions(-) diff --git a/plots/rose-basic/implementations/python/altair.py b/plots/rose-basic/implementations/python/altair.py index 15a09c180d..253b790017 100644 --- a/plots/rose-basic/implementations/python/altair.py +++ b/plots/rose-basic/implementations/python/altair.py @@ -1,7 +1,7 @@ """ anyplot.ai rose-basic: Basic Rose Chart Library: altair 6.1.0 | Python 3.13.13 -Quality: 86/100 | Updated: 2026-04-30 +Quality: 87/100 | Updated: 2026-04-30 """ import os diff --git a/plots/rose-basic/metadata/python/altair.yaml b/plots/rose-basic/metadata/python/altair.yaml index 10978ce55f..2d84f41058 100644 --- a/plots/rose-basic/metadata/python/altair.yaml +++ b/plots/rose-basic/metadata/python/altair.yaml @@ -2,7 +2,7 @@ library: altair language: python specification_id: rose-basic created: '2025-12-23T19:45:47Z' -updated: '2026-04-30T07:12:28Z' +updated: '2026-04-30T07:33:39Z' generated_by: claude-sonnet workflow_run: 25151891021 issue: 1003 @@ -12,61 +12,40 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/rose-basi preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/rose-basic/python/altair/plot-dark.html -quality_score: 86 +quality_score: 87 review: strengths: - - Correct rose/Nightingale chart with 12 equal-angle wedge segments and radius proportional - to value - - Viridis continuous colormap applied to value:Q is appropriate and perceptually - uniform, creating effective dual encoding (radius + color) for the rainfall data - - Radial gridlines at 25/50/75/100 mm with unit labels ('75 mm', '100 mm') aid value - estimation as required by spec - - All font sizes explicitly set and appropriate for the 3600x3600 canvas (title - 32px, month labels 22px, value labels 20px, grid labels 18px) - - 'Full theme-adaptive chrome: PAGE_BG, INK, INK_SOFT tokens used correctly; both - light (#FAF8F1) and dark (#1A1A17) backgrounds render correctly' - - Layer composition with alt.layer() combining gridlines + arcs + value labels + - month labels demonstrates idiomatic Altair usage - - Both PNG and HTML saved per Altair interactive library requirements - - 'Title format correct: ''rose-basic · altair · anyplot.ai''' - - Data is deterministic (hardcoded monthly rainfall array), no seed needed - - KISS code structure with no functions or classes + - Viridis colormap is semantically correct for continuous value-based color encoding, + providing intuitive low-to-high visual hierarchy + - Segment stroke using PAGE_BG creates clean visual separation that adapts correctly + to both light and dark themes + - Five-layer Altair composition is clean and idiomatic — gridlines, labels, data + each isolated + - 'Full theme-adaptive chrome: all INK/INK_SOFT/PAGE_BG tokens properly threaded + throughout' + - 'Output format correct: both PNG and HTML exported for both themes' weaknesses: - - 'Design Excellence gap (13/20): viridis colormap is effective but the overall - layout lacks visual polish — consider adding a subtle center dot, refining gridline - labels with an elevated background box, or adding a concise subtitle with the - scenario (''Monthly Rainfall, mm'')' - - 'DE-03 Data Storytelling: the dual encoding (radius + viridis) is good but could - be stronger — consider annotating the peak month (Nov: 92mm) and trough (Jul: - 22mm) with callout labels or brief annotation text to direct the viewer''s attention - to the story' - - 'DE-02 Visual Refinement: the circular gridlines use strokeOpacity=0.35 and strokeDash=[6,4] - which is appropriate, but the overall chrome could be more refined — the plain - title with no subtitle and the sparse grid label positioning at 3 o''clock feels - unfinished' - - 'LM-02 Distinctive Features: while layer-composition and mark_arc with theta2 - are Altair-specific, the implementation could leverage Altair''s selection or - a more distinctive Vega-Lite feature (e.g., a center circle mark, a custom radial - label layout technique) to differentiate it further from a generic polar chart' - - 'VQ-02 minor label crowding: value labels for June (28), July (22), August (30) - cluster near center due to small segment radii; the label placement formula `max(v - * 1.35, 45)` places them all at similar radii which creates a tight cluster at - bottom' + - Rose chart is positioned in the upper half of the 1200x1200 canvas, leaving excessive + empty space below; center of chart area should be better utilized + - No data storytelling element (e.g. highlighting peak month, focal annotation) + — the chart shows data but does not guide the viewer to the key insight + - Value labels for low-rainfall months (Jun=28, Jul=22, Aug=30) are crowded near + the center; minimum offset or different placement needed for very small segments image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct, not pure white. - Chrome: Title "rose-basic · altair · anyplot.ai" at top center in dark ink, clearly readable. Month labels (Jan–Dec) in bold dark text around the outer ring, readable. Value labels (22–92) near segment tips in bold dark text, readable. Grid labels "75 mm" and "100 mm" at 3 o'clock position in muted INK_SOFT, small but legible. Dashed circular gridlines at 25/50/75/100 mm in subtle gray. - Data: 12 arc segments colored with viridis palette (purple/dark-blue for low values Jun=28, Jul=22; transitioning to teal, green, yellow-green, yellow for high values Nov=92, Dec=88, Oct=85). Segment radii visibly proportional to rainfall values. Winter months (Oct–Jan) dominate with taller, brighter segments. - Legibility verdict: PASS — all text readable against light background; no light-on-light issues. + Background: Warm off-white #FAF8F1 — correct theme surface + Chrome: Title "rose-basic · altair · anyplot.ai" in dark #1A1A17 ink, bold and readable. Month labels (Jan–Dec) in dark INK around the outer edge. Value labels (22–92) in dark INK near segment tips. Grid labels "75 mm" and "100 mm" in INK_SOFT at 3 o'clock position — visible. "25 mm" and "50 mm" labels at very small radii are harder to distinguish but present. + Data: 12 rose segments using viridis colormap — deep purple/indigo for low summer months (Jul=22mm minimum), transitioning through teal and green to bright yellow-green for peak autumn months (Nov=92mm maximum). Segment strokes in PAGE_BG create clean separation. Dashed radial gridlines at four intervals. + Legibility verdict: PASS — all major text elements readable against light background Dark render (plot-dark.png): - Background: Near-black (#1A1A17) — correct, not pure black. - Chrome: Title in light text at top, readable. Month labels in light bold text around outer ring, readable. Value labels in light bold text near segment tips, readable. Grid labels "75 mm" and "100 mm" in muted light-gray (INK_SOFT dark token), readable. Dashed circular gridlines visible against dark background. - Data: Viridis segment colors appear identical to the light render — same purple-to-yellow gradient encoding rainfall values. No color shift between themes, data identity preserved. - Legibility verdict: PASS — no dark-on-dark issues; all text uses light INK/INK_SOFT tokens appropriate for dark surface. + Background: Near-black #1A1A17 — correct theme surface + Chrome: Title text in light cream #F0EFE8, clearly readable. Month labels in light text. Value labels in light INK. Grid labels in INK_SOFT (#B8B7B0) — readable. No dark-on-dark failures detected. + Data: Viridis colors are identical to light render — purple for low months, yellow-green for high months. Segment strokes use #1A1A17 (dark PAGE_BG) providing appropriate separation on dark surface. + Legibility verdict: PASS — all text readable against dark background, no theme-adaptation failures criteria_checklist: visual_quality: - score: 26 + score: 27 max: 30 items: - id: VQ-01 @@ -74,54 +53,51 @@ review: score: 7 max: 8 passed: true - comment: 'All font sizes explicitly set: title 32px, month labels 22px, value - labels 20px, grid labels 18px. All readable at 3600x3600. Grid labels slightly - small at 18px but within spec.' + comment: 'Font sizes explicitly set (title=32, month=22, values=20, grid=18). + All text readable in both themes. Minor: 25mm grid label at very small radius + barely distinguishable.' - id: VQ-02 name: No Overlap score: 5 max: 6 passed: true - comment: Mostly no overlap; slight crowding of value labels for small segments - (Jun=28, Jul=22, Aug=30) which cluster at similar radii near center. + comment: Value labels for small summer segments (Jun=28, Jul=22, Aug=30) are + clustered near center; slight crowding but no hard collision. - id: VQ-03 name: Element Visibility - score: 5 + score: 6 max: 6 passed: true - comment: Segments clearly visible with viridis coloring. Small segments (Jun/Jul/Aug) - are genuinely small due to low values, which is correct for a rose chart. + comment: All 12 segments clearly visible with distinct stroke separation. + Dashed radial gridlines readable at all rings. - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Viridis is perceptually uniform and CVD-safe. Good luminance progression. + comment: Viridis is perceptually uniform and CVD-safe. No red-green sole signal. - id: VQ-05 name: Layout & Canvas score: 3 max: 4 passed: true - comment: 'Chart fills ~60-70% of 3600x3600 canvas. Circular layout with gridlines - is well-proportioned. Minor: data-heavy upper quadrant leaves lower portion - visually sparse.' + comment: 3600x3600px correct square format. Rose positioned correctly but + sits in upper half leaving disproportionate empty space below. - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Grid labels include units ('75 mm', '100 mm'). Month labels descriptive. - Title correct. + comment: Title format correct. Grid labels provide scale context in mm units. - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'Viridis applied to continuous value:Q is correct per style guide. - Backgrounds are #FAF8F1 (light) and #1A1A17 (dark). All chrome uses theme-adaptive - tokens. Both renders correct.' + comment: 'Viridis correctly applied to continuous value-based color encoding. + Backgrounds #FAF8F1 (light) and #1A1A17 (dark) correct.' design_excellence: - score: 13 + score: 11 max: 20 items: - id: DE-01 @@ -129,25 +105,23 @@ review: score: 5 max: 8 passed: true - comment: 'Above default: viridis dual-encoding (radius + color) is a thoughtful - design choice. White segment strokes add definition. Overall feels professional - but not exceptional.' + comment: Viridis creates meaningful visual hierarchy from low to peak months. + Segment stroke with PAGE_BG creates clean separation. Professional but conventional + composition. - id: DE-02 name: Visual Refinement - score: 4 + score: 3 max: 6 passed: true - comment: 'Good refinement: dashed radial gridlines with low opacity, no axis - chrome, configure_view strokeWidth=0. Could refine grid label positioning - and add a subtitle.' + comment: Dashed radial gridlines deliberate and appropriate. Axes/ticks suppressed + correctly for circular chart. Moderate refinement beyond defaults. - id: DE-03 name: Data Storytelling - score: 4 + score: 3 max: 6 passed: true - comment: Dual encoding (radius + viridis color) makes winter peak immediately - visible. Value labels enable precise reading. Missing explicit annotation - of peak/trough to direct viewer attention. + comment: Cyclical seasonal pattern visible through radius + viridis. No explicit + focal-point emphasis or annotations to guide viewer beyond raw data. spec_compliance: score: 15 max: 15 @@ -157,29 +131,28 @@ review: score: 5 max: 5 passed: true - comment: Correct rose/Nightingale chart with equal-angle wedge segments and - radius proportional to value. + comment: Correct Nightingale/rose chart with radius proportional to value. - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: 'All spec features present: circular arrangement, radius proportional - to value, radial gridlines, 12-month cyclical data, starts at top (12 o''clock).' + comment: Radial gridlines at 25/50/75/100mm, radius proportional to value, + 12-month circular ordering, Jan at 12 o'clock. - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Categories at angular positions, values determine radius. All 12 - months represented. + comment: Monthly rainfall correctly encoded as segment radius. All 12 data + points shown. - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title 'rose-basic · altair · anyplot.ai' correct. No legend (appropriate - — value labels shown directly on segments, continuous color has no legend). + comment: Title matches required format. No categorical legend needed for continuous + viridis encoding. data_quality: score: 15 max: 15 @@ -189,23 +162,22 @@ review: score: 6 max: 6 passed: true - comment: Full range from 22 to 92 mm shows meaningful variation. Both high-value - (winter) and low-value (summer) months clearly represented. Cyclical pattern - visible. + comment: 'All rose chart aspects demonstrated: radius encoding, angular categories, + radial gridlines, month labels, value labels.' - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Monthly rainfall is a classic rose chart use case (Florence Nightingale's - original application). Neutral, real-world scenario. + comment: Monthly rainfall in mm is plausible, neutral, domain-appropriate. + Values show realistic seasonal pattern. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Monthly rainfall values 22-92mm are factually plausible for a Mediterranean/temperate - climate with winter-dominant rainfall. + comment: 22-92mm monthly rainfall realistic for temperate climate. 12 months + is optimal category count per spec. code_quality: score: 10 max: 10 @@ -215,61 +187,59 @@ review: score: 3 max: 3 passed: true - comment: 'Clean linear structure: theme setup -> data -> chart layers -> combine - -> save. No functions or classes.' + comment: Flat top-level code, no functions or classes. - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: Deterministic hardcoded data. No random seed needed. + comment: Fully deterministic; hardcoded data with no randomness. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: Only os, altair, numpy, pandas — all used. + comment: os, altair, numpy, pandas — all actively used. - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Appropriately complex for a layered polar chart. Separate DataFrames - for each layer type is necessary for Altair's architecture. + comment: Clean Altair layer composition. Radius domain/range explicitly controlled. + No fake UI. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html. Correct for Altair - (interactive library). + comment: Saves plot-{THEME}.png and plot-{THEME}.html with scale_factor=3.0. library_mastery: - score: 7 + score: 9 max: 10 items: - id: LM-01 name: Idiomatic Usage - score: 4 + score: 5 max: 5 passed: true - comment: 'Good idiomatic use: mark_arc with theta/theta2/radius, alt.layer() - composition, configure_view/configure_axis, scale with domain/range. Solid - Altair patterns.' + comment: Correct use of alt.Theta/Theta2/Radius encoding for arc marks. alt.layer() + composition. Explicit alt.Scale for polar radius control. - id: LM-02 name: Distinctive Features - score: 3 + score: 4 max: 5 passed: true - comment: Layer composition with multiple mark types is Altair-distinctive. - Theta2 for arc spans, radius scale with explicit domain/range for polar - layout. Could go further with more uniquely Altair features. - verdict: REJECTED + comment: mark_arc with theta/theta2/radius (Altair polar encoding), 5-layer + composition, interactive hover tooltips, HTML export. Could push further + with dynamic elements. + verdict: APPROVED impl_tags: dependencies: [] techniques: - - layer-composition - hover-tooltips - html-export + - layer-composition + - polar-projection patterns: [] dataprep: [] styling: