Skip to content

feat(plotnine): implement line-stress-strain#9298

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/line-stress-strain/plotnine
Jun 21, 2026
Merged

feat(plotnine): implement line-stress-strain#9298
MarkusNeusinger merged 6 commits into
mainfrom
implementation/line-stress-strain/plotnine

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: line-stress-strain - python/plotnine

Implements the python/plotnine version of line-stress-strain.

File: plots/line-stress-strain/implementations/python/plotnine.py

Parent Issue: #4413


🤖 impl-generate workflow

github-actions Bot added 2 commits June 21, 2026 09:40
Regen from quality 90. Addressed:
- Canvas: fixed figure_size to (8, 4.5) at dpi=400 for exact 3200x1800px output (was 16x9 @ dpi=300)
- Theme-adaptive chrome: added PAGE_BG, INK, INK_SOFT, REGION_ALPHA tokens for light/dark
- Imprint palette: main curve now uses #009E73 (position 1) instead of non-Imprint #306998
- Save filename: now plot-{THEME}.png as required (was plot.png)
- Change request: reduced from 4 region bands to 3 (elastic, strain hardening, necking); yield plateau kept as critical point marker only
- Text sizes: standardized geom_text to ~3mm per library guide; element_text to 12/10/8pt
- 0.2% offset annotation size now consistent with other labels
- Added sys.path workaround for plotnine.py naming conflict
@claude

claude Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1) — correct. Three colored region bands visible: a very narrow blue-tinted elastic sliver at the far left (~0 to 0.001 strain), a beige/tan strain-hardening band (~0.001 to 0.22), and a pink/salmon necking band (0.22–0.35). Main stress-strain curve in brand green #009E73 is prominent and correct (elastic rise → yield plateau → strain hardening → necking). Three matte-red markers at yield point, UTS, and fracture. Red dashed 0.2% offset line is a nearly vertical sliver near the origin. Annotations: "Yield Point (0.2% offset)" bold dark, "UTS" bold, "Fracture" bold, "E = 210 GPa" in blue, "0.2% offset" small italic red, and italic region labels "Elastic" / "Strain Hardening" / "Necking". Title, axis labels, and tick labels are all dark and clearly readable against the light background. The "Elastic" region label is positioned just past the elastic band boundary (at x=0.003, which is inside the strain-hardening zone). Legibility: PASS.

