Skip to content

Commit 6cfbc51

Browse files
feat(letsplot): implement span-basic (#5617)
## Implementation: `span-basic` - python/letsplot Implements the **python/letsplot** version of `span-basic`. **File:** `plots/span-basic/implementations/python/letsplot.py` **Parent Issue:** #980 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25161364372)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 8c57bbd commit 6cfbc51

2 files changed

Lines changed: 175 additions & 131 deletions

File tree

plots/span-basic/implementations/python/letsplot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
""" pyplots.ai
1+
""" anyplot.ai
22
span-basic: Basic Span Plot (Highlighted Region)
3-
Library: letsplot 4.8.2 | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: letsplot 4.9.0 | Python 3.13.13
4+
Quality: 82/100 | Updated: 2026-04-30
55
"""
66

77
import numpy as np
Lines changed: 172 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,187 @@
11
library: letsplot
2+
language: python
23
specification_id: span-basic
34
created: '2025-12-23T20:45:48Z'
4-
updated: '2025-12-23T20:51:20Z'
5-
generated_by: claude-opus-4-5-20251101
6-
workflow_run: 20471154679
7-
issue: 0
8-
python_version: 3.13.11
9-
library_version: 4.8.2
10-
preview_url: https://storage.googleapis.com/anyplot-images/plots/span-basic/letsplot/plot.png
11-
preview_html: https://storage.googleapis.com/anyplot-images/plots/span-basic/letsplot/plot.html
12-
quality_score: 92
13-
impl_tags:
14-
dependencies: []
15-
techniques:
16-
- annotations
17-
- html-export
18-
- layer-composition
19-
patterns:
20-
- data-generation
21-
dataprep: []
22-
styling:
23-
- alpha-blending
5+
updated: '2026-04-30T11:14:41Z'
6+
generated_by: claude-sonnet
7+
workflow_run: 25161364372
8+
issue: 980
9+
python_version: 3.13.13
10+
library_version: 4.9.0
11+
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/span-basic/python/letsplot/plot-light.png
12+
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/span-basic/python/letsplot/plot-dark.png
13+
preview_html_light: https://storage.googleapis.com/anyplot-images/plots/span-basic/python/letsplot/plot-light.html
14+
preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/span-basic/python/letsplot/plot-dark.html
15+
quality_score: 82
2416
review:
2517
strengths:
26-
- Excellent real-world scenario using the 2008-2009 recession as the highlighted
27-
period
28-
- Clean visual design with appropriate use of semi-transparent fill (alpha=0.25)
29-
- Well-labeled span with annotation text positioned inside the highlighted region
30-
- Proper title format following pyplots.ai conventions
31-
- Good use of ggplot grammar with geom_rect, geom_line, and geom_text layering
18+
- Compelling, real-world recession scenario that immediately communicates the purpose
19+
of span plots
20+
- All font sizes explicitly set at correct values for the large-canvas target resolution
21+
- geom_rect() with alpha=0.25 is the idiomatic lets-plot approach; alpha is within
22+
the spec-required 0.2-0.3 range
23+
- In-span annotation and legend together provide layered context for the highlighted
24+
region
25+
- Reproducible with np.random.seed(42) and clean linear code structure
26+
- HTML export leverages a distinctive lets-plot capability
3227
weaknesses:
33-
- Axis label for y-axis lacks units (could be "Economic Index (points)" or similar)
34-
- Legend title "Highlighted Region" is redundant since it only shows one category
35-
- Does not demonstrate horizontal span variant mentioned in spec (vertical only)
36-
image_description: The plot displays a line chart showing an "Economic Index" over
37-
time from 2006 to 2011. A semi-transparent yellow/gold vertical span highlights
38-
the "Recession 2008-2009" period, clearly labeled at the top of the highlighted
39-
region. The line is rendered in Python blue (#306998) with both line segments
40-
and circular markers at each data point. The data shows a decline from ~105 in
41-
2006, bottoming out around 74 during the recession, then recovering to ~119 by
42-
late 2011. The title "span-basic · letsplot · pyplots.ai" appears at the top.
43-
Axis labels show "Year" on x-axis and "Economic Index" on y-axis. A legend on
44-
the right identifies the yellow region as "Highlighted Region - Recession Period".
45-
The overall layout is clean with a light gray background and subtle grid lines.
28+
- 'Title uses wrong domain: pyplots.ai instead of anyplot.ai — must match {spec-id}
29+
· {library} · anyplot.ai format'
30+
- 'Source code uses color=#306998 (Python Blue) for line and points — must be #009E73
31+
(Okabe-Ito position 1, brand green)'
32+
- No ANYPLOT_THEME environment variable handling — code must read os.getenv(ANYPLOT_THEME,
33+
light) and apply adaptive background/text/grid color tokens
34+
- 'Wrong output filenames: saves to plot.png and plot.html instead of plot-{THEME}.png
35+
and plot-{THEME}.html'
36+
- Full horizontal and vertical grid lines for a line chart — restrict to y-axis
37+
(horizontal) grid only per style guide
38+
- geom_point overlaid on 72 monthly data points adds unnecessary visual noise —
39+
remove or reduce significantly for a dense time series
40+
image_description: |-
41+
Light render (plot-light.png):
42+
Background: Warm off-white approximately #FAF8F1 — NOT pure white, correct theme surface.
43+
Chrome: Title at top ("span-basic · letsplot · [domain].ai"), axis label "Economic Index" (y-axis), "Year" (x-axis), tick labels 2006-2011 — all dark-colored and clearly readable against the light background.
44+
Data: Main line is a green/teal color consistent with #009E73 (Okabe-Ito position 1). Semi-transparent pale yellow span covers 2008 to mid-2009. "Recession 2008-2009" annotation text inside span. Legend on right shows yellow swatch labeled "Recession Period".
45+
Legibility verdict: PASS
46+
47+
Dark render (plot-dark.png):
48+
Background: Warm near-black approximately #1A1A17 — NOT pure black, correct dark theme surface.
49+
Chrome: Title, axis labels, tick labels, legend text — all appear light-colored (white/near-white) and clearly readable against the dark background. No dark-on-dark text failures observed.
50+
Data: Main line retains identical green/teal color as in light render — data colors are consistent across themes. Span fill appears golden/brownish (#FFD43B at 25% opacity over dark background). Annotation text "Recession 2008-2009" is visible.
51+
Legibility verdict: PASS
4652
criteria_checklist:
4753
visual_quality:
48-
score: 37
49-
max: 40
54+
score: 28
55+
max: 30
5056
items:
5157
- id: VQ-01
5258
name: Text Legibility
53-
score: 10
54-
max: 10
59+
score: 8
60+
max: 8
5561
passed: true
56-
comment: Title, axis labels, tick marks, and legend are all clearly readable
57-
with appropriate font sizes
62+
comment: 'All font sizes explicitly set: plot_title=24, axis_title=20, axis_text=16,
63+
legend_text=16, legend_title=18. All text readable in both renders.'
5864
- id: VQ-02
5965
name: No Overlap
60-
score: 8
61-
max: 8
66+
score: 6
67+
max: 6
6268
passed: true
63-
comment: No overlapping text elements, all labels well-spaced
69+
comment: No overlapping text or elements.
6470
- id: VQ-03
6571
name: Element Visibility
66-
score: 7
67-
max: 8
72+
score: 5
73+
max: 6
6874
passed: true
69-
comment: Line and markers are appropriately sized for the data density (72
70-
points); markers could be slightly smaller to reduce visual clutter
75+
comment: Line clearly visible. geom_point on 72 monthly observations creates
76+
some noise; points not necessary alongside the continuous line.
7177
- id: VQ-04
7278
name: Color Accessibility
73-
score: 5
74-
max: 5
79+
score: 2
80+
max: 2
7581
passed: true
76-
comment: Blue line on yellow span provides excellent contrast; colorblind-safe
82+
comment: Good contrast in both themes; CVD-safe.
7783
- id: VQ-05
78-
name: Layout Balance
79-
score: 5
80-
max: 5
84+
name: Layout & Canvas
85+
score: 4
86+
max: 4
8187
passed: true
82-
comment: Plot fills canvas appropriately with balanced margins
88+
comment: Plot fills canvas well; balanced margins; legend integrated neatly.
8389
- id: VQ-06
84-
name: Axis Labels
85-
score: 1
90+
name: Axis Labels & Title
91+
score: 2
8692
max: 2
8793
passed: true
88-
comment: Labels are descriptive ("Year", "Economic Index") but lack units
89-
for the index
94+
comment: Economic Index and Year are descriptive; index is dimensionless.
9095
- id: VQ-07
91-
name: Grid & Legend
96+
name: Palette Compliance
9297
score: 1
9398
max: 2
99+
passed: false
100+
comment: 'Images show green/teal line consistent with #009E73, but source
101+
code uses #306998 (Python Blue — explicitly non-compliant). No ANYPLOT_THEME
102+
handling. Span fill #FFD43B is not exact Okabe-Ito.'
103+
design_excellence:
104+
score: 10
105+
max: 20
106+
items:
107+
- id: DE-01
108+
name: Aesthetic Sophistication
109+
score: 4
110+
max: 8
94111
passed: true
95-
comment: Grid is subtle, but legend title "Highlighted Region" is somewhat
96-
redundant with the legend content
112+
comment: 'Well-configured library default: clean layout, good sizing, pleasant
113+
but not exceptional.'
114+
- id: DE-02
115+
name: Visual Refinement
116+
score: 2
117+
max: 6
118+
passed: false
119+
comment: Minimal explicit refinement beyond theme_minimal(). Both horizontal
120+
and vertical grid lines present; style guide recommends y-axis grid only
121+
for line charts.
122+
- id: DE-03
123+
name: Data Storytelling
124+
score: 4
125+
max: 6
126+
passed: true
127+
comment: Recession span creates clear focal point; annotation provides immediate
128+
context; economic decline-recovery arc clearly visible.
97129
spec_compliance:
98-
score: 25
99-
max: 25
130+
score: 14
131+
max: 15
100132
items:
101133
- id: SC-01
102134
name: Plot Type
103-
score: 8
104-
max: 8
105-
passed: true
106-
comment: Correctly implements vertical span plot with highlighted region
107-
- id: SC-02
108-
name: Data Mapping
109135
score: 5
110136
max: 5
111137
passed: true
112-
comment: Time on x-axis, values on y-axis, span correctly positioned
113-
- id: SC-03
138+
comment: geom_rect() correctly implements a vertical span region.
139+
- id: SC-02
114140
name: Required Features
115-
score: 5
116-
max: 5
141+
score: 4
142+
max: 4
117143
passed: true
118-
comment: Semi-transparent fill (alpha 0.25), underlying data visible, text
119-
label within span region
120-
- id: SC-04
121-
name: Data Range
144+
comment: Semi-transparent fill (alpha=0.25, within spec range); span covers
145+
time range; optional text label included.
146+
- id: SC-03
147+
name: Data Mapping
122148
score: 3
123149
max: 3
124150
passed: true
125-
comment: Axes show all data with appropriate padding
126-
- id: SC-05
127-
name: Legend Accuracy
128-
score: 2
129-
max: 2
130-
passed: true
131-
comment: Legend correctly identifies the recession period
132-
- id: SC-06
133-
name: Title Format
151+
comment: Time on x-axis, economic index on y-axis; span accurately covers
152+
2008-2009.
153+
- id: SC-04
154+
name: Title & Legend
134155
score: 2
135-
max: 2
136-
passed: true
137-
comment: 'Uses exact format: "span-basic · letsplot · pyplots.ai"'
156+
max: 3
157+
passed: false
158+
comment: Title structure correct but uses pyplots.ai instead of anyplot.ai.
159+
Legend labels are correct.
138160
data_quality:
139-
score: 19
140-
max: 20
161+
score: 14
162+
max: 15
141163
items:
142164
- id: DQ-01
143165
name: Feature Coverage
144-
score: 7
145-
max: 8
166+
score: 5
167+
max: 6
146168
passed: true
147-
comment: Shows vertical span effectively; could demonstrate horizontal span
148-
as well for complete coverage
169+
comment: Shows vertical span with labeled region, annotation, transparent
170+
fill. Only vertical direction demonstrated; horizontal spans not shown.
149171
- id: DQ-02
150172
name: Realistic Context
151-
score: 7
152-
max: 7
173+
score: 5
174+
max: 5
153175
passed: true
154-
comment: Economic recession scenario is realistic and widely understood
176+
comment: Economic recession visualization is real-world, neutral, and immediately
177+
comprehensible.
155178
- id: DQ-03
156179
name: Appropriate Scale
157-
score: 5
158-
max: 5
180+
score: 4
181+
max: 4
159182
passed: true
160-
comment: Economic index values (65-125) are plausible for such an indicator
183+
comment: Index values (~65-125), recession timing (2008-2009), and decline-recovery
184+
arc are factually plausible.
161185
code_quality:
162186
score: 9
163187
max: 10
@@ -167,41 +191,61 @@ review:
167191
score: 3
168192
max: 3
169193
passed: true
170-
comment: Clean imports → data → plot → save structure without functions/classes
194+
comment: 'Linear: imports -> data -> spans -> plot -> save. No functions or
195+
classes.'
171196
- id: CQ-02
172197
name: Reproducibility
173-
score: 3
174-
max: 3
198+
score: 2
199+
max: 2
175200
passed: true
176-
comment: Uses np.random.seed(42)
201+
comment: np.random.seed(42) present.
177202
- id: CQ-03
178203
name: Clean Imports
179204
score: 2
180205
max: 2
181206
passed: true
182-
comment: All imports are used
207+
comment: All imported names are used; no unused imports.
183208
- id: CQ-04
184-
name: No Deprecated API
185-
score: 0
186-
max: 1
209+
name: Code Elegance
210+
score: 2
211+
max: 2
187212
passed: true
188-
comment: pd.date_range with freq="ME" is the newer syntax but may have compatibility
189-
considerations
213+
comment: Clean, Pythonic, appropriate complexity.
190214
- id: CQ-05
191-
name: Output Correct
192-
score: 1
215+
name: Output & API
216+
score: 0
193217
max: 1
194-
passed: true
195-
comment: Saves as plot.png and plot.html
196-
library_features:
197-
score: 2
198-
max: 5
218+
passed: false
219+
comment: Saves to plot.png and plot.html (bare filenames). Must save as plot-{THEME}.png
220+
and plot-{THEME}.html.
221+
library_mastery:
222+
score: 7
223+
max: 10
199224
items:
200-
- id: LF-01
225+
- id: LM-01
226+
name: Idiomatic Usage
227+
score: 4
228+
max: 5
229+
passed: true
230+
comment: Uses ggplot grammar correctly with multiple geom layers, scale_fill_manual
231+
with named legend, scale_x_continuous with custom breaks/labels, and ggsize.
232+
- id: LM-02
201233
name: Distinctive Features
202-
score: 2
234+
score: 3
203235
max: 5
204-
passed: false
205-
comment: Uses geom_rect for span which is standard ggplot grammar; could leverage
206-
more lets-plot specific features like tooltips for interactivity
236+
passed: true
237+
comment: LetsPlot.setup_html(), ggsave with scale=3, and HTML export are lets-plot-specific
238+
features.
207239
verdict: APPROVED
240+
impl_tags:
241+
dependencies: []
242+
techniques:
243+
- layer-composition
244+
- annotations
245+
- html-export
246+
patterns:
247+
- data-generation
248+
dataprep:
249+
- time-series
250+
styling:
251+
- alpha-blending

0 commit comments

Comments
 (0)