Skip to content

feat(plotnine): implement spectrogram-mel#8415

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/spectrogram-mel/plotnine
Jun 3, 2026
Merged

feat(plotnine): implement spectrogram-mel#8415
MarkusNeusinger merged 6 commits into
mainfrom
implementation/spectrogram-mel/plotnine

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented Jun 3, 2026

Implementation: spectrogram-mel - python/plotnine

Implements the python/plotnine version of spectrogram-mel.

File: plots/spectrogram-mel/implementations/python/plotnine.py

Parent Issue: #4672


🤖 impl-generate workflow

github-actions Bot added 2 commits June 3, 2026 18:05
Regen from quality 90. Addressed:
- Canvas: fixed figure_size=(16,9) dpi=300 → (8,4.5) dpi=400 → exact 3200×1800
- Theme: added ANYPLOT_THEME env var support with fully adaptive chrome tokens
- Output: fixed plot.save("plot.png") → plot.save(f"plot-{THEME}.png", ...)
- Title: fixed "pyplots.ai" → "anyplot.ai", added missing "python" language token
- Colormap: replaced hardcoded inferno-like gradient with Imprint sequential palette (PAGE_BG → #009E73 → #4467A3)
- Change request: replaced 220 Hz + chirp sweep with 330 Hz (E4) fundamental + rhythmic noise bursts
- LM-02: added spectral peak trajectory as a grammar-of-graphics second data layer (geom_line)
- Annotations: increased F0 reference line alpha from 0.15 → 0.6, now clearly visible
- sys.path fix: prevents plotnine.py from shadowing the installed plotnine package
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jun 3, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The mel-spectrogram is rendered on a warm off-white background (#FAF8F1). The raster heatmap fills the plot area with a 3-stop gradient from near-background through brand green (#009E73) to blue (#4467A3), encoding Power (dB) from ~−80 to 0. Bright vertical stripes at ~0.3, 0.8, 1.3, 1.8, 2.3, 2.8 s correspond to rhythmic noise bursts. The ochre spectral peak trajectory (IMPRINT_PALETTE[3] = #BD8233) is visible as a jagged line riding the dominant frequency, clearly contrasting with the green/blue spectrogram. A dashed green F₀ reference line runs horizontally at ~330 Hz, and a small "F₀ = 330 Hz" text annotation appears above it. The Y-axis shows Hz labels (128–8000 Hz) at mel-band positions, the X-axis shows Time (s), and the colorbar is on the right labeled "Power (dB)". Title reads "spectrogram-mel · python · plotnine · anyplot.ai". All text is clearly readable against the light background — no light-on-light failures.

Dark render (plot-dark.png): The same plot on the near-black background (#1A1A17). Data colors are identical to the light render (green→blue raster, ochre peak trajectory, green F₀ line). Chrome flips correctly: title and axis labels render in near-white (#F0EFE8 equivalent), tick labels in light gray (#B8B7B0 equivalent). Colorbar shows tick marks and "Power (dB)" label in light text. No dark-on-dark failures observed — all text is readable against the dark background. Brand green #009E73 remains visible in both the colormap and the overlay elements.

Both renders are theme-correct and display identical data colors with only chrome flipping between themes.

Score: 87/100

Category Score Max
Visual Quality 27 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 7 10
Total 87 100

Visual Quality (27/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (title 12pt, axes 10pt, ticks 8pt, legend 8pt). The F₀ annotation uses in geom_text (≈8.5 pt), which is on the small side at mobile widths. All major labels clearly readable in both themes.
  • VQ-02: No Overlap (6/6) — No text or element collisions observed.
  • VQ-03: Element Visibility (5/6) — Heatmap, peak trajectory, F₀ line, and colorbar are all well-sized and visible. F₀ label is marginally small.
  • VQ-04: Color Accessibility (1/2) — The F₀ reference line uses #009E73 (brand green) against a green-dominant spectrogram, producing low contrast for CVD viewers. The dashed linetype provides partial redundancy, but color distinction is weak. Ochre peak trajectory is well-contrasted.
  • VQ-05: Layout & Canvas (4/4) — Canvas correct at 3200×1800 px (8×4.5 in @ 400 dpi). Good proportions; plot fills the canvas well; colorbar properly positioned on right; margins generous.
  • VQ-06: Axis Labels & Title (2/2) — "Time (s)", "Frequency (Hz)", "Power (dB)" colorbar — all descriptive with units.
  • VQ-07: Palette Compliance (2/2) — Custom 3-stop gradient [PAGE_BG → #009E73 → #4467A3] is an Imprint-derived sequential cmap — correct for single-polarity continuous data. Backgrounds are #FAF8F1 (light) / #1A1A17 (dark). Chrome is fully theme-adaptive in both renders.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Clearly above a library default: custom Imprint-derived colormap, intentional multi-layer composition (heatmap + ochre trajectory + dashed F₀ + annotation), alpha used thoughtfully. Not quite publication-ready (title and label typography could be more polished), but distinctly designed.
  • DE-02: Visual Refinement (4/6) — Grid fully removed; theme_minimal base keeps spines minimal; colorbar narrow and well-proportioned (). Clean plot area with no visual noise.
  • DE-03: Data Storytelling (4/6) — Spectral peak trajectory (ochre) guides the eye through dominant frequency over time. F₀ reference line + label ground the viewer in the note's fundamental. Rhythmic bursts visible as vertical stripes. Clear visual hierarchy through color contrast and labeled reference.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct mel-spectrogram using geom_raster with mel-scaled frequency axis.
  • SC-02: Required Features (4/4) — dB conversion (10·log10 + 0 dB normalization), Hz-labeled Y-axis via np.interp, colorbar labeled "Power (dB)", n_fft=2048/hop_length=512/n_mels=128, STFT-based power spectrum. Sequential Imprint cmap used instead of viridis/magma/inferno (correct per style guide).
  • SC-03: Data Mapping (3/3) — X=time (s), Y=mel band indexed to Hz, fill=Power (dB). All data mapped correctly.
  • SC-04: Title & Legend (3/3) — Title is "spectrogram-mel · python · plotnine · anyplot.ai" (correct format). Colorbar labeled "Power (dB)".

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Synthesized signal with fundamental (330 Hz / E4), harmonics (660, 990, 1650, 3300 Hz), amplitude decay envelopes, and rhythmic noise bursts. Shows full range of spectrogram features.
  • DQ-02: Realistic Context (5/5) — Musical/audio signal synthesis is a completely realistic and neutral scientific scenario. Comment explains the audio design intent.
  • DQ-03: Appropriate Scale (4/4) — 22050 Hz sample rate, 3 s duration, 128 mel bands, n_fft=2048, hop_length=512 — all standard audio ML parameters.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear: imports → data synthesis → STFT → mel filterbank → DataFrame construction → plot → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — .
  • CQ-03: Clean Imports (2/2) — All imports are used. sys.path manipulation is explained and necessary for the naming conflict.
  • CQ-04: Code Elegance (2/2) — Vectorized mel filterbank (no loops), clean grammar-of-graphics composition, well-organized sections.
  • CQ-05: Output & API (1/1) — .

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Expert multi-layer grammar-of-graphics: geom_raster for heatmap, geom_line with and separate data for peak trajectory, geom_segment for reference line, geom_text for annotation, scale_fill_gradientn + guides(fill=guide_colorbar(...)) for colorbar customization. Proper coord_cartesian for clipping. Note: in guide_colorbar is not a standard plotnine parameter (likely silently ignored); the correct parameter is .
  • LM-02: Distinctive Features (3/5) — geom_raster is the idiomatic plotnine choice for raster heatmaps (vs geom_tile). Grammar-of-graphics multi-dataset layer composition with is distinctively ggplot-family. Does not leverage uniquely plotnine features beyond the ggplot paradigm.

Score Caps Applied

  • None

Strengths

  • Excellent multi-layer grammar-of-graphics composition (geom_raster + geom_line + geom_segment + geom_text with separate datasets and inherit_aes=False) — idiomatic plotnine
  • Perfect spec compliance: manual mel filterbank (vectorized, no librosa dependency), correct dB conversion, Hz-labeled Y-axis, proper STFT parameters
  • Thoughtful Imprint-derived colormap [PAGE_BG → #009E73 → #4467A3] — Imprint sequential cmap fully compliant, with smart PAGE_BG floor for silence-blends-with-background effect
  • Ochre (#BD8233) spectral peak trajectory visually pops against the green/blue spectrogram — strong contrast
  • Both themes fully correct: backgrounds, chrome, and colorbar all theme-adaptive; data colors identical across renders

Weaknesses

  • F₀ reference line uses #009E73 (brand green) against a green-dominant spectrogram — low contrast especially under CVD (deuteranopia). Consider using ochre (#BD8233), cyan (#2ABCCD), or INK_SOFT instead of brand green for the reference line so it's distinguishable from the heatmap
  • F₀ annotation label (≈8.5 pt) is very small — increase to size=3.5–4.0 to ensure mobile readability
  • in is not a recognized plotnine parameter — replace with (the correct plotnine API)
  • DE-01 gap: to reach 6/8, polish the typography — bold the title weight, add slight padding between colorbar and plot, or consider a thin spine on the left/bottom for grounding

Issues Found

  1. VQ-04 LOW: F₀ reference line (#009E73 brand green) has low contrast against the green spectrogram background, especially under deuteranopia
    • Fix: Change F₀ line color to (#2ABCCD cyan) or for clear visual distinction from the green heatmap
  2. LM-01 MINOR: — is not a valid plotnine parameter
    • Fix: Replace with
  3. VQ-01 MINOR: F₀ label too small at
    • Fix: Increase to or

AI Feedback for Next Attempt

Good implementation overall. Three targeted fixes: (1) Change the F₀ reference line color from #009E73 to #2ABCCD (cyan) or INK_SOFT so it's visually distinct from the green heatmap background — reduces CVD-accessibility concern. (2) Fix → to use the correct plotnine API. (3) Increase the F₀ annotation text size from 3.0 to 3.5–4.0 mm for better mobile readability. Optional: bold the title with to push DE-01 above 5.

Verdict: REJECTED

@github-actions github-actions Bot added quality:87 Quality score 87/100 ai-rejected Quality not OK, triggers update labels Jun 3, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Jun 3, 2026
Attempt 1/3 - fixes based on AI review
@github-actions
Copy link
Copy Markdown
Contributor Author

github-actions Bot commented Jun 3, 2026

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jun 3, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The mel-spectrogram renders on a warm off-white #FAF8F1 background. The heatmap fills the full plot area with a teal-green-to-blue gradient: silence maps to #FAF8F1, mid-energy to brand green #009E73, peak energy to #4467A3 blue. Six rhythmic burst events are visible as vertical brightening columns at ~0.3 s intervals. An ochre (#BD8233) spectral peak trajectory line overlays the lower frequency bands (~256–512 Hz range), spiking at each percussion burst. A cyan (#2ABCCD) dashed F₀ reference line runs horizontally at the 330 Hz mel-band. A small "F₀ = 330 Hz" annotation in INK_SOFT sits just above the reference line. Title in bold dark ink, axis labels and tick labels (128–8000 Hz, 0–3 s) in dark-grey INK_SOFT. Colorbar on the right labeled "Power (dB)" with ticks at 0, −20, −40, −60. All text is clearly readable against the light background.

Dark render (plot-dark.png): The same plot on a warm near-black #1A1A17 surface. The heatmap data colors are identical — the green-blue gradient emerges seamlessly from the dark background (the #1A1A17 start of the colormap blends silence with the surface, an intentional design choice). Ochre peak trajectory and cyan F₀ reference line are identically positioned and colored. Title and all axis/tick labels render in light cream/grey (#F0EFE8 / #B8B7B0) — fully readable against the dark background. No dark-on-dark text failures. The colorbar's lowest-energy swatch (−60 dB = #1A1A17) blends slightly with the dark legend area, making the bottom colorbar tick slightly ambiguous, but all text labels remain legible.

Both renders pass the theme-readability check. Data colors are identical across both themes (only chrome flips).

Score: 91/100

Category Score Max
Visual Quality 28 30
Design Excellence 14 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 9 10
Total 91 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (title=12, axis=10, ticks=8, legend=8); F₀ annotation size=3.5 mm slightly small at mobile scale
  • VQ-02: No Overlap (6/6) — No overlapping elements
  • VQ-03: Element Visibility (5/6) — Heatmap and reference line excellent; spectral peak trajectory (size=0.9, alpha=0.65) somewhat thin against the heatmap
  • VQ-04: Color Accessibility (2/2) — CVD-safe sequential colormap; ochre and cyan overlays distinguishable across CVD types
  • VQ-05: Layout & Canvas (4/4) — 3200×1800 landscape, heatmap fills plot area, colorbar well-positioned, no overflow or clipping
  • VQ-06: Axis Labels & Title (2/2) — "Time (s)", "Frequency (Hz)", "Power (dB)" all descriptive with units
  • VQ-07: Palette Compliance (2/2) — Sequential colormap PAGE_BG→#009E73#4467A3 (Imprint-derived, theme-adaptive); backgrounds #FAF8F1/#1A1A17 correct; all chrome theme-adaptive

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) — Strong design: custom Imprint colormap, three analytically purposeful layers with distinct hue choices (green-blue heatmap, ochre peak, cyan F₀), professional spectrogram aesthetic
  • DE-02: Visual Refinement (4/6) — Grid fully disabled (appropriate for heatmap), clean theme_minimal base, generous margins, properly sized colorbar key
  • DE-03: Data Storytelling (4/6) — Spectral peak trajectory guides the viewer through temporal energy concentration; F₀ reference provides an analytical anchor; burst events create a clear rhythmic visual pattern

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct mel-spectrogram with mel-scaled frequency axis
  • SC-02: Required Features (4/4) — dB scale, sequential colormap, time X-axis, mel-Hz Y-axis, colorbar in dB, n_fft=2048, hop=512, n_mels=128, synthesized audio
  • SC-03: Data Mapping (3/3) — X=time(s), Y=mel-band with Hz labels, fill=Power(dB)
  • SC-04: Title & Legend (3/3) — "spectrogram-mel · python · plotnine · anyplot.ai"; colorbar "Power (dB)"

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Fundamental (E4, 330 Hz), harmonics (660/990/1650/3300 Hz), temporal decay, rhythmic noise bursts — full mel-spectrogram feature coverage
  • DQ-02: Realistic Context (5/5) — Realistic musical audio signal, neutral scientific domain
  • DQ-03: Appropriate Scale (4/4) — 22050 Hz sample rate, 3 s duration, 0 to −60+ dB range — standard audio ML parameters

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear Imports→Data→Plot→Save, no functions or classes
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set
  • CQ-03: Clean Imports (2/2) — All imports used; scipy.signal.stft correctly needed
  • CQ-04: Code Elegance (2/2) — Vectorized mel filterbank without librosa is clean and appropriately sophisticated
  • CQ-05: Output & API (1/1) — plot.save(f"plot-{THEME}.png", dpi=400, width=8, height=4.5, units="in")

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — Expert grammar-of-graphics: ggplot + geom layers + scales + guides + theme, correct inherit_aes=False for secondary data layers
  • LM-02: Distinctive Features (4/5) — geom_raster(interpolate=True) for smooth heatmap, guide_colorbar(nbin=256), multi-dataframe layer composition — distinctively plotnine/ggplot

Score Caps Applied

  • None

Strengths

  • Clean vectorized mel filterbank implementation without librosa dependency — all DSP computed from scratch using scipy.signal.stft and numpy matrix ops
  • Multi-layer grammar-of-graphics composition: geom_raster heatmap + ochre spectral peak trajectory + cyan F₀ reference line, each with correctly isolated inherit_aes=False
  • Theme-adaptive Imprint colormap (PAGE_BG → #009E73 → #4467A3) gives seamless silence-to-energy gradient that adapts correctly to both light and dark surfaces
  • Full spec compliance: dB scale, mel y-axis with Hz labels, colorbar labeled in dB, synthesized realistic audio with harmonics and percussion bursts

Weaknesses

  • Spectral peak trajectory (ochre line, size=0.9, alpha=0.65) is thin and partially translucent against the green-blue heatmap; increase to size=1.2 and alpha=0.8 for more prominence at mobile scale
  • F₀ annotation geom_text size=3.5 mm (≈10 pt) is slightly small for the 3200×1800 canvas; increase to size=4.0
  • Colorbar lowest stop in dark mode (#1A1A17) blends with the near-black legend background, making the −60 dB tick visually ambiguous; add legend_background=element_rect(fill=ELEVATED_BG) to create contrast

Issues Found

  1. VQ-03 MINOR: Spectral peak trajectory line slightly thin (size=0.9, alpha=0.65)
    • Fix: Increase to size=1.2, alpha=0.8
  2. DE-02 MINOR: Colorbar dark-mode contrast — lowest swatch blends with background
    • Fix: Add legend_background=element_rect(fill=ELEVATED_BG, color="none") to theme

AI Feedback for Next Attempt

The implementation is strong with excellent spec compliance, clean code, and a well-designed multi-layer composition. Minor improvements: (1) increase spectral peak trajectory visibility with size=1.2 and alpha=0.8; (2) bump F₀ annotation to size=4.0; (3) add explicit legend_background using ELEVATED_BG so the dark-mode colorbar bottom swatch has contrast. These are polish items only — the overall design and analytical depth are above expectations.

Verdict: APPROVED

@github-actions github-actions Bot added quality:91 Quality score 91/100 ai-approved Quality OK, ready for merge and removed quality:87 Quality score 87/100 labels Jun 3, 2026
@MarkusNeusinger MarkusNeusinger merged commit d4131c1 into main Jun 3, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/spectrogram-mel/plotnine branch June 3, 2026 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt quality:91 Quality score 91/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant