From 09339b0b258113a0b887b894283d34f3b061294a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:35:36 +0000 Subject: [PATCH 1/5] feat(plotnine): implement piano-roll-midi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../implementations/python/plotnine.py | 152 ++++++++++-------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/plots/piano-roll-midi/implementations/python/plotnine.py b/plots/piano-roll-midi/implementations/python/plotnine.py index fd31e00202..65a3e6cc8e 100644 --- a/plots/piano-roll-midi/implementations/python/plotnine.py +++ b/plots/piano-roll-midi/implementations/python/plotnine.py @@ -1,9 +1,11 @@ -""" pyplots.ai +"""anyplot.ai piano-roll-midi: MIDI Piano Roll Visualization -Library: plotnine 0.15.3 | Python 3.14.3 -Quality: 91/100 | Created: 2026-03-07 +Library: plotnine | Python 3.13 +Quality: pending | Created: 2026-06-03 """ +import os + import numpy as np import pandas as pd from plotnine import ( @@ -20,7 +22,7 @@ ggplot, guide_colorbar, labs, - scale_fill_cmap, + scale_fill_gradient, scale_x_continuous, scale_y_continuous, theme, @@ -28,11 +30,26 @@ ) -# Data - A short chord progression with melody (C major -> F major -> G major -> C major) +# Theme tokens (Imprint palette, theme-adaptive chrome) +THEME = os.getenv("ANYPLOT_THEME", "light") +PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" +ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" +INK = "#1A1A17" if THEME == "light" else "#F0EFE8" +INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" + +# Piano key shading (theme-adaptive) +WHITE_KEY_BG = "#EDE9DE" if THEME == "light" else "#212120" +BLACK_KEY_BG = "#D8D4C8" if THEME == "light" else "#141413" +BEAT_LINE = "#C4C0B4" if THEME == "light" else "#2C2C29" +MEASURE_LINE = "#8A8780" if THEME == "light" else "#4A4A46" +OCTAVE_LINE = "#ABA89C" if THEME == "light" else "#363632" + +# Data — C major → F major → G major → C major chord progression with melody np.random.seed(42) notes = [ - # Measure 1: C major chord + melody (opening — mf) + # Measure 1: C major chord + melody (mf) (0.0, 2.0, 48, 80), # C3 bass (0.0, 2.0, 52, 70), # E3 (0.0, 2.0, 55, 70), # G3 @@ -42,17 +59,17 @@ (2.0, 1.0, 65, 105), # F4 (3.0, 0.5, 64, 85), # E4 (3.5, 0.5, 62, 80), # D4 - # Measure 2: F major chord + melody (building — f to ff) + # Measure 2: F major chord + melody (f to ff) (4.0, 2.0, 53, 75), # F3 bass (4.0, 2.0, 57, 65), # A3 (4.0, 2.0, 60, 65), # C4 (4.0, 1.0, 65, 110), # F4 melody (5.0, 0.5, 67, 95), # G4 (5.5, 0.5, 69, 100), # A4 - (6.0, 1.5, 72, 115), # C5 high point - CLIMAX + (6.0, 1.5, 72, 115), # C5 — CLIMAX (7.5, 0.5, 69, 80), # A4 # Measure 3: G major chord + descending melody (diminuendo) - (8.0, 2.0, 50, 85), # D3 bass (G/D inversion — tighter pitch range) + (8.0, 2.0, 50, 85), # D3 bass (G/D inversion) (8.0, 2.0, 55, 70), # G3 (8.0, 2.0, 59, 70), # B3 (8.0, 1.0, 71, 105), # B4 melody @@ -61,13 +78,13 @@ (10.0, 1.0, 65, 95), # F4 (11.0, 0.5, 64, 80), # E4 (11.5, 0.5, 62, 75), # D4 - # Measure 4: C major resolution (ending — p, fading) + # Measure 4: C major resolution (p, fading) (12.0, 2.0, 48, 90), # C3 bass (12.0, 2.0, 52, 75), # E3 (12.0, 2.0, 55, 75), # G3 - (12.0, 3.0, 60, 110), # C4 melody - long resolution + (12.0, 3.0, 60, 110), # C4 — long resolution (14.0, 1.0, 64, 70), # E4 - (15.0, 1.0, 60, 60), # C4 ending - soft fade + (15.0, 1.0, 60, 60), # C4 — soft fade ] df = pd.DataFrame(notes, columns=["start", "duration", "pitch", "velocity"]) @@ -75,56 +92,48 @@ df["ymin"] = df["pitch"] - 0.4 df["ymax"] = df["pitch"] + 0.4 -# MIDI note name mapping note_names = ["C", "C♯", "D", "D♯", "E", "F", "F♯", "G", "G♯", "A", "A♯", "B"] -pitch_min = df["pitch"].min() - 1 -pitch_max = df["pitch"].max() + 1 +pitch_min = int(df["pitch"].min()) - 1 # 47 +pitch_max = int(df["pitch"].max()) + 1 # 73 -# Background rows for black/white key distinction +# Background rows — theme-adaptive black/white key shading black_key_semitones = {1, 3, 6, 8, 10} -bg_rows = [] -for p in range(pitch_min, pitch_max + 1): - semitone = p % 12 - is_black = semitone in black_key_semitones - bg_rows.append({"ymin": p - 0.5, "ymax": p + 0.5, "fill_color": "#e6e4ef" if is_black else "#f8f7fc"}) - +bg_rows = [ + {"ymin": p - 0.5, "ymax": p + 0.5, "fill_color": BLACK_KEY_BG if p % 12 in black_key_semitones else WHITE_KEY_BG} + for p in range(pitch_min, pitch_max + 1) +] bg_df = pd.DataFrame(bg_rows) -# Y-axis labels: show only white-key pitches and pitches with notes to reduce crowding -used_pitches = set(df["pitch"].unique()) -pitch_labels_map = {p: f"{note_names[p % 12]}{p // 12 - 1}" for p in range(pitch_min, pitch_max + 1)} -# Show white keys that have data, plus octave C notes for orientation -white_key_semitones = {0, 2, 4, 5, 7, 9, 11} -label_pitches = sorted( - {p for p in used_pitches if p % 12 in white_key_semitones} - | {p for p in range(pitch_min, pitch_max + 1) if p % 12 == 0} -) -label_names = [pitch_labels_map[p] for p in label_pitches] +# Y-axis: C (octave markers) and G (dominant) only — avoids adjacent-label crowding +label_pitches = sorted(p for p in range(pitch_min, pitch_max + 1) if p % 12 in {0, 7}) +label_names = [f"{note_names[p % 12]}{p // 12 - 1}" for p in label_pitches] # Measure structure total_beats = 16 measure_lines = [0, 4, 8, 12, 16] beat_lines = [b for b in range(total_beats + 1) if b not in measure_lines] -# Measure labels at top with chord names +# Chord labels at measure tops measure_labels = pd.DataFrame( {"x": [2, 6, 10, 14], "label": ["I (C)", "IV (F)", "V (G)", "I (C)"], "y": [pitch_max + 0.8] * 4} ) -# Dynamic markings to enhance storytelling +# Dynamic markings below piano roll dynamic_labels = pd.DataFrame({"x": [2, 6.5, 10, 14.5], "label": ["mf", "ff", "dim.", "p"], "y": [pitch_min - 0.3] * 4}) -# Horizontal separators at octave boundaries (every C note) +# Octave boundary lines at each C note octave_cs = [p for p in range(pitch_min, pitch_max + 1) if p % 12 == 0] octave_lines = pd.DataFrame( {"y": [c - 0.5 for c in octave_cs], "xstart": [-0.3] * len(octave_cs), "xend": [total_beats + 0.3] * len(octave_cs)} ) -# Plot using theme_void as base for maximum control (plotnine-distinctive) +title = "piano-roll-midi · python · plotnine · anyplot.ai" + +# Plot plot = ( ggplot() - # Background rows - alternating shading for black/white keys + # Background rows — black/white key distinction + geom_rect( bg_df, aes(xmin=-0.3, xmax=total_beats + 0.3, ymin="ymin", ymax="ymax"), @@ -132,50 +141,51 @@ color=None, show_legend=False, ) - # Beat grid lines (subtle) - + geom_vline(xintercept=beat_lines, color="#d4d2e0", size=0.25, linetype="dotted") - # Measure grid lines (stronger) - + geom_vline(xintercept=measure_lines, color="#9895b0", size=0.5, linetype="solid") - # Octave boundary lines + # Beat grid (subtle dotted) + + geom_vline(xintercept=beat_lines, color=BEAT_LINE, size=0.25, linetype="dotted") + # Measure boundaries (solid) + + geom_vline(xintercept=measure_lines, color=MEASURE_LINE, size=0.5, linetype="solid") + # Octave boundary lines (dashed) + geom_segment( - octave_lines, aes(x="xstart", xend="xend", y="y", yend="y"), color="#b0adc5", size=0.35, linetype="dashed" + octave_lines, aes(x="xstart", xend="xend", y="y", yend="y"), color=OCTAVE_LINE, size=0.35, linetype="dashed" + ) + # Note rectangles — Imprint sequential colormap (green=soft → blue=loud) + + geom_rect(df, aes(xmin="start", xmax="end", ymin="ymin", ymax="ymax", fill="velocity"), color=INK, size=0.3) + # Climax annotation + + annotate("text", x=7.6, y=72 + 1.0, label="← climax", size=3.0, color="#AE3030", fontstyle="italic", ha="left") + # Chord labels at top of each measure + + geom_text(measure_labels, aes(x="x", y="y", label="label"), size=3.5, color=INK_SOFT, fontstyle="italic") + # Dynamic markings below + + geom_text(dynamic_labels, aes(x="x", y="y", label="label"), size=3.0, color=INK_MUTED, fontstyle="italic") + # Imprint sequential cmap: #009E73 (soft/piano) → #4467A3 (loud/forte) + + scale_fill_gradient( + low="#009E73", high="#4467A3", limits=(55, 120), name="Velocity", guide=guide_colorbar(nbin=200) ) - # Note rectangles with velocity color mapping - + geom_rect(df, aes(xmin="start", xmax="end", ymin="ymin", ymax="ymax", fill="velocity"), color="#2d2a3e", size=0.3) - # Climax annotation using plotnine annotate - + annotate("text", x=7.6, y=72 + 1.0, label="← climax", size=9, color="#e05634", fontstyle="italic", ha="left") - # Measure chord labels at top - + geom_text(measure_labels, aes(x="x", y="y", label="label"), size=11, color="#4a4568", fontstyle="italic") - # Dynamic markings below the piano roll - + geom_text(dynamic_labels, aes(x="x", y="y", label="label"), size=9, color="#7a7590", fontstyle="italic") - # Color scale: viridis for perceptual uniformity and colorblind safety - + scale_fill_cmap(cmap_name="inferno", limits=(55, 120), name="Velocity", guide=guide_colorbar(nbin=200)) + scale_y_continuous(breaks=label_pitches, labels=label_names, expand=(0.02, 0.02)) + scale_x_continuous(breaks=measure_lines, labels=["0", "4", "8", "12", "16"], expand=(0.01, 0.01)) + coord_cartesian(xlim=(-0.3, total_beats + 0.3), ylim=(pitch_min - 1.2, pitch_max + 1.5)) - + labs(x="Time (beats)", y="Pitch (note)", title="piano-roll-midi · plotnine · pyplots.ai") - # Start from theme_void for full control, then add back what we need + + labs(x="Time (beats)", y="Pitch", title=title) + theme_void() + theme( - figure_size=(16, 9), - plot_title=element_text(size=24, weight="bold", color="#2d2a3e", margin={"b": 15}), - axis_title_x=element_text(size=20, color="#4a4568", margin={"t": 10}), - axis_title_y=element_text(size=20, color="#4a4568", margin={"r": 10}), - axis_text_x=element_text(size=16, color="#4a4568"), - axis_text_y=element_text(size=16, color="#4a4568"), - axis_ticks_major=element_line(color="#9895b0", size=0.5), - axis_ticks_length=4, + figure_size=(8, 4.5), + plot_title=element_text(size=12, weight="bold", color=INK, margin={"b": 8}), + axis_title_x=element_text(size=10, color=INK, margin={"t": 6}), + axis_title_y=element_text(size=10, color=INK, margin={"r": 6}), + axis_text_x=element_text(size=8, color=INK_SOFT), + axis_text_y=element_text(size=8, color=INK_SOFT), + axis_ticks_major=element_line(color=INK_SOFT, size=0.4), + axis_ticks_length=3, legend_position="right", - legend_title=element_text(size=16, color="#4a4568"), - legend_text=element_text(size=14, color="#4a4568"), - legend_background=element_rect(fill="#f8f7fc", color=None), - legend_key_height=40, - legend_key_width=12, - panel_background=element_rect(fill="#f8f7fc", color=None), - plot_background=element_rect(fill="white", color=None), + legend_title=element_text(size=8, color=INK), + legend_text=element_text(size=8, color=INK_SOFT), + legend_background=element_rect(fill=ELEVATED_BG, color=None), + legend_key_height=30, + legend_key_width=10, + panel_background=element_rect(fill=PAGE_BG, color=None), + plot_background=element_rect(fill=PAGE_BG, color=None), plot_margin=0.02, ) ) # Save -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 0794d608ac28281e7a41582cca9188282d123e1c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:35:49 +0000 Subject: [PATCH 2/5] chore(plotnine): add metadata for piano-roll-midi --- .../metadata/python/plotnine.yaml | 231 ++---------------- 1 file changed, 16 insertions(+), 215 deletions(-) diff --git a/plots/piano-roll-midi/metadata/python/plotnine.yaml b/plots/piano-roll-midi/metadata/python/plotnine.yaml index dcfce384ba..2dfc01f92e 100644 --- a/plots/piano-roll-midi/metadata/python/plotnine.yaml +++ b/plots/piano-roll-midi/metadata/python/plotnine.yaml @@ -1,220 +1,21 @@ +# Per-library metadata for plotnine implementation of piano-roll-midi +# Auto-generated by impl-generate.yml + library: plotnine +language: python specification_id: piano-roll-midi created: '2026-03-07T19:46:37Z' -updated: '2026-03-07T20:15:24Z' -generated_by: claude-opus-4-5-20251101 -workflow_run: 22805912195 +updated: '2026-06-03T03:35:48Z' +generated_by: claude-sonnet +workflow_run: 26861817386 issue: 4565 -python_version: 3.14.3 -library_version: 0.15.3 -preview_url: https://storage.googleapis.com/anyplot-images/plots/piano-roll-midi/plotnine/plot.png -preview_html: null -quality_score: 91 +language_version: 3.13.13 +library_version: 0.15.5 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/piano-roll-midi/python/plotnine/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/piano-roll-midi/python/plotnine/plot-dark.png +preview_html_light: null +preview_html_dark: null +quality_score: null review: - strengths: - - Excellent data storytelling with chord labels, dynamic markings, and climax annotation - creating a musical narrative - - Cohesive purple-themed design with inferno colormap that feels domain-appropriate - - Complete spec compliance with all required features present - - Realistic musical data with proper I-IV-V-I progression showing varied durations - and dynamics - - Clean use of theme_void() as a base for full visual control - weaknesses: - - Y-axis pitch labels slightly crowded where adjacent pitches are both labeled - image_description: The plot displays a MIDI piano roll visualization on a light - purple/white background. Horizontal colored rectangles represent musical notes, - positioned by pitch (y-axis, labeled C3 through C5 with note names) and time (x-axis, - 0-16 beats). The inferno colormap maps velocity from dark purple (soft, ~60) to - yellow (loud, ~120). Alternating row shading distinguishes black keys (slightly - darker lavender) from white keys (lighter). Vertical dotted lines mark beats, - solid gray lines mark measure boundaries at beats 0, 4, 8, 12, 16. Chord labels - (I (C), IV (F), V (G), I (C)) appear at the top, and dynamic markings (mf, ff, - dim., p) at the bottom. A red italic "← climax" annotation marks the C5 note. - The title reads "piano-roll-midi · plotnine · pyplots.ai" in bold dark text. A - velocity colorbar legend is on the right side. - criteria_checklist: - visual_quality: - score: 28 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 8 - max: 8 - passed: true - comment: 'All font sizes explicitly set: title=24, axis titles=20, ticks=16, - legend=16/14' - - id: VQ-02 - name: No Overlap - score: 5 - max: 6 - passed: true - comment: Slight crowding on y-axis where adjacent pitches have labels close - together - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Note rectangles clearly visible with good height and contrast - - id: VQ-04 - name: Color Accessibility - score: 4 - max: 4 - passed: true - comment: Inferno colormap is perceptually uniform and colorblind-safe - - id: VQ-05 - name: Layout & Canvas - score: 3 - max: 4 - passed: true - comment: Good 16:9 proportions, minor extra whitespace above chord labels - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: Time (beats) and Pitch (note) are descriptive with units - design_excellence: - score: 16 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 6 - max: 8 - passed: true - comment: Cohesive purple color scheme with inferno colormap, chord numerals - and dynamic markings - - id: DE-02 - name: Visual Refinement - score: 5 - max: 6 - passed: true - comment: theme_void base with selective restoration, subtle grid hierarchy, - polished legend - - id: DE-03 - name: Data Storytelling - score: 5 - max: 6 - passed: true - comment: Musical narrative with climax annotation, dynamic markings, chord - progression labels - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct piano roll with horizontal rectangles by pitch and time - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: 'All spec features: key shading, note names, grid lines, velocity - coloring, auto-fit range' - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: X=time (beats), Y=pitch (note names), all data visible - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Correct title format, velocity colorbar legend present - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: Chord progressions, varying durations, varying velocities, bass+melody - separation - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Real I-IV-V-I chord progression in C major with melodic contour - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: MIDI pitches 48-72, velocities 60-115, durations 0.5-3.0 beats - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Linear flow: imports, data, dataframes, plot, save' - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: np.random.seed(42) set, data is deterministic - - 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, well-organized, appropriate complexity - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Saves as plot.png with dpi=300, current API - library_mastery: - score: 7 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: Proper grammar of graphics with theme_void base for full control - - id: LM-02 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: theme_void, scale_fill_cmap with guide_colorbar, annotate, per-layer - data - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - annotations - - layer-composition - - colorbar - patterns: - - data-generation - dataprep: [] - styling: - - minimal-chrome - - custom-colormap - - grid-styling - - edge-highlighting + strengths: [] + weaknesses: [] From 2f34ba86c44efdc25e12058b5581746fec167c80 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:42:52 +0000 Subject: [PATCH 3/5] chore(plotnine): update quality score 88 and review feedback for piano-roll-midi --- .../implementations/python/plotnine.py | 6 +- .../metadata/python/plotnine.yaml | 261 +++++++++++++++++- 2 files changed, 257 insertions(+), 10 deletions(-) diff --git a/plots/piano-roll-midi/implementations/python/plotnine.py b/plots/piano-roll-midi/implementations/python/plotnine.py index 65a3e6cc8e..55e77ca4b3 100644 --- a/plots/piano-roll-midi/implementations/python/plotnine.py +++ b/plots/piano-roll-midi/implementations/python/plotnine.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai piano-roll-midi: MIDI Piano Roll Visualization -Library: plotnine | Python 3.13 -Quality: pending | Created: 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/piano-roll-midi/metadata/python/plotnine.yaml b/plots/piano-roll-midi/metadata/python/plotnine.yaml index 2dfc01f92e..561bcf5a7d 100644 --- a/plots/piano-roll-midi/metadata/python/plotnine.yaml +++ b/plots/piano-roll-midi/metadata/python/plotnine.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for plotnine implementation of piano-roll-midi -# Auto-generated by impl-generate.yml - library: plotnine language: python specification_id: piano-roll-midi created: '2026-03-07T19:46:37Z' -updated: '2026-06-03T03:35:48Z' +updated: '2026-06-03T03:42:52Z' generated_by: claude-sonnet workflow_run: 26861817386 issue: 4565 @@ -15,7 +12,257 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/piano-rol preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/piano-roll-midi/python/plotnine/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: null +quality_score: 88 review: - strengths: [] - weaknesses: [] + 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 musically 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 + convention' + 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 (e.g. #272720 vs #0D0D0B) so the black/white key metaphor reads in both + themes' + - '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 — extend ylim top to pitch_max+2.5 and move chord + labels to y=pitch_max+1.8 for clear separation' + - Dynamic markings at y=pitch_min-0.3 are wedged between the piano roll and x-axis + ticks; move to y=pitch_min-0.6 and expand coord_cartesian y-bottom accordingly + - Chord labels (size=3.5mm) and dynamic markings (size=3.0mm) may fall below mobile-readable + threshold at ~400px scaled width — increase to 3.5/4.0mm respectively + image_description: |- + Light render (plot-light.png): + Background: Warm off-white #FAF8F1 — correct theme surface + Chrome: Title "piano-roll-midi · python · plotnine · anyplot.ai" bold, ~65% of plot width, clearly readable in dark INK. Axis labels "Pitch" (y) and "Time (beats)" (x) at 10pt in INK, clearly readable. Tick labels C3/G3/C4/G4/C5 and 0/4/8/12/16 at 8pt INK_SOFT, readable. Chord labels (I (C), IV (F), V (G), I (C)) in italic INK_SOFT at top margin — small but readable at full resolution. Dynamic markings (mf, ff, dim., p) in italic INK_MUTED at bottom margin — small but readable. + Data: Alternating white-key (#EDE9DE) and black-key (#D8D4C8) horizontal bands clearly distinguish piano keyboard rows. Note rectangles colored via Imprint imprint_seq (#009E73 green for low velocity -> #4467A3 blue for high velocity) with dark INK borders. Dotted beat lines and solid measure lines provide time structure. Dashed octave boundary lines at C notes. "← climax" annotation in #AE3030 matte red marks peak note at C5. Colorbar "Velocity" legend 60-120 on right side. + Legibility verdict: PASS + + Dark render (plot-dark.png): + Background: Warm near-black #1A1A17 — correct theme surface + Chrome: All chrome tokens correctly flipped to light values. Title in #F0EFE8 (INK dark-theme), clearly readable against dark background. Axis labels in #F0EFE8, readable. Tick labels in #B8B7B0 (INK_SOFT dark-theme), readable. Chord labels and dynamic markings in lighter tones, readable. No dark-on-dark text failure detected. + Data: Data colors (green-to-blue gradient) are identical to light render — Imprint palette positions stay constant across themes as required. Note rectangles clearly visible against dark background. Beat/measure lines visible with adjusted dark-theme colors. HOWEVER: the piano key row alternation (WHITE_KEY_BG=#212120 vs BLACK_KEY_BG=#141413) is barely perceptible over the #1A1A17 background — the black/white key distinction is much weaker than in the light render. + Legibility verdict: PASS (with concern: piano-key row distinction extremely faint in dark mode, spec requires visible alternating shading) + criteria_checklist: + visual_quality: + score: 26 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: Title 12pt, axis labels 10pt, tick labels 8pt all explicit and readable. + Chord labels (3.5mm) and dynamic markings (3.0mm) readable at full canvas + but may be borderline at mobile scale. + - id: VQ-02 + name: No Overlap + score: 5 + max: 6 + passed: true + comment: No hard overlaps. Climax annotation (x=7.6, y=73) is tight against + IV(F) chord label (x=6, y=73.8) creating crowded top margin without actual + collision. + - id: VQ-03 + name: Element Visibility + score: 5 + max: 6 + passed: true + comment: 'Note rects well-defined with INK borders. Velocity gradient reads + clearly. Piano key row contrast in dark theme is very faint (#212120 vs + #141413 over #1A1A17).' + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Imprint sequential cmap (#009E73->#4467A3) is CVD-safe. No red-green + as sole signal. + - id: VQ-05 + name: Layout & Canvas + score: 3 + max: 4 + passed: true + comment: 3200x1800 correct. Good overall proportions. Minor crowding in top + margin (chord labels + climax annotation) and bottom margin (dynamic labels + between piano roll and x-ticks). + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Title matches required format exactly. X=Time (beats) with units, + Y=Pitch with note-name tick labels (C3-C5). + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'scale_fill_gradient(low=#009E73, high=#4467A3) is exact imprint_seq + cmap. Backgrounds #FAF8F1/#1A1A17. All chrome theme-adaptive.' + design_excellence: + score: 14 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: 'Well above generic defaults: custom piano-key background rows, differentiated + beat/measure lines, dashed octave boundaries, chord symbols, dynamic markings. + Thoughtful DAW-inspired design.' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: theme_void() removes superfluous chrome. Background rows replace + panel background meaningfully. Beat/measure visual hierarchy is deliberate. + Legend uses ELEVATED_BG frame. + - id: DE-03 + name: Data Storytelling + score: 5 + max: 6 + passed: true + comment: Climax annotation guides viewer to musical high point. Chord progression + labels (I->IV->V->I) frame harmonic arc. Dynamic markings (mf->ff->dim.->p) + narrate intensity curve. Multiple storytelling layers working cohesively. + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: 'Correct MIDI piano roll: horizontal rectangles by pitch (y) and + time onset (x), width=duration.' + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Y-axis note names, alternating key shading, beat+measure grid lines, + velocity sequential colormap, pitch range auto-fit — all present. + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X=time beats, Y=MIDI pitch as note names, color=velocity, width=duration. + All 4 data dimensions mapped correctly. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title piano-roll-midi · python · plotnine · anyplot.ai exact match. + Velocity colorbar with 60/80/100/120 breaks. + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: 'All piano-roll dimensions: pitch, onset, duration, velocity. Musical + annotation layers demonstrate full use of the format.' + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Classic C->F->G->C chord progression with realistic MIDI voice leading, + velocity dynamics (mf->ff->dim.->p), melodic climax at C5. Musically plausible + and content-neutral. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: 35 notes over 16 beats (4 measures) within 20-200 note / 4-16 measure + spec range. Pitch C3-C5 (MIDI 48-72) is realistic. + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: Flat script, no unnecessary 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 used, no dead imports detected. + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clear readable structure, well-named variables, no fake UI elements. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves as plot-{THEME}.png with correct canvas settings (dpi=400, + width=8, height=4.5). + library_mastery: + score: 8 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: Correct grammar-of-graphics layering. Multiple independent dataframes + passed to individual geoms idiomatically. coord_cartesian for precise axis + control is the right plotnine pattern. + - id: LM-02 + name: Distinctive Features + score: 4 + max: 5 + passed: true + comment: 'Uses plotnine layer composition: geom_rect for both background rows + and note rects (two datasets), geom_vline + geom_segment + geom_text + annotate + in one pipeline. guide_colorbar(nbin=200) for smooth gradient. scale_y_continuous + with fully custom breaks/labels for pitch names.' + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - colorbar + - annotations + - layer-composition + - manual-ticks + patterns: + - data-generation + - iteration-over-groups + dataprep: [] + styling: + - minimal-chrome + - custom-colormap + - edge-highlighting + - grid-styling From c6bac00f67be8edaba0f58e4570601b6b1712b8c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:47:41 +0000 Subject: [PATCH 4/5] fix(plotnine): address review feedback for piano-roll-midi Attempt 1/3 - fixes based on AI review --- .../implementations/python/plotnine.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plots/piano-roll-midi/implementations/python/plotnine.py b/plots/piano-roll-midi/implementations/python/plotnine.py index 55e77ca4b3..a8a3196dd2 100644 --- a/plots/piano-roll-midi/implementations/python/plotnine.py +++ b/plots/piano-roll-midi/implementations/python/plotnine.py @@ -1,4 +1,4 @@ -""" anyplot.ai +"""anyplot.ai piano-roll-midi: MIDI Piano Roll Visualization Library: plotnine 0.15.5 | Python 3.13.13 Quality: 88/100 | Updated: 2026-06-03 @@ -38,9 +38,9 @@ INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" -# Piano key shading (theme-adaptive) -WHITE_KEY_BG = "#EDE9DE" if THEME == "light" else "#212120" -BLACK_KEY_BG = "#D8D4C8" if THEME == "light" else "#141413" +# Piano key shading (theme-adaptive) — dark values boosted for visible contrast over #1A1A17 +WHITE_KEY_BG = "#EDE9DE" if THEME == "light" else "#272720" +BLACK_KEY_BG = "#D8D4C8" if THEME == "light" else "#0D0D0B" BEAT_LINE = "#C4C0B4" if THEME == "light" else "#2C2C29" MEASURE_LINE = "#8A8780" if THEME == "light" else "#4A4A46" OCTAVE_LINE = "#ABA89C" if THEME == "light" else "#363632" @@ -116,11 +116,11 @@ # Chord labels at measure tops measure_labels = pd.DataFrame( - {"x": [2, 6, 10, 14], "label": ["I (C)", "IV (F)", "V (G)", "I (C)"], "y": [pitch_max + 0.8] * 4} + {"x": [2, 6, 10, 14], "label": ["I (C)", "IV (F)", "V (G)", "I (C)"], "y": [pitch_max + 1.8] * 4} ) # Dynamic markings below piano roll -dynamic_labels = pd.DataFrame({"x": [2, 6.5, 10, 14.5], "label": ["mf", "ff", "dim.", "p"], "y": [pitch_min - 0.3] * 4}) +dynamic_labels = pd.DataFrame({"x": [2, 6.5, 10, 14.5], "label": ["mf", "ff", "dim.", "p"], "y": [pitch_min - 0.6] * 4}) # Octave boundary lines at each C note octave_cs = [p for p in range(pitch_min, pitch_max + 1) if p % 12 == 0] @@ -154,16 +154,16 @@ # Climax annotation + annotate("text", x=7.6, y=72 + 1.0, label="← climax", size=3.0, color="#AE3030", fontstyle="italic", ha="left") # Chord labels at top of each measure - + geom_text(measure_labels, aes(x="x", y="y", label="label"), size=3.5, color=INK_SOFT, fontstyle="italic") + + geom_text(measure_labels, aes(x="x", y="y", label="label"), size=4.0, color=INK_SOFT, fontstyle="italic") # Dynamic markings below - + geom_text(dynamic_labels, aes(x="x", y="y", label="label"), size=3.0, color=INK_MUTED, fontstyle="italic") + + geom_text(dynamic_labels, aes(x="x", y="y", label="label"), size=3.5, color=INK_MUTED, fontstyle="italic") # Imprint sequential cmap: #009E73 (soft/piano) → #4467A3 (loud/forte) + scale_fill_gradient( low="#009E73", high="#4467A3", limits=(55, 120), name="Velocity", guide=guide_colorbar(nbin=200) ) + scale_y_continuous(breaks=label_pitches, labels=label_names, expand=(0.02, 0.02)) + scale_x_continuous(breaks=measure_lines, labels=["0", "4", "8", "12", "16"], expand=(0.01, 0.01)) - + coord_cartesian(xlim=(-0.3, total_beats + 0.3), ylim=(pitch_min - 1.2, pitch_max + 1.5)) + + coord_cartesian(xlim=(-0.3, total_beats + 0.3), ylim=(pitch_min - 1.5, pitch_max + 2.5)) + labs(x="Time (beats)", y="Pitch", title=title) + theme_void() + theme( From b45d490cb3f04d3182a0243235e1515e8f72a659 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:55:27 +0000 Subject: [PATCH 5/5] chore(plotnine): update quality score 91 and review feedback for piano-roll-midi --- .../implementations/python/plotnine.py | 4 +- .../metadata/python/plotnine.yaml | 225 ++++++++++-------- 2 files changed, 132 insertions(+), 97 deletions(-) diff --git a/plots/piano-roll-midi/implementations/python/plotnine.py b/plots/piano-roll-midi/implementations/python/plotnine.py index a8a3196dd2..6518397f5d 100644 --- a/plots/piano-roll-midi/implementations/python/plotnine.py +++ b/plots/piano-roll-midi/implementations/python/plotnine.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai piano-roll-midi: MIDI Piano Roll Visualization Library: plotnine 0.15.5 | Python 3.13.13 -Quality: 88/100 | Updated: 2026-06-03 +Quality: 91/100 | Updated: 2026-06-03 """ import os diff --git a/plots/piano-roll-midi/metadata/python/plotnine.yaml b/plots/piano-roll-midi/metadata/python/plotnine.yaml index 561bcf5a7d..07aecf677b 100644 --- a/plots/piano-roll-midi/metadata/python/plotnine.yaml +++ b/plots/piano-roll-midi/metadata/python/plotnine.yaml @@ -2,7 +2,7 @@ library: plotnine language: python specification_id: piano-roll-midi created: '2026-03-07T19:46:37Z' -updated: '2026-06-03T03:42:52Z' +updated: '2026-06-03T03:55:27Z' generated_by: claude-sonnet workflow_run: 26861817386 issue: 4565 @@ -12,46 +12,54 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/piano-rol preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/piano-roll-midi/python/plotnine/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: 88 +quality_score: 91 review: 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 musically 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 - convention' + - 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 encoding — proper imprint_seq use' + - 'Complete spec compliance: note names on Y-axis, velocity colorbar, beat/measure + grid, pitch range auto-fitted, all required features present' + - Flat KISS code structure with all font sizes explicitly set via element_text — + no functions or classes, fully reproducible with hardcoded data + - Climax annotation (#AE3030 italic) correctly highlights the musical peak at C5 + in measure 2 + - Both themes render correctly with no dark-on-dark or light-on-light failures — + all chrome tokens thread through properly 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 (e.g. #272720 vs #0D0D0B) so the black/white key metaphor reads in both - themes' - - '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 — extend ylim top to pitch_max+2.5 and move chord - labels to y=pitch_max+1.8 for clear separation' - - Dynamic markings at y=pitch_min-0.3 are wedged between the piano roll and x-axis - ticks; move to y=pitch_min-0.6 and expand coord_cartesian y-bottom accordingly - - Chord labels (size=3.5mm) and dynamic markings (size=3.0mm) may fall below mobile-readable - threshold at ~400px scaled width — increase to 3.5/4.0mm respectively + - 'In dark render, black-key rows (#0D0D0B) against the #1A1A17 background provide + very little contrast — the piano key distinction is barely perceptible in dark + mode, making the chromatic structure hard to read. Consider boosting BLACK_KEY_BG + dark value slightly (e.g. #151510) while keeping it below #1A1A17.' + - 'LM-02: The plotnine implementation uses the grammar of graphics well but a piano + roll of this type can be replicated in matplotlib with similar effort — no distinctively + plotnine-only feature (e.g. stat_* transforms, facet_grid, position adjustments) + is leveraged.' + - 'DE-03: The data storytelling through chord labels and dynamic markings is good + but the visual hierarchy between the melody notes (higher pitch, high velocity) + and accompaniment chords (lower pitch, lower velocity) is implicit rather than + visually reinforced — e.g., a subtle size or alpha difference between melody and + bass notes would strengthen the focal point.' image_description: |- Light render (plot-light.png): - Background: Warm off-white #FAF8F1 — correct theme surface - Chrome: Title "piano-roll-midi · python · plotnine · anyplot.ai" bold, ~65% of plot width, clearly readable in dark INK. Axis labels "Pitch" (y) and "Time (beats)" (x) at 10pt in INK, clearly readable. Tick labels C3/G3/C4/G4/C5 and 0/4/8/12/16 at 8pt INK_SOFT, readable. Chord labels (I (C), IV (F), V (G), I (C)) in italic INK_SOFT at top margin — small but readable at full resolution. Dynamic markings (mf, ff, dim., p) in italic INK_MUTED at bottom margin — small but readable. - Data: Alternating white-key (#EDE9DE) and black-key (#D8D4C8) horizontal bands clearly distinguish piano keyboard rows. Note rectangles colored via Imprint imprint_seq (#009E73 green for low velocity -> #4467A3 blue for high velocity) with dark INK borders. Dotted beat lines and solid measure lines provide time structure. Dashed octave boundary lines at C notes. "← climax" annotation in #AE3030 matte red marks peak note at C5. Colorbar "Velocity" legend 60-120 on right side. - Legibility verdict: PASS + Background: Warm off-white #FAF8F1 — correct. The piano roll rows alternate between two subtle warm grays: lighter (#EDE9DE) for white keys and slightly darker (#D8D4C8) for black keys. The contrast between these two shading values is clearly visible and creates the piano-keyboard-style visual structure. + Chrome: Bold title "piano-roll-midi · python · plotnine · anyplot.ai" is readable in dark #1A1A17 ink. Y-axis tick labels (C3, G3, C4, G4, C5) and X-axis tick labels (0, 4, 8, 12, 16) are clearly readable in #4A4A44 (INK_SOFT). X-axis label "Time (beats)" and Y-axis label "Pitch" are readable in #1A1A17. Chord labels (I (C), IV (F), V (G), I (C)) and dynamic markings (mf, ff, dim., p) are visible in muted ink tones. Velocity colorbar labeled "Velocity" with 60/80/100/120 ticks is readable. + Data: Note rectangles rendered from #009E73 (green, low velocity ~60) to #4467A3 (blue, high velocity ~115). The C5 "climax" note at beat 6–7.5 is deep blue (velocity 115), clearly the peak. Bass notes (C3, E3, G3) are rendered in mid-green. Melody notes show the crescendo to climax and subsequent diminuendo. "← climax" annotation in #AE3030 italic marks the peak. Measure lines (solid), beat lines (dotted), octave lines (dashed) provide clear structural grid. + Legibility verdict: PASS — all text readable, correct theme colors throughout. Dark render (plot-dark.png): - Background: Warm near-black #1A1A17 — correct theme surface - Chrome: All chrome tokens correctly flipped to light values. Title in #F0EFE8 (INK dark-theme), clearly readable against dark background. Axis labels in #F0EFE8, readable. Tick labels in #B8B7B0 (INK_SOFT dark-theme), readable. Chord labels and dynamic markings in lighter tones, readable. No dark-on-dark text failure detected. - Data: Data colors (green-to-blue gradient) are identical to light render — Imprint palette positions stay constant across themes as required. Note rectangles clearly visible against dark background. Beat/measure lines visible with adjusted dark-theme colors. HOWEVER: the piano key row alternation (WHITE_KEY_BG=#212120 vs BLACK_KEY_BG=#141413) is barely perceptible over the #1A1A17 background — the black/white key distinction is much weaker than in the light render. - Legibility verdict: PASS (with concern: piano-key row distinction extremely faint in dark mode, spec requires visible alternating shading) + Background: Warm near-black #1A1A17 — correct. Row alternation is present: white-key rows (#272720) are subtly lighter than the background, black-key rows (#0D0D0B) are darker — nearly invisible at #0D0D0B. The piano key distinction is much more subtle in dark mode than light mode. + Chrome: Title in light #F0EFE8 ink — clearly readable. Y-axis and X-axis tick labels in #B8B7B0 — readable. Axis labels "Pitch" and "Time (beats)" in light ink — readable. Chord labels in #B8B7B0 — readable. Dynamic markings in #A8A79F — small but legible. Velocity colorbar readable. No dark-on-dark failures detected. + Data: Note rectangle colors are identical to light render (#009E73 to #4467A3 gradient) — Imprint data colors are theme-independent, confirmed. The "← climax" annotation in #AE3030 is visible against the dark background. Measure and beat grid lines are visible as slightly lighter/darker lines. + Legibility verdict: PASS — all text readable with appropriate light-on-dark chrome. Minor note: black-key row distinction (#0D0D0B vs #1A1A17 background) is barely perceptible in dark mode. criteria_checklist: visual_quality: - score: 26 + score: 29 max: 30 items: - id: VQ-01 @@ -59,82 +67,90 @@ review: score: 7 max: 8 passed: true - comment: Title 12pt, axis labels 10pt, tick labels 8pt all explicit and readable. - Chord labels (3.5mm) and dynamic markings (3.0mm) readable at full canvas - but may be borderline at mobile scale. + comment: 'All font sizes explicitly set (title 12pt, axis labels 10pt, tick + labels 8pt, geom_text annotations 3.5-4mm). All text readable in both themes. + Minor: dynamic markings (INK_MUTED at size=3.5mm) are at the minimum viable + size but still legible.' - id: VQ-02 name: No Overlap - score: 5 + score: 6 max: 6 passed: true - comment: No hard overlaps. Climax annotation (x=7.6, y=73) is tight against - IV(F) chord label (x=6, y=73.8) creating crowded top margin without actual - collision. + comment: No overlapping text or data elements. Chord labels well-separated + at measure midpoints. Dynamic markings well-placed below piano roll. Climax + annotation positioned above C5 note with adequate clearance. - id: VQ-03 name: Element Visibility - score: 5 + score: 6 max: 6 passed: true - comment: 'Note rects well-defined with INK borders. Velocity gradient reads - clearly. Piano key row contrast in dark theme is very faint (#212120 vs - #141413 over #1A1A17).' + comment: Note rectangles clearly visible in both themes with dark border outline. + Varying widths (duration) and colors (velocity) clearly distinguishable. + 35 notes at appropriate scale. - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Imprint sequential cmap (#009E73->#4467A3) is CVD-safe. No red-green - as sole signal. + comment: Velocity colormap green-to-blue (imprint_seq) is CVD-safe (green + and blue distinguish well under deuteranopia/protanopia). No red-green sole + signal. Dark note outlines provide redundant structural encoding. - id: VQ-05 name: Layout & Canvas - score: 3 + score: 4 max: 4 passed: true - comment: 3200x1800 correct. Good overall proportions. Minor crowding in top - margin (chord labels + climax annotation) and bottom margin (dynamic labels - between piano roll and x-ticks). + comment: 3200x1800 landscape. Piano roll fills the canvas well with appropriate + margins. Colorbar legend positioned right. coord_cartesian ensures note + rectangles don't overflow. No clipping detected at any edge. - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Title matches required format exactly. X=Time (beats) with units, - Y=Pitch with note-name tick labels (C3-C5). + comment: Title 'piano-roll-midi · python · plotnine · anyplot.ai' correct + format. X-axis 'Time (beats)' — descriptive with units. Y-axis 'Pitch' with + note names on ticks (C3, G3, C4, G4, C5). All informative. - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'scale_fill_gradient(low=#009E73, high=#4467A3) is exact imprint_seq - cmap. Backgrounds #FAF8F1/#1A1A17. All chrome theme-adaptive.' + comment: 'Continuous velocity data uses imprint_seq (low=#009E73, high=#4467A3) + — correct. Background #FAF8F1 light / #1A1A17 dark — correct. Data colors + identical across both renders. All chrome tokens theme-adaptive. Piano key + shading colors are structural (not data colors) — acceptable.' design_excellence: score: 14 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 5 + score: 6 max: 8 passed: true - comment: 'Well above generic defaults: custom piano-key background rows, differentiated - beat/measure lines, dashed octave boundaries, chord symbols, dynamic markings. - Thoughtful DAW-inspired design.' + comment: 'Strong design clearly above defaults: piano key alternating backgrounds + with theme adaptation, chord progression labels, dynamic markings, climax + annotation in semantic red, three-tier grid hierarchy. Shows genuine domain + expertise and intentional visual design.' - id: DE-02 name: Visual Refinement score: 4 max: 6 passed: true - comment: theme_void() removes superfluous chrome. Background rows replace - panel background meaningfully. Beat/measure visual hierarchy is deliberate. - Legend uses ELEVATED_BG frame. + comment: theme_void() as base removes all default chrome. Three-tier grid + hierarchy (dotted beat lines 0.25, solid measure lines 0.5, dashed octave + lines 0.35) is well-executed visual refinement. Clean colorbar, proper whitespace + (plot_margin=0.02). Above minimal-refinement default. - id: DE-03 name: Data Storytelling - score: 5 + score: 4 max: 6 passed: true - comment: Climax annotation guides viewer to musical high point. Chord progression - labels (I->IV->V->I) frame harmonic arc. Dynamic markings (mf->ff->dim.->p) - narrate intensity curve. Multiple storytelling layers working cohesively. + comment: 'Visual hierarchy: I-IV-V-I chord labels create harmonic narrative. + mf→ff→dim→p dynamic markings tell the intensity arc. Climax annotation with + red color draws the eye to the musical peak. Good storytelling but melody/bass + distinction not visually reinforced (no size/alpha differentiation).' spec_compliance: score: 15 max: 15 @@ -144,29 +160,34 @@ review: score: 5 max: 5 passed: true - comment: 'Correct MIDI piano roll: horizontal rectangles by pitch (y) and - time onset (x), width=duration.' + comment: 'Correct piano roll visualization: horizontal rectangles for notes, + Y=pitch, X=time, width=duration, color=velocity. Piano keyboard row structure + in background.' - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Y-axis note names, alternating key shading, beat+measure grid lines, - velocity sequential colormap, pitch range auto-fit — all present. + comment: 'All required features: note names on Y-axis (C3/G3/C4/G4/C5), alternating + black/white key backgrounds, beat grid (dotted) and measure grid (solid), + velocity colormap (sequential green-to-blue), pitch range auto-fitted with + margin.' - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X=time beats, Y=MIDI pitch as note names, color=velocity, width=duration. - All 4 data dimensions mapped correctly. + comment: X=time in beats, Y=pitch (MIDI numbers 48-72 with note names), color=velocity, + width=duration. All 4 measures (16 beats) visible. Chord progression and + melody fully shown. - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title piano-roll-midi · python · plotnine · anyplot.ai exact match. - Velocity colorbar with 60/80/100/120 breaks. + comment: Title 'piano-roll-midi · python · plotnine · anyplot.ai' matches + required format exactly. Velocity colorbar labeled correctly. Y-axis displays + note names (spec requirement for human-readable pitch labels). data_quality: score: 15 max: 15 @@ -176,23 +197,27 @@ review: score: 6 max: 6 passed: true - comment: 'All piano-roll dimensions: pitch, onset, duration, velocity. Musical - annotation layers demonstrate full use of the format.' + comment: 'Shows all piano roll features: chord voicings (multiple simultaneous + notes), melodic runs (eighth/quarter notes), varying note durations, full + velocity range (60-115), bass + melody register coverage, 4-measure phrase + structure with chord progression.' - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Classic C->F->G->C chord progression with realistic MIDI voice leading, - velocity dynamics (mf->ff->dim.->p), melodic climax at C5. Musically plausible - and content-neutral. + comment: I-IV-V-I chord progression (C→F→G→C) is a canonical Western music + structure. Velocity values (60-115) are realistic for a mf to ff musical + phrase. Note durations (0.5-3.0 beats) are musically plausible. The climax + at measure 2 (ff, C5) is musically authentic. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: 35 notes over 16 beats (4 measures) within 20-200 note / 4-16 measure - spec range. Pitch C3-C5 (MIDI 48-72) is realistic. + comment: MIDI values 48-72 (C3-C5) appropriate range for a 2-octave piano + arrangement. Velocity 60-115 within MIDI range (0-127). 16 beats = 4 measures + in 4/4 time. All values factually correct for MIDI piano roll context. code_quality: score: 10 max: 10 @@ -202,53 +227,64 @@ review: score: 3 max: 3 passed: true - comment: Flat script, no unnecessary functions or classes. + comment: 'Flat script: tokens → data → derived data → plot layers → save. + No functions or classes. Clear organization with comments marking sections.' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: np.random.seed(42) set. + comment: np.random.seed(42) set. Data is fully hardcoded tuples — deterministic + regardless of seed. Fully reproducible. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used, no dead imports detected. + comment: 'All imports from plotnine are used: ggplot, aes, geom_rect, geom_segment, + geom_text, geom_vline, annotate, scale_fill_gradient, scale_x_continuous, + scale_y_continuous, coord_cartesian, labs, guide_colorbar, theme, theme_void, + element_text, element_line, element_rect. numpy, pandas, os all used.' - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Clear readable structure, well-named variables, no fake UI elements. + comment: Pythonic, appropriate complexity for the visualization. No fake interactivity. + List comprehensions for bg_rows and label generation. Multiple DataFrames + for different geom layers is the correct plotnine pattern. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot-{THEME}.png with correct canvas settings (dpi=400, - width=8, height=4.5). + comment: Saves as plot-{THEME}.png using plot.save() with correct dpi=400, + width=8, height=4.5, units='in'. Current plotnine 0.15.5 API. library_mastery: score: 8 max: 10 items: - id: LM-01 name: Idiomatic Usage - score: 4 + score: 5 max: 5 passed: true - comment: Correct grammar-of-graphics layering. Multiple independent dataframes - passed to individual geoms idiomatically. coord_cartesian for precise axis - control is the right plotnine pattern. + comment: 'Expertly uses plotnine''s grammar of graphics: multiple geom layers + on different data frames (bg_df for backgrounds, df for notes, measure_labels, + dynamic_labels, octave_lines), scale functions for both axes and fill, coord_cartesian + for clipping, guide_colorbar for legend, fine-grained theme() customization. + Idiomatic plotnine.' - id: LM-02 name: Distinctive Features - score: 4 + score: 3 max: 5 passed: true - comment: 'Uses plotnine layer composition: geom_rect for both background rows - and note rects (two datasets), geom_vline + geom_segment + geom_text + annotate - in one pipeline. guide_colorbar(nbin=200) for smooth gradient. scale_y_continuous - with fully custom breaks/labels for pitch names.' + comment: 'Uses some plotnine-specific features: multiple data frame layers + in a single ggplot() chain, guide_colorbar() for colorbar customization, + annotate() for text overlays, element_text/element_rect/element_line theme + components. The piano roll structure itself could be replicated in matplotlib + — no uniquely-plotnine statistical transformation (stat_*, position_*, facet_*) + is leveraged.' verdict: APPROVED impl_tags: dependencies: [] @@ -265,4 +301,3 @@ impl_tags: - minimal-chrome - custom-colormap - edge-highlighting - - grid-styling