Skip to content

Commit d054bac

Browse files
feat(letsplot): implement stem-basic (#5635)
## Implementation: `stem-basic` - python/letsplot Implements the **python/letsplot** version of `stem-basic`. **File:** `plots/stem-basic/implementations/python/letsplot.py` **Parent Issue:** #972 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/25172580885)* --------- 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 b028400 commit d054bac

2 files changed

Lines changed: 160 additions & 126 deletions

File tree

plots/stem-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
stem-basic: Basic Stem Plot
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: 86/100 | Updated: 2026-04-30
55
"""
66
# ruff: noqa: F405
77

Lines changed: 157 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,175 @@
11
library: letsplot
2+
language: python
23
specification_id: stem-basic
34
created: '2025-12-23T20:47:53Z'
4-
updated: '2025-12-23T20:56:51Z'
5-
generated_by: claude-opus-4-5-20251101
6-
workflow_run: 20471158070
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/stem-basic/letsplot/plot.png
11-
preview_html: https://storage.googleapis.com/anyplot-images/plots/stem-basic/letsplot/plot.html
12-
quality_score: 92
13-
impl_tags:
14-
dependencies: []
15-
techniques:
16-
- html-export
17-
patterns:
18-
- data-generation
19-
dataprep: []
20-
styling: []
5+
updated: '2026-04-30T15:23:56Z'
6+
generated_by: claude-sonnet
7+
workflow_run: 25172580885
8+
issue: 972
9+
python_version: 3.13.13
10+
library_version: 4.9.0
11+
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/stem-basic/python/letsplot/plot-light.png
12+
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/stem-basic/python/letsplot/plot-dark.png
13+
preview_html_light: https://storage.googleapis.com/anyplot-images/plots/stem-basic/python/letsplot/plot-light.html
14+
preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/stem-basic/python/letsplot/plot-dark.html
15+
quality_score: 86
2116
review:
2217
strengths:
23-
- Excellent stem plot implementation using geom_segment + geom_point + geom_hline
24-
combination
25-
- Clean, readable code following KISS principles
26-
- Good choice of damped oscillation data that demonstrates the discrete nature of
27-
stem plots
28-
- Proper sizing for 4800x2700 output with scaled text elements
29-
- Consistent blue color scheme (#306998) for all stem elements
18+
- Excellent data choice (damped oscillation) demonstrating both positive and negative
19+
stems with a clear signal processing narrative
20+
- Decay envelope curves add genuine visual storytelling — viewer immediately grasps
21+
the exponential decay pattern without annotations
22+
- 'Correct Okabe-Ito #009E73 color with fully theme-adaptive chrome (backgrounds,
23+
text, grid, baseline) in both renders'
24+
- 'Complete spec compliance: correct title format, descriptive axis labels with
25+
units, all spec features present'
26+
- Clean KISS code structure, reproducible seed, correct output filenames
3027
weaknesses:
31-
- Could add units to axis labels (e.g., "Amplitude (a.u.)" for arbitrary units)
32-
- Does not leverage lets-plot interactive features like tooltips
33-
image_description: The plot displays a stem plot with 30 data points representing
34-
a damped oscillation signal. Blue vertical stems (#306998) extend from a black
35-
horizontal baseline at y=0 to blue circular markers at the top of each stem. The
36-
x-axis is labeled "Sample Index" (ranging 0-30), and the y-axis is labeled "Amplitude"
37-
(ranging approximately -0.7 to 1.1). The title "stem-basic · letsplot · pyplots.ai"
38-
is positioned at the top-left. The plot uses a clean minimal theme with light
39-
gray dashed grid lines. The data clearly shows the damped oscillation pattern
40-
- high amplitude oscillations at the start that progressively decay toward zero
41-
as the sample index increases.
28+
- Grid still uses dashed style rather than solid subtle lines with opacity RULE
29+
token — replace panel_grid linetype with solid and use RULE color token
30+
- 'LM-02 opportunity missed: letsplot''s interactive HTML output could configure
31+
tooltips showing sample index and amplitude value on hover'
32+
image_description: |-
33+
Light render (plot-light.png):
34+
Background: Warm off-white consistent with #FAF8F1 — correct, not pure white
35+
Chrome: Title "stem-basic · letsplot · anyplot.ai" in dark text (top-left), x-axis "Sample Index" and y-axis "Amplitude (a.u.)" labels in dark text, dark tick labels — all clearly readable
36+
Data: 30 teal-green stems (#009E73) as thin vertical lines from y=0 baseline to data points, with filled circular markers at tips; dark horizontal baseline at y=0; two dashed decay-envelope curves bracket the oscillation
37+
Legibility verdict: PASS
38+
39+
Dark render (plot-dark.png):
40+
Background: Near-black consistent with #1A1A17 — correct dark theme
41+
Chrome: Title, axis labels, and tick labels appear in light near-white text — all clearly readable against dark background; no dark-on-dark text failures observed; baseline adapts to lighter tone; grid lines visible in lighter tone
42+
Data: Teal-green stems and markers identical in color to light render (#009E73) — only chrome flipped, data colors unchanged; envelope curves also identical in color
43+
Legibility verdict: PASS
4244
criteria_checklist:
4345
visual_quality:
44-
score: 36
45-
max: 40
46+
score: 28
47+
max: 30
4648
items:
4749
- id: VQ-01
4850
name: Text Legibility
49-
score: 10
50-
max: 10
51+
score: 7
52+
max: 8
5153
passed: true
52-
comment: Title, axis labels, and tick marks are all clearly readable at proper
53-
sizes
54+
comment: Font sizes set (title 24, axis 20, tick 16); readable in both themes;
55+
slight concern about title size relative to 4800x2700 canvas
5456
- id: VQ-02
5557
name: No Overlap
56-
score: 8
57-
max: 8
58+
score: 6
59+
max: 6
5860
passed: true
59-
comment: No overlapping text elements
61+
comment: Clean separation, no overlapping elements in either render
6062
- id: VQ-03
6163
name: Element Visibility
62-
score: 8
63-
max: 8
64+
score: 5
65+
max: 6
6466
passed: true
65-
comment: Stems and markers are well-sized for the 30 data points, appropriate
66-
alpha
67+
comment: Stems and markers clearly visible; near-zero stems are very short
68+
but distinguishable
6769
- id: VQ-04
6870
name: Color Accessibility
69-
score: 5
70-
max: 5
71+
score: 2
72+
max: 2
7173
passed: true
72-
comment: Single blue color scheme is colorblind-safe
74+
comment: Single series, good contrast against both light and dark surfaces
7375
- id: VQ-05
74-
name: Layout Balance
75-
score: 5
76-
max: 5
76+
name: Layout & Canvas
77+
score: 4
78+
max: 4
7779
passed: true
78-
comment: Good proportions, plot fills canvas well with balanced margins
80+
comment: Good 16:9 proportions, plot fills canvas well, no cut-off elements
7981
- id: VQ-06
80-
name: Axis Labels
81-
score: 1
82+
name: Axis Labels & Title
83+
score: 2
8284
max: 2
83-
passed: false
84-
comment: Descriptive labels but no units ("Amplitude" could specify units)
85+
passed: true
86+
comment: Amplitude (a.u.) with units and Sample Index are descriptive
8587
- id: VQ-07
86-
name: Grid & Legend
87-
score: 1
88+
name: Palette Compliance
89+
score: 2
8890
max: 2
91+
passed: true
92+
comment: 'First series #009E73; light background ~#FAF8F1; dark background
93+
~#1A1A17; chrome is theme-adaptive in both renders'
94+
design_excellence:
95+
score: 12
96+
max: 20
97+
items:
98+
- id: DE-01
99+
name: Aesthetic Sophistication
100+
score: 5
101+
max: 8
102+
passed: true
103+
comment: Correct Okabe-Ito brand color, theme-adaptive chrome, decay envelope
104+
curves elevate above plain default; not yet publication-ready
105+
- id: DE-02
106+
name: Visual Refinement
107+
score: 3
108+
max: 6
89109
passed: false
90-
comment: Grid is subtle with dashed lines, but baseline could have better
91-
contrast
110+
comment: Grid remains dashed rather than solid subtle lines with opacity token;
111+
improved over attempt 1 but still not fully refined
112+
- id: DE-03
113+
name: Data Storytelling
114+
score: 4
115+
max: 6
116+
passed: true
117+
comment: Decay envelope curves actively guide the viewer to understand the
118+
damped oscillation; signal processing story is clear
92119
spec_compliance:
93-
score: 25
94-
max: 25
120+
score: 15
121+
max: 15
95122
items:
96123
- id: SC-01
97124
name: Plot Type
98-
score: 8
99-
max: 8
100-
passed: true
101-
comment: Correct stem plot implementation using segments + points
102-
- id: SC-02
103-
name: Data Mapping
104125
score: 5
105126
max: 5
106127
passed: true
107-
comment: X/Y correctly assigned (sample index vs amplitude)
108-
- id: SC-03
128+
comment: Correct stem plot via geom_segment + geom_point + geom_hline baseline
129+
- id: SC-02
109130
name: Required Features
110-
score: 5
111-
max: 5
131+
score: 4
132+
max: 4
112133
passed: true
113-
comment: 'All spec features present: vertical stems, markers at top, baseline
114-
at y=0'
115-
- id: SC-04
116-
name: Data Range
134+
comment: Thin stems, clear circular markers, y=0 baseline, consistent styling
135+
throughout
136+
- id: SC-03
137+
name: Data Mapping
117138
score: 3
118139
max: 3
119140
passed: true
120-
comment: Axes show all data appropriately
121-
- id: SC-05
122-
name: Legend Accuracy
123-
score: 2
124-
max: 2
125-
passed: true
126-
comment: No legend needed, N/A
127-
- id: SC-06
128-
name: Title Format
129-
score: 2
130-
max: 2
141+
comment: x=Sample Index, y=Amplitude, all 30 data points shown
142+
- id: SC-04
143+
name: Title & Legend
144+
score: 3
145+
max: 3
131146
passed: true
132-
comment: 'Uses correct format: "stem-basic · letsplot · pyplots.ai"'
147+
comment: Title stem-basic · letsplot · anyplot.ai correct; no legend appropriate
148+
for single series
133149
data_quality:
134-
score: 18
135-
max: 20
150+
score: 15
151+
max: 15
136152
items:
137153
- id: DQ-01
138154
name: Feature Coverage
139-
score: 7
140-
max: 8
155+
score: 6
156+
max: 6
141157
passed: true
142-
comment: Shows damped oscillation with both positive and negative values,
143-
good variety
158+
comment: Stems both above and below baseline; decay pattern demonstrates temporal
159+
variation; 30 points show full range
144160
- id: DQ-02
145161
name: Realistic Context
146-
score: 7
147-
max: 7
162+
score: 5
163+
max: 5
148164
passed: true
149-
comment: Damped oscillation is a realistic signal processing scenario
165+
comment: Damped oscillation is canonical signal processing scenario; neutral,
166+
scientific
150167
- id: DQ-03
151168
name: Appropriate Scale
152169
score: 4
153-
max: 5
154-
passed: false
155-
comment: Values are sensible but somewhat abstract without real-world context
170+
max: 4
171+
passed: true
172+
comment: Values in ~[-0.7, 1.0] normalized amplitude range; physically plausible
156173
code_quality:
157174
score: 10
158175
max: 10
@@ -162,41 +179,58 @@ review:
162179
score: 3
163180
max: 3
164181
passed: true
165-
comment: 'Simple script: imports → data → plot → save'
182+
comment: No functions/classes, clean linear script
166183
- id: CQ-02
167184
name: Reproducibility
168-
score: 3
169-
max: 3
185+
score: 2
186+
max: 2
170187
passed: true
171-
comment: Uses np.random.seed(42)
188+
comment: np.random.seed(42)
172189
- id: CQ-03
173190
name: Clean Imports
174191
score: 2
175192
max: 2
176193
passed: true
177-
comment: All imports are used
194+
comment: Only used imports; noqa for star import is acceptable for letsplot
178195
- id: CQ-04
179-
name: No Deprecated API
180-
score: 1
181-
max: 1
196+
name: Code Elegance
197+
score: 2
198+
max: 2
182199
passed: true
183-
comment: Uses current lets-plot API
200+
comment: Appropriate complexity, envelope curves are a clean addition
184201
- id: CQ-05
185-
name: Output Correct
202+
name: Output & API
186203
score: 1
187204
max: 1
188205
passed: true
189-
comment: Saves as plot.png and plot.html
190-
library_features:
191-
score: 3
192-
max: 5
206+
comment: Output files plot-light.png/plot-dark.png and plot-light.html/plot-dark.html
207+
confirmed present
208+
library_mastery:
209+
score: 6
210+
max: 10
193211
items:
194-
- id: LF-01
195-
name: Uses distinctive library features
196-
score: 3
212+
- id: LM-01
213+
name: Idiomatic Usage
214+
score: 4
215+
max: 5
216+
passed: true
217+
comment: Correct ggplot grammar, geom_segment+geom_point for stems is idiomatic,
218+
ANYPLOT_THEME pattern applied
219+
- id: LM-02
220+
name: Distinctive Features
221+
score: 2
197222
max: 5
198223
passed: false
199-
comment: Uses ggplot grammar correctly with geom_segment + geom_point combination,
200-
but doesn't leverage any uniquely lets-plot features like interactivity
201-
or tooltips
224+
comment: HTML export present (letsplot distinctive); envelope curves via geom_line
225+
layer; interactive tooltips not configured
202226
verdict: APPROVED
227+
impl_tags:
228+
dependencies: []
229+
techniques:
230+
- layer-composition
231+
- html-export
232+
patterns:
233+
- data-generation
234+
dataprep: []
235+
styling:
236+
- alpha-blending

0 commit comments

Comments
 (0)