diff --git a/plots/slope-basic/implementations/python/plotly.py b/plots/slope-basic/implementations/python/plotly.py
index 158d0b26f8..e21065090f 100644
--- a/plots/slope-basic/implementations/python/plotly.py
+++ b/plots/slope-basic/implementations/python/plotly.py
@@ -1,12 +1,28 @@
-""" pyplots.ai
+""" anyplot.ai
slope-basic: Basic Slope Chart (Slopegraph)
-Library: plotly 6.5.0 | Python 3.13.11
-Quality: 91/100 | Created: 2025-12-23
+Library: plotly 6.7.0 | Python 3.13.13
+Quality: 88/100 | Updated: 2026-04-30
"""
+import os
+
import plotly.graph_objects as go
+# Theme tokens
+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"
+INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
+GRID = "rgba(26,26,23,0.10)" if THEME == "light" else "rgba(240,239,232,0.10)"
+
+# Okabe-Ito: increase = brand green, decrease = vermillion, flat = adaptive neutral
+COLOR_UP = "#009E73"
+COLOR_DOWN = "#D55E00"
+COLOR_FLAT = INK_MUTED
+
# Data - Product sales Q1 vs Q4 comparison (10 products showing various patterns)
products = [
"Laptop Pro",
@@ -21,24 +37,21 @@
"Monitor Stand",
]
-# Sales figures in thousands ($K)
sales_q1 = [245, 180, 120, 195, 85, 110, 45, 30, 75, 55]
sales_q4 = [310, 220, 195, 160, 145, 130, 95, 85, 70, 40]
-# Color coding by change direction
colors = []
for q1, q4 in zip(sales_q1, sales_q4, strict=True):
if q4 > q1:
- colors.append("#306998") # Python Blue for increase
+ colors.append(COLOR_UP)
elif q4 < q1:
- colors.append("#FFD43B") # Python Yellow for decrease
+ colors.append(COLOR_DOWN)
else:
- colors.append("#888888") # Gray for no change
+ colors.append(COLOR_FLAT)
-# Create figure
+# Plot
fig = go.Figure()
-# Add slope lines for each product
for i, product in enumerate(products):
fig.add_trace(
go.Scatter(
@@ -46,14 +59,14 @@
y=[sales_q1[i], sales_q4[i]],
mode="lines+markers",
line={"color": colors[i], "width": 3},
- marker={"size": 14},
+ marker={"size": 14, "color": colors[i]},
name=product,
showlegend=False,
hovertemplate=f"{product}
Q1: ${sales_q1[i]}K
Q4: ${sales_q4[i]}K",
)
)
-# Add labels at start points (Q1)
+# Labels at Q1 (left side)
for i, product in enumerate(products):
fig.add_annotation(
x=-0.05,
@@ -64,7 +77,7 @@
font={"size": 16, "color": colors[i]},
)
-# Add labels at end points (Q4)
+# Labels at Q4 (right side)
for i, product in enumerate(products):
fig.add_annotation(
x=1.05,
@@ -75,11 +88,14 @@
font={"size": 16, "color": colors[i]},
)
-# Layout
+# Style
fig.update_layout(
+ paper_bgcolor=PAGE_BG,
+ plot_bgcolor=PAGE_BG,
+ font={"color": INK},
title={
- "text": "Product Sales Q1 vs Q4 · slope-basic · plotly · pyplots.ai",
- "font": {"size": 28},
+ "text": "Product Sales Q1 vs Q4 · slope-basic · plotly · anyplot.ai",
+ "font": {"size": 28, "color": INK},
"x": 0.5,
"xanchor": "center",
},
@@ -87,23 +103,24 @@
"tickmode": "array",
"tickvals": [0, 1],
"ticktext": ["Q1 2024", "Q4 2024"],
- "tickfont": {"size": 22},
- "range": [-0.4, 1.4],
+ "tickfont": {"size": 22, "color": INK_SOFT},
+ "range": [-0.5, 1.5],
"showgrid": False,
"zeroline": False,
+ "linecolor": INK_SOFT,
},
yaxis={
- "title": {"text": "Sales ($K)", "font": {"size": 22}},
- "tickfont": {"size": 18},
+ "title": {"text": "Sales ($K)", "font": {"size": 22, "color": INK}},
+ "tickfont": {"size": 18, "color": INK_SOFT},
"showgrid": True,
"gridwidth": 1,
- "gridcolor": "rgba(0,0,0,0.1)",
+ "gridcolor": GRID,
"zeroline": False,
+ "linecolor": INK_SOFT,
},
- template="plotly_white",
- margin={"l": 200, "r": 200, "t": 80, "b": 60},
+ margin={"l": 220, "r": 220, "t": 80, "b": 60},
)
-# Save outputs
-fig.write_image("plot.png", width=1600, height=900, scale=3)
-fig.write_html("plot.html")
+# Save
+fig.write_image(f"plot-{THEME}.png", width=1600, height=900, scale=3)
+fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")
diff --git a/plots/slope-basic/metadata/python/plotly.yaml b/plots/slope-basic/metadata/python/plotly.yaml
index f8774d0fb6..c462247808 100644
--- a/plots/slope-basic/metadata/python/plotly.yaml
+++ b/plots/slope-basic/metadata/python/plotly.yaml
@@ -1,174 +1,182 @@
library: plotly
+language: python
specification_id: slope-basic
created: '2025-12-23T20:45:26Z'
-updated: '2025-12-23T20:52:45Z'
-generated_by: claude-opus-4-5-20251101
-workflow_run: 20471149656
-issue: 0
-python_version: 3.13.11
-library_version: 6.5.0
-preview_url: https://storage.googleapis.com/anyplot-images/plots/slope-basic/plotly/plot.png
-preview_html: https://storage.googleapis.com/anyplot-images/plots/slope-basic/plotly/plot.html
-quality_score: 91
-impl_tags:
- dependencies: []
- techniques:
- - annotations
- - hover-tooltips
- - html-export
- patterns:
- - data-generation
- - iteration-over-groups
- dataprep: []
- styling: []
+updated: '2026-04-30T17:01:48Z'
+generated_by: claude-sonnet
+workflow_run: 25177301713
+issue: 981
+python_version: 3.13.13
+library_version: 6.7.0
+preview_url_light: https://storage.googleapis.com/anyplot-images/plots/slope-basic/python/plotly/plot-light.png
+preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/slope-basic/python/plotly/plot-dark.png
+preview_html_light: https://storage.googleapis.com/anyplot-images/plots/slope-basic/python/plotly/plot-light.html
+preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/slope-basic/python/plotly/plot-dark.html
+quality_score: 88
review:
strengths:
- - Excellent color coding system using Python brand colors (blue for increase, yellow
- for decrease)
- - Clean, professional appearance with appropriate font sizes for high-resolution
- output
- - Good use of Plotly annotation system for endpoint labels
- - Realistic business scenario with varied data showing both increases and decreases
- - Proper implementation of hover templates for interactive exploration
- - Correct title format following pyplots.ai conventions
+ - Semantic color encoding (green=increase, orange=decrease) creates immediate directional
+ communication
+ - All theme tokens correctly applied — both light and dark renders pass legibility
+ checks
+ - 'Perfect spec compliance: bilateral labels, direction color coding, correct time-point
+ labels'
+ - Realistic neutral business data demonstrating rank inversions and varied magnitudes
+ - Clean plotly idioms with proper HTML+PNG output and working interactive hover
+ tooltips
weaknesses:
- - Missing a legend explaining what blue and yellow colors represent (increase vs
- decrease)
- - Some endpoint labels are positioned close together and could benefit from slight
- vertical adjustment to prevent near-overlap
- image_description: 'The plot displays a slope chart (slopegraph) comparing product
- sales between Q1 2024 and Q4 2024 for 10 tech products. Blue lines (#306998 -
- Python Blue) represent products with sales increases (8 products: Laptop Pro,
- Wireless Earbuds, Smart Watch, Gaming Mouse, Mechanical Keyboard, Webcam HD, USB
- Hub). Yellow/gold lines (#FFD43B - Python Yellow) represent products with sales
- decreases (3 products: Tablet Ultra, Portable SSD, Monitor Stand). Each product
- has labels at both endpoints showing the product name and sales value in $K. The
- chart uses a clean white template with subtle horizontal grid lines. The title
- "Product Sales Q1 vs Q4 · slope-basic · plotly · pyplots.ai" is centered at the
- top. The Y-axis displays "Sales ($K)" ranging from approximately 30 to 310. The
- X-axis shows the two time points "Q1 2024" and "Q4 2024".'
+ - Label crowding in lower y-range ($30-$110K band) where 7 products compete for
+ vertical annotation space
+ - Top and right axis spines still visible — removing them would add visual refinement
+ - No size or weight variation on biggest movers (Laptop Pro, Tablet Ultra) to amplify
+ storytelling emphasis
+ image_description: |-
+ Light render (plot-light.png):
+ Background: Warm off-white (#FAF8F1) — correct, not pure white
+ Chrome: Title "Product Sales Q1 vs Q4 · slope-basic · plotly · anyplot.ai" in dark ink, clearly readable. Y-axis label "Sales ($K)" readable. X-tick labels "Q1 2024"/"Q4 2024" in INK_SOFT, readable. Annotations in matching line colors (green/orange), readable.
+ Data: 10 product lines — most in #009E73 (green, increasing), 3 in #D55E00 (orange, decreasing). Lines at width=3 with size-14 markers. Crossing lines visible (Tablet Ultra falls while Smart Watch rises).
+ Legibility verdict: PASS — all text readable; minor label crowding in lower value band ($30-$110K) but no unreadable text.
+
+ Dark render (plot-dark.png):
+ Background: Warm near-black (#1A1A17) — correct, not pure black
+ Chrome: Title in #F0EFE8 (light), clearly readable. Axis labels and ticks in #B8B7B0, readable. Annotations in matching line colors (same green/orange as light render), readable against dark background.
+ Data: Colors identical to light render — green #009E73 and orange #D55E00 unchanged. Only background, text, and grid chrome flipped. No dark-on-dark failures detected.
+ Legibility verdict: PASS — all text readable in dark theme; brand green #009E73 highly visible on near-black surface.
criteria_checklist:
visual_quality:
- score: 36
- max: 40
+ score: 28
+ max: 30
items:
- id: VQ-01
name: Text Legibility
- score: 10
- max: 10
+ score: 8
+ max: 8
passed: true
- comment: Title at 28pt, axis labels at 22pt, tick labels at 18pt, annotations
- at 16pt - all perfectly readable
+ comment: 'All font sizes explicitly set: title 28px, x-ticks 22px, y-title
+ 22px, y-ticks 18px, annotations 16px'
- id: VQ-02
name: No Overlap
- score: 7
- max: 8
+ score: 4
+ max: 6
passed: true
- comment: Most labels are readable, but some endpoint labels are slightly close
- together (e.g., Smart Watch/Tablet Ultra on left, Gaming Mouse/Mechanical
- Keyboard on right)
+ comment: Moderate label crowding in lower y-band ($30-$110K) with 7 products;
+ readable but not perfectly spaced
- id: VQ-03
name: Element Visibility
- score: 8
- max: 8
+ score: 6
+ max: 6
passed: true
- comment: Lines have good width (3), markers are sized appropriately (14),
- clear visual hierarchy
+ comment: Lines at width=3, markers at size=14, well-adapted for canvas size
- id: VQ-04
name: Color Accessibility
- score: 5
- max: 5
+ score: 2
+ max: 2
passed: true
- comment: Blue/yellow color scheme is colorblind-safe, good contrast against
- white background
+ comment: Okabe-Ito positions 1 and 2 are CVD-safe with strong luminance contrast
- id: VQ-05
- name: Layout Balance
+ name: Layout & Canvas
score: 4
- max: 5
+ max: 4
passed: true
- comment: Good use of margins (200px on sides), plot fills canvas well, but
- could use slightly more vertical space
+ comment: Generous bilateral margins (220px) appropriate for slope chart annotations;
+ balanced layout
- id: VQ-06
- name: Axis Labels
+ name: Axis Labels & Title
score: 2
max: 2
passed: true
- comment: Y-axis has "Sales ($K)" with units, X-axis shows time period names
+ comment: Y-axis Sales ($K) with units; X-axis time-point tick labels Q1 2024/Q4
+ 2024
- id: VQ-07
- name: Grid & Legend
- score: 0
+ name: Palette Compliance
+ score: 2
max: 2
passed: true
- comment: Grid is subtle (alpha 0.1), but no legend explaining blue=increase,
- yellow=decrease
+ comment: 'Background #FAF8F1/#1A1A17 confirmed; first series #009E73, second
+ #D55E00; chrome fully theme-adaptive'
+ design_excellence:
+ score: 13
+ max: 20
+ items:
+ - id: DE-01
+ name: Aesthetic Sophistication
+ score: 5
+ max: 8
+ passed: true
+ comment: Semantic color encoding and inline labels above defaults; not yet
+ at strong-design level
+ - id: DE-02
+ name: Visual Refinement
+ score: 4
+ max: 6
+ passed: true
+ comment: X-axis grid hidden, y-axis grid uses rgba token; top/right spines
+ still visible
+ - id: DE-03
+ name: Data Storytelling
+ score: 4
+ max: 6
+ passed: true
+ comment: Semantic colors communicate direction immediately; crossing lines
+ tell rank-change story; no additional size variation for biggest movers
spec_compliance:
- score: 25
- max: 25
+ score: 15
+ max: 15
items:
- id: SC-01
name: Plot Type
- score: 8
- max: 8
- passed: true
- comment: Correct slope chart (slopegraph) implementation
- - id: SC-02
- name: Data Mapping
score: 5
max: 5
passed: true
- comment: Entity names as labels, values at start/end correctly mapped
- - id: SC-03
+ comment: Correct slope chart/slopegraph with bilateral axes and connecting
+ lines
+ - id: SC-02
name: Required Features
- score: 5
- max: 5
+ score: 4
+ max: 4
passed: true
- comment: Labels at both endpoints, color coding by direction (increase vs
- decrease), vertical axes labeled with time points
- - id: SC-04
- name: Data Range
+ comment: Labels at both endpoints, direction color coding, time-point axis
+ labels, 10 entities in 5-15 range
+ - id: SC-03
+ name: Data Mapping
score: 3
max: 3
passed: true
- comment: All data points visible within range
- - id: SC-05
- name: Legend Accuracy
- score: 2
- max: 2
- passed: true
- comment: No traditional legend but color coding is consistent and understandable
- from context
- - id: SC-06
- name: Title Format
- score: 2
- max: 2
+ comment: X=time points, Y=sales values, all 10 entities visible
+ - id: SC-04
+ name: Title & Legend
+ score: 3
+ max: 3
passed: true
- comment: 'Uses correct format: "Product Sales Q1 vs Q4 · slope-basic · plotly
- · pyplots.ai"'
+ comment: 'Title format correct: slope-basic · plotly · anyplot.ai; inline
+ labels replace legend appropriately'
data_quality:
- score: 20
- max: 20
+ score: 15
+ max: 15
items:
- id: DQ-01
name: Feature Coverage
- score: 8
- max: 8
+ score: 6
+ max: 6
passed: true
- comment: Shows both increases (majority) and decreases (3 products), varied
- magnitudes of change, demonstrates rank changes
+ comment: Shows increases, decreases, rank inversions, steep vs gradual changes
+ — all slope chart features
- id: DQ-02
name: Realistic Context
- score: 7
- max: 7
+ score: 5
+ max: 5
passed: true
- comment: Tech product sales Q1 vs Q4 is a realistic business scenario
+ comment: Tech product quarterly sales comparison — neutral, recognizable business
+ scenario
- id: DQ-03
name: Appropriate Scale
- score: 5
- max: 5
+ score: 4
+ max: 4
passed: true
- comment: Sales values in $30K-$310K range are realistic for product lines
+ comment: Sales values $30K-$310K plausible for product category quarterly
+ sales; realistic change percentages
code_quality:
- score: 7
+ score: 10
max: 10
items:
- id: CQ-01
@@ -176,40 +184,62 @@ review:
score: 3
max: 3
passed: true
- comment: 'Linear script: imports → data → plot → save'
+ comment: 'Flat: imports → tokens → data → colors → plot → annotations → layout
+ → save'
- id: CQ-02
name: Reproducibility
- score: 0
- max: 3
- passed: false
- comment: No random data used, but data is hardcoded (acceptable, but deterministic)
+ score: 2
+ max: 2
+ passed: true
+ comment: All data hardcoded and deterministic; no random seed needed
- id: CQ-03
name: Clean Imports
score: 2
max: 2
passed: true
- comment: Only plotly.graph_objects imported
+ comment: Only os and plotly.graph_objects; both used
- id: CQ-04
- name: No Deprecated API
- score: 1
- max: 1
+ name: Code Elegance
+ score: 2
+ max: 2
passed: true
- comment: Uses current Plotly API
+ comment: Clean iteration patterns for colors, traces, and annotations; no
+ over-engineering
- id: CQ-05
- name: Output Correct
+ name: Output & API
score: 1
max: 1
passed: true
- comment: Saves as plot.png and plot.html
- library_features:
- score: 3
- max: 5
+ comment: Saves plot-{THEME}.png (4800x2700 via scale=3) and plot-{THEME}.html;
+ correct for plotly
+ library_mastery:
+ score: 7
+ max: 10
items:
- - id: LF-01
- name: Uses distinctive library features
+ - id: LM-01
+ name: Idiomatic Usage
+ score: 4
+ max: 5
+ passed: true
+ comment: Proper go.Figure/add_trace pattern with hovertemplate and update_layout;
+ good idiomatic plotly
+ - id: LM-02
+ name: Distinctive Features
score: 3
max: 5
passed: true
- comment: Uses Plotly's annotation system, hover templates for interactivity,
- but could leverage more Plotly-specific features
+ comment: Interactive hover with hovertemplate and HTML export are genuinely
+ plotly-distinctive capabilities
verdict: APPROVED
+impl_tags:
+ dependencies: []
+ techniques:
+ - annotations
+ - hover-tooltips
+ - html-export
+ patterns:
+ - data-generation
+ - iteration-over-groups
+ dataprep: []
+ styling:
+ - grid-styling