Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions plots/streamgraph-basic/implementations/python/plotnine.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
""" pyplots.ai
""" anyplot.ai
streamgraph-basic: Basic Stream Graph
Library: plotnine 0.15.1 | Python 3.13.11
Quality: 98/100 | Created: 2025-12-14
Library: plotnine 0.15.3 | Python 3.13.13
Quality: 79/100 | Created: 2026-05-05
"""

import numpy as np
Expand Down
284 changes: 267 additions & 17 deletions plots/streamgraph-basic/metadata/python/plotnine.yaml
Original file line number Diff line number Diff line change
@@ -1,26 +1,276 @@
library: plotnine
language: python
specification_id: streamgraph-basic
created: 2025-12-14 19:44:18+00:00
updated: 2025-12-14 19:44:18+00:00
generated_by: claude-opus-4-5-20251101
workflow_run: 20213171391
updated: '2026-05-05T03:37:22Z'
generated_by: claude-sonnet
workflow_run: 25356129081
issue: 856
python_version: 3.13.11
library_version: 0.15.1
preview_url: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/plotnine/plot.png
preview_html: null
quality_score: 98
python_version: 3.13.13
library_version: 0.15.3
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/plotnine/plot-light.png
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/streamgraph-basic/python/plotnine/plot-dark.png
preview_html_light: null
preview_html_dark: null
quality_score: 79
review:
strengths:
- Correct streamgraph implementation using geom_ribbon with properly centered symmetric
baseline (-totals/2)
- Realistic music streaming data with 5 genres over 24 months using sinusoidal trends
- All font sizes explicitly set (title 24pt, axis labels 20pt, tick labels 16pt,
legend 16pt) and readable in both renders
- KISS code structure with clear Imports → Data → Plot → Save flow
- Reproducible with np.random.seed(42)
- Clean imports — all symbols used
- Good canvas utilization with legend correctly positioned to the right
weaknesses:
- 'VQ-07 FAIL: Uses non-Okabe-Ito palette (colors=["#306998", "#FFD43B", "#FF6B6B",
"#4ECDC4", "#9B59B6"]) — #306998 is legacy Python Blue explicitly flagged as non-compliant;
first series must be #009E73 brand green'
- 'Missing ANYPLOT_THEME support: no os.getenv("ANYPLOT_THEME", "light") reading
and no theme-adaptive tokens (PAGE_BG, ELEVATED_BG, INK, INK_SOFT) applied via
anyplot_theme; both renders likely rely on pipeline-level dark mode injection
rather than proper implementation'
- 'CQ-05: Saves to "plot.png" instead of f"plot-{THEME}.png" — must be plot-light.png
/ plot-dark.png'
- 'SC-02: Spec explicitly requires smooth interpolation (spline/basis) for flowing
curves; implementation connects data points without any smoothing'
- 'Design Excellence low: no spine customization beyond theme_minimal defaults,
no visual hierarchy or focal emphasis on any genre trend, data displayed but not
interpreted'
- Code docstring header still says "pyplots.ai" (old branding) though rendered title
correctly shows anyplot.ai
image_description: |-
Light render (plot-light.png):
Background: Warm off-white (~#FAF8F1) for both page and panel backgrounds. PASS.
Chrome: Title "streamgraph-basic · plotnine · anyplot.ai" in dark text clearly readable. X-axis label "Month" and Y-axis label "Streaming Hours" readable in dark text at appropriate sizes. Tick labels (Jan '23, Jul '23, Jan '24, Jul '24; -400 to 400) all readable. Legend positioned right with Genre title and 5 swatches (Pop, Rock, Hip-Hop, Electronic, Jazz) — all readable.
Data: 5 centered ribbon bands filling the plot from ~-380 to ~+380. Colors: bottom (Pop) = teal (~#306998?), Rock = orange-brown, Hip-Hop = medium blue, Electronic = pink/lavender, Jazz = yellow/gold. Note: actual hex values (#306998, #FFD43B, #FF6B6B, #4ECDC4, #9B59B6) are non-Okabe-Ito — first series is NOT #009E73.
Legibility verdict: PASS — all text is readable against light background.

Dark render (plot-dark.png):
Background: Very dark near-black (appears close to pure #000000 rather than warm #1A1A17 — no theme tokens applied in code). FAIL on exact spec but functionally dark.
Chrome: Title, axis labels, and tick labels appear in white/light text — readable against dark background. No dark-on-dark failures observed for text. Legend box has dark background with light text — readable.
Data: Colors appear identical to light render — same teal, orange, blue, pink, yellow/gold bands. Data colors are consistent between themes (only chrome flips). However, visible black gap below the bottom green ribbon to the -400 axis mark suggests pure-black panel background bleeding through rather than #1A1A17.
Legibility verdict: PASS for text readability. FAIL for correct background token (#1A1A17 not implemented — theme switching handled externally by pipeline, not by code).
criteria_checklist:
visual_quality:
score: 27
max: 30
items:
- id: VQ-01
name: Text Legibility
score: 8
max: 8
passed: true
comment: 'All font sizes explicitly set: title 24pt, axis_title 20pt, axis_text
16pt, legend_text 16pt, legend_title 18pt. Readable in both light and dark
renders.'
- id: VQ-02
name: No Overlap
score: 6
max: 6
passed: true
comment: No text overlap. X-axis has only 4 well-spaced labels. Legend does
not overlap data area.
- id: VQ-03
name: Element Visibility
score: 6
max: 6
passed: true
comment: All 5 ribbon bands clearly visible and well-sized. Alpha=0.85 provides
good opacity with slight transparency.
- id: VQ-04
name: Color Accessibility
score: 1
max: 2
passed: false
comment: 'Custom palette (#306998, #FFD43B, #FF6B6B, #4ECDC4, #9B59B6) not
designed for CVD safety. Reasonable luminance variation helps since layers
are spatially separated, but not Okabe-Ito guaranteed safe.'
- id: VQ-05
name: Layout & Canvas
score: 4
max: 4
passed: true
comment: Streamgraph fills the canvas well. Legend positioned outside plot
area to the right. No content cut off. Good canvas utilization (>60%).
- id: VQ-06
name: Axis Labels & Title
score: 2
max: 2
passed: true
comment: 'Y-axis: ''Streaming Hours'' (descriptive with implicit units). X-axis:
''Month''. Title uses correct anyplot.ai format in rendered output.'
- id: VQ-07
name: Palette Compliance
score: 0
max: 2
passed: false
comment: 'FAIL: Uses custom non-Okabe-Ito colors. #306998 (Python Blue) explicitly
flagged as non-compliant. First series must be #009E73. Dark background
likely not #1A1A17 (no theme tokens in code). Score: 0.'
design_excellence:
score: 9
max: 20
items:
- id: DE-01
name: Aesthetic Sophistication
score: 4
max: 8
passed: false
comment: Well-configured theme_minimal() with explicit font sizes and custom
(non-Okabe-Ito) colors. Streamgraph form is sophisticated but design execution
is library-default level.
- id: DE-02
name: Visual Refinement
score: 3
max: 6
passed: false
comment: theme_minimal() provides clean look with subtle grid. Explicit font
sizing adds polish. No explicit spine removal, no grid direction restriction,
no whitespace tuning beyond defaults.
- id: DE-03
name: Data Storytelling
score: 2
max: 6
passed: false
comment: Data displayed without visual hierarchy. No genre highlighted, no
trend emphasized. Viewer must find their own story in the flowing shapes.
spec_compliance:
score: 14
max: 15
items:
- id: SC-01
name: Plot Type
score: 5
max: 5
passed: true
comment: Correct streamgraph with symmetric centered baseline (baseline =
-totals/2). Uses geom_ribbon to create the characteristic flowing band appearance.
- id: SC-02
name: Required Features
score: 3
max: 4
passed: false
comment: 'Centered baseline ✓, legend ✓, distinct colors ✓, multiple categories
✓. Missing: explicit smooth interpolation (spline/basis). Spec explicitly
requires ''smooth interpolation for flowing curves''.'
- id: SC-03
name: Data Mapping
score: 3
max: 3
passed: true
comment: X=month (time), Y=streaming hours centered around 0. All 5 genres
visible. Y-axis correctly shows both positive and negative range (-400 to
400).
- id: SC-04
name: Title & Legend
score: 3
max: 3
passed: true
comment: 'Rendered title: ''streamgraph-basic · plotnine · anyplot.ai'' —
correct format. Legend shows all 5 genres with correct labels. (Note: code
file still has ''pyplots.ai'' branding in labs() call and docstring.)'
data_quality:
score: 14
max: 15
items:
- id: DQ-01
name: Feature Coverage
score: 5
max: 6
passed: true
comment: Shows 5 genres (3-8 range ✓), 24 time points (10-100 range ✓), centered
baseline, varying magnitudes per genre, time trends visible. Could show
more dramatic crossover/convergence to better demonstrate the format's storytelling
power.
- id: DQ-02
name: Realistic Context
score: 5
max: 5
passed: true
comment: Music streaming hours by genre (Pop, Rock, Hip-Hop, Electronic, Jazz)
over two years — realistic, neutral, comprehensible scenario.
- id: DQ-03
name: Appropriate Scale
score: 4
max: 4
passed: true
comment: Base values 100-200 hours/month per genre are plausible streaming
magnitudes. Total ~600-800 hours/month across genres is reasonable. Y-axis
range (-400 to 400) correctly reflects the centered baseline.
code_quality:
score: 9
max: 10
items:
- id: CQ-01
name: KISS Structure
score: 3
max: 3
passed: true
comment: 'Linear flow: Imports → Data generation → Streamgraph position calculation
→ Long-form DataFrame → Plot → Save. No functions or classes.'
- id: CQ-02
name: Reproducibility
score: 2
max: 2
passed: true
comment: np.random.seed(42) set before data generation.
- id: CQ-03
name: Clean Imports
score: 2
max: 2
passed: true
comment: All plotnine imports are used (aes, element_text, geom_ribbon, ggplot,
labs, scale_fill_manual, scale_x_continuous, theme, theme_minimal). numpy
and pandas used.
- id: CQ-04
name: Code Elegance
score: 2
max: 2
passed: true
comment: Clean Pythonic code. Matrix-based streamgraph position calculation
is appropriate. No over-engineering or fake functionality.
- id: CQ-05
name: Output & API
score: 0
max: 1
passed: false
comment: 'FAIL: Saves to ''plot.png'' instead of f''plot-{THEME}.png''. No
ANYPLOT_THEME env var reading. Should read os.getenv(''ANYPLOT_THEME'',
''light'') and save as plot-{THEME}.png.'
library_mastery:
score: 6
max: 10
items:
- id: LM-01
name: Idiomatic Usage
score: 4
max: 5
passed: true
comment: 'Good use of plotnine''s grammar of graphics: ggplot() + geom_ribbon()
+ scale_fill_manual() + labs() + theme_minimal() + theme(). pd.Categorical
for ordered factor control is idiomatic. Minor: could use ggsave() instead
of plot.save().'
- id: LM-02
name: Distinctive Features
score: 2
max: 5
passed: false
comment: geom_ribbon with fill aesthetic and the grammar-of-graphics layering
via + operator are distinctive to plotnine/ggplot2. However, the streamgraph
computation itself is library-agnostic, and geom_ribbon appears in letsplot/R
ggplot2 as well. No uniquely plotnine features leveraged.
verdict: REJECTED
impl_tags:
dependencies: []
techniques: []
techniques:
- layer-composition
patterns:
- data-generation
- matrix-construction
- data-generation
- matrix-construction
- iteration-over-groups
dataprep: []
styling:
- alpha-blending
review:
strengths: []
weaknesses: []
improvements: []
verdict: APPROVED
- alpha-blending
Loading