Skip to content

feat(bokeh): implement spectrogram-mel#8414

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

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

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

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

Implementation: spectrogram-mel - python/bokeh

Implements the python/bokeh version of spectrogram-mel.

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

Parent Issue: #4672


🤖 impl-generate workflow

github-actions Bot and others added 2 commits June 3, 2026 18:06
Regen from quality 92. Addressed:
- Canvas corrected to 3200x1800 (was 4800x2700)
- Added ANYPLOT_THEME support with theme-adaptive PAGE_BG/INK/INK_SOFT tokens
- Fixed title to spectrogram-mel · python · bokeh · anyplot.ai
- Replaced export_png with Selenium + CDP setDeviceMetricsOverride (canonical save pattern)
- Switched from quad glyphs to p.image for idiomatic Bokeh image rendering (LM-01)
- Y-axis now uses linear mel band indices with Hz override labels (works correctly with p.image)
- Removed p.outline_line_color for cleaner aesthetic (DE-02)
- Colorbar title/label colors now use INK/INK_SOFT theme tokens

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@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 plot renders on a warm off-white (#FAF8F1) background. The mel-spectrogram occupies nearly the full plot area with a Magma colormap running from dark purple/black (low power) through orange-red to bright yellow (high power). The title "spectrogram-mel · python · bokeh · anyplot.ai" is bold, dark-inked, and clearly readable at the top. Y-axis shows frequency labels at 50 Hz, 100 Hz, 200 Hz, 500 Hz, 1000 Hz, 2000 Hz, 4000 Hz, 8000 Hz. X-axis shows time 0–4 seconds. A colorbar on the right is labeled "Power (dB)" with ticks at −20, −30, −40, −50, −60. Two white italic annotations label the "C Major Arpeggio (C4 → E4 → G4 → C5)" and "Descending (A4 → F4 → D4)" sections, separated by a dashed vertical line. Dotted horizontal reference lines mark C4 and C5 fundamentals with text labels on the right edge. All text is readable against the light background.

Dark render (plot-dark.png): The plot renders on a near-black (#1A1A17) border background with the spectrogram interior at #4. The spectrogram data colors are identical to the light render (Magma colormap, same harmonic bands visible). Title and axis text appear light-colored against the dark border, all readable. Critical failure: the ColorBar widget's background_fill_color was not set to PAGE_BG, so the colorbar area on the right side renders with a white background against the dark page — a jarring white rectangle in the dark render. Colorbar tick labels are set to INK_SOFT (#B8B7B0 in dark mode = light gray), which renders with very low contrast against this white colorbar background — the −20/−30/−40/−50/−60 dB tick values are barely readable. Title, axis labels, and tick labels on the main plot area pass legibility checks.

Score: 87/100

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

Visual Quality (24/30)

  • VQ-01: Text Legibility (5/8) — All sizes explicitly set (title 50pt, axis 42pt, ticks 34pt). Main plot text readable in both themes. Dark render colorbar tick labels (INK_SOFT #B8B7B0) rendered against white colorbar background — very low contrast, barely readable.
  • VQ-02: No Overlap (6/6) — No overlapping elements detected in either render.
  • VQ-03: Element Visibility (6/6) — Spectrogram image fully visible; harmonic bands and frequency structure clearly discernible at full resolution.
  • VQ-04: Color Accessibility (2/2) — Magma is perceptually uniform and CVD-safe. White annotations visible against dark spectrogram.
  • VQ-05: Layout & Canvas (3/4) — Canvas 3200×1800, min_border values correctly set, colorbar positioned right. Colorbar white background in dark render creates a visual artifact breaking the dark theme.
  • VQ-06: Axis Labels & Title (2/2) — X: "Time (seconds)", Y: "Frequency (Hz)", Colorbar: "Power (dB)" — all descriptive with units.
  • VQ-07: Palette Compliance (0/2) — Non-compliant. Uses Magma256 (a Bokeh named palette) for continuous data. The bokeh.md library guide explicitly forbids this: "Forbidden: bokeh's Viridis/Cividis/BrBG and any other named palette for continuous data." Must use ANYPLOT_SEQ256 (imprint_seq, green→blue). Additionally, color_bar.background_fill_color not set to PAGE_BG, causing a white colorbar background in dark mode.

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above default: custom mel filter bank from scratch, harmonically synthesized melody, thoughtful annotation strategy. However, non-compliant colormap and colorbar white background in dark mode reduce polish below publication-ready level.
  • DE-02: Visual Refinement (4/6) — Grid hidden (appropriate for image glyph), outline removed, min_borders set, annotations semi-transparent (alpha 0.65–0.85). Colorbar background not theme-adaptive in dark mode is a refinement oversight.
  • DE-03: Data Storytelling (5/6) — Strong storytelling: C-major arpeggio narrative with labeled ascending/descending sections, dashed box separating regions, C4/C5 horizontal reference guides. Viewer immediately understands the musical structure.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct mel-spectrogram: STFT → mel filterbank → dB scale → image glyph.
  • SC-02: Required Features (4/4) — All spec features: dB scale, Hz labels at key mel bands, colorbar labeled in dB, n_fft=2048, hop_length=512, n_mels=128, synthesized audio.
  • SC-03: Data Mapping (3/3) — X: time in seconds, Y: mel-frequency bands with Hz overrides, color: power in dB.
  • SC-04: Title & Legend (3/3) — Title matches required format exactly.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows mel compression (dense low-freq bands, sparse high-freq), harmonic overtones, temporal note structure, attack/release envelopes, background noise.
  • DQ-02: Realistic Context (5/5) — C-major melody with correct note frequencies (C4=261.63 Hz, E4=329.63 Hz, etc.) is a natural, neutral audio ML context.
  • DQ-03: Appropriate Scale (4/4) — 4s at 22050 Hz, canonical STFT parameters, dB range realistic for synthesized audio, correct musical note frequencies.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear flow, no functions/classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All imports are used; no extras.
  • CQ-04: Code Elegance (2/2) — Clean mel filterbank from scratch avoids librosa dependency; CDP setDeviceMetricsOverride for exact canvas dimensions is the correct pattern.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html.

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — Expert Bokeh usage: p.image() for the spectrogram, LinearColorMapper + ColorBar, HoverTool with @image{0.1} dB format, FixedTicker + major_label_overrides for Hz labels, BoxAnnotation, Span, Label.
  • LM-02: Distinctive Features (4/5) — HoverTool reading spectrogram pixel values interactively, major_label_overrides for custom axis labels, and BoxAnnotation for region highlighting are distinctively Bokeh. Not quite 5 as the core rendering (image glyph) is standard.

Score Caps Applied

  • None

Strengths

  • Excellent spec compliance: mel filterbank computed from scratch, correct STFT parameters, dB scale, all required Hz tick labels at mel band edges, colorbar labeled in dB
  • Strong data storytelling: arpeggio labels, dashed section separator, C4/C5 reference lines create a clear musical narrative
  • Expert Bokeh library usage: HoverTool with spectrogram value readout, major_label_overrides, BoxAnnotation, Span — idiomatic and distinctive
  • Correct canvas sizing (3200×1800) with proper min_border reservations; CDP override for exact PNG dimensions
  • Realistic, correctly-parameterized synthesized audio data with harmonic overtones and natural envelopes

Weaknesses

  • Non-Imprint continuous colormap: Magma256 (a Bokeh named palette) is used instead of the required imprint_seq (green→blue gradient). The bokeh.md guide and style guide explicitly forbid all Bokeh named palettes for continuous data. Replace with: ANYPLOT_SEQ256 = [_lerp_hex("#009E73", "#4467A3", t/255.0) for t in range(256)] and pass to LinearColorMapper(palette=ANYPLOT_SEQ256, ...)
  • ColorBar background not theme-adaptive: color_bar.background_fill_color was not set, defaulting to white in the dark render — white rectangle on dark background. Fix: add color_bar.background_fill_color = PAGE_BG and color_bar.background_fill_alpha = 1.0 in the ColorBar constructor
  • Colorbar tick label contrast in dark mode: INK_SOFT (#B8B7B0) on the white colorbar background gives very low contrast. Once the background is fixed to PAGE_BG (#1A1A17), the contrast against the dark surface will be correct

Issues Found

  1. VQ-07 CRITICAL — Non-Imprint colormap: Magma256 used instead of required imprint_seq.
    • Fix: Build as a 256-stop lerp from to and use
  2. VQ-07/VQ-01 — Colorbar not dark-adapted: ColorBar background defaults to white in dark render.
    • Fix: Add to the constructor

AI Feedback for Next Attempt

Two focused fixes needed: (1) Replace with a custom 256-stop colormap (). (2) Add to the constructor so the colorbar area is dark in dark mode. All annotations, storytelling, mel filterbank logic, and Bokeh patterns are excellent — preserve them.

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 plot renders on a warm off-white (#FAF8F1) background. The mel-spectrogram occupies the full inner-chart area, displayed using the imprint_seq colormap (green #009E73 at low dB → blue #4467A3 at high dB). The musical notes (C4→E4→G4→C5 arpeggio, then A4→F4→D4 descending) appear as darker-blue horizontal bands against a bright-green noise floor. The bold title "spectrogram-mel · python · bokeh · anyplot.ai" is clearly visible in dark INK text. Y-axis shows Hz labels at acoustically meaningful frequencies (50→8000 Hz) in INK_SOFT; x-axis shows time in seconds. A dashed white BoxAnnotation separates the arpeggio region; white italic annotations at top identify both sections. Horizontal dotted Spans mark C4/C5 fundamentals with bold white labels at the right edge. The colorbar on the right with "Power (dB)" title and dark text is fully readable. All text is readable against the light background. Legibility verdict: PASS.

Dark render (plot-dark.png): The plot renders on warm near-black (#1A1A17). The spectrogram colors are identical to the light render — same green-to-blue gradient, same horizontal note bands — confirming data colors flip with theme. All chrome flips correctly: title and axis labels use light INK (#F0EFE8); tick labels use light INK_SOFT (#B8B7B0); colorbar background uses PAGE_BG (#1A1A17) with light text. No dark-on-dark failures observed; all labels are clearly readable against the dark surface. Legibility verdict: PASS.

Both paragraphs are required. A review that only describes one render is invalid.

Score: 92/100

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

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — All sizes explicitly set (title 50pt, axis labels 42pt, tick labels 34pt). Minor: colorbar tick labels at 22pt and inner italic annotations at 22pt are slightly below canonical 34pt; these could be harder to read at mobile widths.
  • VQ-02: No Overlap (6/6) — No overlapping text or data elements in either render.
  • VQ-03: Element Visibility (6/6) — Spectrogram image fully visible; note bands clearly distinguishable from noise floor; colorbar range well-chosen.
  • VQ-04: Color Accessibility (2/2) — imprint_seq (green→blue) is perceptually uniform and CVD-safe; sequential progression is accessible without hue alone.
  • VQ-05: Layout & Canvas (4/4) — 3200×1800 canvas gate passed; min_border_* values correctly reserve space; plot fills canvas well with balanced margins.
  • VQ-06: Axis Labels & Title (2/2) — "Time (seconds)", "Frequency (Hz)", colorbar "Power (dB)" all descriptive with units.
  • VQ-07: Palette Compliance (2/2) — imprint_seq ("#009E73"→"#4467A3") used for continuous data; background #FAF8F1 / #1A1A17 correct; all chrome is theme-adaptive via INK / INK_SOFT tokens.

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) — Clearly above library defaults: custom imprint_seq colormap, BoxAnnotation region highlight, Span guides for C4/C5, hz-calibrated FixedTicker, theme-adaptive colorbar styling, HoverTool for HTML interactivity. Not quite at publication-ready FiveThirtyEight level due to the non-traditional direction of the sequential cmap for spectrograms (bright green = low energy vs conventional dark=low).
  • DE-02: Visual Refinement (4/6) — Grid hidden (alpha=0, correct for spectrogram); outline removed; colorbar styled with INK/INK_SOFT; axis chrome themed. Min_border values prevent clipping. No spine removal attempted but the full axis frame is appropriate for a spectrogram image glyph.
  • DE-03: Data Storytelling (4/6) — Annotations clearly narrate the C major arpeggio and descending passage; BoxAnnotation separates the two sections visually; C4/C5 Span guides orient the viewer to specific pitches; Hz ticks chosen at musically/perceptually meaningful breakpoints. Story is clear without requiring the viewer to decode raw data.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct mel-spectrogram using STFT + triangular mel filterbank + dB conversion.
  • SC-02: Required Features (4/4) — n_fft=2048, hop_length=512, n_mels=128; dB-scale conversion; Hz labels at key mel band edges; colorbar labeled in dB; synthesized audio (no external file loading).
  • SC-03: Data Mapping (3/3) — X=time (seconds), Y=mel band index with Hz override labels, Color=power (dB); all data axes fully shown.
  • SC-04: Title & Legend (3/3) — Title is exactly "spectrogram-mel · python · bokeh · anyplot.ai"; no separate legend needed (colorbar serves this role).

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — C major arpeggio (C4→E4→G4→C5) + descending (A4→F4→D4) with harmonics (4 partials), ADSR-style envelopes, and background noise; demonstrates note onset, sustain, and harmonic structure.
  • DQ-02: Realistic Context (5/5) — Real-world musical scenario with standard note frequencies (C4=261.63 Hz, A4=440 Hz, etc.); neutral, comprehensible content with no sensitive topics.
  • DQ-03: Appropriate Scale (4/4) — sample_rate=22050 Hz (CD quality), 4s duration, dB range typical for normalized audio; all note frequencies factually accurate.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Linear flow: imports → data generation → STFT → mel filterbank → plot → save. _lerp_hex helper is minimal and necessary for the colormap.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All imports are used (os, sys, time, Path, numpy, bokeh models, scipy.signal, selenium, PIL).
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic; no over-engineering; HoverTool is legitimate for an interactive library.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.html + plot-{THEME}.png; current Bokeh 3.x API throughout.

Library Mastery (9/10)

  • LM-01: Idiomatic Usage (5/5) — Expert use of figure.image() with LinearColorMapper, ColorBar, BoxAnnotation, Span, Label, FixedTicker + major_label_overrides, HoverTool; output_file + Selenium screenshot pattern.
  • LM-02: Distinctive Features (4/5) — BoxAnnotation, Span, interactive HoverTool with image pixel readout, and major_label_overrides for custom Hz labels are all Bokeh-specific. Slightly below 5/5 as the overall pattern (image glyph + hover) is a common Bokeh use case.

Score Caps Applied

  • None — DE-01=6>2 and DE-02=4>2, no "correct but boring" cap triggered. No other caps apply.

Strengths

  • Mel filterbank computed from scratch (triangular filters) without librosa dependency, demonstrating deep signal processing knowledge
  • Correct imprint_seq colormap applied to continuous power data, with theme-adaptive chrome throughout both renders
  • Annotations narrate the C major arpeggio story: BoxAnnotation region, italic labels, C4/C5 Span guides, and Hz ticks at perceptually meaningful frequencies
  • HoverTool provides time/dB readout in the HTML artifact, a genuine Bokeh interactive advantage
  • CDP-based Selenium screenshot + PIL canvas-pinning ensures exact 3200×1800 output dimensions

Weaknesses

  • Colorbar tick labels (22pt) and inner annotation labels (22pt) are below the canonical 34pt tick size; at mobile widths these may be harder to read — raise colorbar major_label_text_font_size to "28pt" and annotation text_font_size to "26pt"
  • The imprint_seq green-to-blue direction maps low energy to bright green and high energy to darker blue, which is counter-intuitive for spectrograms (traditional: dark=silence, bright=signal); consider reversing the palette stops (_lerp_hex("#4467A3", "#009E73", t/255.0)) so the silence floor is dark blue and the active notes are bright green
  • DE-02 could be elevated by hiding the colorbar border line (bar_line_color=None is already set) and adding a subtle stroke to the colorbar itself for separation from the background

Issues Found

  1. VQ-01 MINOR: Colorbar tick labels at 22pt and inner annotations at 22pt are below the 34pt canonical tick size
    • Fix: Raise major_label_text_font_size="28pt" in ColorBar and annotation text_font_size="26pt"
  2. DE-01 OPPORTUNITY: Sequential colormap direction (green=low, blue=high) inverts typical spectrogram convention
    • Fix: Reverse endpoint order in _lerp_hex calls so dark blue anchors the noise floor and bright green marks active signal

AI Feedback for Next Attempt

The implementation is high quality with strong spec compliance, correct palette usage, and excellent data storytelling through annotations. If a repair is needed: (1) raise colorbar and annotation font sizes to 28pt/26pt for better mobile legibility; (2) optionally reverse the imprint_seq direction so bright (#009E73 green) highlights high-energy notes and dark blue (#4467A3) anchors the noise floor, which matches intuitive spectrogram reading convention.

Verdict: APPROVED

@github-actions github-actions Bot added quality:92 Quality score 92/100 ai-approved Quality OK, ready for merge and removed quality:87 Quality score 87/100 labels Jun 3, 2026
@MarkusNeusinger MarkusNeusinger merged commit 67e2398 into main Jun 3, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/spectrogram-mel/bokeh branch June 3, 2026 18:25
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:92 Quality score 92/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant