Skip to content

feat(highcharts): implement sn-curve-basic#7525

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/sn-curve-basic/highcharts
May 20, 2026
Merged

feat(highcharts): implement sn-curve-basic#7525
MarkusNeusinger merged 6 commits into
mainfrom
implementation/sn-curve-basic/highcharts

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: sn-curve-basic - python/highcharts

Implements the python/highcharts version of sn-curve-basic.

File: plots/sn-curve-basic/implementations/python/highcharts.py

Parent Issue: #3826


🤖 impl-generate workflow

github-actions Bot added 2 commits May 20, 2026 14:27
Regen from quality 87. Addressed:
- Region band labels bumped from 32px to 36px for better readability
- Legend shifted to y:140 (was 100) to reduce visual tension with Infinite Life label
- Added CDP Emulation.setDeviceMetricsOverride for authoritative 3200x1800 viewport
- Added --headless=new and --hide-scrollbars Selenium flags
- Added PIL pad-or-crop safety net for exact canvas dimensions
- Note: LineSeries lives in highcharts_core.options.series.area in this version (no separate .line module exists); review's CQ-03 flag was inaccurate but import is now confirmed correct
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 20, 2026

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): The plot renders on a warm off-white #FAF8F1 background. Title "sn-curve-basic · python · highcharts · anyplot.ai" is bold and fills ~70% of the width. The scatter test data points are rendered in Okabe-Ito brand green (#009E73) and the Basquin fit line in vermillion (#D55E00). Three semi-transparent region bands (Low-Cycle Fatigue: pale orange, High-Cycle Fatigue: pale blue, Infinite Life: pale green) span the x-axis with labels at the top. Three dashed horizontal reference lines mark Ultimate Strength (500 MPa, red), Yield Strength (350 MPa, amber), and Endurance Limit (200 MPa, green) with labels on the right side. Both logarithmic axes are labelled with units. Legend sits in the upper-right corner. All title, axis label, tick, and region-band text is clearly readable against the light background. However, the red "Ultimate Strength (500 MPa)" plotLine label partially overlaps the legend box in the upper-right corner, reducing clarity.

Dark render (plot-dark.png): The same layout renders on a warm near-black #1A1A17 background. Title, axis labels, and tick labels all switch to light-colored text (#F0EFE8 / #B8B7B0) and are clearly readable — no dark-on-dark failure observed. Data colors (green scatter, orange fit line) are identical to the light render. Region band labels remain readable in secondary ink. Reference line labels retain their semantic colors and are legible. The overlap between the Ultimate Strength label and the legend is also present in the dark render. Both renders pass theme-readability.

Score: 83/100

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