Dark render (plot-dark.png): Warm near-black background (#1A1A17) — correct. Title, axis labels, and tick labels all adapt to light-cream/soft tones — no dark-on-dark failures. The three region bands produce heavier fills in dark mode: elastic becomes a dark olive-blue tint, strain-hardening becomes a dark olive-tan, and necking becomes a dark brownish-red — more saturated than light mode. The green curve (#009E73) remains clearly distinguishable against all three dark fills. Matte-red markers remain identifiable. The "0.2% offset" italic label (size=3mm, #AE3030) at the bottom-left is the weakest legibility element — marginally readable against the dark olive fill. Data colors are identical to the light render; only chrome flips. Legibility: PASS (marginal on "0.2% offset" annotation).

Score: 79/100

Category Score Max
Visual Quality 24 30
Design Excellence 12 20
Spec Compliance 12 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 6 10
Total 79 100

Visual Quality (24/30)

  • VQ-01: Text Legibility (6/8) — Title, axis labels, tick labels readable in both themes. "0.2% offset" annotation (size=3mm, matte red) is marginal in dark render. "Elastic" label mispositioned into adjacent region band.
  • VQ-02: No Overlap (5/6) — Minor crowding near yield region where offset line, yield marker, and "Yield Point" label cluster. No hard overlap.
  • VQ-03: Element Visibility (5/6) — Green curve and red markers clearly visible. Elastic band is a very narrow sliver (inherent to physics but visually hard to read). Region fills heavier in dark mode.
  • VQ-04: Color Accessibility (1/2) — Green curve + red critical-point markers form a CVD-challenging pair. Mitigated by distinct shape encoding (line vs. filled dot), but remains a concern for deuteranopia users.
  • VQ-05: Layout & Canvas (3/4) — Canvas gate passed. Good proportions. Narrow elastic region is physically accurate. No overflow or clipping.
  • VQ-06: Axis Labels & Title (2/2) — X: "Engineering Strain" (dimensionless, no units needed ✓); Y: "Engineering Stress (MPa)" with units ✓.
  • VQ-07: Palette Compliance (2/2) — First series = #009E73 ✓. Region shading uses Imprint positions 2–4 with alpha ✓. Critical markers use semantic matte red #AE3030 ✓. Backgrounds #FAF8F1/#1A1A17 ✓. Data colors invariant across themes ✓.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above default: thoughtful three-region color banding, multiple annotation types, Imprint palette used consistently. Heavy dark-mode region fills and uniform typography prevent a higher score.
  • DE-02: Visual Refinement (3/6) — theme_minimal base, vertical grid disabled (panel_grid_major_x=element_blank), no minor grid. However panel_border keeps a 4-sided frame instead of the recommended L-shaped spine. Above default (2) for grid discipline.
  • DE-03: Data Storytelling (4/6) — Solid engineering narrative: region bands, critical points, 0.2% offset construction, E modulus annotation all guide the reader through the material behavior. Above default (2).

Spec Compliance (12/15)

  • SC-01: Plot Type (5/5) — Correct engineering stress-strain curve with all characteristic phases.
  • SC-02: Required Features (4/4) — All required elements present: region labels, yield point with 0.2% offset method, UTS, fracture point, elastic modulus annotation, offset construction line.
  • SC-03: Data Mapping (3/3) — Correct axes, correct curve shape (elastic → yield plateau → hardening → necking → fracture).
  • SC-04: Title & Legend (0/3) — FAIL: Title reads line-stress-strain · plotnine · pyplots.ai but the required format is line-stress-strain · python · plotnine · anyplot.ai. Two errors: (1) missing python language; (2) domain is pyplots.ai instead of anyplot.ai.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Complete: elastic, yield plateau, strain hardening, necking, and fracture all modeled; critical points and annotations fully present.
  • DQ-02: Realistic Context (5/5) — Textbook-accurate mild steel: E=210 GPa, yield=250 MPa, UTS=400 MPa, fracture_strain=0.35. No controversial content.
  • DQ-03: Appropriate Scale (4/4) — 175 data points for smooth curves; strain 0–0.35 and stress 0–460 MPa appropriate for mild steel.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat linear script, no functions or classes, clear variable organization.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set; all data is deterministic.
  • CQ-03: Clean Imports (2/2) — All imports used; sys.path manipulation is necessary for the plotnine.py filename collision.
  • CQ-04: Code Elegance (2/2) — Clean plotnine grammar-of-graphics layering. No fake UI. Appropriate complexity.
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png with dpi=400, width=8, height=4.5 ✓.

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — Good: annotate() for non-data shapes, geom_segment() for construction lines, scale_color_identity() + scale_size_identity() for manual aesthetics, coord_cartesian() for axis limits. Above default.
  • LM-02: Distinctive Features (2/5) — annotate('rect') for region shading (ggplot2-specific), geom_text() for vectorized labels, layered grammar-of-graphics composition. Above default but no advanced plotnine features (faceting, complex scales, stat transformations).

Score Caps Applied

  • None — no cap conditions triggered.

Strengths

  • Complete spec compliance: all required engineering chart features implemented (region bands, 0.2% offset construction, UTS/yield/fracture markers, E modulus annotation)
  • Perfect data quality: realistic mild steel parameters with textbook-accurate stress-strain curve shape
  • Full theme-adaptive chrome correctly applied to all non-data elements across both renders
  • Correct Imprint palette usage: brand green first, semantic matte red for critical points, region shading from Imprint positions 2–4

Weaknesses

  • SC-04 FAIL: Title must be line-stress-strain · python · plotnine · anyplot.ai — fix labs(title=...) to include python and use anyplot.ai not pyplots.ai
  • "Elastic" region label (x=0.003) is positioned inside the strain-hardening band because the elastic zone ends at ~0.00119 strain — move label to x≈0.0005 or use an arrow/segment to tie it to the correct region
  • Dark-mode region fills are quite heavy (alpha=0.28 on dark bg creates saturated olive/tan/brownish fills) — consider REGION_ALPHA=0.12 for dark theme for a more refined appearance
  • "0.2% offset" italic annotation is marginal in the dark render (small size=3mm, matte red #AE3030 on dark olive background) — increase to size=3.5 and consider INK_SOFT for better contrast
  • 4-sided panel border instead of recommended L-shaped spine (remove top/right spines)

Issues Found

  1. SC-04 CRITICAL: Wrong title — pyplots.ai instead of anyplot.ai, missing python language token
    • Fix: labs(title="line-stress-strain · python · plotnine · anyplot.ai")
  2. VQ-01 / DE-03 LOW: "Elastic" label mispositioned in adjacent region band
    • Fix: Place at x≈0.0005 (inside elastic band) or annotate with small arrow connecting to the band
  3. DE-02 LOW: 4-sided panel border vs. L-shaped frame
    • Fix: Remove panel_border and instead keep only axis_line elements on left and bottom

AI Feedback for Next Attempt

The most critical fix is the title: change labs(title=...) to "line-stress-strain · python · plotnine · anyplot.ai". Secondary: reduce REGION_ALPHA to 0.12 for the dark theme to lighten the heavy region fills. Move the "Elastic" label inside the elastic band (x≈0.0005) or use an annotation segment. Replace the 4-sided panel border with L-shaped spines (remove panel_border, keep axis_line). Increase "0.2% offset" annotation to size=3.5 and use INK_SOFT color for better legibility in dark mode.

Verdict: APPROVED

@github-actions github-actions Bot added quality:79 Quality score 79/100 ai-rejected Quality not OK, triggers update labels Jun 21, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Jun 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude

claude Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white #FAF8F1 background. The main engineering stress-strain curve is drawn in brand green #009E73 (Imprint position 1) as a continuous line. Three region shadings distinguish the elastic zone (thin left strip in #4467A3 blue at alpha=0.18), the strain hardening zone (large central region in #BD8233 ochre), and the necking zone (right region in #AE3030 red). Critical points are marked with red dots at yield, UTS, and fracture. A dashed red 0.2% offset line is drawn from x=0.002. Blue text annotation reads "E = 210 GPa". Italic region labels ("Elastic", "Strain Hardening", "Necking") and bold critical point labels ("Yield Point (0.2% offset)", "UTS", "Fracture") are placed throughout. Axis labels "Engineering Stress (MPa)" and "Engineering Strain" are clear at 10pt; title is bold 12pt. All primary text is readable against the light background. Secondary annotation texts at size=3.0mm (≈8.5pt) are very small at 400px mobile width but readable at desktop.

Dark render (plot-dark.png): The same plot on the warm near-black #1A1A17 surface. All data colors are identical to the light render — the main curve remains #009E73, region shadings use the same Imprint hues (at alpha=0.13, slightly lower), and critical point markers retain #AE3030. Chrome elements correctly flip: title, axis labels, and tick labels render in light #F0EFE8/#B8B7B0 tones. No dark-on-dark failures observed — all text elements use the theme-adaptive INK and INK_SOFT tokens correctly. Grid remains horizontal-only and subtle. The plot is fully readable on the dark surface.

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

Score: 83/100

Category Score Max
Visual Quality 25 30
Design Excellence 12 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 6 10
Total 83 100

Visual Quality (25/30)

  • VQ-01: Text Legibility (6/8) — Font sizes explicitly set (title=12pt, axis=10pt, ticks=8pt). Main text readable at desktop and mobile. Secondary geom_text annotations at size=3.0 (≈8.5pt) are quite small at 400px mobile width — region labels and critical point labels are borderline at that scale.
  • VQ-02: No Overlap (5/6) — No actual text overlaps. The left elastic zone (x=0–0.03) is dense with dashed line, yield marker, and multiple annotation labels at different y positions — crowded but non-overlapping.
  • VQ-03: Element Visibility (5/6) — Main curve and markers clearly visible. Region shadings appropriately subtle. Elastic region is inherently narrow (<0.3% of x-axis scale), which is physically accurate for steel.
  • VQ-04: Color Accessibility (2/2) — Imprint palette is CVD-safe. Semantic red for failure markers; Imprint hues for regions.
  • VQ-05: Layout & Canvas (3/4) — Canvas correct at 3200×1800. Balanced margins. Minor deduction for full 4-sided panel border adding slight visual weight.
  • VQ-06: Axis Labels & Title (2/2) — "Engineering Stress (MPa)" with units; "Engineering Strain" (dimensionless, no unit needed). Title format correct.
  • VQ-07: Palette Compliance (2/2) — Main curve #009E73 (position 1). Region shadings use Imprint positions 3/4/5. Backgrounds #FAF8F1 light / #1A1A17 dark. All chrome tokens theme-adaptive. Data colors identical between themes.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above typical defaults: region shading with intentional alpha, semantic color choices for critical points, visual hierarchy through annotation placement. Not publication-ready but clearly designed with intention.
  • DE-02: Visual Refinement (3/6) — Horizontal-only grid is good. Full 4-sided panel border via panel_border=element_rect(...) counter to the recommended L-shaped frame (remove top/right). Some refinement present but not fully minimal.
  • DE-03: Data Storytelling (4/6) — Region shading guides the viewer through material behavior stages. Labeled critical points tell the engineering story clearly. 0.2% offset construction illustrated. Plot has a clear narrative arc.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct engineering stress-strain line chart with all major curve regions.
  • SC-02: Required Features (4/4) — All spec requirements satisfied: region labels (elastic/strain hardening/necking), critical points (yield/UTS/fracture), elastic modulus annotation ("E = 210 GPa"), 0.2% offset line drawn with correct slope. Multi-material overlay is optional per spec — not penalized.
  • SC-03: Data Mapping (3/3) — X=engineering strain (0–0.35), Y=engineering stress (0–460 MPa). All regions visible.
  • SC-04: Title & Legend (3/3) — Title is line-stress-strain · python · plotnine · anyplot.ai — correct mandatory format. No legend needed (single main curve with inline annotations).

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows all stages: elastic (linear), yield plateau, strain hardening (power law), necking, fracture. 0.2% offset method correctly computed and displayed.
  • DQ-02: Realistic Context (5/5) — Mild steel tensile test — real, neutral, scientific scenario.
  • DQ-03: Appropriate Scale (4/4) — E=210 GPa (correct for steel), yield=250 MPa, UTS=400 MPa, fracture strain=35% — all factually accurate for mild structural steel.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean Imports→Data→Plot→Save. sys.path workaround is documented and necessary.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All plotnine imports used.
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic code. No fake UI or over-engineering.
  • CQ-05: Output & API (1/1) — Saves as plot-{THEME}.png using current plotnine API.

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — Good grammar of graphics layering: annotate + geom_line + geom_point + geom_segment + geom_text. Uses scale_color_identity and scale_size_identity idiomatically. coord_cartesian for axis limits is correct ggplot2 pattern.
  • LM-02: Distinctive Features (2/5) — annotate('rect', ...) for region shading is the most idiomatic plotnine/ggplot2 feature used. Nothing uniquely plotnine-exclusive that couldn't be reproduced in matplotlib with comparable effort.

Score Caps Applied

  • None — no caps applied. DE-01=5 > 2 so the "generic + no visual refinement" cap does not trigger.

Strengths

  • Correct Imprint palette usage: #009E73 main curve, theme-adaptive chrome in both renders with no dark-on-dark failures
  • Complete spec compliance: region shading, 0.2% offset line, all critical points annotated, elastic modulus labeled
  • Factually accurate engineering data (E=210 GPa for mild steel, plausible yield/UTS/fracture values)
  • Clean plotnine grammar of graphics with layered annotate regions and geom_segment for offset construction line
  • Perfact code quality: KISS structure, seed set, clean imports, proper output naming

Weaknesses

  • Secondary annotation texts at geom_text(size=3.0) (≈8.5pt) are very small at 400px mobile width — region labels and critical point labels barely readable on mobile; consider size=3.5–4.0
  • Full 4-sided panel border (panel_border=element_rect(...)) counter to recommended L-shaped frame; removing top/right would improve visual refinement (DE-02)
  • DE-01 aesthetic sophistication is limited to spec-required elements; no additional design choices beyond functional compliance
  • LM-02 library distinctiveness modest — no uniquely plotnine-exclusive capability exploited

Issues Found

  1. DE-02 LOW: Full panel border retained — theme_minimal() removes it by default but panel_border=element_rect(color=INK_SOFT, fill=None) re-adds a complete 4-sided frame
    • Fix: Remove panel_border argument (or use panel_border=element_blank()) and rely on axis_line for the L-frame
  2. VQ-01 MINOR: geom_text(size=3.0) annotation labels too small for 400px mobile — affects region labels and critical point text
    • Fix: Increase to size=3.5 or size=4.0 for region labels and critical point annotations

AI Feedback for Next Attempt

If repair is triggered: (1) increase geom_text and annotate text sizes to size=3.5–4.0 for all secondary labels; (2) remove panel_border=element_rect(...) from theme — let axis_line handle the L-shaped frame instead; these two changes would push DE-02 to 4–5/6 and VQ-01 to 7–8/8.

Verdict: APPROVED

@github-actions github-actions Bot added quality:83 Quality score 83/100 ai-approved Quality OK, ready for merge and removed quality:79 Quality score 79/100 labels Jun 21, 2026
@MarkusNeusinger MarkusNeusinger merged commit f5641c1 into main Jun 21, 2026
2 checks passed
@MarkusNeusinger MarkusNeusinger deleted the implementation/line-stress-strain/plotnine branch June 21, 2026 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt quality:83 Quality score 83/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant