From 2e49cbe6498067dc8778ad0946d9778605181994 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Jun 2026 09:45:47 +0000 Subject: [PATCH 1/3] feat(ggplot2): implement line-stress-strain --- .../implementations/r/ggplot2.R | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 plots/line-stress-strain/implementations/r/ggplot2.R diff --git a/plots/line-stress-strain/implementations/r/ggplot2.R b/plots/line-stress-strain/implementations/r/ggplot2.R new file mode 100644 index 0000000000..647edc58b1 --- /dev/null +++ b/plots/line-stress-strain/implementations/r/ggplot2.R @@ -0,0 +1,275 @@ +#' anyplot.ai +#' line-stress-strain: Engineering Stress-Strain Curve +#' Library: ggplot2 | R 4.4 +#' Quality: pending | Created: 2026-06-21 + +library(ggplot2) +library(dplyr) +library(ragg) + +set.seed(42) + +# Theme tokens +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" +INK_MUTED <- if (THEME == "light") "#6B6A63" else "#A8A79F" + +IMPRINT_PALETTE <- c( + "#009E73", # 1 — brand green (first series) + "#C475FD", # 2 — lavender + "#4467A3", # 3 — blue + "#BD8233", # 4 — ochre + "#AE3030", # 5 — matte red + "#2ABCCD", # 6 — cyan + "#954477", # 7 — rose + "#99B314" # 8 — lime +) + +GRID_COLOR <- adjustcolor(INK, alpha.f = 0.12) + +# --- Mild Steel (AISI 1020): elastic + Luders plateau + hardening + necking --- +E_steel <- 200000 # Young's modulus (MPa) +eps_y_steel <- 0.00125 # upper yield strain +sig_y_upper <- 250 # upper yield strength (MPa) +sig_y_lower <- 228 # lower yield / Luders plateau (MPa) +eps_plateau <- 0.016 # end of Luders plateau +sig_uts_steel <- 410 # ultimate tensile strength (MPa) +eps_uts_steel <- 0.200 # strain at UTS +sig_frac_steel <- 355 # engineering stress at fracture (MPa) +eps_frac_steel <- 0.350 # fracture strain + +t_e <- seq(0, 1, length.out = 40) +eps_e1 <- t_e * eps_y_steel +sig_e1 <- E_steel * eps_e1 + +t_p <- seq(0, 1, length.out = 70) +eps_p1 <- eps_y_steel + t_p * (eps_plateau - eps_y_steel) +sig_p1 <- sig_y_upper + (sig_y_lower - sig_y_upper) * (1 - exp(-12 * t_p)) / (1 - exp(-12)) + +t_h <- seq(0, 1, length.out = 130) +eps_h1 <- eps_plateau + t_h * (eps_uts_steel - eps_plateau) +sig_h1 <- sig_y_lower + (sig_uts_steel - sig_y_lower) * t_h^0.40 + +t_n <- seq(0, 1, length.out = 80) +eps_n1 <- eps_uts_steel + t_n * (eps_frac_steel - eps_uts_steel) +sig_n1 <- sig_uts_steel - (sig_uts_steel - sig_frac_steel) * t_n^0.35 + +steel <- data.frame( + strain = c(eps_e1, eps_p1, eps_h1, eps_n1), + stress_mpa = c(sig_e1, sig_p1, sig_h1, sig_n1), + material = "Mild Steel (AISI 1020)" +) + +# --- Aluminum 6061-T6: smooth curve, 0.2% offset yield --- +E_al <- 69000 # Young's modulus (MPa) +sig_02 <- 276 # 0.2% offset yield strength (MPa) +eps_el_al <- sig_02 / E_al # elastic limit strain ~0.004 +eps_02_al <- eps_el_al + 0.002 # yield strain via 0.2% offset ~0.006 +sig_uts_al <- 310 +eps_uts_al <- 0.12 +sig_frac_al <- 285 +eps_frac_al <- 0.17 + +eps_al <- seq(0, eps_frac_al, length.out = 250) +sig_al <- ifelse( + eps_al <= eps_el_al, + E_al * eps_al, + pmin( + sig_02 + (sig_uts_al - sig_02) * + ((eps_al - eps_el_al) / (eps_uts_al - eps_el_al))^0.38, + sig_uts_al + ) +) +is_neck_al <- eps_al > eps_uts_al +sig_al[is_neck_al] <- sig_uts_al - (sig_uts_al - sig_frac_al) * + ((eps_al[is_neck_al] - eps_uts_al) / (eps_frac_al - eps_uts_al))^0.55 + +alum <- data.frame( + strain = eps_al, + stress_mpa = pmax(0, sig_al), + material = "Aluminum 6061-T6" +) + +# Combined +df <- rbind(steel, alum) +df$material <- factor(df$material, + levels = c("Mild Steel (AISI 1020)", "Aluminum 6061-T6")) + +# --- 0.2% offset line for aluminum --- +offset_df <- data.frame( + strain = c(0.002, eps_02_al), + stress_mpa = E_al * c(0.002 - 0.002, eps_02_al - 0.002) +) + +# --- Critical points (yield, UTS, fracture for both materials) --- +crit <- data.frame( + strain = c( + eps_y_steel, eps_uts_steel, eps_frac_steel, + eps_02_al, eps_uts_al, eps_frac_al + ), + stress_mpa = c( + sig_y_upper, sig_uts_steel, sig_frac_steel, + sig_02, sig_uts_al, sig_frac_al + ), + material = factor( + c( + "Mild Steel (AISI 1020)", "Mild Steel (AISI 1020)", "Mild Steel (AISI 1020)", + "Aluminum 6061-T6", "Aluminum 6061-T6", "Aluminum 6061-T6" + ), + levels = c("Mild Steel (AISI 1020)", "Aluminum 6061-T6") + ) +) + +plot_title <- "line-stress-strain · r · ggplot2 · anyplot.ai" + +# --- Plot --- +p <- ggplot(df, aes(x = strain, y = stress_mpa, color = material)) + + geom_line(linewidth = 1.2) + + # 0.2% offset dashed line (aluminum) + geom_line( + data = offset_df, + aes(x = strain, y = stress_mpa), + color = INK_SOFT, + linetype = "dashed", + linewidth = 0.8, + inherit.aes = FALSE + ) + + # Critical points + geom_point( + data = crit, + aes(x = strain, y = stress_mpa, color = material), + size = 3.5, + shape = 21, + fill = PAGE_BG, + stroke = 1.5, + inherit.aes = FALSE + ) + + scale_color_manual( + values = c( + "Mild Steel (AISI 1020)" = IMPRINT_PALETTE[1], + "Aluminum 6061-T6" = IMPRINT_PALETTE[2] + ) + ) + + # Region boundary vertical guidelines + annotate("segment", + x = eps_plateau, xend = eps_plateau, y = 0, yend = 440, + color = INK_MUTED, linetype = "dotted", linewidth = 0.5 + ) + + annotate("segment", + x = eps_uts_steel, xend = eps_uts_steel, y = 0, yend = 440, + color = INK_MUTED, linetype = "dotted", linewidth = 0.5 + ) + + # Region labels + annotate("text", + x = (0 + eps_plateau) / 2, y = 448, + label = "Elastic", + color = INK_MUTED, size = 3.2, fontface = "italic", hjust = 0.5 + ) + + annotate("text", + x = (eps_plateau + eps_uts_steel) / 2, y = 448, + label = "Strain Hardening", + color = INK_MUTED, size = 3.2, fontface = "italic", hjust = 0.5 + ) + + annotate("text", + x = (eps_uts_steel + eps_frac_steel) / 2, y = 448, + label = "Necking", + color = INK_MUTED, size = 3.2, fontface = "italic", hjust = 0.5 + ) + + # Young's modulus slope indicator (steel, elastic region) + annotate("segment", + x = 0, xend = 0.00100, y = 0, yend = 200, + color = INK_MUTED, linewidth = 1.6 + ) + + annotate("text", + x = 0.00110, y = 108, + label = "E = 200 GPa", color = INK_MUTED, + size = 2.9, fontface = "italic", hjust = 0 + ) + + # Steel critical point labels + annotate("text", + x = eps_y_steel + 0.004, y = sig_y_upper + 16, + label = "YS = 250 MPa", color = IMPRINT_PALETTE[1], + size = 3.0, hjust = 0 + ) + + annotate("text", + x = eps_uts_steel - 0.002, y = sig_uts_steel + 16, + label = "UTS = 410 MPa", color = IMPRINT_PALETTE[1], + size = 3.0, hjust = 1 + ) + + annotate("text", + x = eps_frac_steel - 0.002, y = sig_frac_steel - 26, + label = "Fracture", color = IMPRINT_PALETTE[1], + size = 3.0, hjust = 1 + ) + + # Aluminum: 0.2% offset label + critical point labels + annotate("text", + x = 0.0030, y = 16, + label = "0.2% offset line", color = INK_SOFT, + size = 2.8, fontface = "italic", hjust = 0 + ) + + annotate("text", + x = eps_02_al + 0.004, y = sig_02 - 22, + label = "0.2% YS = 276 MPa", color = IMPRINT_PALETTE[2], + size = 3.0, hjust = 0 + ) + + annotate("text", + x = eps_uts_al + 0.003, y = sig_uts_al + 16, + label = "UTS = 310 MPa", color = IMPRINT_PALETTE[2], + size = 3.0, hjust = 0 + ) + + annotate("text", + x = eps_frac_al - 0.002, y = sig_frac_al - 26, + label = "Fracture", color = IMPRINT_PALETTE[2], + size = 3.0, hjust = 1 + ) + + labs( + title = plot_title, + x = "Engineering Strain (mm/mm)", + y = "Engineering Stress (MPa)", + color = "Material" + ) + + scale_x_continuous( + limits = c(0, 0.37), + expand = expansion(mult = c(0.01, 0.02)) + ) + + scale_y_continuous( + limits = c(0, 460), + expand = expansion(mult = c(0.01, 0.02)) + ) + + 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_line(color = GRID_COLOR, linewidth = 0.3), + panel.grid.minor = element_blank(), + panel.border = element_blank(), + axis.line = element_line(color = INK_SOFT, linewidth = 0.5), + axis.ticks = element_line(color = INK_SOFT, linewidth = 0.4), + axis.title = element_text(color = INK, size = 10), + axis.text = element_text(color = INK_SOFT, size = 8), + plot.title = element_text(color = INK, size = 12, face = "bold", + margin = margin(b = 8)), + plot.margin = margin(t = 12, r = 16, b = 10, l = 10), + 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 = "inside", + legend.position.inside = c(0.80, 0.22), + legend.key.height = unit(1.0, "lines"), + legend.margin = margin(4, 8, 4, 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 36264f1b7d92ffb451b6e62c6750b5385e33f69f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Jun 2026 09:46:02 +0000 Subject: [PATCH 2/3] chore(ggplot2): add metadata for line-stress-strain --- .../metadata/r/ggplot2.yaml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 plots/line-stress-strain/metadata/r/ggplot2.yaml diff --git a/plots/line-stress-strain/metadata/r/ggplot2.yaml b/plots/line-stress-strain/metadata/r/ggplot2.yaml new file mode 100644 index 0000000000..9dad0b6962 --- /dev/null +++ b/plots/line-stress-strain/metadata/r/ggplot2.yaml @@ -0,0 +1,21 @@ +# Per-library metadata for ggplot2 implementation of line-stress-strain +# Auto-generated by impl-generate.yml + +library: ggplot2 +language: r +specification_id: line-stress-strain +created: '2026-06-21T09:46:01Z' +updated: '2026-06-21T09:46:01Z' +generated_by: claude-sonnet +workflow_run: 27900282175 +issue: 4413 +language_version: 4.4.1 +library_version: 3.5.1 +preview_url_light: https://storage.googleapis.com/anyplot-images/plots/line-stress-strain/r/ggplot2/plot-light.png +preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/line-stress-strain/r/ggplot2/plot-dark.png +preview_html_light: null +preview_html_dark: null +quality_score: null +review: + strengths: [] + weaknesses: [] From b9595a46ca8aa4121d5e5b9ef714967f290cd8b0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Jun 2026 09:53:19 +0000 Subject: [PATCH 3/3] chore(ggplot2): update quality score 86 and review feedback for line-stress-strain --- .../implementations/r/ggplot2.R | 4 +- .../metadata/r/ggplot2.yaml | 244 +++++++++++++++++- 2 files changed, 239 insertions(+), 9 deletions(-) diff --git a/plots/line-stress-strain/implementations/r/ggplot2.R b/plots/line-stress-strain/implementations/r/ggplot2.R index 647edc58b1..84d65abfef 100644 --- a/plots/line-stress-strain/implementations/r/ggplot2.R +++ b/plots/line-stress-strain/implementations/r/ggplot2.R @@ -1,7 +1,7 @@ #' anyplot.ai #' line-stress-strain: Engineering Stress-Strain Curve -#' Library: ggplot2 | R 4.4 -#' Quality: pending | Created: 2026-06-21 +#' Library: ggplot2 3.5.1 | R 4.4.1 +#' Quality: 86/100 | Created: 2026-06-21 library(ggplot2) library(dplyr) diff --git a/plots/line-stress-strain/metadata/r/ggplot2.yaml b/plots/line-stress-strain/metadata/r/ggplot2.yaml index 9dad0b6962..1fe8940795 100644 --- a/plots/line-stress-strain/metadata/r/ggplot2.yaml +++ b/plots/line-stress-strain/metadata/r/ggplot2.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for ggplot2 implementation of line-stress-strain -# Auto-generated by impl-generate.yml - library: ggplot2 language: r specification_id: line-stress-strain created: '2026-06-21T09:46:01Z' -updated: '2026-06-21T09:46:01Z' +updated: '2026-06-21T09:53:19Z' generated_by: claude-sonnet workflow_run: 27900282175 issue: 4413 @@ -15,7 +12,240 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/line-stre preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/line-stress-strain/r/ggplot2/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: null +quality_score: 86 review: - strengths: [] - weaknesses: [] + strengths: + - 'Excellent physics accuracy: Luders plateau for steel, smooth nonlinear response + for aluminum — both curves are textbook-quality' + - All seven spec-required features implemented (regions, critical points, 0.2% offset + method, Young's modulus, multi-material overlay) + - 'Imprint palette applied correctly with #009E73 as first series' + - Open-circle critical point markers (fill=PAGE_BG) are an elegant ggplot2 detail + that adapts to both themes + - Inside legend placement is clean and space-efficient + weaknesses: + - Young's modulus slope segment (0,0)->(0.001,200) spans only 0.27% of the x-axis + width and appears as a near-vertical dash at the y-axis — conveys no meaningful + slope information; should be drawn 5-10x longer (e.g., to strain~0.005-0.01) with + a label explaining the slope represents E + - 'Annotation crowding in upper-left: YS=250 MPa (green) and 0.2% YS=276 MPa (lavender) + are only ~12 MPa apart vertically and both left-aligned near x~0.005-0.010 — increase + vertical separation or use offset arrows/leaders to prevent visual collision' + - 0.2% offset line annotation label at size=2.8 is the smallest text element and + may be illegible at mobile scale — increase to size=3.2 minimum + - library(dplyr) is imported but never used — remove + image_description: |- + Light render (plot-light.png): + Background: Warm off-white #FAF8F1 — correct theme surface + Chrome: Title "line-stress-strain · r · ggplot2 · anyplot.ai" bold dark (#1A1A17), fully readable. Axis labels "Engineering Stress (MPa)" and "Engineering Strain (mm/mm)" at 10pt in dark ink. Tick labels at 8pt in INK_SOFT (#4A4A44). Region labels ("Elastic", "Strain Hardening", "Necking") in italic INK_MUTED, readable near top of plot. Critical point annotations in material colors. "E = 200 GPa" and "0.2% offset line" labels small (size=2.8-2.9) but readable at full resolution. + Data: Steel in Imprint green #009E73, Aluminum in Imprint lavender #C475FD. Open-circle markers (fill=PAGE_BG, stroke=1.5) at critical points. 0.2% offset dashed line in INK_SOFT gray. Young's modulus slope segment in INK_MUTED gray near y-axis (very narrow at chart scale). + Legibility verdict: PASS — all text readable against light background; minor crowding of YS labels in upper-left. + + Dark render (plot-dark.png): + Background: Warm near-black #1A1A17 — correct dark theme surface + Chrome: Title in light cream (#F0EFE8), axis labels in INK (#F0EFE8), tick labels in INK_SOFT (#B8B7B0). Region labels in INK_MUTED (#A8A79F). All annotation text using adaptive ink tokens. Legend box at #242420 with muted border. No dark-on-dark failures observed — all chrome elements correctly use light-theme-flipped tokens. + Data: Colors identical to light render — green #009E73 for steel, lavender #C475FD for aluminum — only chrome flipped as expected. + Legibility verdict: PASS — all text clearly visible against dark background; no dark-on-dark failures. + criteria_checklist: + visual_quality: + score: 26 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 6 + max: 8 + passed: true + comment: Title/axis/tick text readable in both themes. Annotation sizes 2.8-3.2 + ggplot2 units are small — borderline at mobile scale. + - id: VQ-02 + name: No Overlap + score: 5 + max: 6 + passed: true + comment: 'Minor crowding: YS=250 MPa and 0.2% YS=276 MPa labels only 12 MPa + apart vertically in upper-left region.' + - id: VQ-03 + name: Element Visibility + score: 5 + max: 6 + passed: true + comment: Lines and markers clearly visible. Young's modulus slope segment + spans only 0.27% of x-axis — appears as near-vertical dash at y-axis, not + a readable slope indicator. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Two Imprint hues (green, lavender) are perceptually distinct and + CVD-safe. + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Canvas 3200x1800 passed gate. Title ~55% width. Inside legend well-placed. + No clipping. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: Engineering Strain (mm/mm) and Engineering Stress (MPa) — descriptive + with units. + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'First series #009E73, second #C475FD. Backgrounds #FAF8F1 light + / #1A1A17 dark. Grid at 12% INK opacity.' + design_excellence: + score: 14 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 6 + max: 8 + passed: true + comment: 'Above defaults: Imprint palette, inside legend, open-circle markers + (fill=PAGE_BG), themed backgrounds, clear typography hierarchy, region boundary + guides.' + - id: DE-02 + name: Visual Refinement + score: 4 + max: 6 + passed: true + comment: panel.border removed, minor grid disabled, 12%-opacity major grid, + elevated legend background. L-shaped spine preserved. + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Region labels walk viewer through deformation stages. All critical + properties annotated. Multi-material comparison adds value. Young's modulus + indicator weak. + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Engineering stress-strain curve with geom_line — correct chart type. + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Region labels, critical points, 0.2% offset method, Young's modulus + annotation, offset line, multi-material overlay — all present. + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X=strain, Y=stress, correct axes, full data range shown, physically + realistic curves. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title 'line-stress-strain · r · ggplot2 · anyplot.ai' matches required + format. Legend labels accurate. + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: Elastic region, Luders plateau (steel), strain hardening, necking, + fracture — all represented. 0.2% offset method illustrated. + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: AISI 1020 steel and Al 6061-T6 are real materials with accurate mechanical + properties. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Stress 0-410 MPa and strain 0-0.35 are physically correct for these + materials. + code_quality: + score: 9 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: No functions or classes; clean sequential script. + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: set.seed(42) present; data generation is deterministic. + - id: CQ-03 + name: Clean Imports + score: 1 + max: 2 + passed: false + comment: library(dplyr) imported but unused — rbind/data.frame/factor are + all base R. + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Well-organized with clear commented sections. No fake interactivity. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: sprintf('plot-%s.png', THEME) correct; ragg::agg_png device used. + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: 'Correct grammar of graphics: aes(), geom_line/geom_point, annotate(), + scale_color_manual(), theme() chaining, expansion() — all idiomatic.' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: shape=21 open-circle markers; legend.position.inside with modern + ggplot2 >=3.5 API; adjustcolor() for grid opacity; inherit.aes=FALSE for + multi-layer data. + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - annotations + - layer-composition + patterns: + - data-generation + dataprep: [] + styling: + - edge-highlighting