Skip to content

Commit 6305303

Browse files
feat(matplotlib): implement scatter-lag (#5270)
## Implementation: `scatter-lag` - matplotlib Implements the **matplotlib** version of `scatter-lag`. **File:** `plots/scatter-lag/implementations/matplotlib.py` **Parent Issue:** #5251 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/24313009889)* --------- 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 2390f0a commit 6305303

File tree

2 files changed

+308
-0
lines changed

2 files changed

+308
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
""" pyplots.ai
2+
scatter-lag: Lag Plot for Time Series Autocorrelation Diagnosis
3+
Library: matplotlib 3.10.8 | Python 3.14.3
4+
Quality: 85/100 | Created: 2026-04-12
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
10+
11+
# Data — synthetic AR(1) process with strong positive autocorrelation
12+
np.random.seed(42)
13+
n_observations = 500
14+
phi = 0.85
15+
noise = np.random.normal(0, 1, n_observations)
16+
series = np.zeros(n_observations)
17+
series[0] = noise[0]
18+
for i in range(1, n_observations):
19+
series[i] = phi * series[i - 1] + noise[i]
20+
21+
lag = 1
22+
y_t = series[:-lag]
23+
y_t_lag = series[lag:]
24+
time_index = np.arange(len(y_t))
25+
26+
# Correlation
27+
r_value = np.corrcoef(y_t, y_t_lag)[0, 1]
28+
29+
# Plot
30+
fig, ax = plt.subplots(figsize=(16, 9))
31+
32+
scatter = ax.scatter(
33+
y_t, y_t_lag, c=time_index, cmap="viridis", s=120, alpha=0.65, edgecolors="white", linewidth=0.5, zorder=2
34+
)
35+
36+
# Diagonal reference line (y = x)
37+
data_min = min(y_t.min(), y_t_lag.min())
38+
data_max = max(y_t.max(), y_t_lag.max())
39+
margin = (data_max - data_min) * 0.05
40+
ax.plot(
41+
[data_min - margin, data_max + margin],
42+
[data_min - margin, data_max + margin],
43+
color="#AAAAAA",
44+
linewidth=2,
45+
linestyle="--",
46+
alpha=0.6,
47+
zorder=1,
48+
)
49+
50+
# Colorbar
51+
cbar = fig.colorbar(scatter, ax=ax, pad=0.02, aspect=30)
52+
cbar.set_label("Time Index", fontsize=18)
53+
cbar.ax.tick_params(labelsize=14)
54+
55+
# Correlation annotation
56+
ax.text(
57+
0.04,
58+
0.96,
59+
f"r = {r_value:.3f}",
60+
transform=ax.transAxes,
61+
fontsize=20,
62+
verticalalignment="top",
63+
fontweight="medium",
64+
color="#333333",
65+
)
66+
67+
# Style
68+
ax.set_xlabel("y(t)", fontsize=20)
69+
ax.set_ylabel(f"y(t + {lag})", fontsize=20)
70+
ax.set_title("AR(1) Autocorrelation · scatter-lag · matplotlib · pyplots.ai", fontsize=24, fontweight="medium")
71+
ax.tick_params(axis="both", labelsize=16)
72+
ax.spines["top"].set_visible(False)
73+
ax.spines["right"].set_visible(False)
74+
ax.grid(True, alpha=0.2, linewidth=0.8)
75+
76+
plt.tight_layout()
77+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
library: matplotlib
2+
specification_id: scatter-lag
3+
created: '2026-04-12T18:10:35Z'
4+
updated: '2026-04-12T18:25:18Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 24313009889
7+
issue: 5251
8+
python_version: 3.14.3
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/scatter-lag/matplotlib/plot.png
11+
preview_html: null
12+
quality_score: 85
13+
review:
14+
strengths:
15+
- 'Perfect code quality: clean KISS structure, seed set, correct API throughout'
16+
- Temporal color encoding via viridis clearly reveals time structure in the scatter
17+
- r=0.834 annotation with ax.transAxes relative positioning is well-executed
18+
- 'All required spec features implemented: diagonal reference line, time-index color,
19+
r-value annotation'
20+
- Font sizes explicitly set at all levels for high-res output
21+
weaknesses:
22+
- Marker size s=120 too large for 499 data points causing dense overlap; reduce
23+
to s=50-60, alpha=0.45-0.55
24+
- Title format deviates from spec-id · library · pyplots.ai — has extra AR(1) Autocorrelation
25+
prefix
26+
- Full x+y gridlines instead of preferred y-axis-only grid
27+
- Generic annotation box style; needs subtle white background bbox with no border
28+
edge
29+
image_description: The plot shows a scatter plot of an AR(1) time series against
30+
its lag-1 version. The x-axis is labeled "y(t)" and the y-axis "y(t + 1)", with
31+
values ranging roughly from -4.5 to 5.5 on both axes. Approximately 499 data points
32+
are colored using the viridis colormap, transitioning from dark purple (time index
33+
0) to bright yellow (time index ~499), with a colorbar on the right labeled "Time
34+
Index". A dashed diagonal reference line (y = x) runs from lower-left to upper-right
35+
in light gray. The data forms a strong linear cluster along the diagonal, visually
36+
confirming high positive autocorrelation. An annotation in the upper-left corner
37+
shows "r = 0.834" in bold. The title reads "AR(1) Autocorrelation · scatter-lag
38+
· matplotlib · pyplots.ai". Top and right spines are removed; a subtle grid (alpha=0.2)
39+
is visible. The overall layout is clean and professional on a light background
40+
with a 16:9 aspect ratio.
41+
criteria_checklist:
42+
visual_quality:
43+
score: 28
44+
max: 30
45+
items:
46+
- id: VQ-01
47+
name: Text Legibility
48+
score: 8
49+
max: 8
50+
passed: true
51+
comment: 'All font sizes explicitly set: title=24, labels=20, ticks=16, colorbar
52+
label=18, colorbar ticks=14, annotation=20'
53+
- id: VQ-02
54+
name: No Overlap
55+
score: 6
56+
max: 6
57+
passed: true
58+
comment: No overlapping text or elements
59+
- id: VQ-03
60+
name: Element Visibility
61+
score: 4
62+
max: 6
63+
passed: true
64+
comment: s=120, alpha=0.65 for 499 points is too large per guideline (s=20-50
65+
for 300+); visible crowding in dense center
66+
- id: VQ-04
67+
name: Color Accessibility
68+
score: 4
69+
max: 4
70+
passed: true
71+
comment: Viridis colormap is perceptually uniform and colorblind-safe
72+
- id: VQ-05
73+
name: Layout & Canvas
74+
score: 4
75+
max: 4
76+
passed: true
77+
comment: Good canvas utilization, balanced margins, colorbar well-positioned
78+
- id: VQ-06
79+
name: Axis Labels & Title
80+
score: 2
81+
max: 2
82+
passed: true
83+
comment: y(t) and y(t+1) are standard notation for lag plots; appropriate
84+
and descriptive
85+
design_excellence:
86+
score: 12
87+
max: 20
88+
items:
89+
- id: DE-01
90+
name: Aesthetic Sophistication
91+
score: 4
92+
max: 8
93+
passed: true
94+
comment: Clean functional design; viridis and spine removal add polish but
95+
overall is a well-configured library default
96+
- id: DE-02
97+
name: Visual Refinement
98+
score: 4
99+
max: 6
100+
passed: true
101+
comment: Spines removed, subtle grid (alpha=0.2), tight_layout; deducted for
102+
full x+y grid instead of preferred y-axis-only
103+
- id: DE-03
104+
name: Data Storytelling
105+
score: 4
106+
max: 6
107+
passed: true
108+
comment: Temporal color encoding reveals time structure, r annotation quantifies
109+
the pattern, diagonal line guides interpretation
110+
spec_compliance:
111+
score: 14
112+
max: 15
113+
items:
114+
- id: SC-01
115+
name: Plot Type
116+
score: 5
117+
max: 5
118+
passed: true
119+
comment: 'Correct lag plot: scatter of y(t) vs y(t+k)'
120+
- id: SC-02
121+
name: Required Features
122+
score: 4
123+
max: 4
124+
passed: true
125+
comment: Diagonal y=x reference line, time-index color encoding, r-value annotation,
126+
configurable lag all present
127+
- id: SC-03
128+
name: Data Mapping
129+
score: 3
130+
max: 3
131+
passed: true
132+
comment: x=y(t), y=y(t+1), correct per spec
133+
- id: SC-04
134+
name: Title & Legend
135+
score: 2
136+
max: 3
137+
passed: false
138+
comment: Title has extra 'AR(1) Autocorrelation · ' prefix before spec-id;
139+
should start with scatter-lag · matplotlib · pyplots.ai
140+
data_quality:
141+
score: 14
142+
max: 15
143+
items:
144+
- id: DQ-01
145+
name: Feature Coverage
146+
score: 5
147+
max: 6
148+
passed: true
149+
comment: Strong autocorrelation case clearly demonstrated; missing contrast
150+
with random/uncorrelated case which spec explicitly describes
151+
- id: DQ-02
152+
name: Realistic Context
153+
score: 5
154+
max: 5
155+
passed: true
156+
comment: AR(1) synthetic process is explicitly listed in spec; neutral and
157+
scientifically appropriate
158+
- id: DQ-03
159+
name: Appropriate Scale
160+
score: 4
161+
max: 4
162+
passed: true
163+
comment: Values -4.5 to 5.5 are realistic for zero-mean AR(1) with Gaussian
164+
noise std=1
165+
code_quality:
166+
score: 10
167+
max: 10
168+
items:
169+
- id: CQ-01
170+
name: KISS Structure
171+
score: 3
172+
max: 3
173+
passed: true
174+
comment: Imports → Data → Plot → Save, no functions or classes
175+
- id: CQ-02
176+
name: Reproducibility
177+
score: 2
178+
max: 2
179+
passed: true
180+
comment: np.random.seed(42) set
181+
- id: CQ-03
182+
name: Clean Imports
183+
score: 2
184+
max: 2
185+
passed: true
186+
comment: Only matplotlib.pyplot and numpy, both used
187+
- id: CQ-04
188+
name: Code Elegance
189+
score: 2
190+
max: 2
191+
passed: true
192+
comment: Clean, Pythonic, appropriate complexity for AR(1) generation
193+
- id: CQ-05
194+
name: Output & API
195+
score: 1
196+
max: 1
197+
passed: true
198+
comment: Saves as plot.png, dpi=300, bbox_inches='tight', no deprecated functions
199+
library_mastery:
200+
score: 7
201+
max: 10
202+
items:
203+
- id: LM-01
204+
name: Idiomatic Usage
205+
score: 4
206+
max: 5
207+
passed: true
208+
comment: Uses ax.scatter with c= colormap, fig.colorbar(), ax methods throughout;
209+
correct but no advanced matplotlib patterns
210+
- id: LM-02
211+
name: Distinctive Features
212+
score: 3
213+
max: 5
214+
passed: true
215+
comment: c= parameter with colormap + colorbar on scatter is distinctive matplotlib;
216+
ax.transAxes for relative text placement is a nice touch
217+
verdict: REJECTED
218+
impl_tags:
219+
dependencies: []
220+
techniques:
221+
- annotations
222+
- colorbar
223+
patterns:
224+
- data-generation
225+
- explicit-figure
226+
dataprep: []
227+
styling:
228+
- alpha-blending
229+
- custom-colormap
230+
- edge-highlighting
231+
- grid-styling

0 commit comments

Comments
 (0)