Skip to content

feat(plotnine): implement piano-roll-midi#8305

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/piano-roll-midi/plotnine
Jun 3, 2026
Merged

feat(plotnine): implement piano-roll-midi#8305
MarkusNeusinger merged 6 commits into
mainfrom
implementation/piano-roll-midi/plotnine

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

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

Implementation: piano-roll-midi - python/plotnine

Implements the python/plotnine version of piano-roll-midi.

File: plots/piano-roll-midi/implementations/python/plotnine.py

Parent Issue: #4565


🤖 impl-generate workflow

github-actions Bot and others added 2 commits June 3, 2026 03:35
Regen from quality 91. Addressed:
- canvas: fixed figure_size=(8,4.5) dpi=400 → 3200×1800 (was 16×9 dpi=300)
- output: renamed plot.png → plot-{THEME}.png (theme-suffixed)
- theme: full ANYPLOT_THEME env handling with theme-adaptive chrome tokens
- colormap: replaced forbidden scale_fill_cmap(inferno) with imprint_seq
  (scale_fill_gradient low=#009E73 high=#4467A3 per Imprint palette rules)
- background: theme-adaptive PAGE_BG/ELEVATED_BG (was hardcoded white)
- piano key shading: theme-adaptive WHITE_KEY_BG/BLACK_KEY_BG
- title: added language token + fixed domain (python · plotnine · anyplot.ai)
- y-axis crowding: show only C and G notes (octave + dominant)

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 surface. Horizontal bands alternate between warm light-grey (#EDE9DE white-key rows) and slightly darker grey (#D8D4C8 black-key rows) to mirror the piano keyboard layout — the contrast is clearly visible. Note rectangles span the piano roll area colored via the Imprint sequential colormap (brand green #009E73 for lower velocity → blue #4467A3 for higher velocity). Dotted vertical lines mark beat subdivisions and solid vertical lines mark measure boundaries at beats 0, 4, 8, 12, 16. Dashed horizontal lines delineate octave boundaries at C notes. Chord symbols (I (C), IV (F), V (G), I (C)) appear in italic INK_SOFT at the top margin. Dynamic markings (mf, ff, dim., p) appear in italic INK_MUTED at the bottom margin. A red "← climax" annotation marks the C5 peak note. The colorbar legend on the right shows "Velocity" 60–120. Title, axis labels ("Pitch", "Time (beats)"), and tick labels (C3, G3, C4, G4, C5 on Y; 0/4/8/12/16 on X) are all clearly readable against the light background. No dark-on-light failure. Legibility verdict: PASS

Dark render (plot-dark.png): The plot renders on a warm near-black #1A1A17 surface. The alternating piano-key row shading is present (WHITE_KEY_BG #212120, BLACK_KEY_BG #141413) but the contrast is considerably more subtle than in the light render — the distinction between white-key and black-key rows is barely perceptible. Data colors (green→blue gradient) are identical to the light render and clearly visible against the dark background. All chrome elements flip correctly: title, axis labels, tick labels, chord symbols, and dynamic markings appear in light off-white (#F0EFE8 / #B8B7B0 / #A8A79F tokens). No dark-on-dark text failure observed — all labels are readable. The "← climax" annotation in #AE3030 (matte red) reads adequately but is quite small. Legibility verdict: PASS (with note: piano-key row distinction is very faint in dark mode)

Score: 88/100

Category Score Max
Visual Quality 26 30
Design Excellence 14 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 8 10
Total 88 100

Visual Quality (26/30)

  • VQ-01: Text Legibility (7/8) — Title (12pt), axis labels (10pt), tick labels (8pt) all explicit and readable at full resolution in both themes. Chord labels (3.5mm≈10pt) and dynamic markings (3.0mm≈8.5pt) are readable at full canvas but may be borderline at mobile/thumbnail scale (~400px width).
  • VQ-02: No Overlap (5/6) — No hard overlaps detected. The "← climax" annotation (x=7.6, y=73) is tight against the "IV (F)" chord label (x=6, y=73.8) in both renders, creating a visually crowded top-margin zone without actual character collision.
  • VQ-03: Element Visibility (5/6) — Note rectangles are well-defined with INK borders. Velocity gradient reads clearly in both themes. However, the white-key vs. black-key row contrast in the dark render (#212120 vs #141413) is very faint — the spec's "alternate shading to distinguish black keys from white keys" is marginally satisfied in dark mode but nearly invisible.
  • VQ-04: Color Accessibility (2/2) — Imprint sequential cmap (#009E73#4467A3) is CVD-safe; not relying on red-green as sole signal.
  • VQ-05: Layout & Canvas (3/4) — 3200×1800 confirmed. Layout is well-proportioned. Title fills ~65% of width at 12pt. Minor concern: chord labels + climax annotation create a slightly cramped top margin; dynamic labels are wedged tightly between the piano roll bottom and x-tick labels.
  • VQ-06: Axis Labels & Title (2/2) — Title matches piano-roll-midi · python · plotnine · anyplot.ai format. X="Time (beats)" with units; Y="Pitch" with note-name tick labels (C3→C5). Both descriptive and correct.
  • VQ-07: Palette Compliance (2/2) — Continuous color uses scale_fill_gradient(low="#009E73", high="#4467A3") — exactly the Imprint imprint_seq cmap. Plot backgrounds #FAF8F1/#1A1A17. All chrome is theme-adaptive.

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (5/8) — Well above generic defaults: custom alternating piano-key background rows thematically mirror a real DAW; differentiated beat (dotted) vs. measure (solid) vertical lines; dashed octave-boundary horizontals add structural depth; chord symbols and dynamic markings provide musical context rarely seen in static charts. Not quite exceptional (some spacing tension, dark-theme key distinction too subtle) but clearly thoughtful.
  • DE-02: Visual Refinement (4/6) — theme_void() removes all superfluous chrome. Background rows replace the panel background meaningfully. Legend uses ELEVATED_BG frame. Beat/measure line visual hierarchy is deliberate. Ticks kept minimal with explicit sizes. Solid refinement above the default of 2.
  • DE-03: Data Storytelling (5/6) — The "← climax" annotation guides the viewer to the musical high point; chord progression labels (I→IV→V→I) frame the harmonic arc; dynamic markings (mf→ff→dim.→p) narrate the intensity curve. The velocity colormap directly encodes the sonic dynamics. Multiple storytelling layers working cohesively.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct MIDI piano roll: horizontal rectangles positioned by pitch (y) and time onset (x), width = duration.
  • SC-02: Required Features (4/4) — Y-axis note names (C3–C5) ✅; alternating black/white key row shading ✅; beat (dotted) + measure (solid) vertical grid lines ✅; sequential velocity colormap (soft=green → loud=blue) ✅; pitch range auto-fit with margin ✅.
  • SC-03: Data Mapping (3/3) — X: time in beats (0–16); Y: MIDI pitch as note names; color: velocity (55–120); width: duration. All 4 data dimensions mapped correctly.
  • SC-04: Title & Legend (3/3) — Title piano-roll-midi · python · plotnine · anyplot.ai exact match. "Velocity" colorbar with 60/80/100/120 breaks. ✅

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — All piano-roll dimensions represented: pitch, onset time, duration (bar width), and velocity (color). Musical annotation layers demonstrate full use of the format.
  • DQ-02: Realistic Context (5/5) — Classic C→F→G→C chord progression with realistic MIDI voice leading, velocity dynamics (mf→ff→dim.→p), and a melodic climax at C5. Musically plausible and content-neutral.
  • DQ-03: Appropriate Scale (4/4) — 35 notes over 16 beats (4 measures) within the 20–200 note / 4–16 measure spec range. Pitch range C3–C5 (MIDI 48–72) is a natural piano playing range.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat script, no unnecessary abstractions or functions/classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All imports used; no dead imports detected.
  • CQ-04: Code Elegance (2/2) — Clear, readable structure with well-named variables. No fake UI elements. geom_rect + multiple layer approach is clean.
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png with correct canvas settings (dpi=400, width=8, height=4.5).

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (4/5) — Correct grammar-of-graphics layering with ggplot() + geom_* + scale_* + coord_* + labs() + theme(). Multiple independent dataframes passed to individual geoms idiomatically. coord_cartesian for precise axis control without data clipping is the right plotnine pattern.
  • LM-02: Distinctive Features (4/5) — Uses plotnine-distinctive layer composition effectively: geom_rect for both background rows and note rectangles (two separate datasets), geom_vline + geom_segment + geom_text + annotate in a single pipeline. guide_colorbar(nbin=200) for smooth gradient display. scale_y_continuous with fully custom breaks/labels for pitch names. This goes well beyond a simple geom_point use case.

Score Caps Applied

  • None applied.

Strengths

  • Full spec compliance: all four required piano-roll features implemented (note rects, key-row shading, beat/measure grid, velocity colormap)
  • Excellent data storytelling: chord labels, dynamic markings, and climax annotation working as cohesive musical narrative
  • Correct Imprint sequential colormap (#009E73#4467A3) with appropriate direction (soft=green, loud=blue)
  • Strong use of plotnine layer composition — multiple independent dataframes passed to individual geoms idiomatically
  • Perfect code quality: clean flat script, deterministic seed, correct output naming

Weaknesses

  • Dark-mode piano key row distinction is nearly invisible — WHITE_KEY_BG=#212120 and BLACK_KEY_BG=#141413 are too similar over #1A1A17 background; increase the contrast difference (e.g. #252523 vs #0F0F0E, or add 10% alpha difference)
  • Top margin is crowded: chord labels (y=pitch_max+0.8) and "← climax" annotation (y=72+1.0) are only 0.8 pitch units apart — nudge the climax annotation to x<7.0 or increase y margin by setting ylim top to pitch_max+2.0
  • Dynamic markings at y=pitch_min-0.3 are wedged between the piano roll and x-axis; moving them slightly lower (y=pitch_min-0.6) or adjusting the coord_cartesian y-bottom would give more breathing room
  • Chord labels and dynamic markings may fall below mobile-readable threshold when scaled to ~400px width — consider increasing from size=3.0/3.5 to 3.5/4.0

Issues Found

  1. VQ-03 MINOR: Dark-mode piano key alternating rows are barely distinguishable (#212120 vs #141413 on #1A1A17). The spec requires visible black/white key distinction in both renders.
    • Fix: Increase the brightness delta between WHITE_KEY_BG and BLACK_KEY_BG in dark theme, e.g. WHITE_KEY_BG = "#27271F" and BLACK_KEY_BG = "#0D0D0B" or similar values with more contrast.
  2. VQ-02 / VQ-05 MINOR: Top margin crowding between chord labels (y≈73.8) and climax annotation (y≈73) creates a visually compressed zone.
    • Fix: Extend ylim top to pitch_max + 2.5 and move chord labels to y = pitch_max + 1.8 so the climax annotation has clear vertical separation.

AI Feedback for Next Attempt

The implementation is strong: correct plot type, full spec features, excellent musical storytelling, and proper Imprint palette usage. Two targeted fixes would lift it further: (1) increase the white-key vs. black-key background row brightness delta in the dark theme so the piano keyboard metaphor reads clearly on #1A1A17; (2) add a bit more vertical space at the top by expanding ylim and nudging the chord label y-position so the climax annotation doesn't crowd them. Everything else — colormap, chord annotations, dynamic markings, code structure — is well-executed and should be preserved.

Verdict: APPROVED

@github-actions github-actions Bot added quality:88 Quality score: 88/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 piano roll rows alternate between two subtle warm grays — lighter (#EDE9DE) for white keys and slightly darker (#D8D4C8) for black keys — producing a clearly readable chromatic structure. Note rectangles are colored from #009E73 (green, low velocity ~60) to #4467A3 (blue, high velocity ~115). The deep-blue C5 note in measure 2 (beat 6–7.5, velocity 115) is the most prominent note — the climax of the phrase. Bass chords (C3/E3/G3/G3/B3) appear in mid-green. Chord labels (I (C), IV (F), V (G), I (C)) are rendered above the piano roll in muted italic, dynamic markings (mf, ff, dim., p) are placed below. A red italic "← climax" annotation marks the peak. The velocity colorbar sits cleanly on the right. Title, axis labels, tick labels, and legend text are all clearly readable against the light background. All text is readable.

Dark render (plot-dark.png): The background is warm near-black #1A1A17. Row alternation is present: white-key rows (#272720) are subtly lighter than the background; black-key rows (#0D0D0B) are darker — creating very low contrast in dark mode. The piano key distinction is barely perceptible in dark mode compared to light mode. Note rectangle colors are identical to the light render (green → blue gradient, Imprint data colors are theme-independent — confirmed). The title renders in light #F0EFE8 ink, clearly readable. Y-axis and X-axis tick labels in #B8B7B0 are readable. Axis labels in light ink — readable. Chord labels and dynamic markings in secondary/tertiary ink — visible. Velocity colorbar visible. The "← climax" annotation in #AE3030 red remains legible on the dark background. No dark-on-dark failures detected. All text is readable against the dark background.

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

Score: 91/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 8 10
Total 91 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (title 12pt, axis labels 10pt, tick labels 8pt, geom_text annotations 3.5–4 mm). All text readable in both themes. Minor: dynamic markings (INK_MUTED, size=3.5 mm) are at the minimum viable size but still legible.
  • VQ-02: No Overlap (6/6) — No overlapping text or data elements. Chord labels, dynamic markings, and climax annotation all well-spaced.
  • VQ-03: Element Visibility (6/6) — Note rectangles clearly visible in both themes with dark border outline; varying widths and velocity colors clearly distinguishable.
  • VQ-04: Color Accessibility (2/2) — Imprint sequential green→blue is CVD-safe. No red-green sole signal. Note outlines provide redundant structural encoding.
  • VQ-05: Layout & Canvas (4/4) — 3200×1800 landscape. Piano roll fills canvas well; colorbar positioned right. coord_cartesian clips correctly; no edge clipping detected.
  • VQ-06: Axis Labels & Title (2/2) — "Time (beats)" with units, "Pitch" with note names on ticks; title in correct format.
  • VQ-07: Palette Compliance (2/2) — Velocity uses imprint_seq (#009E73#4467A3); background #FAF8F1 / #1A1A17; data colors identical across themes; all chrome tokens theme-adaptive.

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) — Strong design clearly above defaults: piano key alternating backgrounds with theme adaptation, chord progression labels (I–IV–V–I), dynamic markings (mf/ff/dim./p), climax annotation in semantic red, three-tier grid hierarchy. Shows genuine musical domain expertise and intentional visual design.
  • DE-02: Visual Refinement (4/6) — theme_void() as base removes default chrome; three-tier grid hierarchy (dotted beat 0.25, solid measure 0.5, dashed octave 0.35) is well-executed refinement; clean colorbar and margins.
  • DE-03: Data Storytelling (4/6) — Chord labels create harmonic narrative; mf→ff→dim→p dynamic arc tells the intensity story; climax annotation focuses the eye on the musical peak. Good storytelling, but melody/bass distinction is not visually reinforced (no size or alpha differentiation between registers).

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct piano roll: horizontal rectangles positioned by pitch (Y) and time (X), width=duration, color=velocity.
  • SC-02: Required Features (4/4) — Note names on Y-axis, black/white key background alternation, beat (dotted) and measure (solid) grid lines, sequential velocity colormap, pitch range auto-fitted with margin.
  • SC-03: Data Mapping (3/3) — X=time in beats, Y=pitch with note names, color=velocity, width=duration; all 16 beats / 4 measures visible.
  • SC-04: Title & Legend (3/3) — Title piano-roll-midi · python · plotnine · anyplot.ai matches required format exactly; Velocity colorbar labeled correctly.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Demonstrates chord voicings, melodic runs, varying durations, full velocity range (60–115), bass + melody registers, 4-measure I–IV–V–I phrase.
  • DQ-02: Realistic Context (5/5) — Canonical Western chord progression (C→F→G→C), realistic MIDI velocities, musically plausible note durations, authentic climax structure.
  • DQ-03: Appropriate Scale (4/4) — MIDI 48–72 (C3–C5), velocity 60–115, 16 beats = 4 measures in 4/4 — all factually correct for a MIDI piano roll.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat script: tokens → data → derived data → plot layers → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set; data is hardcoded tuples — fully deterministic.
  • CQ-03: Clean Imports (2/2) — All plotnine imports are used; numpy, pandas, os all used. No unused imports.
  • CQ-04: Code Elegance (2/2) — Pythonic, appropriate complexity; multiple DataFrames for different geom layers is the correct plotnine pattern; no fake interactivity.
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png with dpi=400, width=8, height=4.5, units='in'. Current plotnine 0.15.5 API.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (5/5) — Expertly uses plotnine's grammar of graphics: multiple geom layers on separate data frames, scale functions for axes and fill, coord_cartesian, guide_colorbar, fine-grained theme() customization.
  • LM-02: Distinctive Features (3/5) — Uses some plotnine-specific features (multi-dataframe layer composition, guide_colorbar, annotate, element theme components). The piano roll structure itself is replicable in matplotlib — no uniquely-plotnine capability (stat transforms, position adjustments, facet_*) is leveraged.

Score Caps Applied

  • None — no cap-triggering conditions met.

Strengths

  • Piano-key alternating backgrounds with correct theme adaptation (WHITE_KEY_BG/BLACK_KEY_BG tokens) — genuinely distinctive domain-aware design
  • Three-tier grid hierarchy (dotted beat lines, solid measure boundaries, dashed octave lines) creates elegant visual structure
  • Chord progression labels (I, IV, V, I) and dynamic markings (mf, ff, dim., p) provide real musical narrative context
  • Imprint sequential colormap (#009E73 soft → #4467A3 loud) applied correctly for velocity — proper imprint_seq use
  • Complete spec compliance: note names on Y-axis, velocity colorbar, beat/measure grid, pitch range auto-fitted, all features present
  • Both themes render correctly with no dark-on-dark or light-on-light failures

Weaknesses

  • In dark render, black-key rows (#0D0D0B) against #1A1A17 background provide very little contrast — the piano key distinction is barely perceptible in dark mode. Consider boosting BLACK_KEY_BG dark value slightly (e.g. #151510) while keeping it darker than the #272720 white-key rows.
  • LM-02: No distinctively plotnine-only feature (stat transforms, position adjustments, facet_grid) is leveraged — the implementation could be replicated in matplotlib with similar effort.
  • DE-03: Melody/bass register distinction is not visually reinforced — a subtle size or alpha difference between melody notes (high pitch) and accompaniment chords (lower pitch) would strengthen the focal hierarchy.

Issues Found

  1. VQ-01 MINOR: Dynamic markings (mf, ff, dim., p) at size=3.5 mm / INK_MUTED are at the lower limit of legibility — readable at full resolution but borderline at mobile scale.
    • Fix: Increase to size=4.0 or use INK_SOFT instead of INK_MUTED for slightly higher contrast.
  2. DE-03 MODERATE: No visual differentiation between melody line and bass chord notes — both are sized and styled identically.
    • Fix: Consider slight alpha difference (bass notes alpha=0.85, melody alpha=1.0) or thicker outlines on melody notes to guide the viewer's eye.

AI Feedback for Next Attempt

The implementation is strong — spec compliance and data quality are perfect. To push further: (1) Boost the dark-mode black-key row color slightly for better piano key contrast in dark theme. (2) Add a subtle visual differentiation between melody notes and bass/chord notes (alpha or outline weight) to strengthen the data storytelling focal hierarchy. (3) Consider using a plotnine-specific feature like faceting or stat transforms to demonstrate library mastery if the plot permits it.

Verdict: APPROVED

@github-actions github-actions Bot added quality:91 Quality score 91/100 ai-approved Quality OK, ready for merge and removed quality:88 Quality score: 88/100 labels Jun 3, 2026
@MarkusNeusinger MarkusNeusinger merged commit 0691439 into main Jun 3, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/piano-roll-midi/plotnine branch June 3, 2026 03:55
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