Visual Quality (23/30)

  • VQ-01: Text Legibility (7/8) — All font sizes explicitly set (66px title, 56px axis labels, 44px ticks, 34–36px region/reference labels). All readable in both themes. Minor: x-axis title is tight at the bottom edge but visible.
  • VQ-02: No Overlap (3/6) — The plotLine label "Ultimate Strength (500 MPa)" at align="right" overlaps the legend box positioned in the upper-right. The text is partially obscured in both renders.
  • VQ-03: Element Visibility (5/6) — Scatter radius=10, fit line lineWidth=5, ~40 data points — elements clearly visible and well-sized for the data density.
  • VQ-04: Color Accessibility (1/2) — Reference lines use red (#E53935) and green (#43A047) in the same plot. These are non-Okabe-Ito custom hex values and create a red-green pairing that may be problematic for CVD users, even though the lines are labelled.
  • VQ-05: Layout & Canvas (3/4) — Good margins and canvas utilization. Slight concern: x-axis title is very close to the bottom canvas edge at the 3200×1800 resolution (marginBottom=120 is adequate but tight).
  • VQ-06: Axis Labels & Title (2/2) — "Number of Cycles to Failure (N)" and "Stress Amplitude (MPa)" — descriptive with units.
  • VQ-07: Palette Compliance (2/2) — Test Data = #009E73 (Okabe-Ito Add workflow diagram for new prototype discovery #1, correct); Basquin Fit = #D55E00 (Okabe-Ito Add Claude Code GitHub Workflow #2, correct). Backgrounds #FAF8F1/#1A1A17 correct. Both renders theme-correct.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above a plain default: the region bands, semantic reference lines, and marker edge highlights show design thought. However, the full Highcharts chart box frame remains visible (no spine removal), and the legend/label overlap detracts from the polished feel. Solid but not publication-ready.
  • DE-02: Visual Refinement (3/6) — Grid at rgba 0.10 opacity is subtle; scatter markers use PAGE_BG-colored edges for definition; custom margins set. Missing: no removal of top/right chart border (all four plot frame borders are visible), which the style guide recommends removing for a cleaner L-shaped or open look.
  • DE-03: Data Storytelling (4/6) — Three named fatigue regions with distinct color bands plus three labeled reference lines give strong visual hierarchy. The viewer immediately understands material behavior zones and key threshold values. Clearly above bare data display.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct S-N scatter + Basquin fit overlay, logarithmic axes on both.
  • SC-02: Required Features (4/4) — Both log axes, Ultimate Strength / Yield Strength / Endurance Limit reference lines, three fatigue region bands with labels, Basquin power-law fit line, scatter test data with variability — all spec requirements met.
  • SC-03: Data Mapping (3/3) — X = cycles (log), Y = stress amplitude (log), correct mapping.
  • SC-04: Title & Legend (3/3) — Title is exactly "sn-curve-basic · python · highcharts · anyplot.ai". Legend labels "Test Data" and "Basquin Fit" match series names.

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows scatter variability at each stress level, a fitted trend line, region delineation, and threshold reference lines — all key aspects of an S-N curve.
  • DQ-02: Realistic Context (5/5) — Structural steel fatigue test data, neutral engineering domain, real-world comprehensible scenario.
  • DQ-03: Appropriate Scale (4/4) — Stress 150–600 MPa and cycle range 100–10⁸ are typical for structural steel S-N curves. Basquin parameters (A=1200, b=0.12) produce plausible results.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Flat imports → data → chart config → series → render. No functions or classes.
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set.
  • CQ-03: Clean Imports (2/2) — All imports (numpy, highcharts_core, PIL, selenium, os, etc.) are used.
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic, appropriate complexity. No fake interactivity.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html. Current API used.

Library Mastery (8/10)

  • LM-01: Idiomatic Usage (4/5) — Correct use of Chart/HighchartsOptions, ScatterSeries+LineSeries, log-axis config, plotLines, plotBands with labels. Uses highcharts_core Python bindings idiomatically.
  • LM-02: Distinctive Features (4/5) — plotBands (region shading with labels) and plotLines (reference annotations) are Highcharts-distinctive chart-level features not easily replicated in matplotlib/seaborn. CDP viewport override and PIL safety net are Highcharts-export best practices.

Score Caps Applied

  • None

Strengths

  • Perfect spec compliance: all three fatigue regions, three reference lines (Ultimate/Yield/Endurance), log-log axes, Basquin fit — nothing missing.
  • Excellent data quality: realistic structural steel scenario with correct parameter ranges and natural scatter.
  • Strong data storytelling via plotBands region shading — viewer immediately reads fatigue life zones.
  • All Okabe-Ito palette requirements met; both theme renders are correct.
  • Clean, idiomatic Highcharts code with proper CDP viewport and PIL safety net.

Weaknesses

  • plotLine label "Ultimate Strength (500 MPa)" overlaps the legend box (upper-right). Fix: move legend lower (increase y offset) or shift plotLine labels further left / to the left side (align="left", x=10), or reduce legend y to start below the 500 MPa line level.
  • Full chart frame box is visible (all four borders). Remove top and right chart borders for the standard L-shaped or borderless look: set chart.options.chart = {..., 'plotBorderWidth': 0} and configure the two axes to show only the left/bottom line via lineWidth: 1 vs 0 on top/right.
  • Reference lines use non-Okabe-Ito custom hexes (#E53935, #FB8C00, #43A047). Use Okabe-Ito analogues (#D55E00 for danger, #E69F00 for caution, #009E73 already used as data color — consider #56B4E9 or #CC79A7 for the endurance limit) or replace with the style-guide's position-8 adaptive neutral plus semantic annotation text.
  • x-axis title is slightly cramped at the bottom canvas edge; increase marginBottom from 120 to 140–150 for breathing room.

Issues Found

  1. VQ-02 / DE-01 OVERLAP: plotLine label "Ultimate Strength (500 MPa)" overlaps the legend box in both renders.
    • Fix: Change plotLine label align to "left" and x: 10, OR increase legend y to 200+ to push it below the 500 MPa level.
  2. DE-02 SPINE: All four chart frame borders are visible. Remove top and right borders.
    • Fix: Add 'plotBorderWidth': 0 to chart options and set xAxis.lineWidth: 1 / yAxis.lineWidth: 1 only where needed.
  3. VQ-04 CVD: Red+green reference line pair. Prefer Okabe-Ito palette positions for reference lines or use shape/dash differentiation in addition to color.

AI Feedback for Next Attempt

Fix the legend/plotLine overlap first (highest visual impact): move the plotLine labels to align left (x=10) instead of right, so they don't compete with the upper-right legend box. Remove the chart plot border (plotBorderWidth: 0) for a cleaner L-frame look. Replace reference line colors with Okabe-Ito values or clearly differentiated semantic alternatives to avoid the red-green CVD pairing. Increase marginBottom to 140 for more x-axis title breathing room. These four fixes should push the score above 90.

Verdict: REJECTED

@github-actions github-actions Bot added quality:83 Quality score 83/100 ai-rejected Quality not OK, triggers update labels May 20, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels May 20, 2026
Attempt 1/3 - fixes based on AI review
@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
Copy link
Copy Markdown
Contributor

claude Bot commented May 20, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): The plot displays on a warm off-white #FAF8F1 background. Three lightly-colored background bands fill the chart area: an orange-tinted Low-Cycle Fatigue region (100–10k cycles), a blue-tinted High-Cycle Fatigue region (10k–1M cycles), and a green-tinted Infinite Life region (1M–100M cycles), each labeled at the top of their band. Approximately 35–40 scatter points in brand green #009E73 with white marker edges fall in a descending cluster from ~450 MPa at 1k cycles down to ~210 MPa at 1M+ cycles. An orange #D55E00 Basquin fit line runs cleanly through the scatter. Three dashed horizontal reference lines appear: pink/purple Ultimate Strength at 500 MPa, yellow Yield Strength at 350 MPa, and sky-blue Endurance Limit at 200 MPa, each with a colored label at the left of the plot area. Title in dark bold text spans ~70% of plot width. All text is clearly readable against the light background; no light-on-light failures.

Dark render (plot-dark.png): The same chart on a warm near-black #1A1A17 background. Title and axis labels render in light #F0EFE8 ink; tick labels in muted light #B8B7B0. The legend box uses the elevated dark #242420 fill. Data colors are identical to the light render: scatter points remain #009E73 green and the Basquin fit remains #D55E00 orange. The background fatigue-region bands are still distinguishable. The three reference line labels (pink, yellow, sky-blue) remain fully readable on the dark surface. No dark-on-dark failures observed — the theme adaptation is complete and correct.

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

Score: 89/100

Category Score Max
Visual Quality 29 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 7 10
Total 89 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (8/8) — All font sizes explicitly set (title 66px, axis 56px, ticks 44px, legend 44px, region labels 36px, reference line labels 34px); readable in both themes; proportions balanced
  • VQ-02: No Overlap (5/6) — Minor label density in upper-left where the Low-Cycle Fatigue band label and Ultimate Strength plotLine label share vertical space; no severe overlap
  • VQ-03: Element Visibility (6/6) — Marker radius=10 appropriate for ~35–40 data points; Basquin fit lineWidth=5 clearly visible
  • VQ-04: Color Accessibility (2/2) — CVD-safe Okabe-Ito palette; series distinguishable without relying on hue alone
  • VQ-05: Layout & Canvas (4/4) — Canvas gate passed; balanced generous margins (150L, 80R, 140B, 100T); good canvas utilization
  • VQ-06: Axis Labels & Title (2/2) — "Number of Cycles to Failure (N)" and "Stress Amplitude (MPa)" — descriptive with units
  • VQ-07: Palette Compliance (2/2) — First series #009E73 ✓, second #D55E00 ✓, backgrounds #FAF8F1/#1A1A17 ✓, full theme-adaptive chrome in both renders ✓

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Above defaults: background region bands and material reference lines show thoughtful design intent; clean composition; not yet FiveThirtyEight publication-level polish
  • DE-02: Visual Refinement (4/6) — Subtle grid (rgba 0.10 alpha), background shading adds visual depth, generous margins; no spine removal (all four axis lines remain visible)
  • DE-03: Data Storytelling (4/6) — Three labeled fatigue regime bands and three material reference lines create strong visual hierarchy; viewer immediately understands engineering context; clearly above-default storytelling

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct S-N curve: scatter data + Basquin fit line on dual logarithmic axes
  • SC-02: Required Features (4/4) — All features present: log axes, three region bands (Low/High-Cycle/Infinite Life), three reference lines (Ultimate/Yield/Endurance), scatter + Basquin fit
  • SC-03: Data Mapping (3/3) — X: cycles (100–10^8), Y: stress MPa (150–600); correct axes with appropriate ranges
  • SC-04: Title & Legend (3/3) — Title sn-curve-basic · python · highcharts · anyplot.ai correct; legend "Test Data" and "Basquin Fit" appropriate

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6) — Shows variability across stress levels, three fatigue regimes, material reference properties, and power-law fit
  • DQ-02: Realistic Context (5/5) — Structural steel fatigue testing — real engineering domain, neutral
  • DQ-03: Appropriate Scale (4/4) — Ultimate 500 MPa, Yield 350 MPa, Endurance 200 MPa realistic for structural steel; cycle range 10^2–10^8 appropriate for fatigue testing

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3) — Clean Imports → Data → Plot → Save flow; no functions or classes
  • CQ-02: Reproducibility (2/2) — np.random.seed(42) set
  • CQ-03: Clean Imports (2/2) — All imports used (LineSeries from area module is unusual but functional)
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic; appropriate complexity for the visualization
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png + plot-{THEME}.html; PIL safety-net for exact canvas dimensions

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — Correct Chart + HighchartsOptions + ScatterSeries + LineSeries pattern; plotBands and plotLines used idiomatically; CDP override for exact viewport dimensions
  • LM-02: Distinctive Features (3/5) — plotBands for region shading and plotLines with colored labels are genuinely Highcharts-specific features not easily replicated in other libraries

