Skip to content

Commit 2bfb71a

Browse files
feat(pygal): implement scatter-basic (#5324)
## Implementation: `scatter-basic` - python/pygal Implements the **python/pygal** version of `scatter-basic`. **File:** `plots/scatter-basic/implementations/python/pygal.py` **Parent Issue:** #611 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/24860707249)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 5102331 commit 2bfb71a

2 files changed

Lines changed: 84 additions & 79 deletions

File tree

plots/scatter-basic/implementations/python/pygal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" anyplot.ai
22
scatter-basic: Basic Scatter Plot
33
Library: pygal 3.1.0 | Python 3.14.4
4-
Quality: 87/100 | Created: 2026-04-23
4+
Quality: 86/100 | Updated: 2026-04-23
55
"""
66

77
import os

plots/scatter-basic/metadata/python/pygal.yaml

Lines changed: 83 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2,123 +2,129 @@ library: pygal
22
language: python
33
specification_id: scatter-basic
44
created: '2025-12-10T20:55:10Z'
5-
updated: '2026-04-23T19:43:30Z'
5+
updated: '2026-04-23T22:06:20Z'
66
generated_by: claude-opus
7-
workflow_run: 24853810841
7+
workflow_run: 24860707249
88
issue: 611
99
python_version: 3.14.4
1010
library_version: 3.1.0
1111
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/pygal/plot-light.png
1212
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/pygal/plot-dark.png
1313
preview_html_light: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/pygal/plot-light.html
1414
preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/scatter-basic/python/pygal/plot-dark.html
15-
quality_score: 87
15+
quality_score: 86
1616
review:
1717
strengths:
18-
- 'Perfect visual quality across both themes: correct Okabe-Ito palette, theme-adaptive
19-
chrome, explicit font sizing, no overlap'
20-
- Strong data storytelling via the 70% passing-threshold split — viewer immediately
21-
grasps the study→outcome narrative
22-
- Flawless spec compliance and code structure; clean KISS code with proper seed
23-
and correct pygal.XY() usage
18+
- 'Excellent data storytelling: splitting data at 70% passing threshold creates
19+
a meaningful visual narrative that guides the viewer'
20+
- Perfect Okabe-Ito palette compliance — brand green (#009E73) as first series,
21+
orange (#D55E00) as second, consistent across both renders
22+
- 'Both light and dark themes render cleanly: correct warm off-white (#FAF8F1) and
23+
near-black (#1A1A17) backgrounds with all text readable in both'
24+
- Clean, minimal code structure with deterministic seed (np.random.seed(42)) and
25+
no functions or classes
26+
- Interactive HTML output correctly generated alongside PNG, using js=[] to remove
27+
external CDN dependencies for offline reliability
28+
- Axis labels carry units ('hrs' and '%') and the data context (study hours vs exam
29+
scores) is realistic and neutral
2430
weaknesses:
25-
- 'DE-01 (4/8): Still reads as a well-configured library default — no standout design
26-
element (trend line, custom hover template, refined marker styling) to elevate
27-
to publication quality'
28-
- 'DE-02 (2/6): Visual refinement limited — both x+y grids active, chart frame on
29-
all sides, margin=60 is small for 4800px canvas; pygal restricts spine removal
30-
but grids can be reduced'
31-
- 'LM-02 (3/5): Does not exploit pygal strongest distinctive feature — rich interactive
32-
SVG tooltips; js=[] suppresses all interactivity; a more distinctive implementation
33-
leverages pygal interactive nature'
31+
- 'INK_MUTED for dark theme is #6E6D66, which deviates from the style guide value
32+
#A8A79F — the dark value is too close to the background and may make grid lines/subtle
33+
text less visible than intended'
34+
- Font sizes (52px title, 40px labels) significantly exceed the pixel-based library
35+
guideline of 28px/22px — renders look fine but are outside spec; may affect visual
36+
proportions at different viewport sizes
37+
- Minor point crowding in the low-study-hours / below-70% region; the 180 points
38+
with opacity=0.7 reveal overlap reasonably, but larger dot sizes (dots_size=17)
39+
amplify collision in dense areas
3440
image_description: |-
3541
Light render (plot-light.png):
36-
Background: Warm off-white (#FAF8F1) — correct, not pure white
37-
Chrome: Title "scatter-basic · pygal · anyplot.ai" in dark ink at top — readable. Axis labels "Study Hours per Week (hrs)" and "Exam Score (%)" in dark ink — readable. Tick labels on both axes in dark ink — readable. Both x+y grid lines subtle.
38-
Data: First series "Passing (≥ 70%)" in #009E73 (brand green/teal), second series "Below 70%" in #D55E00 (orange). 180 dots at opacity=0.7. Clear positive correlation visible. Legend at bottom with two columns.
39-
Legibility verdict: PASS
42+
Background: Warm off-white consistent with #FAF8F1 — correct theme surface, not pure white.
43+
Chrome: Title "scatter-basic · pygal · anyplot.ai" centered at top in dark ink, clearly readable. X-axis label "Study Hours per Week (hrs)" and Y-axis label "Exam Score (%)" both visible in dark text. Tick labels (1.0–14.0 hrs on X; 20%–100% on Y) rendered in dark secondary text against the light background — all legible. Grid lines are subtle but present on both axes.
44+
Data: Two series — teal/green (#009E73, "Passing ≥ 70%") dots clustered in the upper-right, and orange (#D55E00, "Below 70%") dots clustered in the lower-left, with a clear positive correlation trend visible across 180 points. Dot size and 70% opacity balance visibility against overlap. Legend at bottom shows both series labels clearly.
45+
Legibility verdict: PASS — all text readable against the light background; no light-on-light failures.
4046
4147
Dark render (plot-dark.png):
42-
Background: Near-black (#1A1A17) — correct, not pure black
43-
Chrome: Title, axis labels, and tick labels all rendered in light text clearly readable against dark background. No dark-on-dark failures detected. Grid lines subtle and visible.
44-
Data: Colors identical to light render — teal (#009E73) and orange (#D55E00) dots both visible against dark background. Brand green #009E73 clearly readable on dark surface.
45-
Legibility verdict: PASS
48+
Background: Near-black consistent with #1A1A17 — correct dark surface, not pure black.
49+
Chrome: Title and axis labels rendered in light/off-white text (#F0EFE8), clearly readable against the dark background. Tick labels also appear as light text — no dark-on-dark failures observed. Grid lines are subtle but visible as slightly lighter lines against the dark background.
50+
Data: Data colors are identical to the light render — same teal (#009E73) and orange (#D55E00) dots with the same distribution. Okabe-Ito positions 1–2 are unchanged between themes, confirming correct theme-adaptive implementation.
51+
Legibility verdict: PASS — all text is readable against the dark background; no dark-on-dark failures detected.
4652
criteria_checklist:
4753
visual_quality:
48-
score: 30
54+
score: 28
4955
max: 30
5056
items:
5157
- id: VQ-01
5258
name: Text Legibility
53-
score: 8
59+
score: 7
5460
max: 8
5561
passed: true
56-
comment: 'All font sizes explicitly set: title 52px, labels 40px, major_labels
57-
36px, legend 34px; readable in both themes'
62+
comment: All text readable in both themes; font sizes (52px title, 40px label)
63+
above the 28px/22px guideline but renders look proportionate
5864
- id: VQ-02
5965
name: No Overlap
60-
score: 6
66+
score: 5
6167
max: 6
6268
passed: true
63-
comment: No overlapping text elements; legend at bottom cleanly separated
69+
comment: Some point crowding in dense lower-left region; opacity=0.7 and dot
70+
separation help but overlap is visible at dots_size=17
6471
- id: VQ-03
6572
name: Element Visibility
6673
score: 6
6774
max: 6
6875
passed: true
69-
comment: dots_size=17 with opacity=0.7 well-matched to 180 points
76+
comment: Both series clearly visible with good marker size and Okabe-Ito contrast
7077
- id: VQ-04
7178
name: Color Accessibility
7279
score: 2
7380
max: 2
7481
passed: true
75-
comment: Okabe-Ito positions 1+2 (teal/orange) are CVD-safe and high-contrast
82+
comment: Okabe-Ito palette is CVD-safe; green/orange provide adequate contrast
7683
- id: VQ-05
7784
name: Layout & Canvas
7885
score: 4
7986
max: 4
8087
passed: true
81-
comment: Scatter fills 60-70% of canvas; margins balanced; no content cut
82-
off
88+
comment: 4800x2700 landscape, generous margins, legend at bottom not obstructing
89+
data
8390
- id: VQ-06
8491
name: Axis Labels & Title
8592
score: 2
8693
max: 2
8794
passed: true
88-
comment: 'Labels include units: Study Hours per Week (hrs) and Exam Score
89-
(%)'
95+
comment: Axis labels include units (hrs, %)
9096
- id: VQ-07
9197
name: Palette Compliance
9298
score: 2
9399
max: 2
94100
passed: true
95-
comment: 'First series #009E73, second #D55E00; backgrounds #FAF8F1/#1A1A17;
96-
theme-correct chrome in both renders'
101+
comment: 'First series #009E73, second #D55E00; light #FAF8F1 and dark #1A1A17
102+
backgrounds; data colors identical between themes'
97103
design_excellence:
98-
score: 10
104+
score: 12
99105
max: 20
100106
items:
101107
- id: DE-01
102108
name: Aesthetic Sophistication
103-
score: 4
109+
score: 5
104110
max: 8
105-
passed: false
106-
comment: Well-configured style (Okabe-Ito, explicit fonts, semantic colors)
107-
but overall look is a polished library default
111+
passed: true
112+
comment: Intentional data split at 70% passing threshold adds narrative hierarchy
113+
above generic defaults
108114
- id: DE-02
109115
name: Visual Refinement
110-
score: 2
116+
score: 3
111117
max: 6
112-
passed: false
113-
comment: Both x+y grids visible; no spine removal (pygal limits this); minimal
114-
refinement beyond default chart frame
118+
passed: true
119+
comment: Grid appropriate for scatter, clean font family, bottom legend —
120+
limited refinement options within pygal API
115121
- id: DE-03
116122
name: Data Storytelling
117123
score: 4
118124
max: 6
119125
passed: true
120-
comment: 70% threshold split and semantic color encoding immediately convey
121-
study-outcome narrative
126+
comment: Pass/fail split creates clear focal point and communicates the study-hours-to-outcome
127+
narrative effectively
122128
spec_compliance:
123129
score: 15
124130
max: 15
@@ -128,51 +134,52 @@ review:
128134
score: 5
129135
max: 5
130136
passed: true
131-
comment: pygal.XY() is correct scatter implementation
137+
comment: pygal.XY() with stroke=False is the correct scatter plot type
132138
- id: SC-02
133139
name: Required Features
134140
score: 4
135141
max: 4
136142
passed: true
137-
comment: Transparency (opacity=0.7), axis labels, descriptive title, grid
138-
lines all present; 180-point dataset
143+
comment: Transparency (opacity=0.7), axis labels, title, grid lines all present
139144
- id: SC-03
140145
name: Data Mapping
141146
score: 3
142147
max: 3
143148
passed: true
144-
comment: Study hours on x, exam scores on y; all data visible within specified
145-
ranges
149+
comment: Study hours on X (independent), exam scores on Y (dependent), 180
150+
points in range, positive correlation visible
146151
- id: SC-04
147152
name: Title & Legend
148153
score: 3
149154
max: 3
150155
passed: true
151-
comment: Title 'scatter-basic · pygal · anyplot.ai' correct format; legend
152-
labels meaningful
156+
comment: Title is 'scatter-basic · pygal · anyplot.ai'; legend labels 'Passing
157+
(≥ 70%)' and 'Below 70%' match data series
153158
data_quality:
154-
score: 15
159+
score: 14
155160
max: 15
156161
items:
157162
- id: DQ-01
158163
name: Feature Coverage
159-
score: 6
164+
score: 5
160165
max: 6
161166
passed: true
162-
comment: Shows full positive-correlation scatter with realistic noise, visible
163-
spread, and outliers
167+
comment: Good coverage of scatter fundamentals; two-series split adds dimension;
168+
no regression line or additional annotation layer
164169
- id: DQ-02
165170
name: Realistic Context
166171
score: 5
167172
max: 5
168173
passed: true
169-
comment: Study hours vs exam scores is a neutral, real-world educational scenario
174+
comment: Study hours vs exam scores is classic, neutral, real-world scenario
175+
with plausible ranges
170176
- id: DQ-03
171177
name: Appropriate Scale
172178
score: 4
173179
max: 4
174180
passed: true
175-
comment: Study hours 1.5-13.5 hrs/week, exam scores 20-100% — realistic values
181+
comment: 1–14 hours and 20–100% are realistic; 180 data points is within recommended
182+
50–500 range
176183
code_quality:
177184
score: 10
178185
max: 10
@@ -182,32 +189,32 @@ review:
182189
score: 3
183190
max: 3
184191
passed: true
185-
comment: Flat imports->data->style->chart->save; no functions or classes
192+
comment: Linear script, no functions or classes
186193
- id: CQ-02
187194
name: Reproducibility
188195
score: 2
189196
max: 2
190197
passed: true
191-
comment: np.random.seed(42) set
198+
comment: np.random.seed(42) ensures deterministic output
192199
- id: CQ-03
193200
name: Clean Imports
194201
score: 2
195202
max: 2
196203
passed: true
197-
comment: Only os, sys, numpy, pygal, pygal.style.Style used
204+
comment: All imports used; sys used for path manipulation workaround
198205
- id: CQ-04
199206
name: Code Elegance
200207
score: 2
201208
max: 2
202209
passed: true
203-
comment: Clean, Pythonic; sys.path.pop(0) workaround explained; appropriate
204-
complexity
210+
comment: Clean structure; sys.path.pop(0) workaround is necessary and explained;
211+
noqa comments justified
205212
- id: CQ-05
206213
name: Output & API
207214
score: 1
208215
max: 1
209216
passed: true
210-
comment: Saves plot-{THEME}.png and plot-{THEME}.html; current pygal API
217+
comment: Saves plot-{THEME}.png and plot-{THEME}.html correctly
211218
library_mastery:
212219
score: 7
213220
max: 10
@@ -217,24 +224,22 @@ review:
217224
score: 4
218225
max: 5
219226
passed: true
220-
comment: Uses pygal.XY() with XY coordinate tuples, Style object, value/x_value
221-
formatters, legend_at_bottom_columns, range/xrange
227+
comment: Correct pygal.XY() for scatter, Style object for theming, xrange/range
228+
for axis control, lambda formatters
222229
- id: LM-02
223230
name: Distinctive Features
224231
score: 3
225232
max: 5
226-
passed: false
227-
comment: Interactive HTML output, custom formatters, dots_size control; js=[]
228-
suppresses interactivity; could exploit pygal tooltip customization or SVG
229-
features more
230-
verdict: REJECTED
233+
passed: true
234+
comment: Interactive HTML output, opacity_hover for hover state, js=[] for
235+
offline/CDN-free output, value_formatter for tooltip customization
236+
verdict: APPROVED
231237
impl_tags:
232238
dependencies: []
233239
techniques:
234240
- html-export
235241
patterns:
236242
- data-generation
237-
- iteration-over-groups
238243
dataprep: []
239244
styling:
240245
- alpha-blending

0 commit comments

Comments
 (0)