From ba1af9e4d772404d299645b1cb9efa9e147676bf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:44:24 +0000 Subject: [PATCH 1/5] feat(ggplot2): implement piano-roll-midi --- .../implementations/r/ggplot2.R | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 plots/piano-roll-midi/implementations/r/ggplot2.R diff --git a/plots/piano-roll-midi/implementations/r/ggplot2.R b/plots/piano-roll-midi/implementations/r/ggplot2.R new file mode 100644 index 0000000000..be6c0f3e37 --- /dev/null +++ b/plots/piano-roll-midi/implementations/r/ggplot2.R @@ -0,0 +1,194 @@ +#' anyplot.ai +#' piano-roll-midi: MIDI Piano Roll Visualization +#' Library: ggplot2 | R 4.4 +#' Quality: pending | Created: 2026-06-03 + +library(ggplot2) +library(ragg) + +set.seed(42) + +# Theme tokens (Imprint palette) +THEME <- Sys.getenv("ANYPLOT_THEME", "light") +PAGE_BG <- if (THEME == "light") "#FAF8F1" else "#1A1A17" +ELEVATED_BG <- if (THEME == "light") "#FFFDF6" else "#242420" +INK <- if (THEME == "light") "#1A1A17" else "#F0EFE8" +INK_SOFT <- if (THEME == "light") "#4A4A44" else "#B8B7B0" + +# Imprint sequential colormap for velocity: green (quiet) -> blue (loud) +CMAP_LOW <- "#009E73" # Imprint position 1 — pianissimo +CMAP_HIGH <- "#4467A3" # Imprint position 3 — fortissimo + +# Piano keyboard row background colors +KEY_WHITE <- if (THEME == "light") "#EBE7DC" else "#222220" +KEY_BLACK <- if (THEME == "light") "#D3CDB8" else "#1D1D1B" + +# MIDI note number -> note name with octave (e.g., 60 -> "C4") +midi_to_name <- function(midi) { + note_names <- c("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") + paste0(note_names[(midi %% 12) + 1], floor(midi / 12) - 1) +} + +is_black_key <- function(midi) { + (midi %% 12) %in% c(1L, 3L, 6L, 8L, 10L) +} + +# --- Data: 8-measure C-major piano piece (32 beats, 4/4 time) --------------- + +# Right hand: eighth notes (0.5 beat each), melodic lines building to climax +rh_pitches <- c( + 60, 62, 64, 67, 69, 67, 64, 62, # m1: gentle ascent/descent + 60, 64, 67, 72, 71, 69, 67, 65, # m2: arpeggiated C chord + 64, 67, 69, 72, 74, 72, 69, 67, # m3: E-based run + 65, 67, 69, 72, 71, 72, 69, 67, # m4: F-based figure + 64, 67, 71, 72, 74, 76, 74, 72, # m5: climbing higher + 71, 72, 74, 76, 77, 79, 77, 76, # m6: climax in upper register + 74, 72, 71, 69, 67, 65, 64, 62, # m7: long descent + 60, 62, 64, 65, 64, 62, 60, 60 # m8: quiet resolution to C4 +) +rh_starts <- seq(0, 31.5, by = 0.5) +rh_durations <- rep(0.45, 64L) + +# Velocity arc: mf start -> ff climax (m6) -> p resolution +vel_raw <- c( + seq(55, 70, length.out = 8L), + seq(68, 82, length.out = 8L), + seq(80, 90, length.out = 8L), + seq(88, 95, length.out = 8L), + seq(93, 103, length.out = 8L), + seq(103, 118, length.out = 8L), + seq(112, 85, length.out = 8L), + seq(80, 48, length.out = 8L) +) +rh_vel <- pmin(pmax(round(vel_raw + rnorm(64L, 0, 4)), 30L), 127L) + +# Left hand: bass root on every quarter beat (C-F-Am-G progression, 2 measures each) +bass_pitches <- rep(c(48L, 53L, 57L, 55L), each = 8L) +bass_starts <- 0:31 +bass_dur <- rep(0.85, 32L) +bass_vel <- pmin(pmax(round(seq(62, 72, length.out = 32L) + rnorm(32L, 0, 3)), 30L), 100L) + +notes_df <- data.frame( + start = c(rh_starts, as.numeric(bass_starts)), + end = c(rh_starts + rh_durations, bass_starts + bass_dur), + pitch = c(rh_pitches, bass_pitches), + velocity = c(rh_vel, bass_vel) +) + +# Pitch range with 1-semitone margin +pitch_min <- min(notes_df$pitch) - 1L +pitch_max <- max(notes_df$pitch) + 1L +all_pitches <- seq(pitch_min, pitch_max) + +# Separate background row data by key type +white_rows <- all_pitches[!is_black_key(all_pitches)] +black_rows <- all_pitches[ is_black_key(all_pitches)] + +bg_white <- data.frame( + xmin = 0, xmax = 32, + ymin = white_rows - 0.5, ymax = white_rows + 0.5 +) +bg_black <- data.frame( + xmin = 0, xmax = 32, + ymin = black_rows - 0.5, ymax = black_rows + 0.5 +) + +# Y-axis: label only white keys +y_labels <- sapply(white_rows, midi_to_name) + +# Beat / measure grid positions (beat lines exclude measure boundaries) +beat_xs <- (1:31)[!(1:31 %% 4 == 0)] +measure_xs <- seq(0L, 32L, by = 4L) + +plot_title <- "piano-roll-midi · r · ggplot2 · anyplot.ai" + +# --- Plot ------------------------------------------------------------------- +p <- ggplot() + + # Piano keyboard background: white keys + geom_rect( + data = bg_white, + aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), + fill = KEY_WHITE, color = NA + ) + + # Piano keyboard background: black keys + geom_rect( + data = bg_black, + aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), + fill = KEY_BLACK, color = NA + ) + + # Beat subdivision lines (very faint) + geom_vline( + xintercept = beat_xs, + color = INK_SOFT, linewidth = 0.12, alpha = 0.35 + ) + + # Measure boundary lines (stronger) + geom_vline( + xintercept = measure_xs, + color = INK, linewidth = 0.4, alpha = 0.5 + ) + + # MIDI notes colored by velocity + geom_rect( + data = notes_df, + aes( + xmin = start, xmax = end, + ymin = pitch - 0.42, ymax = pitch + 0.42, + fill = velocity + ), + color = PAGE_BG, linewidth = 0.15 + ) + + # Imprint sequential colormap for velocity (green=quiet, blue=loud) + scale_fill_gradient( + low = CMAP_LOW, + high = CMAP_HIGH, + limits = c(0, 127), + name = "Velocity", + breaks = c(0, 32, 64, 96, 127), + labels = c("pp", "p", "mf", "f", "ff") + ) + + scale_x_continuous( + name = "Measure", + breaks = seq(0, 32, by = 4), + labels = paste0("m", 1:9), + expand = expansion(add = c(0, 0)) + ) + + scale_y_continuous( + name = "Pitch", + breaks = white_rows, + labels = y_labels, + expand = expansion(add = c(0.5, 0.5)) + ) + + labs(title = plot_title) + + theme_minimal(base_size = 8) + + theme( + plot.background = element_rect(fill = PAGE_BG, color = PAGE_BG), + panel.background = element_rect(fill = PAGE_BG, color = NA), + panel.grid.major = element_blank(), + panel.grid.minor = element_blank(), + panel.border = element_rect(color = INK_SOFT, fill = NA, linewidth = 0.35), + axis.title = element_text(color = INK, size = 10), + axis.text = element_text(color = INK_SOFT, size = 8), + axis.text.y = element_text(color = INK_SOFT, size = 7), + plot.title = element_text(color = INK, size = 12, face = "bold"), + legend.background = element_rect(fill = ELEVATED_BG, color = INK_SOFT, linewidth = 0.3), + legend.text = element_text(color = INK_SOFT, size = 8), + legend.title = element_text(color = INK, size = 9), + legend.position = "right", + plot.margin = margin(12, 12, 10, 10) + ) + + guides( + fill = guide_colorbar( + barheight = 12, + barwidth = 0.8 + ) + ) + +# --- Save ------------------------------------------------------------------- +ggsave( + filename = sprintf("plot-%s.png", THEME), + plot = p, + device = ragg::agg_png, + width = 8, + height = 4.5, + units = "in", + dpi = 400 +) From 9086a68baa65bd3e63ae00c308c3a07269cd5a47 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:44:41 +0000 Subject: [PATCH 2/5] chore(ggplot2): add metadata for piano-roll-midi --- plots/piano-roll-midi/metadata/r/ggplot2.yaml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 plots/piano-roll-midi/metadata/r/ggplot2.yaml diff --git a/plots/piano-roll-midi/metadata/r/ggplot2.yaml b/plots/piano-roll-midi/metadata/r/ggplot2.yaml new file mode 100644 index 0000000000..3c5998d870 --- /dev/null +++ b/plots/piano-roll-midi/metadata/r/ggplot2.yaml @@ -0,0 +1,21 @@ +# Per-library metadata for ggplot2 implementation of piano-roll-midi +# Auto-generated by impl-generate.yml + +library: ggplot2 +language: r +specification_id: piano-roll-midi +created: '2026-06-03T03:44:41Z' +updated: '2026-06-03T03:44:41Z' +generated_by: claude-sonnet +workflow_run: 26862063235 +issue: 4565 +language_version: 4.4.1 +library_version: 3.5.1 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/piano-roll-midi/r/ggplot2/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/piano-roll-midi/r/ggplot2/plot-dark.png +preview_html_light: null +preview_html_dark: null +quality_score: null +review: + strengths: [] + weaknesses: [] From d8aec78d05f72671e9ff1d3d099f6f70a5916ce8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:51:16 +0000 Subject: [PATCH 3/5] chore(ggplot2): update quality score 86 and review feedback for piano-roll-midi --- .../implementations/r/ggplot2.R | 4 +- plots/piano-roll-midi/metadata/r/ggplot2.yaml | 256 +++++++++++++++++- 2 files changed, 251 insertions(+), 9 deletions(-) diff --git a/plots/piano-roll-midi/implementations/r/ggplot2.R b/plots/piano-roll-midi/implementations/r/ggplot2.R index be6c0f3e37..a056afb688 100644 --- a/plots/piano-roll-midi/implementations/r/ggplot2.R +++ b/plots/piano-roll-midi/implementations/r/ggplot2.R @@ -1,7 +1,7 @@ #' anyplot.ai #' piano-roll-midi: MIDI Piano Roll Visualization -#' Library: ggplot2 | R 4.4 -#' Quality: pending | Created: 2026-06-03 +#' Library: ggplot2 3.5.1 | R 4.4.1 +#' Quality: 86/100 | Created: 2026-06-03 library(ggplot2) library(ragg) diff --git a/plots/piano-roll-midi/metadata/r/ggplot2.yaml b/plots/piano-roll-midi/metadata/r/ggplot2.yaml index 3c5998d870..70065ed9a7 100644 --- a/plots/piano-roll-midi/metadata/r/ggplot2.yaml +++ b/plots/piano-roll-midi/metadata/r/ggplot2.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for ggplot2 implementation of piano-roll-midi -# Auto-generated by impl-generate.yml - library: ggplot2 language: r specification_id: piano-roll-midi created: '2026-06-03T03:44:41Z' -updated: '2026-06-03T03:44:41Z' +updated: '2026-06-03T03:51:16Z' generated_by: claude-sonnet workflow_run: 26862063235 issue: 4565 @@ -15,7 +12,252 @@ 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/r/ggplot2/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: null +quality_score: 86 review: - strengths: [] - weaknesses: [] + strengths: + - 'Perfect spec compliance: all required piano roll features (keyboard background, + note names, two-weight grid, velocity colormap, auto-fitted pitch range) are present + and correct' + - Musical dynamics labels (pp/p/mf/f/ff) on the velocity colorbar — domain-appropriate + and reader-friendly + - Correct Imprint seq colormap (#009E73→#4467A3) for velocity; both renders are + fully theme-adaptive with no chrome failures + - Rich, realistic musical data with a clear dynamic arc (mf→ff→p) that creates natural + visual hierarchy through color + - Clean idiomatic ggplot2 grammar-of-graphics composition with properly weighted + beat/measure grid lines + weaknesses: + - 'DE-03 below potential: the dynamic climax at m6–m7 is visible in color but not + accented — add a subtle translucent highlight or annotation near the climax measure + to guide the viewer to the dynamic peak' + - Y-axis tick labels at size 7 are at the minimum acceptable threshold; increase + axis.text.y from 7 to 8 for better mobile readability + - Two helper functions (midi_to_name, is_black_key) deviate from strict KISS — could + be inlined as named vectors/logical masks + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct theme surface, not pure white. + Chrome: Title "piano-roll-midi · r · ggplot2 · anyplot.ai" bold in dark ink (#1A1A17), clearly readable. Axis labels "Measure" (x) and "Pitch" (y) in dark ink, size 10. Tick labels (note names G5..B2 on y-axis, m1-m9 on x-axis) in INK_SOFT (#4A4A44), size 7-8. All text readable. + Data: Right-hand melody notes rendered as near-square green-to-teal rectangles (velocity ~55-80, color near #009E73). As velocity increases toward climax (m6), notes shift from teal to blue (#4467A3). Left-hand bass notes (C3, F3, A3, G3 rows) appear as longer teal rectangles. Piano keyboard alternation visible as warm beige rows. + First series / primary data color: #009E73 (brand green) at low velocity end — correct. + Legibility verdict: PASS + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct dark surface, not pure black. + Chrome: Title in near-white (#F0EFE8), clearly readable. Axis labels in #F0EFE8. Tick labels in #B8B7B0 (INK_SOFT dark variant). Legend box has elevated dark background (#242420) with subtle border. All text readable — no dark-on-dark failure. + Data: Identical velocity color gradient (green #009E73 to blue #4467A3) as light render. Only chrome flips between themes. Keyboard row alternation visible in dark gray tones (#222220 vs #1D1D1B). Measure boundary lines visible as faint-white vertical lines. + Legibility verdict: PASS + criteria_checklist: + visual_quality: + score: 28 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All font sizes explicitly set (title=12, axis.title=10, axis.text=8, + axis.text.y=7); well-proportioned. Y-axis at size 7 is minimum acceptable + — may be small at mobile widths. + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping text or data elements in either render. + - id: VQ-03 + name: Element Visibility + score: 5 + max: 6 + passed: true + comment: Notes clearly visible; right-hand melody notes are near-square (0.45 + beat duration) rather than clearly horizontal — realistic for eighth notes + but reduces the characteristic piano-roll rectangle feel. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Imprint seq colormap (green→blue) is CVD-safe; keyboard row contrast + adequate. + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Plot fills canvas well with balanced margins; legend well-positioned; + no content cut off. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Measure and Pitch are descriptive for the domain. + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Velocity uses imprint_seq (CMAP_LOW=#009E73, CMAP_HIGH=#4467A3); + backgrounds are #FAF8F1 (light) / #1A1A17 (dark); chrome is theme-correct + in both renders.' + design_excellence: + score: 12 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: 'Above generic defaults: piano keyboard background alternation, musical + dynamics labels (pp/p/mf/f/ff), clean velocity gradient. Not quite publication-ready + — no focal-point emphasis at dynamic climax.' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: Grid removed and replaced with two-weight beat/measure lines; legend + styled with elevated background; note rectangles have thin PAGE_BG borders. + All four panel borders retained appropriately for enclosed piano roll grid. + - id: DE-03 + name: Data Storytelling + score: 3 + max: 6 + passed: true + comment: Velocity arc (mf→ff→p) visible in color gradient; melodic ascent/descent + spatially clear. Above default of 2 but no annotation or visual accent guides + viewer to the climax. + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correct piano roll / DAW-style visualization with all required structural + elements. + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Note names on Y-axis, black/white key background alternation, beat+measure + grid lines with two visual weights, sequential velocity colormap, pitch + range auto-fitted with 1-semitone margin — all present. + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X=start time in beats, Y=pitch (MIDI→note names), width=duration, + fill=velocity — all correctly mapped. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title 'piano-roll-midi · r · ggplot2 · anyplot.ai' exactly correct. + Velocity colorbar with pp/p/mf/f/ff labels is domain-correct. + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: Right-hand melody + left-hand bass, varying durations (0.45 vs 0.85 + beats), dynamic arc (mf→ff→p), 3+ octave range, 96 total notes covering + all aspects of the piano roll format. + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: 8-measure C-major piano piece with C-F-Am-G bass progression; realistic + MIDI pitch numbers and velocity values. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: MIDI pitches 48-79 (C3-G5, sensible piano range); velocities 30-127 + (realistic dynamic arc); 32 beats / 4/4 time. All proportions factually + correct. + code_quality: + score: 9 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 2 + max: 3 + passed: true + comment: Two small helper functions (midi_to_name, is_black_key) deviate from + strict no-functions pattern; both are compact (2-3 lines) and justified + for this plot type. + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: set.seed(42) present. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: Only ggplot2 and ragg imported, both used. + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean, idiomatic R; no over-engineering; no fake functionality. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves as plot-${THEME}.png via ragg; correct API usage. + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: 'Grammar-of-graphics layer composition is idiomatic: multiple geom_rect() + layers with separate data frames, scale_fill_gradient(), explicit breaks/labels, + guides(fill=guide_colorbar()). Very clean ggplot2 usage.' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses ggplot2's layered grammar to compose background rects + vlines + + note rects from different data sources in a single plot — a distinctive + ggplot2 strength. + verdict: REJECTED +impl_tags: + dependencies: [] + techniques: + - colorbar + - layer-composition + - manual-ticks + patterns: + - data-generation + dataprep: [] + styling: + - custom-colormap + - edge-highlighting + - alpha-blending + - grid-styling From 4abb29fda55f1711e40330dafa91d3e29131d4f6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 03:56:43 +0000 Subject: [PATCH 4/5] fix(ggplot2): address review feedback for piano-roll-midi Attempt 1/3 - fixes based on AI review --- .../implementations/r/ggplot2.R | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/plots/piano-roll-midi/implementations/r/ggplot2.R b/plots/piano-roll-midi/implementations/r/ggplot2.R index a056afb688..e75ecda839 100644 --- a/plots/piano-roll-midi/implementations/r/ggplot2.R +++ b/plots/piano-roll-midi/implementations/r/ggplot2.R @@ -1,7 +1,6 @@ #' anyplot.ai #' piano-roll-midi: MIDI Piano Roll Visualization #' Library: ggplot2 3.5.1 | R 4.4.1 -#' Quality: 86/100 | Created: 2026-06-03 library(ggplot2) library(ragg) @@ -16,22 +15,15 @@ INK <- if (THEME == "light") "#1A1A17" else "#F0EFE8" INK_SOFT <- if (THEME == "light") "#4A4A44" else "#B8B7B0" # Imprint sequential colormap for velocity: green (quiet) -> blue (loud) -CMAP_LOW <- "#009E73" # Imprint position 1 — pianissimo -CMAP_HIGH <- "#4467A3" # Imprint position 3 — fortissimo +CMAP_LOW <- "#009E73" +CMAP_HIGH <- "#4467A3" # Piano keyboard row background colors KEY_WHITE <- if (THEME == "light") "#EBE7DC" else "#222220" KEY_BLACK <- if (THEME == "light") "#D3CDB8" else "#1D1D1B" -# MIDI note number -> note name with octave (e.g., 60 -> "C4") -midi_to_name <- function(midi) { - note_names <- c("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") - paste0(note_names[(midi %% 12) + 1], floor(midi / 12) - 1) -} - -is_black_key <- function(midi) { - (midi %% 12) %in% c(1L, 3L, 6L, 8L, 10L) -} +NOTE_NAMES <- c("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") +BLACK_KEYS <- c(1L, 3L, 6L, 8L, 10L) # --- Data: 8-measure C-major piano piece (32 beats, 4/4 time) --------------- @@ -81,25 +73,22 @@ pitch_max <- max(notes_df$pitch) + 1L all_pitches <- seq(pitch_min, pitch_max) # Separate background row data by key type -white_rows <- all_pitches[!is_black_key(all_pitches)] -black_rows <- all_pitches[ is_black_key(all_pitches)] +white_rows <- all_pitches[!(all_pitches %% 12 %in% BLACK_KEYS)] +black_rows <- all_pitches[ all_pitches %% 12 %in% BLACK_KEYS] -bg_white <- data.frame( - xmin = 0, xmax = 32, - ymin = white_rows - 0.5, ymax = white_rows + 0.5 -) -bg_black <- data.frame( - xmin = 0, xmax = 32, - ymin = black_rows - 0.5, ymax = black_rows + 0.5 -) +bg_white <- data.frame(xmin = 0, xmax = 32, ymin = white_rows - 0.5, ymax = white_rows + 0.5) +bg_black <- data.frame(xmin = 0, xmax = 32, ymin = black_rows - 0.5, ymax = black_rows + 0.5) # Y-axis: label only white keys -y_labels <- sapply(white_rows, midi_to_name) +y_labels <- paste0(NOTE_NAMES[(white_rows %% 12) + 1], floor(white_rows / 12) - 1) # Beat / measure grid positions (beat lines exclude measure boundaries) beat_xs <- (1:31)[!(1:31 %% 4 == 0)] measure_xs <- seq(0L, 32L, by = 4L) +# Climax highlight: measure 6 (beats 20-24) is the dynamic peak (ff) +climax_df <- data.frame(xmin = 20, xmax = 24, ymin = pitch_min - 0.5, ymax = pitch_max + 0.5) + plot_title <- "piano-roll-midi · r · ggplot2 · anyplot.ai" # --- Plot ------------------------------------------------------------------- @@ -116,6 +105,12 @@ p <- ggplot() + aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), fill = KEY_BLACK, color = NA ) + + # Subtle translucent highlight at dynamic climax (m6, beats 20-24) + geom_rect( + data = climax_df, + aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), + fill = CMAP_HIGH, color = NA, alpha = 0.10 + ) + # Beat subdivision lines (very faint) geom_vline( xintercept = beat_xs, @@ -136,6 +131,11 @@ p <- ggplot() + ), color = PAGE_BG, linewidth = 0.15 ) + + # "ff" annotation marking the dynamic peak + annotate( + "text", x = 22, y = pitch_max - 0.3, + label = "ff", color = INK, size = 2.5, fontface = "bold.italic" + ) + # Imprint sequential colormap for velocity (green=quiet, blue=loud) scale_fill_gradient( low = CMAP_LOW, @@ -167,7 +167,7 @@ p <- ggplot() + panel.border = element_rect(color = INK_SOFT, fill = NA, linewidth = 0.35), axis.title = element_text(color = INK, size = 10), axis.text = element_text(color = INK_SOFT, size = 8), - axis.text.y = element_text(color = INK_SOFT, size = 7), + axis.text.y = element_text(color = INK_SOFT, size = 8), plot.title = element_text(color = INK, size = 12, face = "bold"), legend.background = element_rect(fill = ELEVATED_BG, color = INK_SOFT, linewidth = 0.3), legend.text = element_text(color = INK_SOFT, size = 8), From 425938e4e78d728d96a9929b01a71f9c4401fe91 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 3 Jun 2026 04:01:51 +0000 Subject: [PATCH 5/5] chore(ggplot2): update quality score 89 and review feedback for piano-roll-midi --- .../implementations/r/ggplot2.R | 1 + plots/piano-roll-midi/metadata/r/ggplot2.yaml | 161 ++++++++---------- 2 files changed, 70 insertions(+), 92 deletions(-) diff --git a/plots/piano-roll-midi/implementations/r/ggplot2.R b/plots/piano-roll-midi/implementations/r/ggplot2.R index e75ecda839..8ce58d6f3a 100644 --- a/plots/piano-roll-midi/implementations/r/ggplot2.R +++ b/plots/piano-roll-midi/implementations/r/ggplot2.R @@ -1,6 +1,7 @@ #' anyplot.ai #' piano-roll-midi: MIDI Piano Roll Visualization #' Library: ggplot2 3.5.1 | R 4.4.1 +#' Quality: 89/100 | Created: 2026-06-03 library(ggplot2) library(ragg) diff --git a/plots/piano-roll-midi/metadata/r/ggplot2.yaml b/plots/piano-roll-midi/metadata/r/ggplot2.yaml index 70065ed9a7..66fbbee30e 100644 --- a/plots/piano-roll-midi/metadata/r/ggplot2.yaml +++ b/plots/piano-roll-midi/metadata/r/ggplot2.yaml @@ -2,7 +2,7 @@ library: ggplot2 language: r specification_id: piano-roll-midi created: '2026-06-03T03:44:41Z' -updated: '2026-06-03T03:51:16Z' +updated: '2026-06-03T04:01:51Z' generated_by: claude-sonnet workflow_run: 26862063235 issue: 4565 @@ -12,41 +12,38 @@ 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/r/ggplot2/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: 86 +quality_score: 89 review: strengths: - - 'Perfect spec compliance: all required piano roll features (keyboard background, - note names, two-weight grid, velocity colormap, auto-fitted pitch range) are present - and correct' - - Musical dynamics labels (pp/p/mf/f/ff) on the velocity colorbar — domain-appropriate - and reader-friendly - - Correct Imprint seq colormap (#009E73→#4467A3) for velocity; both renders are - fully theme-adaptive with no chrome failures - - Rich, realistic musical data with a clear dynamic arc (mf→ff→p) that creates natural - visual hierarchy through color - - Clean idiomatic ggplot2 grammar-of-graphics composition with properly weighted - beat/measure grid lines + - 'Perfect spec compliance: all four required features (note names, black/white + key rows, beat+measure grid differentiation, velocity colormap) correctly implemented' + - Musically authentic data with realistic C-major progression, proper MIDI note + numbers, and convincing dynamic arc (mf→ff climax→p resolution) + - 'Effective storytelling: climax highlight overlay + ff annotation create a clear + narrative focal point' + - Correct Imprint sequential palette (green→blue) for continuous velocity data; + full theme-adaptive chrome with no dark-on-dark or light-on-light failures weaknesses: - - 'DE-03 below potential: the dynamic climax at m6–m7 is visible in color but not - accented — add a subtle translucent highlight or annotation near the climax measure - to guide the viewer to the dynamic peak' - - Y-axis tick labels at size 7 are at the minimum acceptable threshold; increase - axis.text.y from 7 to 8 for better mobile readability - - Two helper functions (midi_to_name, is_black_key) deviate from strict KISS — could - be inlined as named vectors/logical masks + - 'Piano keyboard row contrast is low in both themes (light: #EBE7DC vs #D3CDB8; + dark: #222220 vs #1D1D1B) — spec asks for white and dark alternation but rows + look nearly identical; increase contrast (e.g., light theme KEY_BLACK → #C8C2AE) + for better piano keyboard readability' + - ff annotation at size=2.5 (~7pt on 3200×1800 canvas) is small — bump to size=3.5–4 + for better catalog-scale visibility + - Beat subdivision lines (alpha=0.35, linewidth=0.12) may be imperceptible on some + displays — raise alpha to 0.5 or linewidth to 0.18 image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct theme surface, not pure white. - Chrome: Title "piano-roll-midi · r · ggplot2 · anyplot.ai" bold in dark ink (#1A1A17), clearly readable. Axis labels "Measure" (x) and "Pitch" (y) in dark ink, size 10. Tick labels (note names G5..B2 on y-axis, m1-m9 on x-axis) in INK_SOFT (#4A4A44), size 7-8. All text readable. - Data: Right-hand melody notes rendered as near-square green-to-teal rectangles (velocity ~55-80, color near #009E73). As velocity increases toward climax (m6), notes shift from teal to blue (#4467A3). Left-hand bass notes (C3, F3, A3, G3 rows) appear as longer teal rectangles. Piano keyboard alternation visible as warm beige rows. - First series / primary data color: #009E73 (brand green) at low velocity end — correct. - Legibility verdict: PASS + Background: Warm off-white #FAF8F1 — correct light surface. + Chrome: Title "piano-roll-midi · r · ggplot2 · anyplot.ai" in bold dark ink, clearly readable. Y-axis label "Pitch" and X-axis label "Measure" in dark ink at 10pt. Tick labels (note names C3–G5 on Y; m1–m9 on X) in INK_SOFT at 8pt — all readable. Legend "Velocity" title and pp/p/mf/f/ff labels visible. + Data: MIDI note rectangles colored on Imprint sequential (green #009E73 for low velocity → blue #4467A3 for high velocity). Alternating beige row shading (white keys #EBE7DC, black keys #D3CDB8 — subtle contrast). Beat lines faint (alpha=0.35), measure boundaries darker. Climax overlay (m6) in translucent blue. "ff" annotation at peak. + Legibility verdict: PASS — all text readable, no light-on-light issues. Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct dark surface, not pure black. - Chrome: Title in near-white (#F0EFE8), clearly readable. Axis labels in #F0EFE8. Tick labels in #B8B7B0 (INK_SOFT dark variant). Legend box has elevated dark background (#242420) with subtle border. All text readable — no dark-on-dark failure. - Data: Identical velocity color gradient (green #009E73 to blue #4467A3) as light render. Only chrome flips between themes. Keyboard row alternation visible in dark gray tones (#222220 vs #1D1D1B). Measure boundary lines visible as faint-white vertical lines. - Legibility verdict: PASS + Background: Warm near-black #1A1A17 — correct dark surface. + Chrome: Title and axis labels render in light ink (#F0EFE8), tick labels in #B8B7B0 — fully readable against dark background. Legend text readable. No dark-on-dark failures detected. + Data: MIDI note colors IDENTICAL to light render — Imprint sequential green→blue unchanged. Row alternation visible but very subtle in dark theme (#222220 vs #1D1D1B). "ff" annotation legible in dark context. + Legibility verdict: PASS — all text readable in dark theme, no dark-on-dark issues. criteria_checklist: visual_quality: score: 28 @@ -57,79 +54,71 @@ review: score: 7 max: 8 passed: true - comment: All font sizes explicitly set (title=12, axis.title=10, axis.text=8, - axis.text.y=7); well-proportioned. Y-axis at size 7 is minimum acceptable - — may be small at mobile widths. + comment: All text at correct style-guide sizes; ff annotation at size=2.5 + (~7pt) is slightly small for canvas - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping text or data elements in either render. + comment: No text or element collisions - id: VQ-03 name: Element Visibility score: 5 max: 6 passed: true - comment: Notes clearly visible; right-hand melody notes are near-square (0.45 - beat duration) rather than clearly horizontal — realistic for eighth notes - but reduces the characteristic piano-roll rectangle feel. + comment: Note rectangles clearly visible; beat lines intentionally faint (alpha=0.35) + may be imperceptible - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Imprint seq colormap (green→blue) is CVD-safe; keyboard row contrast - adequate. + comment: Imprint sequential (green→blue) is CVD-safe - id: VQ-05 name: Layout & Canvas score: 4 max: 4 passed: true - comment: Plot fills canvas well with balanced margins; legend well-positioned; - no content cut off. + comment: 3200x1800 canvas confirmed, generous margins, legend well-placed - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: Measure and Pitch are descriptive for the domain. + comment: Pitch with note names, Measure with m1-m9, correct title format - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'Velocity uses imprint_seq (CMAP_LOW=#009E73, CMAP_HIGH=#4467A3); - backgrounds are #FAF8F1 (light) / #1A1A17 (dark); chrome is theme-correct - in both renders.' + comment: imprint_seq (green→blue) for velocity; correct backgrounds; identical + data colors across themes design_excellence: - score: 12 + score: 14 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 5 + score: 6 max: 8 passed: true - comment: 'Above generic defaults: piano keyboard background alternation, musical - dynamics labels (pp/p/mf/f/ff), clean velocity gradient. Not quite publication-ready - — no focal-point emphasis at dynamic climax.' + comment: Domain-specific piano key row shading, dynamic labels on colorbar, + climax highlight overlay show clear design intent - id: DE-02 name: Visual Refinement score: 4 max: 6 passed: true - comment: Grid removed and replaced with two-weight beat/measure lines; legend - styled with elevated background; note rectangles have thin PAGE_BG borders. - All four panel borders retained appropriately for enclosed piano roll grid. + comment: Custom beat/measure lines replace default grid; elevated legend; + piano row alternation — but row contrast is subtle - id: DE-03 name: Data Storytelling - score: 3 + score: 4 max: 6 passed: true - comment: Velocity arc (mf→ff→p) visible in color gradient; melodic ascent/descent - spatially clear. Above default of 2 but no annotation or visual accent guides - viewer to the climax. + comment: Velocity arc narrated by color; climax highlight and ff annotation + create clear focal point spec_compliance: score: 15 max: 15 @@ -139,30 +128,26 @@ review: score: 5 max: 5 passed: true - comment: Correct piano roll / DAW-style visualization with all required structural - elements. + comment: 'Correct piano roll: horizontal rectangles at pitch x time' - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Note names on Y-axis, black/white key background alternation, beat+measure - grid lines with two visual weights, sequential velocity colormap, pitch - range auto-fitted with 1-semitone margin — all present. + comment: Note names on Y-axis, black/white key rows, beat+measure grid differentiation, + sequential velocity colormap - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X=start time in beats, Y=pitch (MIDI→note names), width=duration, - fill=velocity — all correctly mapped. + comment: X=time, Y=pitch, fill=velocity — all correct - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title 'piano-roll-midi · r · ggplot2 · anyplot.ai' exactly correct. - Velocity colorbar with pp/p/mf/f/ff labels is domain-correct. + comment: Correct title format; velocity colorbar with pp/p/mf/f/ff labels data_quality: score: 15 max: 15 @@ -172,60 +157,55 @@ review: score: 6 max: 6 passed: true - comment: Right-hand melody + left-hand bass, varying durations (0.45 vs 0.85 - beats), dynamic arc (mf→ff→p), 3+ octave range, 96 total notes covering - all aspects of the piano roll format. + comment: Onset, duration, pitch, velocity; right-hand melody + left-hand bass; + full dynamic arc - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: 8-measure C-major piano piece with C-F-Am-G bass progression; realistic - MIDI pitch numbers and velocity values. + comment: Authentic C-major piano piece; C-F-Am-G progression; realistic MIDI + velocity progression - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: MIDI pitches 48-79 (C3-G5, sensible piano range); velocities 30-127 - (realistic dynamic arc); 32 beats / 4/4 time. All proportions factually - correct. + comment: 96 notes in 20-200 range; pitch C3-G5 appropriate; velocity 30-127 code_quality: - score: 9 + score: 10 max: 10 items: - id: CQ-01 name: KISS Structure - score: 2 + score: 3 max: 3 passed: true - comment: Two small helper functions (midi_to_name, is_black_key) deviate from - strict no-functions pattern; both are compact (2-3 lines) and justified - for this plot type. + comment: Flat script, no functions or classes - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: set.seed(42) present. + comment: set.seed(42) present - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: Only ggplot2 and ragg imported, both used. + comment: Only ggplot2 and ragg imported, both used - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Clean, idiomatic R; no over-engineering; no fake functionality. + comment: Clean layered grammar, no fake interactivity - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves as plot-${THEME}.png via ragg; correct API usage. + comment: Saves as plot-{THEME}.png via ragg::agg_png at 3200x1800 library_mastery: score: 7 max: 10 @@ -235,29 +215,26 @@ review: score: 4 max: 5 passed: true - comment: 'Grammar-of-graphics layer composition is idiomatic: multiple geom_rect() - layers with separate data frames, scale_fill_gradient(), explicit breaks/labels, - guides(fill=guide_colorbar()). Very clean ggplot2 usage.' + comment: Multiple geom layers, scale_fill_gradient, guide_colorbar, expansion() + — idiomatic ggplot2 grammar - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: Uses ggplot2's layered grammar to compose background rects + vlines - + note rects from different data sources in a single plot — a distinctive - ggplot2 strength. - verdict: REJECTED + comment: Good layered composition but no especially distinctive ggplot2 features + beyond standard geoms + verdict: APPROVED impl_tags: dependencies: [] techniques: - colorbar + - annotations - layer-composition - - manual-ticks patterns: - data-generation dataprep: [] styling: - custom-colormap - - edge-highlighting - alpha-blending - - grid-styling + - edge-highlighting