Score Caps Applied

  • None — no caps triggered (DE-01=5 and DE-02=4, both >2; all other category scores non-zero)

Strengths

  • All spec features implemented: logarithmic dual axes, three fatigue regime background bands with labels, three material reference lines (Ultimate/Yield/Endurance), scatter test data, and Basquin power-law fit line
  • Full theme-adaptive chrome: backgrounds #FAF8F1/#1A1A17, INK/INK_SOFT tokens applied to all text, grid, and legend — both renders legible
  • Highcharts-specific plotBands and plotLines used idiomatically for region shading and horizontal reference annotations
  • Realistic structural steel fatigue data (seed-controlled) with factually plausible material constants
  • Clean KISS code with explicit font sizes at every level and PIL safety-net for exact canvas dimensions

Weaknesses

  • Minor label crowding in upper-left: the "Low-Cycle Fatigue" band label and "Ultimate Strength (500 MPa)" plotLine label share vertical space near the top of the chart — consider offsetting the region label downward (y: 50) or moving the plotLine label to the right (align: "right")
  • No spine removal: Highcharts default axis frame remains on all four sides; removing top and right axis lines would improve visual refinement per the style guide
  • Design Excellence ceiling: composition is well-structured but lacks final typographic polish to reach publication quality

Issues Found

  1. VQ-02 MINOR: Label crowding at top-left (Low-Cycle Fatigue region label + Ultimate Strength plotLine label overlap vertically)
    • Fix: Increase region label y offset to ~50 or shift plotLine label alignment to "right" with x: -10
  2. DE-02 MODERATE: No top/right spine removal
    • Fix: Add chart.options.x_axis = {..., "lineWidth": 0} and style tweaks to remove top/right frame lines

AI Feedback for Next Attempt

Score 89/100 — APPROVED at Attempt 2 threshold (≥80). No repair needed. The implementation is strong: all spec features present, realistic data, clean code, correct theme adaptation in both renders, and idiomatic Highcharts usage with plotBands/plotLines. Minor improvements (spine removal, label crowding at top-left) are noted as polish opportunities but do not block approval.

Verdict: APPROVED

@github-actions github-actions Bot added quality:89 Quality score 89/100 ai-approved Quality OK, ready for merge and removed quality:83 Quality score 83/100 labels May 20, 2026
@MarkusNeusinger MarkusNeusinger merged commit b0156b3 into main May 20, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/sn-curve-basic/highcharts branch May 20, 2026 14:45
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:89 Quality score 89/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant