From c34e94b4803cc689dd89e601f9e0015ca1d22b97 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 01:11:32 +0000 Subject: [PATCH 1/5] feat(plotnine): implement waveform-audio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regen from quality 92. Addressed: - Canvas size: figure_size=(16,9) dpi=300 → (8,4.5) dpi=400 (3200×1800) - Save filename: plot.png → plot-{THEME}.png - Added ANYPLOT_THEME env var handling for light/dark themes - Background colors: #ffffff/#f5f5f0 → theme-adaptive PAGE_BG tokens - Phase colors: replaced non-Imprint custom hexes with Imprint palette positions 1,3,2 - Title: fixed language token + "anyplot.ai" brand - Font sizes: recalibrated from (16,9) scale to (8,4.5) scale --- .../implementations/python/plotnine.py | 73 +++++++++++-------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/plots/waveform-audio/implementations/python/plotnine.py b/plots/waveform-audio/implementations/python/plotnine.py index 926bed2fbc..f4c1c9024e 100644 --- a/plots/waveform-audio/implementations/python/plotnine.py +++ b/plots/waveform-audio/implementations/python/plotnine.py @@ -1,9 +1,11 @@ -""" pyplots.ai +"""anyplot.ai waveform-audio: Audio Waveform Plot -Library: plotnine 0.15.3 | Python 3.14.3 -Quality: 92/100 | Created: 2026-03-07 +Library: plotnine | Python 3.13 +Quality: pending | Updated: 2026-06-03 """ +import os + import numpy as np import pandas as pd from plotnine import ( @@ -27,6 +29,16 @@ ) +# Theme tokens +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" + +# Imprint palette — positions 1, 3, 2 for Attack, Sustain, Release phases +IMPRINT_PALETTE = ["#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030", "#2ABCCD", "#954477", "#99B314"] + # Data - synthetic audio waveform: tone with harmonics and amplitude envelope np.random.seed(42) sample_rate = 22050 @@ -34,7 +46,6 @@ num_samples = int(sample_rate * duration) time = np.linspace(0, duration, num_samples) -# Primary tone at 220 Hz with harmonics fundamental = 220 signal = ( 0.6 * np.sin(2 * np.pi * fundamental * time) @@ -43,26 +54,23 @@ + 0.05 * np.sin(2 * np.pi * fundamental * 5 * time) ) -# Amplitude envelope: attack-sustain-release shape envelope = np.ones_like(time) attack_end = int(0.05 * sample_rate) sustain_end = int(1.1 * sample_rate) envelope[:attack_end] = np.linspace(0, 1, attack_end) envelope[sustain_end:] = np.linspace(1, 0, num_samples - sustain_end) -# Add slight vibrato and noise for realism vibrato = 1.0 + 0.03 * np.sin(2 * np.pi * 5 * time) noise = np.random.normal(0, 0.02, num_samples) amplitude = np.clip((signal * envelope * vibrato) + noise, -1.0, 1.0) -# Downsample for plotting using min/max envelope to avoid aliasing +# Downsample using min/max envelope to avoid aliasing chunk_size = 64 num_chunks = num_samples // chunk_size time_chunks = np.array([time[i * chunk_size] for i in range(num_chunks)]) amp_min = np.array([amplitude[i * chunk_size : (i + 1) * chunk_size].min() for i in range(num_chunks)]) amp_max = np.array([amplitude[i * chunk_size : (i + 1) * chunk_size].max() for i in range(num_chunks)]) -# Classify each chunk into attack/sustain/release phase for storytelling attack_time = 0.05 sustain_time = 1.1 phase = [] @@ -83,46 +91,47 @@ } ) -# Phase colors: distinct hues to tell the waveform story -phase_colors = {"Attack": "#E8651A", "Sustain": "#306998", "Release": "#6A4C93"} +# Imprint palette: Attack=green (pos 1), Sustain=blue (pos 3), Release=lavender (pos 2) +phase_colors = {"Attack": IMPRINT_PALETTE[0], "Sustain": IMPRINT_PALETTE[2], "Release": IMPRINT_PALETTE[1]} phase_alphas = {"Attack": 0.85, "Sustain": 0.65, "Release": 0.55} -# Plot - use fill mapped to phase for data storytelling (DE-03) +title = "waveform-audio · python · plotnine · anyplot.ai" + +# Plot plot = ( ggplot(df, aes(x="time")) + geom_ribbon(aes(ymin="amp_min", ymax="amp_max", fill="phase", alpha="phase"), show_legend=False) + scale_fill_manual(values=phase_colors) + scale_alpha_manual(values=phase_alphas) - + geom_hline(yintercept=0, color="#888888", size=0.3, linetype="solid") - # Phase boundary markers - + geom_vline(xintercept=attack_time, color="#E8651A", size=0.4, linetype="dashed", alpha=0.6) - + geom_vline(xintercept=sustain_time, color="#6A4C93", size=0.4, linetype="dashed", alpha=0.6) - # Phase labels via annotate (DE-03 storytelling) - + annotate("text", x=0.025, y=0.92, label="Attack", size=11, color="#E8651A", fontstyle="italic") - + annotate("text", x=0.575, y=0.92, label="Sustain", size=11, color="#306998", fontstyle="italic") - + annotate("text", x=1.30, y=0.92, label="Release", size=11, color="#6A4C93", fontstyle="italic") - + labs(x="Time (seconds)", y="Amplitude", title="waveform-audio · plotnine · pyplots.ai") + + geom_hline(yintercept=0, color=INK_MUTED, size=0.4, linetype="solid") + + geom_vline(xintercept=attack_time, color=INK_SOFT, size=0.3, linetype="dashed", alpha=0.5) + + geom_vline(xintercept=sustain_time, color=INK_SOFT, size=0.3, linetype="dashed", alpha=0.5) + + annotate("text", x=0.025, y=0.90, label="Attack", size=3.0, color=IMPRINT_PALETTE[0], fontstyle="italic") + + annotate("text", x=0.575, y=0.90, label="Sustain", size=3.0, color=IMPRINT_PALETTE[2], fontstyle="italic") + + annotate("text", x=1.30, y=0.90, label="Release", size=3.0, color=IMPRINT_PALETTE[1], fontstyle="italic") + + labs(x="Time (seconds)", y="Amplitude", title=title) + scale_x_continuous( breaks=np.arange(0, duration + 0.1, 0.25), labels=lambda lst: [f"{v:.2f}" for v in lst], expand=(0.01, 0.01) ) + scale_y_continuous(limits=(-1.0, 1.0), breaks=np.arange(-1.0, 1.1, 0.25)) + theme_minimal() + theme( - figure_size=(16, 9), - text=element_text(size=14, color="#2d2d2d"), - axis_title=element_text(size=20, color="#2d2d2d", margin={"t": 12, "r": 12}), - axis_text=element_text(size=16, color="#555555"), - plot_title=element_text(size=24, weight="bold", color="#1a1a1a", margin={"b": 12}), - panel_background=element_rect(fill="#f5f5f0", color="none"), - plot_background=element_rect(fill="#ffffff", color="none"), - panel_grid_major_y=element_line(color="#dcdcdc", size=0.25, linetype="dotted"), + figure_size=(8, 4.5), + text=element_text(size=7, color=INK), + axis_title=element_text(size=10, color=INK), + axis_text=element_text(size=8, color=INK_SOFT), + plot_title=element_text(size=12, color=INK), + legend_text=element_text(size=8, color=INK_SOFT), + panel_background=element_rect(fill=PAGE_BG, color="none"), + plot_background=element_rect(fill=PAGE_BG, color="none"), + panel_grid_major_y=element_line(color=INK, size=0.3, alpha=0.15), panel_grid_major_x=element_blank(), panel_grid_minor=element_blank(), - axis_line_x=element_line(color="#888888", size=0.5), - axis_ticks_major_x=element_line(color="#888888", size=0.4), + axis_line_x=element_line(color=INK_SOFT, size=0.5), + axis_line_y=element_line(color=INK_SOFT, size=0.5), + axis_ticks_major_x=element_line(color=INK_SOFT, size=0.4), axis_ticks_major_y=element_blank(), - plot_margin=0.02, ) ) -plot.save("plot.png", dpi=300, verbose=False) +plot.save(f"plot-{THEME}.png", dpi=400, width=8, height=4.5, units="in", verbose=False) From d65df72fa7e43a05dde37cab9f0ec3cbda0d45e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 01:11:44 +0000 Subject: [PATCH 2/5] chore(plotnine): add metadata for waveform-audio --- .../metadata/python/plotnine.yaml | 224 ++---------------- 1 file changed, 16 insertions(+), 208 deletions(-) diff --git a/plots/waveform-audio/metadata/python/plotnine.yaml b/plots/waveform-audio/metadata/python/plotnine.yaml index 40e0bf536a..12d485f906 100644 --- a/plots/waveform-audio/metadata/python/plotnine.yaml +++ b/plots/waveform-audio/metadata/python/plotnine.yaml @@ -1,213 +1,21 @@ +# Per-library metadata for plotnine implementation of waveform-audio +# Auto-generated by impl-generate.yml + library: plotnine +language: python specification_id: waveform-audio created: '2026-03-07T14:58:25Z' -updated: '2026-03-07T15:08:44Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 22801238614 +updated: '2026-06-03T01:11:44Z' +generated_by: claude-sonnet +workflow_run: 26857483373 issue: 4563 -python_version: 3.14.3 -library_version: 0.15.3 -preview_url: https://storage.googleapis.com/anyplot-images/plots/waveform-audio/plotnine/plot.png -preview_html: null -quality_score: 92 +language_version: 3.13.13 +library_version: 0.15.5 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/waveform-audio/python/plotnine/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/waveform-audio/python/plotnine/plot-dark.png +preview_html_light: null +preview_html_dark: null +quality_score: null review: - strengths: - - Excellent data storytelling through phase-colored waveform (Attack/Sustain/Release) - with boundary markers - - Min/max envelope downsampling properly handles dense waveform display - - Warm panel background and custom color palette create polished professional appearance - - Realistic audio data with harmonics vibrato and noise - - Full spec compliance with all required features implemented - weaknesses: - - Phase annotation label size (11) is smaller than other text elements - - Data downsampling uses list comprehensions instead of vectorized numpy reshape - operations - image_description: 'The plot displays an audio waveform as a filled ribbon symmetric - around a zero baseline on a warm off-white panel background (#f5f5f0). The x-axis - shows "Time (seconds)" from 0.00 to 1.50, and the y-axis shows "Amplitude" from - -1.00 to 1.00. The waveform is colored by three distinct phases: orange for the - short Attack phase (0-0.05s) showing rapid amplitude increase, steel blue for - the Sustain phase (0.05-1.10s) showing steady oscillation at ~0.75 amplitude, - and purple for the Release phase (1.10-1.50s) showing gradual decay to zero. Dashed - vertical lines mark the phase boundaries. Italic phase labels appear near the - top of each region. A subtle horizontal zero-line bisects the waveform. The title - reads "waveform-audio · plotnine · pyplots.ai" in bold at the top. Y-axis has - dotted grid lines; x-axis grid is removed. The waveform clearly shows the harmonic - content with visible beat patterns in the sustain region.' - criteria_checklist: - visual_quality: - score: 29 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 7 - max: 8 - passed: true - comment: All major font sizes explicitly set; phase annotation labels at size=11 - slightly small - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: No overlapping text elements - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Waveform clearly visible with min/max envelope rendering - - id: VQ-04 - name: Color Accessibility - score: 4 - max: 4 - passed: true - comment: Orange/blue/purple palette is colorblind-distinguishable - - id: VQ-05 - name: Layout & Canvas - score: 4 - max: 4 - passed: true - comment: Good 16:9 layout with balanced margins - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: Time (seconds) with units, Amplitude descriptive - design_excellence: - score: 16 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 6 - max: 8 - passed: true - comment: Custom phase palette, warm background, intentional typography hierarchy - - id: DE-02 - name: Visual Refinement - score: 5 - max: 6 - passed: true - comment: Removed x-grid, subtle dotted y-grid, warm panel background - - id: DE-03 - name: Data Storytelling - score: 5 - max: 6 - passed: true - comment: Phase-colored waveform with boundary markers creates clear narrative - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct audio waveform with filled area symmetric around zero - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: All spec features present including envelope rendering - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: X=time, Y=amplitude, correct mapping - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Correct title format, phase labels annotated directly - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: Shows attack, sustain, release, harmonics, noise - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: 220Hz A3 note with harmonics, realistic audio scenario - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: Standard sample rate, realistic duration and amplitude - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Linear flow: imports, data, plot, save' - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: np.random.seed(42) set - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: All imports used - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Clean, well-organized code - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Saves as plot.png with dpi=300 - library_mastery: - score: 7 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: Good grammar of graphics usage with aes, geom_ribbon, scales - - id: LM-02 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: Categorical fill mapping on geom_ribbon with scale_alpha_manual - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - annotations - - layer-composition - patterns: - - data-generation - dataprep: - - binning - styling: - - alpha-blending - - grid-styling + strengths: [] + weaknesses: [] From a63ffb816853dbcf321bd5b9ff9a71ff9efda789 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 01:18:05 +0000 Subject: [PATCH 3/5] chore(plotnine): update quality score 88 and review feedback for waveform-audio --- .../implementations/python/plotnine.py | 6 +- .../metadata/python/plotnine.yaml | 251 +++++++++++++++++- 2 files changed, 247 insertions(+), 10 deletions(-) diff --git a/plots/waveform-audio/implementations/python/plotnine.py b/plots/waveform-audio/implementations/python/plotnine.py index f4c1c9024e..fa83e2b71c 100644 --- a/plots/waveform-audio/implementations/python/plotnine.py +++ b/plots/waveform-audio/implementations/python/plotnine.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai waveform-audio: Audio Waveform Plot -Library: plotnine | Python 3.13 -Quality: pending | Updated: 2026-06-03 +Library: plotnine 0.15.5 | Python 3.13.13 +Quality: 88/100 | Updated: 2026-06-03 """ import os diff --git a/plots/waveform-audio/metadata/python/plotnine.yaml b/plots/waveform-audio/metadata/python/plotnine.yaml index 12d485f906..52f382f301 100644 --- a/plots/waveform-audio/metadata/python/plotnine.yaml +++ b/plots/waveform-audio/metadata/python/plotnine.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for plotnine implementation of waveform-audio -# Auto-generated by impl-generate.yml - library: plotnine language: python specification_id: waveform-audio created: '2026-03-07T14:58:25Z' -updated: '2026-06-03T01:11:44Z' +updated: '2026-06-03T01:18:04Z' generated_by: claude-sonnet workflow_run: 26857483373 issue: 4563 @@ -15,7 +12,247 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/waveform- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/waveform-audio/python/plotnine/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: null +quality_score: 88 review: - strengths: [] - weaknesses: [] + strengths: + - Phase-based waveform coloring with Imprint palette creates clear Attack/Sustain/Release + visual storytelling + - Min/max envelope rendering correctly handles dense waveform aliasing as specified + - Perfect spec compliance — filled ribbon, zero line, proper axes, synthetic audio + data with harmonics and envelope + - 'All theme tokens wired correctly: both light and dark renders are fully readable + with correct backgrounds and text colors' + - 'Code quality is exemplary: seed set, clean imports, KISS structure, correct output + API' + weaknesses: + - 'VQ-07: Palette order is non-canonical (Attack=#009E73 pos-1, Sustain=#4467A3 + pos-3, Release=#C475FD pos-2) — no clear semantic justification for swapping positions + 2 and 3; use canonical order Attack=pos-1 (#009E73), Sustain=pos-2 (#C475FD), + Release=pos-3 (#4467A3) unless a strong semantic reason for the swap is documented' + - 'VQ-01/DE-01: Phase annotation labels (size=3.0 mm ≈ 8.5pt) are quite small in + both renders — increase to size=3.5–4.0 for better mobile legibility and visual + impact' + - 'DE-01: Design could be elevated further — consider adding a subtle waveform amplitude + envelope overlay (e.g. a smoothed outline geom_line on top of the ribbon), or + adjusting alpha values to better reveal the oscillation pattern inside the ribbon' + - 'DE-02: Minor: the axis lines could use a slightly more generous margin at the + right side to breathe; phase divider lines (geom_vline) and zero line could be + given slightly more visual weight contrast' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct; not pure white. + Chrome: Title "waveform-audio · python · plotnine · anyplot.ai" in dark ink, clearly readable. Axis labels "Time (seconds)" (x) and "Amplitude" (y) are dark, well-proportioned. Tick labels (-1.00 to 1.00 on y; 0.00 to 1.50 on x) are readable in INK_SOFT. Phase labels "Attack", "Sustain", "Release" as small italic annotations in their respective Imprint colors — readable at full size, slightly small. + Data: Three ribbon fills — Attack (short left section, #009E73 green at alpha=0.85), Sustain (wide middle section, #4467A3 blue at alpha=0.65), Release (right tapering section, #C475FD lavender at alpha=0.55). Horizontal zero-line in INK_MUTED. Dashed vertical dividers at phase boundaries in INK_SOFT. Waveform envelope clearly shows the amplitude dynamics. + Legibility verdict: PASS — all text readable against light background. + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct; not pure black. + Chrome: Title in light #F0EFE8 text — readable. Axis labels and tick labels in light INK_SOFT (#B8B7B0) — readable. No dark-on-dark failures observed. Phase annotation labels in their Imprint colors (green/blue/lavender) — all visible against dark background. + Data: Colors identical to light render — #009E73 Attack, #4467A3 Sustain, #C475FD Release. Same alpha values. Zero-line visible. Phase dividers visible. + Legibility verdict: PASS — all text readable against dark background; no dark-on-dark issues. + criteria_checklist: + visual_quality: + score: 28 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All font sizes explicitly set (title=12pt, axis_title=10pt, axis_text=8pt). + Phase annotation labels at size=3.0mm are slightly small — readable at full + resolution but tight at mobile scale. + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping text or data elements in either render. + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: Dense waveform handled with min/max envelope rendering. Ribbon fills + clearly visible at appropriate alpha values per phase. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Imprint palette with CVD-safe hues. Phase labels use matching colors. + Good contrast. + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Canvas gate passed (3200x1800). Waveform fills the plot area well. + No clipping. Balanced margins. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: 'X: ''Time (seconds)'' with units. Y: ''Amplitude'' (normalized -1 + to 1 implied by axis range).' + - id: VQ-07 + name: Palette Compliance + score: 1 + max: 2 + passed: false + comment: 'First series (Attack) is #009E73 — correct. However Sustain uses + pos-3 (#4467A3) and Release uses pos-2 (#C475FD) — non-canonical order 1,3,2 + without semantic justification. Backgrounds and chrome are correct.' + design_excellence: + score: 13 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: Above well-configured default. Phase-based coloring with different + alpha values, direct labels, and dividers shows design intent. Not yet at + publication-ready level. + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: theme_minimal() removes top/right spines. Y-axis-only grid at 15% + opacity is correct. Axis lines and ticks explicitly styled. + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Clear ADSR story through phase colors, labels, and dividers. Visual + hierarchy guides the viewer through the audio dynamics. + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: 'Correct waveform visualization: geom_ribbon as filled area mirrored + above and below zero.' + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: 'All features present: filled area, semi-transparent fills, zero-line, + time x-axis, amplitude y-axis (-1 to +1), min/max envelope rendering, synthetic + audio data.' + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: Time on x-axis (0 to 1.5s), normalized amplitude on y-axis (-1.0 + to 1.0). Correct mapping. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: 'Title: ''waveform-audio · python · plotnine · anyplot.ai'' — correct + format. No legend (show_legend=False); phases labeled via direct annotations.' + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: 'Shows all aspects: attack onset, sustained oscillation with vibrato, + release decay, amplitude envelope, harmonic content.' + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Realistic A3 musical note (220Hz fundamental) with harmonics, amplitude + envelope, vibrato, and noise floor. Neutral topic. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: 22050Hz sample rate, 1.5s duration, normalized amplitude — all physically + realistic for audio. + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: Clean Imports -> Data -> Plot -> Save structure. No functions or + classes. + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: np.random.seed(42) set. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All imports are used. + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean, readable code. No fake interactivity. Phase loop is readable. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves as plot-{THEME}.png with correct dpi/dimensions. + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: 'Good idiomatic plotnine: ggplot + geom_ribbon + aes with fill/alpha + mapped to categorical phase variable + scale_fill_manual + scale_alpha_manual. + Layer composition is well-executed.' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses geom_ribbon with dual aesthetic mapping (fill + alpha to same + categorical variable) — distinctly ggplot/plotnine grammar. geom_ribbon + for waveform envelope is a natural plotnine idiom. + verdict: REJECTED +impl_tags: + dependencies: [] + techniques: + - annotations + - layer-composition + patterns: + - data-generation + dataprep: + - binning + styling: + - alpha-blending From 76576530adf99a4d431bb02bee0671a38592cd6b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 01:21:28 +0000 Subject: [PATCH 4/5] fix(plotnine): address review feedback for waveform-audio Attempt 1/3 - fixes based on AI review --- .../implementations/python/plotnine.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plots/waveform-audio/implementations/python/plotnine.py b/plots/waveform-audio/implementations/python/plotnine.py index fa83e2b71c..b66619725d 100644 --- a/plots/waveform-audio/implementations/python/plotnine.py +++ b/plots/waveform-audio/implementations/python/plotnine.py @@ -1,4 +1,4 @@ -""" anyplot.ai +"""anyplot.ai waveform-audio: Audio Waveform Plot Library: plotnine 0.15.5 | Python 3.13.13 Quality: 88/100 | Updated: 2026-06-03 @@ -36,7 +36,7 @@ INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" -# Imprint palette — positions 1, 3, 2 for Attack, Sustain, Release phases +# Imprint palette — positions 1, 2, 3 for Attack, Sustain, Release phases IMPRINT_PALETTE = ["#009E73", "#C475FD", "#4467A3", "#BD8233", "#AE3030", "#2ABCCD", "#954477", "#99B314"] # Data - synthetic audio waveform: tone with harmonics and amplitude envelope @@ -91,8 +91,8 @@ } ) -# Imprint palette: Attack=green (pos 1), Sustain=blue (pos 3), Release=lavender (pos 2) -phase_colors = {"Attack": IMPRINT_PALETTE[0], "Sustain": IMPRINT_PALETTE[2], "Release": IMPRINT_PALETTE[1]} +# Imprint palette: Attack=green (pos 1), Sustain=lavender (pos 2), Release=blue (pos 3) +phase_colors = {"Attack": IMPRINT_PALETTE[0], "Sustain": IMPRINT_PALETTE[1], "Release": IMPRINT_PALETTE[2]} phase_alphas = {"Attack": 0.85, "Sustain": 0.65, "Release": 0.55} title = "waveform-audio · python · plotnine · anyplot.ai" @@ -106,9 +106,9 @@ + geom_hline(yintercept=0, color=INK_MUTED, size=0.4, linetype="solid") + geom_vline(xintercept=attack_time, color=INK_SOFT, size=0.3, linetype="dashed", alpha=0.5) + geom_vline(xintercept=sustain_time, color=INK_SOFT, size=0.3, linetype="dashed", alpha=0.5) - + annotate("text", x=0.025, y=0.90, label="Attack", size=3.0, color=IMPRINT_PALETTE[0], fontstyle="italic") - + annotate("text", x=0.575, y=0.90, label="Sustain", size=3.0, color=IMPRINT_PALETTE[2], fontstyle="italic") - + annotate("text", x=1.30, y=0.90, label="Release", size=3.0, color=IMPRINT_PALETTE[1], fontstyle="italic") + + annotate("text", x=0.025, y=0.90, label="Attack", size=3.5, color=IMPRINT_PALETTE[0], fontstyle="italic") + + annotate("text", x=0.575, y=0.90, label="Sustain", size=3.5, color=IMPRINT_PALETTE[1], fontstyle="italic") + + annotate("text", x=1.30, y=0.90, label="Release", size=3.5, color=IMPRINT_PALETTE[2], fontstyle="italic") + labs(x="Time (seconds)", y="Amplitude", title=title) + scale_x_continuous( breaks=np.arange(0, duration + 0.1, 0.25), labels=lambda lst: [f"{v:.2f}" for v in lst], expand=(0.01, 0.01) From 91d94963774bbefdd721ef02fd15e7c4f893f37a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 01:27:56 +0000 Subject: [PATCH 5/5] chore(plotnine): update quality score 86 and review feedback for waveform-audio --- .../implementations/python/plotnine.py | 4 +- .../metadata/python/plotnine.yaml | 179 +++++++++--------- 2 files changed, 88 insertions(+), 95 deletions(-) diff --git a/plots/waveform-audio/implementations/python/plotnine.py b/plots/waveform-audio/implementations/python/plotnine.py index b66619725d..b390479d64 100644 --- a/plots/waveform-audio/implementations/python/plotnine.py +++ b/plots/waveform-audio/implementations/python/plotnine.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai waveform-audio: Audio Waveform Plot Library: plotnine 0.15.5 | Python 3.13.13 -Quality: 88/100 | Updated: 2026-06-03 +Quality: 86/100 | Updated: 2026-06-03 """ import os diff --git a/plots/waveform-audio/metadata/python/plotnine.yaml b/plots/waveform-audio/metadata/python/plotnine.yaml index 52f382f301..b836101d31 100644 --- a/plots/waveform-audio/metadata/python/plotnine.yaml +++ b/plots/waveform-audio/metadata/python/plotnine.yaml @@ -2,7 +2,7 @@ library: plotnine language: python specification_id: waveform-audio created: '2026-03-07T14:58:25Z' -updated: '2026-06-03T01:18:04Z' +updated: '2026-06-03T01:27:56Z' generated_by: claude-sonnet workflow_run: 26857483373 issue: 4563 @@ -12,101 +12,92 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/waveform- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/waveform-audio/python/plotnine/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: 88 +quality_score: 86 review: strengths: - - Phase-based waveform coloring with Imprint palette creates clear Attack/Sustain/Release - visual storytelling - - Min/max envelope rendering correctly handles dense waveform aliasing as specified - - Perfect spec compliance — filled ribbon, zero line, proper axes, synthetic audio - data with harmonics and envelope - - 'All theme tokens wired correctly: both light and dark renders are fully readable - with correct backgrounds and text colors' - - 'Code quality is exemplary: seed set, clean imports, KISS structure, correct output - API' + - Three-phase color segmentation (Attack/Sustain/Release) with Imprint palette positions + 1-3 in correct order creates an informative, visually purposeful waveform + - Min/max envelope downsampling (chunk_size=64) correctly avoids aliasing on the + 22050 Hz signal — spec-compliant and technically sound + - All theme tokens properly adapted for both light and dark renders with no dark-on-dark + failures + - Realistic synthetic audio data (220 Hz + harmonics + vibrato + noise) at standard + 22050 Hz sample rate weaknesses: - - 'VQ-07: Palette order is non-canonical (Attack=#009E73 pos-1, Sustain=#4467A3 - pos-3, Release=#C475FD pos-2) — no clear semantic justification for swapping positions - 2 and 3; use canonical order Attack=pos-1 (#009E73), Sustain=pos-2 (#C475FD), - Release=pos-3 (#4467A3) unless a strong semantic reason for the swap is documented' - - 'VQ-01/DE-01: Phase annotation labels (size=3.0 mm ≈ 8.5pt) are quite small in - both renders — increase to size=3.5–4.0 for better mobile legibility and visual - impact' - - 'DE-01: Design could be elevated further — consider adding a subtle waveform amplitude - envelope overlay (e.g. a smoothed outline geom_line on top of the ribbon), or - adjusting alpha values to better reveal the oscillation pattern inside the ribbon' - - 'DE-02: Minor: the axis lines could use a slightly more generous margin at the - right side to breathe; phase divider lines (geom_vline) and zero line could be - given slightly more visual weight contrast' + - Y-axis label reads 'Amplitude' without a unit/range qualifier; change to 'Amplitude + (normalized)' or 'Amplitude [-1, 1]' to earn full VQ-06 points + - Phase annotation labels use size=3.5 (~10 pt) which is too small for annotations + at this canvas size and especially cramped for the narrow Attack region at x~0.025; + increase to size=5-6 + - Design Excellence loses points due to the annotation labels being too small to + function as strong narrative anchors — the phase story is told by color but not + reinforced by legible text emphasis image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct; not pure white. - Chrome: Title "waveform-audio · python · plotnine · anyplot.ai" in dark ink, clearly readable. Axis labels "Time (seconds)" (x) and "Amplitude" (y) are dark, well-proportioned. Tick labels (-1.00 to 1.00 on y; 0.00 to 1.50 on x) are readable in INK_SOFT. Phase labels "Attack", "Sustain", "Release" as small italic annotations in their respective Imprint colors — readable at full size, slightly small. - Data: Three ribbon fills — Attack (short left section, #009E73 green at alpha=0.85), Sustain (wide middle section, #4467A3 blue at alpha=0.65), Release (right tapering section, #C475FD lavender at alpha=0.55). Horizontal zero-line in INK_MUTED. Dashed vertical dividers at phase boundaries in INK_SOFT. Waveform envelope clearly shows the amplitude dynamics. - Legibility verdict: PASS — all text readable against light background. + Background: Warm off-white (~#FAF8F1) — correct, not pure white + Chrome: Title "waveform-audio · python · plotnine · anyplot.ai" in dark ink — readable. Axis labels "Time (seconds)" and "Amplitude" in dark ink — readable. Tick labels (-1.00 to 1.00 on y, 0.00 to 1.50 on x) in secondary ink — readable. Phase annotations "Attack", "Sustain", "Release" in respective palette colors — small but visible. + Data: Attack ribbon in Imprint green (#009E73), Sustain ribbon in Imprint lavender (#C475FD), Release ribbon in Imprint blue (#4467A3). All ribbons symmetric around zero. Horizontal zero reference line visible. Dashed vertical phase boundary lines visible. + Legibility verdict: PASS Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct; not pure black. - Chrome: Title in light #F0EFE8 text — readable. Axis labels and tick labels in light INK_SOFT (#B8B7B0) — readable. No dark-on-dark failures observed. Phase annotation labels in their Imprint colors (green/blue/lavender) — all visible against dark background. - Data: Colors identical to light render — #009E73 Attack, #4467A3 Sustain, #C475FD Release. Same alpha values. Zero-line visible. Phase dividers visible. - Legibility verdict: PASS — all text readable against dark background; no dark-on-dark issues. + Background: Warm near-black (~#1A1A17) — correct, not pure black + Chrome: Title and axis labels in light ink (#F0EFE8) — readable against dark background. Tick labels in secondary ink (#B8B7B0) — readable. Phase annotations in palette colors — legible. No dark-on-dark failures detected. + Data: Same Imprint green, lavender, and blue data colors as light render — palette is theme-independent and identical. Zero reference line visible in warm muted gray (INK_MUTED dark token). Grid lines subtle. + Legibility verdict: PASS criteria_checklist: visual_quality: - score: 28 + score: 29 max: 30 items: - id: VQ-01 name: Text Legibility - score: 7 + score: 8 max: 8 passed: true - comment: All font sizes explicitly set (title=12pt, axis_title=10pt, axis_text=8pt). - Phase annotation labels at size=3.0mm are slightly small — readable at full - resolution but tight at mobile scale. + comment: All font sizes explicitly set (title=12pt, axis_title=10pt, axis_text=8pt); + well-proportioned in both themes - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text or data elements in either render. + comment: No text or data collisions in either render - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: Dense waveform handled with min/max envelope rendering. Ribbon fills - clearly visible at appropriate alpha values per phase. + comment: Min/max envelope downsampling correctly represents dense waveform; + ribbons clearly visible - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Imprint palette with CVD-safe hues. Phase labels use matching colors. - Good contrast. + comment: CVD-safe Imprint green/lavender/blue triplet with sufficient hue + separation - id: VQ-05 name: Layout & Canvas score: 4 max: 4 passed: true - comment: Canvas gate passed (3200x1800). Waveform fills the plot area well. - No clipping. Balanced margins. + comment: Canvas gate passed; waveform fills canvas well; balanced margins - id: VQ-06 name: Axis Labels & Title - score: 2 + score: 1 max: 2 - passed: true - comment: 'X: ''Time (seconds)'' with units. Y: ''Amplitude'' (normalized -1 - to 1 implied by axis range).' + passed: false + comment: X-axis 'Time (seconds)' complete; Y-axis 'Amplitude' lacks unit qualifier + like '(normalized)' or '[-1, 1]' - id: VQ-07 name: Palette Compliance - score: 1 + score: 2 max: 2 - passed: false - comment: 'First series (Attack) is #009E73 — correct. However Sustain uses - pos-3 (#4467A3) and Release uses pos-2 (#C475FD) — non-canonical order 1,3,2 - without semantic justification. Backgrounds and chrome are correct.' + passed: true + comment: 'Attack=#009E73 (pos 1), Sustain=#C475FD (pos 2), Release=#4467A3 + (pos 3); backgrounds #FAF8F1/#1A1A17 correct' design_excellence: - score: 13 + score: 11 max: 20 items: - id: DE-01 @@ -114,23 +105,25 @@ review: score: 5 max: 8 passed: true - comment: Above well-configured default. Phase-based coloring with different - alpha values, direct labels, and dividers shows design intent. Not yet at - publication-ready level. + comment: 'Above configured default: phase-segmented design with intentional + Imprint color assignment and per-phase alpha variation (0.85/0.65/0.55) + reflects real audio dynamics' - id: DE-02 name: Visual Refinement - score: 4 + score: 3 max: 6 passed: true - comment: theme_minimal() removes top/right spines. Y-axis-only grid at 15% - opacity is correct. Axis lines and ticks explicitly styled. + comment: Y-only grid at alpha=0.15 subtle; x-grid suppressed; theme_minimal + base; axis lines colored. Above minimal but whitespace and typography could + be tighter - id: DE-03 name: Data Storytelling - score: 4 + score: 3 max: 6 passed: true - comment: Clear ADSR story through phase colors, labels, and dividers. Visual - hierarchy guides the viewer through the audio dynamics. + comment: ADSR phase narrative told via color; Sustain dominance is visually + clear. Phase annotation labels at size=3.5 too small to function as strong + narrative anchors spec_compliance: score: 15 max: 15 @@ -140,55 +133,53 @@ review: score: 5 max: 5 passed: true - comment: 'Correct waveform visualization: geom_ribbon as filled area mirrored - above and below zero.' + comment: Correct audio waveform as filled ribbon symmetric around zero - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: 'All features present: filled area, semi-transparent fills, zero-line, - time x-axis, amplitude y-axis (-1 to +1), min/max envelope rendering, synthetic - audio data.' + comment: Filled area, semi-transparent fill, horizontal zero line, time x-axis, + amplitude y-axis, min/max envelope — all present - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: Time on x-axis (0 to 1.5s), normalized amplitude on y-axis (-1.0 - to 1.0). Correct mapping. + comment: Time (0-1.5 s) on x, amplitude (-1 to +1) on y, full data range shown - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: 'Title: ''waveform-audio · python · plotnine · anyplot.ai'' — correct - format. No legend (show_legend=False); phases labeled via direct annotations.' + comment: Title is 'waveform-audio · python · plotnine · anyplot.ai'; no legend + (replaced by inline annotations) data_quality: - score: 15 + score: 14 max: 15 items: - id: DQ-01 name: Feature Coverage - score: 6 + score: 5 max: 6 passed: true - comment: 'Shows all aspects: attack onset, sustained oscillation with vibrato, - release decay, amplitude envelope, harmonic content.' + comment: Attack envelope, sustained oscillation with vibrato, harmonic content, + amplitude decay, noise — strong coverage; minor deduction for harmonic detail + obscured by dense aliasing - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Realistic A3 musical note (220Hz fundamental) with harmonics, amplitude - envelope, vibrato, and noise floor. Neutral topic. + comment: 220 Hz fundamental (A3 note) with 2nd/3rd/5th harmonics, 22050 Hz + sample rate, 1.5 s duration, vibrato at 5 Hz — all real-world plausible - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: 22050Hz sample rate, 1.5s duration, normalized amplitude — all physically - realistic for audio. + comment: Normalized amplitude [-1, 1], realistic duration, proper sample rate; + np.clip prevents artefacts code_quality: score: 10 max: 10 @@ -198,32 +189,32 @@ review: score: 3 max: 3 passed: true - comment: Clean Imports -> Data -> Plot -> Save structure. No functions or - classes. + comment: 'Linear: imports → tokens → data → plot → save; no functions or classes' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set. + comment: np.random.seed(42) set - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports are used. + comment: All imported symbols including scale_alpha_manual are used - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Clean, readable code. No fake interactivity. Phase loop is readable. + comment: Appropriate complexity; no fake UI; chunking loop is clear and purposeful - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot-{THEME}.png with correct dpi/dimensions. + comment: plot.save(f'plot-{THEME}.png', dpi=400, width=8, height=4.5, units='in') + — correct library_mastery: score: 7 max: 10 @@ -233,25 +224,27 @@ review: score: 4 max: 5 passed: true - comment: 'Good idiomatic plotnine: ggplot + geom_ribbon + aes with fill/alpha - mapped to categorical phase variable + scale_fill_manual + scale_alpha_manual. - Layer composition is well-executed.' + comment: Fluent ggplot2 grammar with geom_ribbon dual-aes mapping (fill+alpha), + scale_fill_manual + scale_alpha_manual; annotate, geom_hline, geom_vline + layered naturally - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: Uses geom_ribbon with dual aesthetic mapping (fill + alpha to same - categorical variable) — distinctly ggplot/plotnine grammar. geom_ribbon - for waveform envelope is a natural plotnine idiom. - verdict: REJECTED + comment: Combining geom_ribbon with simultaneous fill+alpha aesthetic mappings + from one categorical variable is a plotnine/ggplot2 distinctive pattern + not easily replicated in matplotlib + verdict: APPROVED impl_tags: dependencies: [] techniques: - annotations - layer-composition + - manual-ticks patterns: - data-generation + - iteration-over-groups dataprep: - binning styling: