diff --git a/plots/acf-pacf/implementations/python/plotly.py b/plots/acf-pacf/implementations/python/plotly.py
index dc46cc6d98..1e291df358 100644
--- a/plots/acf-pacf/implementations/python/plotly.py
+++ b/plots/acf-pacf/implementations/python/plotly.py
@@ -1,15 +1,33 @@
-""" pyplots.ai
+""" anyplot.ai
acf-pacf: Autocorrelation and Partial Autocorrelation (ACF/PACF) Plot
-Library: plotly 6.6.0 | Python 3.14.3
-Quality: 90/100 | Created: 2026-03-14
+Library: plotly 6.8.0 | Python 3.13.13
+Quality: 91/100 | Updated: 2026-06-10
"""
+import os
+
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
-# Data — simulate monthly retail sales with AR(2) structure
+# Theme tokens
+THEME = os.getenv("ANYPLOT_THEME", "light")
+PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
+ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
+INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
+INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
+INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F"
+GRID = "rgba(26,26,23,0.15)" if THEME == "light" else "rgba(240,239,232,0.15)"
+
+# Imprint palette — position 1 for significant lags
+BRAND = "#009E73"
+
+# Confidence band fill/border (INK_MUTED at low opacity)
+band_fill = "rgba(107,106,99,0.12)" if THEME == "light" else "rgba(168,167,159,0.12)"
+band_border = "rgba(107,106,99,0.40)" if THEME == "light" else "rgba(168,167,159,0.40)"
+
+# Data — monthly retail sales AR(2) process
np.random.seed(42)
n_obs = 200
ar1_coeff, ar2_coeff = 0.7, -0.3
@@ -45,14 +63,19 @@
lags_pacf = np.arange(1, n_lags + 1)
pacf_plot = pacf_values[1:]
-# Classify significant lags
acf_significant = np.abs(acf_values) > conf_bound
pacf_significant = np.abs(pacf_plot) > conf_bound
-# Colors
-sig_color = "#E8590C"
-nonsig_color = "#94A3B8"
-band_color = "rgba(148, 163, 184, 0.15)"
+# Build stem coords using None separators (one trace per class, not per stem)
+acf_sig_x, acf_sig_y, acf_nsig_x, acf_nsig_y = [], [], [], []
+for lag, val, sig in zip(lags_acf, acf_values, acf_significant, strict=False):
+ (acf_sig_x if sig else acf_nsig_x).extend([int(lag), int(lag), None])
+ (acf_sig_y if sig else acf_nsig_y).extend([0, float(val), None])
+
+pacf_sig_x, pacf_sig_y, pacf_nsig_x, pacf_nsig_y = [], [], [], []
+for lag, val, sig in zip(lags_pacf, pacf_plot, pacf_significant, strict=False):
+ (pacf_sig_x if sig else pacf_nsig_x).extend([int(lag), int(lag), None])
+ (pacf_sig_y if sig else pacf_nsig_y).extend([0, float(val), None])
# Plot
fig = make_subplots(
@@ -65,77 +88,95 @@
hover_tpl = "Lag %{x}
Correlation: %{y:.3f}"
-# ACF stems and markers (row 1)
-for i, lag in enumerate(lags_acf):
- color = sig_color if acf_significant[i] else nonsig_color
+# ACF stems (row 1)
+if acf_sig_x:
fig.add_trace(
go.Scatter(
- x=[lag, lag],
- y=[0, acf_values[i]],
+ x=acf_sig_x,
+ y=acf_sig_y,
mode="lines",
- line={"color": color, "width": 3},
+ line={"color": BRAND, "width": 3},
showlegend=False,
hoverinfo="skip",
),
row=1,
col=1,
)
-
-sig_mask_acf = acf_significant
-if np.any(sig_mask_acf):
+if acf_nsig_x:
+ fig.add_trace(
+ go.Scatter(
+ x=acf_nsig_x,
+ y=acf_nsig_y,
+ mode="lines",
+ line={"color": INK_MUTED, "width": 2},
+ showlegend=False,
+ hoverinfo="skip",
+ ),
+ row=1,
+ col=1,
+ )
+if np.any(acf_significant):
fig.add_trace(
go.Scatter(
- x=lags_acf[sig_mask_acf],
- y=acf_values[sig_mask_acf],
+ x=lags_acf[acf_significant],
+ y=acf_values[acf_significant],
mode="markers",
- marker={"size": 13, "color": sig_color, "line": {"color": "white", "width": 2}},
name="Significant",
- showlegend=True,
+ marker={"size": 12, "color": BRAND, "line": {"color": PAGE_BG, "width": 2}},
hovertemplate=hover_tpl,
),
row=1,
col=1,
)
-if np.any(~sig_mask_acf):
+if np.any(~acf_significant):
fig.add_trace(
go.Scatter(
- x=lags_acf[~sig_mask_acf],
- y=acf_values[~sig_mask_acf],
+ x=lags_acf[~acf_significant],
+ y=acf_values[~acf_significant],
mode="markers",
- marker={"size": 10, "color": nonsig_color, "line": {"color": "white", "width": 1.5}},
name="Non-significant",
- showlegend=True,
+ marker={"size": 9, "color": INK_MUTED, "line": {"color": PAGE_BG, "width": 1.5}},
hovertemplate=hover_tpl,
),
row=1,
col=1,
)
-# PACF stems and markers (row 2)
-for i, lag in enumerate(lags_pacf):
- color = sig_color if pacf_significant[i] else nonsig_color
+# PACF stems (row 2)
+if pacf_sig_x:
fig.add_trace(
go.Scatter(
- x=[lag, lag],
- y=[0, pacf_plot[i]],
+ x=pacf_sig_x,
+ y=pacf_sig_y,
mode="lines",
- line={"color": color, "width": 3},
+ line={"color": BRAND, "width": 3},
+ showlegend=False,
+ hoverinfo="skip",
+ ),
+ row=2,
+ col=1,
+ )
+if pacf_nsig_x:
+ fig.add_trace(
+ go.Scatter(
+ x=pacf_nsig_x,
+ y=pacf_nsig_y,
+ mode="lines",
+ line={"color": INK_MUTED, "width": 2},
showlegend=False,
hoverinfo="skip",
),
row=2,
col=1,
)
-
if np.any(pacf_significant):
fig.add_trace(
go.Scatter(
x=lags_pacf[pacf_significant],
y=pacf_plot[pacf_significant],
mode="markers",
- marker={"size": 13, "color": sig_color, "line": {"color": "white", "width": 2}},
- name="Significant",
showlegend=False,
+ marker={"size": 12, "color": BRAND, "line": {"color": PAGE_BG, "width": 2}},
hovertemplate=hover_tpl,
),
row=2,
@@ -147,16 +188,15 @@
x=lags_pacf[~pacf_significant],
y=pacf_plot[~pacf_significant],
mode="markers",
- marker={"size": 10, "color": nonsig_color, "line": {"color": "white", "width": 1.5}},
- name="Non-significant",
showlegend=False,
+ marker={"size": 9, "color": INK_MUTED, "line": {"color": PAGE_BG, "width": 1.5}},
hovertemplate=hover_tpl,
),
row=2,
col=1,
)
-# Shaded confidence bands and zero lines for both subplots
+# Confidence bands and zero baselines
for row in [1, 2]:
x_start, x_end = (0, n_lags) if row == 1 else (1, n_lags)
fig.add_trace(
@@ -164,8 +204,8 @@
x=[x_start, x_end, x_end, x_start],
y=[conf_bound, conf_bound, -conf_bound, -conf_bound],
fill="toself",
- fillcolor=band_color,
- line={"color": "rgba(148, 163, 184, 0.4)", "width": 1, "dash": "dash"},
+ fillcolor=band_fill,
+ line={"color": band_border, "width": 1, "dash": "dash"},
showlegend=(row == 1),
name="95% Confidence",
hoverinfo="skip",
@@ -178,7 +218,7 @@
x=[x_start, x_end],
y=[0, 0],
mode="lines",
- line={"color": "#CBD5E1", "width": 1},
+ line={"color": INK_SOFT, "width": 1.5},
showlegend=False,
hoverinfo="skip",
),
@@ -186,61 +226,74 @@
col=1,
)
+# Title (length-adaptive font size)
+title_str = "Monthly Retail Sales · acf-pacf · python · plotly · anyplot.ai"
+subtitle = "AR(2) Process (n=200, φ₁=0.7, φ₂=−0.3)"
+n = len(title_str)
+title_size = round(16 * (67 / n)) if n > 67 else 16
+
# Layout
fig.update_layout(
+ autosize=False,
+ width=800,
+ height=450,
+ template="plotly_white",
+ paper_bgcolor=PAGE_BG,
+ plot_bgcolor=PAGE_BG,
+ margin={"l": 90, "r": 50, "t": 130, "b": 100},
title={
- "text": (
- "acf-pacf · plotly · pyplots.ai"
- "
"
- "Monthly Retail Sales — AR(2) Process (n=200, φ₁=0.7, φ₂=−0.3)"
- ""
- ),
- "font": {"size": 28, "color": "#1E293B"},
+ "text": f"{title_str}
{subtitle}",
+ "font": {"size": title_size, "color": INK},
"x": 0.5,
"xanchor": "center",
},
- template="plotly_white",
- plot_bgcolor="#FAFBFC",
- paper_bgcolor="#FFFFFF",
- margin={"l": 90, "r": 50, "t": 120, "b": 70},
- height=900,
- width=1600,
- legend={"orientation": "h", "yanchor": "bottom", "y": 1.02, "xanchor": "right", "x": 1, "font": {"size": 16}},
- hoverlabel={"font_size": 16},
+ legend={
+ "orientation": "h",
+ "yanchor": "top",
+ "y": -0.18,
+ "xanchor": "center",
+ "x": 0.5,
+ "font": {"size": 10, "color": INK_SOFT},
+ "bgcolor": ELEVATED_BG,
+ "bordercolor": INK_SOFT,
+ "borderwidth": 1,
+ },
+ hoverlabel={"font_size": 13},
)
-# Style subplot titles
+# Subplot title font
for annotation in fig.layout.annotations:
- annotation.font = {"size": 20, "color": "#475569"}
+ annotation.font = {"size": 13, "color": INK_SOFT}
# Y-axes
for row, label in [(1, "ACF (correlation)"), (2, "PACF (correlation)")]:
fig.update_yaxes(
title_text=label,
- title_font={"size": 22, "color": "#334155"},
- tickfont={"size": 18, "color": "#64748B"},
+ title_font={"size": 12, "color": INK},
+ tickfont={"size": 10, "color": INK_SOFT},
showgrid=True,
- gridcolor="rgba(0,0,0,0.05)",
- gridwidth=1,
+ gridcolor=GRID,
zeroline=False,
+ showline=True,
+ linecolor=INK_SOFT,
row=row,
col=1,
)
-# X-axes
+# X-axes (global then row-specific)
fig.update_xaxes(
- title_text="Lag (periods)",
- title_font={"size": 22, "color": "#334155"},
- tickfont={"size": 18, "color": "#64748B"},
+ tickfont={"size": 10, "color": INK_SOFT},
+ linecolor=INK_SOFT,
showgrid=False,
- row=2,
- col=1,
+ showspikes=True,
+ spikecolor=INK_MUTED,
+ spikethickness=1,
+ spikedash="dot",
+ spikemode="across",
)
-fig.update_xaxes(showgrid=False, tickfont={"size": 18, "color": "#64748B"}, row=1, col=1)
-
-# Spike lines for cross-subplot reference
-fig.update_xaxes(showspikes=True, spikecolor="#94A3B8", spikethickness=1, spikedash="dot", spikemode="across")
+fig.update_xaxes(showline=True, title_text="Lag (periods)", title_font={"size": 12, "color": INK}, row=2, col=1)
+fig.update_xaxes(showline=False, row=1, col=1)
# Save
-fig.write_image("plot.png", width=1600, height=900, scale=3)
-fig.write_html("plot.html", include_plotlyjs="cdn")
+fig.write_image(f"plot-{THEME}.png", width=800, height=450, scale=4)
+fig.write_html(f"plot-{THEME}.html", include_plotlyjs="cdn")
diff --git a/plots/acf-pacf/metadata/python/plotly.yaml b/plots/acf-pacf/metadata/python/plotly.yaml
index f621607865..9e5926eb6e 100644
--- a/plots/acf-pacf/metadata/python/plotly.yaml
+++ b/plots/acf-pacf/metadata/python/plotly.yaml
@@ -1,100 +1,158 @@
library: plotly
+language: python
specification_id: acf-pacf
created: '2026-03-14T22:18:42Z'
-updated: '2026-03-14T22:37:22Z'
-generated_by: claude-opus-4-5-20251101
-workflow_run: 23097477554
+updated: '2026-06-10T02:01:48Z'
+generated_by: claude-sonnet
+workflow_run: 27247137183
issue: 4663
-python_version: 3.14.3
-library_version: 6.6.0
-preview_url: https://storage.googleapis.com/anyplot-images/plots/acf-pacf/plotly/plot.png
-preview_html: https://storage.googleapis.com/anyplot-images/plots/acf-pacf/plotly/plot.html
-quality_score: 90
+language_version: 3.13.13
+library_version: 6.8.0
+preview_url_light: https://storage.googleapis.com/anyplot-images/plots/acf-pacf/python/plotly/plot-light.png
+preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/acf-pacf/python/plotly/plot-dark.png
+preview_html_light: https://storage.googleapis.com/anyplot-images/plots/acf-pacf/python/plotly/plot-light.html
+preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/acf-pacf/python/plotly/plot-dark.html
+quality_score: 91
review:
strengths:
- - Perfect spec compliance with all required features (stem lines, confidence bands,
- lag 0 in ACF, PACF from lag 1)
- - 'Excellent data choice: AR(2) process creates textbook-quality ACF/PACF demonstration'
- - Strong visual hierarchy through significant/non-significant color and size differentiation
- - Good use of Plotly interactivity (hover tooltips, spike lines, HTML export)
- - All font sizes explicitly set and well-calibrated for output resolution
+ - 'Excellent significant/non-significant visual encoding: green (#009E73) stems+markers
+ vs muted grey creates immediate visual hierarchy that guides the viewer to meaningful
+ lags'
+ - 'Perfect spec compliance: ACF top / PACF bottom with shared x-axis, lag-0 in ACF,
+ PACF starting at lag 1, 95% confidence band as filled polygon with dashed border,
+ 35 lags in correct range'
+ - 'Idiomatic Plotly usage: make_subplots with shared_xaxes, None-separator multi-segment
+ line trick for efficient stem rendering, hover templates with ,
+ spike lines across both subplots'
+ - 'Full theme adaptation: all chrome tokens (title, axis labels, tick labels, legend,
+ grid, backgrounds, confidence band fill) correctly switch between #FAF8F1 / #1A1A17
+ surfaces with no dark-on-dark failures'
+ - Correct and self-contained PACF implementation via Durbin-Levinson recursion —
+ no external statsmodels dependency required
+ - Clean KISS code structure with seed for reproducibility, no unused imports, no
+ functions or classes
+ - Descriptive axis labels with units ('ACF (correlation)', 'PACF (correlation)',
+ 'Lag (periods)') and a realistic AR(2) context subtitle
weaknesses:
- - Per-stem loop is verbose due to Plotly lacking native stem plot support
- - Design could push further toward publication-ready with more refined grid handling
+ - 'DE-01 moderate (5/8): The visualization uses template=''plotly_white'' as base
+ — top/right axis lines remain visible rather than applying the style-guide''s
+ L-shaped or spine-free aesthetic; removing or muting the top/right axis lines
+ would improve polish'
+ - 'DE-02 (4/6): Axes retain plotly_white default frame; spines (top/right plot borders)
+ are not removed — applying showline=False to the top and right bounding lines
+ of each subplot would add visual refinement'
+ - 'LM-02 (4/5): Hover and spike functionality is present but the spike lines apply
+ a uniform style across both subplots; a crossfilter-style shared spike linking
+ (spikemode=''across+toaxis'') or custom hoverinfo aggregating both ACF and PACF
+ values at the same lag would demonstrate deeper Plotly mastery'
+ - 'VQ-01 minor (7/8): Subplot annotation titles at 13px are slightly closer in weight
+ to the 12px axis labels than ideal — bumping subplot annotation fonts to 14px
+ would better reinforce the panel title / axis label hierarchy'
image_description: |-
- The plot displays two vertically stacked subplots on a light gray (#FAFBFC) background. The top subplot shows the Autocorrelation Function (ACF) and the bottom shows the Partial Autocorrelation Function (PACF) for a simulated AR(2) monthly retail sales process. The main title reads "acf-pacf · plotly · pyplots.ai" in dark navy (~28pt), with a gray subtitle "Monthly Retail Sales — AR(2) Process (n=200, φ₁=0.7, φ₂=−0.3)". Each subplot has its own subtitle ("Autocorrelation (ACF)" and "Partial Autocorrelation (PACF)") in medium gray.
+ Light render (plot-light.png):
+ Background: Warm off-white #FAF8F1 — correct, not pure white
+ Chrome: Title "Monthly Retail Sales · acf-pacf · python · plotly · anyplot.ai" centered in dark ink (#1A1A17), subtitle in soft muted tone. Subplot titles "Autocorrelation (ACF)" and "Partial Autocorrelation (PACF)" in INK_SOFT above each panel. Y-axis labels "ACF (correlation)" and "PACF (correlation)" in dark ink. X-axis label "Lag (periods)" in dark ink. Tick labels in INK_SOFT. Legend box at bottom with ELEVATED_BG fill and INK_SOFT border. All text clearly readable.
+ Data: Significant lags rendered in brand green #009E73 (vertical stems width=3 + circular markers size=12 with white edge). Non-significant lags in muted grey (#6B6A63) with stems width=2 + markers size=9 with white edge. 95% confidence band as filled polygon (low-opacity grey fill, dashed grey border). Zero baseline as subtle INK_SOFT line. ACF lag-0 = 1.0 prominent; AR(2) pattern visible with decay. PACF shows clear cutoff at lag 2.
+ Legibility verdict: PASS — all text readable, proper hierarchy, no overflow or overlap
- Vertical stem lines extend from zero to each correlation value. Significant lags are rendered in orange-red (#E8590C) with larger markers (size 13, white edge), while non-significant lags appear in muted gray (#94A3B8) with smaller markers (size 10). A light shaded band with dashed borders marks the 95% confidence interval (±1.96/√200 ≈ ±0.139). The ACF subplot shows lag 0 at 1.0, lag 1 ~0.5, then decay with lags 3 and 5 slightly below the confidence bound. The PACF shows a sharp cutoff after lag 2 (lag 1 ~0.48, lag 2 ~-0.33), consistent with an AR(2) process. A horizontal legend at top-right shows "Significant", "Non-significant", and "95% Confidence". X-axis labeled "Lag (periods)", Y-axes labeled "ACF (correlation)" and "PACF (correlation)".
+ Dark render (plot-dark.png):
+ Background: Warm near-black #1A1A17 — correct, not pure black
+ Chrome: All text tokens correctly flipped — title in #F0EFE8, axis labels and tick labels in #B8B7B0/INK_SOFT equivalents. Subplot titles in soft light tone. Legend box uses dark ELEVATED_BG (#242420). Grid uses light-on-dark rgba. No dark-on-dark failures observed — every text element is clearly visible against the dark background.
+ Data: Data colors are identical to light render — significant lags still in #009E73 green, non-significant in adapted muted grey. Confidence band fill/border adapt via rgba opacity. Zero baseline adapts to INK_SOFT dark token. Green stems stand out clearly against the dark background.
+ Legibility verdict: PASS — all text readable in dark theme, no dark-on-dark failures, brand green #009E73 clearly visible
criteria_checklist:
visual_quality:
- score: 30
+ score: 29
max: 30
items:
- id: VQ-01
name: Text Legibility
- score: 8
+ score: 7
max: 8
passed: true
- comment: 'All font sizes explicitly set: title 28pt, axis labels 22pt, ticks
- 18pt, subplot titles 20pt, legend 16pt'
+ comment: 'All font sizes explicitly set (title adaptive 16px, subplot annotations
+ 13px, axis labels 12px, ticks 10px, legend 10px). Both themes fully readable.
+ Minor: subplot annotation titles at 13px only 1px above axis label 12px
+ — slightly weak panel title hierarchy.'
- id: VQ-02
name: No Overlap
score: 6
max: 6
passed: true
- comment: No overlapping text elements anywhere
+ comment: No text overlaps. Stems and markers well-separated. Legend below
+ plot does not overlap data. Subplot titles clear of data areas.
- id: VQ-03
name: Element Visibility
score: 6
max: 6
passed: true
- comment: Stem width=3, markers differentiated by size (13 vs 10) with white
- edges
+ comment: Significant markers size=12 with white edge excellent visibility.
+ Non-significant size=9 appropriately secondary. Stem widths 3 (significant)
+ vs 2 (non-significant) reinforce hierarchy. Confidence band fill + dashed
+ border clearly visible in both themes.
- id: VQ-04
name: Color Accessibility
- score: 4
- max: 4
+ score: 2
+ max: 2
passed: true
- comment: Orange-red vs muted gray is colorblind-safe with strong luminance
- contrast
+ comment: Green (#009E73) vs muted grey is CVD-safe contrast pair. Not a red-green
+ pair. White marker edges add additional definition. Good luminance contrast.
- id: VQ-05
name: Layout & Canvas
score: 4
max: 4
passed: true
- comment: Both subplots fill canvas well with balanced margins
+ comment: 3200x1800 canvas confirmed (width=800, height=450, scale=4). Margins
+ l=90, r=50, t=130, b=100 generous and balanced. Two subplots with vertical_spacing=0.10
+ — good breathing room. Legend at bottom well-positioned.
- id: VQ-06
name: Axis Labels & Title
score: 2
max: 2
passed: true
- comment: 'Descriptive labels with context: ACF (correlation), PACF (correlation),
- Lag (periods)'
+ comment: 'Y-axes: ''ACF (correlation)'' and ''PACF (correlation)'' — descriptive
+ with units. X-axis: ''Lag (periods)'' — descriptive with units. Title includes
+ descriptive prefix and correct anyplot format.'
+ - id: VQ-07
+ name: Palette Compliance
+ score: 2
+ max: 2
+ passed: true
+ comment: 'Significant lags use #009E73 (Imprint position 1) correctly. Non-significant
+ uses INK_MUTED semantic anchor (theme-adaptive muted) — correct usage. Background
+ #FAF8F1 / #1A1A17 confirmed. All chrome theme-adaptive. Data colors identical
+ between light and dark renders.'
design_excellence:
- score: 14
+ score: 13
max: 20
items:
- id: DE-01
name: Aesthetic Sophistication
- score: 6
+ score: 5
max: 8
passed: true
- comment: Thoughtful orange/gray palette with intentional hierarchy, white
- marker edges, shaded confidence bands
+ comment: 'Above defaults: intentional significant/non-significant visual hierarchy,
+ white marker edges for definition, soft confidence band fills, adaptive
+ subtitle with parameter info, length-adaptive title. Template=''plotly_white''
+ base limits full score — top/right axis lines visible.'
- id: DE-02
name: Visual Refinement
score: 4
max: 6
passed: true
- comment: plotly_white template, subtle grid lines, custom background, x-axis
- grid disabled
+ comment: Y-grid only (x-grid off), subtle gridcolor at 15% opacity, legend
+ with ELEVATED_BG and border, subplot title muted color. Good refinement
+ but top/right spines from plotly_white default not explicitly removed —
+ full spine cleanup would push to 6/6.
- id: DE-03
name: Data Storytelling
score: 4
max: 6
passed: true
- comment: AR(2) data creates clear narrative with PACF cutoff at lag 2, color
- coding guides viewer
+ comment: 'Clear visual hierarchy: green significant vs grey non-significant
+ creates immediate focal points. AR(2) pattern story (decay in ACF, cutoff
+ at lag 2 in PACF) is visually unmistakable. Subtitle explains the process
+ parameters. Viewer understands the ARIMA model order at a glance.'
spec_compliance:
score: 15
max: 15
@@ -104,26 +162,34 @@ review:
score: 5
max: 5
passed: true
- comment: ACF and PACF as stem plots in two vertically stacked subplots
+ comment: Correct ACF/PACF stem plot with two vertically stacked subplots sharing
+ x-axis. Vertical stem lines (not filled bars) from zero baseline. Exactly
+ matches spec description.
- id: SC-02
name: Required Features
score: 4
max: 4
passed: true
- comment: 'All spec features present: stem lines, confidence bands, lag 0 in
- ACF, PACF from lag 1, shared x-axis, 35 lags'
+ comment: ACF top / PACF bottom ✓. Stem lines from zero ✓. 95% CI dashed horizontal
+ lines (as filled polygon with dashed border) ✓. Lag 0 in ACF (=1.0) ✓. PACF
+ from lag 1 ✓. 35 lags (within 30-40 range) ✓. X-axis 'Lag' ✓. Y-axes 'ACF'
+ and 'PACF' ✓.
- id: SC-03
name: Data Mapping
score: 3
max: 3
passed: true
- comment: X=lag number, Y=correlation values, full range shown
+ comment: X-axis shows lag numbers 0-35. Y-axes show correlation values -1
+ to 1. ACF top, PACF bottom. Shared x-axis correctly implemented via shared_xaxes=True.
- id: SC-04
name: Title & Legend
score: 3
max: 3
passed: true
- comment: Title matches required format, legend labels are descriptive
+ comment: 'Title ''Monthly Retail Sales · acf-pacf · python · plotly · anyplot.ai''
+ matches {Descriptive Title} · {spec-id} · {language} · {library} · anyplot.ai
+ format. Legend labels: ''Significant'', ''Non-significant'', ''95% Confidence''
+ — correct and informative.'
data_quality:
score: 15
max: 15
@@ -133,24 +199,28 @@ review:
score: 6
max: 6
passed: true
- comment: 'AR(2) shows all key features: ACF decay, PACF cutoff, positive and
- negative correlations'
+ comment: 'Shows all ACF/PACF features: ACF decay pattern, PACF cutoff at lag
+ 2 (AR(2) signature), significant vs non-significant distinction, confidence
+ band, zero baseline, lag-0=1.0 in ACF. Full feature coverage.'
- id: DQ-02
name: Realistic Context
score: 5
max: 5
passed: true
- comment: Monthly Retail Sales is a real-world neutral scenario with realistic
- AR coefficients
+ comment: Monthly retail sales is a neutral, comprehensible real-world scenario.
+ AR(2) process with specific coefficients (φ₁=0.7, φ₂=−0.3) provides a realistic
+ time series model. Subtitle explains the generative process clearly.
- id: DQ-03
name: Appropriate Scale
score: 4
max: 4
passed: true
- comment: n=200 within recommended range, correlations in [-1,1], confidence
- bounds correct
+ comment: n=200 observations (within 100-500 recommended range). 35 lags (within
+ 30-40 range). Confidence bound ≈0.139 (1.96/√200) — mathematically correct.
+ Correlation values within [-1, 1]. AR(2) coefficients are realistic and
+ stationary.
code_quality:
- score: 9
+ score: 10
max: 10
items:
- id: CQ-01
@@ -158,49 +228,62 @@ review:
score: 3
max: 3
passed: true
- comment: 'Clean linear flow: imports, data, ACF, PACF, plot, save'
+ comment: Clean Imports → Theme tokens → Data generation → ACF/PACF computation
+ → Stem coordinate building → Plot construction → Layout → Save. No functions
+ or classes.
- id: CQ-02
name: Reproducibility
score: 2
max: 2
passed: true
- comment: np.random.seed(42) set at start
+ comment: np.random.seed(42) present. Deterministic AR(2) simulation.
- id: CQ-03
name: Clean Imports
score: 2
max: 2
passed: true
- comment: Three imports, all used
+ comment: 'All 4 imports used: os (ANYPLOT_THEME), numpy (data/computation),
+ plotly.graph_objects (traces), plotly.subplots (make_subplots). No unused
+ imports.'
- id: CQ-04
name: Code Elegance
- score: 1
+ score: 2
max: 2
- passed: false
- comment: Per-stem loop creating individual traces is verbose, though a Plotly
- limitation
+ passed: true
+ comment: Clever None-separator technique for multi-segment stem lines. Durbin-Levinson
+ recursion correctly implemented inline. Conditional trace addition (if acf_sig_x:).
+ Length-adaptive title formula. Appropriate complexity for the plot type.
- id: CQ-05
name: Output & API
score: 1
max: 1
passed: true
- comment: Saves as plot.png with correct dimensions, also exports HTML
+ comment: Saves plot-{THEME}.png with autosize=False, correct width=800/height=450/scale=4.
+ Also saves plot-{THEME}.html appropriate for interactive Plotly library.
library_mastery:
- score: 7
+ score: 9
max: 10
items:
- id: LM-01
name: Idiomatic Usage
- score: 4
+ score: 5
max: 5
passed: true
- comment: Good use of make_subplots, go.Scatter, hovertemplate, update methods
+ comment: make_subplots with shared_xaxes=True, subplot_titles. go.Scatter
+ with fill='toself' for confidence polygon. None-separator multi-segment
+ lines (idiomatic Plotly pattern). hovertemplate with to
+ suppress trace name. update_xaxes/update_yaxes per row. Spike lines configuration.
- id: LM-02
name: Distinctive Features
- score: 3
+ score: 4
max: 5
passed: true
- comment: Hover tooltips, spike lines, HTML export, fill=toself for confidence
- regions
+ comment: 'Plotly-distinctive: hover tooltips showing lag and correlation,
+ HTML export for interactive exploration, spike lines (showspikes=True, spikemode=''across'')
+ enabling cross-subplot lag tracking, filled polygon confidence band. Minor
+ gap: both subplots share the same spike config but don''t aggregate values
+ at the same lag in a single hover — a crossfilter-style unified hover tooltip
+ would max this score.'
verdict: APPROVED
impl_tags:
dependencies: []
@@ -210,9 +293,9 @@ impl_tags:
- html-export
patterns:
- data-generation
+ - matrix-construction
- iteration-over-groups
- dataprep:
- - autocorrelation
+ dataprep: []
styling:
- edge-highlighting
- - grid-styling
+ - alpha-blending